| Index: src/arm/debug-arm.cc
 | 
| ===================================================================
 | 
| --- src/arm/debug-arm.cc	(revision 5352)
 | 
| +++ src/arm/debug-arm.cc	(working copy)
 | 
| @@ -130,21 +130,30 @@
 | 
|  
 | 
|  
 | 
|  static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 | 
| -                                          RegList pointer_regs) {
 | 
| -  // Save the content of all general purpose registers in memory. This copy in
 | 
| -  // memory is later pushed onto the JS expression stack for the fake JS frame
 | 
| -  // generated and also to the C frame generated on top of that. In the JS
 | 
| -  // frame ONLY the registers containing pointers will be pushed on the
 | 
| -  // expression stack. This causes the GC to update these  pointers so that
 | 
| -  // they will have the correct value when returning from the debugger.
 | 
| -  __ SaveRegistersToMemory(kJSCallerSaved);
 | 
| -
 | 
| +                                          RegList object_regs,
 | 
| +                                          RegList non_object_regs) {
 | 
|    __ EnterInternalFrame();
 | 
|  
 | 
| -  // Store the registers containing object pointers on the expression stack to
 | 
| -  // make sure that these are correctly updated during GC.
 | 
| -  // Use sp as base to push.
 | 
| -  __ CopyRegistersFromMemoryToStack(sp, pointer_regs);
 | 
| +  // Store the registers containing live values on the expression stack to
 | 
| +  // make sure that these are correctly updated during GC. Non object values
 | 
| +  // are stored as a smi causing it to be untouched by GC.
 | 
| +  ASSERT((object_regs & ~kJSCallerSaved) == 0);
 | 
| +  ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
 | 
| +  ASSERT((object_regs & non_object_regs) == 0);
 | 
| +  if ((object_regs | non_object_regs) != 0) {
 | 
| +    for (int i = 0; i < kNumJSCallerSaved; i++) {
 | 
| +      int r = JSCallerSavedCode(i);
 | 
| +      Register reg = { r };
 | 
| +      if ((non_object_regs & (1 << r)) != 0) {
 | 
| +        if (FLAG_debug_code) {
 | 
| +          __ tst(reg, Operand(0xc0000000));
 | 
| +          __ Assert(eq, "Unable to encode value as smi");
 | 
| +        }
 | 
| +        __ mov(reg, Operand(reg, LSL, kSmiTagSize));
 | 
| +      }
 | 
| +    }
 | 
| +    __ stm(db_w, sp, object_regs | non_object_regs);
 | 
| +  }
 | 
|  
 | 
|  #ifdef DEBUG
 | 
|    __ RecordComment("// Calling from debug break to runtime - come in - over");
 | 
| @@ -152,19 +161,27 @@
 | 
|    __ mov(r0, Operand(0));  // no arguments
 | 
|    __ mov(r1, Operand(ExternalReference::debug_break()));
 | 
|  
 | 
| -  CEntryStub ceb(1, ExitFrame::MODE_DEBUG);
 | 
| +  CEntryStub ceb(1);
 | 
|    __ CallStub(&ceb);
 | 
|  
 | 
| -  // Restore the register values containing object pointers from the expression
 | 
| -  // stack in the reverse order as they where pushed.
 | 
| -  // Use sp as base to pop.
 | 
| -  __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);
 | 
| +  // Restore the register values from the expression stack.
 | 
| +  if ((object_regs | non_object_regs) != 0) {
 | 
| +    __ ldm(ia_w, sp, object_regs | non_object_regs);
 | 
| +    for (int i = 0; i < kNumJSCallerSaved; i++) {
 | 
| +      int r = JSCallerSavedCode(i);
 | 
| +      Register reg = { r };
 | 
| +      if ((non_object_regs & (1 << r)) != 0) {
 | 
| +        __ mov(reg, Operand(reg, LSR, kSmiTagSize));
 | 
| +      }
 | 
| +      if (FLAG_debug_code &&
 | 
| +          (((object_regs |non_object_regs) & (1 << r)) == 0)) {
 | 
| +        __ mov(reg, Operand(kDebugZapValue));
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
|  
 | 
|    __ LeaveInternalFrame();
 | 
|  
 | 
| -  // Finally restore all registers.
 | 
| -  __ RestoreRegistersFromMemory(kJSCallerSaved);
 | 
| -
 | 
|    // Now that the break point has been handled, resume normal execution by
 | 
|    // jumping to the target address intended by the caller and that was
 | 
|    // overwritten by the address of DebugBreakXXX.
 | 
| @@ -184,7 +201,7 @@
 | 
|    // -----------------------------------
 | 
|    // Registers r0 and r2 contain objects that need to be pushed on the
 | 
|    // expression stack of the fake JS frame.
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
 | 
| +  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -198,7 +215,7 @@
 | 
|    // -----------------------------------
 | 
|    // Registers r0, r1, and r2 contain objects that need to be pushed on the
 | 
|    // expression stack of the fake JS frame.
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit());
 | 
| +  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -206,9 +223,8 @@
 | 
|    // ---------- S t a t e --------------
 | 
|    //  -- lr     : return address
 | 
|    //  -- r0     : key
 | 
| -  //  -- sp[0]  : key
 | 
| -  //  -- sp[4]  : receiver
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit());
 | 
| +  //  -- r1     : receiver
 | 
| +  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -218,24 +234,24 @@
 | 
|    //  -- r1     : key
 | 
|    //  -- r2     : receiver
 | 
|    //  -- lr     : return address
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit());
 | 
| +  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
 | 
|    // Calling convention for IC call (from ic-arm.cc)
 | 
|    // ----------- S t a t e -------------
 | 
| -  //  -- r2: name
 | 
| +  //  -- r2     : name
 | 
|    // -----------------------------------
 | 
| -  Generate_DebugBreakCallHelper(masm, r2.bit());
 | 
| +  Generate_DebugBreakCallHelper(masm, r2.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
 | 
| -  // In places other than IC call sites it is expected that r0 is TOS which
 | 
| -  // is an object - this is not generally the case so this should be used with
 | 
| -  // care.
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit());
 | 
| +  // Calling convention for construct call (from builtins-arm.cc)
 | 
| +  //  -- r0     : number of arguments (not smi)
 | 
| +  //  -- r1     : constructor function
 | 
| +  Generate_DebugBreakCallHelper(masm, r1.bit(), r0.bit());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -243,7 +259,7 @@
 | 
|    // In places other than IC call sites it is expected that r0 is TOS which
 | 
|    // is an object - this is not generally the case so this should be used with
 | 
|    // care.
 | 
| -  Generate_DebugBreakCallHelper(masm, r0.bit());
 | 
| +  Generate_DebugBreakCallHelper(masm, r0.bit(), 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -251,7 +267,7 @@
 | 
|    // ----------- S t a t e -------------
 | 
|    //  No registers used on entry.
 | 
|    // -----------------------------------
 | 
| -  Generate_DebugBreakCallHelper(masm, 0);
 | 
| +  Generate_DebugBreakCallHelper(masm, 0, 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -273,7 +289,7 @@
 | 
|  void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
 | 
|    // In the places where a debug break slot is inserted no registers can contain
 | 
|    // object pointers.
 | 
| -  Generate_DebugBreakCallHelper(masm, 0);
 | 
| +  Generate_DebugBreakCallHelper(masm, 0, 0);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |