Chromium Code Reviews| Index: src/d8.cc |
| diff --git a/src/d8.cc b/src/d8.cc |
| index 01801f80f6d30a158e944a992e0c823b1741f04e..d1f11a7189f0a9aa0f8f612028219d661ead176b 100644 |
| --- a/src/d8.cc |
| +++ b/src/d8.cc |
| @@ -9,7 +9,7 @@ |
| #include <algorithm> |
| #include <fstream> |
| -#include <map> |
| +#include <unordered_map> |
| #include <utility> |
| #include <vector> |
| @@ -558,29 +558,68 @@ std::string EnsureAbsolutePath(const std::string& path, |
| return IsAbsolutePath(path) ? path : dir_name + '/' + path; |
| } |
| +// Per-context Module data, allowing sharing of module maps |
| +// across top-level module loads. |
| +class ModuleEmbedderData { |
| + private: |
| + class ModuleGlobalHash { |
| + public: |
| + explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {} |
| + size_t operator()(const Global<Module>& module) const { |
| + return module.Get(isolate_)->GetIdentityHash(); |
| + } |
| + |
| + private: |
| + Isolate* isolate_; |
| + }; |
| + |
| + public: |
| + explicit ModuleEmbedderData(Isolate* isolate) |
| + : module_to_directory_map(10, ModuleGlobalHash(isolate)) {} |
| + |
| + // Map from normalized module specifiers to Modules. |
| + std::unordered_map<std::string, Global<Module>> specifier_to_module_map; |
| + // 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.
|
| + std::unordered_map<Global<Module>, std::string, ModuleGlobalHash> |
| + module_to_directory_map; |
| +}; |
| + |
| +enum D8EmbedderDataFields { |
| + 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
|
| + kModuleEmbedderDataIndex |
| +}; |
| + |
| +void InitializeModuleEmbedderData(Local<Context> context) { |
| + context->SetAlignedPointerInEmbedderData( |
| + kModuleEmbedderDataIndex, new ModuleEmbedderData(context->GetIsolate())); |
| +} |
| + |
| +ModuleEmbedderData* GetModuleDataFromContext(Local<Context> context) { |
| + return static_cast<ModuleEmbedderData*>( |
| + context->GetAlignedPointerFromEmbedderData(kModuleEmbedderDataIndex)); |
| +} |
| + |
| MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, |
| Local<String> specifier, |
| - Local<Module> referrer, |
| - Local<Value> data) { |
| + Local<Module> referrer) { |
| Isolate* isolate = context->GetIsolate(); |
| - auto module_map = static_cast<std::map<std::string, Global<Module>>*>( |
| - External::Cast(*data)->Value()); |
| - Local<String> dir_name = Local<String>::Cast(referrer->GetEmbedderData()); |
| + ModuleEmbedderData* d = GetModuleDataFromContext(context); |
| + auto dir_name_it = |
| + d->module_to_directory_map.find(Global<Module>(isolate, referrer)); |
| + CHECK(dir_name_it != d->module_to_directory_map.end()); |
| std::string absolute_path = |
| - EnsureAbsolutePath(ToSTLString(specifier), ToSTLString(dir_name)); |
| - auto it = module_map->find(absolute_path); |
| - if (it != module_map->end()) { |
| - return it->second.Get(isolate); |
| - } |
| - return MaybeLocal<Module>(); |
| + EnsureAbsolutePath(ToSTLString(specifier), dir_name_it->second); |
| + auto module_it = d->specifier_to_module_map.find(absolute_path); |
| + CHECK(module_it != d->specifier_to_module_map.end()); |
| + return module_it->second.Get(isolate); |
| } |
| } // anonymous namespace |
| -MaybeLocal<Module> Shell::FetchModuleTree( |
| - Isolate* isolate, const std::string& file_name, |
| - std::map<std::string, Global<Module>>* module_map) { |
| +MaybeLocal<Module> Shell::FetchModuleTree(Local<Context> context, |
| + const std::string& file_name) { |
| DCHECK(IsAbsolutePath(file_name)); |
| + Isolate* isolate = context->GetIsolate(); |
| TryCatch try_catch(isolate); |
| try_catch.SetVerbose(true); |
| Local<String> source_text = ReadFile(isolate, file_name.c_str()); |
| @@ -597,19 +636,20 @@ MaybeLocal<Module> Shell::FetchModuleTree( |
| ReportException(isolate, &try_catch); |
| return MaybeLocal<Module>(); |
| } |
| - module_map->insert( |
| + |
| + ModuleEmbedderData* d = GetModuleDataFromContext(context); |
| + d->specifier_to_module_map.insert( |
| std::make_pair(file_name, Global<Module>(isolate, module))); |
| std::string dir_name = DirName(file_name); |
| - module->SetEmbedderData( |
| - String::NewFromUtf8(isolate, dir_name.c_str(), NewStringType::kNormal) |
| - .ToLocalChecked()); |
| + d->module_to_directory_map.insert( |
| + 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.
|
| for (int i = 0, length = module->GetModuleRequestsLength(); i < length; ++i) { |
| Local<String> name = module->GetModuleRequest(i); |
| std::string absolute_path = EnsureAbsolutePath(ToSTLString(name), dir_name); |
| - if (!module_map->count(absolute_path)) { |
| - if (FetchModuleTree(isolate, absolute_path, module_map).IsEmpty()) { |
| + if (!d->specifier_to_module_map.count(absolute_path)) { |
| + if (FetchModuleTree(context, absolute_path).IsEmpty()) { |
| return MaybeLocal<Module>(); |
| } |
| } |
| @@ -621,14 +661,16 @@ MaybeLocal<Module> Shell::FetchModuleTree( |
| bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { |
| HandleScope handle_scope(isolate); |
| + PerIsolateData* data = PerIsolateData::Get(isolate); |
| + Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); |
| + Context::Scope context_scope(realm); |
| + |
| std::string absolute_path = |
| EnsureAbsolutePath(file_name, GetWorkingDirectory()); |
| std::replace(absolute_path.begin(), absolute_path.end(), '\\', '/'); |
| Local<Module> root_module; |
| - std::map<std::string, Global<Module>> module_map; |
| - if (!FetchModuleTree(isolate, absolute_path, &module_map) |
| - .ToLocal(&root_module)) { |
| + if (!FetchModuleTree(realm, absolute_path).ToLocal(&root_module)) { |
| return false; |
| } |
| @@ -636,16 +678,9 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { |
| try_catch.SetVerbose(true); |
| MaybeLocal<Value> maybe_result; |
| - { |
| - PerIsolateData* data = PerIsolateData::Get(isolate); |
| - Local<Context> realm = data->realms_[data->realm_current_].Get(isolate); |
| - Context::Scope context_scope(realm); |
| - |
| - if (root_module->Instantiate(realm, ResolveModuleCallback, |
| - External::New(isolate, &module_map))) { |
| - maybe_result = root_module->Evaluate(realm); |
| - EmptyMessageQueues(isolate); |
| - } |
| + if (root_module->Instantiate(realm, ResolveModuleCallback)) { |
| + maybe_result = root_module->Evaluate(realm); |
| + EmptyMessageQueues(isolate); |
| } |
| Local<Value> result; |
| if (!maybe_result.ToLocal(&result)) { |
| @@ -775,6 +810,7 @@ MaybeLocal<Context> Shell::CreateRealm( |
| try_catch.ReThrow(); |
| return MaybeLocal<Context>(); |
| } |
| + InitializeModuleEmbedderData(context); |
| data->realms_[index].Reset(isolate, context); |
| args.GetReturnValue().Set(index); |
| return context; |
| @@ -1476,6 +1512,7 @@ Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) { |
| EscapableHandleScope handle_scope(isolate); |
| Local<Context> context = Context::New(isolate, NULL, global_template); |
| DCHECK(!context.IsEmpty()); |
| + InitializeModuleEmbedderData(context); |
| Context::Scope scope(context); |
| i::Factory* factory = reinterpret_cast<i::Isolate*>(isolate)->factory(); |