Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/ast/modules.h"
6 : #include "src/ast/ast-value-factory.h"
7 : #include "src/ast/scopes.h"
8 : #include "src/objects-inl.h"
9 : #include "src/objects/module-inl.h"
10 : #include "src/pending-compilation-error-handler.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 299102 : bool ModuleDescriptor::AstRawStringComparer::operator()(
16 297598 : const AstRawString* lhs, const AstRawString* rhs) const {
17 : // Fast path for equal pointers: a pointer is not strictly less than itself.
18 299102 : if (lhs == rhs) return false;
19 :
20 : // Order by contents (ordering by hash is unstable across runs).
21 297598 : if (lhs->is_one_byte() != rhs->is_one_byte()) {
22 : return lhs->is_one_byte();
23 : }
24 297598 : if (lhs->byte_length() != rhs->byte_length()) {
25 36449 : return lhs->byte_length() < rhs->byte_length();
26 : }
27 522298 : return memcmp(lhs->raw_data(), rhs->raw_data(), lhs->byte_length()) < 0;
28 : }
29 :
30 2064 : void ModuleDescriptor::AddImport(const AstRawString* import_name,
31 : const AstRawString* local_name,
32 : const AstRawString* module_request,
33 : const Scanner::Location loc,
34 2064 : const Scanner::Location specifier_loc,
35 : Zone* zone) {
36 2064 : Entry* entry = new (zone) Entry(loc);
37 2064 : entry->local_name = local_name;
38 2064 : entry->import_name = import_name;
39 2064 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
40 : AddRegularImport(entry);
41 2064 : }
42 :
43 245 : void ModuleDescriptor::AddStarImport(const AstRawString* local_name,
44 : const AstRawString* module_request,
45 : const Scanner::Location loc,
46 245 : const Scanner::Location specifier_loc,
47 : Zone* zone) {
48 245 : Entry* entry = new (zone) Entry(loc);
49 245 : entry->local_name = local_name;
50 245 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
51 : AddNamespaceImport(entry, zone);
52 245 : }
53 :
54 135 : void ModuleDescriptor::AddEmptyImport(const AstRawString* module_request,
55 135 : const Scanner::Location specifier_loc) {
56 135 : AddModuleRequest(module_request, specifier_loc);
57 135 : }
58 :
59 :
60 18900 : void ModuleDescriptor::AddExport(
61 : const AstRawString* local_name, const AstRawString* export_name,
62 : Scanner::Location loc, Zone* zone) {
63 18900 : Entry* entry = new (zone) Entry(loc);
64 18900 : entry->export_name = export_name;
65 18900 : entry->local_name = local_name;
66 : AddRegularExport(entry);
67 18900 : }
68 :
69 100 : void ModuleDescriptor::AddExport(const AstRawString* import_name,
70 : const AstRawString* export_name,
71 : const AstRawString* module_request,
72 : const Scanner::Location loc,
73 100 : const Scanner::Location specifier_loc,
74 : Zone* zone) {
75 : DCHECK_NOT_NULL(import_name);
76 : DCHECK_NOT_NULL(export_name);
77 100 : Entry* entry = new (zone) Entry(loc);
78 100 : entry->export_name = export_name;
79 100 : entry->import_name = import_name;
80 100 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
81 : AddSpecialExport(entry, zone);
82 100 : }
83 :
84 105 : void ModuleDescriptor::AddStarExport(const AstRawString* module_request,
85 : const Scanner::Location loc,
86 105 : const Scanner::Location specifier_loc,
87 : Zone* zone) {
88 105 : Entry* entry = new (zone) Entry(loc);
89 105 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
90 : AddSpecialExport(entry, zone);
91 105 : }
92 :
93 : namespace {
94 :
95 3325 : Handle<Object> ToStringOrUndefined(Isolate* isolate, const AstRawString* s) {
96 : return (s == nullptr)
97 : ? Handle<Object>::cast(isolate->factory()->undefined_value())
98 4338 : : Handle<Object>::cast(s->string());
99 : }
100 :
101 8328 : const AstRawString* FromStringOrUndefined(Isolate* isolate,
102 : AstValueFactory* avfactory,
103 : Handle<Object> object) {
104 16656 : if (object->IsUndefined(isolate)) return nullptr;
105 5257 : return avfactory->GetString(Handle<String>::cast(object));
106 : }
107 :
108 : } // namespace
109 :
110 723 : Handle<ModuleInfoEntry> ModuleDescriptor::Entry::Serialize(
111 : Isolate* isolate) const {
112 723 : CHECK(Smi::IsValid(module_request)); // TODO(neis): Check earlier?
113 : return ModuleInfoEntry::New(
114 : isolate, ToStringOrUndefined(isolate, export_name),
115 : ToStringOrUndefined(isolate, local_name),
116 : ToStringOrUndefined(isolate, import_name), module_request, cell_index,
117 723 : location.beg_pos, location.end_pos);
118 : }
119 :
120 2776 : ModuleDescriptor::Entry* ModuleDescriptor::Entry::Deserialize(
121 2776 : Isolate* isolate, AstValueFactory* avfactory,
122 : Handle<ModuleInfoEntry> entry) {
123 : Entry* result = new (avfactory->zone()) Entry(Scanner::Location::invalid());
124 : result->export_name = FromStringOrUndefined(
125 5552 : isolate, avfactory, handle(entry->export_name(), isolate));
126 : result->local_name = FromStringOrUndefined(
127 5552 : isolate, avfactory, handle(entry->local_name(), isolate));
128 : result->import_name = FromStringOrUndefined(
129 5552 : isolate, avfactory, handle(entry->import_name(), isolate));
130 2776 : result->module_request = entry->module_request();
131 2776 : result->cell_index = entry->cell_index();
132 2776 : return result;
133 : }
134 :
135 1098 : Handle<FixedArray> ModuleDescriptor::SerializeRegularExports(Isolate* isolate,
136 : Zone* zone) const {
137 : // We serialize regular exports in a way that lets us later iterate over their
138 : // local names and for each local name immediately access all its export
139 : // names. (Regular exports have neither import name nor module request.)
140 :
141 : ZoneVector<Handle<Object>> data(
142 1098 : ModuleInfo::kRegularExportLength * regular_exports_.size(), zone);
143 : int index = 0;
144 :
145 19744 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
146 : // Find out how many export names this local name has.
147 : auto next = it;
148 : int count = 0;
149 17623 : do {
150 : DCHECK_EQ(it->second->local_name, next->second->local_name);
151 : DCHECK_EQ(it->second->cell_index, next->second->cell_index);
152 : ++next;
153 17623 : ++count;
154 17623 : } while (next != regular_exports_.end() && next->first == it->first);
155 :
156 17548 : Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(count);
157 17548 : data[index + ModuleInfo::kRegularExportLocalNameOffset] =
158 17548 : it->second->local_name->string();
159 17548 : data[index + ModuleInfo::kRegularExportCellIndexOffset] =
160 35096 : handle(Smi::FromInt(it->second->cell_index), isolate);
161 35096 : data[index + ModuleInfo::kRegularExportExportNamesOffset] = export_names;
162 17548 : index += ModuleInfo::kRegularExportLength;
163 :
164 : // Collect the export names.
165 : int i = 0;
166 52719 : for (; it != next; ++it) {
167 52869 : export_names->set(i++, *it->second->export_name->string());
168 : }
169 : DCHECK_EQ(i, count);
170 :
171 : // Continue with the next distinct key.
172 : DCHECK(it == next);
173 : }
174 : DCHECK_LE(index, static_cast<int>(data.size()));
175 1098 : data.resize(index);
176 :
177 : // We cannot create the FixedArray earlier because we only now know the
178 : // precise size.
179 1098 : Handle<FixedArray> result = isolate->factory()->NewFixedArray(index);
180 53742 : for (int i = 0; i < index; ++i) {
181 105288 : result->set(i, *data[i]);
182 : }
183 1098 : return result;
184 : }
185 :
186 3217 : void ModuleDescriptor::DeserializeRegularExports(
187 3860 : Isolate* isolate, AstValueFactory* avfactory,
188 : Handle<ModuleInfo> module_info) {
189 6971 : for (int i = 0, count = module_info->RegularExportCount(); i < count; ++i) {
190 7508 : Handle<String> local_name(module_info->RegularExportLocalName(i), isolate);
191 3754 : int cell_index = module_info->RegularExportCellIndex(i);
192 : Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
193 7508 : isolate);
194 :
195 7614 : for (int j = 0, length = export_names->length(); j < length; ++j) {
196 : Handle<String> export_name(String::cast(export_names->get(j)), isolate);
197 :
198 : Entry* entry =
199 : new (avfactory->zone()) Entry(Scanner::Location::invalid());
200 3860 : entry->local_name = avfactory->GetString(local_name);
201 3860 : entry->export_name = avfactory->GetString(export_name);
202 3860 : entry->cell_index = cell_index;
203 :
204 : AddRegularExport(entry);
205 : }
206 : }
207 3217 : }
208 :
209 35571 : void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
210 89977 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
211 18835 : Entry* entry = it->second;
212 : DCHECK_NOT_NULL(entry->local_name);
213 18835 : auto import = regular_imports_.find(entry->local_name);
214 18835 : if (import != regular_imports_.end()) {
215 : // Found an indirect export. Patch export entry and move it from regular
216 : // to special.
217 : DCHECK_NULL(entry->import_name);
218 : DCHECK_LT(entry->module_request, 0);
219 : DCHECK_NOT_NULL(import->second->import_name);
220 : DCHECK_LE(0, import->second->module_request);
221 : DCHECK_LT(import->second->module_request,
222 : static_cast<int>(module_requests_.size()));
223 40 : entry->import_name = import->second->import_name;
224 40 : entry->module_request = import->second->module_request;
225 : // Hack: When the indirect export cannot be resolved, we want the error
226 : // message to point at the import statement, not at the export statement.
227 : // Therefore we overwrite [entry]'s location here. Note that Validate()
228 : // has already checked for duplicate exports, so it's guaranteed that we
229 : // won't need to report any error pointing at the (now lost) export
230 : // location.
231 40 : entry->location = import->second->location;
232 40 : entry->local_name = nullptr;
233 : AddSpecialExport(entry, zone);
234 : it = regular_exports_.erase(it);
235 : } else {
236 : it++;
237 : }
238 : }
239 35571 : }
240 :
241 10039 : ModuleDescriptor::CellIndexKind ModuleDescriptor::GetCellIndexKind(
242 : int cell_index) {
243 10039 : if (cell_index > 0) return kExport;
244 1398 : if (cell_index < 0) return kImport;
245 5 : return kInvalid;
246 : }
247 :
248 35571 : void ModuleDescriptor::AssignCellIndices() {
249 : int export_index = 1;
250 89852 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
251 18710 : auto current_key = it->first;
252 : // This local name may be exported under multiple export names. Assign the
253 : // same index to each such entry.
254 18795 : do {
255 18795 : Entry* entry = it->second;
256 : DCHECK_NOT_NULL(entry->local_name);
257 : DCHECK_NULL(entry->import_name);
258 : DCHECK_LT(entry->module_request, 0);
259 : DCHECK_EQ(entry->cell_index, 0);
260 18795 : entry->cell_index = export_index;
261 : it++;
262 18795 : } while (it != regular_exports_.end() && it->first == current_key);
263 18710 : export_index++;
264 : }
265 :
266 : int import_index = -1;
267 73206 : for (const auto& elem : regular_imports_) {
268 2064 : Entry* entry = elem.second;
269 : DCHECK_NOT_NULL(entry->local_name);
270 : DCHECK_NOT_NULL(entry->import_name);
271 : DCHECK_LE(0, entry->module_request);
272 : DCHECK_EQ(entry->cell_index, 0);
273 2064 : entry->cell_index = import_index;
274 2064 : import_index--;
275 : }
276 35571 : }
277 :
278 : namespace {
279 :
280 19000 : const ModuleDescriptor::Entry* BetterDuplicate(
281 : const ModuleDescriptor::Entry* candidate,
282 : ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*>& export_names,
283 : const ModuleDescriptor::Entry* current_duplicate) {
284 : DCHECK_NOT_NULL(candidate->export_name);
285 : DCHECK(candidate->location.IsValid());
286 : auto insert_result =
287 38000 : export_names.insert(std::make_pair(candidate->export_name, candidate));
288 19000 : if (insert_result.second) return current_duplicate;
289 25 : if (current_duplicate == nullptr) {
290 25 : current_duplicate = insert_result.first->second;
291 : }
292 25 : return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
293 : ? candidate
294 25 : : current_duplicate;
295 : }
296 :
297 : } // namespace
298 :
299 35611 : const ModuleDescriptor::Entry* ModuleDescriptor::FindDuplicateExport(
300 : Zone* zone) const {
301 : const ModuleDescriptor::Entry* duplicate = nullptr;
302 : ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*> export_names(
303 : zone);
304 90122 : for (const auto& elem : regular_exports_) {
305 18900 : duplicate = BetterDuplicate(elem.second, export_names, duplicate);
306 : }
307 71427 : for (auto entry : special_exports_) {
308 205 : if (entry->export_name == nullptr) continue; // Star export.
309 100 : duplicate = BetterDuplicate(entry, export_names, duplicate);
310 : }
311 35611 : return duplicate;
312 : }
313 :
314 35611 : bool ModuleDescriptor::Validate(ModuleScope* module_scope,
315 : PendingCompilationErrorHandler* error_handler,
316 : Zone* zone) {
317 : DCHECK_EQ(this, module_scope->module());
318 : DCHECK_NOT_NULL(error_handler);
319 :
320 : // Report error iff there are duplicate exports.
321 : {
322 35611 : const Entry* entry = FindDuplicateExport(zone);
323 35611 : if (entry != nullptr) {
324 : error_handler->ReportMessageAt(
325 : entry->location.beg_pos, entry->location.end_pos,
326 25 : MessageTemplate::kDuplicateExport, entry->export_name);
327 25 : return false;
328 : }
329 : }
330 :
331 : // Report error iff there are exports of non-existent local names.
332 90007 : for (const auto& elem : regular_exports_) {
333 18850 : const Entry* entry = elem.second;
334 : DCHECK_NOT_NULL(entry->local_name);
335 37700 : if (module_scope->LookupLocal(entry->local_name) == nullptr) {
336 : error_handler->ReportMessageAt(
337 : entry->location.beg_pos, entry->location.end_pos,
338 15 : MessageTemplate::kModuleExportUndefined, entry->local_name);
339 : return false;
340 : }
341 : }
342 :
343 35571 : MakeIndirectExportsExplicit(zone);
344 35571 : AssignCellIndices();
345 35571 : return true;
346 : }
347 :
348 : } // namespace internal
349 183867 : } // namespace v8
|