diff options
Diffstat (limited to 'runtime/interpreter/interpreter.cc')
-rw-r--r-- | runtime/interpreter/interpreter.cc | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 871fad7b80..e7b4731ef8 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -18,12 +18,14 @@ #include <limits> +#include "common_throws.h" #include "interpreter_common.h" #include "mirror/string-inl.h" #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" #include "stack.h" #include "unstarted_runtime.h" +#include "mterp/mterp.h" namespace art { namespace interpreter { @@ -223,19 +225,33 @@ static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& s } enum InterpreterImplKind { - kSwitchImpl, // Switch-based interpreter implementation. - kComputedGotoImplKind // Computed-goto-based interpreter implementation. + kSwitchImplKind, // Switch-based interpreter implementation. + kComputedGotoImplKind, // Computed-goto-based interpreter implementation. + kMterpImplKind // Assembly interpreter }; static std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) { - os << ((rhs == kSwitchImpl) ? "Switch-based interpreter" : "Computed-goto-based interpreter"); + os << ((rhs == kSwitchImplKind) + ? "Switch-based interpreter" + : (rhs == kComputedGotoImplKind) + ? "Computed-goto-based interpreter" + : "Asm interpreter"); return os; } #if !defined(__clang__) +#if defined(__arm__) && !defined(ART_USE_READ_BARRIER) +// TODO: remove when all targets implemented. +static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind; +#else static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind; +#endif #else // Clang 3.4 fails to build the goto interpreter implementation. -static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl; +#if defined(__arm__) && !defined(ART_USE_READ_BARRIER) +static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind; +#else +static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImplKind; +#endif template<bool do_access_check, bool transaction_active> JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) { LOG(FATAL) << "UNREACHABLE"; @@ -262,18 +278,52 @@ static JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFr static inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register) { - DCHECK(shadow_frame.GetMethod()->IsInvokable()); + DCHECK(!shadow_frame.GetMethod()->IsAbstract()); DCHECK(!shadow_frame.GetMethod()->IsNative()); shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); bool transaction_active = Runtime::Current()->IsActiveTransaction(); if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) { // Enter the "without access check" interpreter. - if (kInterpreterImplKind == kSwitchImpl) { + if (kInterpreterImplKind == kMterpImplKind) { if (transaction_active) { - return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register); + // No Mterp variant - just use the switch interpreter. + return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register, + false); } else { - return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register); + const instrumentation::Instrumentation* const instrumentation = + Runtime::Current()->GetInstrumentation(); + while (true) { + if (instrumentation->IsActive() || !Runtime::Current()->IsStarted()) { + // TODO: allow JIT profiling instrumentation. Now, just punt on all instrumentation. +#if !defined(__clang__) + return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register); +#else + return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register, + false); +#endif + } + bool returned = ExecuteMterpImpl(self, code_item, &shadow_frame, &result_register); + if (returned) { + return result_register; + } else { + // Mterp didn't like that instruction. Single-step it with the reference interpreter. + JValue res = ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, + result_register, true); + if (shadow_frame.GetDexPC() == DexFile::kDexNoIndex) { + // Single-stepped a return or an exception not handled locally. Return to caller. + return res; + } + } + } + } + } else if (kInterpreterImplKind == kSwitchImplKind) { + if (transaction_active) { + return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register, + false); + } else { + return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register, + false); } } else { DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); @@ -285,11 +335,22 @@ static inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item, } } else { // Enter the "with access check" interpreter. - if (kInterpreterImplKind == kSwitchImpl) { + if (kInterpreterImplKind == kMterpImplKind) { + // No access check variants for Mterp. Just use the switch version. + if (transaction_active) { + return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register, + false); + } else { + return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register, + false); + } + } else if (kInterpreterImplKind == kSwitchImplKind) { if (transaction_active) { - return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register, + false); } else { - return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register, + false); } } else { DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); @@ -500,5 +561,13 @@ void ArtInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* co self->PopShadowFrame(); } +void CheckInterpreterAsmConstants() { + CheckMterpAsmConstants(); +} + +void InitInterpreterTls(Thread* self) { + InitMterpTls(self); +} + } // namespace interpreter } // namespace art |