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