RFR(M): 8073866: Fix for 8064703 is not sufficient
Roland Westrelin
roland.westrelin at oracle.com
Mon Mar 16 10:45:28 UTC 2015
>>> About store after allocation check. I don't understand next code:
>>>
>>> 4852 if (saved_jvms == NULL && alloc != NULL) {
>>> 4853 // We're not emitting the guards, see if we have a tightly
>>> 4854 // allocation now that we've done the null check
>>> 4855 alloc = tightly_coupled_allocation(dest, NULL);
>>>
>>> I thought we should NULLify alloc if there is store.
>>>
>>> Also (saved_jvms != NULL) in next checks:
>>>
>>> 4874 if ((!has_src || !has_dest) && (alloc == NULL || saved_jvms != NULL)) {
>>>
>>> 4919 if (has_src && has_dest && (alloc == NULL || saved_jvms != NULL)) {
>>>
>>> It looks like it negates alloc == NULL check since saved_jvms != NULL is true only when alloc != NULL. So the guarded code is executed regardless alloc value. Or I may be missing something
>>
>> if alloc == NULL we don’t have to worry about guards so we can emit all of them
>
> yes
>
>> if saved_jvms != NULL (then alloc != NULL) then we can emit all guards
>
> Because you will move allocation. Right?
Yes.
>> if saved_jvms == NULL and alloc != NULL, we don’t emit any guard but the arraycopy node could still take advantage of a tightly allocated allocation. The null check is mandatory and if it resulted in an uncommon trap then we don’t have a tightly coupled allocation. That’s why tightly_coupled_allocation() is called again to make sure it takes the null check into account.
>
> So we don't generate guards here (validated = false) but we generated them later during macro expansion in generate_arraycopy(). Right?
Yes.
> Can you instead create boolean local which is used in this checks and add comments explaining when guards can be emitted
> and when not and why it is okey to not emit them here.
Ok.
> BTW, arraycopy_move_allocation_here() should check alloc != NULL
Ok.
Roland.
>
> Vladimir
>
>>
>> Roland.
>>
>>>
>>> Thanks,
>>> Vladimir
>>>
>>> On 3/12/15 9:17 AM, Roland Westrelin wrote:
>>>> http://cr.openjdk.java.net/~roland/8073866/webrev.00/
>>>>
>>>> The fix for:
>>>> https://bugs.openjdk.java.net/browse/JDK-8064703
>>>> causes reexecution of an allocation in case we deoptimize between a tightly coupled allocation and an arraycopy so an uninitialized array is not seen in the interpreter. That change causes 2 problems:
>>>>
>>>> 1) as in the test case in the webrev above, it could cause re-execution of side effects and so be visible from the application. It could even cause incorrect execution.
>>>> 2) it leaves an uninitialized array in the heap. Not all GCs are robust enough to handle that.
>>>>
>>>> The fix for 1) is to check for no store after the allocation. I verified that restricting the allocations to those not followed by stores don’t cause the performance regression observed in:
>>>> https://bugs.openjdk.java.net/browse/JDK-8060252
>>>> to come back (a regression that happened when tightly coupled allocations were disabled entirely by mistake).
>>>>
>>>> The fix I propose for 2) is to move the allocation from before the guards to after the guards. Allocations considered tightly coupled follow a pattern that allows that. All other fixes I considered (doing array initialization before the uncommon traps on the slow path, doing array initialization in the uncommon trap runtime code) seemed uglier to me.
>>>>
>>>> The change TestArrayCopyNoInitDeopt.java guarantees the test passes with -Xcomp and tiered enabled. -Xmixed after -Xcomp on the command line when tiered is enabled doesn’t entirely undo the effect of -Xcomp.
>>>>
>>>> Roland.
>>>>
>>
More information about the hotspot-compiler-dev
mailing list