diff options
Diffstat (limited to 'runtime/interpreter')
| -rw-r--r-- | runtime/interpreter/interpreter.cc | 8 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_common.cc | 5 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_common.h | 12 |
3 files changed, 22 insertions, 3 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 6c6232c437..3ac80c6642 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -399,14 +399,19 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa JValue value; // Set value to last known result in case the shadow frame chain is empty. value.SetJ(ret_val->GetJ()); + // Are we executing the first shadow frame? + bool first = true; while (shadow_frame != nullptr) { self->SetTopOfShadowStack(shadow_frame); const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem(); const uint32_t dex_pc = shadow_frame->GetDexPC(); uint32_t new_dex_pc; if (UNLIKELY(self->IsExceptionPending())) { + // If we deoptimize from the QuickExceptionHandler, we already reported the exception to + // the instrumentation. To prevent from reporting it a second time, we simply pass a + // null Instrumentation*. const instrumentation::Instrumentation* const instrumentation = - Runtime::Current()->GetInstrumentation(); + first ? nullptr : Runtime::Current()->GetInstrumentation(); uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc, instrumentation); new_dex_pc = found_dex_pc; // the dex pc of a matching catch handler @@ -424,6 +429,7 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa ShadowFrame* old_frame = shadow_frame; shadow_frame = shadow_frame->GetLink(); ShadowFrame::DeleteDeoptimizedFrame(old_frame); + first = false; } ret_val->SetJ(value.GetJ()); } diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index af67379375..6602840ed0 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -414,20 +414,21 @@ EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimNot) // iput-objec #undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL #undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL +// We accept a null Instrumentation* meaning we must not report anything to the instrumentation. uint32_t FindNextInstructionFollowingException( Thread* self, ShadowFrame& shadow_frame, uint32_t dex_pc, const instrumentation::Instrumentation* instrumentation) { self->VerifyStack(); StackHandleScope<2> hs(self); Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException())); - if (instrumentation->HasExceptionCaughtListeners() + if (instrumentation != nullptr && instrumentation->HasExceptionCaughtListeners() && self->IsExceptionThrownByCurrentMethod(exception.Get())) { instrumentation->ExceptionCaughtEvent(self, exception.Get()); } bool clear_exception = false; uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock( hs.NewHandle(exception->GetClass()), dex_pc, &clear_exception); - if (found_dex_pc == DexFile::kDexNoIndex) { + if (found_dex_pc == DexFile::kDexNoIndex && instrumentation != nullptr) { // Exception is not caught by the current method. We will unwind to the // caller. Notify any instrumentation listener. instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(), diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index fdefb9f74c..7398778d15 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -265,6 +265,13 @@ static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instr result->SetJ(0); return false; } else { + if (type == kVirtual || type == kInterface) { + instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); + if (UNLIKELY(instrumentation->HasInvokeVirtualOrInterfaceListeners())) { + instrumentation->InvokeVirtualOrInterface( + self, receiver, sf_method, shadow_frame.GetDexPC(), called_method); + } + } return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data, result); } @@ -297,6 +304,11 @@ static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, result->SetJ(0); return false; } else { + instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); + if (UNLIKELY(instrumentation->HasInvokeVirtualOrInterfaceListeners())) { + instrumentation->InvokeVirtualOrInterface( + self, receiver, shadow_frame.GetMethod(), shadow_frame.GetDexPC(), called_method); + } // No need to check since we've been quickened. return DoCall<is_range, false>(called_method, self, shadow_frame, inst, inst_data, result); } |