summaryrefslogtreecommitdiffstats
path: root/runtime/stack.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r--runtime/stack.cc468
1 files changed, 312 insertions, 156 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc
index b39aebfc4f..d570880d35 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -134,8 +134,7 @@ mirror::Object* StackVisitor::GetThisObject() const {
} else {
return cur_shadow_frame_->GetVRegReference(0);
}
- } else if (m->IsOptimized(GetInstructionSetPointerSize(
- Runtime::Current()->GetInstructionSet()))) {
+ } else if (m->IsOptimized(sizeof(void*))) {
// TODO: Implement, currently only used for exceptions when jdwp is enabled.
UNIMPLEMENTED(WARNING)
<< "StackVisitor::GetThisObject is unimplemented with the optimizing compiler";
@@ -163,42 +162,10 @@ bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
if (cur_quick_frame_ != nullptr) {
DCHECK(context_ != nullptr); // You can't reliably read registers without a context.
DCHECK(m == GetMethod());
- const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
- DCHECK(code_pointer != nullptr);
- const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
- QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
- uint32_t vmap_offset;
- // TODO: IsInContext stops before spotting floating point registers.
- 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();
- uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
- if (!IsAccessibleRegister(reg, is_float)) {
- return false;
- }
- uintptr_t ptr_val = GetRegister(reg, is_float);
- bool target64 = Is64BitInstructionSet(kRuntimeISA);
- if (target64) {
- bool wide_lo = (kind == kLongLoVReg) || (kind == kDoubleLoVReg);
- bool wide_hi = (kind == kLongHiVReg) || (kind == kDoubleHiVReg);
- int64_t value_long = static_cast<int64_t>(ptr_val);
- if (wide_lo) {
- ptr_val = static_cast<uintptr_t>(value_long & 0xFFFFFFFF);
- } else if (wide_hi) {
- ptr_val = static_cast<uintptr_t>(value_long >> 32);
- }
- }
- *val = ptr_val;
- return true;
+ if (m->IsOptimized(sizeof(void*))) {
+ return GetVRegFromOptimizedCode(m, vreg, kind, val);
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
- // its instructions?
- uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
- frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
- DCHECK(addr != nullptr);
- *val = *addr;
- return true;
+ return GetVRegFromQuickCode(m, vreg, kind, val);
}
} else {
DCHECK(cur_shadow_frame_ != nullptr);
@@ -207,6 +174,86 @@ bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
}
}
+bool StackVisitor::GetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+ uint32_t* val) const {
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
+ uint32_t vmap_offset;
+ // TODO: IsInContext stops before spotting floating point registers.
+ 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();
+ uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
+ return GetRegisterIfAccessible(reg, kind, val);
+ } else {
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ *val = *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
+ return true;
+ }
+}
+
+bool StackVisitor::GetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+ uint32_t* val) const {
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ uint32_t native_pc_offset = m->NativeQuickPcOffset(cur_quick_frame_pc_);
+ CodeInfo code_info = m->GetOptimizedCodeInfo();
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ DCHECK_LT(vreg, code_item->registers_size_);
+ DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map,
+ code_item->registers_size_);
+ DexRegisterMap::LocationKind location_kind = dex_register_map.GetLocationKind(vreg);
+ switch (location_kind) {
+ case DexRegisterMap::kInStack: {
+ const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ const uint8_t* addr = reinterpret_cast<const uint8_t*>(cur_quick_frame_) + offset;
+ *val = *reinterpret_cast<const uint32_t*>(addr);
+ return true;
+ }
+ case DexRegisterMap::kInRegister:
+ case DexRegisterMap::kInFpuRegister: {
+ uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ return GetRegisterIfAccessible(reg, kind, val);
+ }
+ case DexRegisterMap::kConstant:
+ *val = dex_register_map.GetConstant(vreg);
+ return true;
+ case DexRegisterMap::kNone:
+ return false;
+ }
+ UNREACHABLE();
+ return false;
+}
+
+bool StackVisitor::GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const {
+ const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
+ if (!IsAccessibleRegister(reg, is_float)) {
+ return false;
+ }
+ uintptr_t ptr_val = GetRegister(reg, is_float);
+ const bool target64 = Is64BitInstructionSet(kRuntimeISA);
+ if (target64) {
+ const bool wide_lo = (kind == kLongLoVReg) || (kind == kDoubleLoVReg);
+ const bool wide_hi = (kind == kLongHiVReg) || (kind == kDoubleHiVReg);
+ int64_t value_long = static_cast<int64_t>(ptr_val);
+ if (wide_lo) {
+ ptr_val = static_cast<uintptr_t>(Low32Bits(value_long));
+ } else if (wide_hi) {
+ ptr_val = static_cast<uintptr_t>(High32Bits(value_long));
+ }
+ }
+ *val = ptr_val;
+ return true;
+}
+
bool StackVisitor::GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
VRegKind kind_hi, uint64_t* val) const {
if (kind_lo == kLongLoVReg) {
@@ -215,45 +262,15 @@ bool StackVisitor::GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin
DCHECK_EQ(kind_hi, kDoubleHiVReg);
} else {
LOG(FATAL) << "Expected long or double: kind_lo=" << kind_lo << ", kind_hi=" << kind_hi;
+ UNREACHABLE();
}
if (cur_quick_frame_ != nullptr) {
DCHECK(context_ != nullptr); // You can't reliably read registers without a context.
DCHECK(m == GetMethod());
- const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
- DCHECK(code_pointer != nullptr);
- const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
- QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
- uint32_t vmap_offset_lo, vmap_offset_hi;
- // TODO: IsInContext stops before spotting floating point registers.
- if (vmap_table.IsInContext(vreg, kind_lo, &vmap_offset_lo) &&
- vmap_table.IsInContext(vreg + 1, kind_hi, &vmap_offset_hi)) {
- bool is_float = (kind_lo == kDoubleLoVReg);
- uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
- uint32_t reg_lo = vmap_table.ComputeRegister(spill_mask, vmap_offset_lo, kind_lo);
- uint32_t reg_hi = vmap_table.ComputeRegister(spill_mask, vmap_offset_hi, kind_hi);
- if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) {
- return false;
- }
- uintptr_t ptr_val_lo = GetRegister(reg_lo, is_float);
- uintptr_t ptr_val_hi = GetRegister(reg_hi, is_float);
- bool target64 = Is64BitInstructionSet(kRuntimeISA);
- if (target64) {
- int64_t value_long_lo = static_cast<int64_t>(ptr_val_lo);
- int64_t value_long_hi = static_cast<int64_t>(ptr_val_hi);
- ptr_val_lo = static_cast<uintptr_t>(value_long_lo & 0xFFFFFFFF);
- ptr_val_hi = static_cast<uintptr_t>(value_long_hi >> 32);
- }
- *val = (static_cast<uint64_t>(ptr_val_hi) << 32) | static_cast<uint32_t>(ptr_val_lo);
- return true;
+ if (m->IsOptimized(sizeof(void*))) {
+ return GetVRegPairFromOptimizedCode(m, vreg, kind_lo, kind_hi, val);
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
- // its instructions?
- uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
- frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
- DCHECK(addr != nullptr);
- *val = *reinterpret_cast<uint64_t*>(addr);
- return true;
+ return GetVRegPairFromQuickCode(m, vreg, kind_lo, kind_hi, val);
}
} else {
DCHECK(cur_shadow_frame_ != nullptr);
@@ -262,61 +279,185 @@ bool StackVisitor::GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin
}
}
+bool StackVisitor::GetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
+ VRegKind kind_hi, uint64_t* val) const {
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
+ uint32_t vmap_offset_lo, vmap_offset_hi;
+ // TODO: IsInContext stops before spotting floating point registers.
+ if (vmap_table.IsInContext(vreg, kind_lo, &vmap_offset_lo) &&
+ vmap_table.IsInContext(vreg + 1, kind_hi, &vmap_offset_hi)) {
+ bool is_float = (kind_lo == kDoubleLoVReg);
+ uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
+ uint32_t reg_lo = vmap_table.ComputeRegister(spill_mask, vmap_offset_lo, kind_lo);
+ uint32_t reg_hi = vmap_table.ComputeRegister(spill_mask, vmap_offset_hi, kind_hi);
+ return GetRegisterPairIfAccessible(reg_lo, reg_hi, kind_lo, val);
+ } else {
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
+ *val = *reinterpret_cast<uint64_t*>(addr);
+ return true;
+ }
+}
+
+bool StackVisitor::GetVRegPairFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg,
+ VRegKind kind_lo, VRegKind kind_hi,
+ uint64_t* val) const {
+ uint32_t low_32bits;
+ uint32_t high_32bits;
+ bool success = GetVRegFromOptimizedCode(m, vreg, kind_lo, &low_32bits);
+ success &= GetVRegFromOptimizedCode(m, vreg + 1, kind_hi, &high_32bits);
+ if (success) {
+ *val = (static_cast<uint64_t>(high_32bits) << 32) | static_cast<uint64_t>(low_32bits);
+ }
+ return success;
+}
+
+bool StackVisitor::GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi,
+ VRegKind kind_lo, uint64_t* val) const {
+ const bool is_float = (kind_lo == kDoubleLoVReg);
+ if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) {
+ return false;
+ }
+ uintptr_t ptr_val_lo = GetRegister(reg_lo, is_float);
+ uintptr_t ptr_val_hi = GetRegister(reg_hi, is_float);
+ bool target64 = Is64BitInstructionSet(kRuntimeISA);
+ if (target64) {
+ int64_t value_long_lo = static_cast<int64_t>(ptr_val_lo);
+ int64_t value_long_hi = static_cast<int64_t>(ptr_val_hi);
+ ptr_val_lo = static_cast<uintptr_t>(Low32Bits(value_long_lo));
+ ptr_val_hi = static_cast<uintptr_t>(High32Bits(value_long_hi));
+ }
+ *val = (static_cast<uint64_t>(ptr_val_hi) << 32) | static_cast<uint32_t>(ptr_val_lo);
+ return true;
+}
+
bool StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
VRegKind kind) {
if (cur_quick_frame_ != nullptr) {
- DCHECK(context_ != nullptr); // You can't reliably write registers without a context.
- DCHECK(m == GetMethod());
- const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
- DCHECK(code_pointer != nullptr);
- const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
- QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
- uint32_t vmap_offset;
- // TODO: IsInContext stops before spotting floating point registers.
- 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, kind);
- if (!IsAccessibleRegister(reg, is_float)) {
- return false;
- }
- bool target64 = Is64BitInstructionSet(kRuntimeISA);
- // Deal with 32 or 64-bit wide registers in a way that builds on all targets.
- if (target64) {
- bool wide_lo = (kind == kLongLoVReg) || (kind == kDoubleLoVReg);
- bool wide_hi = (kind == kLongHiVReg) || (kind == kDoubleHiVReg);
- if (wide_lo || wide_hi) {
- uintptr_t old_reg_val = GetRegister(reg, is_float);
- uint64_t new_vreg_portion = static_cast<uint64_t>(new_value);
- uint64_t old_reg_val_as_wide = static_cast<uint64_t>(old_reg_val);
- uint64_t mask = 0xffffffff;
- if (wide_lo) {
- mask = mask << 32;
- } else {
- new_vreg_portion = new_vreg_portion << 32;
- }
- new_value = static_cast<uintptr_t>((old_reg_val_as_wide & mask) | new_vreg_portion);
- }
+ DCHECK(context_ != nullptr); // You can't reliably write registers without a context.
+ DCHECK(m == GetMethod());
+ if (m->IsOptimized(sizeof(void*))) {
+ return SetVRegFromOptimizedCode(m, vreg, new_value, kind);
+ } else {
+ return SetVRegFromQuickCode(m, vreg, new_value, kind);
}
- SetRegister(reg, new_value, is_float);
- return true;
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
- // its instructions?
- uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
- frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
- DCHECK(addr != nullptr);
- *addr = new_value;
+ cur_shadow_frame_->SetVReg(vreg, new_value);
return true;
}
+}
+
+bool StackVisitor::SetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+ VRegKind kind) {
+ DCHECK(context_ != nullptr); // You can't reliably write registers without a context.
+ DCHECK(m == GetMethod());
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
+ uint32_t vmap_offset;
+ // TODO: IsInContext stops before spotting floating point registers.
+ 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();
+ uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
+ return SetRegisterIfAccessible(reg, new_value, kind);
} else {
- DCHECK(cur_shadow_frame_ != nullptr);
- cur_shadow_frame_->SetVReg(vreg, new_value);
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
+ *addr = new_value;
return true;
}
}
+bool StackVisitor::SetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+ VRegKind kind) {
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ uint32_t native_pc_offset = m->NativeQuickPcOffset(cur_quick_frame_pc_);
+ CodeInfo code_info = m->GetOptimizedCodeInfo();
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ DCHECK_LT(vreg, code_item->registers_size_);
+ DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(stack_map,
+ code_item->registers_size_);
+ DexRegisterMap::LocationKind location_kind = dex_register_map.GetLocationKind(vreg);
+ uint32_t dex_pc = m->ToDexPc(cur_quick_frame_pc_, false);
+ switch (location_kind) {
+ case DexRegisterMap::kInStack: {
+ const int32_t offset = dex_register_map.GetStackOffsetInBytes(vreg);
+ uint8_t* addr = reinterpret_cast<uint8_t*>(cur_quick_frame_) + offset;
+ *reinterpret_cast<uint32_t*>(addr) = new_value;
+ return true;
+ }
+ case DexRegisterMap::kInRegister:
+ case DexRegisterMap::kInFpuRegister: {
+ uint32_t reg = dex_register_map.GetMachineRegister(vreg);
+ return SetRegisterIfAccessible(reg, new_value, kind);
+ }
+ case DexRegisterMap::kConstant:
+ LOG(ERROR) << StringPrintf("Cannot change value of DEX register v%u used as a constant at "
+ "DEX pc 0x%x (native pc 0x%x) of method %s",
+ vreg, dex_pc, native_pc_offset,
+ PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str());
+ return false;
+ case DexRegisterMap::kNone:
+ LOG(ERROR) << StringPrintf("No location for DEX register v%u at DEX pc 0x%x "
+ "(native pc 0x%x) of method %s",
+ vreg, dex_pc, native_pc_offset,
+ PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str());
+ return false;
+ default:
+ LOG(FATAL) << StringPrintf("Unknown location for DEX register v%u at DEX pc 0x%x "
+ "(native pc 0x%x) of method %s",
+ vreg, dex_pc, native_pc_offset,
+ PrettyMethod(cur_quick_frame_->AsMirrorPtr()).c_str());
+ UNREACHABLE();
+ }
+}
+
+bool StackVisitor::SetRegisterIfAccessible(uint32_t reg, uint32_t new_value, VRegKind kind) {
+ const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
+ if (!IsAccessibleRegister(reg, is_float)) {
+ return false;
+ }
+ const bool target64 = Is64BitInstructionSet(kRuntimeISA);
+
+ // Create a new value that can hold both low 32 and high 32 bits, in
+ // case we are running 64 bits.
+ uintptr_t full_new_value = new_value;
+ // Deal with 32 or 64-bit wide registers in a way that builds on all targets.
+ if (target64) {
+ bool wide_lo = (kind == kLongLoVReg) || (kind == kDoubleLoVReg);
+ bool wide_hi = (kind == kLongHiVReg) || (kind == kDoubleHiVReg);
+ if (wide_lo || wide_hi) {
+ uintptr_t old_reg_val = GetRegister(reg, is_float);
+ uint64_t new_vreg_portion = static_cast<uint64_t>(new_value);
+ uint64_t old_reg_val_as_wide = static_cast<uint64_t>(old_reg_val);
+ uint64_t mask = 0xffffffff;
+ if (wide_lo) {
+ mask = mask << 32;
+ } else {
+ new_vreg_portion = new_vreg_portion << 32;
+ }
+ full_new_value = static_cast<uintptr_t>((old_reg_val_as_wide & mask) | new_vreg_portion);
+ }
+ }
+ SetRegister(reg, full_new_value, is_float);
+ return true;
+}
+
bool StackVisitor::SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
VRegKind kind_lo, VRegKind kind_hi) {
if (kind_lo == kLongLoVReg) {
@@ -329,49 +470,10 @@ bool StackVisitor::SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new
if (cur_quick_frame_ != nullptr) {
DCHECK(context_ != nullptr); // You can't reliably write registers without a context.
DCHECK(m == GetMethod());
- const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
- DCHECK(code_pointer != nullptr);
- const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
- QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
- uint32_t vmap_offset_lo, vmap_offset_hi;
- // TODO: IsInContext stops before spotting floating point registers.
- if (vmap_table.IsInContext(vreg, kind_lo, &vmap_offset_lo) &&
- vmap_table.IsInContext(vreg + 1, kind_hi, &vmap_offset_hi)) {
- bool is_float = (kind_lo == kDoubleLoVReg);
- uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
- uint32_t reg_lo = vmap_table.ComputeRegister(spill_mask, vmap_offset_lo, kind_lo);
- uint32_t reg_hi = vmap_table.ComputeRegister(spill_mask, vmap_offset_hi, kind_hi);
- if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) {
- return false;
- }
- uintptr_t new_value_lo = static_cast<uintptr_t>(new_value & 0xFFFFFFFF);
- uintptr_t new_value_hi = static_cast<uintptr_t>(new_value >> 32);
- bool target64 = Is64BitInstructionSet(kRuntimeISA);
- // Deal with 32 or 64-bit wide registers in a way that builds on all targets.
- if (target64) {
- uintptr_t old_reg_val_lo = GetRegister(reg_lo, is_float);
- uintptr_t old_reg_val_hi = GetRegister(reg_hi, is_float);
- uint64_t new_vreg_portion_lo = static_cast<uint64_t>(new_value_lo);
- uint64_t new_vreg_portion_hi = static_cast<uint64_t>(new_value_hi) << 32;
- uint64_t old_reg_val_lo_as_wide = static_cast<uint64_t>(old_reg_val_lo);
- uint64_t old_reg_val_hi_as_wide = static_cast<uint64_t>(old_reg_val_hi);
- uint64_t mask_lo = static_cast<uint64_t>(0xffffffff) << 32;
- uint64_t mask_hi = 0xffffffff;
- new_value_lo = static_cast<uintptr_t>((old_reg_val_lo_as_wide & mask_lo) | new_vreg_portion_lo);
- new_value_hi = static_cast<uintptr_t>((old_reg_val_hi_as_wide & mask_hi) | new_vreg_portion_hi);
- }
- SetRegister(reg_lo, new_value_lo, is_float);
- SetRegister(reg_hi, new_value_hi, is_float);
- return true;
+ if (m->IsOptimized(sizeof(void*))) {
+ return SetVRegPairFromOptimizedCode(m, vreg, new_value, kind_lo, kind_hi);
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
- // its instructions?
- uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
- frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
- DCHECK(addr != nullptr);
- *reinterpret_cast<uint64_t*>(addr) = new_value;
- return true;
+ return SetVRegPairFromQuickCode(m, vreg, new_value, kind_lo, kind_hi);
}
} else {
DCHECK(cur_shadow_frame_ != nullptr);
@@ -380,6 +482,60 @@ bool StackVisitor::SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new
}
}
+bool StackVisitor::SetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
+ VRegKind kind_lo, VRegKind kind_hi) {
+ const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
+ DCHECK(code_pointer != nullptr);
+ const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
+ uint32_t vmap_offset_lo, vmap_offset_hi;
+ // TODO: IsInContext stops before spotting floating point registers.
+ if (vmap_table.IsInContext(vreg, kind_lo, &vmap_offset_lo) &&
+ vmap_table.IsInContext(vreg + 1, kind_hi, &vmap_offset_hi)) {
+ bool is_float = (kind_lo == kDoubleLoVReg);
+ uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
+ uint32_t reg_lo = vmap_table.ComputeRegister(spill_mask, vmap_offset_lo, kind_lo);
+ uint32_t reg_hi = vmap_table.ComputeRegister(spill_mask, vmap_offset_hi, kind_hi);
+ return SetRegisterPairIfAccessible(reg_lo, reg_hi, new_value, is_float);
+ } else {
+ const DexFile::CodeItem* code_item = m->GetCodeItem();
+ DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be NULL or how would we compile
+ // its instructions?
+ uint32_t* addr = GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
+ *reinterpret_cast<uint64_t*>(addr) = new_value;
+ return true;
+ }
+}
+
+bool StackVisitor::SetVRegPairFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
+ VRegKind kind_lo, VRegKind kind_hi) {
+ uint32_t low_32bits = Low32Bits(new_value);
+ uint32_t high_32bits = High32Bits(new_value);
+ bool success = SetVRegFromOptimizedCode(m, vreg, low_32bits, kind_lo);
+ success &= SetVRegFromOptimizedCode(m, vreg + 1, high_32bits, kind_hi);
+ return success;
+}
+
+bool StackVisitor::SetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi,
+ uint64_t new_value, bool is_float) {
+ if (!IsAccessibleRegister(reg_lo, is_float) || !IsAccessibleRegister(reg_hi, is_float)) {
+ return false;
+ }
+ uintptr_t new_value_lo = static_cast<uintptr_t>(new_value & 0xFFFFFFFF);
+ uintptr_t new_value_hi = static_cast<uintptr_t>(new_value >> 32);
+ bool target64 = Is64BitInstructionSet(kRuntimeISA);
+ // Deal with 32 or 64-bit wide registers in a way that builds on all targets.
+ if (target64) {
+ DCHECK_EQ(reg_lo, reg_hi);
+ SetRegister(reg_lo, new_value, is_float);
+ } else {
+ SetRegister(reg_lo, new_value_lo, is_float);
+ SetRegister(reg_hi, new_value_hi, is_float);
+ }
+ return true;
+}
+
bool StackVisitor::IsAccessibleGPR(uint32_t reg) const {
DCHECK(context_ != nullptr);
return context_->IsAccessibleGPR(reg);