1 // Copyright 2012 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_D8_D8_H_
6 #define V8_D8_D8_H_
7 
8 #include <iterator>
9 #include <map>
10 #include <memory>
11 #include <queue>
12 #include <string>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16 
17 #include "src/base/once.h"
18 #include "src/base/platform/time.h"
19 #include "src/d8/async-hooks-wrapper.h"
20 #include "src/strings/string-hasher.h"
21 #include "src/utils/allocation.h"
22 #include "src/utils/utils.h"
23 
24 namespace v8 {
25 
26 class D8Console;
27 
28 namespace internal {
29 class CancelableTaskManager;
30 }  // namespace internal
31 
32 // A single counter in a counter collection.
33 class Counter {
34  public:
35   static const int kMaxNameSize = 64;
36   int32_t* Bind(const char* name, bool histogram);
ptr()37   int32_t* ptr() { return &count_; }
count()38   int32_t count() { return count_; }
sample_total()39   int32_t sample_total() { return sample_total_; }
is_histogram()40   bool is_histogram() { return is_histogram_; }
41   void AddSample(int32_t sample);
42 
43  private:
44   int32_t count_;
45   int32_t sample_total_;
46   bool is_histogram_;
47   uint8_t name_[kMaxNameSize];
48 };
49 
50 // A set of counters and associated information.  An instance of this
51 // class is stored directly in the memory-mapped counters file if
52 // the --map-counters options is used
53 class CounterCollection {
54  public:
55   CounterCollection();
56   Counter* GetNextCounter();
57 
58  private:
59   static const unsigned kMaxCounters = 512;
60   uint32_t magic_number_;
61   uint32_t max_counters_;
62   uint32_t max_name_size_;
63   uint32_t counters_in_use_;
64   Counter counters_[kMaxCounters];
65 };
66 
67 using CounterMap = std::unordered_map<std::string, Counter*>;
68 
69 class SourceGroup {
70  public:
SourceGroup()71   SourceGroup()
72       : next_semaphore_(0),
73         done_semaphore_(0),
74         thread_(nullptr),
75         argv_(nullptr),
76         begin_offset_(0),
77         end_offset_(0) {}
78 
79   ~SourceGroup();
80 
Begin(char ** argv,int offset)81   void Begin(char** argv, int offset) {
82     argv_ = const_cast<const char**>(argv);
83     begin_offset_ = offset;
84   }
85 
End(int offset)86   void End(int offset) { end_offset_ = offset; }
87 
88   // Returns true on success, false if an uncaught exception was thrown.
89   bool Execute(Isolate* isolate);
90 
91   void StartExecuteInThread();
92   void WaitForThread();
93   void JoinThread();
94 
95  private:
96   class IsolateThread : public base::Thread {
97    public:
98     explicit IsolateThread(SourceGroup* group);
99 
Run()100     void Run() override { group_->ExecuteInThread(); }
101 
102    private:
103     SourceGroup* group_;
104   };
105 
106   void ExecuteInThread();
107 
108   base::Semaphore next_semaphore_;
109   base::Semaphore done_semaphore_;
110   base::Thread* thread_;
111 
112   void ExitShell(int exit_code);
113   Local<String> ReadFile(Isolate* isolate, const char* name);
114 
115   const char** argv_;
116   int begin_offset_;
117   int end_offset_;
118 };
119 
120 class SerializationData {
121  public:
SerializationData()122   SerializationData() : size_(0) {}
123 
data()124   uint8_t* data() { return data_.get(); }
size()125   size_t size() { return size_; }
backing_stores()126   const std::vector<std::shared_ptr<v8::BackingStore>>& backing_stores() {
127     return backing_stores_;
128   }
sab_backing_stores()129   const std::vector<std::shared_ptr<v8::BackingStore>>& sab_backing_stores() {
130     return sab_backing_stores_;
131   }
compiled_wasm_modules()132   const std::vector<CompiledWasmModule>& compiled_wasm_modules() {
133     return compiled_wasm_modules_;
134   }
135 
136  private:
137   struct DataDeleter {
operatorDataDeleter138     void operator()(uint8_t* p) const { free(p); }
139   };
140 
141   std::unique_ptr<uint8_t, DataDeleter> data_;
142   size_t size_;
143   std::vector<std::shared_ptr<v8::BackingStore>> backing_stores_;
144   std::vector<std::shared_ptr<v8::BackingStore>> sab_backing_stores_;
145   std::vector<CompiledWasmModule> compiled_wasm_modules_;
146 
147  private:
148   friend class Serializer;
149 
150   DISALLOW_COPY_AND_ASSIGN(SerializationData);
151 };
152 
153 class SerializationDataQueue {
154  public:
155   void Enqueue(std::unique_ptr<SerializationData> data);
156   bool Dequeue(std::unique_ptr<SerializationData>* data);
157   bool IsEmpty();
158   void Clear();
159 
160  private:
161   base::Mutex mutex_;
162   std::vector<std::unique_ptr<SerializationData>> data_;
163 };
164 
165 class Worker : public std::enable_shared_from_this<Worker> {
166  public:
167   explicit Worker(const char* script);
168   ~Worker();
169 
170   // Post a message to the worker. The worker will take ownership of the
171   // SerializationData. This function should only be called by the thread that
172   // created the Worker.
173   void PostMessage(std::unique_ptr<SerializationData> data);
174   // Synchronously retrieve messages from the worker's outgoing message queue.
175   // If there is no message in the queue, block until a message is available.
176   // If there are no messages in the queue and the worker is no longer running,
177   // return nullptr.
178   // This function should only be called by the thread that created the Worker.
179   std::unique_ptr<SerializationData> GetMessage();
180   // Terminate the worker's event loop. Messages from the worker that have been
181   // queued can still be read via GetMessage().
182   // This function can be called by any thread.
183   void Terminate();
184   // Terminate and join the thread.
185   // This function can be called by any thread.
186   void TerminateAndWaitForThread();
187 
188   // Start running the given worker in another thread.
189   static bool StartWorkerThread(std::shared_ptr<Worker> worker);
190 
191  private:
192   friend class ProcessMessageTask;
193   friend class TerminateTask;
194 
195   void ProcessMessage(std::unique_ptr<SerializationData> data);
196   void ProcessMessages();
197 
198   class WorkerThread : public base::Thread {
199    public:
WorkerThread(std::shared_ptr<Worker> worker)200     explicit WorkerThread(std::shared_ptr<Worker> worker)
201         : base::Thread(base::Thread::Options("WorkerThread")),
202           worker_(std::move(worker)) {}
203 
204     void Run() override;
205 
206    private:
207     std::shared_ptr<Worker> worker_;
208   };
209 
210   void ExecuteInThread();
211   static void PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args);
212 
213   base::Semaphore out_semaphore_{0};
214   SerializationDataQueue out_queue_;
215   base::Thread* thread_ = nullptr;
216   char* script_;
217   std::atomic<bool> running_;
218   // For signalling that the worker has started.
219   base::Semaphore started_semaphore_{0};
220 
221   // For posting tasks to the worker
222   std::shared_ptr<TaskRunner> task_runner_;
223   i::CancelableTaskManager* task_manager_;
224 
225   // Protects reading / writing task_runner_. (The TaskRunner itself doesn't
226   // need locking, but accessing the Worker's data member does.)
227   base::Mutex worker_mutex_;
228 
229   // Only accessed by the worker thread.
230   Isolate* isolate_ = nullptr;
231   v8::Persistent<v8::Context> context_;
232 };
233 
234 class PerIsolateData {
235  public:
236   explicit PerIsolateData(Isolate* isolate);
237 
238   ~PerIsolateData();
239 
Get(Isolate * isolate)240   inline static PerIsolateData* Get(Isolate* isolate) {
241     return reinterpret_cast<PerIsolateData*>(isolate->GetData(0));
242   }
243 
244   class RealmScope {
245    public:
246     explicit RealmScope(PerIsolateData* data);
247     ~RealmScope();
248 
249    private:
250     PerIsolateData* data_;
251   };
252 
253   inline void SetTimeout(Local<Function> callback, Local<Context> context);
254   inline MaybeLocal<Function> GetTimeoutCallback();
255   inline MaybeLocal<Context> GetTimeoutContext();
256 
GetAsyncHooks()257   AsyncHooks* GetAsyncHooks() { return async_hooks_wrapper_; }
258 
259   void RemoveUnhandledPromise(Local<Promise> promise);
260   void AddUnhandledPromise(Local<Promise> promise, Local<Message> message,
261                            Local<Value> exception);
262   int HandleUnhandledPromiseRejections();
263 
264  private:
265   friend class Shell;
266   friend class RealmScope;
267   Isolate* isolate_;
268   int realm_count_;
269   int realm_current_;
270   int realm_switch_;
271   Global<Context>* realms_;
272   Global<Value> realm_shared_;
273   std::queue<Global<Function>> set_timeout_callbacks_;
274   std::queue<Global<Context>> set_timeout_contexts_;
275   bool ignore_unhandled_promises_;
276   std::vector<std::tuple<Global<Promise>, Global<Message>, Global<Value>>>
277       unhandled_promises_;
278   AsyncHooks* async_hooks_wrapper_;
279 
280   int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
281                         int arg_offset);
282   int RealmFind(Local<Context> context);
283 };
284 
285 extern bool check_d8_flag_contradictions;
286 
287 class ShellOptions {
288  public:
289   enum CodeCacheOptions {
290     kNoProduceCache,
291     kProduceCache,
292     kProduceCacheAfterExecute
293   };
294 
~ShellOptions()295   ~ShellOptions() { delete[] isolate_sources; }
296 
297   // In analogy to Flag::CheckFlagChange() in src/flags/flag.cc, only allow
298   // repeated flags for identical boolean values. We allow exceptions for flags
299   // with enum-like arguments since their conflicts can also be specified
300   // completely.
301   template <class T,
302             bool kAllowIdenticalAssignment = std::is_same<T, bool>::value>
303   class DisallowReassignment {
304    public:
DisallowReassignment(const char * name,T value)305     DisallowReassignment(const char* name, T value)
306         : name_(name), value_(value) {}
307 
T()308     operator T() const { return value_; }  // NOLINT
get()309     T get() const { return value_; }
310     DisallowReassignment& operator=(T value) {
311       if (check_d8_flag_contradictions) {
312         if (kAllowIdenticalAssignment) {
313           if (specified_ && value_ != value) {
314             FATAL("Contradictory values for d8 flag --%s", name_);
315           }
316         } else {
317           if (specified_) {
318             FATAL("Repeated specification of d8 flag --%s", name_);
319           }
320         }
321       }
322       value_ = value;
323       specified_ = true;
324       return *this;
325     }
Overwrite(T value)326     void Overwrite(T value) { value_ = value; }
327 
328    private:
329     const char* name_;
330     T value_;
331     bool specified_ = false;
332   };
333 
334   DisallowReassignment<bool> fuzzilli_coverage_statistics = {
335       "fuzzilli-coverage-statistics", false};
336   DisallowReassignment<bool> fuzzilli_enable_builtins_coverage = {
337       "fuzzilli-enable-builtins-coverage", true};
338   DisallowReassignment<bool> send_idle_notification = {"send-idle-notification",
339                                                        false};
340   DisallowReassignment<bool> invoke_weak_callbacks = {"invoke-weak-callbacks",
341                                                       false};
342   DisallowReassignment<bool> omit_quit = {"omit-quit", false};
343   DisallowReassignment<bool> wait_for_background_tasks = {
344       "wait-for-background-tasks", true};
345   DisallowReassignment<bool> stress_opt = {"stress-opt", false};
346   DisallowReassignment<int> stress_runs = {"stress-runs", 1};
347   DisallowReassignment<bool> stress_snapshot = {"stress-snapshot", false};
348   DisallowReassignment<bool> interactive_shell = {"shell", false};
349   bool test_shell = false;
350   DisallowReassignment<bool> expected_to_throw = {"throws", false};
351   DisallowReassignment<bool> ignore_unhandled_promises = {
352       "ignore-unhandled-promises", false};
353   DisallowReassignment<bool> mock_arraybuffer_allocator = {
354       "mock-arraybuffer-allocator", false};
355   DisallowReassignment<size_t> mock_arraybuffer_allocator_limit = {
356       "mock-arraybuffer-allocator-limit", 0};
357   DisallowReassignment<bool> multi_mapped_mock_allocator = {
358       "multi-mapped-mock-allocator", false};
359   DisallowReassignment<bool> enable_inspector = {"enable-inspector", false};
360   int num_isolates = 1;
361   DisallowReassignment<v8::ScriptCompiler::CompileOptions, true>
362       compile_options = {"cache", v8::ScriptCompiler::kNoCompileOptions};
363   DisallowReassignment<CodeCacheOptions, true> code_cache_options = {
364       "cache", CodeCacheOptions::kNoProduceCache};
365   DisallowReassignment<bool> streaming_compile = {"streaming-compile", false};
366   DisallowReassignment<SourceGroup*> isolate_sources = {"isolate-sources",
367                                                         nullptr};
368   DisallowReassignment<const char*> icu_data_file = {"icu-data-file", nullptr};
369   DisallowReassignment<const char*> icu_locale = {"icu-locale", nullptr};
370   DisallowReassignment<const char*> snapshot_blob = {"snapshot_blob", nullptr};
371   DisallowReassignment<bool> trace_enabled = {"trace-enabled", false};
372   DisallowReassignment<const char*> trace_path = {"trace-path", nullptr};
373   DisallowReassignment<const char*> trace_config = {"trace-config", nullptr};
374   DisallowReassignment<const char*> lcov_file = {"lcov", nullptr};
375   DisallowReassignment<bool> disable_in_process_stack_traces = {
376       "disable-in-process-stack-traces", false};
377   DisallowReassignment<int> read_from_tcp_port = {"read-from-tcp-port", -1};
378   DisallowReassignment<bool> enable_os_system = {"enable-os-system", false};
379   DisallowReassignment<bool> quiet_load = {"quiet-load", false};
380   DisallowReassignment<int> thread_pool_size = {"thread-pool-size", 0};
381   DisallowReassignment<bool> stress_delay_tasks = {"stress-delay-tasks", false};
382   std::vector<const char*> arguments;
383   DisallowReassignment<bool> include_arguments = {"arguments", true};
384   DisallowReassignment<bool> cpu_profiler = {"cpu-profiler", false};
385   DisallowReassignment<bool> cpu_profiler_print = {"cpu-profiler-print", false};
386   DisallowReassignment<bool> fuzzy_module_file_extensions = {
387       "fuzzy-module-file-extensions", true};
388 };
389 
390 class Shell : public i::AllStatic {
391  public:
392   enum PrintResult : bool { kPrintResult = true, kNoPrintResult = false };
393   enum ReportExceptions : bool {
394     kReportExceptions = true,
395     kNoReportExceptions = false
396   };
397   enum ProcessMessageQueue : bool {
398     kProcessMessageQueue = true,
399     kNoProcessMessageQueue = false
400   };
401 
402   static bool ExecuteString(Isolate* isolate, Local<String> source,
403                             Local<Value> name, PrintResult print_result,
404                             ReportExceptions report_exceptions,
405                             ProcessMessageQueue process_message_queue);
406   static bool ExecuteModule(Isolate* isolate, const char* file_name);
407   static void ReportException(Isolate* isolate, Local<Message> message,
408                               Local<Value> exception);
409   static void ReportException(Isolate* isolate, TryCatch* try_catch);
410   static Local<String> ReadFile(Isolate* isolate, const char* name);
411   static Local<Context> CreateEvaluationContext(Isolate* isolate);
412   static int RunMain(Isolate* isolate, bool last_run);
413   static int Main(int argc, char* argv[]);
414   static void Exit(int exit_code);
415   static void OnExit(Isolate* isolate);
416   static void CollectGarbage(Isolate* isolate);
417   static bool EmptyMessageQueues(Isolate* isolate);
418   static bool CompleteMessageLoop(Isolate* isolate);
419 
420   static bool HandleUnhandledPromiseRejections(Isolate* isolate);
421 
422   static void PostForegroundTask(Isolate* isolate, std::unique_ptr<Task> task);
423   static void PostBlockingBackgroundTask(std::unique_ptr<Task> task);
424 
425   static std::unique_ptr<SerializationData> SerializeValue(
426       Isolate* isolate, Local<Value> value, Local<Value> transfer);
427   static MaybeLocal<Value> DeserializeValue(
428       Isolate* isolate, std::unique_ptr<SerializationData> data);
429   static int* LookupCounter(const char* name);
430   static void* CreateHistogram(const char* name, int min, int max,
431                                size_t buckets);
432   static void AddHistogramSample(void* histogram, int sample);
433   static void MapCounters(v8::Isolate* isolate, const char* name);
434 
435   static void PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args);
436   static void PerformanceMeasureMemory(
437       const v8::FunctionCallbackInfo<v8::Value>& args);
438 
439   static void RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args);
440   static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
441   static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
442   static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
443   static void RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args);
444   static void RealmCreateAllowCrossRealmAccess(
445       const v8::FunctionCallbackInfo<v8::Value>& args);
446   static void RealmDetachGlobal(
447       const v8::FunctionCallbackInfo<v8::Value>& args);
448   static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
449   static void RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args);
450   static void RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args);
451   static void RealmSharedGet(Local<String> property,
452                              const PropertyCallbackInfo<Value>& info);
453   static void RealmSharedSet(Local<String> property, Local<Value> value,
454                              const PropertyCallbackInfo<void>& info);
455 
456   static void LogGetAndStop(const v8::FunctionCallbackInfo<v8::Value>& args);
457 
458   static void AsyncHooksCreateHook(
459       const v8::FunctionCallbackInfo<v8::Value>& args);
460   static void AsyncHooksExecutionAsyncId(
461       const v8::FunctionCallbackInfo<v8::Value>& args);
462   static void AsyncHooksTriggerAsyncId(
463       const v8::FunctionCallbackInfo<v8::Value>& args);
464 
465   static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
466   static void PrintErr(const v8::FunctionCallbackInfo<v8::Value>& args);
467   static void Write(const v8::FunctionCallbackInfo<v8::Value>& args);
468   static void WaitUntilDone(const v8::FunctionCallbackInfo<v8::Value>& args);
469   static void NotifyDone(const v8::FunctionCallbackInfo<v8::Value>& args);
470   static void QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args);
471   static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
472   static void Version(const v8::FunctionCallbackInfo<v8::Value>& args);
473   static void Read(const v8::FunctionCallbackInfo<v8::Value>& args);
474   static void ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
475   static Local<String> ReadFromStdin(Isolate* isolate);
ReadLine(const v8::FunctionCallbackInfo<v8::Value> & args)476   static void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
477     args.GetReturnValue().Set(ReadFromStdin(args.GetIsolate()));
478   }
479   static void Load(const v8::FunctionCallbackInfo<v8::Value>& args);
480   static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args);
481   static void WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args);
482   static void WorkerPostMessage(
483       const v8::FunctionCallbackInfo<v8::Value>& args);
484   static void WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
485   static void WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args);
486   static void WorkerTerminateAndWait(
487       const v8::FunctionCallbackInfo<v8::Value>& args);
488   // The OS object on the global object contains methods for performing
489   // operating system calls:
490   //
491   // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2) will
492   // run the command, passing the arguments to the program.  The standard output
493   // of the program will be picked up and returned as a multiline string.  If
494   // timeout1 is present then it should be a number.  -1 indicates no timeout
495   // and a positive number is used as a timeout in milliseconds that limits the
496   // time spent waiting between receiving output characters from the program.
497   // timeout2, if present, should be a number indicating the limit in
498   // milliseconds on the total running time of the program.  Exceptions are
499   // thrown on timeouts or other errors or if the exit status of the program
500   // indicates an error.
501   //
502   // os.chdir(dir) changes directory to the given directory.  Throws an
503   // exception/ on error.
504   //
505   // os.setenv(variable, value) sets an environment variable.  Repeated calls to
506   // this method leak memory due to the API of setenv in the standard C library.
507   //
508   // os.umask(alue) calls the umask system call and returns the old umask.
509   //
510   // os.mkdirp(name, mask) creates a directory.  The mask (if present) is anded
511   // with the current umask.  Intermediate directories are created if necessary.
512   // An exception is not thrown if the directory already exists.  Analogous to
513   // the "mkdir -p" command.
514   static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
515   static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
516   static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
517   static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
518   static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
519   static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
520   static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
521   static MaybeLocal<Promise> HostImportModuleDynamically(
522       Local<Context> context, Local<ScriptOrModule> referrer,
523       Local<String> specifier);
524   static void ModuleResolutionSuccessCallback(
525       const v8::FunctionCallbackInfo<v8::Value>& info);
526   static void ModuleResolutionFailureCallback(
527       const v8::FunctionCallbackInfo<v8::Value>& info);
528   static void HostInitializeImportMetaObject(Local<Context> context,
529                                              Local<Module> module,
530                                              Local<Object> meta);
531 
532 #ifdef V8_FUZZILLI
533   static void Fuzzilli(const v8::FunctionCallbackInfo<v8::Value>& args);
534 #endif  // V8_FUZZILLI
535 
536   // Data is of type DynamicImportData*. We use void* here to be able
537   // to conform with MicrotaskCallback interface and enqueue this
538   // function in the microtask queue.
539   static void DoHostImportModuleDynamically(void* data);
540   static void AddOSMethods(v8::Isolate* isolate,
541                            Local<ObjectTemplate> os_template);
542 
543   static const char* kPrompt;
544   static ShellOptions options;
545   static ArrayBuffer::Allocator* array_buffer_allocator;
546 
547   static void SetWaitUntilDone(Isolate* isolate, bool value);
548   static void NotifyStartStreamingTask(Isolate* isolate);
549   static void NotifyFinishStreamingTask(Isolate* isolate);
550 
551   static char* ReadCharsFromTcpPort(const char* name, int* size_out);
552 
set_script_executed()553   static void set_script_executed() { script_executed_.store(true); }
use_interactive_shell()554   static bool use_interactive_shell() {
555     return (options.interactive_shell || !script_executed_.load()) &&
556            !options.test_shell;
557   }
558 
559   static void WaitForRunningWorkers();
560   static void AddRunningWorker(std::shared_ptr<Worker> worker);
561   static void RemoveRunningWorker(const std::shared_ptr<Worker>& worker);
562 
563   static void Initialize(Isolate* isolate, D8Console* console,
564                          bool isOnMainThread = true);
565 
566   static void PromiseRejectCallback(v8::PromiseRejectMessage reject_message);
567 
568  private:
569   static Global<Context> evaluation_context_;
570   static base::OnceType quit_once_;
571   static Global<Function> stringify_function_;
572   static const char* stringify_source_;
573   static CounterMap* counter_map_;
574   // We statically allocate a set of local counters to be used if we
575   // don't want to store the stats in a memory-mapped file
576   static CounterCollection local_counters_;
577   static CounterCollection* counters_;
578   static base::OS::MemoryMappedFile* counters_file_;
579   static base::LazyMutex context_mutex_;
580   static const base::TimeTicks kInitialTicks;
581 
582   static base::LazyMutex workers_mutex_;  // Guards the following members.
583   static bool allow_new_workers_;
584   static std::unordered_set<std::shared_ptr<Worker>> running_workers_;
585 
586   // Multiple isolates may update this flag concurrently.
587   static std::atomic<bool> script_executed_;
588 
589   static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate);
590   // Append LCOV coverage data to file.
591   static void WriteLcovData(v8::Isolate* isolate, const char* file);
592   static Counter* GetCounter(const char* name, bool is_histogram);
593   static Local<String> Stringify(Isolate* isolate, Local<Value> value);
594   static void RunShell(Isolate* isolate);
595   static bool SetOptions(int argc, char* argv[]);
596 
597   static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
598   static Local<ObjectTemplate> CreateOSTemplate(Isolate* isolate);
599   static Local<FunctionTemplate> CreateWorkerTemplate(Isolate* isolate);
600   static Local<ObjectTemplate> CreateAsyncHookTemplate(Isolate* isolate);
601   static Local<ObjectTemplate> CreateTestRunnerTemplate(Isolate* isolate);
602   static Local<ObjectTemplate> CreatePerformanceTemplate(Isolate* isolate);
603   static Local<ObjectTemplate> CreateRealmTemplate(Isolate* isolate);
604   static Local<ObjectTemplate> CreateD8Template(Isolate* isolate);
605 
606   static MaybeLocal<Context> CreateRealm(
607       const v8::FunctionCallbackInfo<v8::Value>& args, int index,
608       v8::MaybeLocal<Value> global_object);
609   static void DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
610                            int index);
611   static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Module> origin_module,
612                                             v8::Local<v8::Context> context,
613                                             const std::string& file_name);
614   static ScriptCompiler::CachedData* LookupCodeCache(Isolate* isolate,
615                                                      Local<Value> name);
616   static void StoreInCodeCache(Isolate* isolate, Local<Value> name,
617                                const ScriptCompiler::CachedData* data);
618   // We may have multiple isolates running concurrently, so the access to
619   // the isolate_status_ needs to be concurrency-safe.
620   static base::LazyMutex isolate_status_lock_;
621   static std::map<Isolate*, bool> isolate_status_;
622   static std::map<Isolate*, int> isolate_running_streaming_tasks_;
623 
624   static base::LazyMutex cached_code_mutex_;
625   static std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
626       cached_code_map_;
627   static std::atomic<int> unhandled_promise_rejections_;
628 };
629 
630 }  // namespace v8
631 
632 #endif  // V8_D8_D8_H_
633