summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2019-12-18 14:57:30 +0000
committer Nicolas Geoffray <ngeoffray@google.com> 2019-12-18 20:00:28 +0000
commitd7651b107688bdbee908ea927e054c5796150a67 (patch)
tree02f9a75b8949448e60ef71a3ef4ac6f09c1c776d
parent7ba68ffa031040fe91a923278910297ecf17edbe (diff)
Fix StackVisitor::GetVReg for Nterp.
If the required type is reference, we should look at the reference array. Test: 686-get-this Bug: 112676029 Change-Id: Iee786723f67c576878d2f5d56f96694b75699cd1
-rw-r--r--runtime/nterp_helpers.cc4
-rw-r--r--runtime/nterp_helpers.h7
-rw-r--r--runtime/stack.cc34
3 files changed, 30 insertions, 15 deletions
diff --git a/runtime/nterp_helpers.cc b/runtime/nterp_helpers.cc
index 9b265c2cac..65221163b5 100644
--- a/runtime/nterp_helpers.cc
+++ b/runtime/nterp_helpers.cc
@@ -143,6 +143,10 @@ uint32_t NterpGetVReg(ArtMethod** frame, uint16_t vreg) {
return reinterpret_cast<uint32_t*>(NterpGetRegistersArray(frame))[vreg];
}
+uint32_t NterpGetVRegReference(ArtMethod** frame, uint16_t vreg) {
+ return reinterpret_cast<uint32_t*>(NterpGetReferenceArray(frame))[vreg];
+}
+
uintptr_t NterpGetCatchHandler() {
// Nterp uses the same landing pad for all exceptions. The dex_pc_ptr set before
// longjmp will actually be used to jmp to the catch handler.
diff --git a/runtime/nterp_helpers.h b/runtime/nterp_helpers.h
index 7dbf92efaa..aacd178258 100644
--- a/runtime/nterp_helpers.h
+++ b/runtime/nterp_helpers.h
@@ -67,6 +67,13 @@ uintptr_t NterpGetCatchHandler();
uint32_t NterpGetVReg(ArtMethod** frame, uint16_t vreg)
REQUIRES_SHARED(Locks::mutator_lock_);
+/**
+ * Returns the value of dex register number `vreg` in the given frame if it is a
+ * reference. Return 0 otehrwise.
+ */
+uint32_t NterpGetVRegReference(ArtMethod** frame, uint16_t vreg)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
} // namespace art
#endif // ART_RUNTIME_NTERP_HELPERS_H_
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 72690da088..20e97dc968 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -218,22 +218,26 @@ bool StackVisitor::GetVReg(ArtMethod* m,
if (GetVRegFromDebuggerShadowFrame(vreg, kind, val)) {
return true;
}
+ bool result = false;
if (cur_oat_quick_method_header_->IsNterpMethodHeader()) {
- *val = NterpGetVReg(cur_quick_frame_, vreg);
- return true;
- }
- DCHECK(cur_oat_quick_method_header_->IsOptimized());
- if (location.has_value() && kind != kReferenceVReg) {
- uint32_t val2 = *val;
- // The caller already known the register location, so we can use the faster overload
- // which does not decode the stack maps.
- bool ok = GetVRegFromOptimizedCode(location.value(), kind, val);
- // Compare to the slower overload.
- DCHECK_EQ(ok, GetVRegFromOptimizedCode(m, vreg, kind, &val2));
- DCHECK_EQ(*val, val2);
- return ok;
+ result = true;
+ *val = (kind == kReferenceVReg)
+ ? NterpGetVRegReference(cur_quick_frame_, vreg)
+ : NterpGetVReg(cur_quick_frame_, vreg);
+ } else {
+ DCHECK(cur_oat_quick_method_header_->IsOptimized());
+ if (location.has_value() && kind != kReferenceVReg) {
+ uint32_t val2 = *val;
+ // The caller already known the register location, so we can use the faster overload
+ // which does not decode the stack maps.
+ result = GetVRegFromOptimizedCode(location.value(), kind, val);
+ // Compare to the slower overload.
+ DCHECK_EQ(result, GetVRegFromOptimizedCode(m, vreg, kind, &val2));
+ DCHECK_EQ(*val, val2);
+ } else {
+ result = GetVRegFromOptimizedCode(m, vreg, kind, val);
+ }
}
- bool res = GetVRegFromOptimizedCode(m, vreg, kind, val);
if (kind == kReferenceVReg) {
// Perform a read barrier in case we are in a different thread and GC is ongoing.
mirror::Object* out = reinterpret_cast<mirror::Object*>(static_cast<uintptr_t>(*val));
@@ -241,7 +245,7 @@ bool StackVisitor::GetVReg(ArtMethod* m,
DCHECK_LT(ptr_out, std::numeric_limits<uint32_t>::max());
*val = static_cast<uint32_t>(ptr_out);
}
- return res;
+ return result;
} else {
DCHECK(cur_shadow_frame_ != nullptr);
if (kind == kReferenceVReg) {