Quantcast

[9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

Tobias Hartmann-2
Hi,

please review the following patch:
https://bugs.openjdk.java.net/browse/JDK-8173699
http://cr.openjdk.java.net/~thartmann/8173699/webrev.00/

The Graal compiled method java.lang.invoke.MemberName$Factory::resolve() calls into the method handle runtime via MethodHandleNatives::resolve() which throws a NoSuchMethodError because method resolution failed (see methodHandles.cpp, line 1234). We then call into JVMCIRuntime::exception_handler_for_pc() -> SharedRuntime::compute_compiled_exc_handler() to determine the appropriate exception handler. Because the ExceptionHandlerTable has no entry for this pc, we deoptimize and return to the DeoptimizationBlob at offset _unpack_with_exception_in_tls which calls Deoptimization::fetch_unroll_info(). Since the callee returns a MemberName object, the ScopeDesc is marked as return_oop() and the re-allocation code expects the return register (eax) to contain the oop of this returned object. We fail when trying to save the oop, because eax contains not an oop but the address of SharedRuntime::deopt_blob()->unpack_with_exception_in_tls() which was returned from JVMCIRuntime::exception_handler_for_pc() right before and is therefore still in eax.

As Tom suggested in the bug comments, we should ignore the return_oop() when dispatching an exception and only try to retrieve the oop when performing re-allocation during a normal deoptimization (if exec_mode == Unpack_deopt). This code should be refactored with JDK 10. I filed JDK-8173823.

This problem only affects JVMCI compiled code. C1 does not set return_oop() because it does not eliminate allocations (see IRScopeDebugInfo::record_debug_info()) and therefore does not need to re-allocate objects on deoptimization. C2 computes the exception handler via OptoRuntime::handle_exception_C() and uses DeoptimizationBlob::_unpack_with_exception as handler in case the nmethod was deoptimized. When calling Deoptimization::fetch_unroll_info() from the DeoptimizationBlob, eax still contains the exception oop and therefore the code works "by accident" because the exception oop is treated as returned oop.

Tested with JVMCI test and RBT (running).

Thanks to Tom and Dean for the help!

Thanks,
Tobias
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

Vladimir Ivanov
Looks good.

Best regards,
Vladimir Ivanov

On 2/2/17 4:04 PM, Tobias Hartmann wrote:

> Hi,
>
> please review the following patch:
> https://bugs.openjdk.java.net/browse/JDK-8173699
> http://cr.openjdk.java.net/~thartmann/8173699/webrev.00/
>
> The Graal compiled method java.lang.invoke.MemberName$Factory::resolve() calls into the method handle runtime via MethodHandleNatives::resolve() which throws a NoSuchMethodError because method resolution failed (see methodHandles.cpp, line 1234). We then call into JVMCIRuntime::exception_handler_for_pc() -> SharedRuntime::compute_compiled_exc_handler() to determine the appropriate exception handler. Because the ExceptionHandlerTable has no entry for this pc, we deoptimize and return to the DeoptimizationBlob at offset _unpack_with_exception_in_tls which calls Deoptimization::fetch_unroll_info(). Since the callee returns a MemberName object, the ScopeDesc is marked as return_oop() and the re-allocation code expects the return register (eax) to contain the oop of this returned object. We fail when trying to save the oop, because eax contains not an oop but the address of SharedRuntime::deopt_blob()->unpack_with_exception_in_tls() which was returned from JVMCIRuntime::exception_handler_for_pc() right before and is therefore still in eax.
>
> As Tom suggested in the bug comments, we should ignore the return_oop() when dispatching an exception and only try to retrieve the oop when performing re-allocation during a normal deoptimization (if exec_mode == Unpack_deopt). This code should be refactored with JDK 10. I filed JDK-8173823.
>
> This problem only affects JVMCI compiled code. C1 does not set return_oop() because it does not eliminate allocations (see IRScopeDebugInfo::record_debug_info()) and therefore does not need to re-allocate objects on deoptimization. C2 computes the exception handler via OptoRuntime::handle_exception_C() and uses DeoptimizationBlob::_unpack_with_exception as handler in case the nmethod was deoptimized. When calling Deoptimization::fetch_unroll_info() from the DeoptimizationBlob, eax still contains the exception oop and therefore the code works "by accident" because the exception oop is treated as returned oop.
>
> Tested with JVMCI test and RBT (running).
>
> Thanks to Tom and Dean for the help!
>
> Thanks,
> Tobias
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

Tobias Hartmann-2

On 02.02.2017 14:06, Vladimir Ivanov wrote:
> Looks good.

Wow, that was fast :) Thank you!

