Index: src/liveedit.cc |
diff --git a/src/liveedit.cc b/src/liveedit.cc |
index cf7f4c802c79f7464e4e2bf282f3b9387f4be9ba..e55f24ec3eabda772401057241f33f022aeccbdc 100644 |
--- a/src/liveedit.cc |
+++ b/src/liveedit.cc |
@@ -1533,6 +1533,38 @@ static bool FixTryCatchHandler(StackFrame* top_frame, |
} |
+// Initializes an artificial stack frame. The data it contains is used for: |
+// a. successful work of frame dropper code which eventually gets control, |
+// b. being compatible with regular stack structure for various stack |
+// iterators. |
+// Returns address of stack allocated pointer to restarted function, |
+// 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. |
+// Frame structure (conforms InternalFrame structure): |
+// -- code |
+// -- SMI maker |
+// -- function (slot is called "context") |
+// -- frame base |
+static Object** 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)); |
+} |
+ |
+ |
// Removes specified range of frames from stack. There may be 1 or more |
// frames in range. Anyway the bottom frame is restarted rather than dropped, |
// and therefore has to be a JavaScript frame. |
@@ -1540,9 +1572,9 @@ static bool FixTryCatchHandler(StackFrame* top_frame, |
static const char* DropFrames(Vector<StackFrame*> frames, |
int top_frame_index, |
int bottom_js_frame_index, |
- Debug::FrameDropMode* mode, |
+ LiveEdit::FrameDropMode* mode, |
Object*** restarter_frame_function_pointer) { |
- if (!Debug::kFrameDropperSupported) { |
+ if (!LiveEdit::kFrameDropperSupported) { |
return "Stack manipulations are not supported in this architecture."; |
} |
@@ -1555,34 +1587,30 @@ static const char* DropFrames(Vector<StackFrame*> frames, |
// Check the nature of the top frame. |
Isolate* isolate = bottom_js_frame->isolate(); |
Code* pre_top_frame_code = pre_top_frame->LookupCode(); |
- bool frame_has_padding; |
+ bool frame_has_padding = true; |
if (pre_top_frame_code->is_inline_cache_stub() && |
pre_top_frame_code->is_debug_stub()) { |
// OK, we can drop inline cache calls. |
- *mode = Debug::FRAME_DROPPED_IN_IC_CALL; |
- frame_has_padding = Debug::FramePaddingLayout::kIsSupported; |
+ *mode = LiveEdit::FRAME_DROPPED_IN_IC_CALL; |
} else if (pre_top_frame_code == |
isolate->builtins()->builtin(Builtins::kSlot_DebugBreak)) { |
// OK, we can drop debug break slot. |
- *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; |
- frame_has_padding = Debug::FramePaddingLayout::kIsSupported; |
+ *mode = LiveEdit::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; |
} else if (pre_top_frame_code == |
- isolate->builtins()->builtin( |
- Builtins::kFrameDropper_LiveEdit)) { |
+ isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)) { |
// OK, we can drop our own code. |
pre_top_frame = frames[top_frame_index - 2]; |
top_frame = frames[top_frame_index - 1]; |
- *mode = Debug::CURRENTLY_SET_MODE; |
+ *mode = LiveEdit::CURRENTLY_SET_MODE; |
frame_has_padding = false; |
} else if (pre_top_frame_code == |
- isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) { |
- *mode = Debug::FRAME_DROPPED_IN_RETURN_CALL; |
- frame_has_padding = Debug::FramePaddingLayout::kIsSupported; |
+ isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) { |
+ *mode = LiveEdit::FRAME_DROPPED_IN_RETURN_CALL; |
} else if (pre_top_frame_code->kind() == Code::STUB && |
pre_top_frame_code->major_key() == CodeStub::CEntry) { |
// Entry from our unit tests on 'debugger' statement. |
// It's fine, we support this case. |
- *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; |
+ *mode = LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL; |
// We don't have a padding from 'debugger' statement call. |
// Here the stub is CEntry, it's not debug-only and can't be padded. |
// If anyone would complain, a proxy padded stub could be added. |
@@ -1591,19 +1619,19 @@ static const char* DropFrames(Vector<StackFrame*> frames, |
// This must be adaptor that remain from the frame dropping that |
// is still on stack. A frame dropper frame must be above it. |
ASSERT(frames[top_frame_index - 2]->LookupCode() == |
- isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)); |
+ isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)); |
pre_top_frame = frames[top_frame_index - 3]; |
top_frame = frames[top_frame_index - 2]; |
- *mode = Debug::CURRENTLY_SET_MODE; |
+ *mode = LiveEdit::CURRENTLY_SET_MODE; |
frame_has_padding = false; |
} else { |
return "Unknown structure of stack above changing function"; |
} |
Address unused_stack_top = top_frame->sp(); |
+ int new_frame_size = LiveEdit::kFrameDropperFrameSize * kPointerSize; |
Address unused_stack_bottom = bottom_js_frame->fp() |
- - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. |
- + kPointerSize; // Bigger address end is exclusive. |
+ - new_frame_size + kPointerSize; // Bigger address end is exclusive. |
Address* top_frame_pc_address = top_frame->pc_address(); |
@@ -1616,11 +1644,10 @@ static const char* DropFrames(Vector<StackFrame*> frames, |
static_cast<int>(unused_stack_top - unused_stack_bottom); |
Address padding_start = pre_top_frame->fp() - |
- Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize; |
+ LiveEdit::kFrameDropperFrameSize * kPointerSize; |
Address padding_pointer = padding_start; |
- Smi* padding_object = |
- Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue); |
+ Smi* padding_object = Smi::FromInt(LiveEdit::kFramePaddingValue); |
while (Memory::Object_at(padding_pointer) == padding_object) { |
padding_pointer -= kPointerSize; |
} |
@@ -1637,7 +1664,7 @@ static const char* DropFrames(Vector<StackFrame*> frames, |
MemMove(padding_start + kPointerSize - shortage_bytes, |
padding_start + kPointerSize, |
- Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize); |
+ LiveEdit::kFrameDropperFrameSize * kPointerSize); |
pre_top_frame->UpdateFp(pre_top_frame->fp() - shortage_bytes); |
pre_pre_frame->SetCallerFp(pre_top_frame->fp()); |
@@ -1661,7 +1688,7 @@ static const char* DropFrames(Vector<StackFrame*> frames, |
pre_top_frame->SetCallerFp(bottom_js_frame->fp()); |
*restarter_frame_function_pointer = |
- Debug::SetUpFrameDropperFrame(bottom_js_frame, code); |
+ SetUpFrameDropperFrame(bottom_js_frame, code); |
ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); |
@@ -1776,7 +1803,7 @@ static const char* DropActivationsInActiveThreadImpl( |
return target.GetNotFoundMessage(); |
} |
- Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED; |
+ LiveEdit::FrameDropMode drop_mode = LiveEdit::FRAMES_UNTOUCHED; |
Object** restarter_frame_function_pointer = NULL; |
const char* error_message = DropFrames(frames, top_frame_index, |
bottom_js_frame_index, &drop_mode, |