Some debugging support fixes on ARM simulator port.
authorfeng@chromium.org <feng@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Nov 2008 17:44:16 +0000 (17:44 +0000)
committerfeng@chromium.org <feng@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Nov 2008 17:44:16 +0000 (17:44 +0000)
1) Let SaveContext remember the top JS frame stack pointer so it works in simulator where C stack and JS stack are separated;
2) Use the new calling convension in %DebugBreakCallHelper function;

Review URL: http://codereview.chromium.org/10663

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@774 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/builtins-arm.cc
src/runtime.cc
src/top.h

index c1b654f4ffb7f1cc8e41a6aced1c7958e9db3ef0..503a2d38ff69aa3d80d0bc70e6642c4dd6da1cb6 100644 (file)
@@ -663,36 +663,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
   // they will have the correct value when returning from the debugger.
   __ SaveRegistersToMemory(kJSCallerSaved);
 
-  // This is a direct call from a debug breakpoint. To build a fake JS frame
-  // with no parameters push a function and a receiver, keep the current
-  // return address in lr, and set r0 to zero.
-  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
-  __ ldr(r3, MemOperand(ip));
-  __ mov(r0, Operand(0));  // Null receiver and zero arguments.
-  __ stm(db_w, sp, r0.bit() | r3.bit());  // push function and receiver
-
-  // r0: number of arguments.
-  // What follows is an inlined version of EnterJSFrame(0, 0).
-  // It needs to be kept in sync if any calling conventions are changed.
-
-  // Compute parameter pointer before making changes
-  // ip = sp + kPointerSize*(args_len+1);  // +1 for receiver, args_len == 0
-  __ add(ip, sp, Operand(kPointerSize));
-
-  __ mov(r3, Operand(0));  // args_len to be saved
-  __ mov(r2, Operand(cp));  // context to be saved
-
-  // push in reverse order: context (r2), args_len (r3), caller_pp, caller_fp,
-  // sp_on_exit (ip == pp), return address
-  __ stm(db_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit() |
-         ip.bit() | lr.bit());
-  // Setup new frame pointer.
-  __ add(fp, sp, Operand(-StandardFrameConstants::kContextOffset));
-  __ mov(pp, Operand(ip));  // setup new parameter pointer
-  // r0 is already set to 0 as spare slot to store caller code object during GC
-  __ push(r0);  // code pointer
-
-  // Inlined EnterJSFrame ends here.
+  __ EnterInternalFrame();
 
   // Store the registers containing object pointers on the expression stack to
   // make sure that these are correctly updated during GC.
@@ -702,7 +673,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 #ifdef DEBUG
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
-  // r0 is already 0, no arguments
+  __ mov(r0, Operand(0));  // no arguments
   __ mov(r1, Operand(ExternalReference::debug_break()));
 
   CEntryDebugBreakStub ceb;
@@ -713,14 +684,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
   // Use sp as base to pop.
   __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);
 
-  // What follows is an inlined version of ExitJSFrame(0).
-  // It needs to be kept in sync if any calling conventions are changed.
-  // NOTE: loading the return address to lr and discarding the (fake) function
-  //       is an addition to this inlined copy.
-
-  __ mov(sp, Operand(fp));  // respect ABI stack constraint
-  __ ldm(ia, sp, pp.bit() | fp.bit() | sp.bit() | lr.bit());
-  __ pop();  // discard fake function
+  __ LeaveInternalFrame();
 
   // Inlined ExitJSFrame ends here.
 
index 1d40e4cd4bd8355a3630644c92fdfbf7e015f734..c336077885243c6ce0b5d024e0d11017af11540e 100644 (file)
@@ -4797,9 +4797,10 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
   SaveContext* save = Top::save_context();
-  while (save != NULL && reinterpret_cast<Address>(save) < it.frame()->sp()) {
+  while (save != NULL && !save->below(it.frame())) {
     save = save->prev();
   }
+  ASSERT(save != NULL);
 
   // Get the frame id.
   Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
@@ -5299,7 +5300,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
   SaveContext* save = Top::save_context();
-  while (save != NULL && reinterpret_cast<Address>(save) < frame->sp()) {
+  while (save != NULL && !save->below(frame)) {
     save = save->prev();
   }
   ASSERT(save != NULL);
index 866487c83592279a36f6ba15f12342b25721566f..431f05e8ff4de84378bec619f9224e32e42694dd 100644 (file)
--- a/src/top.h
+++ b/src/top.h
@@ -312,6 +312,10 @@ class SaveContext BASE_EMBEDDED {
 #endif
       prev_(Top::save_context()) {
     Top::set_save_context(this);
+
+    // If there is no JS frame under the current C frame, use the value 0.
+    JavaScriptFrameIterator it;
+    js_sp_ = it.done() ? 0 : it.frame()->sp();
   }
 
   ~SaveContext() {
@@ -322,12 +326,18 @@ class SaveContext BASE_EMBEDDED {
   Handle<Context> context() { return context_; }
   SaveContext* prev() { return prev_; }
 
+  // Returns true if this save context is below a given JavaScript frame.
+  bool below(JavaScriptFrame* frame) {
+    return (js_sp_ == 0) || (frame->sp() < js_sp_);
+  }
+
  private:
   Handle<Context> context_;
 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
   Handle<Context> dummy_;
 #endif
   SaveContext* prev_;
+  Address js_sp_;  // The top JS frame's sp when saving context.
 };