Commit 6fa44eb9 authored by peter.rybin@gmail.com's avatar peter.rybin@gmail.com

LiveEdit: implement stack manipulations for x64

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5264 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4673c5dc
......@@ -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
......
......@@ -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;
......
......@@ -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();
......
......@@ -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
......
......@@ -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.";
}
......
......@@ -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
......
......@@ -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() {
......
......@@ -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
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