Best regards,
Tobias

> On 2/2/17 4:04 PM, Tobias Hartmann wrote:
>> Hi,
>>
>> please review the following patch:
>> https://bugs.openjdk.java.net/browse/JDK-8173699
>> http://cr.openjdk.java.net/~thartmann/8173699/webrev.00/
>>
>> The Graal compiled method java.lang.invoke.MemberName$Factory::resolve() calls into the method handle runtime via MethodHandleNatives::resolve() which throws a NoSuchMethodError because method resolution failed (see methodHandles.cpp, line 1234). We then call into JVMCIRuntime::exception_handler_for_pc() -> SharedRuntime::compute_compiled_exc_handler() to determine the appropriate exception handler. Because the ExceptionHandlerTable has no entry for this pc, we deoptimize and return to the DeoptimizationBlob at offset _unpack_with_exception_in_tls which calls Deoptimization::fetch_unroll_info(). Since the callee returns a MemberName object, the ScopeDesc is marked as return_oop() and the re-allocation code expects the return register (eax) to contain the oop of this returned object. We fail when trying to save the oop, because eax contains not an oop but the address of SharedRuntime::deopt_blob()->unpack_with_exception_in_tls() which was returned from
>> JVMCIRuntime::exception_handler_for_pc() right before and is therefore still in eax.
>>
>> As Tom suggested in the bug comments, we should ignore the return_oop() when dispatching an exception and only try to retrieve the oop when performing re-allocation during a normal deoptimization (if exec_mode == Unpack_deopt). This code should be refactored with JDK 10. I filed JDK-8173823.
>>
>> This problem only affects JVMCI compiled code. C1 does not set return_oop() because it does not eliminate allocations (see IRScopeDebugInfo::record_debug_info()) and therefore does not need to re-allocate objects on deoptimization. C2 computes the exception handler via OptoRuntime::handle_exception_C() and uses DeoptimizationBlob::_unpack_with_exception as handler in case the nmethod was deoptimized. When calling Deoptimization::fetch_unroll_info() from the DeoptimizationBlob, eax still contains the exception oop and therefore the code works "by accident" because the exception oop is treated as returned oop.
>>
>> Tested with JVMCI test and RBT (running).
>>
>> Thanks to Tom and Dean for the help!
>>
>> Thanks,
>> Tobias
>>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

Vladimir Kozlov
In reply to this post by Vladimir Ivanov
+1

Vladimir K

On 2/2/17 5:06 AM, Vladimir Ivanov wrote:

> Looks good.
>
> Best regards,
> Vladimir Ivanov
>
> On 2/2/17 4:04 PM, Tobias Hartmann wrote:
>> Hi,
>>
>> please review the following patch:
>> https://bugs.openjdk.java.net/browse/JDK-8173699
>> http://cr.openjdk.java.net/~thartmann/8173699/webrev.00/
>>
>> The Graal compiled method
>> java.lang.invoke.MemberName$Factory::resolve() calls into the method
>> handle runtime via MethodHandleNatives::resolve() which throws a
>> NoSuchMethodError because method resolution failed (see
>> methodHandles.cpp, line 1234). We then call into
>> JVMCIRuntime::exception_handler_for_pc() ->
>> SharedRuntime::compute_compiled_exc_handler() to determine the
>> appropriate exception handler. Because the ExceptionHandlerTable has
>> no entry for this pc, we deoptimize and return to the
>> DeoptimizationBlob at offset _unpack_with_exception_in_tls which calls
>> Deoptimization::fetch_unroll_info(). Since the callee returns a
>> MemberName object, the ScopeDesc is marked as return_oop() and the
>> re-allocation code expects the return register (eax) to contain the
>> oop of this returned object. We fail when trying to save the oop,
>> because eax contains not an oop but the address of
>> SharedRuntime::deopt_blob()->unpack_with_exception_in_tls() which was
>> returned from JVMCIRuntime::exception_handler_for_pc() right before
>> and is therefore still in eax.
>>
>> As Tom suggested in the bug comments, we should ignore the
>> return_oop() when dispatching an exception and only try to retrieve
>> the oop when performing re-allocation during a normal deoptimization
>> (if exec_mode == Unpack_deopt). This code should be refactored with
>> JDK 10. I filed JDK-8173823.
>>
>> This problem only affects JVMCI compiled code. C1 does not set
>> return_oop() because it does not eliminate allocations (see
>> IRScopeDebugInfo::record_debug_info()) and therefore does not need to
>> re-allocate objects on deoptimization. C2 computes the exception
>> handler via OptoRuntime::handle_exception_C() and uses
>> DeoptimizationBlob::_unpack_with_exception as handler in case the
>> nmethod was deoptimized. When calling
>> Deoptimization::fetch_unroll_info() from the DeoptimizationBlob, eax
>> still contains the exception oop and therefore the code works "by
>> accident" because the exception oop is treated as returned oop.
>>
>> Tested with JVMCI test and RBT (running).
>>
>> Thanks to Tom and Dean for the help!
>>
>> Thanks,
>> Tobias
>>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [9] RFR(S): 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop"

