diff options
| -rw-r--r-- | src/class_linker.cc | 5 | ||||
| -rw-r--r-- | src/runtime_support.cc | 20 |
2 files changed, 16 insertions, 9 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 14f4b7e9ff..045974f8c3 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -2067,12 +2067,14 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit) { uint64_t t1 = NanoTime(); + bool success = true; { ObjectLock lock(klass); if (self->IsExceptionPending()) { WrapExceptionInInitializer(); klass->SetStatus(Class::kStatusError); + success = false; } else { RuntimeStats* global_stats = Runtime::Current()->GetStats(); RuntimeStats* thread_stats = self->GetStats(); @@ -2088,8 +2090,7 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit) { } lock.NotifyAll(); } - - return true; + return success; } bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& lock) { diff --git a/src/runtime_support.cc b/src/runtime_support.cc index 1a6d2e65c3..696ef70b42 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -408,12 +408,18 @@ void* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, Method** sp, Method* called = linker->ResolveMethod(method_idx, *caller_sp, true); if (LIKELY(!thread->IsExceptionPending())) { if (LIKELY(called->IsDirect())) { - // Update CodeAndDirectMethod table - Method* caller = *caller_sp; - DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); - dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called); - // We got this far, ensure that the declaring class is initialized - linker->EnsureInitialized(called->GetDeclaringClass(), true); + // Ensure that the called method's class is initialized + Class* called_class = called->GetDeclaringClass(); + linker->EnsureInitialized(called_class, true); + if (LIKELY(called_class->IsInitialized())) { + // Update CodeAndDirectMethod table and avoid the trampoline when we know the called class + // is initialized (see test 084-class-init SlowInit) + Method* caller = *caller_sp; + DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); + dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called); + // We got this far, ensure that the declaring class is initialized + linker->EnsureInitialized(called->GetDeclaringClass(), true); + } } else { // Direct method has been made virtual thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", @@ -430,7 +436,7 @@ void* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, Method** sp, thread->ClearException(); } else { // Expect class to at least be initializing - CHECK(called->GetDeclaringClass()->IsInitializing()); + DCHECK(called->GetDeclaringClass()->IsInitializing()); // Set up entry into main method regs[0] = reinterpret_cast<uintptr_t>(called); code = const_cast<void*>(called->GetCode()); |