diff options
Diffstat (limited to 'runtime/interpreter/interpreter_common.cc')
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 57 |
1 files changed, 3 insertions, 54 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 1fcace6d3b..c5e54436e1 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -439,7 +439,7 @@ static bool DoVarHandleInvokeCommon(Thread* self, bool is_var_args = inst->HasVarArgs(); const uint32_t vRegC = is_var_args ? inst->VRegC_45cc() : inst->VRegC_4rcc(); const uint16_t vRegH = is_var_args ? inst->VRegH_45cc() : inst->VRegH_4rcc(); - StackHandleScope<4> hs(self); + StackHandleScope<3> hs(self); Handle<mirror::VarHandle> var_handle = hs.NewHandle( ObjPtr<mirror::VarHandle>::DownCast(shadow_frame.GetVRegReference(vRegC))); ArtMethod* method = shadow_frame.GetMethod(); @@ -458,63 +458,12 @@ static bool DoVarHandleInvokeCommon(Thread* self, all_operands = &range_operands.value(); } NoReceiverInstructionOperands operands(all_operands); - ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); - // If the `ThreadLocalRandom` class is not yet initialized, do the `VarHandle` operation - // without creating a managed `MethodType` object. This avoids a circular initialization - // issue when `ThreadLocalRandom.<clinit>` indirectly calls `AtomicLong.compareAndSet()` - // (implemented with a `VarHandle`) and the `MethodType` caching circles back to the - // `ThreadLocalRandom` with uninitialized `seeder` and throws NPE. - // - // Do a quick test for "visibly initialized" without a read barrier and, if that fails, - // do a thorough test for "initialized" (including load acquire) with the read barrier. - ArtField* field = WellKnownClasses::java_util_concurrent_ThreadLocalRandom_seeder; - if (LIKELY(field->GetDeclaringClass<kWithoutReadBarrier>()->IsVisiblyInitialized()) || - field->GetDeclaringClass()->IsInitialized()) { - Handle<mirror::MethodType> callsite_type(hs.NewHandle( - class_linker->ResolveMethodType(self, dex::ProtoIndex(vRegH), dex_cache, class_loader))); - if (LIKELY(callsite_type != nullptr)) { - return VarHandleInvokeAccessor(self, - shadow_frame, - var_handle, - callsite_type, - access_mode, - &operands, - result); - } - // This implies we couldn't resolve one or more types in this VarHandle, - // or we could not allocate the `MethodType` object. - CHECK(self->IsExceptionPending()); - if (self->GetException()->GetClass() != WellKnownClasses::java_lang_OutOfMemoryError.Get()) { - return false; - } - // Clear the OOME and retry without creating an actual `MethodType` object. - // This prevents unexpected OOME for trivial `VarHandle` operations. - // It also prevents odd situations where a `VarHandle` operation succeeds but the same - // operation fails later because the `MethodType` object was evicted from the `DexCache` - // and we suddenly run out of memory to allocate a new one. - // - // We have previously seen OOMEs in the run-test `183-rmw-stress-test` with - // `--optimizng --no-image` (boot class path methods run in interpreter without JIT) - // but it probably happened on the first execution of a trivial `VarHandle` operation - // and not due to the `DexCache` eviction mentioned above. - self->ClearException(); - } - - VariableSizedHandleScope callsite_type_hs(self); - mirror::RawMethodType callsite_type(&callsite_type_hs); - if (!class_linker->ResolveMethodType(self, - dex::ProtoIndex(vRegH), - dex_cache, - class_loader, - callsite_type)) { - CHECK(self->IsExceptionPending()); - return false; - } return VarHandleInvokeAccessor(self, shadow_frame, + method, var_handle, - callsite_type, + dex::ProtoIndex(vRegH), access_mode, &operands, result); |