Tobias Hartmann-2
Thanks, Vladimir!

Best regards,
Tobias

On 02.02.2017 17:42, Vladimir Kozlov wrote:

> +1
>
> Vladimir K
>
> On 2/2/17 5:06 AM, Vladimir Ivanov wrote:
>> Looks good.
>>
>> Best regards,
>> Vladimir Ivanov
>>
>> On 2/2/17 4:04 PM, Tobias Hartmann wrote:
>>> Hi,
>>>
>>> please review the following patch:
>>> https://bugs.openjdk.java.net/browse/JDK-8173699
>>> http://cr.openjdk.java.net/~thartmann/8173699/webrev.00/
>>>
>>> The Graal compiled method
>>> java.lang.invoke.MemberName$Factory::resolve() calls into the method
>>> handle runtime via MethodHandleNatives::resolve() which throws a
>>> NoSuchMethodError because method resolution failed (see
>>> methodHandles.cpp, line 1234). We then call into
>>> JVMCIRuntime::exception_handler_for_pc() ->
>>> SharedRuntime::compute_compiled_exc_handler() to determine the
>>> appropriate exception handler. Because the ExceptionHandlerTable has
>>> no entry for this pc, we deoptimize and return to the
>>> DeoptimizationBlob at offset _unpack_with_exception_in_tls which calls
>>> Deoptimization::fetch_unroll_info(). Since the callee returns a
>>> MemberName object, the ScopeDesc is marked as return_oop() and the
>>> re-allocation code expects the return register (eax) to contain the
>>> oop of this returned object. We fail when trying to save the oop,
>>> because eax contains not an oop but the address of
>>> SharedRuntime::deopt_blob()->unpack_with_exception_in_tls() which was
>>> returned from JVMCIRuntime::exception_handler_for_pc() right before
>>> and is therefore still in eax.
>>>
>>> As Tom suggested in the bug comments, we should ignore the
>>> return_oop() when dispatching an exception and only try to retrieve
>>> the oop when performing re-allocation during a normal deoptimization
>>> (if exec_mode == Unpack_deopt). This code should be refactored with
>>> JDK 10. I filed JDK-8173823.
>>>
>>> This problem only affects JVMCI compiled code. C1 does not set
>>> return_oop() because it does not eliminate allocations (see
>>> IRScopeDebugInfo::record_debug_info()) and therefore does not need to
>>> re-allocate objects on deoptimization. C2 computes the exception
>>> handler via OptoRuntime::handle_exception_C() and uses
>>> DeoptimizationBlob::_unpack_with_exception as handler in case the
>>> nmethod was deoptimized. When calling
>>> Deoptimization::fetch_unroll_info() from the DeoptimizationBlob, eax
>>> still contains the exception oop and therefore the code works "by
>>> accident" because the exception oop is treated as returned oop.
>>>
>>> Tested with JVMCI test and RBT (running).
>>>
>>> Thanks to Tom and Dean for the help!
>>>
>>> Thanks,
>>> Tobias
>>>
Loading...