| Index: src/debug/liveedit.cc
|
| diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
|
| index ff7a0e8b99c32ebc76d3f5f0f06c2687e4692c5f..d192b755d72c551fb08e4043f824347f64355868 100644
|
| --- a/src/debug/liveedit.cc
|
| +++ b/src/debug/liveedit.cc
|
| @@ -1660,20 +1660,60 @@
|
| // 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) {}
|
| + MultipleFunctionTarget(Handle<JSArray> old_shared_array,
|
| + Handle<JSArray> new_shared_array,
|
| + Handle<JSArray> result)
|
| + : old_shared_array_(old_shared_array),
|
| + new_shared_array_(new_shared_array),
|
| + result_(result) {}
|
| bool MatchActivation(StackFrame* frame,
|
| LiveEdit::FunctionPatchabilityStatus status) {
|
| - return CheckActivation(m_shared_info_array, m_result, frame, status);
|
| + return CheckActivation(old_shared_array_, result_, frame, status);
|
| }
|
| const char* GetNotFoundMessage() const {
|
| return NULL;
|
| }
|
| + bool FrameUsesNewTarget(StackFrame* frame) {
|
| + if (!frame->is_java_script()) return false;
|
| + JavaScriptFrame* jsframe = JavaScriptFrame::cast(frame);
|
| + Handle<SharedFunctionInfo> old_shared(jsframe->function()->shared());
|
| + Isolate* isolate = old_shared->GetIsolate();
|
| + int len = GetArrayLength(old_shared_array_);
|
| + // Find corresponding new shared function info and return whether it
|
| + // references new.target.
|
| + for (int i = 0; i < len; i++) {
|
| + HandleScope scope(isolate);
|
| + Handle<Object> old_element =
|
| + Object::GetElement(isolate, old_shared_array_, i).ToHandleChecked();
|
| + if (!old_shared.is_identical_to(UnwrapSharedFunctionInfoFromJSValue(
|
| + Handle<JSValue>::cast(old_element)))) {
|
| + continue;
|
| + }
|
| +
|
| + Handle<Object> new_element =
|
| + Object::GetElement(isolate, new_shared_array_, i).ToHandleChecked();
|
| + if (new_element->IsUndefined()) return false;
|
| + Handle<SharedFunctionInfo> new_shared =
|
| + UnwrapSharedFunctionInfoFromJSValue(
|
| + Handle<JSValue>::cast(new_element));
|
| + if (new_shared->scope_info()->HasNewTarget()) {
|
| + SetElementSloppy(
|
| + result_, i,
|
| + Handle<Smi>(
|
| + Smi::FromInt(
|
| + LiveEdit::FUNCTION_BLOCKED_NO_NEW_TARGET_ON_RESTART),
|
| + isolate));
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| private:
|
| - Handle<JSArray> m_shared_info_array;
|
| - Handle<JSArray> m_result;
|
| + Handle<JSArray> old_shared_array_;
|
| + Handle<JSArray> new_shared_array_;
|
| + Handle<JSArray> result_;
|
| };
|
|
|
|
|
| @@ -1720,11 +1760,14 @@
|
| non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
|
| break;
|
| }
|
| - if (frame->is_java_script() &&
|
| - JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) {
|
| - non_droppable_frame_found = true;
|
| - non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
|
| - break;
|
| + if (frame->is_java_script()) {
|
| + SharedFunctionInfo* shared =
|
| + JavaScriptFrame::cast(frame)->function()->shared();
|
| + if (shared->is_generator()) {
|
| + non_droppable_frame_found = true;
|
| + non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
|
| + break;
|
| + }
|
| }
|
| if (target.MatchActivation(
|
| frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
|
| @@ -1748,6 +1791,9 @@
|
| }
|
| }
|
|
|
| + // We cannot restart a frame that uses new.target.
|
| + if (target.FrameUsesNewTarget(frames[bottom_js_frame_index])) return NULL;
|
| +
|
| if (!do_drop) {
|
| // We are in check-only mode.
|
| return NULL;
|
| @@ -1785,9 +1831,10 @@
|
| // 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) {
|
| - MultipleFunctionTarget target(shared_info_array, result);
|
| - Isolate* isolate = shared_info_array->GetIsolate();
|
| + Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array,
|
| + Handle<JSArray> result, bool do_drop) {
|
| + MultipleFunctionTarget target(old_shared_array, new_shared_array, result);
|
| + Isolate* isolate = old_shared_array->GetIsolate();
|
|
|
| const char* message =
|
| DropActivationsInActiveThreadImpl(isolate, target, do_drop);
|
| @@ -1795,7 +1842,7 @@
|
| return message;
|
| }
|
|
|
| - int array_len = GetArrayLength(shared_info_array);
|
| + int array_len = GetArrayLength(old_shared_array);
|
|
|
| // Replace "blocked on active" with "replaced on active" status.
|
| for (int i = 0; i < array_len; i++) {
|
| @@ -1851,16 +1898,16 @@
|
|
|
| class InactiveThreadActivationsChecker : public ThreadVisitor {
|
| public:
|
| - InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
|
| + InactiveThreadActivationsChecker(Handle<JSArray> old_shared_array,
|
| Handle<JSArray> result)
|
| - : shared_info_array_(shared_info_array), result_(result),
|
| - has_blocked_functions_(false) {
|
| - }
|
| + : old_shared_array_(old_shared_array),
|
| + result_(result),
|
| + has_blocked_functions_(false) {}
|
| void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
|
| for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
|
| - has_blocked_functions_ |= CheckActivation(
|
| - shared_info_array_, result_, it.frame(),
|
| - LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
|
| + has_blocked_functions_ |=
|
| + CheckActivation(old_shared_array_, result_, it.frame(),
|
| + LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
|
| }
|
| }
|
| bool HasBlockedFunctions() {
|
| @@ -1868,20 +1915,21 @@
|
| }
|
|
|
| private:
|
| - Handle<JSArray> shared_info_array_;
|
| + Handle<JSArray> old_shared_array_;
|
| Handle<JSArray> result_;
|
| bool has_blocked_functions_;
|
| };
|
|
|
|
|
| Handle<JSArray> LiveEdit::CheckAndDropActivations(
|
| - Handle<JSArray> shared_info_array, bool do_drop) {
|
| - Isolate* isolate = shared_info_array->GetIsolate();
|
| - int len = GetArrayLength(shared_info_array);
|
| -
|
| - DCHECK(shared_info_array->HasFastElements());
|
| - Handle<FixedArray> shared_info_array_elements(
|
| - FixedArray::cast(shared_info_array->elements()));
|
| + Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array,
|
| + bool do_drop) {
|
| + Isolate* isolate = old_shared_array->GetIsolate();
|
| + int len = GetArrayLength(old_shared_array);
|
| +
|
| + DCHECK(old_shared_array->HasFastElements());
|
| + Handle<FixedArray> old_shared_array_elements(
|
| + FixedArray::cast(old_shared_array->elements()));
|
|
|
| Handle<JSArray> result = isolate->factory()->NewJSArray(len);
|
| Handle<FixedArray> result_elements =
|
| @@ -1897,12 +1945,12 @@
|
| // running (as we wouldn't want to restart them, because we don't know where
|
| // to restart them from) or suspended. Fail if any one corresponds to the set
|
| // of functions being edited.
|
| - if (FindActiveGenerators(shared_info_array_elements, result_elements, len)) {
|
| + if (FindActiveGenerators(old_shared_array_elements, result_elements, len)) {
|
| return result;
|
| }
|
|
|
| // Check inactive threads. Fail if some functions are blocked there.
|
| - InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
|
| + InactiveThreadActivationsChecker inactive_threads_checker(old_shared_array,
|
| result);
|
| isolate->thread_manager()->IterateArchivedThreads(
|
| &inactive_threads_checker);
|
| @@ -1911,8 +1959,8 @@
|
| }
|
|
|
| // Try to drop activations from the current stack.
|
| - const char* error_message =
|
| - DropActivationsInActiveThread(shared_info_array, result, do_drop);
|
| + const char* error_message = DropActivationsInActiveThread(
|
| + old_shared_array, new_shared_array, result, do_drop);
|
| if (error_message != NULL) {
|
| // Add error message as an array extra element.
|
| Handle<String> str =
|
| @@ -1945,6 +1993,17 @@
|
| LiveEdit::FunctionPatchabilityStatus saved_status() {
|
| return m_saved_status;
|
| }
|
| + void set_status(LiveEdit::FunctionPatchabilityStatus status) {
|
| + m_saved_status = status;
|
| + }
|
| +
|
| + bool FrameUsesNewTarget(StackFrame* frame) {
|
| + if (!frame->is_java_script()) return false;
|
| + JavaScriptFrame* jsframe = JavaScriptFrame::cast(frame);
|
| + Handle<SharedFunctionInfo> shared(jsframe->function()->shared());
|
| + return shared->scope_info()->HasNewTarget();
|
| + }
|
| +
|
| private:
|
| JavaScriptFrame* m_frame;
|
| LiveEdit::FunctionPatchabilityStatus m_saved_status;
|
|
|