Clean up JNI calling convention callee saves.
Precalculate callee saves at compile time and return them
as ArrayRef<> instead of keeping then in a std::vector<>.
Change-Id: I4fd7d2bbf6138dc31b0fe8554eac35b0777ec9ef
diff --git a/compiler/jni/jni_cfi_test.cc b/compiler/jni/jni_cfi_test.cc
index 371019a..3526802 100644
--- a/compiler/jni/jni_cfi_test.cc
+++ b/compiler/jni/jni_cfi_test.cc
@@ -52,7 +52,7 @@
std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv(
ManagedRuntimeCallingConvention::Create(&arena, is_static, is_synchronized, shorty, isa));
const int frame_size(jni_conv->FrameSize());
- const std::vector<ManagedRegister>& callee_save_regs = jni_conv->CalleeSaveRegisters();
+ ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters();
// Assemble the method.
std::unique_ptr<Assembler> jni_asm(Assembler::Create(&arena, isa));
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 9d2732a..29411f0 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -31,10 +31,6 @@
S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15
};
-static const SRegister kHFSCalleeSaveRegisters[] = {
- S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31
-};
-
static const DRegister kHFDArgumentRegisters[] = {
D0, D1, D2, D3, D4, D5, D6, D7
};
@@ -42,6 +38,57 @@
static_assert(arraysize(kHFDArgumentRegisters) * 2 == arraysize(kHFSArgumentRegisters),
"ks d argument registers mismatch");
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ ArmManagedRegister::FromCoreRegister(R5),
+ ArmManagedRegister::FromCoreRegister(R6),
+ ArmManagedRegister::FromCoreRegister(R7),
+ ArmManagedRegister::FromCoreRegister(R8),
+ ArmManagedRegister::FromCoreRegister(R10),
+ ArmManagedRegister::FromCoreRegister(R11),
+ // Hard float registers.
+ ArmManagedRegister::FromSRegister(S16),
+ ArmManagedRegister::FromSRegister(S17),
+ ArmManagedRegister::FromSRegister(S18),
+ ArmManagedRegister::FromSRegister(S19),
+ ArmManagedRegister::FromSRegister(S20),
+ ArmManagedRegister::FromSRegister(S21),
+ ArmManagedRegister::FromSRegister(S22),
+ ArmManagedRegister::FromSRegister(S23),
+ ArmManagedRegister::FromSRegister(S24),
+ ArmManagedRegister::FromSRegister(S25),
+ ArmManagedRegister::FromSRegister(S26),
+ ArmManagedRegister::FromSRegister(S27),
+ ArmManagedRegister::FromSRegister(S28),
+ ArmManagedRegister::FromSRegister(S29),
+ ArmManagedRegister::FromSRegister(S30),
+ ArmManagedRegister::FromSRegister(S31)
+};
+
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ // LR is a special callee save which is not reported by CalleeSaveRegisters().
+ uint32_t result = 1 << LR;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsArm().IsCoreRegister()) {
+ result |= (1 << r.AsArm().AsCoreRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t CalculateFpCalleeSpillMask() {
+ uint32_t result = 0;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsArm().IsSRegister()) {
+ result |= (1 << r.AsArm().AsSRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = CalculateFpCalleeSpillMask();
+
// Calling convention
ManagedRegister ArmManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
@@ -223,32 +270,15 @@
cur_reg++; // bump the iterator for every argument
}
padding_ = padding;
-
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R5));
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R6));
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R7));
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R8));
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R10));
- callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R11));
-
- for (size_t i = 0; i < arraysize(kHFSCalleeSaveRegisters); ++i) {
- callee_save_regs_.push_back(ArmManagedRegister::FromSRegister(kHFSCalleeSaveRegisters[i]));
- }
}
uint32_t ArmJniCallingConvention::CoreSpillMask() const {
// Compute spill mask to agree with callee saves initialized in the constructor
- uint32_t result = 0;
- result = 1 << R5 | 1 << R6 | 1 << R7 | 1 << R8 | 1 << R10 | 1 << R11 | 1 << LR;
- return result;
+ return kCoreCalleeSpillMask;
}
uint32_t ArmJniCallingConvention::FpSpillMask() const {
- uint32_t result = 0;
- for (size_t i = 0; i < arraysize(kHFSCalleeSaveRegisters); ++i) {
- result |= (1 << kHFSCalleeSaveRegisters[i]);
- }
- return result;
+ return kFpCalleeSpillMask;
}
ManagedRegister ArmJniCallingConvention::ReturnScratchRegister() const {
@@ -269,6 +299,10 @@
kStackAlignment);
}
+ArrayRef<const ManagedRegister> ArmJniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
// JniCallingConvention ABI follows AAPCS where longs and doubles must occur
// in even register numbers and stack slots
void ArmJniCallingConvention::Next() {
diff --git a/compiler/jni/quick/arm/calling_convention_arm.h b/compiler/jni/quick/arm/calling_convention_arm.h
index 35b5093..157880b 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.h
+++ b/compiler/jni/quick/arm/calling_convention_arm.h
@@ -58,9 +58,7 @@
void Next() OVERRIDE; // Override default behavior for AAPCS
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
uint32_t FpSpillMask() const OVERRIDE;
@@ -78,9 +76,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
// Padding to ensure longs and doubles are not split in AAPCS
size_t padding_;
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 9aef10e..ab56c1c 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -38,10 +38,65 @@
S0, S1, S2, S3, S4, S5, S6, S7
};
-static const DRegister kDCalleeSaveRegisters[] = {
- D8, D9, D10, D11, D12, D13, D14, D15
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ // Note: The native jni function may call to some VM runtime functions which may suspend
+ // or trigger GC. And the jni method frame will become top quick frame in those cases.
+ // So we need to satisfy GC to save LR and callee-save registers which is similar to
+ // CalleeSaveMethod(RefOnly) frame.
+ // Jni function is the native function which the java code wants to call.
+ // Jni method is the method that is compiled by jni compiler.
+ // Call chain: managed code(java) --> jni method --> jni function.
+ // Thread register(X19) is saved on stack.
+ Arm64ManagedRegister::FromXRegister(X19),
+ Arm64ManagedRegister::FromXRegister(X20),
+ Arm64ManagedRegister::FromXRegister(X21),
+ Arm64ManagedRegister::FromXRegister(X22),
+ Arm64ManagedRegister::FromXRegister(X23),
+ Arm64ManagedRegister::FromXRegister(X24),
+ Arm64ManagedRegister::FromXRegister(X25),
+ Arm64ManagedRegister::FromXRegister(X26),
+ Arm64ManagedRegister::FromXRegister(X27),
+ Arm64ManagedRegister::FromXRegister(X28),
+ Arm64ManagedRegister::FromXRegister(X29),
+ Arm64ManagedRegister::FromXRegister(LR),
+ // Hard float registers.
+ // Considering the case, java_method_1 --> jni method --> jni function --> java_method_2,
+ // we may break on java_method_2 and we still need to find out the values of DEX registers
+ // in java_method_1. So all callee-saves(in managed code) need to be saved.
+ Arm64ManagedRegister::FromDRegister(D8),
+ Arm64ManagedRegister::FromDRegister(D9),
+ Arm64ManagedRegister::FromDRegister(D10),
+ Arm64ManagedRegister::FromDRegister(D11),
+ Arm64ManagedRegister::FromDRegister(D12),
+ Arm64ManagedRegister::FromDRegister(D13),
+ Arm64ManagedRegister::FromDRegister(D14),
+ Arm64ManagedRegister::FromDRegister(D15),
};
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ uint32_t result = 0u;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsArm64().IsXRegister()) {
+ result |= (1 << r.AsArm64().AsXRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t CalculateFpCalleeSpillMask() {
+ uint32_t result = 0;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsArm64().IsDRegister()) {
+ result |= (1 << r.AsArm64().AsDRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = CalculateFpCalleeSpillMask();
+
// Calling convention
ManagedRegister Arm64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
return Arm64ManagedRegister::FromXRegister(X20); // saved on entry restored on exit
@@ -157,47 +212,14 @@
Arm64JniCallingConvention::Arm64JniCallingConvention(bool is_static, bool is_synchronized,
const char* shorty)
: JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
- uint32_t core_spill_mask = CoreSpillMask();
- DCHECK_EQ(XZR, kNumberOfXRegisters - 1); // Exclude XZR from the loop (avoid 1 << 32).
- for (int x_reg = 0; x_reg < kNumberOfXRegisters - 1; ++x_reg) {
- if (((1 << x_reg) & core_spill_mask) != 0) {
- callee_save_regs_.push_back(
- Arm64ManagedRegister::FromXRegister(static_cast<XRegister>(x_reg)));
- }
- }
-
- uint32_t fp_spill_mask = FpSpillMask();
- for (int d_reg = 0; d_reg < kNumberOfDRegisters; ++d_reg) {
- if (((1 << d_reg) & fp_spill_mask) != 0) {
- callee_save_regs_.push_back(
- Arm64ManagedRegister::FromDRegister(static_cast<DRegister>(d_reg)));
- }
- }
}
uint32_t Arm64JniCallingConvention::CoreSpillMask() const {
- // Compute spill mask to agree with callee saves initialized in the constructor.
- // Note: The native jni function may call to some VM runtime functions which may suspend
- // or trigger GC. And the jni method frame will become top quick frame in those cases.
- // So we need to satisfy GC to save LR and callee-save registers which is similar to
- // CalleeSaveMethod(RefOnly) frame.
- // Jni function is the native function which the java code wants to call.
- // Jni method is the method that compiled by jni compiler.
- // Call chain: managed code(java) --> jni method --> jni function.
- // Thread register(X19) is saved on stack.
- return 1 << X19 | 1 << X20 | 1 << X21 | 1 << X22 | 1 << X23 | 1 << X24 |
- 1 << X25 | 1 << X26 | 1 << X27 | 1 << X28 | 1 << X29 | 1 << LR;
+ return kCoreCalleeSpillMask;
}
uint32_t Arm64JniCallingConvention::FpSpillMask() const {
- // Considering the case, java_method_1 --> jni method --> jni function --> java_method_2, we may
- // break on java_method_2 and we still need to find out the values of DEX registers in
- // java_method_1. So all callee-saves(in managed code) need to be saved.
- uint32_t result = 0;
- for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
- result |= (1 << kDCalleeSaveRegisters[i]);
- }
- return result;
+ return kFpCalleeSpillMask;
}
ManagedRegister Arm64JniCallingConvention::ReturnScratchRegister() const {
@@ -218,6 +240,10 @@
return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
}
+ArrayRef<const ManagedRegister> Arm64JniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
bool Arm64JniCallingConvention::IsCurrentParamInRegister() {
if (IsCurrentParamAFloatOrDouble()) {
return (itr_float_and_doubles_ < 8);
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.h b/compiler/jni/quick/arm64/calling_convention_arm64.h
index 37c92b2..337e881 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.h
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.h
@@ -57,9 +57,7 @@
// JNI calling convention
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
uint32_t FpSpillMask() const OVERRIDE;
@@ -77,9 +75,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
DISALLOW_COPY_AND_ASSIGN(Arm64JniCallingConvention);
};
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 2c4b15c..e8f738d 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -17,12 +17,11 @@
#ifndef ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_
#define ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_
-#include <vector>
-
#include "base/arena_object.h"
#include "handle_scope.h"
#include "primitive.h"
#include "thread.h"
+#include "utils/array_ref.h"
#include "utils/managed_register.h"
namespace art {
@@ -301,7 +300,7 @@
virtual bool RequiresSmallResultTypeExtension() const = 0;
// Callee save registers to spill prior to native code (which may clobber)
- virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0;
+ virtual ArrayRef<const ManagedRegister> CalleeSaveRegisters() const = 0;
// Spill mask values
virtual uint32_t CoreSpillMask() const = 0;
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 27714b8..4311a34 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -112,7 +112,7 @@
// 1. Build the frame saving all callee saves
const size_t frame_size(main_jni_conv->FrameSize());
- const std::vector<ManagedRegister>& callee_save_regs = main_jni_conv->CalleeSaveRegisters();
+ ArrayRef<const ManagedRegister> callee_save_regs = main_jni_conv->CalleeSaveRegisters();
__ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs, mr_conv->EntrySpills());
DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(frame_size));
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
index 2d31a98..3d4d140 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ b/compiler/jni/quick/mips/calling_convention_mips.cc
@@ -27,6 +27,32 @@
static const FRegister kFArgumentRegisters[] = { F12, F14 };
static const DRegister kDArgumentRegisters[] = { D6, D7 };
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ MipsManagedRegister::FromCoreRegister(S2),
+ MipsManagedRegister::FromCoreRegister(S3),
+ MipsManagedRegister::FromCoreRegister(S4),
+ MipsManagedRegister::FromCoreRegister(S5),
+ MipsManagedRegister::FromCoreRegister(S6),
+ MipsManagedRegister::FromCoreRegister(S7),
+ MipsManagedRegister::FromCoreRegister(FP),
+ // No hard float callee saves.
+};
+
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ // RA is a special callee save which is not reported by CalleeSaveRegisters().
+ uint32_t result = 1 << RA;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsMips().IsCoreRegister()) {
+ result |= (1 << r.AsMips().AsCoreRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = 0u;
+
// Calling convention
ManagedRegister MipsManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
return MipsManagedRegister::FromCoreRegister(T9);
@@ -161,21 +187,14 @@
cur_reg++; // bump the iterator for every argument
}
padding_ = padding;
-
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S2));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S3));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S4));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S5));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S6));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(S7));
- callee_save_regs_.push_back(MipsManagedRegister::FromCoreRegister(FP));
}
uint32_t MipsJniCallingConvention::CoreSpillMask() const {
- // Compute spill mask to agree with callee saves initialized in the constructor
- uint32_t result = 0;
- result = 1 << S2 | 1 << S3 | 1 << S4 | 1 << S5 | 1 << S6 | 1 << S7 | 1 << FP | 1 << RA;
- return result;
+ return kCoreCalleeSpillMask;
+}
+
+uint32_t MipsJniCallingConvention::FpSpillMask() const {
+ return kFpCalleeSpillMask;
}
ManagedRegister MipsJniCallingConvention::ReturnScratchRegister() const {
@@ -196,6 +215,10 @@
return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize + padding_, kStackAlignment);
}
+ArrayRef<const ManagedRegister> MipsJniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
// JniCallingConvention ABI follows AAPCS where longs and doubles must occur
// in even register numbers and stack slots
void MipsJniCallingConvention::Next() {
diff --git a/compiler/jni/quick/mips/calling_convention_mips.h b/compiler/jni/quick/mips/calling_convention_mips.h
index dc45432..5c128b0 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.h
+++ b/compiler/jni/quick/mips/calling_convention_mips.h
@@ -58,14 +58,10 @@
void Next() OVERRIDE; // Override default behavior for AAPCS
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
- uint32_t FpSpillMask() const OVERRIDE {
- return 0; // Floats aren't spilled in JNI down call
- }
+ uint32_t FpSpillMask() const OVERRIDE;
bool IsCurrentParamInRegister() OVERRIDE;
bool IsCurrentParamOnStack() OVERRIDE;
ManagedRegister CurrentParamRegister() OVERRIDE;
@@ -80,9 +76,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
// Padding to ensure longs and doubles are not split in AAPCS
size_t padding_;
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.cc b/compiler/jni/quick/mips64/calling_convention_mips64.cc
index 807d740..f2e1da8 100644
--- a/compiler/jni/quick/mips64/calling_convention_mips64.cc
+++ b/compiler/jni/quick/mips64/calling_convention_mips64.cc
@@ -31,6 +31,33 @@
F12, F13, F14, F15, F16, F17, F18, F19
};
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ Mips64ManagedRegister::FromGpuRegister(S2),
+ Mips64ManagedRegister::FromGpuRegister(S3),
+ Mips64ManagedRegister::FromGpuRegister(S4),
+ Mips64ManagedRegister::FromGpuRegister(S5),
+ Mips64ManagedRegister::FromGpuRegister(S6),
+ Mips64ManagedRegister::FromGpuRegister(S7),
+ Mips64ManagedRegister::FromGpuRegister(GP),
+ Mips64ManagedRegister::FromGpuRegister(S8),
+ // No hard float callee saves.
+};
+
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ // RA is a special callee save which is not reported by CalleeSaveRegisters().
+ uint32_t result = 1 << RA;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsMips64().IsGpuRegister()) {
+ result |= (1 << r.AsMips64().AsGpuRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = 0u;
+
// Calling convention
ManagedRegister Mips64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
return Mips64ManagedRegister::FromGpuRegister(T9);
@@ -126,22 +153,14 @@
Mips64JniCallingConvention::Mips64JniCallingConvention(bool is_static, bool is_synchronized,
const char* shorty)
: JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S2));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S3));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S4));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S5));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S6));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S7));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(GP));
- callee_save_regs_.push_back(Mips64ManagedRegister::FromGpuRegister(S8));
}
uint32_t Mips64JniCallingConvention::CoreSpillMask() const {
- // Compute spill mask to agree with callee saves initialized in the constructor
- uint32_t result = 0;
- result = 1 << S2 | 1 << S3 | 1 << S4 | 1 << S5 | 1 << S6 | 1 << S7 | 1 << GP | 1 << S8 | 1 << RA;
- DCHECK_EQ(static_cast<size_t>(POPCOUNT(result)), callee_save_regs_.size() + 1);
- return result;
+ return kCoreCalleeSpillMask;
+}
+
+uint32_t Mips64JniCallingConvention::FpSpillMask() const {
+ return kFpCalleeSpillMask;
}
ManagedRegister Mips64JniCallingConvention::ReturnScratchRegister() const {
@@ -162,6 +181,10 @@
return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
}
+ArrayRef<const ManagedRegister> Mips64JniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
bool Mips64JniCallingConvention::IsCurrentParamInRegister() {
return itr_args_ < 8;
}
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.h b/compiler/jni/quick/mips64/calling_convention_mips64.h
index 3d6aab7..99ea3cd 100644
--- a/compiler/jni/quick/mips64/calling_convention_mips64.h
+++ b/compiler/jni/quick/mips64/calling_convention_mips64.h
@@ -57,14 +57,10 @@
// JNI calling convention
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
- uint32_t FpSpillMask() const OVERRIDE {
- return 0; // Floats aren't spilled in JNI down call
- }
+ uint32_t FpSpillMask() const OVERRIDE;
bool IsCurrentParamInRegister() OVERRIDE;
bool IsCurrentParamOnStack() OVERRIDE;
ManagedRegister CurrentParamRegister() OVERRIDE;
@@ -79,9 +75,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
DISALLOW_COPY_AND_ASSIGN(Mips64JniCallingConvention);
};
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 322caca..22c7cd0 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -23,6 +23,28 @@
namespace art {
namespace x86 {
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ X86ManagedRegister::FromCpuRegister(EBP),
+ X86ManagedRegister::FromCpuRegister(ESI),
+ X86ManagedRegister::FromCpuRegister(EDI),
+ // No hard float callee saves.
+};
+
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ // The spilled PC gets a special marker.
+ uint32_t result = 1 << kNumberOfCpuRegisters;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsX86().IsCpuRegister()) {
+ result |= (1 << r.AsX86().AsCpuRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = 0u;
+
// Calling convention
ManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
@@ -169,13 +191,14 @@
X86JniCallingConvention::X86JniCallingConvention(bool is_static, bool is_synchronized,
const char* shorty)
: JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
- callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EBP));
- callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(ESI));
- callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EDI));
}
uint32_t X86JniCallingConvention::CoreSpillMask() const {
- return 1 << EBP | 1 << ESI | 1 << EDI | 1 << kNumberOfCpuRegisters;
+ return kCoreCalleeSpillMask;
+}
+
+uint32_t X86JniCallingConvention::FpSpillMask() const {
+ return kFpCalleeSpillMask;
}
size_t X86JniCallingConvention::FrameSize() {
@@ -192,6 +215,10 @@
return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
}
+ArrayRef<const ManagedRegister> X86JniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
bool X86JniCallingConvention::IsCurrentParamInRegister() {
return false; // Everything is passed by stack.
}
diff --git a/compiler/jni/quick/x86/calling_convention_x86.h b/compiler/jni/quick/x86/calling_convention_x86.h
index cdf0956..9d678b7 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.h
+++ b/compiler/jni/quick/x86/calling_convention_x86.h
@@ -59,14 +59,10 @@
// JNI calling convention
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
- uint32_t FpSpillMask() const OVERRIDE {
- return 0;
- }
+ uint32_t FpSpillMask() const OVERRIDE;
bool IsCurrentParamInRegister() OVERRIDE;
bool IsCurrentParamOnStack() OVERRIDE;
ManagedRegister CurrentParamRegister() OVERRIDE;
@@ -81,9 +77,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
DISALLOW_COPY_AND_ASSIGN(X86JniCallingConvention);
};
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index b6b11ca..cc4d232 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -24,6 +24,45 @@
namespace art {
namespace x86_64 {
+static constexpr ManagedRegister kCalleeSaveRegisters[] = {
+ // Core registers.
+ X86_64ManagedRegister::FromCpuRegister(RBX),
+ X86_64ManagedRegister::FromCpuRegister(RBP),
+ X86_64ManagedRegister::FromCpuRegister(R12),
+ X86_64ManagedRegister::FromCpuRegister(R13),
+ X86_64ManagedRegister::FromCpuRegister(R14),
+ X86_64ManagedRegister::FromCpuRegister(R15),
+ // Hard float registers.
+ X86_64ManagedRegister::FromXmmRegister(XMM12),
+ X86_64ManagedRegister::FromXmmRegister(XMM13),
+ X86_64ManagedRegister::FromXmmRegister(XMM14),
+ X86_64ManagedRegister::FromXmmRegister(XMM15),
+};
+
+static constexpr uint32_t CalculateCoreCalleeSpillMask() {
+ // The spilled PC gets a special marker.
+ uint32_t result = 1 << kNumberOfCpuRegisters;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsX86_64().IsCpuRegister()) {
+ result |= (1 << r.AsX86_64().AsCpuRegister().AsRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t CalculateFpCalleeSpillMask() {
+ uint32_t result = 0;
+ for (auto&& r : kCalleeSaveRegisters) {
+ if (r.AsX86_64().IsXmmRegister()) {
+ result |= (1 << r.AsX86_64().AsXmmRegister().AsFloatRegister());
+ }
+ }
+ return result;
+}
+
+static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
+static constexpr uint32_t kFpCalleeSpillMask = CalculateFpCalleeSpillMask();
+
// Calling convention
ManagedRegister X86_64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
@@ -125,25 +164,14 @@
X86_64JniCallingConvention::X86_64JniCallingConvention(bool is_static, bool is_synchronized,
const char* shorty)
: JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(RBX));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(RBP));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(R12));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(R13));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(R14));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(R15));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromXmmRegister(XMM12));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromXmmRegister(XMM13));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromXmmRegister(XMM14));
- callee_save_regs_.push_back(X86_64ManagedRegister::FromXmmRegister(XMM15));
}
uint32_t X86_64JniCallingConvention::CoreSpillMask() const {
- return 1 << RBX | 1 << RBP | 1 << R12 | 1 << R13 | 1 << R14 | 1 << R15 |
- 1 << kNumberOfCpuRegisters;
+ return kCoreCalleeSpillMask;
}
uint32_t X86_64JniCallingConvention::FpSpillMask() const {
- return 1 << XMM12 | 1 << XMM13 | 1 << XMM14 | 1 << XMM15;
+ return kFpCalleeSpillMask;
}
size_t X86_64JniCallingConvention::FrameSize() {
@@ -160,6 +188,10 @@
return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
}
+ArrayRef<const ManagedRegister> X86_64JniCallingConvention::CalleeSaveRegisters() const {
+ return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
+}
+
bool X86_64JniCallingConvention::IsCurrentParamInRegister() {
return !IsCurrentParamOnStack();
}
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.h b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
index 6e47c9f..e2d3d48 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.h
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
@@ -55,9 +55,7 @@
// JNI calling convention
size_t FrameSize() OVERRIDE;
size_t OutArgSize() OVERRIDE;
- const std::vector<ManagedRegister>& CalleeSaveRegisters() const OVERRIDE {
- return callee_save_regs_;
- }
+ ArrayRef<const ManagedRegister> CalleeSaveRegisters() const OVERRIDE;
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
uint32_t FpSpillMask() const OVERRIDE;
@@ -75,9 +73,6 @@
size_t NumberOfOutgoingStackArgs() OVERRIDE;
private:
- // TODO: these values aren't unique and can be shared amongst instances
- std::vector<ManagedRegister> callee_save_regs_;
-
DISALLOW_COPY_AND_ASSIGN(X86_64JniCallingConvention);
};
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index e5f91dc..a7f4547 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -386,8 +386,9 @@
constexpr size_t kFramePointerSize = kArmPointerSize;
-void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+void ArmAssembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) {
CHECK_EQ(buffer_.Size(), 0U); // Nothing emitted yet
CHECK_ALIGNED(frame_size, kStackAlignment);
@@ -442,7 +443,7 @@
}
void ArmAssembler::RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) {
+ ArrayRef<const ManagedRegister> callee_save_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
cfi_.RememberState();
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index ffbe786..274d0de 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -907,12 +907,13 @@
//
// Emit code that will create an activation on the stack
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack
- void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/arm/managed_register_arm.h b/compiler/utils/arm/managed_register_arm.h
index 5b84058..276db44 100644
--- a/compiler/utils/arm/managed_register_arm.h
+++ b/compiler/utils/arm/managed_register_arm.h
@@ -85,34 +85,34 @@
// There is a one-to-one mapping between ManagedRegister and register id.
class ArmManagedRegister : public ManagedRegister {
public:
- Register AsCoreRegister() const {
+ constexpr Register AsCoreRegister() const {
CHECK(IsCoreRegister());
return static_cast<Register>(id_);
}
- SRegister AsSRegister() const {
+ constexpr SRegister AsSRegister() const {
CHECK(IsSRegister());
return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
}
- DRegister AsDRegister() const {
+ constexpr DRegister AsDRegister() const {
CHECK(IsDRegister());
return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
}
- SRegister AsOverlappingDRegisterLow() const {
+ constexpr SRegister AsOverlappingDRegisterLow() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<SRegister>(d_reg * 2);
}
- SRegister AsOverlappingDRegisterHigh() const {
+ constexpr SRegister AsOverlappingDRegisterHigh() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<SRegister>(d_reg * 2 + 1);
}
- RegisterPair AsRegisterPair() const {
+ constexpr RegisterPair AsRegisterPair() const {
CHECK(IsRegisterPair());
Register reg_low = AsRegisterPairLow();
if (reg_low == R1) {
@@ -122,50 +122,50 @@
}
}
- Register AsRegisterPairLow() const {
+ constexpr Register AsRegisterPairLow() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdLow().
return FromRegId(AllocIdLow()).AsCoreRegister();
}
- Register AsRegisterPairHigh() const {
+ constexpr Register AsRegisterPairHigh() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdHigh().
return FromRegId(AllocIdHigh()).AsCoreRegister();
}
- bool IsCoreRegister() const {
+ constexpr bool IsCoreRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
}
- bool IsSRegister() const {
+ constexpr bool IsSRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfCoreRegIds;
return (0 <= test) && (test < kNumberOfSRegIds);
}
- bool IsDRegister() const {
+ constexpr bool IsDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
return (0 <= test) && (test < kNumberOfDRegIds);
}
// Returns true if this DRegister overlaps SRegisters.
- bool IsOverlappingDRegister() const {
+ constexpr bool IsOverlappingDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
}
- bool IsRegisterPair() const {
+ constexpr bool IsRegisterPair() const {
CHECK(IsValidManagedRegister());
const int test =
id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
return (0 <= test) && (test < kNumberOfPairRegIds);
}
- bool IsSameType(ArmManagedRegister test) const {
+ constexpr bool IsSameType(ArmManagedRegister test) const {
CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
return
(IsCoreRegister() && test.IsCoreRegister()) ||
@@ -182,29 +182,29 @@
void Print(std::ostream& os) const;
- static ArmManagedRegister FromCoreRegister(Register r) {
+ static constexpr ArmManagedRegister FromCoreRegister(Register r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
- static ArmManagedRegister FromSRegister(SRegister r) {
+ static constexpr ArmManagedRegister FromSRegister(SRegister r) {
CHECK_NE(r, kNoSRegister);
return FromRegId(r + kNumberOfCoreRegIds);
}
- static ArmManagedRegister FromDRegister(DRegister r) {
+ static constexpr ArmManagedRegister FromDRegister(DRegister r) {
CHECK_NE(r, kNoDRegister);
return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
}
- static ArmManagedRegister FromRegisterPair(RegisterPair r) {
+ static constexpr ArmManagedRegister FromRegisterPair(RegisterPair r) {
CHECK_NE(r, kNoRegisterPair);
return FromRegId(r + (kNumberOfCoreRegIds +
kNumberOfSRegIds + kNumberOfDRegIds));
}
// Return a RegisterPair consisting of Register r_low and r_low + 1.
- static ArmManagedRegister FromCoreRegisterPair(Register r_low) {
+ static constexpr ArmManagedRegister FromCoreRegisterPair(Register r_low) {
if (r_low != R1) { // not the dalvik special case
CHECK_NE(r_low, kNoRegister);
CHECK_EQ(0, (r_low % 2));
@@ -217,7 +217,7 @@
}
// Return a DRegister overlapping SRegister r_low and r_low + 1.
- static ArmManagedRegister FromSRegisterPair(SRegister r_low) {
+ static constexpr ArmManagedRegister FromSRegisterPair(SRegister r_low) {
CHECK_NE(r_low, kNoSRegister);
CHECK_EQ(0, (r_low % 2));
const int r = r_low / 2;
@@ -226,7 +226,7 @@
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
@@ -251,9 +251,9 @@
friend class ManagedRegister;
- explicit ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static ArmManagedRegister FromRegId(int reg_id) {
+ static constexpr ArmManagedRegister FromRegId(int reg_id) {
ArmManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -264,7 +264,7 @@
} // namespace arm
-inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
+constexpr inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
arm::ArmManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index eb5112b..1842f00 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -683,8 +683,9 @@
DCHECK(registers.IsEmpty());
}
-void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+void Arm64Assembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) {
// Setup VIXL CPURegList for callee-saves.
CPURegList core_reg_list(CPURegister::kRegister, kXRegSize, 0);
@@ -741,7 +742,7 @@
}
void Arm64Assembler::RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) {
+ ArrayRef<const ManagedRegister> callee_save_regs) {
// Setup VIXL CPURegList for callee-saves.
CPURegList core_reg_list(CPURegister::kRegister, kXRegSize, 0);
CPURegList fp_reg_list(CPURegister::kFPRegister, kDRegSize, 0);
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index c4e5de7..91171a8 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -109,12 +109,13 @@
void UnspillRegisters(vixl::CPURegList registers, int offset);
// Emit code that will create an activation on the stack.
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack.
- void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/arm64/managed_register_arm64.h b/compiler/utils/arm64/managed_register_arm64.h
index 46be1c5..f7d74d2 100644
--- a/compiler/utils/arm64/managed_register_arm64.h
+++ b/compiler/utils/arm64/managed_register_arm64.h
@@ -56,80 +56,80 @@
class Arm64ManagedRegister : public ManagedRegister {
public:
- XRegister AsXRegister() const {
+ constexpr XRegister AsXRegister() const {
CHECK(IsXRegister());
return static_cast<XRegister>(id_);
}
- WRegister AsWRegister() const {
+ constexpr WRegister AsWRegister() const {
CHECK(IsWRegister());
return static_cast<WRegister>(id_ - kNumberOfXRegIds);
}
- DRegister AsDRegister() const {
+ constexpr DRegister AsDRegister() const {
CHECK(IsDRegister());
return static_cast<DRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds);
}
- SRegister AsSRegister() const {
+ constexpr SRegister AsSRegister() const {
CHECK(IsSRegister());
return static_cast<SRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds -
kNumberOfDRegIds);
}
- WRegister AsOverlappingWRegister() const {
+ constexpr WRegister AsOverlappingWRegister() const {
CHECK(IsValidManagedRegister());
if (IsZeroRegister()) return WZR;
return static_cast<WRegister>(AsXRegister());
}
- XRegister AsOverlappingXRegister() const {
+ constexpr XRegister AsOverlappingXRegister() const {
CHECK(IsValidManagedRegister());
return static_cast<XRegister>(AsWRegister());
}
- SRegister AsOverlappingSRegister() const {
+ constexpr SRegister AsOverlappingSRegister() const {
CHECK(IsValidManagedRegister());
return static_cast<SRegister>(AsDRegister());
}
- DRegister AsOverlappingDRegister() const {
+ constexpr DRegister AsOverlappingDRegister() const {
CHECK(IsValidManagedRegister());
return static_cast<DRegister>(AsSRegister());
}
- bool IsXRegister() const {
+ constexpr bool IsXRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfXRegIds);
}
- bool IsWRegister() const {
+ constexpr bool IsWRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfXRegIds;
return (0 <= test) && (test < kNumberOfWRegIds);
}
- bool IsDRegister() const {
+ constexpr bool IsDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds);
return (0 <= test) && (test < kNumberOfDRegIds);
}
- bool IsSRegister() const {
+ constexpr bool IsSRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds + kNumberOfDRegIds);
return (0 <= test) && (test < kNumberOfSRegIds);
}
- bool IsGPRegister() const {
+ constexpr bool IsGPRegister() const {
return IsXRegister() || IsWRegister();
}
- bool IsFPRegister() const {
+ constexpr bool IsFPRegister() const {
return IsDRegister() || IsSRegister();
}
- bool IsSameType(Arm64ManagedRegister test) const {
+ constexpr bool IsSameType(Arm64ManagedRegister test) const {
CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
return
(IsXRegister() && test.IsXRegister()) ||
@@ -145,53 +145,53 @@
void Print(std::ostream& os) const;
- static Arm64ManagedRegister FromXRegister(XRegister r) {
+ static constexpr Arm64ManagedRegister FromXRegister(XRegister r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
- static Arm64ManagedRegister FromWRegister(WRegister r) {
+ static constexpr Arm64ManagedRegister FromWRegister(WRegister r) {
CHECK_NE(r, kNoWRegister);
return FromRegId(r + kNumberOfXRegIds);
}
- static Arm64ManagedRegister FromDRegister(DRegister r) {
+ static constexpr Arm64ManagedRegister FromDRegister(DRegister r) {
CHECK_NE(r, kNoDRegister);
return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
}
- static Arm64ManagedRegister FromSRegister(SRegister r) {
+ static constexpr Arm64ManagedRegister FromSRegister(SRegister r) {
CHECK_NE(r, kNoSRegister);
return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds +
kNumberOfDRegIds));
}
// Returns the X register overlapping W register r.
- static Arm64ManagedRegister FromWRegisterX(WRegister r) {
+ static constexpr Arm64ManagedRegister FromWRegisterX(WRegister r) {
CHECK_NE(r, kNoWRegister);
return FromRegId(r);
}
// Return the D register overlapping S register r.
- static Arm64ManagedRegister FromSRegisterD(SRegister r) {
+ static constexpr Arm64ManagedRegister FromSRegisterD(SRegister r) {
CHECK_NE(r, kNoSRegister);
return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
- bool IsStackPointer() const {
+ constexpr bool IsStackPointer() const {
return IsXRegister() && (id_ == SP);
}
- bool IsZeroRegister() const {
+ constexpr bool IsZeroRegister() const {
return IsXRegister() && (id_ == XZR);
}
- int RegId() const {
+ constexpr int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
@@ -202,9 +202,9 @@
friend class ManagedRegister;
- explicit Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static Arm64ManagedRegister FromRegId(int reg_id) {
+ static constexpr Arm64ManagedRegister FromRegId(int reg_id) {
Arm64ManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -215,7 +215,7 @@
} // namespace arm64
-inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
+constexpr inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
arm64::Arm64ManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 5267dc3..80aa630 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -32,6 +32,7 @@
#include "memory_region.h"
#include "mips/constants_mips.h"
#include "offsets.h"
+#include "utils/array_ref.h"
#include "x86/constants_x86.h"
#include "x86_64/constants_x86_64.h"
@@ -375,13 +376,14 @@
virtual void Comment(const char* format ATTRIBUTE_UNUSED, ...) {}
// Emit code that will create an activation on the stack
- virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ virtual void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) = 0;
// Emit code that will remove an activation from the stack
virtual void RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) = 0;
+ ArrayRef<const ManagedRegister> callee_save_regs) = 0;
virtual void IncreaseFrameSize(size_t adjust) = 0;
virtual void DecreaseFrameSize(size_t adjust) = 0;
diff --git a/compiler/utils/managed_register.h b/compiler/utils/managed_register.h
index 893daff..46adb3f 100644
--- a/compiler/utils/managed_register.h
+++ b/compiler/utils/managed_register.h
@@ -47,40 +47,40 @@
// ManagedRegister is a value class. There exists no method to change the
// internal state. We therefore allow a copy constructor and an
// assignment-operator.
- ManagedRegister(const ManagedRegister& other) : id_(other.id_) { }
+ constexpr ManagedRegister(const ManagedRegister& other) : id_(other.id_) { }
ManagedRegister& operator=(const ManagedRegister& other) {
id_ = other.id_;
return *this;
}
- arm::ArmManagedRegister AsArm() const;
- arm64::Arm64ManagedRegister AsArm64() const;
- mips::MipsManagedRegister AsMips() const;
- mips64::Mips64ManagedRegister AsMips64() const;
- x86::X86ManagedRegister AsX86() const;
- x86_64::X86_64ManagedRegister AsX86_64() const;
+ constexpr arm::ArmManagedRegister AsArm() const;
+ constexpr arm64::Arm64ManagedRegister AsArm64() const;
+ constexpr mips::MipsManagedRegister AsMips() const;
+ constexpr mips64::Mips64ManagedRegister AsMips64() const;
+ constexpr x86::X86ManagedRegister AsX86() const;
+ constexpr x86_64::X86_64ManagedRegister AsX86_64() const;
// It is valid to invoke Equals on and with a NoRegister.
- bool Equals(const ManagedRegister& other) const {
+ constexpr bool Equals(const ManagedRegister& other) const {
return id_ == other.id_;
}
- bool IsNoRegister() const {
+ constexpr bool IsNoRegister() const {
return id_ == kNoRegister;
}
- static ManagedRegister NoRegister() {
+ static constexpr ManagedRegister NoRegister() {
return ManagedRegister();
}
- int RegId() const { return id_; }
- explicit ManagedRegister(int reg_id) : id_(reg_id) { }
+ constexpr int RegId() const { return id_; }
+ explicit constexpr ManagedRegister(int reg_id) : id_(reg_id) { }
protected:
static const int kNoRegister = -1;
- ManagedRegister() : id_(kNoRegister) { }
+ constexpr ManagedRegister() : id_(kNoRegister) { }
int id_;
};
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index a1798c0..9368301 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -2438,8 +2438,9 @@
constexpr size_t kFramePointerSize = 4;
-void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+void MipsAssembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) {
CHECK_ALIGNED(frame_size, kStackAlignment);
DCHECK(!overwriting_);
@@ -2453,7 +2454,7 @@
cfi_.RelOffset(DWARFReg(RA), stack_offset);
for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
stack_offset -= kFramePointerSize;
- Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
+ Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
StoreToOffset(kStoreWord, reg, SP, stack_offset);
cfi_.RelOffset(DWARFReg(reg), stack_offset);
}
@@ -2482,7 +2483,7 @@
}
void MipsAssembler::RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) {
+ ArrayRef<const ManagedRegister> callee_save_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
DCHECK(!overwriting_);
cfi_.RememberState();
@@ -2490,7 +2491,7 @@
// Pop callee saves and return address.
int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
for (size_t i = 0; i < callee_save_regs.size(); ++i) {
- Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
+ Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
LoadFromOffset(kLoadWord, reg, SP, stack_offset);
cfi_.Restore(DWARFReg(reg));
stack_offset += kFramePointerSize;
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index ecb67bd..d5e6285 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -414,11 +414,11 @@
// Emit code that will create an activation on the stack.
void BuildFrame(size_t frame_size,
ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack.
- void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/mips/managed_register_mips.h b/compiler/utils/mips/managed_register_mips.h
index 5e7ed11..66204e7 100644
--- a/compiler/utils/mips/managed_register_mips.h
+++ b/compiler/utils/mips/managed_register_mips.h
@@ -87,70 +87,70 @@
// There is a one-to-one mapping between ManagedRegister and register id.
class MipsManagedRegister : public ManagedRegister {
public:
- Register AsCoreRegister() const {
+ constexpr Register AsCoreRegister() const {
CHECK(IsCoreRegister());
return static_cast<Register>(id_);
}
- FRegister AsFRegister() const {
+ constexpr FRegister AsFRegister() const {
CHECK(IsFRegister());
return static_cast<FRegister>(id_ - kNumberOfCoreRegIds);
}
- DRegister AsDRegister() const {
+ constexpr DRegister AsDRegister() const {
CHECK(IsDRegister());
return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds);
}
- FRegister AsOverlappingDRegisterLow() const {
+ constexpr FRegister AsOverlappingDRegisterLow() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<FRegister>(d_reg * 2);
}
- FRegister AsOverlappingDRegisterHigh() const {
+ constexpr FRegister AsOverlappingDRegisterHigh() const {
CHECK(IsOverlappingDRegister());
DRegister d_reg = AsDRegister();
return static_cast<FRegister>(d_reg * 2 + 1);
}
- Register AsRegisterPairLow() const {
+ constexpr Register AsRegisterPairLow() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdLow().
return FromRegId(AllocIdLow()).AsCoreRegister();
}
- Register AsRegisterPairHigh() const {
+ constexpr Register AsRegisterPairHigh() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdHigh().
return FromRegId(AllocIdHigh()).AsCoreRegister();
}
- bool IsCoreRegister() const {
+ constexpr bool IsCoreRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
}
- bool IsFRegister() const {
+ constexpr bool IsFRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfCoreRegIds;
return (0 <= test) && (test < kNumberOfFRegIds);
}
- bool IsDRegister() const {
+ constexpr bool IsDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
return (0 <= test) && (test < kNumberOfDRegIds);
}
// Returns true if this DRegister overlaps FRegisters.
- bool IsOverlappingDRegister() const {
+ constexpr bool IsOverlappingDRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
}
- bool IsRegisterPair() const {
+ constexpr bool IsRegisterPair() const {
CHECK(IsValidManagedRegister());
const int test =
id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds);
@@ -164,32 +164,32 @@
// then false is returned.
bool Overlaps(const MipsManagedRegister& other) const;
- static MipsManagedRegister FromCoreRegister(Register r) {
+ static constexpr MipsManagedRegister FromCoreRegister(Register r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
- static MipsManagedRegister FromFRegister(FRegister r) {
+ static constexpr MipsManagedRegister FromFRegister(FRegister r) {
CHECK_NE(r, kNoFRegister);
return FromRegId(r + kNumberOfCoreRegIds);
}
- static MipsManagedRegister FromDRegister(DRegister r) {
+ static constexpr MipsManagedRegister FromDRegister(DRegister r) {
CHECK_NE(r, kNoDRegister);
return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds);
}
- static MipsManagedRegister FromRegisterPair(RegisterPair r) {
+ static constexpr MipsManagedRegister FromRegisterPair(RegisterPair r) {
CHECK_NE(r, kNoRegisterPair);
return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds));
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
- int RegId() const {
+ constexpr int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
@@ -205,9 +205,9 @@
friend class ManagedRegister;
- explicit MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static MipsManagedRegister FromRegId(int reg_id) {
+ static constexpr MipsManagedRegister FromRegId(int reg_id) {
MipsManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -218,7 +218,7 @@
} // namespace mips
-inline mips::MipsManagedRegister ManagedRegister::AsMips() const {
+constexpr inline mips::MipsManagedRegister ManagedRegister::AsMips() const {
mips::MipsManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index ab480ca..447ede5 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -1977,8 +1977,9 @@
constexpr size_t kFramePointerSize = 8;
-void Mips64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+void Mips64Assembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) {
CHECK_ALIGNED(frame_size, kStackAlignment);
DCHECK(!overwriting_);
@@ -1992,7 +1993,7 @@
cfi_.RelOffset(DWARFReg(RA), stack_offset);
for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
stack_offset -= kFramePointerSize;
- GpuRegister reg = callee_save_regs.at(i).AsMips64().AsGpuRegister();
+ GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
cfi_.RelOffset(DWARFReg(reg), stack_offset);
}
@@ -2003,7 +2004,7 @@
// Write out entry spills.
int32_t offset = frame_size + kFramePointerSize;
for (size_t i = 0; i < entry_spills.size(); ++i) {
- Mips64ManagedRegister reg = entry_spills.at(i).AsMips64();
+ Mips64ManagedRegister reg = entry_spills[i].AsMips64();
ManagedRegisterSpill spill = entry_spills.at(i);
int32_t size = spill.getSize();
if (reg.IsNoRegister()) {
@@ -2022,7 +2023,7 @@
}
void Mips64Assembler::RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) {
+ ArrayRef<const ManagedRegister> callee_save_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
DCHECK(!overwriting_);
cfi_.RememberState();
@@ -2030,7 +2031,7 @@
// Pop callee saves and return address
int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
for (size_t i = 0; i < callee_save_regs.size(); ++i) {
- GpuRegister reg = callee_save_regs.at(i).AsMips64().AsGpuRegister();
+ GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
cfi_.Restore(DWARFReg(reg));
stack_offset += kFramePointerSize;
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index 8acc38a..0cd0708 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -365,13 +365,13 @@
//
// Emit code that will create an activation on the stack.
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack.
- void RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& callee_save_regs) OVERRIDE;
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs) OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
void DecreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/mips64/managed_register_mips64.h b/compiler/utils/mips64/managed_register_mips64.h
index 1d36128..c9f9556 100644
--- a/compiler/utils/mips64/managed_register_mips64.h
+++ b/compiler/utils/mips64/managed_register_mips64.h
@@ -39,22 +39,22 @@
// There is a one-to-one mapping between ManagedRegister and register id.
class Mips64ManagedRegister : public ManagedRegister {
public:
- GpuRegister AsGpuRegister() const {
+ constexpr GpuRegister AsGpuRegister() const {
CHECK(IsGpuRegister());
return static_cast<GpuRegister>(id_);
}
- FpuRegister AsFpuRegister() const {
+ constexpr FpuRegister AsFpuRegister() const {
CHECK(IsFpuRegister());
return static_cast<FpuRegister>(id_ - kNumberOfGpuRegIds);
}
- bool IsGpuRegister() const {
+ constexpr bool IsGpuRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfGpuRegIds);
}
- bool IsFpuRegister() const {
+ constexpr bool IsFpuRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfGpuRegIds;
return (0 <= test) && (test < kNumberOfFpuRegIds);
@@ -67,22 +67,22 @@
// then false is returned.
bool Overlaps(const Mips64ManagedRegister& other) const;
- static Mips64ManagedRegister FromGpuRegister(GpuRegister r) {
+ static constexpr Mips64ManagedRegister FromGpuRegister(GpuRegister r) {
CHECK_NE(r, kNoGpuRegister);
return FromRegId(r);
}
- static Mips64ManagedRegister FromFpuRegister(FpuRegister r) {
+ static constexpr Mips64ManagedRegister FromFpuRegister(FpuRegister r) {
CHECK_NE(r, kNoFpuRegister);
return FromRegId(r + kNumberOfGpuRegIds);
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
- int RegId() const {
+ constexpr int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
@@ -98,9 +98,9 @@
friend class ManagedRegister;
- explicit Mips64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr Mips64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static Mips64ManagedRegister FromRegId(int reg_id) {
+ static constexpr Mips64ManagedRegister FromRegId(int reg_id) {
Mips64ManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -111,7 +111,7 @@
} // namespace mips64
-inline mips64::Mips64ManagedRegister ManagedRegister::AsMips64() const {
+constexpr inline mips64::Mips64ManagedRegister ManagedRegister::AsMips64() const {
mips64::Mips64ManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 84cdb7d..f931d75 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1932,15 +1932,16 @@
constexpr size_t kFramePointerSize = 4;
-void X86Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& spill_regs,
+void X86Assembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> spill_regs,
const ManagedRegisterEntrySpills& entry_spills) {
DCHECK_EQ(buffer_.Size(), 0U); // Nothing emitted yet.
cfi_.SetCurrentCFAOffset(4); // Return address on stack.
CHECK_ALIGNED(frame_size, kStackAlignment);
int gpr_count = 0;
for (int i = spill_regs.size() - 1; i >= 0; --i) {
- Register spill = spill_regs.at(i).AsX86().AsCpuRegister();
+ Register spill = spill_regs[i].AsX86().AsCpuRegister();
pushl(spill);
gpr_count++;
cfi_.AdjustCFAOffset(kFramePointerSize);
@@ -1974,7 +1975,7 @@
}
}
-void X86Assembler::RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& spill_regs) {
+void X86Assembler::RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> spill_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
cfi_.RememberState();
// -kFramePointerSize for ArtMethod*.
@@ -1982,7 +1983,7 @@
addl(ESP, Immediate(adjust));
cfi_.AdjustCFAOffset(-adjust);
for (size_t i = 0; i < spill_regs.size(); ++i) {
- Register spill = spill_regs.at(i).AsX86().AsCpuRegister();
+ Register spill = spill_regs[i].AsX86().AsCpuRegister();
popl(spill);
cfi_.AdjustCFAOffset(-static_cast<int>(kFramePointerSize));
cfi_.Restore(DWARFReg(spill));
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index bc46e9f..fa61662 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -633,12 +633,13 @@
//
// Emit code that will create an activation on the stack
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack
- void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/x86/managed_register_x86.h b/compiler/utils/x86/managed_register_x86.h
index fc20d7e..c0c2b65 100644
--- a/compiler/utils/x86/managed_register_x86.h
+++ b/compiler/utils/x86/managed_register_x86.h
@@ -89,64 +89,64 @@
// There is a one-to-one mapping between ManagedRegister and register id.
class X86ManagedRegister : public ManagedRegister {
public:
- ByteRegister AsByteRegister() const {
+ constexpr ByteRegister AsByteRegister() const {
CHECK(IsCpuRegister());
CHECK_LT(AsCpuRegister(), ESP); // ESP, EBP, ESI and EDI cannot be encoded as byte registers.
return static_cast<ByteRegister>(id_);
}
- Register AsCpuRegister() const {
+ constexpr Register AsCpuRegister() const {
CHECK(IsCpuRegister());
return static_cast<Register>(id_);
}
- XmmRegister AsXmmRegister() const {
+ constexpr XmmRegister AsXmmRegister() const {
CHECK(IsXmmRegister());
return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
}
- X87Register AsX87Register() const {
+ constexpr X87Register AsX87Register() const {
CHECK(IsX87Register());
return static_cast<X87Register>(id_ -
(kNumberOfCpuRegIds + kNumberOfXmmRegIds));
}
- Register AsRegisterPairLow() const {
+ constexpr Register AsRegisterPairLow() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdLow().
return FromRegId(AllocIdLow()).AsCpuRegister();
}
- Register AsRegisterPairHigh() const {
+ constexpr Register AsRegisterPairHigh() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdHigh().
return FromRegId(AllocIdHigh()).AsCpuRegister();
}
- RegisterPair AsRegisterPair() const {
+ constexpr RegisterPair AsRegisterPair() const {
CHECK(IsRegisterPair());
return static_cast<RegisterPair>(id_ -
(kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds));
}
- bool IsCpuRegister() const {
+ constexpr bool IsCpuRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
}
- bool IsXmmRegister() const {
+ constexpr bool IsXmmRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfCpuRegIds;
return (0 <= test) && (test < kNumberOfXmmRegIds);
}
- bool IsX87Register() const {
+ constexpr bool IsX87Register() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
return (0 <= test) && (test < kNumberOfX87RegIds);
}
- bool IsRegisterPair() const {
+ constexpr bool IsRegisterPair() const {
CHECK(IsValidManagedRegister());
const int test = id_ -
(kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds);
@@ -160,33 +160,33 @@
// then false is returned.
bool Overlaps(const X86ManagedRegister& other) const;
- static X86ManagedRegister FromCpuRegister(Register r) {
+ static constexpr X86ManagedRegister FromCpuRegister(Register r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
- static X86ManagedRegister FromXmmRegister(XmmRegister r) {
+ static constexpr X86ManagedRegister FromXmmRegister(XmmRegister r) {
CHECK_NE(r, kNoXmmRegister);
return FromRegId(r + kNumberOfCpuRegIds);
}
- static X86ManagedRegister FromX87Register(X87Register r) {
+ static constexpr X86ManagedRegister FromX87Register(X87Register r) {
CHECK_NE(r, kNoX87Register);
return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
}
- static X86ManagedRegister FromRegisterPair(RegisterPair r) {
+ static constexpr X86ManagedRegister FromRegisterPair(RegisterPair r) {
CHECK_NE(r, kNoRegisterPair);
return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
kNumberOfX87RegIds));
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
- int RegId() const {
+ constexpr int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
@@ -202,9 +202,9 @@
friend class ManagedRegister;
- explicit X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static X86ManagedRegister FromRegId(int reg_id) {
+ static constexpr X86ManagedRegister FromRegId(int reg_id) {
X86ManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -215,7 +215,7 @@
} // namespace x86
-inline x86::X86ManagedRegister ManagedRegister::AsX86() const {
+constexpr inline x86::X86ManagedRegister ManagedRegister::AsX86() const {
x86::X86ManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 5e7b587..3046710 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -2648,15 +2648,16 @@
constexpr size_t kFramePointerSize = 8;
-void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& spill_regs,
+void X86_64Assembler::BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> spill_regs,
const ManagedRegisterEntrySpills& entry_spills) {
DCHECK_EQ(buffer_.Size(), 0U); // Nothing emitted yet.
cfi_.SetCurrentCFAOffset(8); // Return address on stack.
CHECK_ALIGNED(frame_size, kStackAlignment);
int gpr_count = 0;
for (int i = spill_regs.size() - 1; i >= 0; --i) {
- x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
+ x86_64::X86_64ManagedRegister spill = spill_regs[i].AsX86_64();
if (spill.IsCpuRegister()) {
pushq(spill.AsCpuRegister());
gpr_count++;
@@ -2674,7 +2675,7 @@
// spill xmms
int64_t offset = rest_of_frame;
for (int i = spill_regs.size() - 1; i >= 0; --i) {
- x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
+ x86_64::X86_64ManagedRegister spill = spill_regs[i].AsX86_64();
if (spill.IsXmmRegister()) {
offset -= sizeof(double);
movsd(Address(CpuRegister(RSP), offset), spill.AsXmmRegister());
@@ -2707,15 +2708,14 @@
}
}
-void X86_64Assembler::RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& spill_regs) {
+void X86_64Assembler::RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> spill_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
cfi_.RememberState();
int gpr_count = 0;
// unspill xmms
int64_t offset = static_cast<int64_t>(frame_size) - (spill_regs.size() * kFramePointerSize) - 2 * kFramePointerSize;
for (size_t i = 0; i < spill_regs.size(); ++i) {
- x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
+ x86_64::X86_64ManagedRegister spill = spill_regs[i].AsX86_64();
if (spill.IsXmmRegister()) {
offset += sizeof(double);
movsd(spill.AsXmmRegister(), Address(CpuRegister(RSP), offset));
@@ -2728,7 +2728,7 @@
addq(CpuRegister(RSP), Immediate(adjust));
cfi_.AdjustCFAOffset(-adjust);
for (size_t i = 0; i < spill_regs.size(); ++i) {
- x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
+ x86_64::X86_64ManagedRegister spill = spill_regs[i].AsX86_64();
if (spill.IsCpuRegister()) {
popq(spill.AsCpuRegister());
cfi_.AdjustCFAOffset(-static_cast<int>(kFramePointerSize));
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 720a402..361f73c 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -704,12 +704,13 @@
//
// Emit code that will create an activation on the stack
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& callee_save_regs,
+ void BuildFrame(size_t frame_size,
+ ManagedRegister method_reg,
+ ArrayRef<const ManagedRegister> callee_save_regs,
const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
// Emit code that will remove an activation from the stack
- void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
+ void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
OVERRIDE;
void IncreaseFrameSize(size_t adjust) OVERRIDE;
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 9dccc9f..788c725 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -1498,9 +1498,11 @@
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
- std::vector<ManagedRegister> spill_regs;
- spill_regs.push_back(ManagedFromCpu(x86_64::R10));
- spill_regs.push_back(ManagedFromCpu(x86_64::RSI));
+ const ManagedRegister raw_spill_regs[] = {
+ ManagedFromCpu(x86_64::R10),
+ ManagedFromCpu(x86_64::RSI)
+ };
+ ArrayRef<const ManagedRegister> spill_regs(raw_spill_regs);
// Three random entry spills.
ManagedRegisterEntrySpills entry_spills;
@@ -1543,9 +1545,11 @@
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
- std::vector<ManagedRegister> spill_regs;
- spill_regs.push_back(ManagedFromCpu(x86_64::R10));
- spill_regs.push_back(ManagedFromCpu(x86_64::RSI));
+ const ManagedRegister raw_spill_regs[] = {
+ ManagedFromCpu(x86_64::R10),
+ ManagedFromCpu(x86_64::RSI)
+ };
+ ArrayRef<const ManagedRegister> spill_regs(raw_spill_regs);
size_t frame_size = 10 * kStackAlignment;
assembler->RemoveFrame(10 * kStackAlignment, spill_regs);
diff --git a/compiler/utils/x86_64/constants_x86_64.h b/compiler/utils/x86_64/constants_x86_64.h
index 0c782d4..37db6b1 100644
--- a/compiler/utils/x86_64/constants_x86_64.h
+++ b/compiler/utils/x86_64/constants_x86_64.h
@@ -29,15 +29,15 @@
class CpuRegister {
public:
- explicit CpuRegister(Register r) : reg_(r) {}
- explicit CpuRegister(int r) : reg_(Register(r)) {}
- Register AsRegister() const {
+ explicit constexpr CpuRegister(Register r) : reg_(r) {}
+ explicit constexpr CpuRegister(int r) : reg_(Register(r)) {}
+ constexpr Register AsRegister() const {
return reg_;
}
- uint8_t LowBits() const {
+ constexpr uint8_t LowBits() const {
return reg_ & 7;
}
- bool NeedsRex() const {
+ constexpr bool NeedsRex() const {
return reg_ > 7;
}
private:
@@ -47,15 +47,15 @@
class XmmRegister {
public:
- explicit XmmRegister(FloatRegister r) : reg_(r) {}
- explicit XmmRegister(int r) : reg_(FloatRegister(r)) {}
- FloatRegister AsFloatRegister() const {
+ explicit constexpr XmmRegister(FloatRegister r) : reg_(r) {}
+ explicit constexpr XmmRegister(int r) : reg_(FloatRegister(r)) {}
+ constexpr FloatRegister AsFloatRegister() const {
return reg_;
}
- uint8_t LowBits() const {
+ constexpr uint8_t LowBits() const {
return reg_ & 7;
}
- bool NeedsRex() const {
+ constexpr bool NeedsRex() const {
return reg_ > 7;
}
private:
diff --git a/compiler/utils/x86_64/managed_register_x86_64.h b/compiler/utils/x86_64/managed_register_x86_64.h
index c4228c1..32af672 100644
--- a/compiler/utils/x86_64/managed_register_x86_64.h
+++ b/compiler/utils/x86_64/managed_register_x86_64.h
@@ -88,52 +88,52 @@
// There is a one-to-one mapping between ManagedRegister and register id.
class X86_64ManagedRegister : public ManagedRegister {
public:
- CpuRegister AsCpuRegister() const {
+ constexpr CpuRegister AsCpuRegister() const {
CHECK(IsCpuRegister());
return CpuRegister(static_cast<Register>(id_));
}
- XmmRegister AsXmmRegister() const {
+ constexpr XmmRegister AsXmmRegister() const {
CHECK(IsXmmRegister());
return XmmRegister(static_cast<FloatRegister>(id_ - kNumberOfCpuRegIds));
}
- X87Register AsX87Register() const {
+ constexpr X87Register AsX87Register() const {
CHECK(IsX87Register());
return static_cast<X87Register>(id_ -
(kNumberOfCpuRegIds + kNumberOfXmmRegIds));
}
- CpuRegister AsRegisterPairLow() const {
+ constexpr CpuRegister AsRegisterPairLow() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdLow().
return FromRegId(AllocIdLow()).AsCpuRegister();
}
- CpuRegister AsRegisterPairHigh() const {
+ constexpr CpuRegister AsRegisterPairHigh() const {
CHECK(IsRegisterPair());
// Appropriate mapping of register ids allows to use AllocIdHigh().
return FromRegId(AllocIdHigh()).AsCpuRegister();
}
- bool IsCpuRegister() const {
+ constexpr bool IsCpuRegister() const {
CHECK(IsValidManagedRegister());
return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
}
- bool IsXmmRegister() const {
+ constexpr bool IsXmmRegister() const {
CHECK(IsValidManagedRegister());
const int test = id_ - kNumberOfCpuRegIds;
return (0 <= test) && (test < kNumberOfXmmRegIds);
}
- bool IsX87Register() const {
+ constexpr bool IsX87Register() const {
CHECK(IsValidManagedRegister());
const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
return (0 <= test) && (test < kNumberOfX87RegIds);
}
- bool IsRegisterPair() const {
+ constexpr bool IsRegisterPair() const {
CHECK(IsValidManagedRegister());
const int test = id_ -
(kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds);
@@ -147,32 +147,32 @@
// then false is returned.
bool Overlaps(const X86_64ManagedRegister& other) const;
- static X86_64ManagedRegister FromCpuRegister(Register r) {
+ static constexpr X86_64ManagedRegister FromCpuRegister(Register r) {
CHECK_NE(r, kNoRegister);
return FromRegId(r);
}
- static X86_64ManagedRegister FromXmmRegister(FloatRegister r) {
+ static constexpr X86_64ManagedRegister FromXmmRegister(FloatRegister r) {
return FromRegId(r + kNumberOfCpuRegIds);
}
- static X86_64ManagedRegister FromX87Register(X87Register r) {
+ static constexpr X86_64ManagedRegister FromX87Register(X87Register r) {
CHECK_NE(r, kNoX87Register);
return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
}
- static X86_64ManagedRegister FromRegisterPair(RegisterPair r) {
+ static constexpr X86_64ManagedRegister FromRegisterPair(RegisterPair r) {
CHECK_NE(r, kNoRegisterPair);
return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
kNumberOfX87RegIds));
}
private:
- bool IsValidManagedRegister() const {
+ constexpr bool IsValidManagedRegister() const {
return (0 <= id_) && (id_ < kNumberOfRegIds);
}
- int RegId() const {
+ constexpr int RegId() const {
CHECK(!IsNoRegister());
return id_;
}
@@ -188,9 +188,9 @@
friend class ManagedRegister;
- explicit X86_64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
+ explicit constexpr X86_64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
- static X86_64ManagedRegister FromRegId(int reg_id) {
+ static constexpr X86_64ManagedRegister FromRegId(int reg_id) {
X86_64ManagedRegister reg(reg_id);
CHECK(reg.IsValidManagedRegister());
return reg;
@@ -201,7 +201,7 @@
} // namespace x86_64
-inline x86_64::X86_64ManagedRegister ManagedRegister::AsX86_64() const {
+constexpr inline x86_64::X86_64ManagedRegister ManagedRegister::AsX86_64() const {
x86_64::X86_64ManagedRegister reg(id_);
CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
return reg;
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index 3b5b8b5..e9e97b8 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -198,14 +198,14 @@
// types of LHS and RHS.
template <typename LHS, typename RHS>
struct EagerEvaluator {
- EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { }
+ constexpr EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { }
LHS lhs;
RHS rhs;
};
// Helper function for CHECK_xx.
template <typename LHS, typename RHS>
-static inline EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
+static inline constexpr EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
return EagerEvaluator<LHS, RHS>(lhs, rhs);
}