diff options
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r-- | runtime/stack.cc | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc index e49bc1d78f..800acaa320 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -19,6 +19,7 @@ #include "arch/context.h" #include "base/hex_dump.h" #include "entrypoints/runtime_asm_entrypoints.h" +#include "gc_map.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object.h" @@ -84,16 +85,20 @@ bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_fr return false; } -StackVisitor::StackVisitor(Thread* thread, Context* context) - : thread_(thread), cur_shadow_frame_(nullptr), - cur_quick_frame_(nullptr), cur_quick_frame_pc_(0), num_frames_(0), cur_depth_(0), - context_(context) { - DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread; -} - -StackVisitor::StackVisitor(Thread* thread, Context* context, size_t num_frames) - : thread_(thread), cur_shadow_frame_(nullptr), - cur_quick_frame_(nullptr), cur_quick_frame_pc_(0), num_frames_(num_frames), cur_depth_(0), +StackVisitor::StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind) + : StackVisitor(thread, context, walk_kind, 0) {} + +StackVisitor::StackVisitor(Thread* thread, + Context* context, + StackWalkKind walk_kind, + size_t num_frames) + : thread_(thread), + walk_kind_(walk_kind), + cur_shadow_frame_(nullptr), + cur_quick_frame_(nullptr), + cur_quick_frame_pc_(0), + num_frames_(num_frames), + cur_depth_(0), context_(context) { DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread; } @@ -151,6 +156,33 @@ size_t StackVisitor::GetNativePcOffset() const { return GetMethod()->NativeQuickPcOffset(cur_quick_frame_pc_); } +bool StackVisitor::IsReferenceVReg(mirror::ArtMethod* m, uint16_t vreg) { + // Process register map (which native and runtime methods don't have) + if (m->IsNative() || m->IsRuntimeMethod() || m->IsProxyMethod()) { + return false; + } + if (m->IsOptimized(sizeof(void*))) { + return true; // TODO: Implement. + } + const uint8_t* native_gc_map = m->GetNativeGcMap(sizeof(void*)); + CHECK(native_gc_map != nullptr) << PrettyMethod(m); + const DexFile::CodeItem* code_item = m->GetCodeItem(); + // Can't be null or how would we compile its instructions? + DCHECK(code_item != nullptr) << PrettyMethod(m); + NativePcOffsetToReferenceMap map(native_gc_map); + size_t num_regs = std::min(map.RegWidth() * 8, static_cast<size_t>(code_item->registers_size_)); + const uint8_t* reg_bitmap = nullptr; + if (num_regs > 0) { + Runtime* runtime = Runtime::Current(); + const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m, sizeof(void*)); + uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point); + reg_bitmap = map.FindBitMap(native_pc_offset); + DCHECK(reg_bitmap != nullptr); + } + // Does this register hold a reference? + return vreg < num_regs && TestBitmap(vreg, reg_bitmap); +} + bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const { if (cur_quick_frame_ != nullptr) { @@ -537,10 +569,10 @@ void StackVisitor::SetReturnPc(uintptr_t new_ret_pc) { *reinterpret_cast<uintptr_t*>(pc_addr) = new_ret_pc; } -size_t StackVisitor::ComputeNumFrames(Thread* thread) { +size_t StackVisitor::ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) { struct NumFramesVisitor : public StackVisitor { - explicit NumFramesVisitor(Thread* thread_in) - : StackVisitor(thread_in, nullptr), frames(0) {} + NumFramesVisitor(Thread* thread_in, StackWalkKind walk_kind_in) + : StackVisitor(thread_in, nullptr, walk_kind_in), frames(0) {} bool VisitFrame() OVERRIDE { frames++; @@ -549,16 +581,23 @@ size_t StackVisitor::ComputeNumFrames(Thread* thread) { size_t frames; }; - NumFramesVisitor visitor(thread); + NumFramesVisitor visitor(thread, walk_kind); visitor.WalkStack(true); return visitor.frames; } bool StackVisitor::GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) { struct HasMoreFramesVisitor : public StackVisitor { - explicit HasMoreFramesVisitor(Thread* thread, size_t num_frames, size_t frame_height) - : StackVisitor(thread, nullptr, num_frames), frame_height_(frame_height), - found_frame_(false), has_more_frames_(false), next_method_(nullptr), next_dex_pc_(0) { + HasMoreFramesVisitor(Thread* thread, + StackWalkKind walk_kind, + size_t num_frames, + size_t frame_height) + : StackVisitor(thread, nullptr, walk_kind, num_frames), + frame_height_(frame_height), + found_frame_(false), + has_more_frames_(false), + next_method_(nullptr), + next_dex_pc_(0) { } bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -582,7 +621,7 @@ bool StackVisitor::GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32 mirror::ArtMethod* next_method_; uint32_t next_dex_pc_; }; - HasMoreFramesVisitor visitor(thread_, GetNumFrames(), GetFrameHeight()); + HasMoreFramesVisitor visitor(thread_, walk_kind_, GetNumFrames(), GetFrameHeight()); visitor.WalkStack(true); *next_method = visitor.next_method_; *next_dex_pc = visitor.next_dex_pc_; @@ -592,7 +631,7 @@ bool StackVisitor::GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32 void StackVisitor::DescribeStack(Thread* thread) { struct DescribeStackVisitor : public StackVisitor { explicit DescribeStackVisitor(Thread* thread_in) - : StackVisitor(thread_in, nullptr) {} + : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {} bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { LOG(INFO) << "Frame Id=" << GetFrameId() << " " << DescribeLocation(); |