Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: src/d8.cc

Issue 2393303002: [modules] Store Module metadata in per-Context EmbedderData (Closed)
Patch Set: Rebased Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8.h ('k') | src/factory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <fstream> 11 #include <fstream>
12 #include <map> 12 #include <unordered_map>
13 #include <utility> 13 #include <utility>
14 #include <vector> 14 #include <vector>
15 15
16 #ifdef ENABLE_VTUNE_JIT_INTERFACE 16 #ifdef ENABLE_VTUNE_JIT_INTERFACE
17 #include "src/third_party/vtune/v8-vtune.h" 17 #include "src/third_party/vtune/v8-vtune.h"
18 #endif 18 #endif
19 19
20 #include "src/d8.h" 20 #include "src/d8.h"
21 #include "src/ostreams.h" 21 #include "src/ostreams.h"
22 22
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 result = dir_name + '/' + path; 565 result = dir_name + '/' + path;
566 } 566 }
567 std::replace(result.begin(), result.end(), '\\', '/'); 567 std::replace(result.begin(), result.end(), '\\', '/');
568 size_t i; 568 size_t i;
569 while ((i = result.find("/./")) != std::string::npos) { 569 while ((i = result.find("/./")) != std::string::npos) {
570 result.erase(i, 2); 570 result.erase(i, 2);
571 } 571 }
572 return result; 572 return result;
573 } 573 }
574 574
575 // Per-context Module data, allowing sharing of module maps
576 // across top-level module loads.
577 class ModuleEmbedderData {
578 private:
579 class ModuleGlobalHash {
580 public:
581 explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {}
582 size_t operator()(const Global<Module>& module) const {
583 return module.Get(isolate_)->GetIdentityHash();
584 }
585
586 private:
587 Isolate* isolate_;
588 };
589
590 public:
591 explicit ModuleEmbedderData(Isolate* isolate)
592 : module_to_directory_map(10, ModuleGlobalHash(isolate)) {}
593
594 // Map from normalized module specifier to Module.
595 std::unordered_map<std::string, Global<Module>> specifier_to_module_map;
596 // Map from Module to the directory that Module was loaded from.
597 std::unordered_map<Global<Module>, std::string, ModuleGlobalHash>
598 module_to_directory_map;
599 };
600
601 enum {
602 // The debugger reserves the first slot in the Context embedder data.
603 kDebugIdIndex = Context::kDebugIdIndex,
604 kModuleEmbedderDataIndex
605 };
606
607 void InitializeModuleEmbedderData(Local<Context> context) {
608 context->SetAlignedPointerInEmbedderData(
609 kModuleEmbedderDataIndex, new ModuleEmbedderData(context->GetIsolate()));
610 }
611
612 ModuleEmbedderData* GetModuleDataFromContext(Local<Context> context) {
613 return static_cast<ModuleEmbedderData*>(
614 context->GetAlignedPointerFromEmbedderData(kModuleEmbedderDataIndex));
615 }
616
617 void DisposeModuleEmbedderData(Local<Context> context) {
618 delete GetModuleDataFromContext(context);
619 context->SetAlignedPointerInEmbedderData(kModuleEmbedderDataIndex, nullptr);
620 }
621
575 MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, 622 MaybeLocal<Module> ResolveModuleCallback(Local<Context> context,
576 Local<String> specifier, 623 Local<String> specifier,
577 Local<Module> referrer, 624 Local<Module> referrer) {
578 Local<Value> data) {
579 Isolate* isolate = context->GetIsolate(); 625 Isolate* isolate = context->GetIsolate();
580 auto module_map = static_cast<std::map<std::string, Global<Module>>*>( 626 ModuleEmbedderData* d = GetModuleDataFromContext(context);
581 External::Cast(*data)->Value()); 627 auto dir_name_it =
582 Local<String> dir_name = Local<String>::Cast(referrer->GetEmbedderData()); 628 d->module_to_directory_map.find(Global<Module>(isolate, referrer));
629 CHECK(dir_name_it != d->module_to_directory_map.end());
583 std::string absolute_path = 630 std::string absolute_path =
584 NormalizePath(ToSTLString(specifier), ToSTLString(dir_name)); 631 NormalizePath(ToSTLString(specifier), dir_name_it->second);
585 auto it = module_map->find(absolute_path); 632 auto module_it = d->specifier_to_module_map.find(absolute_path);
586 if (it != module_map->end()) { 633 CHECK(module_it != d->specifier_to_module_map.end());
587 return it->second.Get(isolate); 634 return module_it->second.Get(isolate);
588 }
589 return MaybeLocal<Module>();
590 } 635 }
591 636
592 } // anonymous namespace 637 } // anonymous namespace
593 638
594 MaybeLocal<Module> Shell::FetchModuleTree( 639 MaybeLocal<Module> Shell::FetchModuleTree(Local<Context> context,
595 Isolate* isolate, const std::string& file_name, 640 const std::string& file_name) {
596 std::map<std::string, Global<Module>>* module_map) {
597 DCHECK(IsAbsolutePath(file_name)); 641 DCHECK(IsAbsolutePath(file_name));
642 Isolate* isolate = context->GetIsolate();
598 TryCatch try_catch(isolate); 643 TryCatch try_catch(isolate);
599 try_catch.SetVerbose(true); 644 try_catch.SetVerbose(true);
600 Local<String> source_text = ReadFile(isolate, file_name.c_str()); 645 Local<String> source_text = ReadFile(isolate, file_name.c_str());
601 if (source_text.IsEmpty()) { 646 if (source_text.IsEmpty()) {
602 printf("Error reading '%s'\n", file_name.c_str()); 647 printf("Error reading '%s'\n", file_name.c_str());
603 Shell::Exit(1); 648 Shell::Exit(1);
604 } 649 }
605 ScriptOrigin origin( 650 ScriptOrigin origin(
606 String::NewFromUtf8(isolate, file_name.c_str(), NewStringType::kNormal) 651 String::NewFromUtf8(isolate, file_name.c_str(), NewStringType::kNormal)
607 .ToLocalChecked()); 652 .ToLocalChecked());
608 ScriptCompiler::Source source(source_text, origin); 653 ScriptCompiler::Source source(source_text, origin);
609 Local<Module> module; 654 Local<Module> module;
610 if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { 655 if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) {
611 ReportException(isolate, &try_catch); 656 ReportException(isolate, &try_catch);
612 return MaybeLocal<Module>(); 657 return MaybeLocal<Module>();
613 } 658 }
614 module_map->insert( 659
615 std::make_pair(file_name, Global<Module>(isolate, module))); 660 ModuleEmbedderData* d = GetModuleDataFromContext(context);
661 CHECK(d->specifier_to_module_map
662 .insert(std::make_pair(file_name, Global<Module>(isolate, module)))
663 .second);
616 664
617 std::string dir_name = DirName(file_name); 665 std::string dir_name = DirName(file_name);
618 module->SetEmbedderData( 666 CHECK(d->module_to_directory_map
619 String::NewFromUtf8(isolate, dir_name.c_str(), NewStringType::kNormal) 667 .insert(std::make_pair(Global<Module>(isolate, module), dir_name))
620 .ToLocalChecked()); 668 .second);
621 669
622 for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) { 670 for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) {
623 Local<String> name = module->GetModuleRequest(i); 671 Local<String> name = module->GetModuleRequest(i);
624 std::string absolute_path = NormalizePath(ToSTLString(name), dir_name); 672 std::string absolute_path = NormalizePath(ToSTLString(name), dir_name);
625 if (!module_map->count(absolute_path)) { 673 if (!d->specifier_to_module_map.count(absolute_path)) {
626 if (FetchModuleTree(isolate, absolute_path, module_map).IsEmpty()) { 674 if (FetchModuleTree(context, absolute_path).IsEmpty()) {
627 return MaybeLocal<Module>(); 675 return MaybeLocal<Module>();
628 } 676 }
629 } 677 }
630 } 678 }
631 679
632 return module; 680 return module;
633 } 681 }
634 682
635 bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { 683 bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {
636 HandleScope handle_scope(isolate); 684 HandleScope handle_scope(isolate);
637 685
686 PerIsolateData* data = PerIsolateData::Get(isolate);
687 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
688 Context::Scope context_scope(realm);
689
638 std::string absolute_path = NormalizePath(file_name, GetWorkingDirectory()); 690 std::string absolute_path = NormalizePath(file_name, GetWorkingDirectory());
639 691
640 Local<Module> root_module; 692 Local<Module> root_module;
641 std::map<std::string, Global<Module>> module_map; 693 if (!FetchModuleTree(realm, absolute_path).ToLocal(&root_module)) {
642 if (!FetchModuleTree(isolate, absolute_path, &module_map)
643 .ToLocal(&root_module)) {
644 return false; 694 return false;
645 } 695 }
646 696
647 TryCatch try_catch(isolate); 697 TryCatch try_catch(isolate);
648 try_catch.SetVerbose(true); 698 try_catch.SetVerbose(true);
649 699
650 MaybeLocal<Value> maybe_result; 700 MaybeLocal<Value> maybe_result;
651 { 701 if (root_module->Instantiate(realm, ResolveModuleCallback)) {
652 PerIsolateData* data = PerIsolateData::Get(isolate); 702 maybe_result = root_module->Evaluate(realm);
653 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); 703 EmptyMessageQueues(isolate);
654 Context::Scope context_scope(realm);
655
656 if (root_module->Instantiate(realm, ResolveModuleCallback,
657 External::New(isolate, &module_map))) {
658 maybe_result = root_module->Evaluate(realm);
659 EmptyMessageQueues(isolate);
660 }
661 } 704 }
662 Local<Value> result; 705 Local<Value> result;
663 if (!maybe_result.ToLocal(&result)) { 706 if (!maybe_result.ToLocal(&result)) {
664 DCHECK(try_catch.HasCaught()); 707 DCHECK(try_catch.HasCaught());
665 // Print errors that happened during execution. 708 // Print errors that happened during execution.
666 ReportException(isolate, &try_catch); 709 ReportException(isolate, &try_catch);
667 return false; 710 return false;
668 } 711 }
669 DCHECK(!try_catch.HasCaught()); 712 DCHECK(!try_catch.HasCaught());
670 return true; 713 return true;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 old_realms[i].Reset(); 823 old_realms[i].Reset();
781 } 824 }
782 delete[] old_realms; 825 delete[] old_realms;
783 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); 826 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
784 Local<Context> context = Context::New(isolate, NULL, global_template); 827 Local<Context> context = Context::New(isolate, NULL, global_template);
785 if (context.IsEmpty()) { 828 if (context.IsEmpty()) {
786 DCHECK(try_catch.HasCaught()); 829 DCHECK(try_catch.HasCaught());
787 try_catch.ReThrow(); 830 try_catch.ReThrow();
788 return MaybeLocal<Context>(); 831 return MaybeLocal<Context>();
789 } 832 }
833 InitializeModuleEmbedderData(context);
790 data->realms_[index].Reset(isolate, context); 834 data->realms_[index].Reset(isolate, context);
791 args.GetReturnValue().Set(index); 835 args.GetReturnValue().Set(index);
792 return context; 836 return context;
793 } 837 }
794 838
795 // Realm.create() creates a new realm with a distinct security token 839 // Realm.create() creates a new realm with a distinct security token
796 // and returns its index. 840 // and returns its index.
797 void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) { 841 void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
798 CreateRealm(args); 842 CreateRealm(args);
799 } 843 }
(...skipping 13 matching lines...) Expand all
813 void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) { 857 void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
814 Isolate* isolate = args.GetIsolate(); 858 Isolate* isolate = args.GetIsolate();
815 PerIsolateData* data = PerIsolateData::Get(isolate); 859 PerIsolateData* data = PerIsolateData::Get(isolate);
816 int index = data->RealmIndexOrThrow(args, 0); 860 int index = data->RealmIndexOrThrow(args, 0);
817 if (index == -1) return; 861 if (index == -1) return;
818 if (index == 0 || 862 if (index == 0 ||
819 index == data->realm_current_ || index == data->realm_switch_) { 863 index == data->realm_current_ || index == data->realm_switch_) {
820 Throw(args.GetIsolate(), "Invalid realm index"); 864 Throw(args.GetIsolate(), "Invalid realm index");
821 return; 865 return;
822 } 866 }
867 DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
823 data->realms_[index].Reset(); 868 data->realms_[index].Reset();
824 isolate->ContextDisposedNotification(); 869 isolate->ContextDisposedNotification();
825 isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime()); 870 isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
826 } 871 }
827 872
828 873
829 // Realm.switch(i) switches to the realm i for consecutive interactive inputs. 874 // Realm.switch(i) switches to the realm i for consecutive interactive inputs.
830 void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) { 875 void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
831 Isolate* isolate = args.GetIsolate(); 876 Isolate* isolate = args.GetIsolate();
832 PerIsolateData* data = PerIsolateData::Get(isolate); 877 PerIsolateData* data = PerIsolateData::Get(isolate);
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 1526
1482 1527
1483 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) { 1528 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
1484 // This needs to be a critical section since this is not thread-safe 1529 // This needs to be a critical section since this is not thread-safe
1485 base::LockGuard<base::Mutex> lock_guard(context_mutex_.Pointer()); 1530 base::LockGuard<base::Mutex> lock_guard(context_mutex_.Pointer());
1486 // Initialize the global objects 1531 // Initialize the global objects
1487 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); 1532 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
1488 EscapableHandleScope handle_scope(isolate); 1533 EscapableHandleScope handle_scope(isolate);
1489 Local<Context> context = Context::New(isolate, NULL, global_template); 1534 Local<Context> context = Context::New(isolate, NULL, global_template);
1490 DCHECK(!context.IsEmpty()); 1535 DCHECK(!context.IsEmpty());
1536 InitializeModuleEmbedderData(context);
1491 Context::Scope scope(context); 1537 Context::Scope scope(context);
1492 1538
1493 i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory(); 1539 i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory();
1494 i::JSArguments js_args = i::FLAG_js_arguments; 1540 i::JSArguments js_args = i::FLAG_js_arguments;
1495 i::Handle<i::FixedArray> arguments_array = 1541 i::Handle<i::FixedArray> arguments_array =
1496 factory->NewFixedArray(js_args.argc); 1542 factory->NewFixedArray(js_args.argc);
1497 for (int j = 0; j < js_args.argc; j++) { 1543 for (int j = 0; j < js_args.argc; j++) {
1498 i::Handle<i::String> arg = 1544 i::Handle<i::String> arg =
1499 factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked(); 1545 factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked();
1500 arguments_array->set(j, *arg); 1546 arguments_array->set(j, *arg);
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 Isolate::Scope iscope(isolate); 1852 Isolate::Scope iscope(isolate);
1807 { 1853 {
1808 HandleScope scope(isolate); 1854 HandleScope scope(isolate);
1809 PerIsolateData data(isolate); 1855 PerIsolateData data(isolate);
1810 Local<Context> context = Shell::CreateEvaluationContext(isolate); 1856 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1811 { 1857 {
1812 Context::Scope cscope(context); 1858 Context::Scope cscope(context);
1813 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 1859 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1814 Execute(isolate); 1860 Execute(isolate);
1815 } 1861 }
1862 DisposeModuleEmbedderData(context);
1816 } 1863 }
1817 Shell::CollectGarbage(isolate); 1864 Shell::CollectGarbage(isolate);
1818 } 1865 }
1819 done_semaphore_.Signal(); 1866 done_semaphore_.Signal();
1820 } 1867 }
1821 1868
1822 isolate->Dispose(); 1869 isolate->Dispose();
1823 } 1870 }
1824 1871
1825 1872
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
2065 if (Shell::DeserializeValue(isolate, *data, &offset) 2112 if (Shell::DeserializeValue(isolate, *data, &offset)
2066 .ToLocal(&data_value)) { 2113 .ToLocal(&data_value)) {
2067 Local<Value> argv[] = {data_value}; 2114 Local<Value> argv[] = {data_value};
2068 (void)onmessage_fun->Call(context, global, 1, argv); 2115 (void)onmessage_fun->Call(context, global, 1, argv);
2069 } 2116 }
2070 delete data; 2117 delete data;
2071 } 2118 }
2072 } 2119 }
2073 } 2120 }
2074 } 2121 }
2122 DisposeModuleEmbedderData(context);
2075 } 2123 }
2076 Shell::CollectGarbage(isolate); 2124 Shell::CollectGarbage(isolate);
2077 } 2125 }
2078 isolate->Dispose(); 2126 isolate->Dispose();
2079 2127
2080 // Post NULL to wake the thread waiting on GetMessage() if there is one. 2128 // Post NULL to wake the thread waiting on GetMessage() if there is one.
2081 out_queue_.Enqueue(NULL); 2129 out_queue_.Enqueue(NULL);
2082 out_semaphore_.Signal(); 2130 out_semaphore_.Signal();
2083 } 2131 }
2084 2132
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 Local<Context> context = CreateEvaluationContext(isolate); 2296 Local<Context> context = CreateEvaluationContext(isolate);
2249 if (last_run && options.use_interactive_shell()) { 2297 if (last_run && options.use_interactive_shell()) {
2250 // Keep using the same context in the interactive shell. 2298 // Keep using the same context in the interactive shell.
2251 evaluation_context_.Reset(isolate, context); 2299 evaluation_context_.Reset(isolate, context);
2252 } 2300 }
2253 { 2301 {
2254 Context::Scope cscope(context); 2302 Context::Scope cscope(context);
2255 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 2303 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2256 options.isolate_sources[0].Execute(isolate); 2304 options.isolate_sources[0].Execute(isolate);
2257 } 2305 }
2306 DisposeModuleEmbedderData(context);
2258 } 2307 }
2259 CollectGarbage(isolate); 2308 CollectGarbage(isolate);
2260 for (int i = 1; i < options.num_isolates; ++i) { 2309 for (int i = 1; i < options.num_isolates; ++i) {
2261 if (last_run) { 2310 if (last_run) {
2262 options.isolate_sources[i].JoinThread(); 2311 options.isolate_sources[i].JoinThread();
2263 } else { 2312 } else {
2264 options.isolate_sources[i].WaitForThread(); 2313 options.isolate_sources[i].WaitForThread();
2265 } 2314 }
2266 } 2315 }
2267 CleanupWorkers(); 2316 CleanupWorkers();
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
2764 } 2813 }
2765 2814
2766 } // namespace v8 2815 } // namespace v8
2767 2816
2768 2817
2769 #ifndef GOOGLE3 2818 #ifndef GOOGLE3
2770 int main(int argc, char* argv[]) { 2819 int main(int argc, char* argv[]) {
2771 return v8::Shell::Main(argc, argv); 2820 return v8::Shell::Main(argc, argv);
2772 } 2821 }
2773 #endif 2822 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698