summaryrefslogtreecommitdiff
path: root/deps/v8/src/ast/modules.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ast/modules.cc')
-rw-r--r--deps/v8/src/ast/modules.cc248
1 files changed, 185 insertions, 63 deletions
diff --git a/deps/v8/src/ast/modules.cc b/deps/v8/src/ast/modules.cc
index cd47c00b92..2d28d5564b 100644
--- a/deps/v8/src/ast/modules.cc
+++ b/deps/v8/src/ast/modules.cc
@@ -12,49 +12,35 @@ namespace internal {
void ModuleDescriptor::AddImport(
const AstRawString* import_name, const AstRawString* local_name,
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
- DCHECK_NOT_NULL(import_name);
- DCHECK_NOT_NULL(local_name);
- DCHECK_NOT_NULL(module_request);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
+ Entry* entry = new (zone) Entry(loc);
entry->local_name = local_name;
entry->import_name = import_name;
- entry->module_request = module_request;
- regular_imports_.insert(std::make_pair(entry->local_name, entry));
- // We don't care if there's already an entry for this local name, as in that
- // case we will report an error when declaring the variable.
+ entry->module_request = AddModuleRequest(module_request);
+ AddRegularImport(entry);
}
void ModuleDescriptor::AddStarImport(
const AstRawString* local_name, const AstRawString* module_request,
Scanner::Location loc, Zone* zone) {
- DCHECK_NOT_NULL(local_name);
- DCHECK_NOT_NULL(module_request);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
+ Entry* entry = new (zone) Entry(loc);
entry->local_name = local_name;
- entry->module_request = module_request;
- special_imports_.Add(entry, zone);
+ entry->module_request = AddModuleRequest(module_request);
+ AddNamespaceImport(entry, zone);
}
-
-void ModuleDescriptor::AddEmptyImport(
- const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
- DCHECK_NOT_NULL(module_request);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
- entry->module_request = module_request;
- special_imports_.Add(entry, zone);
+void ModuleDescriptor::AddEmptyImport(const AstRawString* module_request) {
+ AddModuleRequest(module_request);
}
void ModuleDescriptor::AddExport(
const AstRawString* local_name, const AstRawString* export_name,
Scanner::Location loc, Zone* zone) {
- DCHECK_NOT_NULL(local_name);
- DCHECK_NOT_NULL(export_name);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
+ Entry* entry = new (zone) Entry(loc);
entry->export_name = export_name;
entry->local_name = local_name;
- exports_.Add(entry, zone);
+ AddRegularExport(entry);
}
@@ -63,40 +49,186 @@ void ModuleDescriptor::AddExport(
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
DCHECK_NOT_NULL(import_name);
DCHECK_NOT_NULL(export_name);
- DCHECK_NOT_NULL(module_request);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
+ Entry* entry = new (zone) Entry(loc);
entry->export_name = export_name;
entry->import_name = import_name;
- entry->module_request = module_request;
- exports_.Add(entry, zone);
+ entry->module_request = AddModuleRequest(module_request);
+ AddSpecialExport(entry, zone);
}
void ModuleDescriptor::AddStarExport(
const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
- DCHECK_NOT_NULL(module_request);
- ModuleEntry* entry = new (zone) ModuleEntry(loc);
- entry->module_request = module_request;
- exports_.Add(entry, zone);
+ Entry* entry = new (zone) Entry(loc);
+ entry->module_request = AddModuleRequest(module_request);
+ AddSpecialExport(entry, zone);
+}
+
+namespace {
+
+Handle<Object> ToStringOrUndefined(Isolate* isolate, const AstRawString* s) {
+ return (s == nullptr)
+ ? Handle<Object>::cast(isolate->factory()->undefined_value())
+ : Handle<Object>::cast(s->string());
+}
+
+const AstRawString* FromStringOrUndefined(Isolate* isolate,
+ AstValueFactory* avfactory,
+ Handle<Object> object) {
+ if (object->IsUndefined(isolate)) return nullptr;
+ return avfactory->GetString(Handle<String>::cast(object));
+}
+
+} // namespace
+
+Handle<ModuleInfoEntry> ModuleDescriptor::Entry::Serialize(
+ Isolate* isolate) const {
+ CHECK(Smi::IsValid(module_request)); // TODO(neis): Check earlier?
+ return ModuleInfoEntry::New(
+ isolate, ToStringOrUndefined(isolate, export_name),
+ ToStringOrUndefined(isolate, local_name),
+ ToStringOrUndefined(isolate, import_name),
+ Handle<Object>(Smi::FromInt(module_request), isolate));
}
-void ModuleDescriptor::MakeIndirectExportsExplicit() {
- for (auto entry : exports_) {
- if (entry->export_name == nullptr) continue;
- if (entry->import_name != nullptr) continue;
+ModuleDescriptor::Entry* ModuleDescriptor::Entry::Deserialize(
+ Isolate* isolate, AstValueFactory* avfactory,
+ Handle<ModuleInfoEntry> entry) {
+ Entry* result = new (avfactory->zone()) Entry(Scanner::Location::invalid());
+ result->export_name = FromStringOrUndefined(
+ isolate, avfactory, handle(entry->export_name(), isolate));
+ result->local_name = FromStringOrUndefined(
+ isolate, avfactory, handle(entry->local_name(), isolate));
+ result->import_name = FromStringOrUndefined(
+ isolate, avfactory, handle(entry->import_name(), isolate));
+ result->module_request = Smi::cast(entry->module_request())->value();
+ 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;
DCHECK_NOT_NULL(entry->local_name);
- auto it = regular_imports_.find(entry->local_name);
- if (it != regular_imports_.end()) {
- // Found an indirect export.
- DCHECK_NOT_NULL(it->second->module_request);
- DCHECK_NOT_NULL(it->second->import_name);
- entry->import_name = it->second->import_name;
- entry->module_request = it->second->module_request;
+ auto import = regular_imports_.find(entry->local_name);
+ if (import != regular_imports_.end()) {
+ // Found an indirect export. Patch export entry and move it from regular
+ // to special.
+ DCHECK_NULL(entry->import_name);
+ DCHECK_LT(entry->module_request, 0);
+ DCHECK_NOT_NULL(import->second->import_name);
+ DCHECK_LE(0, import->second->module_request);
+ DCHECK_LT(import->second->module_request,
+ static_cast<int>(module_requests_.size()));
+ entry->import_name = import->second->import_name;
+ entry->module_request = import->second->module_request;
entry->local_name = nullptr;
+ AddSpecialExport(entry, zone);
+ it = regular_exports_.erase(it);
+ } else {
+ it++;
}
}
}
+namespace {
+
+const ModuleDescriptor::Entry* BetterDuplicate(
+ const ModuleDescriptor::Entry* candidate,
+ ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*>& export_names,
+ const ModuleDescriptor::Entry* current_duplicate) {
+ DCHECK_NOT_NULL(candidate->export_name);
+ DCHECK(candidate->location.IsValid());
+ auto insert_result =
+ export_names.insert(std::make_pair(candidate->export_name, candidate));
+ if (insert_result.second) return current_duplicate;
+ if (current_duplicate == nullptr) {
+ current_duplicate = insert_result.first->second;
+ }
+ return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
+ ? candidate
+ : current_duplicate;
+}
+
+} // namespace
+
+const ModuleDescriptor::Entry* ModuleDescriptor::FindDuplicateExport(
+ Zone* zone) const {
+ const ModuleDescriptor::Entry* duplicate = nullptr;
+ ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*> export_names(
+ zone);
+ for (const auto& elem : regular_exports_) {
+ duplicate = BetterDuplicate(elem.second, export_names, duplicate);
+ }
+ for (auto entry : special_exports_) {
+ if (entry->export_name == nullptr) continue; // Star export.
+ duplicate = BetterDuplicate(entry, export_names, duplicate);
+ }
+ return duplicate;
+}
+
bool ModuleDescriptor::Validate(ModuleScope* module_scope,
PendingCompilationErrorHandler* error_handler,
Zone* zone) {
@@ -105,29 +237,19 @@ bool ModuleDescriptor::Validate(ModuleScope* module_scope,
// Report error iff there are duplicate exports.
{
- ZoneAllocationPolicy allocator(zone);
- ZoneHashMap* export_names = new (zone->New(sizeof(ZoneHashMap)))
- ZoneHashMap(ZoneHashMap::PointersMatch,
- ZoneHashMap::kDefaultHashMapCapacity, allocator);
- for (auto entry : exports_) {
- if (entry->export_name == nullptr) continue;
- AstRawString* key = const_cast<AstRawString*>(entry->export_name);
- ZoneHashMap::Entry* p =
- export_names->LookupOrInsert(key, key->hash(), allocator);
- DCHECK_NOT_NULL(p);
- if (p->value != nullptr) {
- error_handler->ReportMessageAt(
- entry->location.beg_pos, entry->location.end_pos,
- MessageTemplate::kDuplicateExport, entry->export_name);
- return false;
- }
- p->value = key; // Anything but nullptr.
+ const Entry* entry = FindDuplicateExport(zone);
+ if (entry != nullptr) {
+ error_handler->ReportMessageAt(
+ entry->location.beg_pos, entry->location.end_pos,
+ MessageTemplate::kDuplicateExport, entry->export_name);
+ return false;
}
}
// Report error iff there are exports of non-existent local names.
- for (auto entry : exports_) {
- if (entry->local_name == nullptr) continue;
+ for (const auto& elem : regular_exports_) {
+ const Entry* entry = elem.second;
+ DCHECK_NOT_NULL(entry->local_name);
if (module_scope->LookupLocal(entry->local_name) == nullptr) {
error_handler->ReportMessageAt(
entry->location.beg_pos, entry->location.end_pos,
@@ -136,7 +258,7 @@ bool ModuleDescriptor::Validate(ModuleScope* module_scope,
}
}
- MakeIndirectExportsExplicit();
+ MakeIndirectExportsExplicit(zone);
return true;
}