summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/Android.mk3
-rw-r--r--runtime/catch_block_stack_visitor.cc70
-rw-r--r--runtime/catch_block_stack_visitor.h36
-rw-r--r--runtime/deoptimize_stack_visitor.cc87
-rw-r--r--runtime/deoptimize_stack_visitor.h53
-rw-r--r--runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc2
-rw-r--r--runtime/mirror/art_method.cc6
-rw-r--r--runtime/quick_exception_handler.cc (renamed from runtime/catch_finder.cc)66
-rw-r--r--runtime/quick_exception_handler.h (renamed from runtime/catch_finder.h)37
-rw-r--r--runtime/thread.cc18
-rw-r--r--runtime/thread.h5
11 files changed, 248 insertions, 135 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d433fd5..bc971a9 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -36,10 +36,10 @@ LIBART_COMMON_SRC_FILES := \
base/unix_file/string_file.cc \
check_jni.cc \
catch_block_stack_visitor.cc \
- catch_finder.cc \
class_linker.cc \
common_throws.cc \
debugger.cc \
+ deoptimize_stack_visitor.cc \
dex_file.cc \
dex_file_verifier.cc \
dex_instruction.cc \
@@ -129,6 +129,7 @@ LIBART_COMMON_SRC_FILES := \
os_linux.cc \
parsed_options.cc \
primitive.cc \
+ quick_exception_handler.cc \
quick/inline_method_analyser.cc \
reference_table.cc \
reflection.cc \
diff --git a/runtime/catch_block_stack_visitor.cc b/runtime/catch_block_stack_visitor.cc
index 410fff9..8d10a97 100644
--- a/runtime/catch_block_stack_visitor.cc
+++ b/runtime/catch_block_stack_visitor.cc
@@ -17,27 +17,26 @@
#include "catch_block_stack_visitor.h"
#include "dex_instruction.h"
-#include "catch_finder.h"
+#include "mirror/art_method-inl.h"
+#include "quick_exception_handler.h"
#include "sirt_ref.h"
#include "verifier/method_verifier.h"
namespace art {
bool CatchBlockStackVisitor::VisitFrame() {
- catch_finder_->SetHandlerFrameId(GetFrameId());
+ exception_handler_->SetHandlerFrameId(GetFrameId());
mirror::ArtMethod* method = GetMethod();
if (method == nullptr) {
// This is the upcall, we remember the frame and last pc so that we may long jump to them.
- catch_finder_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
- catch_finder_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+ exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
+ exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
return false; // End stack walk.
} else {
if (method->IsRuntimeMethod()) {
// Ignore callee save method.
DCHECK(method->IsCalleeSaveMethod());
return true;
- } else if (is_deoptimization_) {
- return HandleDeoptimization(method);
} else {
return HandleTryItems(method);
}
@@ -46,68 +45,21 @@ bool CatchBlockStackVisitor::VisitFrame() {
bool CatchBlockStackVisitor::HandleTryItems(mirror::ArtMethod* method) {
uint32_t dex_pc = DexFile::kDexNoIndex;
- if (method->IsNative()) {
- ++native_method_count_;
- } else {
+ if (!method->IsNative()) {
dex_pc = GetDexPc();
}
if (dex_pc != DexFile::kDexNoIndex) {
bool clear_exception = false;
- SirtRef<mirror::Class> sirt_method_to_find(Thread::Current(), to_find_);
- uint32_t found_dex_pc = method->FindCatchBlock(sirt_method_to_find, dex_pc, &clear_exception);
- to_find_ = sirt_method_to_find.get();
- catch_finder_->SetClearException(clear_exception);
+ uint32_t found_dex_pc = method->FindCatchBlock(to_find_, dex_pc, &clear_exception);
+ exception_handler_->SetClearException(clear_exception);
if (found_dex_pc != DexFile::kDexNoIndex) {
- catch_finder_->SetHandlerDexPc(found_dex_pc);
- catch_finder_->SetHandlerQuickFramePc(method->ToNativePc(found_dex_pc));
- catch_finder_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+ exception_handler_->SetHandlerDexPc(found_dex_pc);
+ exception_handler_->SetHandlerQuickFramePc(method->ToNativePc(found_dex_pc));
+ exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
return false; // End stack walk.
}
}
return true; // Continue stack walk.
}
-bool CatchBlockStackVisitor::HandleDeoptimization(mirror::ArtMethod* m) {
- MethodHelper mh(m);
- const DexFile::CodeItem* code_item = mh.GetCodeItem();
- CHECK(code_item != nullptr);
- uint16_t num_regs = code_item->registers_size_;
- uint32_t dex_pc = GetDexPc();
- const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
- uint32_t new_dex_pc = dex_pc + inst->SizeInCodeUnits();
- ShadowFrame* new_frame = ShadowFrame::Create(num_regs, nullptr, m, new_dex_pc);
- SirtRef<mirror::DexCache> dex_cache(self_, mh.GetDexCache());
- SirtRef<mirror::ClassLoader> class_loader(self_, mh.GetClassLoader());
- verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader,
- &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m,
- m->GetAccessFlags(), false, true);
- verifier.Verify();
- std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
- for (uint16_t reg = 0; reg < num_regs; ++reg) {
- VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
- switch (kind) {
- case kUndefined:
- new_frame->SetVReg(reg, 0xEBADDE09);
- break;
- case kConstant:
- new_frame->SetVReg(reg, kinds.at((reg * 2) + 1));
- break;
- case kReferenceVReg:
- new_frame->SetVRegReference(reg,
- reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kind)));
- break;
- default:
- new_frame->SetVReg(reg, GetVReg(m, reg, kind));
- break;
- }
- }
- if (prev_shadow_frame_ != nullptr) {
- prev_shadow_frame_->SetLink(new_frame);
- } else {
- catch_finder_->SetTopShadowFrame(new_frame);
- }
- prev_shadow_frame_ = new_frame;
- return true;
-}
-
} // namespace art
diff --git a/runtime/catch_block_stack_visitor.h b/runtime/catch_block_stack_visitor.h
index ce67e27..6f0fe11 100644
--- a/runtime/catch_block_stack_visitor.h
+++ b/runtime/catch_block_stack_visitor.h
@@ -17,39 +17,39 @@
#ifndef ART_RUNTIME_CATCH_BLOCK_STACK_VISITOR_H_
#define ART_RUNTIME_CATCH_BLOCK_STACK_VISITOR_H_
-#include "mirror/throwable.h"
-#include "thread.h"
+#include "mirror/object-inl.h"
+#include "stack.h"
+#include "sirt_ref-inl.h"
namespace art {
-class CatchFinder;
+
+namespace mirror {
+class Throwable;
+} // namespace mirror
+class Context;
+class QuickExceptionHandler;
+class Thread;
class ThrowLocation;
// Finds catch handler or prepares deoptimization.
-class CatchBlockStackVisitor : public StackVisitor {
+class CatchBlockStackVisitor FINAL : public StackVisitor {
public:
- CatchBlockStackVisitor(Thread* self, Context* context, mirror::Throwable* exception,
- bool is_deoptimization, CatchFinder* catch_finder)
+ CatchBlockStackVisitor(Thread* self, Context* context, SirtRef<mirror::Throwable>& exception,
+ QuickExceptionHandler* exception_handler)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : StackVisitor(self, context),
- self_(self), is_deoptimization_(is_deoptimization),
- to_find_(is_deoptimization ? nullptr : exception->GetClass()),
- catch_finder_(catch_finder), native_method_count_(0), prev_shadow_frame_(nullptr) {
+ : StackVisitor(self, context), self_(self), to_find_(self, exception->GetClass()),
+ exception_handler_(exception_handler) {
}
- bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
bool HandleTryItems(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Thread* const self_;
- const bool is_deoptimization_;
// The type of the exception catch block to find.
- mirror::Class* to_find_;
- CatchFinder* const catch_finder_;
- // Number of native methods passed in crawl (equates to number of SIRTs to pop)
- uint32_t native_method_count_;
- ShadowFrame* prev_shadow_frame_;
+ SirtRef<mirror::Class> to_find_;
+ QuickExceptionHandler* const exception_handler_;
DISALLOW_COPY_AND_ASSIGN(CatchBlockStackVisitor);
};
diff --git a/runtime/deoptimize_stack_visitor.cc b/runtime/deoptimize_stack_visitor.cc
new file mode 100644
index 0000000..f2eaf00
--- /dev/null
+++ b/runtime/deoptimize_stack_visitor.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "deoptimize_stack_visitor.h"
+
+#include "mirror/art_method-inl.h"
+#include "object_utils.h"
+#include "quick_exception_handler.h"
+#include "sirt_ref-inl.h"
+#include "verifier/method_verifier.h"
+
+namespace art {
+
+bool DeoptimizeStackVisitor::VisitFrame() {
+ exception_handler_->SetHandlerFrameId(GetFrameId());
+ mirror::ArtMethod* method = GetMethod();
+ if (method == nullptr) {
+ // This is the upcall, we remember the frame and last pc so that we may long jump to them.
+ exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
+ exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+ return false; // End stack walk.
+ } else if (method->IsRuntimeMethod()) {
+ // Ignore callee save method.
+ DCHECK(method->IsCalleeSaveMethod());
+ return true;
+ } else {
+ return HandleDeoptimization(method);
+ }
+}
+
+bool DeoptimizeStackVisitor::HandleDeoptimization(mirror::ArtMethod* m) {
+ MethodHelper mh(m);
+ const DexFile::CodeItem* code_item = mh.GetCodeItem();
+ CHECK(code_item != nullptr);
+ uint16_t num_regs = code_item->registers_size_;
+ uint32_t dex_pc = GetDexPc();
+ const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
+ uint32_t new_dex_pc = dex_pc + inst->SizeInCodeUnits();
+ ShadowFrame* new_frame = ShadowFrame::Create(num_regs, nullptr, m, new_dex_pc);
+ SirtRef<mirror::DexCache> dex_cache(self_, mh.GetDexCache());
+ SirtRef<mirror::ClassLoader> class_loader(self_, mh.GetClassLoader());
+ verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader,
+ &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m,
+ m->GetAccessFlags(), false, true);
+ verifier.Verify();
+ std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
+ for (uint16_t reg = 0; reg < num_regs; ++reg) {
+ VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
+ switch (kind) {
+ case kUndefined:
+ new_frame->SetVReg(reg, 0xEBADDE09);
+ break;
+ case kConstant:
+ new_frame->SetVReg(reg, kinds.at((reg * 2) + 1));
+ break;
+ case kReferenceVReg:
+ new_frame->SetVRegReference(reg,
+ reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kind)));
+ break;
+ default:
+ new_frame->SetVReg(reg, GetVReg(m, reg, kind));
+ break;
+ }
+ }
+ if (prev_shadow_frame_ != nullptr) {
+ prev_shadow_frame_->SetLink(new_frame);
+ } else {
+ exception_handler_->SetTopShadowFrame(new_frame);
+ }
+ prev_shadow_frame_ = new_frame;
+ return true;
+}
+
+} // namespace art
diff --git a/runtime/deoptimize_stack_visitor.h b/runtime/deoptimize_stack_visitor.h
new file mode 100644
index 0000000..c898e7d
--- /dev/null
+++ b/runtime/deoptimize_stack_visitor.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_DEOPTIMIZE_STACK_VISITOR_H_
+#define ART_RUNTIME_DEOPTIMIZE_STACK_VISITOR_H_
+
+#include "base/mutex.h"
+#include "stack.h"
+
+namespace art {
+
+namespace mirror {
+class ArtMethod;
+} // namespace mirror
+class QuickExceptionHandler;
+class Thread;
+
+// Prepares deoptimization.
+class DeoptimizeStackVisitor FINAL : public StackVisitor {
+ public:
+ DeoptimizeStackVisitor(Thread* self, Context* context, QuickExceptionHandler* exception_handler)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : StackVisitor(self, context), self_(self), exception_handler_(exception_handler),
+ prev_shadow_frame_(nullptr) {
+ }
+
+ bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ Thread* const self_;
+ QuickExceptionHandler* const exception_handler_;
+ ShadowFrame* prev_shadow_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeoptimizeStackVisitor);
+};
+
+} // namespace art
+#endif // ART_RUNTIME_DEOPTIMIZE_STACK_VISITOR_H_
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 51c647a..6448045 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -31,7 +31,7 @@ namespace art {
extern "C" void artDeoptimize(Thread* self, mirror::ArtMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
- self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
+ self->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
self->QuickDeliverException();
}
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f3303a8..726004b 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -315,13 +315,13 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
} else {
(*art_portable_invoke_stub)(this, args, args_size, self, result, shorty[0]);
}
- if (UNLIKELY(reinterpret_cast<intptr_t>(self->GetException(NULL)) == -1)) {
- // Unusual case where we were running LLVM generated code and an
+ if (UNLIKELY(self->GetException(nullptr) == Thread::GetDeoptimizationException())) {
+ // Unusual case where we were running generated code and an
// exception was thrown to force the activations to be removed from the
// stack. Continue execution in the interpreter.
self->ClearException();
ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(result);
- self->SetTopOfStack(NULL, 0);
+ self->SetTopOfStack(nullptr, 0);
self->SetTopOfShadowStack(shadow_frame);
interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
}
diff --git a/runtime/catch_finder.cc b/runtime/quick_exception_handler.cc
index f0293d7..d5844b6 100644
--- a/runtime/catch_finder.cc
+++ b/runtime/quick_exception_handler.cc
@@ -14,37 +14,37 @@
* limitations under the License.
*/
-#include "catch_finder.h"
+#include "quick_exception_handler.h"
+
#include "catch_block_stack_visitor.h"
+#include "deoptimize_stack_visitor.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "sirt_ref-inl.h"
namespace art {
-CatchFinder::CatchFinder(Thread* self, const ThrowLocation& throw_location,
- mirror::Throwable* exception, bool is_deoptimization)
- : self_(self), context_(self->GetLongJumpContext()),
- exception_(exception), is_deoptimization_(is_deoptimization), throw_location_(throw_location),
+QuickExceptionHandler::QuickExceptionHandler(Thread* self, bool is_deoptimization)
+ : self_(self), context_(self->GetLongJumpContext()), is_deoptimization_(is_deoptimization),
method_tracing_active_(is_deoptimization ||
Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()),
- handler_quick_frame_(nullptr), handler_quick_frame_pc_(0),
- handler_dex_pc_(0), clear_exception_(false), top_shadow_frame_(nullptr),
- handler_frame_id_(kInvalidFrameId) {
- // Exception not in root sets, can't allow GC.
- last_no_assert_suspension_cause_ = self->StartAssertNoThreadSuspension("Finding catch block");
+ handler_quick_frame_(nullptr), handler_quick_frame_pc_(0), handler_dex_pc_(0),
+ clear_exception_(false), top_shadow_frame_(nullptr), handler_frame_id_(kInvalidFrameId) {
}
-void CatchFinder::FindCatch() {
+void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
+ mirror::Throwable* exception) {
+ DCHECK(!is_deoptimization_);
+ SirtRef<mirror::Throwable> exception_ref(self_, exception);
+
// Walk the stack to find catch handler or prepare for deoptimization.
- CatchBlockStackVisitor visitor(self_, context_, exception_, is_deoptimization_, this);
+ CatchBlockStackVisitor visitor(self_, context_, exception_ref, this);
visitor.WalkStack(true);
mirror::ArtMethod* catch_method = *handler_quick_frame_;
- if (catch_method == nullptr) {
- if (kDebugExceptionDelivery) {
+ if (kDebugExceptionDelivery) {
+ if (catch_method == nullptr) {
LOG(INFO) << "Handler is upcall";
- }
- } else {
- CHECK(!is_deoptimization_);
- if (kDebugExceptionDelivery) {
+ } else {
const DexFile& dex_file = *catch_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
int line_number = dex_file.GetLineNumFromPC(catch_method, handler_dex_pc_);
LOG(INFO) << "Handler: " << PrettyMethod(catch_method) << " (line: " << line_number << ")";
@@ -55,17 +55,23 @@ void CatchFinder::FindCatch() {
DCHECK(!self_->IsExceptionPending());
} else {
// Put exception back in root set with clear throw location.
- self_->SetException(ThrowLocation(), exception_);
- }
- self_->EndAssertNoThreadSuspension(last_no_assert_suspension_cause_);
- // Do instrumentation events after allowing thread suspension again.
- if (!is_deoptimization_) {
- // 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_, catch_method, handler_dex_pc_,
- exception_);
+ self_->SetException(ThrowLocation(), 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();
+ instrumentation->ExceptionCaughtEvent(self_, throw_location, catch_method, handler_dex_pc_,
+ exception_ref.get());
+}
+
+void QuickExceptionHandler::DeoptimizeStack() {
+ DCHECK(is_deoptimization_);
+
+ DeoptimizeStackVisitor visitor(self_, context_, this);
+ visitor.WalkStack(true);
+
+ // Restore deoptimization exception
+ self_->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
}
// Unwinds all instrumentation stack frame prior to catch handler or upcall.
@@ -105,7 +111,7 @@ class InstrumentationStackVisitor : public StackVisitor {
DISALLOW_COPY_AND_ASSIGN(InstrumentationStackVisitor);
};
-void CatchFinder::UpdateInstrumentationStack() {
+void QuickExceptionHandler::UpdateInstrumentationStack() {
if (method_tracing_active_) {
InstrumentationStackVisitor visitor(self_, is_deoptimization_, handler_frame_id_);
visitor.WalkStack(true);
@@ -118,7 +124,7 @@ void CatchFinder::UpdateInstrumentationStack() {
}
}
-void CatchFinder::DoLongJump() {
+void QuickExceptionHandler::DoLongJump() {
if (is_deoptimization_) {
// TODO: proper return value.
self_->SetDeoptimizationShadowFrame(top_shadow_frame_);
diff --git a/runtime/catch_finder.h b/runtime/quick_exception_handler.h
index ebbafe2..d06ce7c 100644
--- a/runtime/catch_finder.h
+++ b/runtime/quick_exception_handler.h
@@ -14,29 +14,39 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_CATCH_FINDER_H_
-#define ART_RUNTIME_CATCH_FINDER_H_
+#ifndef ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
+#define ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
-#include "mirror/art_method-inl.h"
-#include "thread.h"
+#include "base/logging.h"
+#include "base/mutex.h"
namespace art {
+namespace mirror {
+class ArtMethod;
+class Throwable;
+} // namespace mirror
+class Context;
+class Thread;
+class ThrowLocation;
+class ShadowFrame;
+
static constexpr bool kDebugExceptionDelivery = false;
static constexpr size_t kInvalidFrameId = 0xffffffff;
// Manages exception delivery for Quick backend. Not used by Portable backend.
-class CatchFinder {
+class QuickExceptionHandler {
public:
- CatchFinder(Thread* self, const ThrowLocation& throw_location, mirror::Throwable* exception,
- bool is_deoptimization)
+ QuickExceptionHandler(Thread* self, bool is_deoptimization)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ~CatchFinder() {
+ ~QuickExceptionHandler() {
LOG(FATAL) << "UNREACHABLE"; // Expected to take long jump.
}
- void FindCatch() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FindCatch(const ThrowLocation& throw_location, mirror::Throwable* exception)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void DeoptimizeStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void UpdateInstrumentationStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -67,14 +77,9 @@ class CatchFinder {
private:
Thread* const self_;
Context* const context_;
- mirror::Throwable* const exception_;
const bool is_deoptimization_;
- // Location of the throw.
- const ThrowLocation& throw_location_;
// Is method tracing active?
const bool method_tracing_active_;
- // Support for nesting no thread suspension checks.
- const char* last_no_assert_suspension_cause_;
// Quick frame with found handler or last frame if no handler found.
mirror::ArtMethod** handler_quick_frame_;
// PC to branch to for the handler.
@@ -88,8 +93,8 @@ class CatchFinder {
// Frame id of the catch handler or the upcall.
size_t handler_frame_id_;
- DISALLOW_COPY_AND_ASSIGN(CatchFinder);
+ DISALLOW_COPY_AND_ASSIGN(QuickExceptionHandler);
};
} // namespace art
-#endif // ART_RUNTIME_CATCH_FINDER_H_
+#endif // ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 998579d..095404f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -32,7 +32,6 @@
#include "arch/context.h"
#include "base/mutex.h"
-#include "catch_finder.h"
#include "class_linker.h"
#include "class_linker-inl.h"
#include "cutils/atomic.h"
@@ -54,6 +53,7 @@
#include "mirror/stack_trace_element.h"
#include "monitor.h"
#include "object_utils.h"
+#include "quick_exception_handler.h"
#include "reflection.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
@@ -1841,7 +1841,7 @@ void Thread::QuickDeliverException() {
// Don't leave exception visible while we try to find the handler, which may cause class
// resolution.
ClearException();
- bool is_deoptimization = (exception == reinterpret_cast<mirror::Throwable*>(-1));
+ bool is_deoptimization = (exception == GetDeoptimizationException());
if (kDebugExceptionDelivery) {
if (!is_deoptimization) {
mirror::String* msg = exception->GetDetailMessage();
@@ -1852,10 +1852,14 @@ void Thread::QuickDeliverException() {
DumpStack(LOG(INFO) << "Deoptimizing: ");
}
}
- CatchFinder catch_finder(this, throw_location, exception, is_deoptimization);
- catch_finder.FindCatch();
- catch_finder.UpdateInstrumentationStack();
- catch_finder.DoLongJump();
+ QuickExceptionHandler exception_handler(this, is_deoptimization);
+ if (is_deoptimization) {
+ exception_handler.DeoptimizeStack();
+ } else {
+ exception_handler.FindCatch(throw_location, exception);
+ }
+ exception_handler.UpdateInstrumentationStack();
+ exception_handler.DoLongJump();
LOG(FATAL) << "UNREACHABLE";
}
@@ -2060,7 +2064,7 @@ void Thread::VisitRoots(RootCallback* visitor, void* arg) {
if (tlsPtr_.opeer != nullptr) {
visitor(&tlsPtr_.opeer, arg, thread_id, kRootThreadObject);
}
- if (tlsPtr_.exception != nullptr) {
+ if (tlsPtr_.exception != nullptr && tlsPtr_.exception != GetDeoptimizationException()) {
visitor(reinterpret_cast<mirror::Object**>(&tlsPtr_.exception), arg, thread_id, kRootNativeStack);
}
tlsPtr_.throw_location.VisitRoots(visitor, arg);
diff --git a/runtime/thread.h b/runtime/thread.h
index d25bbe9..e5e4cae 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -686,6 +686,11 @@ class Thread {
return tlsPtr_.single_step_control;
}
+ // Returns the fake exception used to activate deoptimization.
+ static mirror::Throwable* GetDeoptimizationException() {
+ return reinterpret_cast<mirror::Throwable*>(-1);
+ }
+
void SetDeoptimizationShadowFrame(ShadowFrame* sf);
void SetDeoptimizationReturnValue(const JValue& ret_val);