summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/interpreter/interpreter_common.cc8
-rw-r--r--runtime/interpreter/interpreter_common.h3
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc19
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc20
-rw-r--r--runtime/jit/jit.cc8
-rw-r--r--runtime/jit/jit.h6
-rw-r--r--runtime/jit/jit_instrumentation.cc8
-rw-r--r--runtime/jit/jit_instrumentation.h5
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc8
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);
}