LiveEdit: implement stack manipulations for x64
authorpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Aug 2010 13:54:28 +0000 (13:54 +0000)
committerpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Aug 2010 13:54:28 +0000 (13:54 +0000)
Review URL: http://codereview.chromium.org/3120011

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

src/arm/debug-arm.cc
src/debug.cc
src/debug.h
src/ia32/debug-ia32.cc
src/liveedit.cc
src/mips/debug-mips.cc
src/x64/debug-x64.cc
test/mjsunit/mjsunit.status

index e87d265..3a94845 100644 (file)
@@ -293,15 +293,11 @@ void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on arm");
 }
 
+const bool Debug::kFrameDropperSupported = false;
+
 #undef __
 
 
-Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
-                                       Handle<Code> code) {
-  UNREACHABLE();
-  return NULL;
-}
-const int Debug::kFrameDropperFrameSize = -1;
 
 #endif  // ENABLE_DEBUGGER_SUPPORT
 
index dbf9df9..c13c8c9 100644 (file)
@@ -582,6 +582,35 @@ int Debug::ArchiveSpacePerThread() {
 }
 
 
+// Frame structure (conforms InternalFrame structure):
+//   -- code
+//   -- SMI maker
+//   -- function (slot is called "context")
+//   -- frame base
+Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
+                                       Handle<Code> code) {
+  ASSERT(bottom_js_frame->is_java_script());
+
+  Address fp = bottom_js_frame->fp();
+
+  // Move function pointer into "context" slot.
+  Memory::Object_at(fp + StandardFrameConstants::kContextOffset) =
+      Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset);
+
+  Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code;
+  Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) =
+      Smi::FromInt(StackFrame::INTERNAL);
+
+  return reinterpret_cast<Object**>(&Memory::Object_at(
+      fp + StandardFrameConstants::kContextOffset));
+}
+
+const int Debug::kFrameDropperFrameSize = 4;
+
+
+
+
+
 // Default break enabled.
 bool Debug::disable_break_ = false;
 
index b6aba5a..98d1919 100644 (file)
@@ -400,6 +400,11 @@ class Debug {
   static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
   static void GenerateSlotDebugBreak(MacroAssembler* masm);
   static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
+
+  // FrameDropper is a code replacement for a JavaScript frame with possibly
+  // several frames above.
+  // There is no calling conventions here, because it never actually gets
+  // called, it only gets returned to.
   static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
 
   // Called from stub-cache.cc.
@@ -431,13 +436,14 @@ class Debug {
   // the value that is called 'restarter_frame_function_pointer'. The value
   // at this address (possibly updated by GC) may be used later when preparing
   // 'step in' operation.
-  // The implementation is architecture-specific.
-  // TODO(LiveEdit): consider reviewing it as architecture-independent.
   static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
                                          Handle<Code> code);
 
   static const int kFrameDropperFrameSize;
 
+  // Architecture-specific constant.
+  static const bool kFrameDropperSupported;
+
  private:
   static bool CompileDebuggerScript(int index);
   static void ClearOneShot();
index 114bdd7..b57cf3d 100644 (file)
@@ -254,15 +254,6 @@ void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
 }
 
 
-// FrameDropper is a code replacement for a JavaScript frame with possibly
-// several frames above.
-// There is no calling conventions here, because it never actually gets called,
-// it only gets returned to.
-// Frame structure (conforms InternalFrame structure):
-//   -- code
-//   -- SMI maker
-//   -- function (slot is called "context")
-//   -- frame base
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   ExternalReference restarter_frame_function_slot =
       ExternalReference(Debug_Address::RestarterFrameFunctionPointer());
@@ -286,30 +277,9 @@ void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   __ jmp(Operand(edx));
 }
 
-#undef __
-
-
-// TODO(LiveEdit): consider making it platform-independent.
-// TODO(LiveEdit): use more named constants instead of numbers.
-Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
-                                       Handle<Code> code) {
-  ASSERT(bottom_js_frame->is_java_script());
-
-  Address fp = bottom_js_frame->fp();
-
-  // Move function pointer into slot that is called referenced
-  // as StandardFrame::context()
-  Memory::Object_at(fp - 1 * kPointerSize) =
-      Memory::Object_at(fp - 2 * kPointerSize);
-
-  Memory::Object_at(fp - 3 * kPointerSize) = *code;
-  Memory::Object_at(fp - 2 * kPointerSize) = Smi::FromInt(StackFrame::INTERNAL);
-
-  return reinterpret_cast<Object**>(&Memory::Object_at(fp - 1 * kPointerSize));
-}
-
-const int Debug::kFrameDropperFrameSize = 4;
+const bool Debug::kFrameDropperSupported = true;
 
+#undef __
 
 #endif  // ENABLE_DEBUGGER_SUPPORT
 
index 2ac24fb..769ac35 100644 (file)
@@ -1206,7 +1206,7 @@ static const char* DropFrames(Vector<StackFrame*> frames,
                               int bottom_js_frame_index,
                               Debug::FrameDropMode* mode,
                               Object*** restarter_frame_function_pointer) {
-  if (Debug::kFrameDropperFrameSize < 0) {
+  if (!Debug::kFrameDropperSupported) {
     return "Stack manipulations are not supported in this architecture.";
   }
 
index 47961fa..b8ae68e 100644 (file)
@@ -114,15 +114,10 @@ void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   masm->Abort("LiveEdit frame dropping is not supported on mips");
 }
 
-#undef __
 
+const bool Debug::kFrameDropperSupported = false;
 
-Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
-                                       Handle<Code> code) {
-  UNREACHABLE();
-  return NULL;
-}
-const int Debug::kFrameDropperFrameSize = -1;
+#undef __
 
 
 #endif  // ENABLE_DEBUGGER_SUPPORT
index 2aa77e7..d5b7e77 100644 (file)
@@ -202,23 +202,39 @@ void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
 
 
 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on x64");
+  masm->ret(0);
 }
 
 
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on x64");
+  ExternalReference restarter_frame_function_slot =
+      ExternalReference(Debug_Address::RestarterFrameFunctionPointer());
+  __ movq(rax, restarter_frame_function_slot);
+  __ movq(Operand(rax, 0), Immediate(0));
+
+  // We do not know our frame height, but set rsp based on rbp.
+  __ lea(rsp, Operand(rbp, -1 * kPointerSize));
+
+  __ pop(rdi);  // Function.
+  __ pop(rbp);
+
+  // Load context from the function.
+  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
+
+  // Get function code.
+  __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+  __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+  __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
+
+  // Re-run JSFunction, rdi is function, rsi is context.
+  __ jmp(rdx);
 }
 
+const bool Debug::kFrameDropperSupported = true;
+
 #undef __
 
 
-Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
-                                       Handle<Code> code) {
-  UNREACHABLE();
-  return NULL;
-}
-const int Debug::kFrameDropperFrameSize = -1;
 
 
 void BreakLocationIterator::ClearDebugBreakAtReturn() {
index ceb5e62..3c8cbdb 100644 (file)
@@ -72,8 +72,4 @@ debug-liveedit-check-stack: SKIP
 # Skip all tests on MIPS.
 *: SKIP
 
-[ $arch == x64 ]
-# Stack manipulations in LiveEdit is implemented for ia32 only.
-debug-liveedit-check-stack: SKIP
-