RecordWriteStubs on ARM need to save FP registers
authormvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Apr 2013 16:01:57 +0000 (16:01 +0000)
committermvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Apr 2013 16:01:57 +0000 (16:01 +0000)
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

src/arm/code-stubs-arm.cc
src/arm/code-stubs-arm.h
src/arm/lithium-codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/arm/simulator-arm.cc

index 8ad3089..d232a88 100644 (file)
@@ -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);
 }
 
 
index 75cbf65..794fb93 100644 (file)
@@ -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());
     }
index e220678..f47e7e8 100644 (file)
@@ -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);
   }
index 616d02d..3f8d922 100644 (file)
@@ -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,
index f9f672b..75194a8 100644 (file)
@@ -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
index 7033390..036fd7f 100644 (file)
@@ -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",