Commit 9515f7ed authored by bjaideep's avatar bjaideep Committed by Commit bot

PPC/s390: [liveedit] reimplement frame restarting.

Port 3f47c63d

Original Commit Message:

    Previously, when restarting a frame, we would rewrite all frames
    between the debugger activation and the frame to restart to squash
    them, and replace the return address with that of a builtin to
    leave that rewritten frame, and restart the function by calling it.

    We now simply remember the frame to drop to, and upon returning
    from the debugger, we check whether to drop the frame, load the
    new FP, and restart the function.

R=yangguo@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:5587
LOG=N

Review-Url: https://codereview.chromium.org/2663453004
Cr-Commit-Position: refs/heads/master@{#42748}
parent 82ef9f75
......@@ -77,14 +77,6 @@ void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Load padding words on stack.
__ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue));
for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
__ push(ip);
}
__ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
__ push(ip);
// Push arguments for DebugBreak call.
if (mode == SAVE_RESULT_REGISTER) {
// Break on return.
......@@ -111,50 +103,47 @@ void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
}
}
}
// Don't bother removing padding bytes pushed on the stack
// as the frame is going to be restored right away.
// Leave the internal frame.
}
// 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.
ExternalReference after_break_target =
ExternalReference::debug_after_break_target_address(masm->isolate());
__ mov(ip, Operand(after_break_target));
__ LoadP(ip, MemOperand(ip));
__ JumpToJSEntry(ip);
}
__ MaybeDropFrames();
void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
// Load the function pointer off of our current stack frame.
__ LoadP(r4, MemOperand(fp, FrameDropperFrameConstants::kFunctionOffset));
// Pop return address and frame
__ LeaveFrame(StackFrame::INTERNAL);
ParameterCount dummy(0);
__ CheckDebugHook(r4, no_reg, dummy, dummy);
// Return to caller.
__ Ret();
}
// Load context from the function.
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kHandleDebuggerStatement, 0);
}
__ MaybeDropFrames();
// Clear new.target as a safety measure.
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
// Return to caller.
__ Ret();
}
// Get function code.
__ LoadP(ip, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset));
__ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
// Frame is being dropped:
// - Drop to the target frame specified by r4.
// - Look up current function on the frame.
// - Leave the frame.
// - Restart the frame by calling the function.
// Re-run JSFunction, r4 is function, cp is context.
__ Jump(ip);
__ mr(fp, r4);
__ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ LeaveFrame(StackFrame::INTERNAL);
__ LoadP(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(
r3, FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
__ mr(r5, r3);
ParameterCount dummy1(r5);
ParameterCount dummy2(r3);
__ InvokeFunction(r4, dummy1, dummy2, JUMP_FUNCTION,
CheckDebugStepCallWrapper());
}
const bool LiveEdit::kFrameDropperSupported = true;
#undef __
......
......@@ -82,14 +82,6 @@ void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Load padding words on stack.
__ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue));
for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
__ push(ip);
}
__ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
__ push(ip);
// Push arguments for DebugBreak call.
if (mode == SAVE_RESULT_REGISTER) {
// Break on return.
......@@ -116,46 +108,44 @@ void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
}
}
}
// Don't bother removing padding bytes pushed on the stack
// as the frame is going to be restored right away.
// Leave the internal frame.
}
__ MaybeDropFrames();
// 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.
ExternalReference after_break_target =
ExternalReference::debug_after_break_target_address(masm->isolate());
__ mov(ip, Operand(after_break_target));
__ LoadP(ip, MemOperand(ip));
__ JumpToJSEntry(ip);
// Return to caller.
__ Ret();
}
void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
// Load the function pointer off of our current stack frame.
__ LoadP(r3, MemOperand(fp, FrameDropperFrameConstants::kFunctionOffset));
// Pop return address and frame
__ LeaveFrame(StackFrame::INTERNAL);
ParameterCount dummy(0);
__ CheckDebugHook(r3, no_reg, dummy, dummy);
// Load context from the function.
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kHandleDebuggerStatement, 0);
}
__ MaybeDropFrames();
// Clear new.target as a safety measure.
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
// Return to caller.
__ Ret();
}
// Get function code.
__ LoadP(ip, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset));
__ AddP(ip, Operand(Code::kHeaderSize - kHeapObjectTag));
void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
// Frame is being dropped:
// - Drop to the target frame specified by r3.
// - Look up current function on the frame.
// - Leave the frame.
// - Restart the frame by calling the function.
// Re-run JSFunction, r3 is function, cp is context.
__ Jump(ip);
__ LoadRR(fp, r3);
__ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ LeaveFrame(StackFrame::INTERNAL);
__ LoadP(r2, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(
r2, FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ LoadRR(r4, r2);
ParameterCount dummy1(r4);
ParameterCount dummy2(r2);
__ InvokeFunction(r3, dummy1, dummy2, JUMP_FUNCTION,
CheckDebugStepCallWrapper());
}
const bool LiveEdit::kFrameDropperSupported = true;
......
......@@ -412,6 +412,15 @@ void ResumeGeneratorDescriptor::InitializePlatformSpecific(
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r4, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
......
......@@ -1576,6 +1576,16 @@ void MacroAssembler::DebugBreak() {
Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
}
void MacroAssembler::MaybeDropFrames() {
// Check whether we need to drop frames to restart a function on the stack.
ExternalReference restart_fp =
ExternalReference::debug_restart_fp_address(isolate());
mov(r4, Operand(restart_fp));
LoadWordArith(r4, MemOperand(r4));
cmpi(r4, Operand::Zero());
Jump(isolate()->builtins()->FrameDropperTrampoline(), RelocInfo::CODE_TARGET,
ne);
}
void MacroAssembler::PushStackHandler() {
// Adjust this code if not the case.
......
......@@ -639,6 +639,7 @@ class MacroAssembler : public Assembler {
// Debugger Support
void DebugBreak();
void MaybeDropFrames();
// ---------------------------------------------------------------------------
// Exception handling
......
......@@ -389,6 +389,14 @@ void ResumeGeneratorDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r3, // loaded new FP
};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
} // namespace internal
} // namespace v8
......
......@@ -1472,6 +1472,17 @@ void MacroAssembler::DebugBreak() {
Call(ces.GetCode(), RelocInfo::DEBUGGER_STATEMENT);
}
void MacroAssembler::MaybeDropFrames() {
// Check whether we need to drop frames to restart a function on the stack.
ExternalReference restart_fp =
ExternalReference::debug_restart_fp_address(isolate());
mov(r3, Operand(restart_fp));
LoadP(r3, MemOperand(r3));
CmpP(r3, Operand::Zero());
Jump(isolate()->builtins()->FrameDropperTrampoline(), RelocInfo::CODE_TARGET,
ne);
}
void MacroAssembler::PushStackHandler() {
// Adjust this code if not the case.
STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
......
......@@ -932,6 +932,7 @@ class MacroAssembler : public Assembler {
// Debugger Support
void DebugBreak();
void MaybeDropFrames();
// ---------------------------------------------------------------------------
// Exception handling
......
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