summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-10-07 09:41:11 +0200
committer VladimĂ­r Marko <vmarko@google.com> 2024-10-07 11:59:00 +0000
commitd576392c76d75335d8284217f2153bdace62b355 (patch)
treeb625b235b2f64c856546e0b230b07d0dbe8f4f06
parentc50d67991682a9ae5e6215031a9852bbf018504b (diff)
Pass ISA to `Context::CalleeSaveAddress()`.
And clean up `QuickArgumentVisitor` implementation. This is a follow-up to https://android-review.googlesource.com/2680018 . Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: I18c0babd5fffa3d93aa4cb4377ef759424854a49
-rw-r--r--runtime/arch/arm/context_arm.cc5
-rw-r--r--runtime/arch/arm64/context_arm64.cc5
-rw-r--r--runtime/arch/context.h9
-rw-r--r--runtime/arch/riscv64/context_riscv64.cc7
-rw-r--r--runtime/arch/x86/context_x86.cc7
-rw-r--r--runtime/arch/x86_64/context_x86_64.cc5
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc81
7 files changed, 49 insertions, 70 deletions
diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc
index 50aec3331b..09756f68b6 100644
--- a/runtime/arch/arm/context_arm.cc
+++ b/runtime/arch/arm/context_arm.cc
@@ -39,20 +39,21 @@ void ArmContext::Reset() {
}
void ArmContext::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
+ const size_t frame_size = frame_info.FrameSizeInBytes();
int spill_pos = 0;
// Core registers come first, from the highest down to the lowest.
uint32_t core_regs = frame_info.CoreSpillMask();
DCHECK_EQ(0u, core_regs & (static_cast<uint32_t>(-1) << kNumberOfCoreRegisters));
for (uint32_t core_reg : HighToLowBits(core_regs)) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kArm>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
// FP registers come second, from the highest down to the lowest.
for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
- fprs_[fp_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ fprs_[fp_reg] = CalleeSaveAddress<InstructionSet::kArm>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index 77009e4932..9b5afb55d2 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -48,18 +48,19 @@ void Arm64Context::Reset() {
}
void Arm64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
+ const size_t frame_size = frame_info.FrameSizeInBytes();
int spill_pos = 0;
// Core registers come first, from the highest down to the lowest.
for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kArm64>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
// FP registers come second, from the highest down to the lowest.
for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
- fprs_[fp_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ fprs_[fp_reg] = CalleeSaveAddress<InstructionSet::kArm64>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
diff --git a/runtime/arch/context.h b/runtime/arch/context.h
index 2c442bdb4a..55988d0a6e 100644
--- a/runtime/arch/context.h
+++ b/runtime/arch/context.h
@@ -40,12 +40,13 @@ class Context {
// Re-initializes the registers for context re-use.
virtual void Reset() = 0;
+ template <InstructionSet kIsa>
static uintptr_t* CalleeSaveAddress(uint8_t* frame, int num, size_t frame_size) {
+ static constexpr size_t kPointerSize = static_cast<size_t>(GetInstructionSetPointerSize(kIsa));
// Callee saves are held at the top of the frame
- uint8_t* save_addr = frame + frame_size - ((num + 1) * sizeof(void*));
- if (kRuntimeISA == InstructionSet::kX86 ||
- kRuntimeISA == InstructionSet::kX86_64) {
- save_addr -= sizeof(void*); // account for return address
+ uint8_t* save_addr = frame + frame_size - ((num + 1) * kPointerSize);
+ if (kIsa == InstructionSet::kX86 || kIsa == InstructionSet::kX86_64) {
+ save_addr -= kPointerSize; // account for return address
}
return reinterpret_cast<uintptr_t*>(save_addr);
}
diff --git a/runtime/arch/riscv64/context_riscv64.cc b/runtime/arch/riscv64/context_riscv64.cc
index dceebe1e1f..779bb17e08 100644
--- a/runtime/arch/riscv64/context_riscv64.cc
+++ b/runtime/arch/riscv64/context_riscv64.cc
@@ -45,19 +45,20 @@ void Riscv64Context::Reset() {
void Riscv64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
// RA is at top of the frame
DCHECK_NE(frame_info.CoreSpillMask() & (1u << RA), 0u);
- gprs_[RA] = CalleeSaveAddress(frame, 0, frame_info.FrameSizeInBytes());
+ const size_t frame_size = frame_info.FrameSizeInBytes();
+ gprs_[RA] = CalleeSaveAddress<InstructionSet::kRiscv64>(frame, 0, frame_size);
// Core registers come first, from the highest down to the lowest, with the exception of RA/X1.
int spill_pos = 1;
for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask() & ~(1u << RA))) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kRiscv64>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
// FP registers come second, from the highest down to the lowest.
for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
- fprs_[fp_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ fprs_[fp_reg] = CalleeSaveAddress<InstructionSet::kRiscv64>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index 40f1a4aa8d..cb915b190e 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -38,6 +38,7 @@ void X86Context::Reset() {
}
void X86Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
+ const size_t frame_size = frame_info.FrameSizeInBytes();
int spill_pos = 0;
// Core registers come first, from the highest down to the lowest.
@@ -45,7 +46,7 @@ void X86Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& fra
frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs)); // Return address spill.
for (uint32_t core_reg : HighToLowBits(core_regs)) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kX86>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
@@ -56,9 +57,9 @@ void X86Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& fra
for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
// Two void* per XMM register.
fprs_[2 * fp_reg] = reinterpret_cast<uint32_t*>(
- CalleeSaveAddress(frame, spill_pos + 1, frame_info.FrameSizeInBytes()));
+ CalleeSaveAddress<InstructionSet::kX86>(frame, spill_pos + 1, frame_size));
fprs_[2 * fp_reg + 1] = reinterpret_cast<uint32_t*>(
- CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes()));
+ CalleeSaveAddress<InstructionSet::kX86>(frame, spill_pos, frame_size));
spill_pos += 2;
}
DCHECK_EQ(spill_pos,
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
index d40395bc8b..f6a3720d55 100644
--- a/runtime/arch/x86_64/context_x86_64.cc
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -37,6 +37,7 @@ void X86_64Context::Reset() {
}
void X86_64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
+ const size_t frame_size = frame_info.FrameSizeInBytes();
int spill_pos = 0;
// Core registers come first, from the highest down to the lowest.
@@ -44,7 +45,7 @@ void X86_64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo&
frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs)); // Return address spill.
for (uint32_t core_reg : HighToLowBits(core_regs)) {
- gprs_[core_reg] = CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes());
+ gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kX86_64>(frame, spill_pos, frame_size);
++spill_pos;
}
DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
@@ -54,7 +55,7 @@ void X86_64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo&
DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters));
for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
fprs_[fp_reg] = reinterpret_cast<uint64_t*>(
- CalleeSaveAddress(frame, spill_pos, frame_info.FrameSizeInBytes()));
+ CalleeSaveAddress<InstructionSet::kX86_64>(frame, spill_pos, frame_size));
++spill_pos;
}
DCHECK_EQ(spill_pos,
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 06cc82077a..fc97e6c1d3 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -67,8 +67,8 @@
namespace art HIDDEN {
// Visits the arguments as saved to the stack by a CalleeSaveType::kRefAndArgs callee save frame.
-template <typename Derived>
-class QuickArgumentVisitorBase {
+template <typename FrameInfo>
+class QuickArgumentVisitorImpl {
// Number of bytes for each out register in the caller method's frame.
static constexpr size_t kBytesStackArgLocation = 4;
// Frame size in bytes of a callee-save frame for RefsAndArgs.
@@ -85,23 +85,23 @@ class QuickArgumentVisitorBase {
RuntimeCalleeSaveFrame::GetReturnPcOffset(CalleeSaveType::kSaveRefsAndArgs);
static size_t GprIndexToGprOffset(uint32_t gpr_index) {
- return Derived::GprIndexToGprOffsetImpl(gpr_index);
+ return FrameInfo::GprIndexToGprOffsetImpl(gpr_index);
}
static constexpr bool kSplitPairAcrossRegisterAndStack =
- Derived::kSplitPairAcrossRegisterAndStack;
- static constexpr bool kAlignPairRegister = Derived::kAlignPairRegister;
- static constexpr bool kQuickSoftFloatAbi = Derived::kQuickSoftFloatAbi;
+ FrameInfo::kSplitPairAcrossRegisterAndStack;
+ static constexpr bool kAlignPairRegister = FrameInfo::kAlignPairRegister;
+ static constexpr bool kQuickSoftFloatAbi = FrameInfo::kQuickSoftFloatAbi;
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled =
- Derived::kQuickDoubleRegAlignedFloatBackFilled;
- static constexpr bool kQuickSkipOddFpRegisters = Derived::kQuickSkipOddFpRegisters;
- static constexpr size_t kNumQuickGprArgs = Derived::kNumQuickGprArgs;
- static constexpr size_t kNumQuickFprArgs = Derived::kNumQuickFprArgs;
- static constexpr bool kGprFprLockstep = Derived::kGprFprLockstep;
- static constexpr bool kNaNBoxing = Derived::kNanBoxing;
+ FrameInfo::kQuickDoubleRegAlignedFloatBackFilled;
+ static constexpr bool kQuickSkipOddFpRegisters = FrameInfo::kQuickSkipOddFpRegisters;
+ static constexpr size_t kNumQuickGprArgs = FrameInfo::kNumQuickGprArgs;
+ static constexpr size_t kNumQuickFprArgs = FrameInfo::kNumQuickFprArgs;
+ static constexpr bool kGprFprLockstep = FrameInfo::kGprFprLockstep;
+ static constexpr bool kNaNBoxing = FrameInfo::kNanBoxing;
public:
- static constexpr bool NaNBoxing() { return Derived::kNaNBoxing; }
+ static constexpr bool NaNBoxing() { return FrameInfo::kNaNBoxing; }
static StackReference<mirror::Object>* GetThisObjectReference(ArtMethod** sp)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -143,7 +143,7 @@ class QuickArgumentVisitorBase {
return *reinterpret_cast<uintptr_t*>(GetCallingPcAddr(sp));
}
- QuickArgumentVisitorBase(ArtMethod** sp, bool is_static, std::string_view shorty)
+ QuickArgumentVisitorImpl(ArtMethod** sp, bool is_static, std::string_view shorty)
REQUIRES_SHARED(Locks::mutator_lock_)
: is_static_(is_static),
shorty_(shorty),
@@ -168,7 +168,7 @@ class QuickArgumentVisitorBase {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
}
- virtual ~QuickArgumentVisitorBase() {}
+ virtual ~QuickArgumentVisitorImpl() {}
virtual void Visit() = 0;
@@ -384,7 +384,7 @@ class QuickArgumentVisitorBase {
bool is_split_long_or_double_;
};
-class QuickArgumentFrameInfoARM : public QuickArgumentVisitorBase<QuickArgumentFrameInfoARM> {
+class QuickArgumentFrameInfoARM {
public:
// The callee save frame is pointed to by SP.
// | argN | |
@@ -416,14 +416,9 @@ class QuickArgumentFrameInfoARM : public QuickArgumentVisitorBase<QuickArgumentF
static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
}
-
- QuickArgumentFrameInfoARM(ArtMethod** sp,
- bool is_static,
- std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_)
- : QuickArgumentVisitorBase(sp, is_static, shorty) {}
};
-class QuickArgumentFrameInfoARM64 : public QuickArgumentVisitorBase<QuickArgumentFrameInfoARM64> {
+class QuickArgumentFrameInfoARM64 {
public:
// The callee save frame is pointed to by SP.
// | argN | |
@@ -457,15 +452,9 @@ class QuickArgumentFrameInfoARM64 : public QuickArgumentVisitorBase<QuickArgumen
static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
}
-
- QuickArgumentFrameInfoARM64(ArtMethod** sp,
- bool is_static,
- std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_)
- : QuickArgumentVisitorBase(sp, is_static, shorty) {}
};
-class QuickArgumentFrameInfoRISCV64 :
- public QuickArgumentVisitorBase<QuickArgumentFrameInfoRISCV64> {
+class QuickArgumentFrameInfoRISCV64 {
public:
// The callee save frame is pointed to by SP.
// | argN | |
@@ -512,14 +501,9 @@ class QuickArgumentFrameInfoRISCV64 :
static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
return (gpr_index + 1) * GetBytesPerGprSpillLocation(kRuntimeISA); // skip S0/X8/FP
}
-
- QuickArgumentFrameInfoRISCV64(ArtMethod** sp,
- bool is_static,
- std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_)
- : QuickArgumentVisitorBase(sp, is_static, shorty) {}
};
-class QuickArgumentFrameInfoX86 : public QuickArgumentVisitorBase<QuickArgumentFrameInfoX86> {
+class QuickArgumentFrameInfoX86 {
public:
// The callee save frame is pointed to by SP.
// | argN | |
@@ -551,15 +535,9 @@ class QuickArgumentFrameInfoX86 : public QuickArgumentVisitorBase<QuickArgumentF
static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
}
-
- QuickArgumentFrameInfoX86(ArtMethod** sp,
- bool is_static,
- std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_)
- : QuickArgumentVisitorBase(sp, is_static, shorty) {}
};
-class QuickArgumentFrameInfoX86_64 :
- public QuickArgumentVisitorBase<QuickArgumentFrameInfoX86_64> {
+class QuickArgumentFrameInfoX86_64 {
public:
// The callee save frame is pointed to by SP.
// | argN | |
@@ -613,33 +591,28 @@ class QuickArgumentFrameInfoX86_64 :
UNREACHABLE();
}
}
-
- QuickArgumentFrameInfoX86_64(ArtMethod** sp,
- bool is_static,
- std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_)
- : QuickArgumentVisitorBase(sp, is_static, shorty) {}
};
namespace detail {
template <InstructionSet>
-struct QAVSelector;
+struct QAFISelector;
template <>
-struct QAVSelector<InstructionSet::kArm> { using type = QuickArgumentFrameInfoARM; };
+struct QAFISelector<InstructionSet::kArm> { using type = QuickArgumentFrameInfoARM; };
template <>
-struct QAVSelector<InstructionSet::kArm64> { using type = QuickArgumentFrameInfoARM64; };
+struct QAFISelector<InstructionSet::kArm64> { using type = QuickArgumentFrameInfoARM64; };
template <>
-struct QAVSelector<InstructionSet::kRiscv64> { using type = QuickArgumentFrameInfoRISCV64; };
+struct QAFISelector<InstructionSet::kRiscv64> { using type = QuickArgumentFrameInfoRISCV64; };
template <>
-struct QAVSelector<InstructionSet::kX86> { using type = QuickArgumentFrameInfoX86; };
+struct QAFISelector<InstructionSet::kX86> { using type = QuickArgumentFrameInfoX86; };
template <>
-struct QAVSelector<InstructionSet::kX86_64> { using type = QuickArgumentFrameInfoX86_64; };
+struct QAFISelector<InstructionSet::kX86_64> { using type = QuickArgumentFrameInfoX86_64; };
} // namespace detail
// TODO(Simulator): Use the quick code ISA instead of kRuntimeISA.
-using QuickArgumentVisitor = detail::QAVSelector<kRuntimeISA>::type;
+using QuickArgumentVisitor = QuickArgumentVisitorImpl<detail::QAFISelector<kRuntimeISA>::type>;
// Returns the 'this' object of a proxy method. This function is only used by StackVisitor. It
// allows to use the QuickArgumentVisitor constants without moving all the code in its own module.