Chromium Code Reviews| 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 <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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 size_t last_slash = path.find_last_of('/'); | 551 size_t last_slash = path.find_last_of('/'); |
| 552 DCHECK(last_slash != std::string::npos); | 552 DCHECK(last_slash != std::string::npos); |
| 553 return path.substr(0, last_slash); | 553 return path.substr(0, last_slash); |
| 554 } | 554 } |
| 555 | 555 |
| 556 std::string EnsureAbsolutePath(const std::string& path, | 556 std::string EnsureAbsolutePath(const std::string& path, |
| 557 const std::string& dir_name) { | 557 const std::string& dir_name) { |
| 558 return IsAbsolutePath(path) ? path : dir_name + '/' + path; | 558 return IsAbsolutePath(path) ? path : dir_name + '/' + path; |
| 559 } | 559 } |
| 560 | 560 |
| 561 // Per-context Module data, allowing sharing of module maps | |
| 562 // across top-level module loads. | |
| 563 class ModuleEmbedderData { | |
| 564 private: | |
| 565 class ModuleGlobalHash { | |
| 566 public: | |
| 567 explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {} | |
| 568 size_t operator()(const Global<Module>& module) const { | |
| 569 return module.Get(isolate_)->GetIdentityHash(); | |
| 570 } | |
| 571 | |
| 572 private: | |
| 573 Isolate* isolate_; | |
| 574 }; | |
| 575 | |
| 576 public: | |
| 577 explicit ModuleEmbedderData(Isolate* isolate) | |
| 578 : module_to_directory_map(10, ModuleGlobalHash(isolate)) {} | |
| 579 | |
| 580 // Map from normalized module specifiers to Modules. | |
| 581 std::unordered_map<std::string, Global<Module>> specifier_to_module_map; | |
| 582 // Map from Module to the directory that Module was loaded from. | |
|
neis
2016/10/06 09:44:46
Nit: keep the comments both in singular or both in
adamk
2016/10/06 20:47:01
Thanks for keeping me honest. Went with singular.
| |
| 583 std::unordered_map<Global<Module>, std::string, ModuleGlobalHash> | |
| 584 module_to_directory_map; | |
| 585 }; | |
| 586 | |
| 587 enum D8EmbedderDataFields { | |
| 588 kDebugIdIndex = Context::kDebugIdIndex, | |
|
neis
2016/10/06 09:44:46
What is this for?
adamk
2016/10/06 20:47:01
Added a comment (and removed the type name). Basic
| |
| 589 kModuleEmbedderDataIndex | |
| 590 }; | |
| 591 | |
| 592 void InitializeModuleEmbedderData(Local<Context> context) { | |
| 593 context->SetAlignedPointerInEmbedderData( | |
| 594 kModuleEmbedderDataIndex, new ModuleEmbedderData(context->GetIsolate())); | |
| 595 } | |
| 596 | |
| 597 ModuleEmbedderData* GetModuleDataFromContext(Local<Context> context) { | |
| 598 return static_cast<ModuleEmbedderData*>( | |
| 599 context->GetAlignedPointerFromEmbedderData(kModuleEmbedderDataIndex)); | |
| 600 } | |
| 601 | |
| 561 MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, | 602 MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, |
| 562 Local<String> specifier, | 603 Local<String> specifier, |
| 563 Local<Module> referrer, | 604 Local<Module> referrer) { |
| 564 Local<Value> data) { | |
| 565 Isolate* isolate = context->GetIsolate(); | 605 Isolate* isolate = context->GetIsolate(); |
| 566 auto module_map = static_cast<std::map<std::string, Global<Module>>*>( | 606 ModuleEmbedderData* d = GetModuleDataFromContext(context); |
| 567 External::Cast(*data)->Value()); | 607 auto dir_name_it = |
| 568 Local<String> dir_name = Local<String>::Cast(referrer->GetEmbedderData()); | 608 d->module_to_directory_map.find(Global<Module>(isolate, referrer)); |
| 609 CHECK(dir_name_it != d->module_to_directory_map.end()); | |
| 569 std::string absolute_path = | 610 std::string absolute_path = |
| 570 EnsureAbsolutePath(ToSTLString(specifier), ToSTLString(dir_name)); | 611 EnsureAbsolutePath(ToSTLString(specifier), dir_name_it->second); |
| 571 auto it = module_map->find(absolute_path); | 612 auto module_it = d->specifier_to_module_map.find(absolute_path); |
| 572 if (it != module_map->end()) { | 613 CHECK(module_it != d->specifier_to_module_map.end()); |
| 573 return it->second.Get(isolate); | 614 return module_it->second.Get(isolate); |
| 574 } | |
| 575 return MaybeLocal<Module>(); | |
| 576 } | 615 } |
| 577 | 616 |
| 578 } // anonymous namespace | 617 } // anonymous namespace |
| 579 | 618 |
| 580 MaybeLocal<Module> Shell::FetchModuleTree( | 619 MaybeLocal<Module> Shell::FetchModuleTree(Local<Context> context, |
| 581 Isolate* isolate, const std::string& file_name, | 620 const std::string& file_name) { |
| 582 std::map<std::string, Global<Module>>* module_map) { | |
| 583 DCHECK(IsAbsolutePath(file_name)); | 621 DCHECK(IsAbsolutePath(file_name)); |
| 622 Isolate* isolate = context->GetIsolate(); | |
| 584 TryCatch try_catch(isolate); | 623 TryCatch try_catch(isolate); |
| 585 try_catch.SetVerbose(true); | 624 try_catch.SetVerbose(true); |
| 586 Local<String> source_text = ReadFile(isolate, file_name.c_str()); | 625 Local<String> source_text = ReadFile(isolate, file_name.c_str()); |
| 587 if (source_text.IsEmpty()) { | 626 if (source_text.IsEmpty()) { |
| 588 printf("Error reading '%s'\n", file_name.c_str()); | 627 printf("Error reading '%s'\n", file_name.c_str()); |
| 589 Shell::Exit(1); | 628 Shell::Exit(1); |
| 590 } | 629 } |
| 591 ScriptOrigin origin( | 630 ScriptOrigin origin( |
| 592 String::NewFromUtf8(isolate, file_name.c_str(), NewStringType::kNormal) | 631 String::NewFromUtf8(isolate, file_name.c_str(), NewStringType::kNormal) |
| 593 .ToLocalChecked()); | 632 .ToLocalChecked()); |
| 594 ScriptCompiler::Source source(source_text, origin); | 633 ScriptCompiler::Source source(source_text, origin); |
| 595 Local<Module> module; | 634 Local<Module> module; |
| 596 if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { | 635 if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { |
| 597 ReportException(isolate, &try_catch); | 636 ReportException(isolate, &try_catch); |
| 598 return MaybeLocal<Module>(); | 637 return MaybeLocal<Module>(); |
| 599 } | 638 } |
| 600 module_map->insert( | 639 |
| 640 ModuleEmbedderData* d = GetModuleDataFromContext(context); | |
| 641 d->specifier_to_module_map.insert( | |
| 601 std::make_pair(file_name, Global<Module>(isolate, module))); | 642 std::make_pair(file_name, Global<Module>(isolate, module))); |
| 602 | 643 |
| 603 std::string dir_name = DirName(file_name); | 644 std::string dir_name = DirName(file_name); |
| 604 module->SetEmbedderData( | 645 d->module_to_directory_map.insert( |
| 605 String::NewFromUtf8(isolate, dir_name.c_str(), NewStringType::kNormal) | 646 std::make_pair(Global<Module>(isolate, module), dir_name)); |
|
neis
2016/10/06 09:44:46
Can you add checks here that these insertions succ
adamk
2016/10/06 20:47:01
Done.
| |
| 606 .ToLocalChecked()); | |
| 607 | 647 |
| 608 for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) { | 648 for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) { |
| 609 Local<String> name = module->GetModuleRequest(i); | 649 Local<String> name = module->GetModuleRequest(i); |
| 610 std::string absolute_path = EnsureAbsolutePath(ToSTLString(name), dir_name); | 650 std::string absolute_path = EnsureAbsolutePath(ToSTLString(name), dir_name); |
| 611 if (!module_map->count(absolute_path)) { | 651 if (!d->specifier_to_module_map.count(absolute_path)) { |
| 612 if (FetchModuleTree(isolate, absolute_path, module_map).IsEmpty()) { | 652 if (FetchModuleTree(context, absolute_path).IsEmpty()) { |
| 613 return MaybeLocal<Module>(); | 653 return MaybeLocal<Module>(); |
| 614 } | 654 } |
| 615 } | 655 } |
| 616 } | 656 } |
| 617 | 657 |
| 618 return module; | 658 return module; |
| 619 } | 659 } |
| 620 | 660 |
| 621 bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { | 661 bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { |
| 622 HandleScope handle_scope(isolate); | 662 HandleScope handle_scope(isolate); |
| 623 | 663 |
| 664 PerIsolateData* data = PerIsolateData::Get(isolate); | |
| 665 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); | |
| 666 Context::Scope context_scope(realm); | |
| 667 | |
| 624 std::string absolute_path = | 668 std::string absolute_path = |
| 625 EnsureAbsolutePath(file_name, GetWorkingDirectory()); | 669 EnsureAbsolutePath(file_name, GetWorkingDirectory()); |
| 626 std::replace(absolute_path.begin(), absolute_path.end(), '\\', '/'); | 670 std::replace(absolute_path.begin(), absolute_path.end(), '\\', '/'); |
| 627 | 671 |
| 628 Local<Module> root_module; | 672 Local<Module> root_module; |
| 629 std::map<std::string, Global<Module>> module_map; | 673 if (!FetchModuleTree(realm, absolute_path).ToLocal(&root_module)) { |
| 630 if (!FetchModuleTree(isolate, absolute_path, &module_map) | |
| 631 .ToLocal(&root_module)) { | |
| 632 return false; | 674 return false; |
| 633 } | 675 } |
| 634 | 676 |
| 635 TryCatch try_catch(isolate); | 677 TryCatch try_catch(isolate); |
| 636 try_catch.SetVerbose(true); | 678 try_catch.SetVerbose(true); |
| 637 | 679 |
| 638 MaybeLocal<Value> maybe_result; | 680 MaybeLocal<Value> maybe_result; |
| 639 { | 681 if (root_module->Instantiate(realm, ResolveModuleCallback)) { |
| 640 PerIsolateData* data = PerIsolateData::Get(isolate); | 682 maybe_result = root_module->Evaluate(realm); |
| 641 Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); | 683 EmptyMessageQueues(isolate); |
| 642 Context::Scope context_scope(realm); | |
| 643 | |
| 644 if (root_module->Instantiate(realm, ResolveModuleCallback, | |
| 645 External::New(isolate, &module_map))) { | |
| 646 maybe_result = root_module->Evaluate(realm); | |
| 647 EmptyMessageQueues(isolate); | |
| 648 } | |
| 649 } | 684 } |
| 650 Local<Value> result; | 685 Local<Value> result; |
| 651 if (!maybe_result.ToLocal(&result)) { | 686 if (!maybe_result.ToLocal(&result)) { |
| 652 DCHECK(try_catch.HasCaught()); | 687 DCHECK(try_catch.HasCaught()); |
| 653 // Print errors that happened during execution. | 688 // Print errors that happened during execution. |
| 654 ReportException(isolate, &try_catch); | 689 ReportException(isolate, &try_catch); |
| 655 return false; | 690 return false; |
| 656 } | 691 } |
| 657 DCHECK(!try_catch.HasCaught()); | 692 DCHECK(!try_catch.HasCaught()); |
| 658 return true; | 693 return true; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 old_realms[i].Reset(); | 803 old_realms[i].Reset(); |
| 769 } | 804 } |
| 770 delete[] old_realms; | 805 delete[] old_realms; |
| 771 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); | 806 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); |
| 772 Local<Context> context = Context::New(isolate, NULL, global_template); | 807 Local<Context> context = Context::New(isolate, NULL, global_template); |
| 773 if (context.IsEmpty()) { | 808 if (context.IsEmpty()) { |
| 774 DCHECK(try_catch.HasCaught()); | 809 DCHECK(try_catch.HasCaught()); |
| 775 try_catch.ReThrow(); | 810 try_catch.ReThrow(); |
| 776 return MaybeLocal<Context>(); | 811 return MaybeLocal<Context>(); |
| 777 } | 812 } |
| 813 InitializeModuleEmbedderData(context); | |
| 778 data->realms_[index].Reset(isolate, context); | 814 data->realms_[index].Reset(isolate, context); |
| 779 args.GetReturnValue().Set(index); | 815 args.GetReturnValue().Set(index); |
| 780 return context; | 816 return context; |
| 781 } | 817 } |
| 782 | 818 |
| 783 // Realm.create() creates a new realm with a distinct security token | 819 // Realm.create() creates a new realm with a distinct security token |
| 784 // and returns its index. | 820 // and returns its index. |
| 785 void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 821 void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 786 CreateRealm(args); | 822 CreateRealm(args); |
| 787 } | 823 } |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1469 | 1505 |
| 1470 | 1506 |
| 1471 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) { | 1507 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) { |
| 1472 // This needs to be a critical section since this is not thread-safe | 1508 // This needs to be a critical section since this is not thread-safe |
| 1473 base::LockGuard<base::Mutex> lock_guard(context_mutex_.Pointer()); | 1509 base::LockGuard<base::Mutex> lock_guard(context_mutex_.Pointer()); |
| 1474 // Initialize the global objects | 1510 // Initialize the global objects |
| 1475 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); | 1511 Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); |
| 1476 EscapableHandleScope handle_scope(isolate); | 1512 EscapableHandleScope handle_scope(isolate); |
| 1477 Local<Context> context = Context::New(isolate, NULL, global_template); | 1513 Local<Context> context = Context::New(isolate, NULL, global_template); |
| 1478 DCHECK(!context.IsEmpty()); | 1514 DCHECK(!context.IsEmpty()); |
| 1515 InitializeModuleEmbedderData(context); | |
| 1479 Context::Scope scope(context); | 1516 Context::Scope scope(context); |
| 1480 | 1517 |
| 1481 i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory(); | 1518 i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory(); |
| 1482 i::JSArguments js_args = i::FLAG_js_arguments; | 1519 i::JSArguments js_args = i::FLAG_js_arguments; |
| 1483 i::Handle<i::FixedArray> arguments_array = | 1520 i::Handle<i::FixedArray> arguments_array = |
| 1484 factory->NewFixedArray(js_args.argc); | 1521 factory->NewFixedArray(js_args.argc); |
| 1485 for (int j = 0; j < js_args.argc; j++) { | 1522 for (int j = 0; j < js_args.argc; j++) { |
| 1486 i::Handle<i::String> arg = | 1523 i::Handle<i::String> arg = |
| 1487 factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked(); | 1524 factory->NewStringFromUtf8(i::CStrVector(js_args[j])).ToHandleChecked(); |
| 1488 arguments_array->set(j, *arg); | 1525 arguments_array->set(j, *arg); |
| (...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2752 } | 2789 } |
| 2753 | 2790 |
| 2754 } // namespace v8 | 2791 } // namespace v8 |
| 2755 | 2792 |
| 2756 | 2793 |
| 2757 #ifndef GOOGLE3 | 2794 #ifndef GOOGLE3 |
| 2758 int main(int argc, char* argv[]) { | 2795 int main(int argc, char* argv[]) { |
| 2759 return v8::Shell::Main(argc, argv); | 2796 return v8::Shell::Main(argc, argv); |
| 2760 } | 2797 } |
| 2761 #endif | 2798 #endif |
| OLD | NEW |