Add fast path for exception vreg copying.
It is not necessary to decode CodeInfo in GetVReg
since the caller already did it.
Test: ./art/test.py -b --host --64 --interpreter
Change-Id: I0f8941f43acdc0f2c43b78ef87d3e796e320c959
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 3fc6fd1..6d1e384 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -201,7 +201,11 @@
return false;
}
-bool StackVisitor::GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const {
+bool StackVisitor::GetVReg(ArtMethod* m,
+ uint16_t vreg,
+ VRegKind kind,
+ uint32_t* val,
+ std::optional<DexRegisterLocation> location) const {
if (cur_quick_frame_ != nullptr) {
DCHECK(context_ != nullptr); // You can't reliably read registers without a context.
DCHECK(m == GetMethod());
@@ -210,6 +214,16 @@
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;
+ }
return GetVRegFromOptimizedCode(m, vreg, kind, val);
} else {
DCHECK(cur_shadow_frame_ != nullptr);
@@ -290,6 +304,32 @@
}
}
+bool StackVisitor::GetVRegFromOptimizedCode(DexRegisterLocation location,
+ VRegKind kind,
+ uint32_t* val) const {
+ switch (location.GetKind()) {
+ case DexRegisterLocation::Kind::kInvalid:
+ break;
+ case DexRegisterLocation::Kind::kInStack: {
+ const uint8_t* sp = reinterpret_cast<const uint8_t*>(cur_quick_frame_);
+ *val = *reinterpret_cast<const uint32_t*>(sp + location.GetStackOffsetInBytes());
+ return true;
+ }
+ case DexRegisterLocation::Kind::kInRegister:
+ case DexRegisterLocation::Kind::kInRegisterHigh:
+ case DexRegisterLocation::Kind::kInFpuRegister:
+ case DexRegisterLocation::Kind::kInFpuRegisterHigh:
+ return GetRegisterIfAccessible(location.GetMachineRegister(), kind, val);
+ case DexRegisterLocation::Kind::kConstant:
+ *val = location.GetConstant();
+ return true;
+ case DexRegisterLocation::Kind::kNone:
+ return false;
+ }
+ LOG(FATAL) << "Unexpected location kind " << location.GetKind();
+ UNREACHABLE();
+}
+
bool StackVisitor::GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const {
const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);