diff options
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r-- | runtime/stack.cc | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc index c33d1ab..ab3bd85 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -16,6 +16,7 @@ #include "stack.h" +#include "base/hex_dump.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object.h" @@ -23,6 +24,7 @@ #include "mirror/object_array-inl.h" #include "object_utils.h" #include "runtime.h" +#include "thread.h" #include "thread_list.h" #include "throw_location.h" #include "verify_object-inl.h" @@ -30,6 +32,14 @@ namespace art { +// Define a piece of memory, the address of which can be used as a marker +// for the gap in the stack added during stack overflow handling. +static uint32_t stack_overflow_object; + +// The stack overflow gap marker is simply a valid unique address. +void* stack_overflow_gap_marker = &stack_overflow_object; + + mirror::Object* ShadowFrame::GetThisObject() const { mirror::ArtMethod* m = GetMethod(); if (m->IsStatic()) { @@ -294,20 +304,56 @@ void StackVisitor::WalkStack(bool include_transitions) { CHECK_EQ(cur_depth_, 0U); bool exit_stubs_installed = Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled(); uint32_t instrumentation_stack_depth = 0; + + bool kDebugStackWalk = false; + bool kDebugStackWalkVeryVerbose = false; // The name says it all. + + if (kDebugStackWalk) { + LOG(INFO) << "walking stack"; + } for (const ManagedStack* current_fragment = thread_->GetManagedStack(); current_fragment != NULL; current_fragment = current_fragment->GetLink()) { cur_shadow_frame_ = current_fragment->GetTopShadowFrame(); cur_quick_frame_ = current_fragment->GetTopQuickFrame(); cur_quick_frame_pc_ = current_fragment->GetTopQuickFramePc(); + if (kDebugStackWalkVeryVerbose) { + LOG(INFO) << "cur_quick_frame: " << cur_quick_frame_; + LOG(INFO) << "cur_quick_frame_pc: " << std::hex << cur_quick_frame_pc_; + } + if (cur_quick_frame_ != NULL) { // Handle quick stack frames. // Can't be both a shadow and a quick fragment. DCHECK(current_fragment->GetTopShadowFrame() == NULL); mirror::ArtMethod* method = *cur_quick_frame_; while (method != NULL) { - SanityCheckFrame(); - bool should_continue = VisitFrame(); - if (UNLIKELY(!should_continue)) { - return; + // Check for a stack overflow gap marker. + if (method == reinterpret_cast<mirror::ArtMethod*>(stack_overflow_gap_marker)) { + // Marker for a stack overflow. This is followed by the offset from the + // current SP to the next frame. There is a gap in the stack here. Jump + // the gap silently. + // Caveat coder: the layout of the overflow marker depends on the architecture. + // The first element is address sized (8 bytes on a 64 bit machine). The second + // element is 32 bits. So be careful with those address calculations. + + // Get the address of the offset, just beyond the marker pointer. + byte* gapsizeaddr = reinterpret_cast<byte*>(cur_quick_frame_) + sizeof(uintptr_t); + uint32_t gap = *reinterpret_cast<uint32_t*>(gapsizeaddr); + CHECK_GT(gap, Thread::kStackOverflowProtectedSize); + mirror::ArtMethod** next_frame = reinterpret_cast<mirror::ArtMethod**>( + reinterpret_cast<byte*>(gapsizeaddr) + gap); + if (kDebugStackWalk) { + LOG(INFO) << "stack overflow marker hit, gap: " << gap << ", next_frame: " << + next_frame; + } + cur_quick_frame_ = next_frame; + method = *next_frame; + CHECK(method != nullptr); + } else { + SanityCheckFrame(); + bool should_continue = VisitFrame(); + if (UNLIKELY(!should_continue)) { + return; + } } if (context_ != NULL) { context_->FillCalleeSaves(*this); @@ -317,6 +363,9 @@ void StackVisitor::WalkStack(bool include_transitions) { size_t return_pc_offset = method->GetReturnPcOffsetInBytes(); byte* return_pc_addr = reinterpret_cast<byte*>(cur_quick_frame_) + return_pc_offset; uintptr_t return_pc = *reinterpret_cast<uintptr_t*>(return_pc_addr); + if (kDebugStackWalkVeryVerbose) { + LOG(INFO) << "frame size: " << frame_size << ", return_pc: " << std::hex << return_pc; + } if (UNLIKELY(exit_stubs_installed)) { // While profiling, the return pc is restored from the side stack, except when walking // the stack for an exception where the side stack will be unwound in VisitFrame. @@ -349,6 +398,10 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_quick_frame_ = reinterpret_cast<mirror::ArtMethod**>(next_frame); cur_depth_++; method = *cur_quick_frame_; + if (kDebugStackWalkVeryVerbose) { + LOG(INFO) << "new cur_quick_frame_: " << cur_quick_frame_; + LOG(INFO) << "new cur_quick_frame_pc_: " << std::hex << cur_quick_frame_pc_; + } } } else if (cur_shadow_frame_ != NULL) { do { |