12 #include <unordered_map> 16 #ifdef ENABLE_VTUNE_JIT_INTERFACE 17 #include "src/third_party/vtune/v8-vtune.h" 20 #include "include/libplatform/libplatform.h" 21 #include "include/libplatform/v8-tracing.h" 22 #include "include/v8-inspector.h" 23 #include "src/api-inl.h" 24 #include "src/base/cpu.h" 25 #include "src/base/logging.h" 26 #include "src/base/platform/platform.h" 27 #include "src/base/platform/time.h" 28 #include "src/base/sys-info.h" 29 #include "src/basic-block-profiler.h" 30 #include "src/d8-console.h" 31 #include "src/d8-platforms.h" 33 #include "src/debug/debug-interface.h" 34 #include "src/interpreter/interpreter.h" 36 #include "src/objects-inl.h" 37 #include "src/objects.h" 38 #include "src/ostreams.h" 39 #include "src/snapshot/natives.h" 40 #include "src/trap-handler/trap-handler.h" 41 #include "src/utils.h" 43 #include "src/wasm/wasm-engine.h" 45 #if !defined(_WIN32) && !defined(_WIN64) 49 #endif // !defined(_WIN32) && !defined(_WIN64) 52 #define DCHECK(condition) assert(condition) 56 #define CHECK(condition) assert(condition) 63 const int kMB = 1024 * 1024;
65 const int kMaxWorkers = 100;
66 const int kMaxSerializerMemoryUsage =
73 void* Allocate(
size_t length)
override {
74 return allocator_->Allocate(length);
77 void* AllocateUninitialized(
size_t length)
override {
78 return allocator_->AllocateUninitialized(length);
81 void Free(
void* data,
size_t length)
override {
82 allocator_->Free(data, length);
86 std::unique_ptr<Allocator> allocator_ =
87 std::unique_ptr<Allocator>(NewDefaultAllocator());
91 class ShellArrayBufferAllocator :
public ArrayBufferAllocatorBase {
93 void* Allocate(
size_t length)
override {
94 if (length >= kVMThreshold)
return AllocateVM(length);
95 return ArrayBufferAllocatorBase::Allocate(length);
98 void* AllocateUninitialized(
size_t length)
override {
99 if (length >= kVMThreshold)
return AllocateVM(length);
100 return ArrayBufferAllocatorBase::AllocateUninitialized(length);
103 void Free(
void* data,
size_t length)
override {
104 if (length >= kVMThreshold) {
105 FreeVM(data, length);
107 ArrayBufferAllocatorBase::Free(data, length);
112 static constexpr
size_t kVMThreshold = 65536;
113 static constexpr
size_t kTwoGB = 2u * 1024u * 1024u * 1024u;
115 void* AllocateVM(
size_t length) {
116 DCHECK_LE(kVMThreshold, length);
119 if (length >= kTwoGB)
return nullptr;
123 size_t allocated = RoundUp(length, page_size);
125 if (allocated >= kTwoGB)
return nullptr;
126 return i::AllocatePages(page_allocator,
nullptr, allocated, page_size,
127 PageAllocator::kReadWrite);
130 void FreeVM(
void* data,
size_t length) {
133 size_t allocated = RoundUp(length, page_size);
134 CHECK(i::FreePages(page_allocator, data, allocated));
139 class MockArrayBufferAllocator :
public ArrayBufferAllocatorBase {
141 void* Allocate(
size_t length)
override {
142 return ArrayBufferAllocatorBase::Allocate(Adjust(length));
145 void* AllocateUninitialized(
size_t length)
override {
146 return ArrayBufferAllocatorBase::AllocateUninitialized(Adjust(length));
149 void Free(
void* data,
size_t length)
override {
150 return ArrayBufferAllocatorBase::Free(data, Adjust(length));
154 size_t Adjust(
size_t length) {
155 const size_t kAllocationLimit = 10 * kMB;
156 return length > kAllocationLimit ? i::AllocatePageSize() : length;
162 class MockArrayBufferAllocatiorWithLimit :
public MockArrayBufferAllocator {
164 explicit MockArrayBufferAllocatiorWithLimit(
size_t allocation_limit)
165 : space_left_(allocation_limit) {}
168 void* Allocate(
size_t length)
override {
169 if (length > space_left_) {
172 space_left_ -= length;
173 return MockArrayBufferAllocator::Allocate(length);
176 void* AllocateUninitialized(
size_t length)
override {
177 if (length > space_left_) {
180 space_left_ -= length;
181 return MockArrayBufferAllocator::AllocateUninitialized(length);
184 void Free(
void* data,
size_t length)
override {
185 space_left_ += length;
186 return MockArrayBufferAllocator::Free(data, length);
190 std::atomic<size_t> space_left_;
194 std::unique_ptr<v8::Platform> g_platform;
196 static Local<Value> Throw(Isolate* isolate,
const char* message) {
197 return isolate->ThrowException(
202 static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context,
203 Local<v8::Object>
object,
const char* property) {
204 Local<String> v8_str =
207 return object->Get(context, v8_str).ToLocalChecked();
210 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object>
object) {
211 if (object->InternalFieldCount() != 1) {
212 Throw(isolate,
"this is not a Worker");
217 static_cast<Worker*
>(
object->GetAlignedPointerFromInternalField(0));
218 if (worker ==
nullptr) {
219 Throw(isolate,
"Worker is defunct because main thread is terminating");
226 base::Thread::Options GetThreadOptions(
const char* name) {
231 return base::Thread::Options(name, 2 * kMB);
241 const char kRecordUntilFull[] =
"record-until-full";
242 const char kRecordContinuously[] =
"record-continuously";
243 const char kRecordAsMuchAsPossible[] =
"record-as-much-as-possible";
245 const char kRecordModeParam[] =
"record_mode";
246 const char kEnableSystraceParam[] =
"enable_systrace";
247 const char kEnableArgumentFilterParam[] =
"enable_argument_filter";
248 const char kIncludedCategoriesParam[] =
"included_categories";
250 class TraceConfigParser {
252 static void FillTraceConfig(v8::Isolate* isolate,
253 platform::tracing::TraceConfig* trace_config,
254 const char* json_str) {
255 HandleScope outer_scope(isolate);
256 Local<Context> context = Context::New(isolate);
257 Context::Scope context_scope(context);
258 HandleScope inner_scope(isolate);
260 Local<String> source =
263 Local<Value> result = JSON::Parse(context, source).ToLocalChecked();
266 trace_config->SetTraceRecordMode(
267 GetTraceRecordMode(isolate, context, trace_config_object));
268 if (GetBoolean(isolate, context, trace_config_object,
269 kEnableSystraceParam)) {
270 trace_config->EnableSystrace();
272 if (GetBoolean(isolate, context, trace_config_object,
273 kEnableArgumentFilterParam)) {
274 trace_config->EnableArgumentFilter();
276 UpdateIncludedCategoriesList(isolate, context, trace_config_object,
281 static bool GetBoolean(v8::Isolate* isolate, Local<Context> context,
282 Local<v8::Object>
object,
const char* property) {
283 Local<Value> value = GetValue(isolate, context,
object, property);
284 if (value->IsNumber()) {
285 return value->BooleanValue(isolate);
290 static int UpdateIncludedCategoriesList(
291 v8::Isolate* isolate, Local<Context> context, Local<v8::Object>
object,
292 platform::tracing::TraceConfig* trace_config) {
294 GetValue(isolate, context,
object, kIncludedCategoriesParam);
295 if (value->IsArray()) {
297 for (
int i = 0, length = v8_array->Length();
i < length; ++
i) {
298 Local<Value> v = v8_array->Get(context,
i)
302 String::Utf8Value str(isolate, v->ToString(context).ToLocalChecked());
303 trace_config->AddIncludedCategory(*str);
305 return v8_array->Length();
310 static platform::tracing::TraceRecordMode GetTraceRecordMode(
311 v8::Isolate* isolate, Local<Context> context, Local<v8::Object>
object) {
312 Local<Value> value = GetValue(isolate, context,
object, kRecordModeParam);
313 if (value->IsString()) {
314 Local<String> v8_string = value->ToString(context).ToLocalChecked();
315 String::Utf8Value str(isolate, v8_string);
316 if (strcmp(kRecordUntilFull, *str) == 0) {
317 return platform::tracing::TraceRecordMode::RECORD_UNTIL_FULL;
318 }
else if (strcmp(kRecordContinuously, *str) == 0) {
319 return platform::tracing::TraceRecordMode::RECORD_CONTINUOUSLY;
320 }
else if (strcmp(kRecordAsMuchAsPossible, *str) == 0) {
321 return platform::tracing::TraceRecordMode::RECORD_AS_MUCH_AS_POSSIBLE;
324 return platform::tracing::TraceRecordMode::RECORD_UNTIL_FULL;
330 static platform::tracing::TraceConfig* CreateTraceConfigFromJSON(
331 v8::Isolate* isolate,
const char* json_str) {
332 platform::tracing::TraceConfig* trace_config =
333 new platform::tracing::TraceConfig();
334 TraceConfigParser::FillTraceConfig(isolate, trace_config, json_str);
346 std::unique_ptr<base::OS::MemoryMappedFile> file)
347 : file_(std::move(file)) {}
348 const char*
data()
const override {
349 return static_cast<char*
>(file_->memory());
351 size_t length()
const override {
return file_->size(); }
354 std::unique_ptr<base::OS::MemoryMappedFile> file_;
357 CounterMap* Shell::counter_map_;
358 base::OS::MemoryMappedFile* Shell::counters_file_ =
nullptr;
359 CounterCollection Shell::local_counters_;
360 CounterCollection* Shell::counters_ = &local_counters_;
361 base::LazyMutex Shell::context_mutex_;
362 const base::TimeTicks Shell::kInitialTicks =
363 base::TimeTicks::HighResolutionNow();
364 Global<Function> Shell::stringify_function_;
365 base::LazyMutex Shell::workers_mutex_;
366 bool Shell::allow_new_workers_ =
true;
367 std::vector<Worker*> Shell::workers_;
368 std::vector<ExternalizedContents> Shell::externalized_contents_;
369 std::atomic<bool> Shell::script_executed_{
false};
370 base::LazyMutex Shell::isolate_status_lock_;
371 std::map<v8::Isolate*, bool> Shell::isolate_status_;
372 base::LazyMutex Shell::cached_code_mutex_;
373 std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
374 Shell::cached_code_map_;
376 Global<Context> Shell::evaluation_context_;
377 ArrayBuffer::Allocator* Shell::array_buffer_allocator;
378 ShellOptions Shell::options;
379 base::OnceType Shell::quit_once_ = V8_ONCE_INIT;
385 source_length_ = source->Utf8Length(isolate);
386 source_buffer_.reset(
new uint8_t[source_length_]);
387 source->WriteUtf8(isolate, reinterpret_cast<char*>(source_buffer_.get()),
395 *src = source_buffer_.release();
398 return source_length_;
403 std::unique_ptr<uint8_t[]> source_buffer_;
410 :
base::Thread(GetThreadOptions(
"BackgroundCompileThread")),
413 v8::ScriptCompiler::StreamedSource::UTF8),
415 &streamed_source_)) {}
417 void Run()
override { task_->Run(); }
420 return &streamed_source_;
426 std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task_;
431 base::MutexGuard lock_guard(cached_code_mutex_.Pointer());
432 CHECK(source->IsString());
435 auto entry = cached_code_map_.find(*key);
436 if (entry != cached_code_map_.end() && entry->second) {
437 int length = entry->second->length;
438 uint8_t* cache =
new uint8_t[length];
439 memcpy(cache, entry->second->data, length);
441 cache, length, ScriptCompiler::CachedData::BufferOwned);
447 void Shell::StoreInCodeCache(Isolate* isolate, Local<Value> source,
448 const ScriptCompiler::CachedData* cache_data) {
449 base::MutexGuard lock_guard(cached_code_mutex_.Pointer());
450 CHECK(source->IsString());
451 if (cache_data ==
nullptr)
return;
454 int length = cache_data->length;
455 uint8_t* cache =
new uint8_t[length];
456 memcpy(cache, cache_data->data, length);
457 cached_code_map_[*key] = std::unique_ptr<ScriptCompiler::CachedData>(
458 new ScriptCompiler::CachedData(cache, length,
459 ScriptCompiler::CachedData::BufferOwned));
463 bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
464 Local<Value> name, PrintResult print_result,
465 ReportExceptions report_exceptions,
466 ProcessMessageQueue process_message_queue) {
467 HandleScope handle_scope(isolate);
468 TryCatch try_catch(isolate);
469 try_catch.SetVerbose(
true);
471 MaybeLocal<Value> maybe_result;
474 PerIsolateData* data = PerIsolateData::Get(isolate);
475 Local<Context> realm =
477 Context::Scope context_scope(realm);
478 MaybeLocal<Script> maybe_script;
479 Local<Context> context(isolate->GetCurrentContext());
480 ScriptOrigin origin(name);
482 if (options.compile_options == ScriptCompiler::kConsumeCodeCache) {
483 ScriptCompiler::CachedData* cached_code =
484 LookupCodeCache(isolate, source);
485 if (cached_code !=
nullptr) {
486 ScriptCompiler::Source script_source(source, origin, cached_code);
488 options.compile_options);
489 CHECK(!cached_code->rejected);
491 ScriptCompiler::Source script_source(source, origin);
493 context, &script_source, ScriptCompiler::kNoCompileOptions);
495 }
else if (options.stress_background_compile) {
497 BackgroundCompileThread background_compile_thread(isolate, source);
498 background_compile_thread.Start();
502 TryCatch ignore_try_catch(isolate);
503 ScriptCompiler::Source script_source(source, origin);
505 ScriptCompiler::kNoCompileOptions));
509 background_compile_thread.Join();
511 context, background_compile_thread.streamed_source(), source, origin);
513 ScriptCompiler::Source script_source(source, origin);
515 options.compile_options);
518 Local<Script> script;
519 if (!maybe_script.ToLocal(&script)) {
521 if (report_exceptions) ReportException(isolate, &try_catch);
525 if (options.code_cache_options ==
526 ShellOptions::CodeCacheOptions::kProduceCache) {
528 ScriptCompiler::CachedData* cached_data =
530 StoreInCodeCache(isolate, source, cached_data);
533 maybe_result = script->Run(realm);
534 if (options.code_cache_options ==
535 ShellOptions::CodeCacheOptions::kProduceCacheAfterExecute) {
537 ScriptCompiler::CachedData* cached_data =
539 StoreInCodeCache(isolate, source, cached_data);
542 if (process_message_queue && !EmptyMessageQueues(isolate)) success =
false;
543 data->realm_current_ = data->realm_switch_;
546 if (!maybe_result.ToLocal(&result)) {
547 DCHECK(try_catch.HasCaught());
549 if (report_exceptions) ReportException(isolate, &try_catch);
552 DCHECK(!try_catch.HasCaught());
554 if (options.test_shell) {
555 if (!result->IsUndefined()) {
559 fwrite(*str,
sizeof(**str), str.length(), stdout);
564 fwrite(*str,
sizeof(**str), str.length(), stdout);
573 std::string ToSTLString(Isolate* isolate, Local<String> v8_str) {
574 String::Utf8Value utf8(isolate, v8_str);
580 bool IsAbsolutePath(
const std::string& path) {
581 #if defined(_WIN32) || defined(_WIN64) 584 return path.find(
':') != std::string::npos;
586 return path[0] ==
'/';
590 std::string GetWorkingDirectory() {
591 #if defined(_WIN32) || defined(_WIN64) 592 char system_buffer[MAX_PATH];
594 DWORD len = GetCurrentDirectoryA(MAX_PATH, system_buffer);
596 return system_buffer;
598 char curdir[PATH_MAX];
599 CHECK_NOT_NULL(getcwd(curdir, PATH_MAX));
605 std::string DirName(
const std::string& path) {
606 DCHECK(IsAbsolutePath(path));
607 size_t last_slash = path.find_last_of(
'/');
608 DCHECK(last_slash != std::string::npos);
609 return path.substr(0, last_slash);
615 std::string NormalizePath(
const std::string& path,
616 const std::string& dir_name) {
618 if (IsAbsolutePath(path)) {
621 result = dir_name +
'/' + path;
623 std::replace(result.begin(), result.end(),
'\\',
'/');
625 while ((
i = result.find(
"/./")) != std::string::npos) {
633 class ModuleEmbedderData {
635 class ModuleGlobalHash {
637 explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {}
638 size_t operator()(
const Global<Module>& module)
const {
639 return module.Get(isolate_)->GetIdentityHash();
647 explicit ModuleEmbedderData(Isolate* isolate)
648 : module_to_specifier_map(10, ModuleGlobalHash(isolate)) {}
651 std::unordered_map<std::string, Global<Module>> specifier_to_module_map;
653 std::unordered_map<Global<Module>, std::string, ModuleGlobalHash>
654 module_to_specifier_map;
658 kModuleEmbedderDataIndex,
659 kInspectorClientIndex
662 void InitializeModuleEmbedderData(Local<Context> context) {
663 context->SetAlignedPointerInEmbedderData(
664 kModuleEmbedderDataIndex,
new ModuleEmbedderData(context->GetIsolate()));
667 ModuleEmbedderData* GetModuleDataFromContext(Local<Context> context) {
668 return static_cast<ModuleEmbedderData*
>(
669 context->GetAlignedPointerFromEmbedderData(kModuleEmbedderDataIndex));
672 void DisposeModuleEmbedderData(Local<Context> context) {
673 delete GetModuleDataFromContext(context);
674 context->SetAlignedPointerInEmbedderData(kModuleEmbedderDataIndex,
nullptr);
677 MaybeLocal<Module> ResolveModuleCallback(Local<Context> context,
678 Local<String> specifier,
679 Local<Module> referrer) {
680 Isolate* isolate = context->GetIsolate();
681 ModuleEmbedderData* d = GetModuleDataFromContext(context);
683 d->module_to_specifier_map.find(Global<Module>(isolate, referrer));
684 CHECK(specifier_it != d->module_to_specifier_map.end());
685 std::string absolute_path = NormalizePath(ToSTLString(isolate, specifier),
686 DirName(specifier_it->second));
687 auto module_it = d->specifier_to_module_map.find(absolute_path);
688 CHECK(module_it != d->specifier_to_module_map.end());
689 return module_it->second.Get(isolate);
694 MaybeLocal<Module> Shell::FetchModuleTree(Local<Context> context,
695 const std::string& file_name) {
696 DCHECK(IsAbsolutePath(file_name));
697 Isolate* isolate = context->GetIsolate();
698 Local<String> source_text = ReadFile(isolate, file_name.c_str());
699 if (source_text.IsEmpty()) {
700 std::string msg =
"Error reading: " + file_name;
701 Throw(isolate, msg.c_str());
702 return MaybeLocal<Module>();
707 Local<Integer>(), Local<Integer>(), Local<Boolean>(), Local<Integer>(),
708 Local<Value>(), Local<Boolean>(), Local<Boolean>(), True(isolate));
709 ScriptCompiler::Source source(source_text, origin);
710 Local<Module> module;
712 return MaybeLocal<Module>();
715 ModuleEmbedderData* d = GetModuleDataFromContext(context);
716 CHECK(d->specifier_to_module_map
717 .insert(std::make_pair(file_name, Global<Module>(isolate, module)))
719 CHECK(d->module_to_specifier_map
720 .insert(std::make_pair(Global<Module>(isolate, module), file_name))
723 std::string dir_name = DirName(file_name);
725 for (
int i = 0, length = module->GetModuleRequestsLength();
i < length; ++
i) {
726 Local<String> name = module->GetModuleRequest(
i);
727 std::string absolute_path =
728 NormalizePath(ToSTLString(isolate, name), dir_name);
729 if (!d->specifier_to_module_map.count(absolute_path)) {
730 if (FetchModuleTree(context, absolute_path).IsEmpty()) {
731 return MaybeLocal<Module>();
741 struct DynamicImportData {
742 DynamicImportData(Isolate* isolate_, Local<String> referrer_,
743 Local<String> specifier_,
744 Local<Promise::Resolver> resolver_)
745 : isolate(isolate_) {
746 referrer.Reset(isolate, referrer_);
747 specifier.Reset(isolate, specifier_);
748 resolver.Reset(isolate, resolver_);
752 Global<String> referrer;
753 Global<String> specifier;
754 Global<Promise::Resolver> resolver;
759 MaybeLocal<Promise> Shell::HostImportModuleDynamically(
760 Local<Context> context, Local<ScriptOrModule> referrer,
761 Local<String> specifier) {
762 Isolate* isolate = context->GetIsolate();
764 MaybeLocal<Promise::Resolver> maybe_resolver =
766 Local<Promise::Resolver> resolver;
767 if (maybe_resolver.ToLocal(&resolver)) {
768 DynamicImportData* data =
new DynamicImportData(
771 isolate->EnqueueMicrotask(Shell::DoHostImportModuleDynamically, data);
772 return resolver->GetPromise();
775 return MaybeLocal<Promise>();
778 void Shell::HostInitializeImportMetaObject(Local<Context> context,
779 Local<Module> module,
780 Local<Object> meta) {
781 Isolate* isolate = context->GetIsolate();
782 HandleScope handle_scope(isolate);
784 ModuleEmbedderData* d = GetModuleDataFromContext(context);
786 d->module_to_specifier_map.find(Global<Module>(isolate, module));
787 CHECK(specifier_it != d->module_to_specifier_map.end());
789 Local<String> url_key =
795 meta->CreateDataProperty(context, url_key, url).ToChecked();
798 void Shell::DoHostImportModuleDynamically(
void* import_data) {
799 std::unique_ptr<DynamicImportData> import_data_(
800 static_cast<DynamicImportData*>(import_data));
801 Isolate* isolate(import_data_->isolate);
802 HandleScope handle_scope(isolate);
804 Local<String> referrer(import_data_->referrer.Get(isolate));
805 Local<String> specifier(import_data_->specifier.Get(isolate));
806 Local<Promise::Resolver> resolver(import_data_->resolver.Get(isolate));
808 PerIsolateData* data = PerIsolateData::Get(isolate);
809 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
810 Context::Scope context_scope(realm);
812 std::string source_url = ToSTLString(isolate, referrer);
813 std::string dir_name =
814 DirName(NormalizePath(source_url, GetWorkingDirectory()));
815 std::string file_name = ToSTLString(isolate, specifier);
816 std::string absolute_path = NormalizePath(file_name, dir_name);
818 TryCatch try_catch(isolate);
819 try_catch.SetVerbose(
true);
821 ModuleEmbedderData* d = GetModuleDataFromContext(realm);
822 Local<Module> root_module;
823 auto module_it = d->specifier_to_module_map.find(absolute_path);
824 if (module_it != d->specifier_to_module_map.end()) {
825 root_module = module_it->second.Get(isolate);
826 }
else if (!FetchModuleTree(realm, absolute_path).ToLocal(&root_module)) {
827 CHECK(try_catch.HasCaught());
828 resolver->Reject(realm, try_catch.Exception()).ToChecked();
832 MaybeLocal<Value> maybe_result;
833 if (root_module->InstantiateModule(realm, ResolveModuleCallback)
835 maybe_result = root_module->Evaluate(realm);
836 EmptyMessageQueues(isolate);
840 if (!maybe_result.ToLocal(&module)) {
841 DCHECK(try_catch.HasCaught());
842 resolver->Reject(realm, try_catch.Exception()).ToChecked();
846 DCHECK(!try_catch.HasCaught());
847 Local<Value> module_namespace = root_module->GetModuleNamespace();
848 resolver->Resolve(realm, module_namespace).ToChecked();
851 bool Shell::ExecuteModule(Isolate* isolate,
const char* file_name) {
852 HandleScope handle_scope(isolate);
854 PerIsolateData* data = PerIsolateData::Get(isolate);
855 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
856 Context::Scope context_scope(realm);
858 std::string absolute_path = NormalizePath(file_name, GetWorkingDirectory());
860 TryCatch try_catch(isolate);
861 try_catch.SetVerbose(
true);
863 Local<Module> root_module;
864 MaybeLocal<Value> maybe_exception;
866 if (!FetchModuleTree(realm, absolute_path).ToLocal(&root_module)) {
867 CHECK(try_catch.HasCaught());
868 ReportException(isolate, &try_catch);
872 MaybeLocal<Value> maybe_result;
873 if (root_module->InstantiateModule(realm, ResolveModuleCallback)
875 maybe_result = root_module->Evaluate(realm);
876 EmptyMessageQueues(isolate);
879 if (!maybe_result.ToLocal(&result)) {
880 DCHECK(try_catch.HasCaught());
882 ReportException(isolate, &try_catch);
885 DCHECK(!try_catch.HasCaught());
889 PerIsolateData::PerIsolateData(Isolate* isolate)
890 : isolate_(isolate), realms_(nullptr) {
891 isolate->SetData(0,
this);
892 if (i::FLAG_expose_async_hooks) {
893 async_hooks_wrapper_ =
new AsyncHooks(isolate);
897 PerIsolateData::~PerIsolateData() {
898 isolate_->SetData(0,
nullptr);
899 if (i::FLAG_expose_async_hooks) {
900 delete async_hooks_wrapper_;
904 void PerIsolateData::SetTimeout(Local<Function> callback,
905 Local<Context> context) {
906 set_timeout_callbacks_.emplace(isolate_, callback);
907 set_timeout_contexts_.emplace(isolate_, context);
910 MaybeLocal<Function> PerIsolateData::GetTimeoutCallback() {
911 if (set_timeout_callbacks_.empty())
return MaybeLocal<Function>();
912 Local<Function> result = set_timeout_callbacks_.front().Get(isolate_);
913 set_timeout_callbacks_.pop();
917 MaybeLocal<Context> PerIsolateData::GetTimeoutContext() {
918 if (set_timeout_contexts_.empty())
return MaybeLocal<Context>();
919 Local<Context> result = set_timeout_contexts_.front().Get(isolate_);
920 set_timeout_contexts_.pop();
924 PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
925 data_->realm_count_ = 1;
926 data_->realm_current_ = 0;
927 data_->realm_switch_ = 0;
928 data_->realms_ =
new Global<Context>[1];
929 data_->realms_[0].Reset(data_->isolate_,
930 data_->isolate_->GetEnteredOrMicrotaskContext());
934 PerIsolateData::RealmScope::~RealmScope() {
938 for (
int i = 1;
i < data_->realm_count_; ++
i) {
939 Global<Context>& realm = data_->realms_[
i];
940 if (realm.IsEmpty())
continue;
941 DisposeModuleEmbedderData(realm.Get(data_->isolate_));
945 data_->realm_count_ = 0;
946 delete[] data_->realms_;
948 if (!data_->realm_shared_.IsEmpty())
949 data_->realm_shared_.Reset();
953 int PerIsolateData::RealmFind(Local<Context> context) {
954 for (
int i = 0;
i < realm_count_; ++
i) {
955 if (realms_[
i] == context)
return i;
961 int PerIsolateData::RealmIndexOrThrow(
964 if (args.Length() < arg_offset || !args[arg_offset]->IsNumber()) {
965 Throw(args.GetIsolate(),
"Invalid argument");
968 int index = args[arg_offset]
969 ->Int32Value(args.GetIsolate()->GetCurrentContext())
971 if (index < 0 || index >= realm_count_ || realms_[index].IsEmpty()) {
972 Throw(args.GetIsolate(),
"Invalid realm index");
983 if (i::FLAG_verify_predictable) {
986 base::TimeDelta delta =
987 base::TimeTicks::HighResolutionNow() - kInitialTicks;
988 args.GetReturnValue().Set(delta.InMillisecondsF());
995 Isolate* isolate = args.GetIsolate();
996 PerIsolateData* data = PerIsolateData::Get(isolate);
997 int index = data->RealmFind(isolate->GetEnteredOrMicrotaskContext());
998 if (index == -1)
return;
999 args.GetReturnValue().Set(index);
1005 Isolate* isolate = args.GetIsolate();
1006 PerIsolateData* data = PerIsolateData::Get(isolate);
1007 if (args.Length() < 1 || !args[0]->IsObject()) {
1008 Throw(args.GetIsolate(),
"Invalid argument");
1011 int index = data->RealmFind(args[0]
1012 ->ToObject(isolate->GetCurrentContext())
1014 ->CreationContext());
1015 if (index == -1)
return;
1016 args.GetReturnValue().Set(index);
1023 PerIsolateData* data = PerIsolateData::Get(args.GetIsolate());
1024 int index = data->RealmIndexOrThrow(args, 0);
1025 if (index == -1)
return;
1026 args.GetReturnValue().Set(
1030 MaybeLocal<Context> Shell::CreateRealm(
1033 Isolate* isolate = args.GetIsolate();
1034 TryCatch try_catch(isolate);
1035 PerIsolateData* data = PerIsolateData::Get(isolate);
1037 Global<Context>* old_realms = data->realms_;
1038 index = data->realm_count_;
1039 data->realms_ =
new Global<Context>[++data->realm_count_];
1040 for (
int i = 0;
i < index; ++
i) {
1041 data->realms_[
i].Reset(isolate, old_realms[
i]);
1042 old_realms[
i].Reset();
1044 delete[] old_realms;
1046 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
1047 Local<Context> context =
1048 Context::New(isolate,
nullptr, global_template, global_object);
1049 DCHECK(!try_catch.HasCaught());
1050 if (context.IsEmpty())
return MaybeLocal<Context>();
1051 InitializeModuleEmbedderData(context);
1052 data->realms_[index].Reset(isolate, context);
1053 args.GetReturnValue().Set(index);
1059 Isolate* isolate = args.GetIsolate();
1060 PerIsolateData* data = PerIsolateData::Get(isolate);
1061 DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
1062 data->realms_[index].Reset();
1063 isolate->ContextDisposedNotification();
1075 void Shell::RealmCreateAllowCrossRealmAccess(
1077 Local<Context> context;
1079 context->SetSecurityToken(
1080 args.GetIsolate()->GetEnteredOrMicrotaskContext()->GetSecurityToken());
1087 Isolate* isolate = args.GetIsolate();
1088 PerIsolateData* data = PerIsolateData::Get(isolate);
1089 int index = data->RealmIndexOrThrow(args, 0);
1090 if (index == -1)
return;
1091 if (index == 0 || index == data->realm_current_ ||
1092 index == data->realm_switch_) {
1093 Throw(args.GetIsolate(),
"Invalid realm index");
1099 DisposeRealm(args, index);
1100 CreateRealm(args, index, global_object);
1105 Isolate* isolate = args.GetIsolate();
1106 PerIsolateData* data = PerIsolateData::Get(isolate);
1107 int index = data->RealmIndexOrThrow(args, 0);
1108 if (index == -1)
return;
1110 index == data->realm_current_ || index == data->realm_switch_) {
1111 Throw(args.GetIsolate(),
"Invalid realm index");
1114 DisposeRealm(args, index);
1120 Isolate* isolate = args.GetIsolate();
1121 PerIsolateData* data = PerIsolateData::Get(isolate);
1122 int index = data->RealmIndexOrThrow(args, 0);
1123 if (index == -1)
return;
1124 data->realm_switch_ = index;
1130 Isolate* isolate = args.GetIsolate();
1131 PerIsolateData* data = PerIsolateData::Get(isolate);
1132 int index = data->RealmIndexOrThrow(args, 0);
1133 if (index == -1)
return;
1134 if (args.Length() < 2 || !args[1]->IsString()) {
1135 Throw(args.GetIsolate(),
"Invalid argument");
1138 ScriptCompiler::Source script_source(
1139 args[1]->ToString(isolate->GetCurrentContext()).ToLocalChecked());
1140 Local<UnboundScript> script;
1142 .ToLocal(&script)) {
1147 int previous_index = data->realm_current_;
1148 data->realm_current_ = data->realm_switch_ = index;
1149 Local<Value> result;
1150 if (!script->BindToCurrentContext()->Run(realm).ToLocal(&result)) {
1152 data->realm_current_ = data->realm_switch_ = previous_index;
1156 data->realm_current_ = data->realm_switch_ = previous_index;
1157 args.GetReturnValue().Set(result);
1162 void Shell::RealmSharedGet(Local<String> property,
1163 const PropertyCallbackInfo<Value>& info) {
1164 Isolate* isolate = info.GetIsolate();
1165 PerIsolateData* data = PerIsolateData::Get(isolate);
1166 if (data->realm_shared_.IsEmpty())
return;
1167 info.GetReturnValue().Set(data->realm_shared_);
1170 void Shell::RealmSharedSet(Local<String> property,
1172 const PropertyCallbackInfo<void>& info) {
1173 Isolate* isolate = info.GetIsolate();
1174 PerIsolateData* data = PerIsolateData::Get(isolate);
1175 data->realm_shared_.Reset(isolate, value);
1180 void Shell::AsyncHooksCreateHook(
1182 Local<Object> wrap =
1183 PerIsolateData::Get(args.GetIsolate())->GetAsyncHooks()->CreateHook(args);
1184 args.GetReturnValue().Set(wrap);
1189 void Shell::AsyncHooksExecutionAsyncId(
1191 Isolate* isolate = args.GetIsolate();
1192 HandleScope handle_scope(isolate);
1193 args.GetReturnValue().Set(v8::Number::New(
1195 PerIsolateData::Get(isolate)->GetAsyncHooks()->GetExecutionAsyncId()));
1198 void Shell::AsyncHooksTriggerAsyncId(
1200 Isolate* isolate = args.GetIsolate();
1201 HandleScope handle_scope(isolate);
1202 args.GetReturnValue().Set(v8::Number::New(
1204 PerIsolateData::Get(isolate)->GetAsyncHooks()->GetTriggerAsyncId()));
1208 for (
int i = 0;
i < args.Length();
i++) {
1209 HandleScope handle_scope(args.GetIsolate());
1215 v8::TryCatch try_catch(args.GetIsolate());
1216 Local<Value> arg = args[
i];
1217 Local<String> str_obj;
1219 if (arg->IsSymbol()) {
1222 if (!arg->ToString(args.GetIsolate()->GetCurrentContext())
1223 .ToLocal(&str_obj)) {
1224 try_catch.ReThrow();
1229 int n =
static_cast<int>(fwrite(*str,
sizeof(**str), str.length(), file));
1230 if (n != str.length()) {
1231 printf(
"Error in fwrite\n");
1232 base::OS::ExitProcess(1);
1237 void WriteAndFlush(FILE* file,
1239 WriteToFile(file, args);
1240 fprintf(file,
"\n");
1245 WriteAndFlush(stdout, args);
1249 WriteAndFlush(stderr, args);
1253 WriteToFile(stdout, args);
1257 String::Utf8Value file(args.GetIsolate(), args[0]);
1258 if (*file ==
nullptr) {
1259 Throw(args.GetIsolate(),
"Error loading file");
1262 if (args.Length() == 2) {
1263 String::Utf8Value format(args.GetIsolate(), args[1]);
1264 if (*format && std::strcmp(*format,
"binary") == 0) {
1269 Local<String> source = ReadFile(args.GetIsolate(), *file);
1270 if (source.IsEmpty()) {
1271 Throw(args.GetIsolate(),
"Error loading file");
1274 args.GetReturnValue().Set(source);
1278 Local<String> Shell::ReadFromStdin(Isolate* isolate) {
1279 static const int kBufferSize = 256;
1280 char buffer[kBufferSize];
1281 Local<String> accumulator =
1288 char* input =
nullptr;
1289 input = fgets(buffer, kBufferSize, stdin);
1290 if (input ==
nullptr)
return Local<String>();
1291 length =
static_cast<int>(strlen(buffer));
1294 }
else if (buffer[length-1] !=
'\n') {
1296 isolate, accumulator,
1299 }
else if (length > 1 && buffer[length-2] ==
'\\') {
1300 buffer[length-2] =
'\n';
1308 isolate, accumulator,
1318 for (
int i = 0;
i < args.Length();
i++) {
1319 HandleScope handle_scope(args.GetIsolate());
1320 String::Utf8Value file(args.GetIsolate(), args[
i]);
1321 if (*file ==
nullptr) {
1322 Throw(args.GetIsolate(),
"Error loading file");
1325 Local<String> source = ReadFile(args.GetIsolate(), *file);
1326 if (source.IsEmpty()) {
1327 Throw(args.GetIsolate(),
"Error loading file");
1331 args.GetIsolate(), source,
1336 options.quiet_load ? kNoReportExceptions : kReportExceptions,
1337 kNoProcessMessageQueue)) {
1338 Throw(args.GetIsolate(),
"Error executing file");
1345 Isolate* isolate = args.GetIsolate();
1346 args.GetReturnValue().Set(v8::Number::New(isolate, 0));
1347 if (args.Length() == 0 || !args[0]->IsFunction())
return;
1349 Local<Context> context = isolate->GetCurrentContext();
1350 PerIsolateData::Get(isolate)->SetTimeout(callback, context);
1354 Isolate* isolate = args.GetIsolate();
1355 HandleScope handle_scope(isolate);
1356 if (args.Length() < 1 || !args[0]->IsString()) {
1357 Throw(args.GetIsolate(),
"1st argument must be string");
1363 bool load_from_file =
true;
1364 if (args.Length() > 1 && args[1]->IsObject()) {
1365 Local<Object>
object = args[1].As<Object>();
1366 Local<Context> context = isolate->GetCurrentContext();
1367 Local<Value> value = GetValue(args.GetIsolate(), context, object,
"type");
1368 if (value->IsString()) {
1369 Local<String> worker_type = value->ToString(context).ToLocalChecked();
1370 String::Utf8Value str(isolate, worker_type);
1371 if (strcmp(
"string", *str) == 0) {
1372 load_from_file =
false;
1373 }
else if (strcmp(
"classic", *str) == 0) {
1374 load_from_file =
true;
1376 Throw(args.GetIsolate(),
"Unsupported worker type");
1382 Local<Value> source;
1383 if (load_from_file) {
1384 String::Utf8Value filename(args.GetIsolate(), args[0]);
1385 source = ReadFile(args.GetIsolate(), *filename);
1386 if (source.IsEmpty()) {
1387 Throw(args.GetIsolate(),
"Error loading worker script");
1394 if (!args.IsConstructCall()) {
1395 Throw(args.GetIsolate(),
"Worker must be constructed with new");
1400 base::MutexGuard lock_guard(workers_mutex_.Pointer());
1401 if (workers_.size() >= kMaxWorkers) {
1402 Throw(args.GetIsolate(),
"Too many workers, I won't let you create more");
1409 args.Holder()->SetAlignedPointerInInternalField(0,
nullptr);
1411 if (!allow_new_workers_)
return;
1413 Worker* worker =
new Worker;
1414 args.Holder()->SetAlignedPointerInInternalField(0, worker);
1415 workers_.push_back(worker);
1417 String::Utf8Value script(args.GetIsolate(), source);
1419 Throw(args.GetIsolate(),
"Can't get worker script");
1422 worker->StartExecuteInThread(*script);
1428 Isolate* isolate = args.GetIsolate();
1429 HandleScope handle_scope(isolate);
1431 if (args.Length() < 1) {
1432 Throw(isolate,
"Invalid argument");
1436 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1441 Local<Value> message = args[0];
1442 Local<Value> transfer =
1444 std::unique_ptr<SerializationData> data =
1445 Shell::SerializeValue(isolate, message, transfer);
1447 worker->PostMessage(std::move(data));
1453 Isolate* isolate = args.GetIsolate();
1454 HandleScope handle_scope(isolate);
1455 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1460 std::unique_ptr<SerializationData> data = worker->GetMessage();
1463 if (Shell::DeserializeValue(isolate, std::move(data)).ToLocal(&value)) {
1464 args.GetReturnValue().Set(value);
1471 Isolate* isolate = args.GetIsolate();
1472 HandleScope handle_scope(isolate);
1473 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1478 worker->Terminate();
1483 int exit_code = (*args)[0]
1484 ->Int32Value(args->GetIsolate()->GetCurrentContext())
1487 args->GetIsolate()->Exit();
1488 OnExit(args->GetIsolate());
1489 base::OS::ExitProcess(exit_code);
1494 base::CallOnce(&quit_once_, &QuitOnce,
1499 SetWaitUntilDone(args.GetIsolate(),
true);
1503 SetWaitUntilDone(args.GetIsolate(),
false);
1507 args.GetReturnValue().Set(
1513 void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
1514 HandleScope handle_scope(isolate);
1515 Local<Context> context = isolate->GetCurrentContext();
1516 bool enter_context = context.IsEmpty();
1517 if (enter_context) {
1523 return *value ? *value :
"<string conversion failed>";
1527 const char* exception_string = ToCString(exception);
1528 Local<Message> message = try_catch->Message();
1529 if (message.IsEmpty()) {
1532 printf(
"%s\n", exception_string);
1533 }
else if (message->GetScriptOrigin().Options().IsWasm()) {
1535 int function_index = message->GetLineNumber(context).FromJust() - 1;
1536 int offset = message->GetStartColumn(context).FromJust();
1537 printf(
"wasm-function[%d]:%d: %s\n", function_index, offset,
1542 message->GetScriptOrigin().ResourceName());
1543 const char* filename_string = ToCString(filename);
1544 int linenum = message->GetLineNumber(context).FromMaybe(-1);
1545 printf(
"%s:%i: %s\n", filename_string, linenum, exception_string);
1546 Local<String> sourceline;
1547 if (message->GetSourceLine(context).ToLocal(&sourceline)) {
1550 const char* sourceline_string = ToCString(sourcelinevalue);
1551 printf(
"%s\n", sourceline_string);
1553 int start = message->GetStartColumn(context).FromJust();
1554 for (
int i = 0;
i < start;
i++) {
1557 int end = message->GetEndColumn(context).FromJust();
1558 for (
int i = start;
i < end;
i++) {
1564 Local<Value> stack_trace_string;
1565 if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
1566 stack_trace_string->IsString()) {
1569 printf(
"%s\n", ToCString(stack_trace));
1572 if (enter_context) context->Exit();
1576 int32_t* Counter::Bind(
const char* name,
bool is_histogram) {
1578 for (
i = 0;
i < kMaxNameSize - 1 && name[
i];
i++)
1579 name_[
i] = static_cast<char>(name[
i]);
1581 is_histogram_ = is_histogram;
1586 void Counter::AddSample(int32_t sample) {
1588 sample_total_ += sample;
1592 CounterCollection::CounterCollection() {
1593 magic_number_ = 0xDEADFACE;
1594 max_counters_ = kMaxCounters;
1595 max_name_size_ = Counter::kMaxNameSize;
1596 counters_in_use_ = 0;
1600 Counter* CounterCollection::GetNextCounter() {
1601 if (counters_in_use_ == kMaxCounters)
return nullptr;
1602 return &counters_[counters_in_use_++];
1606 void Shell::MapCounters(v8::Isolate* isolate,
const char* name) {
1607 counters_file_ = base::OS::MemoryMappedFile::create(
1608 name,
sizeof(CounterCollection), &local_counters_);
1610 (counters_file_ ==
nullptr) ?
nullptr : counters_file_->memory();
1611 if (memory ==
nullptr) {
1612 printf(
"Could not map counters file %s\n", name);
1613 base::OS::ExitProcess(1);
1615 counters_ =
static_cast<CounterCollection*
>(memory);
1616 isolate->SetCounterFunction(LookupCounter);
1617 isolate->SetCreateHistogramFunction(CreateHistogram);
1618 isolate->SetAddHistogramSampleFunction(AddHistogramSample);
1621 Counter* Shell::GetCounter(
const char* name,
bool is_histogram) {
1622 auto map_entry = counter_map_->find(name);
1624 map_entry != counter_map_->end() ? map_entry->second :
nullptr;
1626 if (counter ==
nullptr) {
1627 counter = counters_->GetNextCounter();
1628 if (counter !=
nullptr) {
1629 (*counter_map_)[name] = counter;
1630 counter->Bind(name, is_histogram);
1633 DCHECK(counter->is_histogram() == is_histogram);
1639 int* Shell::LookupCounter(
const char* name) {
1640 Counter* counter = GetCounter(name,
false);
1642 if (counter !=
nullptr) {
1643 return counter->ptr();
1650 void* Shell::CreateHistogram(
const char* name,
1654 return GetCounter(name,
true);
1658 void Shell::AddHistogramSample(
void* histogram,
int sample) {
1659 Counter* counter =
reinterpret_cast<Counter*
>(histogram);
1660 counter->AddSample(sample);
1664 Local<String> Shell::Stringify(Isolate* isolate, Local<Value> value) {
1667 if (stringify_function_.IsEmpty()) {
1673 Local<String> source =
1677 Local<String> name =
1681 ScriptOrigin origin(name);
1682 Local<Script> script =
1684 stringify_function_.Reset(
1685 isolate, script->Run(context).ToLocalChecked().As<Function>());
1688 Local<Value> argv[1] = {value};
1689 v8::TryCatch try_catch(isolate);
1690 MaybeLocal<Value> result = fun->Call(context, Undefined(isolate), 1, argv);
1692 return result.ToLocalChecked().As<String>();
1696 Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
1698 global_template->Set(
1702 global_template->Set(
1706 global_template->Set(
1710 global_template->Set(
1714 global_template->Set(
1718 global_template->Set(
1722 global_template->Set(
1726 global_template->Set(
1733 if (!options.omit_quit) {
1734 global_template->Set(
1740 global_template->Set(
1752 global_template->Set(
1756 global_template->Set(
1757 Symbol::GetToStringTag(isolate),
1763 realm_template->Set(
1767 realm_template->Set(
1771 realm_template->Set(
1775 realm_template->Set(
1779 realm_template->Set(
1784 realm_template->Set(
1788 realm_template->Set(
1792 realm_template->Set(
1796 realm_template->Set(
1800 realm_template->SetAccessor(
1803 RealmSharedGet, RealmSharedSet);
1804 global_template->Set(
1810 performance_template->Set(
1814 global_template->Set(
1817 performance_template);
1819 Local<FunctionTemplate> worker_fun_template =
1821 Local<Signature> worker_signature =
1822 Signature::New(isolate, worker_fun_template);
1823 worker_fun_template->SetClassName(
1826 worker_fun_template->ReadOnlyPrototype();
1827 worker_fun_template->PrototypeTemplate()->Set(
1832 worker_fun_template->PrototypeTemplate()->Set(
1837 worker_fun_template->PrototypeTemplate()->Set(
1842 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
1843 global_template->Set(
1846 worker_fun_template);
1849 AddOSMethods(isolate, os_templ);
1850 global_template->Set(
1855 if (i::FLAG_expose_async_hooks) {
1857 async_hooks_templ->Set(
1861 async_hooks_templ->Set(
1865 async_hooks_templ->Set(
1869 global_template->Set(
1875 return global_template;
1878 static void PrintNonErrorsMessageCallback(Local<Message> message,
1879 Local<Value> error) {
1884 switch (message->ErrorLevel()) {
1885 case v8::Isolate::kMessageWarning:
1886 case v8::Isolate::kMessageLog:
1887 case v8::Isolate::kMessageInfo:
1888 case v8::Isolate::kMessageDebug: {
1892 case v8::Isolate::kMessageError: {
1904 return *value ? *value :
"<string conversion failed>";
1906 Isolate* isolate = Isolate::GetCurrent();
1908 const char* msg_string = ToCString(msg);
1911 message->GetScriptOrigin().ResourceName());
1912 const char* filename_string = ToCString(filename);
1913 Maybe<int> maybeline = message->GetLineNumber(isolate->GetCurrentContext());
1914 int linenum = maybeline.IsJust() ? maybeline.FromJust() : -1;
1915 printf(
"%s:%i: %s\n", filename_string, linenum, msg_string);
1918 void Shell::Initialize(Isolate* isolate) {
1920 if (i::StrLength(i::FLAG_map_counters) != 0)
1921 MapCounters(isolate, i::FLAG_map_counters);
1923 isolate->AddMessageListenerWithErrorLevel(
1924 PrintNonErrorsMessageCallback,
1925 v8::Isolate::kMessageError | v8::Isolate::kMessageWarning |
1926 v8::Isolate::kMessageInfo | v8::Isolate::kMessageDebug |
1927 v8::Isolate::kMessageLog);
1931 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
1933 base::MutexGuard lock_guard(context_mutex_.Pointer());
1935 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
1936 EscapableHandleScope handle_scope(isolate);
1937 Local<Context> context = Context::New(isolate,
nullptr, global_template);
1938 DCHECK(!context.IsEmpty());
1939 InitializeModuleEmbedderData(context);
1940 if (options.include_arguments) {
1941 Context::Scope scope(context);
1942 const std::vector<const char*>& args = options.arguments;
1943 int size =
static_cast<int>(args.size());
1944 Local<Array> array =
Array::New(isolate, size);
1945 for (
int i = 0;
i < size;
i++) {
1949 Local<Number> index = v8::Number::New(isolate,
i);
1950 array->Set(context, index, arg).FromJust();
1952 Local<String> name =
1955 context->Global()->Set(context, name, array).FromJust();
1957 return handle_scope.Escape(context);
1967 return strcmp(lhs.key, rhs.key) < 0;
1970 void Shell::WriteIgnitionDispatchCountersFile(v8::Isolate* isolate) {
1971 HandleScope handle_scope(isolate);
1972 Local<Context> context = Context::New(isolate);
1973 Context::Scope context_scope(context);
1975 Local<Object> dispatch_counters =
reinterpret_cast<i::Isolate*
>(isolate)
1977 ->GetDispatchCountersObject();
1978 std::ofstream dispatch_counters_stream(
1979 i::FLAG_trace_ignition_dispatches_output_file);
1980 dispatch_counters_stream << *String::Utf8Value(
1981 isolate,
JSON::Stringify(context, dispatch_counters).ToLocalChecked());
1985 int LineFromOffset(Local<debug::Script> script,
int offset) {
1986 debug::Location location = script->GetSourceLocation(offset);
1987 return location.GetLineNumber();
1990 void WriteLcovDataForRange(std::vector<uint32_t>& lines,
int start_line,
1993 lines.resize(std::max(static_cast<size_t>(end_line + 1), lines.size()), 0);
1996 lines[start_line] = std::max(lines[start_line], count);
1997 lines[end_line] = std::max(lines[end_line], count);
1999 for (
int k = start_line + 1; k < end_line; k++) lines[k] = count;
2002 void WriteLcovDataForNamedRange(std::ostream& sink,
2003 std::vector<uint32_t>& lines,
2004 const std::string& name,
int start_line,
2006 WriteLcovDataForRange(lines, start_line, end_line, count);
2007 sink <<
"FN:" << start_line + 1 <<
"," << name << std::endl;
2008 sink <<
"FNDA:" << count <<
"," << name << std::endl;
2013 void Shell::WriteLcovData(v8::Isolate* isolate,
const char* file) {
2015 HandleScope handle_scope(isolate);
2016 debug::Coverage coverage = debug::Coverage::CollectPrecise(isolate);
2017 std::ofstream sink(file, std::ofstream::app);
2018 for (
size_t i = 0;
i < coverage.ScriptCount();
i++) {
2019 debug::Coverage::ScriptData script_data = coverage.GetScriptData(
i);
2020 Local<debug::Script> script = script_data.GetScript();
2023 if (!script->Name().ToLocal(&name))
continue;
2024 std::string file_name = ToSTLString(isolate, name);
2026 if (!std::ifstream(file_name).good())
continue;
2028 sink << NormalizePath(file_name, GetWorkingDirectory()) << std::endl;
2029 std::vector<uint32_t> lines;
2030 for (
size_t j = 0; j < script_data.FunctionCount(); j++) {
2031 debug::Coverage::FunctionData function_data =
2032 script_data.GetFunctionData(j);
2036 debug::Location start =
2037 script->GetSourceLocation(function_data.StartOffset());
2038 debug::Location end =
2039 script->GetSourceLocation(function_data.EndOffset());
2040 int start_line = start.GetLineNumber();
2041 int end_line = end.GetLineNumber();
2042 uint32_t count = function_data.Count();
2045 std::stringstream name_stream;
2046 if (function_data.Name().ToLocal(&name)) {
2047 name_stream << ToSTLString(isolate, name);
2049 name_stream <<
"<" << start_line + 1 <<
"-";
2050 name_stream << start.GetColumnNumber() <<
">";
2053 WriteLcovDataForNamedRange(sink, lines, name_stream.str(), start_line,
2058 for (
size_t k = 0; k < function_data.BlockCount(); k++) {
2059 debug::Coverage::BlockData block_data = function_data.GetBlockData(k);
2060 int start_line = LineFromOffset(script, block_data.StartOffset());
2061 int end_line = LineFromOffset(script, block_data.EndOffset() - 1);
2062 uint32_t count = block_data.Count();
2063 WriteLcovDataForRange(lines, start_line, end_line, count);
2067 for (
size_t i = 0;
i < lines.size();
i++) {
2068 sink <<
"DA:" << (
i + 1) <<
"," << lines[
i] << std::endl;
2070 sink <<
"end_of_record" << std::endl;
2074 void Shell::OnExit(v8::Isolate* isolate) {
2076 if (i::FLAG_turbo_profiling) {
2082 if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp) {
2083 const int number_of_counters =
static_cast<int>(counter_map_->size());
2084 CounterAndKey* counters =
new CounterAndKey[number_of_counters];
2086 for (
auto map_entry : *counter_map_) {
2087 counters[j].counter = map_entry.second;
2088 counters[j].key = map_entry.first;
2091 std::sort(counters, counters + number_of_counters);
2093 if (i::FLAG_dump_counters_nvp) {
2095 for (j = 0; j < number_of_counters; j++) {
2096 Counter* counter = counters[j].counter;
2097 const char* key = counters[j].key;
2098 if (counter->is_histogram()) {
2099 printf(
"\"c:%s\"=%i\n", key, counter->count());
2100 printf(
"\"t:%s\"=%i\n", key, counter->sample_total());
2102 printf(
"\"%s\"=%i\n", key, counter->count());
2108 "+----------------------------------------------------------------+" 2109 "-------------+\n");
2114 "+----------------------------------------------------------------+" 2115 "-------------+\n");
2116 for (j = 0; j < number_of_counters; j++) {
2117 Counter* counter = counters[j].counter;
2118 const char* key = counters[j].key;
2119 if (counter->is_histogram()) {
2120 printf(
"| c:%-60s | %11i |\n", key, counter->count());
2121 printf(
"| t:%-60s | %11i |\n", key, counter->sample_total());
2123 printf(
"| %-62s | %11i |\n", key, counter->count());
2127 "+----------------------------------------------------------------+" 2128 "-------------+\n");
2133 delete counters_file_;
2134 delete counter_map_;
2138 static FILE* FOpen(
const char* path,
const char* mode) {
2139 #if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64)) 2141 if (fopen_s(&result, path, mode) == 0) {
2147 FILE* file = fopen(path, mode);
2148 if (file ==
nullptr)
return nullptr;
2149 struct stat file_stat;
2150 if (fstat(fileno(file), &file_stat) != 0)
return nullptr;
2151 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
2152 if (is_regular_file)
return file;
2158 static char* ReadChars(
const char* name,
int* size_out) {
2159 if (Shell::options.read_from_tcp_port >= 0) {
2160 return Shell::ReadCharsFromTcpPort(name, size_out);
2163 FILE* file = FOpen(name,
"rb");
2164 if (file ==
nullptr)
return nullptr;
2166 fseek(file, 0, SEEK_END);
2167 size_t size = ftell(file);
2170 char* chars =
new char[size + 1];
2172 for (
size_t i = 0;
i < size;) {
2173 i += fread(&chars[
i], 1, size -
i, file);
2181 *size_out =
static_cast<int>(size);
2193 static void ReadBufferWeakCallback(
2195 int byte_length = data.GetParameter()->byte_length;
2196 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(
2197 -static_cast<intptr_t>(byte_length));
2199 delete[] data.GetParameter()->data;
2200 data.GetParameter()->handle.Reset();
2201 delete data.GetParameter();
2206 static_assert(
sizeof(
char) ==
sizeof(uint8_t),
2207 "char and uint8_t should both have 1 byte");
2208 Isolate* isolate = args.GetIsolate();
2209 String::Utf8Value filename(isolate, args[0]);
2211 if (*filename ==
nullptr) {
2212 Throw(isolate,
"Error loading file");
2216 DataAndPersistent* data =
new DataAndPersistent;
2217 data->data =
reinterpret_cast<uint8_t*
>(ReadChars(*filename, &length));
2218 if (data->data ==
nullptr) {
2220 Throw(isolate,
"Error reading file");
2223 data->byte_length = length;
2224 Local<v8::ArrayBuffer> buffer =
ArrayBuffer::New(isolate, data->data, length);
2225 data->handle.Reset(isolate, buffer);
2226 data->handle.SetWeak(data, ReadBufferWeakCallback,
2227 v8::WeakCallbackType::kParameter);
2228 isolate->AdjustAmountOfExternalAllocatedMemory(length);
2230 args.GetReturnValue().Set(buffer);
2234 Local<String> Shell::ReadFile(Isolate* isolate,
const char* name) {
2235 std::unique_ptr<base::OS::MemoryMappedFile> file(
2236 base::OS::MemoryMappedFile::open(name));
2237 if (!file)
return Local<String>();
2239 int size =
static_cast<int>(file->size());
2240 char* chars =
static_cast<char*
>(file->memory());
2241 Local<String> result;
2242 if (i::FLAG_use_external_strings && i::String::IsAscii(chars, size)) {
2243 String::ExternalOneByteStringResource* resource =
2244 new ExternalOwningOneByteStringResource(std::move(file));
2245 result = String::NewExternalOneByte(isolate, resource).ToLocalChecked();
2254 void Shell::RunShell(Isolate* isolate) {
2255 HandleScope outer_scope(isolate);
2259 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2260 Local<String> name =
2263 printf(
"V8 version %s\n", V8::GetVersion());
2265 HandleScope inner_scope(isolate);
2267 Local<String> input = Shell::ReadFromStdin(isolate);
2268 if (input.IsEmpty())
break;
2269 ExecuteString(isolate, input, name, kPrintResult, kReportExceptions,
2270 kProcessMessageQueue);
2275 DisposeModuleEmbedderData(context);
2281 isolate_ = context->GetIsolate();
2282 context_.Reset(isolate_, context);
2289 std::unique_ptr<v8_inspector::StringBuffer> message)
override {
2290 Send(message->string());
2292 void sendNotification(
2293 std::unique_ptr<v8_inspector::StringBuffer> message)
override {
2294 Send(message->string());
2296 void flushProtocolNotifications()
override {}
2300 int length =
static_cast<int>(
string.length());
2301 DCHECK_LT(length, v8::String::kMaxLength);
2306 reinterpret_cast<const uint8_t*>(
string.characters8()),
2310 reinterpret_cast<const uint16_t*>(
string.characters16()),
2318 context->Global()->Get(context, callback_name).ToLocalChecked();
2319 if (callback->IsFunction()) {
2320 v8::TryCatch try_catch(isolate_);
2325 if (try_catch.HasCaught()) {
2332 "Maximum call stack size exceeded",
2335 Local<Value> value = exception->Get(context, key).ToLocalChecked();
2336 DCHECK(value->StrictEquals(expected));
2349 if (!connect)
return;
2350 isolate_ = context->GetIsolate();
2352 inspector_ = v8_inspector::V8Inspector::create(isolate_,
this);
2355 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex,
this);
2361 ->GetFunction(context)
2366 CHECK(context->Global()->Set(context, function_name,
function).FromJust());
2368 context_.Reset(isolate_, context);
2374 context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex));
2375 return inspector_client->session_.get();
2378 Local<Context> ensureDefaultContextInGroup(
int group_id)
override {
2380 DCHECK_EQ(kContextGroupId, group_id);
2381 return context_.Get(isolate_);
2384 static void SendInspectorMessage(
2386 Isolate* isolate = args.GetIsolate();
2389 args.GetReturnValue().Set(Undefined(isolate));
2390 Local<String> message = args[0]->ToString(context).ToLocalChecked();
2392 InspectorClient::GetSession(context);
2393 int length = message->Length();
2394 std::unique_ptr<uint16_t[]> buffer(
new uint16_t[length]);
2395 message->Write(isolate, buffer.get(), 0, length);
2397 session->dispatchProtocolMessage(message_view);
2398 args.GetReturnValue().Set(True(isolate));
2401 static const int kContextGroupId = 1;
2403 std::unique_ptr<v8_inspector::V8Inspector> inspector_;
2404 std::unique_ptr<v8_inspector::V8InspectorSession> session_;
2405 std::unique_ptr<v8_inspector::V8Inspector::Channel> channel_;
2410 SourceGroup::~SourceGroup() {
2415 bool ends_with(
const char* input,
const char* suffix) {
2416 size_t input_length = strlen(input);
2417 size_t suffix_length = strlen(suffix);
2418 if (suffix_length <= input_length) {
2419 return strcmp(input + input_length - suffix_length, suffix) == 0;
2424 void SourceGroup::Execute(Isolate* isolate) {
2425 bool exception_was_thrown =
false;
2426 for (
int i = begin_offset_;
i < end_offset_; ++
i) {
2427 const char* arg = argv_[
i];
2428 if (strcmp(arg,
"-e") == 0 &&
i + 1 < end_offset_) {
2430 HandleScope handle_scope(isolate);
2431 Local<String> file_name =
2434 Local<String> source =
2437 Shell::set_script_executed();
2438 if (!Shell::ExecuteString(isolate, source, file_name,
2439 Shell::kNoPrintResult, Shell::kReportExceptions,
2440 Shell::kNoProcessMessageQueue)) {
2441 exception_was_thrown =
true;
2446 }
else if (ends_with(arg,
".mjs")) {
2447 Shell::set_script_executed();
2448 if (!Shell::ExecuteModule(isolate, arg)) {
2449 exception_was_thrown =
true;
2453 }
else if (strcmp(arg,
"--module") == 0 &&
i + 1 < end_offset_) {
2456 Shell::set_script_executed();
2457 if (!Shell::ExecuteModule(isolate, arg)) {
2458 exception_was_thrown =
true;
2462 }
else if (arg[0] ==
'-') {
2468 HandleScope handle_scope(isolate);
2469 Local<String> file_name =
2472 Local<String> source = ReadFile(isolate, arg);
2473 if (source.IsEmpty()) {
2474 printf(
"Error reading '%s'\n", arg);
2475 base::OS::ExitProcess(1);
2477 Shell::set_script_executed();
2478 if (!Shell::ExecuteString(isolate, source, file_name, Shell::kNoPrintResult,
2479 Shell::kReportExceptions,
2480 Shell::kProcessMessageQueue)) {
2481 exception_was_thrown =
true;
2485 if (exception_was_thrown != Shell::options.expected_to_throw) {
2486 base::OS::ExitProcess(1);
2490 Local<String> SourceGroup::ReadFile(Isolate* isolate,
const char* name) {
2491 return Shell::ReadFile(isolate, name);
2494 SourceGroup::IsolateThread::IsolateThread(SourceGroup* group)
2495 : base::Thread(GetThreadOptions(
"IsolateThread")), group_(group) {}
2497 void SourceGroup::ExecuteInThread() {
2498 Isolate::CreateParams create_params;
2499 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
2500 Isolate* isolate = Isolate::New(create_params);
2501 isolate->SetHostImportModuleDynamicallyCallback(
2502 Shell::HostImportModuleDynamically);
2503 isolate->SetHostInitializeImportMetaObjectCallback(
2504 Shell::HostInitializeImportMetaObject);
2505 Shell::SetWaitUntilDone(isolate,
false);
2506 D8Console console(isolate);
2507 debug::SetConsoleDelegate(isolate, &console);
2508 for (
int i = 0;
i < Shell::options.stress_runs; ++
i) {
2509 next_semaphore_.Wait();
2511 Isolate::Scope iscope(isolate);
2512 PerIsolateData data(isolate);
2514 HandleScope scope(isolate);
2515 Local<Context> context = Shell::CreateEvaluationContext(isolate);
2517 Context::Scope cscope(context);
2518 InspectorClient inspector_client(context,
2519 Shell::options.enable_inspector);
2520 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2522 Shell::CompleteMessageLoop(isolate);
2524 DisposeModuleEmbedderData(context);
2526 Shell::CollectGarbage(isolate);
2528 done_semaphore_.Signal();
2535 void SourceGroup::StartExecuteInThread() {
2536 if (thread_ ==
nullptr) {
2537 thread_ =
new IsolateThread(
this);
2540 next_semaphore_.Signal();
2544 void SourceGroup::WaitForThread() {
2545 if (thread_ ==
nullptr)
return;
2546 done_semaphore_.Wait();
2550 void SourceGroup::JoinThread() {
2551 if (thread_ ==
nullptr)
return;
2555 ExternalizedContents::~ExternalizedContents() {
2556 if (data_ !=
nullptr) {
2557 deleter_(data_, length_, deleter_data_);
2561 void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) {
2562 base::MutexGuard lock_guard(&mutex_);
2563 data_.push_back(std::move(data));
2566 bool SerializationDataQueue::Dequeue(
2567 std::unique_ptr<SerializationData>* out_data) {
2569 base::MutexGuard lock_guard(&mutex_);
2570 if (data_.empty())
return false;
2571 *out_data = std::move(data_[0]);
2572 data_.erase(data_.begin());
2577 bool SerializationDataQueue::IsEmpty() {
2578 base::MutexGuard lock_guard(&mutex_);
2579 return data_.empty();
2583 void SerializationDataQueue::Clear() {
2584 base::MutexGuard lock_guard(&mutex_);
2605 void Worker::StartExecuteInThread(
const char* script) {
2607 script_ = i::StrDup(script);
2608 thread_ =
new WorkerThread(
this);
2612 void Worker::PostMessage(std::unique_ptr<SerializationData> data) {
2613 in_queue_.Enqueue(std::move(data));
2614 in_semaphore_.Signal();
2617 std::unique_ptr<SerializationData> Worker::GetMessage() {
2618 std::unique_ptr<SerializationData> result;
2619 while (!out_queue_.Dequeue(&result)) {
2622 if (!base::Relaxed_Load(&running_))
break;
2623 out_semaphore_.Wait();
2629 void Worker::Terminate() {
2630 base::Relaxed_Store(&running_,
false);
2633 PostMessage(
nullptr);
2637 void Worker::WaitForThread() {
2643 void Worker::ExecuteInThread() {
2644 Isolate::CreateParams create_params;
2645 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
2646 Isolate* isolate = Isolate::New(create_params);
2647 isolate->SetHostImportModuleDynamicallyCallback(
2648 Shell::HostImportModuleDynamically);
2649 isolate->SetHostInitializeImportMetaObjectCallback(
2650 Shell::HostInitializeImportMetaObject);
2651 D8Console console(isolate);
2652 debug::SetConsoleDelegate(isolate, &console);
2654 Isolate::Scope iscope(isolate);
2656 HandleScope scope(isolate);
2657 PerIsolateData data(isolate);
2658 Local<Context> context = Shell::CreateEvaluationContext(isolate);
2660 Context::Scope cscope(context);
2661 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2663 Local<Object> global = context->Global();
2664 Local<Value> this_value = External::New(isolate,
this);
2665 Local<FunctionTemplate> postmessage_fun_template =
2668 Local<Function> postmessage_fun;
2669 if (postmessage_fun_template->GetFunction(context)
2670 .ToLocal(&postmessage_fun)) {
2674 postmessage_fun).FromJust();
2678 Local<String> file_name =
2681 Local<String> source =
2684 if (Shell::ExecuteString(
2685 isolate, source, file_name, Shell::kNoPrintResult,
2686 Shell::kReportExceptions, Shell::kProcessMessageQueue)) {
2688 Local<Value> onmessage =
2691 .ToLocalChecked()).ToLocalChecked();
2692 if (onmessage->IsFunction()) {
2696 in_semaphore_.Wait();
2697 std::unique_ptr<SerializationData> data;
2698 if (!in_queue_.Dequeue(&data))
continue;
2702 v8::TryCatch try_catch(isolate);
2704 if (Shell::DeserializeValue(isolate, std::move(data))
2706 Local<Value> argv[] = {value};
2707 MaybeLocal<Value> result =
2708 onmessage_fun->Call(context, global, 1, argv);
2711 if (try_catch.HasCaught()) {
2712 Shell::ReportException(isolate, &try_catch);
2718 DisposeModuleEmbedderData(context);
2720 Shell::CollectGarbage(isolate);
2725 out_queue_.Enqueue(
nullptr);
2726 out_semaphore_.Signal();
2731 Isolate* isolate = args.GetIsolate();
2732 HandleScope handle_scope(isolate);
2734 if (args.Length() < 1) {
2735 Throw(isolate,
"Invalid argument");
2739 Local<Value> message = args[0];
2740 Local<Value> transfer = Undefined(isolate);
2741 std::unique_ptr<SerializationData> data =
2742 Shell::SerializeValue(isolate, message, transfer);
2744 DCHECK(args.Data()->IsExternal());
2746 Worker* worker =
static_cast<Worker*
>(this_value->Value());
2747 worker->out_queue_.Enqueue(std::move(data));
2748 worker->out_semaphore_.Signal();
2753 void SetFlagsFromString(
const char* flags) {
2754 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
2758 bool Shell::SetOptions(
int argc,
char* argv[]) {
2759 bool logfile_per_isolate =
false;
2760 for (
int i = 0;
i < argc;
i++) {
2761 if (strcmp(argv[
i],
"--") == 0) {
2763 for (
int j =
i + 1; j < argc; j++) {
2764 options.arguments.push_back(argv[j]);
2768 }
else if (strcmp(argv[
i],
"--no-arguments") == 0) {
2769 options.include_arguments =
false;
2771 }
else if (strcmp(argv[
i],
"--stress-opt") == 0) {
2772 options.stress_opt =
true;
2774 }
else if (strcmp(argv[
i],
"--nostress-opt") == 0 ||
2775 strcmp(argv[
i],
"--no-stress-opt") == 0) {
2776 options.stress_opt =
false;
2778 }
else if (strcmp(argv[
i],
"--stress-deopt") == 0) {
2779 options.stress_deopt =
true;
2781 }
else if (strcmp(argv[
i],
"--stress-background-compile") == 0) {
2782 options.stress_background_compile =
true;
2784 }
else if (strcmp(argv[
i],
"--nostress-background-compile") == 0 ||
2785 strcmp(argv[
i],
"--no-stress-background-compile") == 0) {
2786 options.stress_background_compile =
false;
2788 }
else if (strcmp(argv[
i],
"--noalways-opt") == 0 ||
2789 strcmp(argv[
i],
"--no-always-opt") == 0) {
2791 options.stress_opt =
false;
2792 options.stress_deopt =
false;
2793 }
else if (strcmp(argv[
i],
"--logfile-per-isolate") == 0) {
2794 logfile_per_isolate =
true;
2796 }
else if (strcmp(argv[
i],
"--shell") == 0) {
2797 options.interactive_shell =
true;
2799 }
else if (strcmp(argv[
i],
"--test") == 0) {
2800 options.test_shell =
true;
2802 }
else if (strcmp(argv[
i],
"--notest") == 0 ||
2803 strcmp(argv[
i],
"--no-test") == 0) {
2804 options.test_shell =
false;
2806 }
else if (strcmp(argv[
i],
"--send-idle-notification") == 0) {
2807 options.send_idle_notification =
true;
2809 }
else if (strcmp(argv[
i],
"--invoke-weak-callbacks") == 0) {
2810 options.invoke_weak_callbacks =
true;
2812 options.send_idle_notification =
true;
2814 }
else if (strcmp(argv[
i],
"--omit-quit") == 0) {
2815 options.omit_quit =
true;
2817 }
else if (strcmp(argv[
i],
"--no-wait-for-wasm") == 0) {
2820 options.wait_for_wasm =
false;
2822 }
else if (strcmp(argv[
i],
"-f") == 0) {
2826 }
else if (strcmp(argv[
i],
"--isolate") == 0) {
2827 options.num_isolates++;
2828 }
else if (strcmp(argv[
i],
"--throws") == 0) {
2829 options.expected_to_throw =
true;
2831 }
else if (strncmp(argv[
i],
"--icu-data-file=", 16) == 0) {
2832 options.icu_data_file = argv[
i] + 16;
2834 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 2835 }
else if (strncmp(argv[
i],
"--natives_blob=", 15) == 0) {
2836 options.natives_blob = argv[
i] + 15;
2838 }
else if (strncmp(argv[
i],
"--snapshot_blob=", 16) == 0) {
2839 options.snapshot_blob = argv[
i] + 16;
2841 #endif // V8_USE_EXTERNAL_STARTUP_DATA 2842 }
else if (strcmp(argv[
i],
"--cache") == 0 ||
2843 strncmp(argv[
i],
"--cache=", 8) == 0) {
2844 const char* value = argv[
i] + 7;
2845 if (!*value || strncmp(value,
"=code", 6) == 0) {
2846 options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
2847 options.code_cache_options =
2848 ShellOptions::CodeCacheOptions::kProduceCache;
2849 }
else if (strncmp(value,
"=none", 6) == 0) {
2850 options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
2851 options.code_cache_options =
2852 ShellOptions::CodeCacheOptions::kNoProduceCache;
2853 }
else if (strncmp(value,
"=after-execute", 15) == 0) {
2854 options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
2855 options.code_cache_options =
2856 ShellOptions::CodeCacheOptions::kProduceCacheAfterExecute;
2857 }
else if (strncmp(value,
"=full-code-cache", 17) == 0) {
2858 options.compile_options = v8::ScriptCompiler::kEagerCompile;
2859 options.code_cache_options =
2860 ShellOptions::CodeCacheOptions::kProduceCache;
2862 printf(
"Unknown option to --cache.\n");
2866 }
else if (strcmp(argv[
i],
"--enable-tracing") == 0) {
2867 options.trace_enabled =
true;
2869 }
else if (strncmp(argv[
i],
"--trace-path=", 13) == 0) {
2870 options.trace_path = argv[
i] + 13;
2872 }
else if (strncmp(argv[
i],
"--trace-config=", 15) == 0) {
2873 options.trace_config = argv[
i] + 15;
2875 }
else if (strcmp(argv[
i],
"--enable-inspector") == 0) {
2876 options.enable_inspector =
true;
2878 }
else if (strncmp(argv[
i],
"--lcov=", 7) == 0) {
2879 options.lcov_file = argv[
i] + 7;
2881 }
else if (strcmp(argv[
i],
"--disable-in-process-stack-traces") == 0) {
2882 options.disable_in_process_stack_traces =
true;
2885 }
else if (strncmp(argv[
i],
"--read-from-tcp-port=", 21) == 0) {
2886 options.read_from_tcp_port = atoi(argv[
i] + 21);
2888 #endif // V8_OS_POSIX 2889 }
else if (strcmp(argv[
i],
"--enable-os-system") == 0) {
2890 options.enable_os_system =
true;
2892 }
else if (strcmp(argv[
i],
"--quiet-load") == 0) {
2893 options.quiet_load =
true;
2895 }
else if (strncmp(argv[
i],
"--thread-pool-size=", 19) == 0) {
2896 options.thread_pool_size = atoi(argv[
i] + 19);
2898 }
else if (strcmp(argv[
i],
"--stress-delay-tasks") == 0) {
2900 options.stress_delay_tasks =
true;
2905 v8::V8::SetFlagsFromCommandLine(&argc, argv,
true);
2906 options.mock_arraybuffer_allocator = i::FLAG_mock_arraybuffer_allocator;
2907 options.mock_arraybuffer_allocator_limit =
2908 i::FLAG_mock_arraybuffer_allocator_limit;
2911 options.isolate_sources =
new SourceGroup[options.num_isolates];
2912 SourceGroup* current = options.isolate_sources;
2913 current->Begin(argv, 1);
2914 for (
int i = 1;
i < argc;
i++) {
2915 const char* str = argv[
i];
2916 if (strcmp(str,
"--isolate") == 0) {
2919 current->Begin(argv,
i + 1);
2920 }
else if (strcmp(str,
"--module") == 0) {
2922 }
else if (strncmp(str,
"--", 2) == 0) {
2923 printf(
"Warning: unknown flag %s.\nTry --help for options\n", str);
2924 }
else if (strcmp(str,
"-e") == 0 &&
i + 1 < argc) {
2925 set_script_executed();
2926 }
else if (strncmp(str,
"-", 1) != 0) {
2928 set_script_executed();
2933 if (!logfile_per_isolate && options.num_isolates) {
2934 SetFlagsFromString(
"--nologfile_per_isolate");
2940 int Shell::RunMain(Isolate* isolate,
int argc,
char* argv[],
bool last_run) {
2941 for (
int i = 1;
i < options.num_isolates; ++
i) {
2942 options.isolate_sources[
i].StartExecuteInThread();
2945 SetWaitUntilDone(isolate,
false);
2946 if (options.lcov_file) {
2947 debug::Coverage::SelectMode(isolate, debug::Coverage::kBlockCount);
2949 HandleScope scope(isolate);
2950 Local<Context> context = CreateEvaluationContext(isolate);
2951 bool use_existing_context = last_run && use_interactive_shell();
2952 if (use_existing_context) {
2954 evaluation_context_.
Reset(isolate, context);
2957 Context::Scope cscope(context);
2958 InspectorClient inspector_client(context, options.enable_inspector);
2959 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2960 options.isolate_sources[0].Execute(isolate);
2961 CompleteMessageLoop(isolate);
2963 if (!use_existing_context) {
2964 DisposeModuleEmbedderData(context);
2966 WriteLcovData(isolate, options.lcov_file);
2968 CollectGarbage(isolate);
2969 for (
int i = 1;
i < options.num_isolates; ++
i) {
2971 options.isolate_sources[
i].JoinThread();
2973 options.isolate_sources[
i].WaitForThread();
2981 void Shell::CollectGarbage(Isolate* isolate) {
2982 if (options.send_idle_notification) {
2983 const double kLongIdlePauseInSeconds = 1.0;
2984 isolate->ContextDisposedNotification();
2985 isolate->IdleNotificationDeadline(
2988 if (options.invoke_weak_callbacks) {
2992 isolate->LowMemoryNotification();
2996 void Shell::SetWaitUntilDone(Isolate* isolate,
bool value) {
2997 base::MutexGuard guard(isolate_status_lock_.Pointer());
2998 if (isolate_status_.count(isolate) == 0) {
2999 isolate_status_.insert(std::make_pair(isolate, value));
3001 isolate_status_[isolate] = value;
3006 bool ProcessMessages(
3008 const std::function<platform::MessageLoopBehavior()>& behavior) {
3013 SealHandleScope shs(isolate);
3014 while (v8::platform::PumpMessageLoop(g_default_platform, isolate,
3016 isolate->RunMicrotasks();
3019 v8::platform::RunIdleTasks(g_default_platform, isolate,
3020 50.0 / base::Time::kMillisecondsPerSecond);
3022 HandleScope handle_scope(isolate);
3023 PerIsolateData* data = PerIsolateData::Get(isolate);
3024 Local<Function> callback;
3025 if (!data->GetTimeoutCallback().ToLocal(&callback))
break;
3026 Local<Context> context;
3027 if (!data->GetTimeoutContext().ToLocal(&context))
break;
3028 TryCatch try_catch(isolate);
3029 try_catch.SetVerbose(
true);
3030 Context::Scope context_scope(context);
3031 if (callback->Call(context, Undefined(isolate), 0,
nullptr).IsEmpty()) {
3032 Shell::ReportException(isolate, &try_catch);
3040 void Shell::CompleteMessageLoop(Isolate* isolate) {
3041 auto get_waiting_behaviour = [isolate]() {
3042 base::MutexGuard guard(isolate_status_lock_.Pointer());
3043 DCHECK_GT(isolate_status_.count(isolate), 0);
3045 i::wasm::WasmEngine* wasm_engine = i_isolate->wasm_engine();
3046 bool should_wait = (options.wait_for_wasm &&
3047 wasm_engine->HasRunningCompileJob(i_isolate)) ||
3048 isolate_status_[isolate];
3049 return should_wait ? platform::MessageLoopBehavior::kWaitForWork
3050 : platform::MessageLoopBehavior::kDoNotWait;
3052 ProcessMessages(isolate, get_waiting_behaviour);
3055 bool Shell::EmptyMessageQueues(Isolate* isolate) {
3056 return ProcessMessages(
3057 isolate, []() {
return platform::MessageLoopBehavior::kDoNotWait; });
3063 : isolate_(isolate),
3064 serializer_(isolate,
this),
3065 current_memory_usage_(0) {}
3072 if (!PrepareTransfer(context, transfer).To(&ok)) {
3073 return Nothing<bool>();
3077 if (!serializer_.
WriteValue(context, value).To(&ok)) {
3079 return Nothing<bool>();
3082 if (!FinalizeTransfer().To(&ok)) {
3083 return Nothing<bool>();
3086 std::pair<uint8_t*, size_t> pair = serializer_.
Release();
3087 data_->data_.reset(pair.first);
3088 data_->size_ = pair.second;
3092 std::unique_ptr<SerializationData> Release() {
return std::move(data_); }
3094 void AppendExternalizedContentsTo(std::vector<ExternalizedContents>* to) {
3095 to->insert(to->end(),
3096 std::make_move_iterator(externalized_contents_.begin()),
3097 std::make_move_iterator(externalized_contents_.end()));
3098 externalized_contents_.clear();
3104 isolate_->ThrowException(Exception::Error(message));
3109 DCHECK_NOT_NULL(data_);
3110 for (
size_t index = 0; index < shared_array_buffers_.size(); ++index) {
3111 if (shared_array_buffers_[index] == shared_array_buffer) {
3112 return Just<uint32_t>(
static_cast<uint32_t>(index));
3116 size_t index = shared_array_buffers_.size();
3117 shared_array_buffers_.emplace_back(isolate_, shared_array_buffer);
3118 data_->shared_array_buffer_contents_.push_back(
3119 MaybeExternalize(shared_array_buffer));
3120 return Just<uint32_t>(
static_cast<uint32_t>(index));
3125 DCHECK_NOT_NULL(data_);
3126 for (
size_t index = 0; index < wasm_modules_.size(); ++index) {
3127 if (wasm_modules_[index] == module) {
3128 return Just<uint32_t>(
static_cast<uint32_t>(index));
3132 size_t index = wasm_modules_.size();
3133 wasm_modules_.emplace_back(isolate_, module);
3134 data_->transferrable_modules_.push_back(module->GetTransferrableModule());
3135 return Just<uint32_t>(
static_cast<uint32_t>(index));
3139 size_t* actual_size)
override {
3142 current_memory_usage_ += size;
3143 if (current_memory_usage_ > kMaxSerializerMemoryUsage)
return nullptr;
3145 void* result = realloc(old_buffer, size);
3146 *actual_size = result ? size : 0;
3154 if (transfer->IsArray()) {
3156 uint32_t length = transfer_array->Length();
3159 if (transfer_array->Get(context,
i).ToLocal(&element)) {
3160 if (!element->IsArrayBuffer()) {
3161 Throw(isolate_,
"Transfer array elements must be an ArrayBuffer");
3162 return Nothing<bool>();
3167 if (std::find(array_buffers_.begin(), array_buffers_.end(),
3168 array_buffer) != array_buffers_.end()) {
3170 "ArrayBuffer occurs in the transfer array more than once");
3171 return Nothing<bool>();
3175 static_cast<uint32_t>(array_buffers_.size()), array_buffer);
3176 array_buffers_.emplace_back(isolate_, array_buffer);
3178 return Nothing<bool>();
3182 }
else if (transfer->IsUndefined()) {
3185 Throw(isolate_,
"Transfer list must be an Array or undefined");
3186 return Nothing<bool>();
3190 template <
typename T>
3191 typename T::Contents MaybeExternalize(Local<T> array_buffer) {
3192 if (array_buffer->IsExternal()) {
3193 return array_buffer->GetContents();
3195 typename T::Contents contents = array_buffer->Externalize();
3196 externalized_contents_.emplace_back(contents);
3201 Maybe<bool> FinalizeTransfer() {
3202 for (
const auto& global_array_buffer : array_buffers_) {
3203 Local<ArrayBuffer> array_buffer =
3205 if (!array_buffer->IsNeuterable()) {
3206 Throw(isolate_,
"ArrayBuffer could not be transferred");
3207 return Nothing<bool>();
3210 ArrayBuffer::Contents contents = MaybeExternalize(array_buffer);
3211 array_buffer->Neuter();
3212 data_->array_buffer_contents_.push_back(contents);
3219 ValueSerializer serializer_;
3220 std::unique_ptr<SerializationData> data_;
3221 std::vector<Global<ArrayBuffer>> array_buffers_;
3222 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_;
3223 std::vector<Global<WasmCompiledModule>> wasm_modules_;
3224 std::vector<ExternalizedContents> externalized_contents_;
3225 size_t current_memory_usage_;
3227 DISALLOW_COPY_AND_ASSIGN(Serializer);
3232 Deserializer(Isolate* isolate, std::unique_ptr<SerializationData> data)
3233 : isolate_(isolate),
3234 deserializer_(isolate, data->data(), data->size(),
this),
3235 data_(std::move(data)) {
3241 if (!deserializer_.
ReadHeader(context).To(&read_header)) {
3246 for (
const auto& contents : data_->array_buffer_contents()) {
3252 return deserializer_.
ReadValue(context);
3256 Isolate* isolate,
uint32_t clone_id)
override {
3257 DCHECK_NOT_NULL(data_);
3258 if (clone_id < data_->shared_array_buffer_contents().size()) {
3260 data_->shared_array_buffer_contents().at(clone_id);
3262 contents.ByteLength());
3268 Isolate* isolate,
uint32_t transfer_id)
override {
3269 DCHECK_NOT_NULL(data_);
3270 if (transfer_id < data_->transferrable_modules().size()) {
3272 isolate_, data_->transferrable_modules().at(transfer_id));
3280 std::unique_ptr<SerializationData> data_;
3285 std::unique_ptr<SerializationData> Shell::SerializeValue(
3286 Isolate* isolate, Local<Value> value, Local<Value> transfer) {
3288 Local<Context> context = isolate->GetCurrentContext();
3289 Serializer serializer(isolate);
3290 std::unique_ptr<SerializationData> data;
3291 if (serializer.WriteValue(context, value, transfer).To(&ok)) {
3292 data = serializer.Release();
3295 base::MutexGuard lock_guard(workers_mutex_.Pointer());
3296 serializer.AppendExternalizedContentsTo(&externalized_contents_);
3300 MaybeLocal<Value> Shell::DeserializeValue(
3301 Isolate* isolate, std::unique_ptr<SerializationData> data) {
3303 Local<Context> context = isolate->GetCurrentContext();
3304 Deserializer deserializer(isolate, std::move(data));
3305 return deserializer.ReadValue(context);
3309 void Shell::CleanupWorkers() {
3313 std::vector<Worker*> workers_copy;
3315 base::MutexGuard lock_guard(workers_mutex_.Pointer());
3316 allow_new_workers_ =
false;
3317 workers_copy.swap(workers_);
3320 for (Worker* worker : workers_copy) {
3321 worker->WaitForThread();
3326 base::MutexGuard lock_guard(workers_mutex_.Pointer());
3327 allow_new_workers_ =
true;
3328 externalized_contents_.clear();
3331 int Shell::Main(
int argc,
char* argv[]) {
3332 std::ofstream trace_file;
3333 v8::base::EnsureConsoleOutput();
3334 if (!SetOptions(argc, argv))
return 1;
3335 v8::V8::InitializeICUDefaultLocation(argv[0], options.icu_data_file);
3337 v8::platform::InProcessStackDumping in_process_stack_dumping =
3338 options.disable_in_process_stack_traces
3339 ? v8::platform::InProcessStackDumping::kDisabled
3340 : v8::platform::InProcessStackDumping::kEnabled;
3342 std::unique_ptr<platform::tracing::TracingController> tracing;
3343 if (options.trace_enabled && !i::FLAG_verify_predictable) {
3344 tracing = base::make_unique<platform::tracing::TracingController>();
3346 trace_file.open(options.trace_path ? options.trace_path :
"v8_trace.json");
3347 platform::tracing::TraceBuffer* trace_buffer =
3348 platform::tracing::TraceBuffer::CreateTraceBufferRingBuffer(
3349 platform::tracing::TraceBuffer::kRingBufferChunks,
3350 platform::tracing::TraceWriter::CreateJSONTraceWriter(trace_file));
3351 tracing->Initialize(trace_buffer);
3354 platform::tracing::TracingController* tracing_controller = tracing.get();
3355 g_platform = v8::platform::NewDefaultPlatform(
3356 options.thread_pool_size, v8::platform::IdleTaskSupport::kEnabled,
3357 in_process_stack_dumping, std::move(tracing));
3358 g_default_platform = g_platform.get();
3359 if (i::FLAG_verify_predictable) {
3360 g_platform = MakePredictablePlatform(std::move(g_platform));
3362 if (options.stress_delay_tasks) {
3363 int64_t random_seed = i::FLAG_fuzzer_random_seed;
3364 if (!random_seed) random_seed = i::FLAG_random_seed;
3367 g_platform = MakeDelayedTasksPlatform(std::move(g_platform), random_seed);
3370 if (i::FLAG_trace_turbo_cfg_file ==
nullptr) {
3371 SetFlagsFromString(
"--trace-turbo-cfg-file=turbo.cfg");
3373 if (i::FLAG_redirect_code_traces_to ==
nullptr) {
3374 SetFlagsFromString(
"--redirect-code-traces-to=code.asm");
3376 v8::V8::InitializePlatform(g_platform.get());
3377 v8::V8::Initialize();
3378 if (options.natives_blob || options.snapshot_blob) {
3379 v8::V8::InitializeExternalStartupData(options.natives_blob,
3380 options.snapshot_blob);
3382 v8::V8::InitializeExternalStartupData(argv[0]);
3385 Isolate::CreateParams create_params;
3386 ShellArrayBufferAllocator shell_array_buffer_allocator;
3387 MockArrayBufferAllocator mock_arraybuffer_allocator;
3388 const size_t memory_limit =
3389 options.mock_arraybuffer_allocator_limit * options.num_isolates;
3390 MockArrayBufferAllocatiorWithLimit mock_arraybuffer_allocator_with_limit(
3391 memory_limit >= options.mock_arraybuffer_allocator_limit
3393 : std::numeric_limits<size_t>::max());
3394 if (options.mock_arraybuffer_allocator) {
3396 Shell::array_buffer_allocator = &mock_arraybuffer_allocator_with_limit;
3398 Shell::array_buffer_allocator = &mock_arraybuffer_allocator;
3401 Shell::array_buffer_allocator = &shell_array_buffer_allocator;
3403 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
3404 #ifdef ENABLE_VTUNE_JIT_INTERFACE 3405 create_params.code_event_handler = vTune::GetVtuneCodeEventHandler();
3407 create_params.constraints.ConfigureDefaults(
3408 base::SysInfo::AmountOfPhysicalMemory(),
3409 base::SysInfo::AmountOfVirtualMemory());
3411 Shell::counter_map_ =
new CounterMap();
3412 if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp || i::FLAG_gc_stats) {
3413 create_params.counter_lookup_callback = LookupCounter;
3414 create_params.create_histogram_callback = CreateHistogram;
3415 create_params.add_histogram_sample_callback = AddHistogramSample;
3418 if (V8_TRAP_HANDLER_SUPPORTED && i::FLAG_wasm_trap_handler) {
3419 constexpr
bool use_default_trap_handler =
true;
3420 if (!v8::V8::EnableWebAssemblyTrapHandler(use_default_trap_handler)) {
3421 FATAL(
"Could not register trap handler");
3425 Isolate* isolate = Isolate::New(create_params);
3426 isolate->SetHostImportModuleDynamicallyCallback(
3427 Shell::HostImportModuleDynamically);
3428 isolate->SetHostInitializeImportMetaObjectCallback(
3429 Shell::HostInitializeImportMetaObject);
3431 D8Console console(isolate);
3433 Isolate::Scope scope(isolate);
3434 Initialize(isolate);
3435 PerIsolateData data(isolate);
3436 debug::SetConsoleDelegate(isolate, &console);
3438 if (options.trace_enabled) {
3439 platform::tracing::TraceConfig* trace_config;
3440 if (options.trace_config) {
3442 char* trace_config_json_str = ReadChars(options.trace_config, &size);
3444 tracing::CreateTraceConfigFromJSON(isolate, trace_config_json_str);
3445 delete[] trace_config_json_str;
3448 platform::tracing::TraceConfig::CreateDefaultTraceConfig();
3450 tracing_controller->StartTracing(trace_config);
3453 if (options.stress_opt || options.stress_deopt) {
3455 ? Testing::kStressTypeOpt
3456 : Testing::kStressTypeDeopt);
3458 for (
int i = 0;
i < options.stress_runs && result == 0;
i++) {
3459 printf(
"============ Stress %d/%d ============\n",
i + 1,
3460 options.stress_runs);
3462 bool last_run =
i == options.stress_runs - 1;
3463 result = RunMain(isolate, argc, argv, last_run);
3465 printf(
"======== Full Deoptimization =======\n");
3467 }
else if (i::FLAG_stress_runs > 0) {
3468 options.stress_runs = i::FLAG_stress_runs;
3469 for (
int i = 0;
i < options.stress_runs && result == 0;
i++) {
3470 printf(
"============ Run %d/%d ============\n",
i + 1,
3471 options.stress_runs);
3472 bool last_run =
i == options.stress_runs - 1;
3473 result = RunMain(isolate, argc, argv, last_run);
3475 }
else if (options.code_cache_options !=
3476 ShellOptions::CodeCacheOptions::kNoProduceCache) {
3477 printf(
"============ Run: Produce code cache ============\n");
3479 Isolate::CreateParams create_params;
3480 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
3481 i::FLAG_hash_seed ^= 1337;
3482 Isolate* isolate2 = Isolate::New(create_params);
3483 i::FLAG_hash_seed ^= 1337;
3484 isolate2->SetHostImportModuleDynamicallyCallback(
3485 Shell::HostImportModuleDynamically);
3486 isolate2->SetHostInitializeImportMetaObjectCallback(
3487 Shell::HostInitializeImportMetaObject);
3489 D8Console console(isolate2);
3490 Initialize(isolate2);
3491 debug::SetConsoleDelegate(isolate2, &console);
3492 PerIsolateData data(isolate2);
3493 Isolate::Scope isolate_scope(isolate2);
3495 result = RunMain(isolate2, argc, argv,
false);
3497 isolate2->Dispose();
3500 DCHECK(options.compile_options == v8::ScriptCompiler::kEagerCompile ||
3501 options.compile_options == v8::ScriptCompiler::kNoCompileOptions);
3502 options.compile_options = v8::ScriptCompiler::kConsumeCodeCache;
3503 options.code_cache_options =
3504 ShellOptions::CodeCacheOptions::kNoProduceCache;
3506 printf(
"============ Run: Consume code cache ============\n");
3508 result = RunMain(isolate, argc, argv,
true);
3509 options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
3511 bool last_run =
true;
3512 result = RunMain(isolate, argc, argv, last_run);
3517 if (use_interactive_shell()) {
3521 if (i::FLAG_trace_ignition_dispatches &&
3522 i::FLAG_trace_ignition_dispatches_output_file !=
nullptr) {
3523 WriteIgnitionDispatchCountersFile(isolate);
3527 cached_code_map_.clear();
3528 evaluation_context_.
Reset();
3529 stringify_function_.Reset();
3530 CollectGarbage(isolate);
3534 V8::ShutdownPlatform();
3546 int main(
int argc,
char* argv[]) {
3547 return v8::Shell::Main(argc, argv);
static V8_WARN_UNUSED_RESULT MaybeLocal< Module > CompileModule(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions, NoCacheReason no_cache_reason=kNoCacheNoReason)
static V8_WARN_UNUSED_RESULT MaybeLocal< Resolver > New(Local< Context > context)
static CachedData * CreateCodeCache(Local< UnboundScript > unbound_script)
static V8_WARN_UNUSED_RESULT MaybeLocal< String > Stringify(Local< Context > context, Local< Value > json_object, Local< String > gap=Local< String >())
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromOneByte(Isolate *isolate, const uint8_t *data, v8::NewStringType type, int length=-1)
static V8_WARN_UNUSED_RESULT MaybeLocal< Script > Compile(Local< Context > context, Source *source, CompileOptions options=kNoCompileOptions, NoCacheReason no_cache_reason=kNoCacheNoReason)
static V8_INLINE Local< T > Cast(Local< S > that)
static int GetStressRuns()
static Local< SharedArrayBuffer > New(Isolate *isolate, size_t byte_length)
MaybeLocal< WasmCompiledModule > GetWasmModuleFromId(Isolate *isolate, uint32_t transfer_id) override
Maybe< uint32_t > GetSharedArrayBufferId(Isolate *isolate, Local< SharedArrayBuffer > shared_array_buffer) override
void FreeBufferMemory(void *buffer) override
MaybeLocal< SharedArrayBuffer > GetSharedArrayBufferFromId(Isolate *isolate, uint32_t clone_id) override
size_t GetMoreData(const uint8_t **src) override
static Local< Array > New(Isolate *isolate, int length=0)
void SetSupportsLegacyWireFormat(bool supports_legacy_wire_format)
const char * data() const override
size_t length() const override
void TransferArrayBuffer(uint32_t transfer_id, Local< ArrayBuffer > array_buffer)
static V8_WARN_UNUSED_RESULT MaybeLocal< Script > Compile(Local< Context > context, Local< String > source, ScriptOrigin *origin=nullptr)
static Local< ObjectTemplate > New(Isolate *isolate, Local< FunctionTemplate > constructor=Local< FunctionTemplate >())
static Local< ArrayBuffer > New(Isolate *isolate, size_t byte_length)
V8_WARN_UNUSED_RESULT Maybe< bool > ReadHeader(Local< Context > context)
V8_WARN_UNUSED_RESULT Maybe< bool > WriteValue(Local< Context > context, Local< Value > value)
V8_WARN_UNUSED_RESULT MaybeLocal< Value > ReadValue(Local< Context > context)
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromTwoByte(Isolate *isolate, const uint16_t *data, v8::NewStringType type, int length=-1)
void ThrowDataCloneError(Local< String > message) override
static V8_WARN_UNUSED_RESULT MaybeLocal< UnboundScript > CompileUnboundScript(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions, NoCacheReason no_cache_reason=kNoCacheNoReason)
static V8_INLINE Local< T > New(Isolate *isolate, Local< T > that)
virtual size_t AllocatePageSize()=0
static void SetStressRunType(StressType type)
static V8_INLINE Local< String > Empty(Isolate *isolate)
static MaybeLocal< WasmCompiledModule > FromTransferrableModule(Isolate *isolate, const TransferrableModule &)
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromUtf8(Isolate *isolate, const char *data, v8::NewStringType type, int length=-1)
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect)
V8_WARN_UNUSED_RESULT std::pair< uint8_t *, size_t > Release()
void * ReallocateBufferMemory(void *old_buffer, size_t size, size_t *actual_size) override
static Local< String > Concat(Isolate *isolate, Local< String > left, Local< String > right)
static void DeoptimizeAll(Isolate *isolate)
static void PrepareStressRun(int run)
static ScriptStreamingTask * StartStreamingScript(Isolate *isolate, StreamedSource *source, CompileOptions options=kNoCompileOptions)
void TransferArrayBuffer(uint32_t transfer_id, Local< ArrayBuffer > array_buffer)