summaryrefslogtreecommitdiff
path: root/runtime/stack.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r--runtime/stack.cc169
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