Index: src/liveedit.cc |
diff --git a/src/liveedit.cc b/src/liveedit.cc |
index e670b442b6d5033c4734d307a3cc74c9d094d537..47208f660c54f93e4aff452ff118d0a492e66f8f 100644 |
--- a/src/liveedit.cc |
+++ b/src/liveedit.cc |
@@ -1595,17 +1595,36 @@ static bool IsDropableFrame(StackFrame* frame) { |
return !frame->is_exit(); |
} |
-// Fills result array with statuses of functions. Modifies the stack |
-// removing all listed function if possible and if do_drop is true. |
-static const char* DropActivationsInActiveThread( |
- Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop, |
- Zone* zone) { |
+ |
+// Describes a set of call frames that execute any of listed functions. |
+// Finding no such frames does not mean error. |
+class MultipleFunctionTarget { |
+ public: |
+ MultipleFunctionTarget(Handle<JSArray> shared_info_array, |
+ Handle<JSArray> result) |
+ : m_shared_info_array(shared_info_array), |
+ m_result(result) {} |
+ bool MatchActivation(StackFrame* frame, |
+ LiveEdit::FunctionPatchabilityStatus status) { |
+ return CheckActivation(m_shared_info_array, m_result, frame, status); |
+ } |
+ const char* GetNotFoundMessage() { |
+ return NULL; |
+ } |
+ private: |
+ Handle<JSArray> m_shared_info_array; |
+ Handle<JSArray> m_result; |
+}; |
+ |
+// Drops all call frame matched by target and all frames above them. |
+template<typename TARGET> |
+static const char* DropActivationsInActiveThreadImpl( |
+ TARGET& target, bool do_drop, Zone* zone) { |
Isolate* isolate = Isolate::Current(); |
Debug* debug = isolate->debug(); |
ZoneScope scope(isolate, DELETE_ON_EXIT); |
Vector<StackFrame*> frames = CreateStackMap(zone); |
- int array_len = Smi::cast(shared_info_array->length())->value(); |
int top_frame_index = -1; |
int frame_index = 0; |
@@ -1615,8 +1634,8 @@ static const char* DropActivationsInActiveThread( |
top_frame_index = frame_index; |
break; |
} |
- if (CheckActivation(shared_info_array, result, frame, |
- LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
+ if (target.MatchActivation( |
+ frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
// We are still above break_frame. It is not a target frame, |
// it is a problem. |
return "Debugger mark-up on stack is not found"; |
@@ -1625,7 +1644,7 @@ static const char* DropActivationsInActiveThread( |
if (top_frame_index == -1) { |
// We haven't found break frame, but no function is blocking us anyway. |
- return NULL; |
+ return target.GetNotFoundMessage(); |
} |
bool target_frame_found = false; |
@@ -1638,8 +1657,8 @@ static const char* DropActivationsInActiveThread( |
c_code_found = true; |
break; |
} |
- if (CheckActivation(shared_info_array, result, frame, |
- LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
+ if (target.MatchActivation( |
+ frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
target_frame_found = true; |
bottom_js_frame_index = frame_index; |
} |
@@ -1651,8 +1670,8 @@ static const char* DropActivationsInActiveThread( |
for (; frame_index < frames.length(); frame_index++) { |
StackFrame* frame = frames[frame_index]; |
if (frame->is_java_script()) { |
- if (CheckActivation(shared_info_array, result, frame, |
- LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
+ if (target.MatchActivation( |
+ frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
// Cannot drop frame under C frames. |
return NULL; |
} |
@@ -1667,7 +1686,7 @@ static const char* DropActivationsInActiveThread( |
if (!target_frame_found) { |
// Nothing to drop. |
- return NULL; |
+ return target.GetNotFoundMessage(); |
} |
Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED; |
@@ -1690,6 +1709,23 @@ static const char* DropActivationsInActiveThread( |
} |
debug->FramesHaveBeenDropped(new_id, drop_mode, |
restarter_frame_function_pointer); |
+ return NULL; |
+} |
+ |
+// Fills result array with statuses of functions. Modifies the stack |
+// removing all listed function if possible and if do_drop is true. |
+static const char* DropActivationsInActiveThread( |
+ Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop, |
+ Zone* zone) { |
+ MultipleFunctionTarget target(shared_info_array, result); |
+ |
+ const char* message = |
+ DropActivationsInActiveThreadImpl(target, do_drop, zone); |
+ if (message) { |
+ return message; |
+ } |
+ |
+ int array_len = Smi::cast(shared_info_array->length())->value(); |
// Replace "blocked on active" with "replaced on active" status. |
for (int i = 0; i < array_len; i++) { |
@@ -1766,6 +1802,41 @@ Handle<JSArray> LiveEdit::CheckAndDropActivations( |
} |
+// Describes a single callframe a target. Not finding this frame |
+// means an error. |
+class SingleFrameTarget { |
+ public: |
+ explicit SingleFrameTarget(JavaScriptFrame* frame) : m_frame(frame) {} |
+ |
+ bool MatchActivation(StackFrame* frame, |
+ LiveEdit::FunctionPatchabilityStatus status) { |
+ if (frame->fp() == m_frame->fp()) { |
+ m_saved_status = status; |
+ return true; |
+ } |
+ return false; |
+ } |
+ const char* GetNotFoundMessage() { |
+ return "Failed to found requested frame"; |
+ } |
+ LiveEdit::FunctionPatchabilityStatus saved_status() { |
+ return m_saved_status; |
+ } |
+ private: |
+ JavaScriptFrame* m_frame; |
+ LiveEdit::FunctionPatchabilityStatus m_saved_status; |
+}; |
+ |
+ |
+// Finds a drops required frame and all frames above. |
+// Returns error message or NULL. |
+const char* LiveEdit::RestartFrame(JavaScriptFrame* frame, Zone* zone) { |
+ SingleFrameTarget target(frame); |
+ |
+ return DropActivationsInActiveThreadImpl(target, true, zone); |
+} |
+ |
+ |
LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
FunctionLiteral* fun) |
: isolate_(isolate) { |