diff options
Diffstat (limited to 'deps/v8/src/ast/modules.cc')
-rw-r--r-- | deps/v8/src/ast/modules.cc | 248 |
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; } |