diff options
Diffstat (limited to 'deps/v8/src/debug/debug.cc')
-rw-r--r-- | deps/v8/src/debug/debug.cc | 126 |
1 files changed, 69 insertions, 57 deletions
diff --git a/deps/v8/src/debug/debug.cc b/deps/v8/src/debug/debug.cc index 1d50226e72..78cb102fa8 100644 --- a/deps/v8/src/debug/debug.cc +++ b/deps/v8/src/debug/debug.cc @@ -11,7 +11,6 @@ #include "src/assembler-inl.h" #include "src/bootstrapper.h" #include "src/code-stubs.h" -#include "src/codegen.h" #include "src/compilation-cache.h" #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" #include "src/compiler.h" @@ -46,7 +45,7 @@ Debug::Debug(Isolate* isolate) break_on_exception_(false), break_on_uncaught_exception_(false), side_effect_check_failed_(false), - debug_info_list_(NULL), + debug_info_list_(nullptr), feature_tracker_(isolate), isolate_(isolate) { ThreadInit(); @@ -282,7 +281,7 @@ void Debug::Iterate(RootVisitor* v) { v->VisitRootPointer(Root::kDebug, &thread_local_.ignore_step_into_function_); } -DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { +DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info) : next_(nullptr) { // Globalize the request debug info object and make it weak. GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); debug_info_ = global_handles->Create(debug_info).location(); @@ -603,8 +602,13 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, Handle<DebugInfo> debug_info(shared->GetDebugInfo()); - // Find the break point and change it. - *source_position = FindBreakablePosition(debug_info, *source_position); + // Find breakable position returns first breakable position after + // *source_position, it can return 0 if no break location is found after + // *source_position. + int breakable_position = FindBreakablePosition(debug_info, *source_position); + if (breakable_position < *source_position) return false; + *source_position = breakable_position; + DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); // At least one active break point now. DCHECK_LT(0, debug_info->GetBreakPointCount()); @@ -653,7 +657,7 @@ void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) { void Debug::ClearBreakPoint(Handle<Object> break_point_object) { HandleScope scope(isolate_); - for (DebugInfoListNode* node = debug_info_list_; node != NULL; + for (DebugInfoListNode* node = debug_info_list_; node != nullptr; node = node->next()) { Handle<Object> result = DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); @@ -1020,7 +1024,7 @@ void Debug::ClearOneShot() { // The current implementation just runs through all the breakpoints. When the // last break point for a function is removed that function is automatically // removed from the list. - for (DebugInfoListNode* node = debug_info_list_; node != NULL; + for (DebugInfoListNode* node = debug_info_list_; node != nullptr; node = node->next()) { Handle<DebugInfo> debug_info = node->debug_info(); ClearBreakPoints(debug_info); @@ -1196,12 +1200,12 @@ void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) { class SharedFunctionInfoFinder { public: explicit SharedFunctionInfoFinder(int target_position) - : current_candidate_(NULL), - current_candidate_closure_(NULL), + : current_candidate_(nullptr), + current_candidate_closure_(nullptr), current_start_position_(kNoSourcePosition), target_position_(target_position) {} - void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) { + void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = nullptr) { if (!shared->IsSubjectToDebugging()) return; int start_position = shared->function_token_position(); if (start_position == kNoSourcePosition) { @@ -1211,11 +1215,11 @@ class SharedFunctionInfoFinder { if (start_position > target_position_) return; if (target_position_ > shared->end_position()) return; - if (current_candidate_ != NULL) { + if (current_candidate_ != nullptr) { if (current_start_position_ == start_position && shared->end_position() == current_candidate_->end_position()) { // If we already have a matching closure, do not throw it away. - if (current_candidate_closure_ != NULL && closure == NULL) return; + if (current_candidate_closure_ != nullptr && closure == nullptr) return; // If a top-level function contains only one function // declaration the source for the top-level and the function // is the same. In that case prefer the non top-level function. @@ -1267,7 +1271,7 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, finder.NewCandidate(info); } shared = finder.Result(); - if (shared == NULL) break; + if (shared == nullptr) break; // We found it if it's already compiled. if (shared->is_compiled()) { Handle<SharedFunctionInfo> shared_handle(shared); @@ -1403,7 +1407,7 @@ void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node) { DCHECK(node->debug_info()->IsEmpty()); - // Unlink from list. If prev is NULL we are looking at the first element. + // Unlink from list. If prev is nullptr we are looking at the first element. if (prev == nullptr) { debug_info_list_ = node->next(); } else { @@ -1560,7 +1564,7 @@ void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) { namespace { v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); - // Isolate::context() may have been NULL when "script collected" event + // Isolate::context() may have been nullptr when "script collected" event // occurred. if (context.is_null()) return v8::Local<v8::Context>(); Handle<Context> native_context(context->native_context()); @@ -1605,7 +1609,7 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { Handle<JSObject> jspromise = Handle<JSObject>::cast(promise); // Mark the promise as already having triggered a message. Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); - JSObject::SetProperty(jspromise, key, key, STRICT).Assert(); + JSObject::SetProperty(jspromise, key, key, LanguageMode::kStrict).Assert(); // Check whether the promise reject is considered an uncaught exception. uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise); } @@ -1742,28 +1746,55 @@ int GetReferenceAsyncTaskId(Isolate* isolate, Handle<JSPromise> promise) { } } // namespace -void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise, +void Debug::RunPromiseHook(PromiseHookType hook_type, Handle<JSPromise> promise, Handle<Object> parent) { + if (hook_type == PromiseHookType::kResolve) return; + if (in_debug_scope() || ignore_events()) return; if (!debug_delegate_) return; + PostponeInterruptsScope no_interrupts(isolate_); + int id = GetReferenceAsyncTaskId(isolate_, promise); - switch (type) { - case PromiseHookType::kInit: - OnAsyncTaskEvent(debug::kDebugPromiseCreated, id, - parent->IsJSPromise() - ? GetReferenceAsyncTaskId( - isolate_, Handle<JSPromise>::cast(parent)) - : 0); - return; - case PromiseHookType::kResolve: - // We can't use this hook because it's called before promise object will - // get resolved status. - return; - case PromiseHookType::kBefore: - OnAsyncTaskEvent(debug::kDebugWillHandle, id, 0); - return; - case PromiseHookType::kAfter: - OnAsyncTaskEvent(debug::kDebugDidHandle, id, 0); - return; + if (hook_type == PromiseHookType::kBefore) { + debug_delegate_->PromiseEventOccurred(debug::kDebugWillHandle, id, false); + } else if (hook_type == PromiseHookType::kAfter) { + debug_delegate_->PromiseEventOccurred(debug::kDebugDidHandle, id, false); + } else { + DCHECK(hook_type == PromiseHookType::kInit); + debug::PromiseDebugActionType type = debug::kDebugPromiseThen; + bool last_frame_was_promise_builtin = false; + JavaScriptFrameIterator it(isolate_); + while (!it.done()) { + std::vector<Handle<SharedFunctionInfo>> infos; + it.frame()->GetFunctions(&infos); + for (size_t i = 1; i <= infos.size(); ++i) { + Handle<SharedFunctionInfo> info = infos[infos.size() - i]; + if (info->IsUserJavaScript()) { + // We should not report PromiseThen and PromiseCatch which is called + // indirectly, e.g. Promise.all calls Promise.then internally. + if (type == debug::kDebugAsyncFunctionPromiseCreated || + last_frame_was_promise_builtin) { + debug_delegate_->PromiseEventOccurred(type, id, IsBlackboxed(info)); + } + return; + } + last_frame_was_promise_builtin = false; + Handle<Code> code(info->code()); + if (*code == *BUILTIN_CODE(isolate_, AsyncFunctionPromiseCreate)) { + type = debug::kDebugAsyncFunctionPromiseCreated; + last_frame_was_promise_builtin = true; + } else if (*code == *BUILTIN_CODE(isolate_, PromiseThen)) { + type = debug::kDebugPromiseThen; + last_frame_was_promise_builtin = true; + } else if (*code == *BUILTIN_CODE(isolate_, PromiseCatch)) { + type = debug::kDebugPromiseCatch; + last_frame_was_promise_builtin = true; + } else if (*code == *BUILTIN_CODE(isolate_, PromiseFinally)) { + type = debug::kDebugPromiseFinally; + last_frame_was_promise_builtin = true; + } + } + it.Advance(); + } } } @@ -1776,7 +1807,8 @@ int Debug::NextAsyncTaskId(Handle<JSObject> promise) { } Handle<Smi> async_id = handle(Smi::FromInt(++thread_local_.async_task_count_), isolate_); - Object::SetProperty(&it, async_id, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED) + Object::SetProperty(&it, async_id, LanguageMode::kSloppy, + Object::MAY_BE_STORE_FROM_KEYED) .ToChecked(); return async_id->value(); } @@ -1852,25 +1884,6 @@ bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source, return true; } -void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id, - int parent_id) { - if (in_debug_scope() || ignore_events()) return; - if (!debug_delegate_) return; - SuppressDebug while_processing(this); - PostponeInterruptsScope no_interrupts(isolate_); - DisableBreak no_recursive_break(this); - bool created_by_user = false; - if (type == debug::kDebugPromiseCreated) { - JavaScriptFrameIterator it(isolate_); - // We need to skip top frame which contains instrumentation. - it.Advance(); - created_by_user = - !it.done() && - !IsFrameBlackboxed(it.frame()); - } - debug_delegate_->PromiseEventOccurred(type, id, parent_id, created_by_user); -} - void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { // Attach the correct debug id to the script. The debug id is used by the // inspector to filter scripts by native context. @@ -2158,8 +2171,7 @@ bool Debug::PerformSideEffectCheckForCallback(Address function) { } void LegacyDebugDelegate::PromiseEventOccurred( - v8::debug::PromiseDebugActionType type, int id, int parent_id, - bool created_by_user) { + v8::debug::PromiseDebugActionType type, int id, bool is_blackboxed) { DebugScope debug_scope(isolate_->debug()); if (debug_scope.failed()) return; HandleScope scope(isolate_); |