RecordWriteStubs on ARM need to save FP registers

A previous change erroneously stopped saving fp registers for write stubs in
snapshotted code. This CL restores correct behavior, and makes sure code that
saves fp registers checks at runtime for 16 or 32 fp registers. Also fix a bug
in the arm simulator debugger.

BUG=

Review URL: https://codereview.chromium.org/14246032

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14359 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dcb3c630
......@@ -1651,14 +1651,7 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
const Register scratch = r1;
if (save_doubles_ == kSaveFPRegs) {
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(scratch);
__ sub(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters));
for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) {
DwVfpRegister reg = DwVfpRegister::from_code(i);
__ vstr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne);
}
__ SaveFPRegs(sp, scratch);
}
const int argument_count = 1;
const int fp_argument_count = 0;
......@@ -1670,14 +1663,7 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
ExternalReference::store_buffer_overflow_function(masm->isolate()),
argument_count);
if (save_doubles_ == kSaveFPRegs) {
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(scratch);
for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) {
DwVfpRegister reg = DwVfpRegister::from_code(i);
__ vldr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne);
}
__ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters));
__ RestoreFPRegs(sp, scratch);
}
__ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0).
}
......@@ -7194,6 +7180,9 @@ void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
Isolate* isolate) {
StoreBufferOverflowStub stub1(kDontSaveFPRegs);
stub1.GetCode(isolate)->set_is_pregenerated(true);
// Hydrogen code stubs need stub2 at snapshot time.
StoreBufferOverflowStub stub2(kSaveFPRegs);
stub2.GetCode(isolate)->set_is_pregenerated(true);
}
......
......@@ -469,34 +469,14 @@ class RecordWriteStub: public PlatformCodeStub {
void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
masm->stm(db_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
if (mode == kSaveFPRegs) {
// Number of d-regs not known at snapshot time.
ASSERT(!Serializer::enabled());
masm->sub(sp,
sp,
Operand(kDoubleSize * (DwVfpRegister::NumRegisters() - 1)));
// Save all VFP registers except d0.
// TODO(hans): We should probably save d0 too. And maybe use vstm.
for (int i = DwVfpRegister::NumRegisters() - 1; i > 0; i--) {
DwVfpRegister reg = DwVfpRegister::from_code(i);
masm->vstr(reg, MemOperand(sp, (i - 1) * kDoubleSize));
}
masm->SaveFPRegs(sp, scratch0_);
}
}
inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
SaveFPRegsMode mode) {
if (mode == kSaveFPRegs) {
// Number of d-regs not known at snapshot time.
ASSERT(!Serializer::enabled());
// Restore all VFP registers except d0.
// TODO(hans): We should probably restore d0 too. And maybe use vldm.
for (int i = DwVfpRegister::NumRegisters() - 1; i > 0; i--) {
DwVfpRegister reg = DwVfpRegister::from_code(i);
masm->vldr(reg, MemOperand(sp, (i - 1) * kDoubleSize));
}
masm->add(sp,
sp,
Operand(kDoubleSize * (DwVfpRegister::NumRegisters() - 1)));
masm->RestoreFPRegs(sp, scratch0_);
}
masm->ldm(ia_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
}
......
......@@ -36,14 +36,6 @@ namespace v8 {
namespace internal {
static SaveFPRegsMode GetSaveFPRegsMode() {
// We don't need to save floating point regs when generating the snapshot
return CpuFeatures::IsSafeForSnapshot(VFP32DREGS)
? kSaveFPRegs
: kDontSaveFPRegs;
}
class SafepointGenerator : public CallWrapper {
public:
SafepointGenerator(LCodeGen* codegen,
......@@ -251,7 +243,7 @@ bool LCodeGen::GeneratePrologue() {
r0,
r3,
GetLinkRegisterState(),
GetSaveFPRegsMode());
kSaveFPRegs);
}
}
Comment(";;; End allocate local context");
......@@ -3078,7 +3070,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
value,
scratch,
GetLinkRegisterState(),
GetSaveFPRegsMode(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
}
......@@ -4267,7 +4259,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
scratch,
temp,
GetLinkRegisterState(),
GetSaveFPRegsMode(),
kSaveFPRegs,
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
}
......@@ -4286,7 +4278,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
value,
scratch,
GetLinkRegisterState(),
GetSaveFPRegsMode(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
}
......@@ -4301,7 +4293,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
value,
object,
GetLinkRegisterState(),
GetSaveFPRegsMode(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
}
......@@ -4495,7 +4487,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
key,
value,
GetLinkRegisterState(),
GetSaveFPRegsMode(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
check_needed);
}
......
......@@ -837,14 +837,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
// Optionally save all double registers.
if (save_doubles) {
// Check CPU flags for number of registers, setting the Z condition flag.
CheckFor32DRegs(ip);
// Push registers d0-d15, and possibly d16-d31, on the stack.
// If d16-d31 are not pushed, decrease the stack pointer instead.
vstm(db_w, sp, d16, d31, ne);
sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
vstm(db_w, sp, d0, d15);
SaveFPRegs(sp, ip);
// Note that d0 will be accessible at
// fp - 2 * kPointerSize - DwVfpRegister::kMaxNumRegisters * kDoubleSize,
// since the sp slot and code slot were pushed after the fp.
......@@ -905,15 +898,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
const int offset = 2 * kPointerSize;
sub(r3, fp,
Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize));
// Check CPU flags for number of registers, setting the Z condition flag.
CheckFor32DRegs(ip);
// Pop registers d0-d15, and possibly d16-d31, from r3.
// If d16-d31 are not popped, increase r3 instead.
vldm(ia_w, r3, d0, d15);
vldm(ia_w, r3, d16, d31, ne);
add(r3, r3, Operand(16 * kDoubleSize), LeaveCC, eq);
RestoreFPRegs(r3, ip);
}
// Clear top frame.
......@@ -3183,6 +3168,22 @@ void MacroAssembler::CheckFor32DRegs(Register scratch) {
}
void MacroAssembler::SaveFPRegs(Register location, Register scratch) {
CheckFor32DRegs(scratch);
vstm(db_w, location, d16, d31, ne);
sub(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
vstm(db_w, location, d0, d15);
}
void MacroAssembler::RestoreFPRegs(Register location, Register scratch) {
CheckFor32DRegs(scratch);
vldm(ia_w, location, d0, d15);
vldm(ia_w, location, d16, d31, ne);
add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
}
void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
Register first,
Register second,
......
......@@ -997,6 +997,13 @@ class MacroAssembler: public Assembler {
// Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
void CheckFor32DRegs(Register scratch);
// Does a runtime check for 16/32 FP registers. Either way, pushes 32 double
// values to location, saving [d0..(d15|d31)].
void SaveFPRegs(Register location, Register scratch);
// Does a runtime check for 16/32 FP registers. Either way, pops 32 double
// values to location, restoring [d0..(d15|d31)].
void RestoreFPRegs(Register location, Register scratch);
// ---------------------------------------------------------------------------
// Runtime calls
......
......@@ -331,7 +331,7 @@ void ArmDebugger::Debug() {
PrintF("\n");
}
}
for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
dvalue = GetVFPDoubleRegisterValue(i);
uint64_t as_words = BitCast<uint64_t>(dvalue);
PrintF("%3s: %f 0x%08x %08x\n",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment