Commit b2b434df authored by neis's avatar neis Committed by Commit bot

[modules] Support exporting a local variable under multiple export names.

R=adamk@chromium.org
BUG=v8:1569

Review-Url: https://codereview.chromium.org/2353403003
Cr-Commit-Position: refs/heads/master@{#39604}
parent 74bf86ab
......@@ -1949,19 +1949,13 @@ bool Module::Instantiate(Local<Context> v8_context,
self->requested_modules()->set(i, *Utils::OpenHandle(*import));
}
// TODO(neis): This will create multiple cells for the same local variable if
// exported under multiple names, which is wrong but cannot be observed at the
// moment. This will be fixed by doing the full-fledged linking here once we
// get there.
// Set up local exports.
i::Handle<i::FixedArray> regular_exports = i::handle(
shared->scope_info()->ModuleDescriptorInfo()->regular_exports(), isolate);
for (int i = 0, length = regular_exports->length(); i < length; ++i) {
i::Handle<i::ModuleInfoEntry> entry =
i::handle(i::ModuleInfoEntry::cast(regular_exports->get(i)), isolate);
DCHECK(entry->import_name()->IsUndefined(isolate));
i::Handle<i::String> export_name =
handle(i::String::cast(entry->export_name()), isolate);
i::Module::CreateExport(self, export_name);
for (int i = 0, n = regular_exports->length(); i < n; i += 2) {
i::Handle<i::FixedArray> export_names(
i::FixedArray::cast(regular_exports->get(i + 1)), isolate);
i::Module::CreateExport(self, export_names);
}
return true;
......@@ -2124,8 +2118,7 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(Isolate* isolate,
if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>();
i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound);
i::Handle<i::Module> module = i_isolate->factory()->NewModule(shared);
return ToApiHandle<Module>(module);
return ToApiHandle<Module>(i_isolate->factory()->NewModule(shared));
}
......
......@@ -110,6 +110,69 @@ ModuleDescriptor::Entry* ModuleDescriptor::Entry::Deserialize(
return result;
}
Handle<FixedArray> ModuleDescriptor::SerializeRegularExports(Isolate* isolate,
Zone* zone) const {
// We serialize regular exports in a way that lets us later iterate over their
// local names and for each local name immediately access all its export
// names. (Regular exports have neither import name nor module request.)
ZoneVector<Handle<Object>> data(zone);
data.reserve(2 * regular_exports_.size());
for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
// Find out how many export names this local name has.
auto next = it;
int size = 0;
do {
++next;
++size;
} while (next != regular_exports_.end() && next->first == it->first);
Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(size);
data.push_back(it->second->local_name->string());
data.push_back(export_names);
// Collect the export names.
int i = 0;
for (; it != next; ++it) {
export_names->set(i++, *it->second->export_name->string());
}
DCHECK_EQ(i, size);
// Continue with the next distinct key.
DCHECK(it == next);
}
// We cannot create the FixedArray earlier because we only now know the
// precise size (the number of unique keys in regular_exports).
int size = static_cast<int>(data.size());
Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
for (int i = 0; i < size; ++i) {
result->set(i, *data[i]);
}
return result;
}
void ModuleDescriptor::DeserializeRegularExports(Isolate* isolate,
AstValueFactory* avfactory,
Handle<FixedArray> data) {
for (int i = 0, length_i = data->length(); i < length_i;) {
Handle<String> local_name(String::cast(data->get(i++)), isolate);
Handle<FixedArray> export_names(FixedArray::cast(data->get(i++)), isolate);
for (int j = 0, length_j = export_names->length(); j < length_j; ++j) {
Handle<String> export_name(String::cast(export_names->get(j)), isolate);
Entry* entry =
new (avfactory->zone()) Entry(Scanner::Location::invalid());
entry->local_name = avfactory->GetString(local_name);
entry->export_name = avfactory->GetString(export_name);
AddRegularExport(entry);
}
}
}
void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
Entry* entry = it->second;
......
......@@ -155,6 +155,11 @@ class ModuleDescriptor : public ZoneObject {
special_imports_.Add(entry, zone);
}
Handle<FixedArray> SerializeRegularExports(Isolate* isolate,
Zone* zone) const;
void DeserializeRegularExports(Isolate* isolate, AstValueFactory* avfactory,
Handle<FixedArray> data);
private:
// TODO(neis): Use STL datastructure instead of ZoneList?
ZoneMap<const AstRawString*, int> module_requests_;
......
......@@ -272,7 +272,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
// Module-specific information (only for module scopes).
if (scope->is_module_scope()) {
Handle<ModuleInfo> module_info =
ModuleInfo::New(isolate, scope->AsModuleScope()->module());
ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
DCHECK_EQ(index, scope_info->ModuleInfoIndex());
scope_info->set(index++, *module_info);
DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
......@@ -852,7 +852,8 @@ Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
return result;
}
Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, ModuleDescriptor* descr) {
Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
ModuleDescriptor* descr) {
// Serialize module requests.
Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
static_cast<int>(descr->module_requests().size()));
......@@ -881,14 +882,8 @@ Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, ModuleDescriptor* descr) {
}
// Serialize regular exports.
Handle<FixedArray> regular_exports = isolate->factory()->NewFixedArray(
static_cast<int>(descr->regular_exports().size()));
{
int i = 0;
for (const auto& elem : descr->regular_exports()) {
regular_exports->set(i++, *elem.second->Serialize(isolate));
}
}
Handle<FixedArray> regular_exports =
descr->SerializeRegularExports(isolate, zone);
// Serialize regular imports.
Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
......
......@@ -167,7 +167,7 @@ ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
module_descriptor_ = new (zone) ModuleDescriptor(zone);
// Deserialize special exports.
Handle<FixedArray> special_exports = handle(module_info->special_exports());
Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
for (int i = 0, n = special_exports->length(); i < n; ++i) {
Handle<ModuleInfoEntry> serialized_entry(
ModuleInfoEntry::cast(special_exports->get(i)), isolate);
......@@ -178,16 +178,12 @@ ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
}
// Deserialize regular exports.
Handle<FixedArray> regular_exports = handle(module_info->regular_exports());
for (int i = 0, n = regular_exports->length(); i < n; ++i) {
Handle<ModuleInfoEntry> serialized_entry(
ModuleInfoEntry::cast(regular_exports->get(i)), isolate);
module_descriptor_->AddRegularExport(ModuleDescriptor::Entry::Deserialize(
isolate, avfactory, serialized_entry));
}
Handle<FixedArray> regular_exports(module_info->regular_exports(), isolate);
module_descriptor_->DeserializeRegularExports(isolate, avfactory,
regular_exports);
// Deserialize special imports.
Handle<FixedArray> special_imports = handle(module_info->special_imports());
Handle<FixedArray> special_imports(module_info->special_imports(), isolate);
for (int i = 0, n = special_imports->length(); i < n; ++i) {
Handle<ModuleInfoEntry> serialized_entry(
ModuleInfoEntry::cast(special_imports->get(i)), isolate);
......@@ -198,7 +194,7 @@ ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
}
// Deserialize regular imports.
Handle<FixedArray> regular_imports = handle(module_info->regular_imports());
Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
for (int i = 0, n = regular_imports->length(); i < n; ++i) {
Handle<ModuleInfoEntry> serialized_entry(
ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
......
......@@ -19580,13 +19580,17 @@ bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
return false;
}
void Module::CreateExport(Handle<Module> module, Handle<String> name) {
void Module::CreateExport(Handle<Module> module, Handle<FixedArray> names) {
DCHECK_LT(0, names->length());
Isolate* isolate = module->GetIsolate();
Handle<Cell> cell =
isolate->factory()->NewCell(isolate->factory()->undefined_value());
Handle<ObjectHashTable> exports(module->exports(), isolate);
DCHECK(exports->Lookup(name)->IsTheHole(isolate));
exports = ObjectHashTable::Put(exports, name, cell);
for (int i = 0, n = names->length(); i < n; ++i) {
Handle<String> name(String::cast(names->get(i)), isolate);
DCHECK(exports->Lookup(name)->IsTheHole(isolate));
exports = ObjectHashTable::Put(exports, name, cell);
}
module->set_exports(*exports);
}
......
......@@ -4582,7 +4582,8 @@ class ModuleInfoEntry : public FixedArray {
class ModuleInfo : public FixedArray {
public:
DECLARE_CAST(ModuleInfo)
static Handle<ModuleInfo> New(Isolate* isolate, ModuleDescriptor* descr);
static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
ModuleDescriptor* descr);
inline FixedArray* module_requests() const;
inline FixedArray* special_exports() const;
inline FixedArray* regular_exports() const;
......@@ -7944,7 +7945,7 @@ class Module : public Struct {
// Storage for [[Evaluated]]
DECL_INT_ACCESSORS(flags)
static void CreateExport(Handle<Module> module, Handle<String> name);
static void CreateExport(Handle<Module> module, Handle<FixedArray> names);
static void StoreExport(Handle<Module> module, Handle<String> name,
Handle<Object> value);
static Handle<Object> LoadExport(Handle<Module> module, Handle<String> name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment