summaryrefslogtreecommitdiffstats
path: root/runtime/stack.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-06-13 14:49:27 +0200
committerSebastien Hertz <shertz@google.com>2014-06-17 11:13:03 +0200
commitaa9b3aee1e06f922e4518713f9b3dff00a0b2597 (patch)
tree992b4565732a728dd901ed8a2f29c9246de328b7 /runtime/stack.cc
parentbc72903b909f5147b8cb207f3e5d02a8ef85e4e7 (diff)
downloadart-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.zip
art-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.tar.gz
art-aa9b3aee1e06f922e4518713f9b3dff00a0b2597.tar.bz2
Fix access to FP registers when visiting stack
Adds GetFPR and SetFPR to Context class so we can read from and write to floating-point registers during stack visit. They return a boolean flag indicating whether the read/write is successful. This allows the debugger to return the JDWP error ABSENT_INFORMATION when we can't read/write a register. We also update GetGPR and SetGPR for consistency. We keep a default GetGPR implementation asserting the read was successful using a CHECK so we don't silently fail. Adds missing JDWP object tags for StackFrame.SetValues to avoid crash when setting corresponding objects (thread, thread group, class object or class loader). Also returns JDWP error INVALID_OBJECT (when the given object id is invalid) instead of crashing with an unimplemented message. Bug: 15433097 Change-Id: I70843c9280e694aec1eae5cf6f2dc155cb9ea10e
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r--runtime/stack.cc48
1 files changed, 36 insertions, 12 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 7e922c5..8d242cd 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -142,7 +142,8 @@ size_t StackVisitor::GetNativePcOffset() const {
return GetMethod()->NativePcOffset(cur_quick_frame_pc_);
}
-uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind) const {
+bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+ uint32_t* val) const {
if (cur_quick_frame_ != NULL) {
DCHECK(context_ != NULL); // You can't reliably read registers without a context.
DCHECK(m == GetMethod());
@@ -155,19 +156,26 @@ uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin
if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) {
bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
- return GetGPR(vmap_table.ComputeRegister(spill_mask, vmap_offset, kind));
+ uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
+ if (is_float) {
+ return GetFPR(reg, val);
+ } else {
+ return GetGPR(reg, val);
+ }
} else {
const DexFile::CodeItem* code_item = m->GetCodeItem();
DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
- return *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ *val = *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
+ return true;
}
} else {
- return cur_shadow_frame_->GetVReg(vreg);
+ *val = cur_shadow_frame_->GetVReg(vreg);
+ return true;
}
}
-void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+bool StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
VRegKind kind) {
if (cur_quick_frame_ != NULL) {
DCHECK(context_ != NULL); // You can't reliably write registers without a context.
@@ -181,8 +189,12 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val
if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) {
bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
- const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kReferenceVReg);
- SetGPR(reg, new_value);
+ const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
+ if (is_float) {
+ return SetFPR(reg, new_value);
+ } else {
+ return SetGPR(reg, new_value);
+ }
} else {
const DexFile::CodeItem* code_item = m->GetCodeItem();
DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
@@ -190,9 +202,11 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val
frame_info.FrameSizeInBytes(), vreg, kRuntimeISA);
byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
*reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
+ return true;
}
} else {
- return cur_shadow_frame_->SetVReg(vreg, new_value);
+ cur_shadow_frame_->SetVReg(vreg, new_value);
+ return true;
}
}
@@ -201,14 +215,24 @@ uintptr_t* StackVisitor::GetGPRAddress(uint32_t reg) const {
return context_->GetGPRAddress(reg);
}
-uintptr_t StackVisitor::GetGPR(uint32_t reg) const {
+bool StackVisitor::GetGPR(uint32_t reg, uintptr_t* val) const {
+ DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine";
+ return context_->GetGPR(reg, val);
+}
+
+bool StackVisitor::SetGPR(uint32_t reg, uintptr_t value) {
+ DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine";
+ return context_->SetGPR(reg, value);
+}
+
+bool StackVisitor::GetFPR(uint32_t reg, uintptr_t* val) const {
DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine";
- return context_->GetGPR(reg);
+ return context_->GetFPR(reg, val);
}
-void StackVisitor::SetGPR(uint32_t reg, uintptr_t value) {
+bool StackVisitor::SetFPR(uint32_t reg, uintptr_t value) {
DCHECK(cur_quick_frame_ != NULL) << "This is a quick frame routine";
- context_->SetGPR(reg, value);
+ return context_->SetFPR(reg, value);
}
uintptr_t StackVisitor::GetReturnPc() const {