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/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 1777b3d..727bdf0 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -325,10 +325,12 @@
// Get vreg value from its current location.
uint32_t vreg_value;
VRegKind vreg_kind = ToVRegKind(throw_vreg_map[vreg].GetKind());
- bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
- vreg,
- vreg_kind,
- &vreg_value);
+ bool get_vreg_success =
+ stack_visitor->GetVReg(stack_visitor->GetMethod(),
+ vreg,
+ vreg_kind,
+ &vreg_value,
+ throw_vreg_map[vreg]);
CHECK(get_vreg_success) << "VReg " << vreg << " was optimized out ("
<< "method=" << ArtMethod::PrettyMethod(stack_visitor->GetMethod())
<< ", dex_pc=" << stack_visitor->GetDexPc() << ", "
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);
diff --git a/runtime/stack.h b/runtime/stack.h
index aa741df..ad73e75 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_STACK_H_
#define ART_RUNTIME_STACK_H_
+#include <optional>
#include <stdint.h>
#include <string>
@@ -223,7 +224,12 @@
bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc)
REQUIRES_SHARED(Locks::mutator_lock_);
- bool GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const
+ bool GetVReg(ArtMethod* m,
+ uint16_t vreg,
+ VRegKind kind,
+ uint32_t* val,
+ std::optional<DexRegisterLocation> location =
+ std::optional<DexRegisterLocation>()) const
REQUIRES_SHARED(Locks::mutator_lock_);
bool GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
@@ -330,6 +336,8 @@
VRegKind kind_lo, VRegKind kind_hi,
uint64_t* val) const
REQUIRES_SHARED(Locks::mutator_lock_);
+ bool GetVRegFromOptimizedCode(DexRegisterLocation location, VRegKind kind, uint32_t* val) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
bool GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, VRegKind kind_lo,
uint64_t* val) const
REQUIRES_SHARED(Locks::mutator_lock_);