summaryrefslogtreecommitdiff
path: root/runtime/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/interpreter')
-rw-r--r--runtime/interpreter/interpreter.cc8
-rw-r--r--runtime/interpreter/interpreter_common.cc5
-rw-r--r--runtime/interpreter/interpreter_common.h12
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);
}