On May 14, 2014, at 3:47 AM, Vladimir Ivanov <vladimir.x.iva...@oracle.com> wrote:
> Tobias, I agree with your evaluation. > > My only concern is that @Stable doesn't work for AtomicReferenceArray, so JIT > doesn't see what is stored in the array. Now that is really unfortunate. > Maybe use a lock instead? > > Best regards, > Vladimir Ivanov > > On 5/14/14 2:33 PM, Tobias Hartmann wrote: >> Hi Remi, >> >> sorry, I accidentally reverted that part.. Here is the correct webrev: >> >> http://cr.openjdk.java.net/~anoll/8005873/webrev.01/ >> >> Thanks, >> Tobias >> >> On 14.05.2014 12:04, Remi Forax wrote: >>> your patch doesn't work ! >>> >>> the array is still allocated as an classical array in the constructor. >>> >>> cheers, >>> Remi >>> >>> Envoyé avec AquaMail pour Android >>> http://www.aqua-mail.com >>> >>> >>> Le 14 mai 2014 11:04:41 Tobias Hartmann <tobias.hartm...@oracle.com> a >>> écrit : >>> >>>> Hi, >>>> >>>> please review the following patch for bug 8005873. >>>> >>>> *Problem* >>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8005873 >>>> >>>> The test creates multiple threads (~500) that repeatedly execute >>>> invokeExact on a method handle referencing a static method. The call >>>> to invokeExact is performed through an optimized inline cache >>>> (CompiledStaticCall) that points to the LambdaForm generated for the >>>> method handle. The IC is first set to interpreted code by >>>> CompiledStaticCall::set_to_interpreted(...) but soon updated to refer >>>> to the compiled version of the lambda form (-Xcomp). >>>> >>>> Because tiered compilation is enabled, the VM decides to compile the >>>> LambdaForm at a different level and sets the old version to >>>> not-entrant. The next call through the IC therefore triggers a >>>> re-resolving of the call site finally performing a Java upcall to >>>> java.lang.invoke.MethodHandleNatives::linkMethod(...) (see call >>>> sequence [1]). A *new* LambdaForm is returned and >>>> CompiledStaticCall::set_to_interpreted(...) is executed again to >>>> update the IC. The assert is hit because the callee differs. >>>> >>>> The problem is that there are multiple LambdaForms created for the >>>> same invokeExact instruction. Caching in the Java runtime code should >>>> guarantee that only one LambdaForm is created and reused. >>>> Instrumenting Invokers::invokeHandleForm(...) shows that almost all >>>> requests result in a cache miss and return a new LambdaForm. >>>> >>>> This behaviour is caused by a race condition in >>>> Invokers::invokeHandleForm(...). Threads may initially see a cache >>>> miss when invoking MethodTypeForm::cachedLambdaForm(...), then create >>>> a new LambdaForm and call MethodTypeForm::setCachedLambdaForm(...) to >>>> update the cache without checking it again. In a high concurrency >>>> setting, this leads to multiple LambdaForms being created for the >>>> same invokeExact instruction because the cache entry is overwritten >>>> by multiple threads. >>>> >>>> *Solution* >>>> Webrev: http://cr.openjdk.java.net/~anoll/8005873/webrev.00/ >>>> >>>> An AtomicReferenceArray is used to cache the LambdaForms and >>>> .get(...) and .compareAndSet(...) are used to retrieve and update the >>>> cache entries. This allows only one thread to set the LambdaForm that >>>> is then being used by all instances of the invokeExact. >>>> >>>> *Testing* >>>> - Failing test (vm/mlvm/meth/stress/jni/nativeAndMH) >>>> - Nashorn + Octane >>>> - JPRT >>>> >>>> Many thanks to Christian Thalinger and Vladimir Ivanov! >>>> >>>> Best, >>>> Tobias >>>> >>>> [1] Call sequence of reresolving the IC target >>>> SharedRuntime::handle_wrong_method(...) >>>> -> SharedRuntime::reresolve_call_site(...) >>>> -> SharedRuntime::find_callee_method(...) >>>> -> SharedRuntime::find_callee_info_helper(...) >>>> -> LinkResolver::resolve_invoke(...) >>>> -> LinkResolver::resolve_invokehandle(...) >>>> -> LinkResolver::resolve_invokehandle(...) >>>> -> LinkResolver::lookup_polymorphic_method(...) >>>> -> SystemDictionary::find_method_handle_invoker(...) >>>> -> Java upcall to java.lang.invoke.MethodHandleNatives::linkMethod(...) >>>> -> Invokers::methodHandleInvokeLinkerMethod(...) >>>> -> Invokers::invokeHandleForm(...) >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> Backport? >>> >>> >>