summaryrefslogtreecommitdiffstats
path: root/runtime/quick_exception_handler.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-05-23 08:59:42 +0200
committerSebastien Hertz <shertz@google.com>2014-06-11 14:29:00 +0200
commit9f1020305292a21fd14a402b189c765a125226ab (patch)
tree6b730cbe56ded370d1b4293629826ad2c7b06f7f /runtime/quick_exception_handler.cc
parentbc72903b909f5147b8cb207f3e5d02a8ef85e4e7 (diff)
downloadart-9f1020305292a21fd14a402b189c765a125226ab.zip
art-9f1020305292a21fd14a402b189c765a125226ab.tar.gz
art-9f1020305292a21fd14a402b189c765a125226ab.tar.bz2
Fix exception reporting from interpreter
To comply with JDWP exception report rules, we must report an exception at the location of the throw (or the first instruction encountered after a native call). To do this, we use the CatchLocationFinder visitor to look for a catch handler until we reach a native frame or the top frame. Because interpreter handles pending exception on a method-by-method basis, we need a flag to remember we already reported the exception and avoid reporting it multiple times when unwinding methods. The drawback is we need to maintain the state of this flag. We clear it when the exception is cleared. In the case we temporarily clear the exception (when finding a catch handler for instance), we restore the flag to its previous value at the same time we restore the pending exception. Bump oat version to force recompilation because we modify Thread offsets. Bug: 14402770 Change-Id: Ic059c58f80b2023b118038301f8f0a24f1e18241
Diffstat (limited to 'runtime/quick_exception_handler.cc')
-rw-r--r--runtime/quick_exception_handler.cc21
1 files changed, 17 insertions, 4 deletions
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index e3f9afc..1034923 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -110,7 +110,8 @@ class CatchBlockStackVisitor FINAL : public StackVisitor {
};
void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
- mirror::Throwable* exception) {
+ mirror::Throwable* exception,
+ bool is_exception_reported) {
DCHECK(!is_deoptimization_);
if (kDebugExceptionDelivery) {
mirror::String* msg = exception->GetDetailMessage();
@@ -141,12 +142,24 @@ void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
} else {
// Put exception back in root set with clear throw location.
self_->SetException(ThrowLocation(), exception_ref.Get());
+ self_->SetExceptionReportedToInstrumentation(is_exception_reported);
}
// The debugger may suspend this thread and walk its stack. Let's do this before popping
// instrumentation frames.
- instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
- instrumentation->ExceptionCaughtEvent(self_, throw_location, handler_method_, handler_dex_pc_,
- exception_ref.Get());
+ if (!is_exception_reported) {
+ instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+ instrumentation->ExceptionCaughtEvent(self_, throw_location, handler_method_, handler_dex_pc_,
+ exception_ref.Get());
+ // We're not catching this exception but let's remind we already reported the exception above
+ // to avoid reporting it twice.
+ self_->SetExceptionReportedToInstrumentation(true);
+ }
+ bool caught_exception = (handler_method_ != nullptr && handler_dex_pc_ != DexFile::kDexNoIndex);
+ if (caught_exception) {
+ // We're catching this exception so we finish reporting it. We do it here to avoid doing it
+ // in the compiled code.
+ self_->SetExceptionReportedToInstrumentation(false);
+ }
}
// Prepares deoptimization.