summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2015-01-20 16:06:43 +0100
committerNicolas Geoffray <ngeoffray@google.com>2015-03-03 11:22:00 +0000
commit7cde48c56df5b57aed524cce44c902bc720f2d6c (patch)
treeb9b9e33b29f46bfe0c2da89c7e3e87c8ee419ccc /compiler
parent4b39eeea67b0fecf21588d7b00e92eb844014c24 (diff)
downloadandroid_art-7cde48c56df5b57aed524cce44c902bc720f2d6c.tar.gz
android_art-7cde48c56df5b57aed524cce44c902bc720f2d6c.tar.bz2
android_art-7cde48c56df5b57aed524cce44c902bc720f2d6c.zip
Stack support for Optimizing compiler
Allows to read/write DEX registers from physical register or stack location when the method is compiled with the Optimizing compiler. Required fixing arm and arm64 JNI compiler by saving floating point registers. Bug: 18547544 Change-Id: I401579f251d1c0a130f6cf4a93a960cdcd7518f5
Diffstat (limited to 'compiler')
-rw-r--r--compiler/jni/quick/arm/calling_convention_arm.cc16
-rw-r--r--compiler/jni/quick/arm/calling_convention_arm.h4
-rw-r--r--compiler/jni/quick/arm64/calling_convention_arm64.cc17
-rw-r--r--compiler/utils/arm/assembler_arm.cc40
-rw-r--r--compiler/utils/arm64/assembler_arm64.cc37
-rw-r--r--compiler/utils/arm64/constants_arm64.h2
6 files changed, 100 insertions, 16 deletions
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 669c3bb716..d3690b271f 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -31,6 +31,10 @@ static const SRegister kHFSArgumentRegisters[] = {
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
};
@@ -226,6 +230,10 @@ ArmJniCallingConvention::ArmJniCallingConvention(bool is_static, bool is_synchro
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 {
@@ -235,6 +243,14 @@ uint32_t ArmJniCallingConvention::CoreSpillMask() const {
return result;
}
+uint32_t ArmJniCallingConvention::FpSpillMask() const {
+ uint32_t result = 0;
+ for (size_t i = 0; i < arraysize(kHFSCalleeSaveRegisters); ++i) {
+ result |= (1 << kHFSCalleeSaveRegisters[i]);
+ }
+ return result;
+}
+
ManagedRegister ArmJniCallingConvention::ReturnScratchRegister() const {
return ArmManagedRegister::FromCoreRegister(R2);
}
diff --git a/compiler/jni/quick/arm/calling_convention_arm.h b/compiler/jni/quick/arm/calling_convention_arm.h
index 604ce1c821..dbecb8eb95 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.h
+++ b/compiler/jni/quick/arm/calling_convention_arm.h
@@ -63,9 +63,7 @@ class ArmJniCallingConvention FINAL : public JniCallingConvention {
}
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;
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index b9c81787f0..05eb80a51a 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -38,6 +38,10 @@ static const SRegister kSArgumentRegisters[] = {
S0, S1, S2, S3, S4, S5, S6, S7
};
+static const DRegister kDCalleeSaveRegisters[] = {
+ D8, D9, D10, D11, D12, D13, D14, D15
+};
+
// Calling convention
ManagedRegister Arm64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
return Arm64ManagedRegister::FromXRegister(X20); // saved on entry restored on exit
@@ -166,6 +170,10 @@ Arm64JniCallingConvention::Arm64JniCallingConvention(bool is_static, bool is_syn
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X28));
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X29));
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X30));
+
+ for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
+ callee_save_regs_.push_back(Arm64ManagedRegister::FromDRegister(kDCalleeSaveRegisters[i]));
+ }
}
uint32_t Arm64JniCallingConvention::CoreSpillMask() const {
@@ -184,10 +192,11 @@ uint32_t Arm64JniCallingConvention::CoreSpillMask() const {
}
uint32_t Arm64JniCallingConvention::FpSpillMask() const {
- // Compute spill mask to agree with callee saves initialized in the constructor
- // Note: All callee-save fp registers will be preserved by aapcs64. And they are not used
- // in the jni method.
- return 0;
+ uint32_t result = 0;
+ for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
+ result |= (1 << kDCalleeSaveRegisters[i]);
+ }
+ return result;
}
ManagedRegister Arm64JniCallingConvention::ReturnScratchRegister() const {
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index a52e6eb30f..a02191bc13 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -385,12 +385,24 @@ void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
// Push callee saves and link register.
RegList push_list = 1 << LR;
size_t pushed_values = 1;
+ int32_t min_s = kNumberOfSRegisters;
+ int32_t max_s = -1;
for (size_t i = 0; i < callee_save_regs.size(); i++) {
- Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
- push_list |= 1 << reg;
- pushed_values++;
+ if (callee_save_regs.at(i).AsArm().IsCoreRegister()) {
+ Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
+ push_list |= 1 << reg;
+ pushed_values++;
+ } else {
+ CHECK(callee_save_regs.at(i).AsArm().IsSRegister());
+ min_s = std::min(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), min_s);
+ max_s = std::max(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), max_s);
+ }
}
PushList(push_list);
+ if (max_s != -1) {
+ pushed_values += 1 + max_s - min_s;
+ vpushs(static_cast<SRegister>(min_s), 1 + max_s - min_s);
+ }
// Increase frame to required size.
CHECK_GT(frame_size, pushed_values * kFramePointerSize); // Must at least have space for Method*.
@@ -427,10 +439,22 @@ void ArmAssembler::RemoveFrame(size_t frame_size,
// Compute callee saves to pop and PC.
RegList pop_list = 1 << PC;
size_t pop_values = 1;
+ int32_t min_s = kNumberOfSRegisters;
+ int32_t max_s = -1;
for (size_t i = 0; i < callee_save_regs.size(); i++) {
- Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
- pop_list |= 1 << reg;
- pop_values++;
+ if (callee_save_regs.at(i).AsArm().IsCoreRegister()) {
+ Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
+ pop_list |= 1 << reg;
+ pop_values++;
+ } else {
+ CHECK(callee_save_regs.at(i).AsArm().IsSRegister());
+ min_s = std::min(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), min_s);
+ max_s = std::max(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), max_s);
+ }
+ }
+
+ if (max_s != -1) {
+ pop_values += 1 + max_s - min_s;
}
// Decrease frame to start of callee saves.
@@ -438,6 +462,10 @@ void ArmAssembler::RemoveFrame(size_t frame_size,
size_t adjust = frame_size - (pop_values * kFramePointerSize);
DecreaseFrameSize(adjust);
+ if (max_s != -1) {
+ vpops(static_cast<SRegister>(min_s), 1 + max_s - min_s);
+ }
+
// Pop callee saves and PC.
PopList(pop_list);
}
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 21014c8bba..58c73674da 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -639,6 +639,7 @@ void Arm64Assembler::EmitExceptionPoll(Arm64Exception *exception) {
}
constexpr size_t kFramePointerSize = 8;
+constexpr unsigned int kJniRefSpillRegsSize = 11 + 8;
void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
const std::vector<ManagedRegister>& callee_save_regs,
@@ -648,7 +649,7 @@ void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
// TODO: *create APCS FP - end of FP chain;
// *add support for saving a different set of callee regs.
- // For now we check that the size of callee regs vector is 11.
+ // For now we check that the size of callee regs vector is 11 core registers and 8 fp registers.
CHECK_EQ(callee_save_regs.size(), kJniRefSpillRegsSize);
// Increase frame to required size - must be at least space to push StackReference<Method>.
CHECK_GT(frame_size, kJniRefSpillRegsSize * kFramePointerSize);
@@ -682,6 +683,23 @@ void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
reg_offset -= 8;
StoreToOffset(X20, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D15, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D14, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D13, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D12, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D11, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D10, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D9, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D8, SP, reg_offset);
+
// Move TR(Caller saved) to ETR(Callee saved). The original (ETR)X21 has been saved on stack.
// This way we make sure that TR is not trashed by native code.
___ Mov(reg_x(ETR), reg_x(TR));
@@ -753,6 +771,23 @@ void Arm64Assembler::RemoveFrame(size_t frame_size, const std::vector<ManagedReg
reg_offset -= 8;
LoadFromOffset(X20, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D15, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D14, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D13, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D12, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D11, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D10, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D9, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D8, SP, reg_offset);
+
// Decrease frame size to start of callee saved regs.
DecreaseFrameSize(frame_size);
diff --git a/compiler/utils/arm64/constants_arm64.h b/compiler/utils/arm64/constants_arm64.h
index ffb54d322f..01e8be9de6 100644
--- a/compiler/utils/arm64/constants_arm64.h
+++ b/compiler/utils/arm64/constants_arm64.h
@@ -29,8 +29,6 @@
namespace art {
namespace arm64 {
-constexpr unsigned int kJniRefSpillRegsSize = 11;
-
constexpr size_t kArm64BaseBufferSize = 4096;
} // namespace arm64