Index: src/debug/debug.cc |
diff --git a/src/debug/debug.cc b/src/debug/debug.cc |
index de9c44079519143b595054d83721e2c61ffb63b3..16d730efce758b63bf80e91e0fab88066c2c6c97 100644 |
--- a/src/debug/debug.cc |
+++ b/src/debug/debug.cc |
@@ -401,6 +401,8 @@ void Debug::ThreadInit() { |
thread_local_.last_fp_ = 0; |
thread_local_.target_fp_ = 0; |
thread_local_.return_value_ = Handle<Object>(); |
+ thread_local_.async_task_count_ = 0; |
+ thread_local_.async_task_ids_ = Handle<JSWeakMap>(); |
clear_suspended_generator(); |
// TODO(isolates): frames_are_dropped_? |
base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
@@ -1663,7 +1665,7 @@ MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, |
return CallFunction("MakeCompileEvent", arraysize(argv), argv); |
} |
-MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<String> type, |
+MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<Smi> type, |
Handle<Object> id, |
Handle<String> name) { |
DCHECK(id->IsNumber()); |
@@ -1786,7 +1788,64 @@ void Debug::OnAfterCompile(Handle<Script> script) { |
ProcessCompileEvent(v8::AfterCompile, script); |
} |
-void Debug::OnAsyncTaskEvent(Handle<String> type, Handle<Object> id, |
+namespace { |
+struct CollectedCallbackData { |
+ Object** location; |
+ int id; |
+ Debug* debug; |
+ Isolate* isolate; |
+ |
+ CollectedCallbackData(Object** location, int id, Debug* debug, |
+ Isolate* isolate) |
+ : location(location), id(id), debug(debug), isolate(isolate) {} |
+}; |
+ |
+void SendAsyncTaskEventCancel(const v8::WeakCallbackInfo<void>& info) { |
+ std::unique_ptr<CollectedCallbackData> data( |
+ reinterpret_cast<CollectedCallbackData*>(info.GetParameter())); |
+ if (!data->debug->is_active()) return; |
+ HandleScope scope(data->isolate); |
+ data->debug->OnAsyncTaskEvent(debug::Cancel, |
+ handle(Smi::FromInt(data->id), data->isolate), |
+ data->isolate->factory()->collected_string()); |
+} |
+ |
+void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { |
+ CollectedCallbackData* data = |
+ reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); |
+ GlobalHandles::Destroy(data->location); |
+ info.SetSecondPassCallback(&SendAsyncTaskEventCancel); |
+} |
+} // namespace |
+ |
+Handle<Object> Debug::NextAsyncTaskId(Handle<JSObject> promise) { |
+ Handle<JSWeakMap> map = thread_local_.async_task_ids_; |
Yang
2016/12/16 13:39:33
How about storing this id simply on the promise ob
kozy
2016/12/16 15:29:35
Done.
My idea was: if we store ids in weak map the
|
+ if (!map.location()) { |
+ map = isolate_->factory()->NewJSWeakMap(); |
+ JSWeakCollection::Initialize(map, isolate_); |
+ thread_local_.async_task_ids_ = |
+ Handle<JSWeakMap>::cast(isolate_->global_handles()->Create(*map)); |
+ } |
+ |
+ Handle<ObjectHashTable> table(ObjectHashTable::cast(map->table())); |
+ CHECK(table->IsKey(isolate_, *promise)); |
+ int32_t hash = Object::GetOrCreateHash(isolate_, promise)->value(); |
+ Handle<Object> lookup(table->Lookup(promise, hash), isolate_); |
+ bool has_value = !lookup->IsTheHole(isolate_); |
+ if (has_value) return lookup; |
+ int id = thread_local_.async_task_count_++; |
+ Handle<Smi> async_id(Smi::FromInt(id), isolate_); |
+ |
+ Handle<Object> global_handle = isolate_->global_handles()->Create(*promise); |
+ GlobalHandles::MakeWeak( |
+ global_handle.location(), |
+ new CollectedCallbackData(global_handle.location(), id, this, isolate_), |
+ &ResetPromiseHandle, v8::WeakCallbackType::kParameter); |
+ JSWeakCollection::Set(map, global_handle, async_id, hash); |
+ return async_id; |
+} |
+ |
+void Debug::OnAsyncTaskEvent(debug::AsyncTaskEventType type, Handle<Object> id, |
Handle<String> name) { |
DCHECK(id->IsNumber()); |
if (in_debug_scope() || ignore_events()) return; |
@@ -1798,7 +1857,8 @@ void Debug::OnAsyncTaskEvent(Handle<String> type, Handle<Object> id, |
// Create the script collected state object. |
Handle<Object> event_data; |
// Bail out and don't call debugger if exception. |
- if (!MakeAsyncTaskEvent(type, id, name).ToHandle(&event_data)) return; |
+ Handle<Smi> type_smi(Smi::FromInt(type), isolate_); |
+ if (!MakeAsyncTaskEvent(type_smi, id, name).ToHandle(&event_data)) return; |
// Process debug event. |
ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data), |