V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
compiler-dispatcher.h
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_
6 #define V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_
7 
8 #include <cstdint>
9 #include <map>
10 #include <memory>
11 #include <unordered_set>
12 #include <utility>
13 
14 #include "src/base/atomic-utils.h"
15 #include "src/base/macros.h"
16 #include "src/base/optional.h"
17 #include "src/base/platform/condition-variable.h"
18 #include "src/base/platform/mutex.h"
19 #include "src/base/platform/semaphore.h"
20 #include "src/globals.h"
21 #include "src/identity-map.h"
22 #include "src/maybe-handles.h"
23 #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
24 
25 namespace v8 {
26 
27 class Platform;
28 enum class MemoryPressureLevel;
29 
30 namespace internal {
31 
32 class AstRawString;
33 class AstValueFactory;
34 class BackgroundCompileTask;
35 class CancelableTaskManager;
36 class UnoptimizedCompileJob;
37 class CompilerDispatcherTracer;
38 class DeferredHandles;
39 class FunctionLiteral;
40 class Isolate;
41 class ParseInfo;
42 class SharedFunctionInfo;
43 class TimedHistogram;
44 class WorkerThreadRuntimeCallStats;
45 class Zone;
46 
47 template <typename T>
48 class Handle;
49 
50 // The CompilerDispatcher uses a combination of idle tasks and background tasks
51 // to parse and compile lazily parsed functions.
52 //
53 // As both parsing and compilation currently requires a preparation and
54 // finalization step that happens on the main thread, every task has to be
55 // advanced during idle time first. Depending on the properties of the task, it
56 // can then be parsed or compiled on either background threads, or during idle
57 // time. Last, it has to be finalized during idle time again.
58 //
59 // CompilerDispatcher::jobs_ maintains the list of all CompilerDispatcherJobs
60 // the CompilerDispatcher knows about.
61 //
62 // CompilerDispatcher::pending_background_jobs_ contains the set of
63 // CompilerDispatcherJobs that can be processed on a background thread.
64 //
65 // CompilerDispatcher::running_background_jobs_ contains the set of
66 // CompilerDispatcherJobs that are currently being processed on a background
67 // thread.
68 //
69 // CompilerDispatcher::DoIdleWork tries to advance as many jobs out of jobs_ as
70 // possible during idle time. If a job can't be advanced, but is suitable for
71 // background processing, it fires off background threads.
72 //
73 // CompilerDispatcher::DoBackgroundWork advances one of the pending jobs, and
74 // then spins of another idle task to potentially do the final step on the main
75 // thread.
76 class V8_EXPORT_PRIVATE CompilerDispatcher {
77  public:
78  typedef uintptr_t JobId;
79 
80  CompilerDispatcher(Isolate* isolate, Platform* platform,
81  size_t max_stack_size);
83 
84  // Returns true if the compiler dispatcher is enabled.
85  bool IsEnabled() const;
86 
87  base::Optional<JobId> Enqueue(const ParseInfo* outer_parse_info,
88  const AstRawString* function_name,
89  const FunctionLiteral* function_literal);
90 
91  // Registers the given |function| with the compilation job |job_id|.
92  void RegisterSharedFunctionInfo(JobId job_id, SharedFunctionInfo* function);
93 
94  // Returns true if there is a pending job with the given id.
95  bool IsEnqueued(JobId job_id) const;
96 
97  // Returns true if there is a pending job registered for the given function.
98  bool IsEnqueued(Handle<SharedFunctionInfo> function) const;
99 
100  // Blocks until the given function is compiled (and does so as fast as
101  // possible). Returns true if the compile job was successful.
102  bool FinishNow(Handle<SharedFunctionInfo> function);
103 
104  // Aborts compilation job |job_id|.
105  void AbortJob(JobId job_id);
106 
107  // Aborts all jobs, blocking until all jobs are aborted.
108  void AbortAll();
109 
110  private:
111  FRIEND_TEST(CompilerDispatcherTest, IdleTaskNoIdleTime);
112  FRIEND_TEST(CompilerDispatcherTest, IdleTaskSmallIdleTime);
113  FRIEND_TEST(CompilerDispatcherTest, FinishNowWithWorkerTask);
114  FRIEND_TEST(CompilerDispatcherTest, AbortJobNotStarted);
115  FRIEND_TEST(CompilerDispatcherTest, AbortJobAlreadyStarted);
116  FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask);
117  FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllRunningWorkerTask);
118  FRIEND_TEST(CompilerDispatcherTest, CompileMultipleOnBackgroundThread);
119 
120  struct Job {
121  explicit Job(BackgroundCompileTask* task_arg);
122  ~Job();
123 
124  bool IsReadyToFinalize(const base::MutexGuard&) {
125  return has_run && (!function.is_null() || aborted);
126  }
127 
128  bool IsReadyToFinalize(base::Mutex* mutex) {
129  base::MutexGuard lock(mutex);
130  return IsReadyToFinalize(lock);
131  }
132 
133  std::unique_ptr<BackgroundCompileTask> task;
135  bool has_run;
136  bool aborted;
137  };
138 
139  typedef std::map<JobId, std::unique_ptr<Job>> JobMap;
141 
142  void WaitForJobIfRunningOnBackground(Job* job);
143  JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const;
144  void ScheduleMoreWorkerTasksIfNeeded();
145  void ScheduleIdleTaskFromAnyThread(const base::MutexGuard&);
146  void DoBackgroundWork();
147  void DoIdleWork(double deadline_in_seconds);
148  // Returns iterator to the inserted job.
149  JobMap::const_iterator InsertJob(std::unique_ptr<Job> job);
150  // Returns iterator following the removed job.
151  JobMap::const_iterator RemoveJob(JobMap::const_iterator job);
152 
153  Isolate* isolate_;
154  AccountingAllocator* allocator_;
155  WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
156  TimedHistogram* background_compile_timer_;
157  std::shared_ptr<v8::TaskRunner> taskrunner_;
158  Platform* platform_;
159  size_t max_stack_size_;
160 
161  // Copy of FLAG_trace_compiler_dispatcher to allow for access from any thread.
162  bool trace_compiler_dispatcher_;
163 
164  std::unique_ptr<CancelableTaskManager> task_manager_;
165 
166  // Id for next job to be added
167  JobId next_job_id_;
168 
169  // Mapping from job_id to job.
170  JobMap jobs_;
171 
172  // Mapping from SharedFunctionInfo to the corresponding unoptimized
173  // compilation's JobId;
174  SharedToJobIdMap shared_to_unoptimized_job_id_;
175 
176  // The following members can be accessed from any thread. Methods need to hold
177  // the mutex |mutex_| while accessing them.
178  base::Mutex mutex_;
179 
180  // True if an idle task is scheduled to be run.
181  bool idle_task_scheduled_;
182 
183  // Number of scheduled or running WorkerTask objects.
184  int num_worker_tasks_;
185 
186  // The set of jobs that can be run on a background thread.
187  std::unordered_set<Job*> pending_background_jobs_;
188 
189  // The set of jobs currently being run on background threads.
190  std::unordered_set<Job*> running_background_jobs_;
191 
192  // If not nullptr, then the main thread waits for the task processing
193  // this job, and blocks on the ConditionVariable main_thread_blocking_signal_.
194  Job* main_thread_blocking_on_job_;
195  base::ConditionVariable main_thread_blocking_signal_;
196 
197  // Test support.
198  base::AtomicValue<bool> block_for_testing_;
199  base::Semaphore semaphore_for_testing_;
200 
201  DISALLOW_COPY_AND_ASSIGN(CompilerDispatcher);
202 };
203 
204 } // namespace internal
205 } // namespace v8
206 
207 #endif // V8_COMPILER_DISPATCHER_COMPILER_DISPATCHER_H_
Definition: libplatform.h:13