diff options
author | 2019-12-18 14:57:30 +0000 | |
---|---|---|
committer | 2019-12-18 20:00:28 +0000 | |
commit | d7651b107688bdbee908ea927e054c5796150a67 (patch) | |
tree | 02f9a75b8949448e60ef71a3ef4ac6f09c1c776d | |
parent | 7ba68ffa031040fe91a923278910297ecf17edbe (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.cc | 4 | ||||
-rw-r--r-- | runtime/nterp_helpers.h | 7 | ||||
-rw-r--r-- | runtime/stack.cc | 34 |
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) { |