Revert "Revert^2 "ART: Add StackVisitor accepting a lambda""
This reverts commit 3d477f3a3eea757a49ca621cc579f711f22fccdd.
Bug: 115837065
Reason for revert: Breaks jdwp tests.
Change-Id: I09249331798970751a20c6b41675c3efef72adfb
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index d4e3d54..afdfefa 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -154,36 +154,46 @@
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 @@
// 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 @@
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 @@
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