diff options
author | Andreas Gampe <agampe@google.com> | 2018-11-16 00:47:49 +0000 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2018-11-16 00:47:49 +0000 |
commit | 8248490f24e8582ce2ead8cd878d8a2c38310a48 (patch) | |
tree | f542af6560561526fc413e361e3323a615b5429c /runtime/quick_exception_handler.cc | |
parent | 36f8d22c672498753b9edc66ba11acc9816b2a17 (diff) |
Revert "ART: Add StackVisitor accepting a lambda"
This reverts commit 36f8d22c672498753b9edc66ba11acc9816b2a17.
Reason for revert: Seems to be breaking test 687
Bug: 115837065
Change-Id: I83bb1a9d76cc701c3d582778e5047ebd5dab5d29
Test: TreeHugger
Diffstat (limited to 'runtime/quick_exception_handler.cc')
-rw-r--r-- | runtime/quick_exception_handler.cc | 159 |
1 files changed, 92 insertions, 67 deletions
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index d4e3d54a99..afdfefaffa 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -154,36 +154,46 @@ class CatchBlockStackVisitor final : public StackVisitor { DISALLOW_COPY_AND_ASSIGN(CatchBlockStackVisitor); }; -static size_t GetInstrumentationFramesToPop(Thread* self, size_t frame_depth) - REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK_NE(frame_depth, kInvalidFrameDepth); - size_t instrumentation_frames_to_pop = 0; - StackVisitor::WalkStack( - [&](art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) { - size_t current_frame_depth = stack_visitor->GetFrameDepth(); - if (current_frame_depth < frame_depth) { - CHECK(stack_visitor->GetMethod() != nullptr); - if (UNLIKELY(reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == - stack_visitor->GetReturnPc())) { - if (!stack_visitor->IsInInlinedFrame()) { - // We do not count inlined frames, because we do not instrument them. The reason we - // include them in the stack walking is the check against `frame_depth_`, which is - // given to us by a visitor that visits inlined frames. - ++instrumentation_frames_to_pop; - } - } - return true; +// Counts instrumentation stack frame prior to catch handler or upcall. +class InstrumentationStackVisitor : public StackVisitor { + public: + InstrumentationStackVisitor(Thread* self, size_t frame_depth) + REQUIRES_SHARED(Locks::mutator_lock_) + : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), + frame_depth_(frame_depth), + instrumentation_frames_to_pop_(0) { + CHECK_NE(frame_depth_, kInvalidFrameDepth); + } + + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { + size_t current_frame_depth = GetFrameDepth(); + if (current_frame_depth < frame_depth_) { + CHECK(GetMethod() != nullptr); + if (UNLIKELY(reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == GetReturnPc())) { + if (!IsInInlinedFrame()) { + // We do not count inlined frames, because we do not instrument them. The reason we + // include them in the stack walking is the check against `frame_depth_`, which is + // given to us by a visitor that visits inlined frames. + ++instrumentation_frames_to_pop_; } - // We reached the frame of the catch handler or the upcall. - return false; - }, - self, - /* context= */ nullptr, - art::StackVisitor::StackWalkKind::kIncludeInlinedFrames, - /* check_suspended */ true, - /* include_transitions */ true); - return instrumentation_frames_to_pop; -} + } + return true; + } else { + // We reached the frame of the catch handler or the upcall. + return false; + } + } + + size_t GetInstrumentationFramesToPop() const { + return instrumentation_frames_to_pop_; + } + + private: + const size_t frame_depth_; + size_t instrumentation_frames_to_pop_; + + DISALLOW_COPY_AND_ASSIGN(InstrumentationStackVisitor); +}; // Finds the appropriate exception catch after calling all method exit instrumentation functions. // Note that this might change the exception being thrown. @@ -219,8 +229,9 @@ void QuickExceptionHandler::FindCatch(ObjPtr<mirror::Throwable> exception) { // Figure out how many of those frames have instrumentation we need to remove (Should be the // exact same as number of new_pop_count if there aren't inlined frames). - size_t instrumentation_frames_to_pop = - GetInstrumentationFramesToPop(self_, handler_frame_depth_); + InstrumentationStackVisitor instrumentation_visitor(self_, handler_frame_depth_); + instrumentation_visitor.WalkStack(true); + size_t instrumentation_frames_to_pop = instrumentation_visitor.GetInstrumentationFramesToPop(); if (kDebugExceptionDelivery) { if (*handler_quick_frame_ == nullptr) { @@ -636,8 +647,10 @@ uintptr_t QuickExceptionHandler::UpdateInstrumentationStack() { DCHECK(is_deoptimization_) << "Non-deoptimization handlers should use FindCatch"; uintptr_t return_pc = 0; if (method_tracing_active_) { - size_t instrumentation_frames_to_pop = - GetInstrumentationFramesToPop(self_, handler_frame_depth_); + InstrumentationStackVisitor visitor(self_, handler_frame_depth_); + visitor.WalkStack(true); + + size_t instrumentation_frames_to_pop = visitor.GetInstrumentationFramesToPop(); instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); return_pc = instrumentation->PopFramesForDeoptimization(self_, instrumentation_frames_to_pop); } @@ -658,41 +671,53 @@ void QuickExceptionHandler::DoLongJump(bool smash_caller_saves) { UNREACHABLE(); } +// Prints out methods with their type of frame. +class DumpFramesWithTypeStackVisitor final : public StackVisitor { + public: + explicit DumpFramesWithTypeStackVisitor(Thread* self, bool show_details = false) + REQUIRES_SHARED(Locks::mutator_lock_) + : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), + show_details_(show_details) {} + + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { + ArtMethod* method = GetMethod(); + if (show_details_) { + LOG(INFO) << "|> pc = " << std::hex << GetCurrentQuickFramePc(); + LOG(INFO) << "|> addr = " << std::hex << reinterpret_cast<uintptr_t>(GetCurrentQuickFrame()); + if (GetCurrentQuickFrame() != nullptr && method != nullptr) { + LOG(INFO) << "|> ret = " << std::hex << GetReturnPc(); + } + } + if (method == nullptr) { + // Transition, do go on, we want to unwind over bridges, all the way. + if (show_details_) { + LOG(INFO) << "N <transition>"; + } + return true; + } else if (method->IsRuntimeMethod()) { + if (show_details_) { + LOG(INFO) << "R " << method->PrettyMethod(true); + } + return true; + } else { + bool is_shadow = GetCurrentShadowFrame() != nullptr; + LOG(INFO) << (is_shadow ? "S" : "Q") + << ((!is_shadow && IsInInlinedFrame()) ? "i" : " ") + << " " + << method->PrettyMethod(true); + return true; // Go on. + } + } + + private: + bool show_details_; + + DISALLOW_COPY_AND_ASSIGN(DumpFramesWithTypeStackVisitor); +}; + void QuickExceptionHandler::DumpFramesWithType(Thread* self, bool details) { - StackVisitor::WalkStack( - [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) { - ArtMethod* method = stack_visitor->GetMethod(); - if (details) { - LOG(INFO) << "|> pc = " << std::hex << stack_visitor->GetCurrentQuickFramePc(); - LOG(INFO) << "|> addr = " << std::hex - << reinterpret_cast<uintptr_t>(stack_visitor->GetCurrentQuickFrame()); - if (stack_visitor->GetCurrentQuickFrame() != nullptr && method != nullptr) { - LOG(INFO) << "|> ret = " << std::hex << stack_visitor->GetReturnPc(); - } - } - if (method == nullptr) { - // Transition, do go on, we want to unwind over bridges, all the way. - if (details) { - LOG(INFO) << "N <transition>"; - } - return true; - } else if (method->IsRuntimeMethod()) { - if (details) { - LOG(INFO) << "R " << method->PrettyMethod(true); - } - return true; - } else { - bool is_shadow = stack_visitor->GetCurrentShadowFrame() != nullptr; - LOG(INFO) << (is_shadow ? "S" : "Q") - << ((!is_shadow && stack_visitor->IsInInlinedFrame()) ? "i" : " ") - << " " - << method->PrettyMethod(true); - return true; // Go on. - } - }, - self, - /* context= */ nullptr, - art::StackVisitor::StackWalkKind::kIncludeInlinedFrames); + DumpFramesWithTypeStackVisitor visitor(self, details); + visitor.WalkStack(true); } } // namespace art |