diff options
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r-- | runtime/stack.cc | 169 |
1 files changed, 9 insertions, 160 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc index eec0460015..19df0d26a1 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -27,6 +27,7 @@ #include "entrypoints/runtime_asm_entrypoints.h" #include "gc/space/image_space.h" #include "gc/space/space-inl.h" +#include "interpreter/shadow_frame.h" #include "jit/jit.h" #include "jit/jit_code_cache.h" #include "linear_alloc.h" @@ -39,7 +40,6 @@ #include "runtime.h" #include "thread.h" #include "thread_list.h" -#include "verify_object.h" namespace art { @@ -47,29 +47,6 @@ using android::base::StringPrintf; static constexpr bool kDebugStackWalk = false; -mirror::Object* ShadowFrame::GetThisObject() const { - ArtMethod* m = GetMethod(); - if (m->IsStatic()) { - return nullptr; - } else if (m->IsNative()) { - return GetVRegReference(0); - } else { - const DexFile::CodeItem* code_item = m->GetCodeItem(); - CHECK(code_item != nullptr) << ArtMethod::PrettyMethod(m); - uint16_t reg = code_item->registers_size_ - code_item->ins_size_; - return GetVRegReference(reg); - } -} - -mirror::Object* ShadowFrame::GetThisObject(uint16_t num_ins) const { - ArtMethod* m = GetMethod(); - if (m->IsStatic()) { - return nullptr; - } else { - return GetVRegReference(NumberOfVRegs() - num_ins); - } -} - StackVisitor::StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind, @@ -97,9 +74,10 @@ StackVisitor::StackVisitor(Thread* thread, } } -InlineInfo StackVisitor::GetCurrentInlineInfo() const { - const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); - uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc_); +static InlineInfo GetCurrentInlineInfo(const OatQuickMethodHeader* method_header, + uintptr_t cur_quick_frame_pc) + REQUIRES_SHARED(Locks::mutator_lock_) { + uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc); CodeInfo code_info = method_header->GetOptimizedCodeInfo(); CodeInfoEncoding encoding = code_info.ExtractEncoding(); StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); @@ -113,7 +91,8 @@ ArtMethod* StackVisitor::GetMethod() const { } else if (cur_quick_frame_ != nullptr) { if (IsInInlinedFrame()) { size_t depth_in_stack_map = current_inlining_depth_ - 1; - InlineInfo inline_info = GetCurrentInlineInfo(); + InlineInfo inline_info = GetCurrentInlineInfo(GetCurrentOatQuickMethodHeader(), + cur_quick_frame_pc_); const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding(); MethodInfo method_info = method_header->GetOptimizedMethodInfo(); @@ -138,8 +117,8 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const { size_t depth_in_stack_map = current_inlining_depth_ - 1; const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); CodeInfoEncoding encoding = method_header->GetOptimizedCodeInfo().ExtractEncoding(); - return GetCurrentInlineInfo().GetDexPcAtDepth(encoding.inline_info.encoding, - depth_in_stack_map); + return GetCurrentInlineInfo(GetCurrentOatQuickMethodHeader(), cur_quick_frame_pc_). + GetDexPcAtDepth(encoding.inline_info.encoding, depth_in_stack_map); } else if (cur_oat_quick_method_header_ == nullptr) { return DexFile::kDexNoIndex; } else { @@ -924,134 +903,4 @@ void StackVisitor::WalkStack(bool include_transitions) { template void StackVisitor::WalkStack<StackVisitor::CountTransitions::kYes>(bool); template void StackVisitor::WalkStack<StackVisitor::CountTransitions::kNo>(bool); -void JavaFrameRootInfo::Describe(std::ostream& os) const { - const StackVisitor* visitor = stack_visitor_; - CHECK(visitor != nullptr); - os << "Type=" << GetType() << " thread_id=" << GetThreadId() << " location=" << - visitor->DescribeLocation() << " vreg=" << vreg_; -} - -int StackVisitor::GetVRegOffsetFromQuickCode(const DexFile::CodeItem* code_item, - uint32_t core_spills, uint32_t fp_spills, - size_t frame_size, int reg, InstructionSet isa) { - PointerSize pointer_size = InstructionSetPointerSize(isa); - if (kIsDebugBuild) { - auto* runtime = Runtime::Current(); - if (runtime != nullptr) { - CHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), pointer_size); - } - } - DCHECK_ALIGNED(frame_size, kStackAlignment); - DCHECK_NE(reg, -1); - int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa) - + POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa) - + sizeof(uint32_t); // Filler. - int num_regs = code_item->registers_size_ - code_item->ins_size_; - int temp_threshold = code_item->registers_size_; - const int max_num_special_temps = 1; - if (reg == temp_threshold) { - // The current method pointer corresponds to special location on stack. - return 0; - } else if (reg >= temp_threshold + max_num_special_temps) { - /* - * Special temporaries may have custom locations and the logic above deals with that. - * However, non-special temporaries are placed relative to the outs. - */ - int temps_start = code_item->outs_size_ * sizeof(uint32_t) - + static_cast<size_t>(pointer_size) /* art method */; - int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t); - return temps_start + relative_offset; - } else if (reg < num_regs) { - int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t); - return locals_start + (reg * sizeof(uint32_t)); - } else { - // Handle ins. - return frame_size + ((reg - num_regs) * sizeof(uint32_t)) - + static_cast<size_t>(pointer_size) /* art method */; - } -} - -void LockCountData::AddMonitor(Thread* self, mirror::Object* obj) { - if (obj == nullptr) { - return; - } - - // If there's an error during enter, we won't have locked the monitor. So check there's no - // exception. - if (self->IsExceptionPending()) { - return; - } - - if (monitors_ == nullptr) { - monitors_.reset(new std::vector<mirror::Object*>()); - } - monitors_->push_back(obj); -} - -void LockCountData::RemoveMonitorOrThrow(Thread* self, const mirror::Object* obj) { - if (obj == nullptr) { - return; - } - bool found_object = false; - if (monitors_ != nullptr) { - // We need to remove one pointer to ref, as duplicates are used for counting recursive locks. - // We arbitrarily choose the first one. - auto it = std::find(monitors_->begin(), monitors_->end(), obj); - if (it != monitors_->end()) { - monitors_->erase(it); - found_object = true; - } - } - if (!found_object) { - // The object wasn't found. Time for an IllegalMonitorStateException. - // The order here isn't fully clear. Assume that any other pending exception is swallowed. - // TODO: Maybe make already pending exception a suppressed exception. - self->ClearException(); - self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;", - "did not lock monitor on object of type '%s' before unlocking", - const_cast<mirror::Object*>(obj)->PrettyTypeOf().c_str()); - } -} - -// Helper to unlock a monitor. Must be NO_THREAD_SAFETY_ANALYSIS, as we can't statically show -// that the object was locked. -void MonitorExitHelper(Thread* self, mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS { - DCHECK(self != nullptr); - DCHECK(obj != nullptr); - obj->MonitorExit(self); -} - -bool LockCountData::CheckAllMonitorsReleasedOrThrow(Thread* self) { - DCHECK(self != nullptr); - if (monitors_ != nullptr) { - if (!monitors_->empty()) { - // There may be an exception pending, if the method is terminating abruptly. Clear it. - // TODO: Should we add this as a suppressed exception? - self->ClearException(); - - // OK, there are monitors that are still locked. To enforce structured locking (and avoid - // deadlocks) we unlock all of them before we raise the IllegalMonitorState exception. - for (mirror::Object* obj : *monitors_) { - MonitorExitHelper(self, obj); - // If this raised an exception, ignore. TODO: Should we add this as suppressed - // exceptions? - if (self->IsExceptionPending()) { - self->ClearException(); - } - } - // Raise an exception, just give the first object as the sample. - mirror::Object* first = (*monitors_)[0]; - self->ThrowNewExceptionF("Ljava/lang/IllegalMonitorStateException;", - "did not unlock monitor on object of type '%s'", - mirror::Object::PrettyTypeOf(first).c_str()); - - // To make sure this path is not triggered again, clean out the monitors. - monitors_->clear(); - - return false; - } - } - return true; -} - } // namespace art |