Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: src/arm/macro-assembler-arm.cc

Issue 194793002: [v8-dev] ARM: safepoints frame optimization (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/arm/macro-assembler-arm.cc
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 437b7312c718f0aa3b936c0176b49d4724049958..6d3c9676adedb8acd8d1fb223481f84fd8b9772c 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -624,72 +624,134 @@ void MacroAssembler::PopFixedFrame(Register marker_reg) {
// Push and pop all registers that can hold pointers.
void MacroAssembler::PushSafepointRegisters() {
- // Safepoints expect a block of contiguous register values starting with r0:
- ASSERT(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters);
- // Safepoints expect a block of kNumSafepointRegisters values on the
- // stack, so adjust the stack for unsaved registers.
- const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
- ASSERT(num_unsaved >= 0);
- sub(sp, sp, Operand(num_unsaved * kPointerSize));
- stm(db_w, sp, kSafepointSavedRegisters);
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT(registers_mask() != kRegListEmpty);
+ stm(db_w, sp, registers_mask());
}
void MacroAssembler::PopSafepointRegisters() {
- const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
- ldm(ia_w, sp, kSafepointSavedRegisters);
- add(sp, sp, Operand(num_unsaved * kPointerSize));
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT(registers_mask() != kRegListEmpty);
+ ldm(ia_w, sp, registers_mask());
}
void MacroAssembler::PushSafepointRegistersAndDoubles() {
- // Number of d-regs not known at snapshot time.
- ASSERT(!Serializer::enabled());
PushSafepointRegisters();
- // Only save allocatable registers.
- ASSERT(kScratchDoubleReg.is(d15) && kDoubleRegZero.is(d14));
- ASSERT(DwVfpRegister::NumReservedRegisters() == 2);
- if (CpuFeatures::IsSupported(VFP32DREGS)) {
- vstm(db_w, sp, d16, d31);
+ // The vstm instruction can only save up to 16 doubles. So we save all the
+ // doubles registers with up to 2 instructions.
+ RegList high_mask = double_registers_mask() & 0xffff0000;
+ if (high_mask != 0) {
+ for (int i = LowDwVfpRegister::kMaxNumLowRegisters;
+ i < DoubleRegister::NumRegisters();
+ i++) {
+ if ((high_mask & (1 << i)) != 0) {
+ int last = i + CompilerIntrinsics::CountSetBits(high_mask) - 1;
+ // When double_registers_mask has been initialized, we ensured that
+ // there is no holes between the first and the last high registers.
+ ASSERT(((((1 << last) - 1) | (1 << last)) & ~((1 << i) - 1)) ==
+ high_mask);
+ vstm(db_w, sp, DwVfpRegister::from_code(i),
+ DwVfpRegister::from_code(last));
+ break;
+ }
+ }
+ }
+ RegList low_mask = double_registers_mask() & 0xffff;
+ if (low_mask != 0) {
+ for (int i = 0; i < LowDwVfpRegister::kMaxNumLowRegisters; i++) {
+ if ((low_mask & (1 << i)) != 0) {
+ int last = i + CompilerIntrinsics::CountSetBits(low_mask) - 1;
+ // When double_registers_mask has been initialized, we ensured that
+ // there is no holes between the first and the last low registers.
+ ASSERT(((((1 << last) - 1) | (1 << last)) & ~((1 << i) - 1)) ==
+ low_mask);
+ vstm(db_w, sp, LowDwVfpRegister::from_code(i),
+ LowDwVfpRegister::from_code(last));
+ break;
+ }
+ }
}
- vstm(db_w, sp, d0, d13);
}
void MacroAssembler::PopSafepointRegistersAndDoubles() {
- // Number of d-regs not known at snapshot time.
- ASSERT(!Serializer::enabled());
- // Only save allocatable registers.
- ASSERT(kScratchDoubleReg.is(d15) && kDoubleRegZero.is(d14));
- ASSERT(DwVfpRegister::NumReservedRegisters() == 2);
- vldm(ia_w, sp, d0, d13);
- if (CpuFeatures::IsSupported(VFP32DREGS)) {
- vldm(ia_w, sp, d16, d31);
+ // The vldm instruction can only restore up to 16 doubles. So we save all the
+ // doubles registers with up to 2 instructions.
+ RegList low_mask = double_registers_mask() & 0xffff;
+ if (low_mask != 0) {
+ for (int i = 0; i < LowDwVfpRegister::kMaxNumLowRegisters; i++) {
+ if ((low_mask & (1 << i)) != 0) {
+ int last = i + CompilerIntrinsics::CountSetBits(low_mask) - 1;
+ // When double_registers_mask has been initialized, we ensured that
+ // there is no holes between the first and the last low registers.
+ ASSERT(((((1 << last) - 1) | (1 << last)) & ~((1 << i) - 1)) ==
+ low_mask);
+ vldm(ia_w, sp, LowDwVfpRegister::from_code(i),
+ LowDwVfpRegister::from_code(last));
+ break;
+ }
+ }
+ }
+ RegList high_mask = double_registers_mask() & 0xffff0000;
+ if (high_mask != 0) {
+ for (int i = LowDwVfpRegister::kMaxNumLowRegisters;
+ i < DoubleRegister::NumRegisters();
+ i++) {
+ if ((high_mask & (1 << i)) != 0) {
+ int last = i + CompilerIntrinsics::CountSetBits(high_mask) - 1;
+ // When double_registers_mask has been initialized, we ensured that
+ // there is no holes between the first and the last high registers.
+ ASSERT(((((1 << last) - 1) | (1 << last)) & ~((1 << i) - 1)) ==
+ high_mask);
+ vldm(ia_w, sp, DwVfpRegister::from_code(i),
+ DwVfpRegister::from_code(last));
+ break;
+ }
+ }
}
PopSafepointRegisters();
}
void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
Register dst) {
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT((registers_mask() & dst.bit()) != kRegListEmpty);
str(src, SafepointRegistersAndDoublesSlot(dst));
}
void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT((registers_mask() & dst.bit()) != kRegListEmpty);
str(src, SafepointRegisterSlot(dst));
}
void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT((registers_mask() & dst.bit()) != kRegListEmpty);
ldr(dst, SafepointRegisterSlot(src));
}
int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
+ // This function must be called from LCodeGen::GenerateCode where
+ // registers_mask and double_registers_mask are set.
+ ASSERT((registers_mask() & (1 << reg_code)) != kRegListEmpty);
// The registers are pushed starting with the highest encoding,
// which means that lowest encodings are closest to the stack pointer.
ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
- return reg_code;
+ ASSERT((registers_mask() & (1 << reg_code)) != 0);
+ // Only count registers below reg_code.
+ return
+ CompilerIntrinsics::CountSetBits(registers_mask() & ((1 << reg_code) - 1));
}
@@ -699,10 +761,9 @@ MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
- // Number of d-regs not known at snapshot time.
- ASSERT(!Serializer::enabled());
// General purpose registers are pushed last on the stack.
- int doubles_size = DwVfpRegister::NumAllocatableRegisters() * kDoubleSize;
+ int doubles_size =
+ CompilerIntrinsics::CountSetBits(double_registers_mask()) * kDoubleSize;
int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
return MemOperand(sp, doubles_size + register_offset);
}
« src/arm/assembler-arm.h ('K') | « src/arm/macro-assembler-arm.h ('k') | src/frames.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698