Add StackVisitor::SetVRegReference().
Avoid converting ObjPtr<>s to uint32_t and back.
Test: m test-art-host-gtest
Test: testrunner.py --host --interpreter
Test: run-jdwp-tests.sh --mode=host --variant=X64
Test: run-jdwp-tests.sh --mode=host --variant=X64 --debug
Bug: 31113334
Change-Id: I4e5c1577930de58772b35179aa4281ae4bbca300
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index a4b579b..408ce69 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -814,13 +814,9 @@
override REQUIRES_SHARED(art::Locks::mutator_lock_) {
switch (type_) {
case art::Primitive::kPrimNot: {
- uint32_t ptr_val;
- art::ObjPtr<art::mirror::Object> obj(caller_->DecodeJObject(val_.l));
- ptr_val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(obj.Ptr()));
- if (!visitor.SetVReg(method,
- static_cast<uint16_t>(slot_),
- ptr_val,
- art::kReferenceVReg)) {
+ if (!visitor.SetVRegReference(method,
+ static_cast<uint16_t>(slot_),
+ caller_->DecodeJObject(val_.l))) {
return ERR(OPAQUE_FRAME);
}
break;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 8a1dbdd..c042d19 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2848,8 +2848,7 @@
VLOG(jdwp) << tag << " object " << o << " is an invalid object";
return JDWP::ERR_INVALID_OBJECT;
}
- if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o.Ptr())),
- kReferenceVReg)) {
+ if (!visitor.SetVRegReference(m, vreg, o)) {
return FailSetLocalValue(visitor, vreg, tag, reinterpret_cast<uintptr_t>(o.Ptr()));
}
break;
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 80a563b..2ea3949 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -38,6 +38,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat_quick_method_header.h"
+#include "obj_ptr-inl.h"
#include "quick/quick_method_frame_info.h"
#include "runtime.h"
#include "thread.h"
@@ -372,13 +373,10 @@
return true;
}
-bool StackVisitor::SetVReg(ArtMethod* m,
- uint16_t vreg,
- uint32_t new_value,
- VRegKind kind) {
+ShadowFrame* StackVisitor::PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide) {
CodeItemDataAccessor accessor(m->DexInstructionData());
if (!accessor.HasCodeItem()) {
- return false;
+ return nullptr;
}
ShadowFrame* shadow_frame = GetCurrentShadowFrame();
if (shadow_frame == nullptr) {
@@ -388,15 +386,32 @@
const uint16_t num_regs = accessor.RegistersSize();
shadow_frame = thread_->FindOrCreateDebuggerShadowFrame(frame_id, num_regs, m, GetDexPc());
CHECK(shadow_frame != nullptr);
- // Remember the vreg has been set for debugging and must not be overwritten by the
+ // Remember the vreg(s) has been set for debugging and must not be overwritten by the
// original value during deoptimization of the stack.
thread_->GetUpdatedVRegFlags(frame_id)[vreg] = true;
+ if (wide) {
+ thread_->GetUpdatedVRegFlags(frame_id)[vreg + 1] = true;
+ }
}
- if (kind == kReferenceVReg) {
- shadow_frame->SetVRegReference(vreg, reinterpret_cast<mirror::Object*>(new_value));
- } else {
- shadow_frame->SetVReg(vreg, new_value);
+ return shadow_frame;
+}
+
+bool StackVisitor::SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) {
+ DCHECK(kind == kIntVReg || kind == kFloatVReg);
+ ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ false);
+ if (shadow_frame == nullptr) {
+ return false;
}
+ shadow_frame->SetVReg(vreg, new_value);
+ return true;
+}
+
+bool StackVisitor::SetVRegReference(ArtMethod* m, uint16_t vreg, ObjPtr<mirror::Object> new_value) {
+ ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ false);
+ if (shadow_frame == nullptr) {
+ return false;
+ }
+ shadow_frame->SetVRegReference(vreg, new_value);
return true;
}
@@ -413,21 +428,9 @@
LOG(FATAL) << "Expected long or double: kind_lo=" << kind_lo << ", kind_hi=" << kind_hi;
UNREACHABLE();
}
- CodeItemDataAccessor accessor(m->DexInstructionData());
- if (!accessor.HasCodeItem()) {
- return false;
- }
- ShadowFrame* shadow_frame = GetCurrentShadowFrame();
+ ShadowFrame* shadow_frame = PrepareSetVReg(m, vreg, /* wide= */ true);
if (shadow_frame == nullptr) {
- // This is a compiled frame: we must prepare for deoptimization (see SetVRegFromDebugger).
- const size_t frame_id = GetFrameId();
- const uint16_t num_regs = accessor.RegistersSize();
- shadow_frame = thread_->FindOrCreateDebuggerShadowFrame(frame_id, num_regs, m, GetDexPc());
- CHECK(shadow_frame != nullptr);
- // Remember the vreg pair has been set for debugging and must not be overwritten by the
- // original value during deoptimization of the stack.
- thread_->GetUpdatedVRegFlags(frame_id)[vreg] = true;
- thread_->GetUpdatedVRegFlags(frame_id)[vreg + 1] = true;
+ return false;
}
shadow_frame->SetVRegLong(vreg, new_value);
return true;
diff --git a/runtime/stack.h b/runtime/stack.h
index 1f305d2..4bc0fc8 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -22,6 +22,7 @@
#include "base/locks.h"
#include "base/macros.h"
+#include "obj_ptr.h"
#include "quick/quick_method_frame_info.h"
#include "stack_map.h"
@@ -236,6 +237,11 @@
// Values will be set in debugger shadow frames. Debugger will make sure deoptimization
// is triggered to make the values effective.
+ bool SetVRegReference(ArtMethod* m, uint16_t vreg, ObjPtr<mirror::Object> new_value)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Values will be set in debugger shadow frames. Debugger will make sure deoptimization
+ // is triggered to make the values effective.
bool SetVRegPair(ArtMethod* m,
uint16_t vreg,
uint64_t new_value,
@@ -328,6 +334,9 @@
uint64_t* val) const
REQUIRES_SHARED(Locks::mutator_lock_);
+ ShadowFrame* PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
void SanityCheckFrame() const REQUIRES_SHARED(Locks::mutator_lock_);
Thread* const thread_;