diff options
-rw-r--r-- | runtime/Android.mk | 3 | ||||
-rw-r--r-- | runtime/catch_block_stack_visitor.cc | 70 | ||||
-rw-r--r-- | runtime/catch_block_stack_visitor.h | 36 | ||||
-rw-r--r-- | runtime/deoptimize_stack_visitor.cc | 87 | ||||
-rw-r--r-- | runtime/deoptimize_stack_visitor.h | 53 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 6 | ||||
-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.cc | 18 | ||||
-rw-r--r-- | runtime/thread.h | 5 |
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); |