diff options
| -rw-r--r-- | runtime/instrumentation.h | 9 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter.cc | 8 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_common.h | 17 | ||||
| -rw-r--r-- | runtime/interpreter/mterp/mterp.cc | 8 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 4 | ||||
| -rw-r--r-- | runtime/runtime.cc | 5 |
6 files changed, 26 insertions, 25 deletions
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index b3fae25210..3bd4fb54af 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -384,15 +384,6 @@ class Instrumentation { have_exception_handled_listeners_; } - // Any instrumentation *other* than what is needed for Jit profiling active? - bool NonJitProfilingActive() const REQUIRES_SHARED(Locks::mutator_lock_) { - return have_dex_pc_listeners_ || have_method_exit_listeners_ || - have_field_read_listeners_ || have_field_write_listeners_ || - have_exception_thrown_listeners_ || have_method_unwind_listeners_ || - have_branch_listeners_ || have_watched_frame_pop_listeners_ || - have_exception_handled_listeners_; - } - // Inform listeners that a method has been entered. A dex PC is provided as we may install // listeners into executing code and get method enter events for methods already on the stack. void MethodEnterEvent(Thread* thread, mirror::Object* this_object, diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index b37a2781b5..5784b9b898 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -248,6 +248,14 @@ static inline JValue Execute( bool from_deoptimize = false) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(!shadow_frame.GetMethod()->IsAbstract()); DCHECK(!shadow_frame.GetMethod()->IsNative()); + + // Check that we are using the right interpreter. + if (kIsDebugBuild && self->UseMterp() != CanUseMterp()) { + // The flag might be currently being updated on all threads. Retry with lock. + MutexLock tll_mu(self, *Locks::thread_list_lock_); + DCHECK_EQ(self->UseMterp(), CanUseMterp()); + } + if (LIKELY(!from_deoptimize)) { // Entering the method, but not via deoptimization. if (kIsDebugBuild) { CHECK_EQ(shadow_frame.GetDexPC(), 0u); diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 96588c8738..9924aa5292 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -128,10 +128,8 @@ template<InvokeType type> static ALWAYS_INLINE bool UseInterpreterToInterpreterFastPath(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { Runtime* runtime = Runtime::Current(); - if (!runtime->IsStarted()) { - return false; - } const void* quick_code = method->GetEntryPointFromQuickCompiledCode(); + DCHECK(runtime->IsStarted()); if (!runtime->GetClassLinker()->IsQuickToInterpreterBridge(quick_code)) { return false; } @@ -144,16 +142,11 @@ static ALWAYS_INLINE bool UseInterpreterToInterpreterFastPath(ArtMethod* method) if (type == kStatic && !method->GetDeclaringClass()->IsInitialized()) { return false; } - if (runtime->IsActiveTransaction() || runtime->GetInstrumentation()->HasMethodEntryListeners()) { - return false; - } + DCHECK(!runtime->IsActiveTransaction()); ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize); if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) { return false; } - if (runtime->GetJit() != nullptr && runtime->GetJit()->JitAtFirstUse()) { - return false; - } return true; } @@ -171,7 +164,9 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // Make sure to check for async exceptions before anything else. - if (UNLIKELY(self->ObserveAsyncException())) { + if (is_mterp && self->UseMterp()) { + DCHECK(!self->ObserveAsyncException()); + } else if (UNLIKELY(self->ObserveAsyncException())) { return false; } const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); @@ -229,7 +224,7 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, } } - if (is_mterp && UseInterpreterToInterpreterFastPath<type>(called_method)) { + if (is_mterp && self->UseMterp() && UseInterpreterToInterpreterFastPath<type>(called_method)) { const uint16_t number_of_inputs = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data); CodeItemDataAccessor accessor(called_method->DexInstructionData()); diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc index 4b6f430e65..ba109bc2b7 100644 --- a/runtime/interpreter/mterp/mterp.cc +++ b/runtime/interpreter/mterp/mterp.cc @@ -146,15 +146,18 @@ bool CanUseMterp() REQUIRES_SHARED(Locks::mutator_lock_) { const Runtime* const runtime = Runtime::Current(); return + runtime->IsStarted() && + !runtime->IsAotCompiler() && !Dbg::IsDebuggerActive() && - !runtime->GetInstrumentation()->NonJitProfilingActive() && + !runtime->GetInstrumentation()->IsActive() && // mterp only knows how to deal with the normal exits. It cannot handle any of the // non-standard force-returns. !runtime->AreNonStandardExitsEnabled() && // An async exception has been thrown. We need to go to the switch interpreter. MTerp doesn't // know how to deal with these so we could end up never dealing with it if we are in an // infinite loop. - !runtime->AreAsyncExceptionsThrown(); + !runtime->AreAsyncExceptionsThrown() && + (runtime->GetJit() == nullptr || !runtime->GetJit()->JitAtFirstUse()); } @@ -560,6 +563,7 @@ extern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame, uint16 MutexLock tll_mu(self, *Locks::thread_list_lock_); DCHECK_EQ(self->UseMterp(), CanUseMterp()); } + DCHECK(!Runtime::Current()->IsActiveTransaction()); const Instruction* inst = Instruction::At(dex_pc_ptr); uint16_t inst_data = inst->Fetch16(0); if (inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION) { diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index f54bf87216..f5c0704098 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -225,7 +225,9 @@ static uint32_t EnableDebugFeatures(uint32_t runtime_flags) { if ((runtime_flags & DEBUG_ALWAYS_JIT) != 0) { jit::JitOptions* jit_options = runtime->GetJITOptions(); CHECK(jit_options != nullptr); - jit_options->SetJitAtFirstUse(); + Runtime::Current()->DoAndMaybeSwitchInterpreter([=]() { + jit_options->SetJitAtFirstUse(); + }); runtime_flags &= ~DEBUG_ALWAYS_JIT; } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 40c7301456..a152692897 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -744,7 +744,7 @@ bool Runtime::Start() { self->TransitionFromRunnableToSuspended(kNative); - started_ = true; + DoAndMaybeSwitchInterpreter([=](){ started_ = true; }); if (!IsImageDex2OatEnabled() || !GetHeap()->HasBootImageSpace()) { ScopedObjectAccess soa(self); @@ -2488,7 +2488,8 @@ void Runtime::CreateJit() { DCHECK(!jit_options_->UseJitCompilation()); } std::string error_msg; - jit_.reset(jit::Jit::Create(jit_options_.get(), &error_msg)); + jit::Jit* jit = jit::Jit::Create(jit_options_.get(), &error_msg); + DoAndMaybeSwitchInterpreter([=](){ jit_.reset(jit); }); if (jit_.get() == nullptr) { LOG(WARNING) << "Failed to create JIT " << error_msg; return; |