@@ -13,6 +13,7 @@ using v8::Isolate;
1313using v8::Object;
1414using v8::Platform;
1515using v8::Task;
16+ using v8::TaskPriority;
1617
1718namespace {
1819
@@ -22,8 +23,31 @@ struct PlatformWorkerData {
2223 ConditionVariable* platform_workers_ready;
2324 int * pending_platform_workers;
2425 int id;
26+ PlatformDebugLogLevel debug_log_level;
2527};
2628
29+ const char * GetTaskPriorityName (TaskPriority priority) {
30+ switch (priority) {
31+ case TaskPriority::kUserBlocking :
32+ return " UserBlocking" ;
33+ case TaskPriority::kUserVisible :
34+ return " UserVisible" ;
35+ case TaskPriority::kBestEffort :
36+ return " BestEffort" ;
37+ default :
38+ return " Unknown" ;
39+ }
40+ }
41+
42+ static void PrintSourceLocation (const v8::SourceLocation& location) {
43+ auto loc = location.ToString ();
44+ if (!loc.empty ()) {
45+ fprintf (stderr, " %s\n " , loc.c_str ());
46+ } else {
47+ fprintf (stderr, " <no location>\n " );
48+ }
49+ }
50+
2751static void PlatformWorkerThread (void * data) {
2852 std::unique_ptr<PlatformWorkerData>
2953 worker_data (static_cast <PlatformWorkerData*>(data));
@@ -39,8 +63,18 @@ static void PlatformWorkerThread(void* data) {
3963 worker_data->platform_workers_ready ->Signal (lock);
4064 }
4165
66+ bool debug_log_enabled =
67+ worker_data->debug_log_level != PlatformDebugLogLevel::kNone ;
68+ int id = worker_data->id ;
4269 while (std::unique_ptr<Task> task =
4370 pending_worker_tasks->Lock ().BlockingPop ()) {
71+ if (debug_log_enabled) {
72+ fprintf (stderr,
73+ " \n PlatformWorkerThread %d running task %p\n " ,
74+ id,
75+ task.get ());
76+ fflush (stderr);
77+ }
4478 task->Run ();
4579 pending_worker_tasks->Lock ().NotifyOfCompletion ();
4680 }
@@ -74,6 +108,12 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
74108
75109 void PostDelayedTask (std::unique_ptr<Task> task, double delay_in_seconds) {
76110 auto locked = tasks_.Lock ();
111+
112+ // The delayed task scheuler is on is own thread with its own loop that
113+ // runs the timers for the scheduled tasks to pop the original task back
114+ // into the the worker task queue. This first pushes the tasks that
115+ // schedules the timers into the local task queue that will be flushed
116+ // by the local event loop.
77117 locked.Push (std::make_unique<ScheduleTask>(
78118 this , std::move (task), delay_in_seconds));
79119 uv_async_send (&flush_tasks_);
@@ -108,6 +148,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
108148 while (!tasks_to_run.empty ()) {
109149 std::unique_ptr<Task> task = std::move (tasks_to_run.front ());
110150 tasks_to_run.pop ();
151+ // This runs either the ScheduleTasks that scheduels the timers to
152+ // pop the tasks back into the worker task runner queue, or the
153+ // or the StopTasks to stop the timers and drop all the pending tasks.
111154 task->Run ();
112155 }
113156 }
@@ -135,9 +178,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
135178 ScheduleTask (DelayedTaskScheduler* scheduler,
136179 std::unique_ptr<Task> task,
137180 double delay_in_seconds)
138- : scheduler_(scheduler),
139- task_ (std::move(task)),
140- delay_in_seconds_(delay_in_seconds) {}
181+ : scheduler_(scheduler),
182+ task_ (std::move(task)),
183+ delay_in_seconds_(delay_in_seconds) {}
141184
142185 void Run () override {
143186 uint64_t delay_millis = llround (delay_in_seconds_ * 1000 );
@@ -172,15 +215,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
172215 }
173216
174217 uv_sem_t ready_;
218+ // Task queue in the worker thread task runner, we push the delayed task back
219+ // to it when the timer expires.
175220 TaskQueue<Task>* pending_worker_tasks_;
176221
222+ // Locally scheduled tasks to be poped into the worker task runner queue.
223+ // It is flushed whenever the next closest timer expires.
177224 TaskQueue<Task> tasks_;
178225 uv_loop_t loop_;
179226 uv_async_t flush_tasks_;
180227 std::unordered_set<uv_timer_t *> timers_;
181228};
182229
183- WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (int thread_pool_size) {
230+ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (
231+ int thread_pool_size, PlatformDebugLogLevel debug_log_level)
232+ : debug_log_level_(debug_log_level) {
184233 Mutex platform_workers_mutex;
185234 ConditionVariable platform_workers_ready;
186235
@@ -192,10 +241,13 @@ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
192241 threads_.push_back (delayed_task_scheduler_->Start ());
193242
194243 for (int i = 0 ; i < thread_pool_size; i++) {
195- PlatformWorkerData* worker_data = new PlatformWorkerData{
196- &pending_worker_tasks_, &platform_workers_mutex,
197- &platform_workers_ready, &pending_platform_workers, i
198- };
244+ PlatformWorkerData* worker_data =
245+ new PlatformWorkerData{&pending_worker_tasks_,
246+ &platform_workers_mutex,
247+ &platform_workers_ready,
248+ &pending_platform_workers,
249+ i,
250+ debug_log_level_};
199251 std::unique_ptr<uv_thread_t > t { new uv_thread_t () };
200252 if (uv_thread_create (t.get (), PlatformWorkerThread,
201253 worker_data) != 0 ) {
@@ -237,8 +289,8 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const {
237289}
238290
239291PerIsolatePlatformData::PerIsolatePlatformData (
240- Isolate* isolate, uv_loop_t * loop)
241- : isolate_(isolate), loop_(loop) {
292+ Isolate* isolate, uv_loop_t * loop, PlatformDebugLogLevel debug_log_level )
293+ : isolate_(isolate), loop_(loop), debug_log_level_(debug_log_level ) {
242294 flush_tasks_ = new uv_async_t ();
243295 CHECK_EQ (0 , uv_async_init (loop, flush_tasks_, FlushTasks));
244296 flush_tasks_->data = static_cast <void *>(this );
@@ -264,6 +316,14 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
264316 // the foreground task runner is being cleaned up by Shutdown(). In that
265317 // case, make sure we wait until the shutdown is completed (which leads
266318 // to flush_tasks_ == nullptr, and the task will be discarded).
319+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
320+ fprintf (stderr, " \n PerIsolatePlatformData::PostTaskImpl %p" , task.get ());
321+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
322+ DumpNativeBacktrace (stderr);
323+ }
324+ fflush (stderr);
325+ }
326+
267327 auto locked = foreground_tasks_.Lock ();
268328 if (flush_tasks_ == nullptr ) return ;
269329 locked.Push (std::move (task));
@@ -272,6 +332,17 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
272332
273333void PerIsolatePlatformData::PostDelayedTask (
274334 std::unique_ptr<Task> task, double delay_in_seconds) {
335+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
336+ fprintf (stderr,
337+ " \n PerIsolatePlatformData::PostDelayedTaskImpl %p %f" ,
338+ task.get (),
339+ delay_in_seconds);
340+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
341+ DumpNativeBacktrace (stderr);
342+ }
343+ fflush (stderr);
344+ }
345+
275346 auto locked = foreground_delayed_tasks_.Lock ();
276347 if (flush_tasks_ == nullptr ) return ;
277348 std::unique_ptr<DelayedTask> delayed (new DelayedTask ());
@@ -339,6 +410,16 @@ void PerIsolatePlatformData::DecreaseHandleCount() {
339410NodePlatform::NodePlatform (int thread_pool_size,
340411 v8::TracingController* tracing_controller,
341412 v8::PageAllocator* page_allocator) {
413+ if (per_process::enabled_debug_list.enabled (
414+ DebugCategory::PLATFORM_VERBOSE)) {
415+ debug_log_level_ = PlatformDebugLogLevel::kVerbose ;
416+ } else if (per_process::enabled_debug_list.enabled (
417+ DebugCategory::PLATFORM_MINIMAL)) {
418+ debug_log_level_ = PlatformDebugLogLevel::kMinimal ;
419+ } else {
420+ debug_log_level_ = PlatformDebugLogLevel::kNone ;
421+ }
422+
342423 if (tracing_controller != nullptr ) {
343424 tracing_controller_ = tracing_controller;
344425 } else {
@@ -355,8 +436,8 @@ NodePlatform::NodePlatform(int thread_pool_size,
355436 DCHECK_EQ (GetTracingController (), tracing_controller_);
356437
357438 thread_pool_size = GetActualThreadPoolSize (thread_pool_size);
358- worker_thread_task_runner_ =
359- std::make_shared<WorkerThreadsTaskRunner>( thread_pool_size);
439+ worker_thread_task_runner_ = std::make_shared<WorkerThreadsTaskRunner>(
440+ thread_pool_size, debug_log_level_ );
360441}
361442
362443NodePlatform::~NodePlatform () {
@@ -365,7 +446,8 @@ NodePlatform::~NodePlatform() {
365446
366447void NodePlatform::RegisterIsolate (Isolate* isolate, uv_loop_t * loop) {
367448 Mutex::ScopedLock lock (per_isolate_mutex_);
368- auto delegate = std::make_shared<PerIsolatePlatformData>(isolate, loop);
449+ auto delegate =
450+ std::make_shared<PerIsolatePlatformData>(isolate, loop, debug_log_level_);
369451 IsolatePlatformDelegate* ptr = delegate.get ();
370452 auto insertion = per_isolate_.emplace (
371453 isolate,
@@ -520,6 +602,17 @@ void NodePlatform::PostTaskOnWorkerThreadImpl(
520602 v8::TaskPriority priority,
521603 std::unique_ptr<v8::Task> task,
522604 const v8::SourceLocation& location) {
605+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
606+ fprintf (stderr,
607+ " \n NodePlatform::PostTaskOnWorkerThreadImpl %s %p" ,
608+ GetTaskPriorityName (priority),
609+ task.get ());
610+ PrintSourceLocation (location);
611+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
612+ DumpNativeBacktrace (stderr);
613+ }
614+ fflush (stderr);
615+ }
523616 worker_thread_task_runner_->PostTask (std::move (task));
524617}
525618
@@ -528,6 +621,18 @@ void NodePlatform::PostDelayedTaskOnWorkerThreadImpl(
528621 std::unique_ptr<v8::Task> task,
529622 double delay_in_seconds,
530623 const v8::SourceLocation& location) {
624+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
625+ fprintf (stderr,
626+ " \n NodePlatform::PostDelayedTaskOnWorkerThreadImpl %s %p %f" ,
627+ GetTaskPriorityName (priority),
628+ task.get (),
629+ delay_in_seconds);
630+ PrintSourceLocation (location);
631+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
632+ DumpNativeBacktrace (stderr);
633+ }
634+ fflush (stderr);
635+ }
531636 worker_thread_task_runner_->PostDelayedTask (std::move (task),
532637 delay_in_seconds);
533638}
@@ -557,6 +662,17 @@ std::unique_ptr<v8::JobHandle> NodePlatform::CreateJobImpl(
557662 v8::TaskPriority priority,
558663 std::unique_ptr<v8::JobTask> job_task,
559664 const v8::SourceLocation& location) {
665+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
666+ fprintf (stderr,
667+ " \n NodePlatform::CreateJobImpl %s %p" ,
668+ GetTaskPriorityName (priority),
669+ job_task.get ());
670+ PrintSourceLocation (location);
671+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
672+ DumpNativeBacktrace (stderr);
673+ }
674+ fflush (stderr);
675+ }
560676 return v8::platform::NewDefaultJobHandle (
561677 this , priority, std::move (job_task), NumberOfWorkerThreads ());
562678}
0 commit comments