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