summaryrefslogtreecommitdiff
path: root/deps/v8/src/debug/debug.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/debug/debug.cc')
-rw-r--r--deps/v8/src/debug/debug.cc126
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_);