From 520633bebd2bf4d70884d30f179dbde9f275aac6 Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Tue, 8 Sep 2015 17:03:36 +0200 Subject: Support deoptimization on exception Allows to deoptimize when an exception is being thrown. We only deoptimize if an executable frame (starting from the catch handler) needs to be executed with the interpreter. Before executing deoptimized frames, the exception is restored. The interpreter starts by handling this exception at the point of the throwing instruction. Bug: 23714835 Change-Id: I0c5f7d4b257644acf12210aae8e5b6bb0f4af1f7 --- runtime/quick_exception_handler.cc | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'runtime/quick_exception_handler.cc') diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 9d5ce9f385..60defbaaa3 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -40,7 +40,7 @@ QuickExceptionHandler::QuickExceptionHandler(Thread* self, bool is_deoptimizatio handler_dex_pc_(0), clear_exception_(false), handler_frame_depth_(kInvalidFrameDepth) { } -// Finds catch handler or prepares for deoptimization. +// Finds catch handler. class CatchBlockStackVisitor FINAL : public StackVisitor { public: CatchBlockStackVisitor(Thread* self, Context* context, Handle* exception, @@ -125,7 +125,7 @@ void QuickExceptionHandler::FindCatch(mirror::Throwable* exception) { StackHandleScope<1> hs(self_); Handle exception_ref(hs.NewHandle(exception)); - // Walk the stack to find catch handler or prepare for deoptimization. + // Walk the stack to find catch handler. CatchBlockStackVisitor visitor(self_, context_, &exception_ref, this); visitor.WalkStack(true); @@ -146,16 +146,6 @@ void QuickExceptionHandler::FindCatch(mirror::Throwable* exception) { // Put exception back in root set with clear throw location. self_->SetException(exception_ref.Get()); } - // The debugger may suspend this thread and walk its stack. Let's do this before popping - // instrumentation frames. - instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); - if (instrumentation->HasExceptionCaughtListeners() - && self_->IsExceptionThrownByCurrentMethod(exception)) { - instrumentation->ExceptionCaughtEvent(self_, exception_ref.Get()); - // Instrumentation may have been updated. - method_tracing_active_ = is_deoptimization_ || - Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled(); - } } // Prepares deoptimization. @@ -189,6 +179,12 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { // Ignore callee save method. DCHECK(method->IsCalleeSaveMethod()); return true; + } else if (method->IsNative()) { + // If we return from JNI with a pending exception and want to deoptimize, we need to skip + // the native method. + // The top method is a runtime method, the native method comes next. + CHECK_EQ(GetFrameDepth(), 1U); + return true; } else { return HandleDeoptimization(method); } @@ -201,7 +197,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { bool HandleDeoptimization(ArtMethod* m) SHARED_REQUIRES(Locks::mutator_lock_) { const DexFile::CodeItem* code_item = m->GetCodeItem(); - CHECK(code_item != nullptr); + CHECK(code_item != nullptr) << "No code item for " << PrettyMethod(m); uint16_t num_regs = code_item->registers_size_; uint32_t dex_pc = GetDexPc(); StackHandleScope<2> hs(self_); // Dex cache, class loader and method. -- cgit v1.2.3-59-g8ed1b