summaryrefslogtreecommitdiff
path: root/runtime/interpreter/interpreter_common.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2017-09-05 09:32:49 -0700
committer Alex Light <allight@google.com> 2017-09-05 10:54:05 -0700
commit9fb1ab1f6bb58bdaccef78bc81b3202d0121e2ed (patch)
treef4ec9bb10a2191f4aa80b1ee40332071bed38bab /runtime/interpreter/interpreter_common.cc
parentc101222c854a0c476f5b6ae64e20adbd38126a3c (diff)
Revert "Revert "JVMTI Exception and ExceptionCatch events""
Fixed error where we were incorrectly not updating a ShadowFrame dex_pc causing deoptimization errors. Bug: 62821960 Bug: 65049545 Test: ./test.py --host -j50 Test: ./art/tools/run-libcore-tests.sh \ --mode=host --variant-X32 --debug This reverts commit 959742483885779f106e000df6dd422fc8657931. Change-Id: I91ab2bc3e645ddf0359c189b19a59a3ecf0d8921
Diffstat (limited to 'runtime/interpreter/interpreter_common.cc')
-rw-r--r--runtime/interpreter/interpreter_common.cc54
1 files changed, 38 insertions, 16 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index ae461fd987..0028b21f94 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -416,35 +416,57 @@ 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 execute any instrumentation events that are triggered by this exception and change the
+// shadow_frame's dex_pc to that of the exception handler if there is one in the current method.
+// Return true if we should continue executing in the current method and false if we need to go up
+// the stack to find an exception handler.
// 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) {
+// TODO We should have a better way to skip instrumentation reporting or possibly rethink that
+// behavior.
+bool MoveToExceptionHandler(Thread* self,
+ ShadowFrame& shadow_frame,
+ const instrumentation::Instrumentation* instrumentation) {
self->VerifyStack();
StackHandleScope<2> hs(self);
Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
- if (instrumentation != nullptr && instrumentation->HasExceptionThrownListeners()
- && self->IsExceptionThrownByCurrentMethod(exception.Get())) {
+ if (instrumentation != nullptr &&
+ instrumentation->HasExceptionThrownListeners() &&
+ self->IsExceptionThrownByCurrentMethod(exception.Get())) {
+ // See b/65049545 for why we don't need to check to see if the exception has changed.
instrumentation->ExceptionThrownEvent(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 && instrumentation != nullptr) {
- if (shadow_frame.NeedsNotifyPop()) {
- instrumentation->WatchedFramePopped(self, shadow_frame);
+ hs.NewHandle(exception->GetClass()), shadow_frame.GetDexPC(), &clear_exception);
+ if (found_dex_pc == DexFile::kDexNoIndex) {
+ if (instrumentation != nullptr) {
+ if (shadow_frame.NeedsNotifyPop()) {
+ instrumentation->WatchedFramePopped(self, shadow_frame);
+ }
+ // Exception is not caught by the current method. We will unwind to the
+ // caller. Notify any instrumentation listener.
+ instrumentation->MethodUnwindEvent(self,
+ shadow_frame.GetThisObject(),
+ shadow_frame.GetMethod(),
+ shadow_frame.GetDexPC());
}
- // Exception is not caught by the current method. We will unwind to the
- // caller. Notify any instrumentation listener.
- instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
- shadow_frame.GetMethod(), dex_pc);
+ return false;
} else {
- // Exception is caught in the current method. We will jump to the found_dex_pc.
- if (clear_exception) {
+ shadow_frame.SetDexPC(found_dex_pc);
+ if (instrumentation != nullptr && instrumentation->HasExceptionHandledListeners()) {
+ self->ClearException();
+ instrumentation->ExceptionHandledEvent(self, exception.Get());
+ if (UNLIKELY(self->IsExceptionPending())) {
+ // Exception handled event threw an exception. Try to find the handler for this one.
+ return MoveToExceptionHandler(self, shadow_frame, instrumentation);
+ } else if (!clear_exception) {
+ self->SetException(exception.Get());
+ }
+ } else if (clear_exception) {
self->ClearException();
}
+ return true;
}
- return found_dex_pc;
}
void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) {