diff options
| -rw-r--r-- | runtime/interpreter/interpreter_common.cc | 8 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_common.h | 3 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_goto_table_impl.cc | 19 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_switch_impl.cc | 20 | ||||
| -rw-r--r-- | runtime/jit/jit.cc | 8 | ||||
| -rw-r--r-- | runtime/jit/jit.h | 6 | ||||
| -rw-r--r-- | runtime/jit/jit_instrumentation.cc | 8 | ||||
| -rw-r--r-- | runtime/jit/jit_instrumentation.h | 5 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 8 |
9 files changed, 78 insertions, 7 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index ecd4de9bd0..6c9cc7017b 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -518,10 +518,10 @@ static inline bool NeedsInterpreter(Thread* self, ShadowFrame* new_shadow_frame) Dbg::IsForcedInterpreterNeededForCalling(self, target); } -static void ArtInterpreterToCompiledCodeBridge(Thread* self, - const DexFile::CodeItem* code_item, - ShadowFrame* shadow_frame, - JValue* result) +void ArtInterpreterToCompiledCodeBridge(Thread* self, + const DexFile::CodeItem* code_item, + ShadowFrame* shadow_frame, + JValue* result) SHARED_REQUIRES(Locks::mutator_lock_) { ArtMethod* method = shadow_frame->GetMethod(); // Ensure static methods are initialized. diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 932d255b0e..949112de5c 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -980,6 +980,9 @@ static inline bool IsBackwardBranch(int32_t branch_offset) { return branch_offset <= 0; } +void ArtInterpreterToCompiledCodeBridge(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame* shadow_frame, JValue* result); + // Explicitly instantiate all DoInvoke functions. #define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range, _do_check) \ template SHARED_REQUIRES(Locks::mutator_lock_) \ diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc index ca006214c8..d50cfe64ae 100644 --- a/runtime/interpreter/interpreter_goto_table_impl.cc +++ b/runtime/interpreter/interpreter_goto_table_impl.cc @@ -21,6 +21,7 @@ #include "base/stl_util.h" // MakeUnique #include "experimental_flags.h" #include "interpreter_common.h" +#include "jit/jit.h" #include "safe_math.h" #include <memory> // std::unique_ptr @@ -183,9 +184,25 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF self->AssertNoPendingException(); } instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); + ArtMethod *method = shadow_frame.GetMethod(); + if (UNLIKELY(instrumentation->HasMethodEntryListeners())) { instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), - shadow_frame.GetMethod(), 0); + method, 0); + } + + if (UNLIKELY(Runtime::Current()->GetJit() != nullptr && + Runtime::Current()->GetJit()->JitAtFirstUse() && + method->HasAnyCompiledCode())) { + JValue result; + + // Pop the shadow frame before calling into compiled code. + self->PopShadowFrame(); + ArtInterpreterToCompiledCodeBridge(self, code_item, &shadow_frame, &result); + // Push the shadow frame back as the caller will expect it. + self->PushShadowFrame(&shadow_frame); + + return result; } } diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index c3b75b29e7..56a213cd1f 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -17,6 +17,7 @@ #include "base/stl_util.h" // MakeUnique #include "experimental_flags.h" #include "interpreter_common.h" +#include "jit/jit.h" #include "safe_math.h" #include <memory> // std::unique_ptr @@ -96,9 +97,26 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item, if (kIsDebugBuild) { self->AssertNoPendingException(); } + + ArtMethod* method = shadow_frame.GetMethod(); + if (UNLIKELY(instrumentation->HasMethodEntryListeners())) { instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), - shadow_frame.GetMethod(), 0); + method, 0); + } + + if (UNLIKELY(Runtime::Current()->GetJit() != nullptr && + Runtime::Current()->GetJit()->JitAtFirstUse() && + method->HasAnyCompiledCode())) { + JValue result; + + // Pop the shadow frame before calling into compiled code. + self->PopShadowFrame(); + ArtInterpreterToCompiledCodeBridge(self, code_item, &shadow_frame, &result); + // Push the shadow frame back as the caller will expect it. + self->PushShadowFrame(&shadow_frame); + + return result; } } const uint16_t* const insns = code_item->insns_; diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 8f4d24f385..f540814fbe 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -202,6 +202,13 @@ void Jit::StopProfileSaver() { } } +bool Jit::JitAtFirstUse() { + if (instrumentation_cache_ != nullptr) { + return instrumentation_cache_->HotMethodThreshold() == 0; + } + return false; +} + Jit::~Jit() { DCHECK(!save_profiling_info_ || !ProfileSaver::IsStarted()); if (dump_info_on_shutdown_) { @@ -217,7 +224,6 @@ Jit::~Jit() { } void Jit::CreateInstrumentationCache(size_t compile_threshold, size_t warmup_threshold) { - CHECK_GT(compile_threshold, 0U); instrumentation_cache_.reset( new jit::JitInstrumentationCache(compile_threshold, warmup_threshold)); } diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 429edf65a6..a80f51f397 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -86,6 +86,8 @@ class Jit { // into the specified class linker to the jit debug interface, void DumpTypeInfoForLoadedTypes(ClassLinker* linker); + bool JitAtFirstUse(); + private: Jit(); bool LoadCompiler(std::string* error_msg); @@ -142,6 +144,10 @@ class JitOptions { void SetSaveProfilingInfo(bool b) { save_profiling_info_ = b; } + void SetJitAtFirstUse() { + use_jit_ = true; + compile_threshold_ = 0; + } private: bool use_jit_; diff --git a/runtime/jit/jit_instrumentation.cc b/runtime/jit/jit_instrumentation.cc index 6b47b677dc..d597b36e95 100644 --- a/runtime/jit/jit_instrumentation.cc +++ b/runtime/jit/jit_instrumentation.cc @@ -162,6 +162,14 @@ void JitInstrumentationListener::MethodEntered(Thread* thread, mirror::Object* /*this_object*/, ArtMethod* method, uint32_t /*dex_pc*/) { + if (UNLIKELY(Runtime::Current()->GetJit()->JitAtFirstUse())) { + // The compiler requires a ProfilingInfo object. + ProfilingInfo::Create(thread, method, /* retry_allocation */ true); + JitCompileTask compile_task(method, JitCompileTask::kCompile); + compile_task.Run(thread); + return; + } + instrumentation_cache_->AddSamples(thread, method, 1); } diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h index 620c087455..06559ad2e4 100644 --- a/runtime/jit/jit_instrumentation.h +++ b/runtime/jit/jit_instrumentation.h @@ -101,6 +101,11 @@ class JitInstrumentationCache { SHARED_REQUIRES(Locks::mutator_lock_); void CreateThreadPool(); void DeleteThreadPool(Thread* self); + + size_t HotMethodThreshold() const { + return hot_method_threshold_; + } + // Wait until there is no more pending compilation tasks. void WaitForCompilationToFinish(Thread* self); diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 67d825efaa..a7881ac52f 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -65,6 +65,7 @@ static void EnableDebugFeatures(uint32_t debug_flags) { DEBUG_ENABLE_SAFEMODE = 1 << 3, DEBUG_ENABLE_JNI_LOGGING = 1 << 4, DEBUG_GENERATE_DEBUG_INFO = 1 << 5, + DEBUG_ALWAYS_JIT = 1 << 6, }; Runtime* const runtime = Runtime::Current(); @@ -109,6 +110,13 @@ static void EnableDebugFeatures(uint32_t debug_flags) { // This is for backwards compatibility with Dalvik. debug_flags &= ~DEBUG_ENABLE_ASSERT; + if ((debug_flags & DEBUG_ALWAYS_JIT) != 0) { + jit::JitOptions* jit_options = runtime->GetJITOptions(); + CHECK(jit_options != nullptr); + jit_options->SetJitAtFirstUse(); + debug_flags &= ~DEBUG_ALWAYS_JIT; + } + if (debug_flags != 0) { LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags); } |