1 // Copyright 2011 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/objects/scope-info.h"
6
7 #include <stdlib.h>
8
9 #include "src/ast/scopes.h"
10 #include "src/ast/variables.h"
11 #include "src/init/bootstrapper.h"
12 #include "src/objects/module-inl.h"
13 #include "src/objects/objects-inl.h"
14 #include "src/objects/string-set-inl.h"
15 #include "src/roots/roots.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // An entry in ModuleVariableEntries consists of several slots:
21 enum ModuleVariableEntryOffset {
22 kModuleVariableNameOffset,
23 kModuleVariableIndexOffset,
24 kModuleVariablePropertiesOffset,
25 kModuleVariableEntryLength // Sentinel value.
26 };
27
28 #ifdef DEBUG
Equals(ScopeInfo other) const29 bool ScopeInfo::Equals(ScopeInfo other) const {
30 if (length() != other.length()) return false;
31 for (int index = 0; index < length(); ++index) {
32 Object entry = get(index);
33 Object other_entry = other.get(index);
34 if (entry.IsSmi()) {
35 if (entry != other_entry) return false;
36 } else {
37 if (HeapObject::cast(entry).map().instance_type() !=
38 HeapObject::cast(other_entry).map().instance_type()) {
39 return false;
40 }
41 if (entry.IsString()) {
42 if (!String::cast(entry).Equals(String::cast(other_entry))) {
43 return false;
44 }
45 } else if (entry.IsScopeInfo()) {
46 if (!ScopeInfo::cast(entry).Equals(ScopeInfo::cast(other_entry))) {
47 return false;
48 }
49 } else if (entry.IsSourceTextModuleInfo()) {
50 if (!SourceTextModuleInfo::cast(entry).Equals(
51 SourceTextModuleInfo::cast(other_entry))) {
52 return false;
53 }
54 } else {
55 UNREACHABLE();
56 }
57 }
58 }
59 return true;
60 }
61 #endif
62
63 // static
64 template <typename LocalIsolate>
Create(LocalIsolate * isolate,Zone * zone,Scope * scope,MaybeHandle<ScopeInfo> outer_scope)65 Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
66 Scope* scope,
67 MaybeHandle<ScopeInfo> outer_scope) {
68 // Collect variables.
69 int context_local_count = 0;
70 int module_vars_count = 0;
71 // Stack allocated block scope variables are allocated in the parent
72 // declaration scope, but are recorded in the block scope's scope info. First
73 // slot index indicates at which offset a particular scope starts in the
74 // parent declaration scope.
75 for (Variable* var : *scope->locals()) {
76 switch (var->location()) {
77 case VariableLocation::CONTEXT:
78 case VariableLocation::REPL_GLOBAL:
79 context_local_count++;
80 break;
81 case VariableLocation::MODULE:
82 module_vars_count++;
83 break;
84 default:
85 break;
86 }
87 }
88 // Determine use and location of the "this" binding if it is present.
89 VariableAllocationInfo receiver_info;
90 if (scope->is_declaration_scope() &&
91 scope->AsDeclarationScope()->has_this_declaration()) {
92 Variable* var = scope->AsDeclarationScope()->receiver();
93 if (!var->is_used()) {
94 receiver_info = VariableAllocationInfo::UNUSED;
95 } else if (var->IsContextSlot()) {
96 receiver_info = VariableAllocationInfo::CONTEXT;
97 context_local_count++;
98 } else {
99 DCHECK(var->IsParameter());
100 receiver_info = VariableAllocationInfo::STACK;
101 }
102 } else {
103 receiver_info = VariableAllocationInfo::NONE;
104 }
105
106 DCHECK(module_vars_count == 0 || scope->is_module_scope());
107
108 // Make sure we allocate the correct amount.
109 DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
110
111 const bool has_new_target =
112 scope->is_declaration_scope() &&
113 scope->AsDeclarationScope()->new_target_var() != nullptr;
114 // TODO(cbruni): Don't always waste a field for the inferred name.
115 const bool has_inferred_function_name = scope->is_function_scope();
116
117 // Determine use and location of the function variable if it is present.
118 VariableAllocationInfo function_name_info;
119 if (scope->is_function_scope()) {
120 if (scope->AsDeclarationScope()->function_var() != nullptr) {
121 Variable* var = scope->AsDeclarationScope()->function_var();
122 if (!var->is_used()) {
123 function_name_info = VariableAllocationInfo::UNUSED;
124 } else if (var->IsContextSlot()) {
125 function_name_info = VariableAllocationInfo::CONTEXT;
126 } else {
127 DCHECK(var->IsStackLocal());
128 function_name_info = VariableAllocationInfo::STACK;
129 }
130 } else {
131 // Always reserve space for the debug name in the scope info.
132 function_name_info = VariableAllocationInfo::UNUSED;
133 }
134 } else if (scope->is_module_scope() || scope->is_script_scope() ||
135 scope->is_eval_scope()) {
136 // Always reserve space for the debug name in the scope info.
137 function_name_info = VariableAllocationInfo::UNUSED;
138 } else {
139 function_name_info = VariableAllocationInfo::NONE;
140 }
141
142 const bool has_brand = scope->is_class_scope()
143 ? scope->AsClassScope()->brand() != nullptr
144 : false;
145 const bool should_save_class_variable_index =
146 scope->is_class_scope()
147 ? scope->AsClassScope()->should_save_class_variable_index()
148 : false;
149 const bool has_function_name =
150 function_name_info != VariableAllocationInfo::NONE;
151 const bool has_position_info = NeedsPositionInfo(scope->scope_type());
152 const bool has_receiver = receiver_info == VariableAllocationInfo::STACK ||
153 receiver_info == VariableAllocationInfo::CONTEXT;
154 const int parameter_count =
155 scope->is_declaration_scope()
156 ? scope->AsDeclarationScope()->num_parameters()
157 : 0;
158 const bool has_outer_scope_info = !outer_scope.is_null();
159
160 const int length = kVariablePartIndex + 2 * context_local_count +
161 (should_save_class_variable_index ? 1 : 0) +
162 (has_receiver ? 1 : 0) +
163 (has_function_name ? kFunctionNameEntries : 0) +
164 (has_inferred_function_name ? 1 : 0) +
165 (has_position_info ? kPositionInfoEntries : 0) +
166 (has_outer_scope_info ? 1 : 0) +
167 (scope->is_module_scope()
168 ? 2 + kModuleVariableEntryLength * module_vars_count
169 : 0);
170
171 Handle<ScopeInfo> scope_info_handle =
172 isolate->factory()->NewScopeInfo(length);
173 int index = kVariablePartIndex;
174 {
175 DisallowHeapAllocation no_gc;
176 ScopeInfo scope_info = *scope_info_handle;
177 WriteBarrierMode mode = scope_info.GetWriteBarrierMode(no_gc);
178
179 bool has_simple_parameters = false;
180 bool is_asm_module = false;
181 bool sloppy_eval_can_extend_vars = false;
182 if (scope->is_function_scope()) {
183 DeclarationScope* function_scope = scope->AsDeclarationScope();
184 has_simple_parameters = function_scope->has_simple_parameters();
185 is_asm_module = function_scope->is_asm_module();
186 }
187 FunctionKind function_kind = kNormalFunction;
188 if (scope->is_declaration_scope()) {
189 function_kind = scope->AsDeclarationScope()->function_kind();
190 sloppy_eval_can_extend_vars =
191 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars();
192 }
193
194 // Encode the flags.
195 int flags =
196 ScopeTypeBits::encode(scope->scope_type()) |
197 SloppyEvalCanExtendVarsBit::encode(sloppy_eval_can_extend_vars) |
198 LanguageModeBit::encode(scope->language_mode()) |
199 DeclarationScopeBit::encode(scope->is_declaration_scope()) |
200 ReceiverVariableBits::encode(receiver_info) |
201 HasClassBrandBit::encode(has_brand) |
202 HasSavedClassVariableIndexBit::encode(
203 should_save_class_variable_index) |
204 HasNewTargetBit::encode(has_new_target) |
205 FunctionVariableBits::encode(function_name_info) |
206 HasInferredFunctionNameBit::encode(has_inferred_function_name) |
207 IsAsmModuleBit::encode(is_asm_module) |
208 HasSimpleParametersBit::encode(has_simple_parameters) |
209 FunctionKindBits::encode(function_kind) |
210 HasOuterScopeInfoBit::encode(has_outer_scope_info) |
211 IsDebugEvaluateScopeBit::encode(scope->is_debug_evaluate_scope()) |
212 ForceContextAllocationBit::encode(
213 scope->ForceContextForLanguageMode()) |
214 PrivateNameLookupSkipsOuterClassBit::encode(
215 scope->private_name_lookup_skips_outer_class()) |
216 HasContextExtensionSlotBit::encode(scope->HasContextExtensionSlot()) |
217 IsReplModeScopeBit::encode(scope->is_repl_mode_scope()) |
218 HasLocalsBlockListBit::encode(false);
219 scope_info.SetFlags(flags);
220
221 scope_info.SetParameterCount(parameter_count);
222 scope_info.SetContextLocalCount(context_local_count);
223
224 // Add context locals' names and info, module variables' names and info.
225 // Context locals are added using their index.
226 int context_local_base = index;
227 int context_local_info_base = context_local_base + context_local_count;
228 int module_var_entry = scope_info.ModuleVariablesIndex();
229
230 for (Variable* var : *scope->locals()) {
231 switch (var->location()) {
232 case VariableLocation::CONTEXT:
233 case VariableLocation::REPL_GLOBAL: {
234 // Due to duplicate parameters, context locals aren't guaranteed to
235 // come in order.
236 int local_index = var->index() - scope->ContextHeaderLength();
237 DCHECK_LE(0, local_index);
238 DCHECK_LT(local_index, context_local_count);
239 uint32_t info =
240 VariableModeField::encode(var->mode()) |
241 InitFlagField::encode(var->initialization_flag()) |
242 MaybeAssignedFlagField::encode(var->maybe_assigned()) |
243 ParameterNumberField::encode(ParameterNumberField::kMax) |
244 IsStaticFlagField::encode(var->is_static_flag());
245 scope_info.set(context_local_base + local_index, *var->name(), mode);
246 scope_info.set(context_local_info_base + local_index,
247 Smi::FromInt(info));
248 break;
249 }
250 case VariableLocation::MODULE: {
251 scope_info.set(module_var_entry + kModuleVariableNameOffset,
252 *var->name(), mode);
253 scope_info.set(module_var_entry + kModuleVariableIndexOffset,
254 Smi::FromInt(var->index()));
255 uint32_t properties =
256 VariableModeField::encode(var->mode()) |
257 InitFlagField::encode(var->initialization_flag()) |
258 MaybeAssignedFlagField::encode(var->maybe_assigned()) |
259 ParameterNumberField::encode(ParameterNumberField::kMax) |
260 IsStaticFlagField::encode(var->is_static_flag());
261 scope_info.set(module_var_entry + kModuleVariablePropertiesOffset,
262 Smi::FromInt(properties));
263 module_var_entry += kModuleVariableEntryLength;
264 break;
265 }
266 default:
267 break;
268 }
269 }
270
271 if (scope->is_declaration_scope()) {
272 // Mark contexts slots with the parameter number they represent. We walk
273 // the list of parameters. That can include duplicate entries if a
274 // parameter name is repeated. By walking upwards, we'll automatically
275 // mark the context slot with the highest parameter number that uses this
276 // variable. That will be the parameter number that is represented by the
277 // context slot. All lower parameters will only be available on the stack
278 // through the arguments object.
279 for (int i = 0; i < parameter_count; i++) {
280 Variable* parameter = scope->AsDeclarationScope()->parameter(i);
281 if (parameter->location() != VariableLocation::CONTEXT) continue;
282 int index = parameter->index() - scope->ContextHeaderLength();
283 int info_index = context_local_info_base + index;
284 int info = Smi::ToInt(scope_info.get(info_index));
285 info = ParameterNumberField::update(info, i);
286 scope_info.set(info_index, Smi::FromInt(info));
287 }
288
289 // TODO(verwaest): Remove this unnecessary entry.
290 if (scope->AsDeclarationScope()->has_this_declaration()) {
291 Variable* var = scope->AsDeclarationScope()->receiver();
292 if (var->location() == VariableLocation::CONTEXT) {
293 int local_index = var->index() - scope->ContextHeaderLength();
294 uint32_t info =
295 VariableModeField::encode(var->mode()) |
296 InitFlagField::encode(var->initialization_flag()) |
297 MaybeAssignedFlagField::encode(var->maybe_assigned()) |
298 ParameterNumberField::encode(ParameterNumberField::kMax) |
299 IsStaticFlagField::encode(var->is_static_flag());
300 scope_info.set(context_local_base + local_index, *var->name(), mode);
301 scope_info.set(context_local_info_base + local_index,
302 Smi::FromInt(info));
303 }
304 }
305 }
306
307 index += 2 * context_local_count;
308
309 DCHECK_EQ(index, scope_info.SavedClassVariableInfoIndex());
310 // If the scope is a class scope and has used static private methods, save
311 // the context slot index of the class variable.
312 // Store the class variable index.
313 if (should_save_class_variable_index) {
314 Variable* class_variable = scope->AsClassScope()->class_variable();
315 DCHECK_EQ(class_variable->location(), VariableLocation::CONTEXT);
316 scope_info.set(index++, Smi::FromInt(class_variable->index()));
317 }
318
319 // If the receiver is allocated, add its index.
320 DCHECK_EQ(index, scope_info.ReceiverInfoIndex());
321 if (has_receiver) {
322 int var_index = scope->AsDeclarationScope()->receiver()->index();
323 scope_info.set(index++, Smi::FromInt(var_index));
324 // ?? DCHECK(receiver_info != CONTEXT || var_index ==
325 // scope_info->ContextLength() - 1);
326 }
327
328 // If present, add the function variable name and its index.
329 DCHECK_EQ(index, scope_info.FunctionNameInfoIndex());
330 if (has_function_name) {
331 Variable* var = scope->AsDeclarationScope()->function_var();
332 int var_index = -1;
333 Object name = Smi::zero();
334 if (var != nullptr) {
335 var_index = var->index();
336 name = *var->name();
337 }
338 scope_info.set(index++, name, mode);
339 scope_info.set(index++, Smi::FromInt(var_index));
340 DCHECK(function_name_info != VariableAllocationInfo::CONTEXT ||
341 var_index == scope_info.ContextLength() - 1);
342 }
343
344 DCHECK_EQ(index, scope_info.InferredFunctionNameIndex());
345 if (has_inferred_function_name) {
346 // The inferred function name is taken from the SFI.
347 index++;
348 }
349
350 DCHECK_EQ(index, scope_info.PositionInfoIndex());
351 if (has_position_info) {
352 scope_info.set(index++, Smi::FromInt(scope->start_position()));
353 scope_info.set(index++, Smi::FromInt(scope->end_position()));
354 }
355
356 // If present, add the outer scope info.
357 DCHECK(index == scope_info.OuterScopeInfoIndex());
358 if (has_outer_scope_info) {
359 scope_info.set(index++, *outer_scope.ToHandleChecked(), mode);
360 }
361 }
362
363 // Module-specific information (only for module scopes).
364 if (scope->is_module_scope()) {
365 Handle<SourceTextModuleInfo> module_info = SourceTextModuleInfo::New(
366 isolate, zone, scope->AsModuleScope()->module());
367 DCHECK_EQ(index, scope_info_handle->ModuleInfoIndex());
368 scope_info_handle->set(index++, *module_info);
369 DCHECK_EQ(index, scope_info_handle->ModuleVariableCountIndex());
370 scope_info_handle->set(index++, Smi::FromInt(module_vars_count));
371 DCHECK_EQ(index, scope_info_handle->ModuleVariablesIndex());
372 // The variable entries themselves have already been written above.
373 index += kModuleVariableEntryLength * module_vars_count;
374 }
375
376 DCHECK_EQ(index, scope_info_handle->length());
377 DCHECK_EQ(parameter_count, scope_info_handle->ParameterCount());
378 DCHECK_EQ(scope->num_heap_slots(), scope_info_handle->ContextLength());
379 return scope_info_handle;
380 }
381
382 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
383 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
384 Scope* scope,
385 MaybeHandle<ScopeInfo> outer_scope);
386 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
387 Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
388 Scope* scope,
389 MaybeHandle<ScopeInfo> outer_scope);
390
391 // static
CreateForWithScope(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)392 Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
393 Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
394 const bool has_outer_scope_info = !outer_scope.is_null();
395 const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
396
397 Factory* factory = isolate->factory();
398 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
399
400 // Encode the flags.
401 int flags =
402 ScopeTypeBits::encode(WITH_SCOPE) |
403 SloppyEvalCanExtendVarsBit::encode(false) |
404 LanguageModeBit::encode(LanguageMode::kSloppy) |
405 DeclarationScopeBit::encode(false) |
406 ReceiverVariableBits::encode(VariableAllocationInfo::NONE) |
407 HasClassBrandBit::encode(false) |
408 HasSavedClassVariableIndexBit::encode(false) |
409 HasNewTargetBit::encode(false) |
410 FunctionVariableBits::encode(VariableAllocationInfo::NONE) |
411 IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
412 FunctionKindBits::encode(kNormalFunction) |
413 HasOuterScopeInfoBit::encode(has_outer_scope_info) |
414 IsDebugEvaluateScopeBit::encode(false) |
415 ForceContextAllocationBit::encode(false) |
416 PrivateNameLookupSkipsOuterClassBit::encode(false) |
417 HasContextExtensionSlotBit::encode(true) |
418 IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
419 scope_info->SetFlags(flags);
420
421 scope_info->SetParameterCount(0);
422 scope_info->SetContextLocalCount(0);
423
424 int index = kVariablePartIndex;
425 DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
426 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
427 DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
428 DCHECK_EQ(index, scope_info->PositionInfoIndex());
429 DCHECK(index == scope_info->OuterScopeInfoIndex());
430 if (has_outer_scope_info) {
431 scope_info->set(index++, *outer_scope.ToHandleChecked());
432 }
433 DCHECK_EQ(index, scope_info->length());
434 DCHECK_EQ(0, scope_info->ParameterCount());
435 DCHECK_EQ(scope_info->ContextHeaderLength(), scope_info->ContextLength());
436 return scope_info;
437 }
438
439 // static
CreateGlobalThisBinding(Isolate * isolate)440 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
441 return CreateForBootstrapping(isolate, BootstrappingType::kScript);
442 }
443
444 // static
CreateForEmptyFunction(Isolate * isolate)445 Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
446 return CreateForBootstrapping(isolate, BootstrappingType::kFunction);
447 }
448
449 // static
CreateForNativeContext(Isolate * isolate)450 Handle<ScopeInfo> ScopeInfo::CreateForNativeContext(Isolate* isolate) {
451 return CreateForBootstrapping(isolate, BootstrappingType::kNative);
452 }
453
454 // static
CreateForBootstrapping(Isolate * isolate,BootstrappingType type)455 Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
456 BootstrappingType type) {
457 const int parameter_count = 0;
458 const bool is_empty_function = type == BootstrappingType::kFunction;
459 const bool is_native_context = type == BootstrappingType::kNative;
460 const bool is_script = type == BootstrappingType::kScript;
461 const int context_local_count =
462 is_empty_function || is_native_context ? 0 : 1;
463 const bool has_receiver = is_script;
464 const bool has_inferred_function_name = is_empty_function;
465 const bool has_position_info = true;
466 const int length = kVariablePartIndex + 2 * context_local_count +
467 (has_receiver ? 1 : 0) +
468 (is_empty_function ? kFunctionNameEntries : 0) +
469 (has_inferred_function_name ? 1 : 0) +
470 (has_position_info ? kPositionInfoEntries : 0);
471
472 Factory* factory = isolate->factory();
473 Handle<ScopeInfo> scope_info =
474 factory->NewScopeInfo(length, AllocationType::kReadOnly);
475
476 // Encode the flags.
477 int flags =
478 ScopeTypeBits::encode(is_empty_function ? FUNCTION_SCOPE : SCRIPT_SCOPE) |
479 SloppyEvalCanExtendVarsBit::encode(false) |
480 LanguageModeBit::encode(LanguageMode::kSloppy) |
481 DeclarationScopeBit::encode(true) |
482 ReceiverVariableBits::encode(is_script ? VariableAllocationInfo::CONTEXT
483 : VariableAllocationInfo::UNUSED) |
484 HasClassBrandBit::encode(false) |
485 HasSavedClassVariableIndexBit::encode(false) |
486 HasNewTargetBit::encode(false) |
487 FunctionVariableBits::encode(is_empty_function
488 ? VariableAllocationInfo::UNUSED
489 : VariableAllocationInfo::NONE) |
490 HasInferredFunctionNameBit::encode(has_inferred_function_name) |
491 IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
492 FunctionKindBits::encode(FunctionKind::kNormalFunction) |
493 HasOuterScopeInfoBit::encode(false) |
494 IsDebugEvaluateScopeBit::encode(false) |
495 ForceContextAllocationBit::encode(false) |
496 PrivateNameLookupSkipsOuterClassBit::encode(false) |
497 HasContextExtensionSlotBit::encode(is_native_context) |
498 IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
499 scope_info->SetFlags(flags);
500 scope_info->SetParameterCount(parameter_count);
501 scope_info->SetContextLocalCount(context_local_count);
502
503 int index = kVariablePartIndex;
504
505 // Here we add info for context-allocated "this".
506 DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
507 if (context_local_count) {
508 scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
509 }
510 DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
511 if (context_local_count > 0) {
512 const uint32_t value =
513 VariableModeField::encode(VariableMode::kConst) |
514 InitFlagField::encode(kCreatedInitialized) |
515 MaybeAssignedFlagField::encode(kNotAssigned) |
516 ParameterNumberField::encode(ParameterNumberField::kMax) |
517 IsStaticFlagField::encode(IsStaticFlag::kNotStatic);
518 scope_info->set(index++, Smi::FromInt(value));
519 }
520
521 // And here we record that this scopeinfo binds a receiver.
522 DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
523 if (has_receiver) {
524 const int receiver_index = scope_info->ContextHeaderLength();
525 scope_info->set(index++, Smi::FromInt(receiver_index));
526 }
527
528 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
529 if (is_empty_function) {
530 scope_info->set(index++, *isolate->factory()->empty_string());
531 scope_info->set(index++, Smi::zero());
532 }
533 DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
534 if (has_inferred_function_name) {
535 scope_info->set(index++, *isolate->factory()->empty_string());
536 }
537 DCHECK_EQ(index, scope_info->PositionInfoIndex());
538 // Store dummy position to be in sync with the {scope_type}.
539 scope_info->set(index++, Smi::zero());
540 scope_info->set(index++, Smi::zero());
541 DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
542 DCHECK_EQ(index, scope_info->length());
543 DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
544 if (is_empty_function || is_native_context) {
545 DCHECK_EQ(scope_info->ContextLength(), 0);
546 } else {
547 DCHECK_EQ(scope_info->ContextLength(),
548 scope_info->ContextHeaderLength() + 1);
549 }
550
551 return scope_info;
552 }
553
554 // static
RecreateWithBlockList(Isolate * isolate,Handle<ScopeInfo> original,Handle<StringSet> blocklist)555 Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
556 Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blocklist) {
557 DCHECK(!original.is_null());
558 if (original->HasLocalsBlockList()) return original;
559
560 Handle<ScopeInfo> scope_info =
561 isolate->factory()->NewScopeInfo(original->length() + 1);
562
563 // Copy the static part first and update the flags to include the
564 // blocklist field, so {LocalsBlockListIndex} returns the correct value.
565 scope_info->CopyElements(isolate, 0, *original, 0, kVariablePartIndex,
566 WriteBarrierMode::UPDATE_WRITE_BARRIER);
567 scope_info->SetFlags(
568 HasLocalsBlockListBit::update(scope_info->Flags(), true));
569
570 // Copy the dynamic part including the provided blocklist:
571 // 1) copy all the fields up to the blocklist index
572 // 2) add the blocklist
573 // 3) copy the remaining fields
574 scope_info->CopyElements(
575 isolate, kVariablePartIndex, *original, kVariablePartIndex,
576 scope_info->LocalsBlockListIndex() - kVariablePartIndex,
577 WriteBarrierMode::UPDATE_WRITE_BARRIER);
578 scope_info->set(scope_info->LocalsBlockListIndex(), *blocklist);
579 scope_info->CopyElements(
580 isolate, scope_info->LocalsBlockListIndex() + 1, *original,
581 scope_info->LocalsBlockListIndex(),
582 scope_info->length() - scope_info->LocalsBlockListIndex() - 1,
583 WriteBarrierMode::UPDATE_WRITE_BARRIER);
584 return scope_info;
585 }
586
Empty(Isolate * isolate)587 ScopeInfo ScopeInfo::Empty(Isolate* isolate) {
588 return ReadOnlyRoots(isolate).empty_scope_info();
589 }
590
scope_type() const591 ScopeType ScopeInfo::scope_type() const {
592 DCHECK_LT(0, length());
593 return ScopeTypeBits::decode(Flags());
594 }
595
is_script_scope() const596 bool ScopeInfo::is_script_scope() const {
597 return length() > 0 && scope_type() == SCRIPT_SCOPE;
598 }
599
SloppyEvalCanExtendVars() const600 bool ScopeInfo::SloppyEvalCanExtendVars() const {
601 bool sloppy_eval_can_extend_vars =
602 length() > 0 && SloppyEvalCanExtendVarsBit::decode(Flags());
603 DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_sloppy(language_mode()));
604 DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_declaration_scope());
605 return sloppy_eval_can_extend_vars;
606 }
607
language_mode() const608 LanguageMode ScopeInfo::language_mode() const {
609 return length() > 0 ? LanguageModeBit::decode(Flags())
610 : LanguageMode::kSloppy;
611 }
612
is_declaration_scope() const613 bool ScopeInfo::is_declaration_scope() const {
614 return DeclarationScopeBit::decode(Flags());
615 }
616
ContextLength() const617 int ScopeInfo::ContextLength() const {
618 if (length() > 0) {
619 int context_locals = ContextLocalCount();
620 bool function_name_context_slot = FunctionVariableBits::decode(Flags()) ==
621 VariableAllocationInfo::CONTEXT;
622 bool force_context = ForceContextAllocationBit::decode(Flags());
623 bool has_context =
624 context_locals > 0 || force_context || function_name_context_slot ||
625 scope_type() == WITH_SCOPE || scope_type() == CLASS_SCOPE ||
626 (scope_type() == BLOCK_SCOPE && SloppyEvalCanExtendVars() &&
627 is_declaration_scope()) ||
628 (scope_type() == FUNCTION_SCOPE && SloppyEvalCanExtendVars()) ||
629 (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
630 scope_type() == MODULE_SCOPE;
631
632 if (has_context) {
633 return ContextHeaderLength() + context_locals +
634 (function_name_context_slot ? 1 : 0);
635 }
636 }
637 return 0;
638 }
639
HasContextExtensionSlot() const640 bool ScopeInfo::HasContextExtensionSlot() const {
641 return HasContextExtensionSlotBit::decode(Flags());
642 }
643
ContextHeaderLength() const644 int ScopeInfo::ContextHeaderLength() const {
645 return HasContextExtensionSlot() ? Context::MIN_CONTEXT_EXTENDED_SLOTS
646 : Context::MIN_CONTEXT_SLOTS;
647 }
648
HasReceiver() const649 bool ScopeInfo::HasReceiver() const {
650 if (length() == 0) return false;
651 return VariableAllocationInfo::NONE != ReceiverVariableBits::decode(Flags());
652 }
653
HasAllocatedReceiver() const654 bool ScopeInfo::HasAllocatedReceiver() const {
655 if (length() == 0) return false;
656 VariableAllocationInfo allocation = ReceiverVariableBits::decode(Flags());
657 return allocation == VariableAllocationInfo::STACK ||
658 allocation == VariableAllocationInfo::CONTEXT;
659 }
660
HasClassBrand() const661 bool ScopeInfo::HasClassBrand() const {
662 return HasClassBrandBit::decode(Flags());
663 }
664
HasSavedClassVariableIndex() const665 bool ScopeInfo::HasSavedClassVariableIndex() const {
666 return HasSavedClassVariableIndexBit::decode(Flags());
667 }
668
HasNewTarget() const669 bool ScopeInfo::HasNewTarget() const {
670 return HasNewTargetBit::decode(Flags());
671 }
672
HasFunctionName() const673 bool ScopeInfo::HasFunctionName() const {
674 if (length() == 0) return false;
675 return VariableAllocationInfo::NONE != FunctionVariableBits::decode(Flags());
676 }
677
HasInferredFunctionName() const678 bool ScopeInfo::HasInferredFunctionName() const {
679 if (length() == 0) return false;
680 return HasInferredFunctionNameBit::decode(Flags());
681 }
682
HasPositionInfo() const683 bool ScopeInfo::HasPositionInfo() const {
684 if (length() == 0) return false;
685 return NeedsPositionInfo(scope_type());
686 }
687
688 // static
NeedsPositionInfo(ScopeType type)689 bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
690 return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
691 type == MODULE_SCOPE;
692 }
693
HasSharedFunctionName() const694 bool ScopeInfo::HasSharedFunctionName() const {
695 return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
696 }
697
SetFunctionName(Object name)698 void ScopeInfo::SetFunctionName(Object name) {
699 DCHECK(HasFunctionName());
700 DCHECK(name.IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
701 set(FunctionNameInfoIndex(), name);
702 }
703
SetInferredFunctionName(String name)704 void ScopeInfo::SetInferredFunctionName(String name) {
705 DCHECK(HasInferredFunctionName());
706 set(InferredFunctionNameIndex(), name);
707 }
708
HasOuterScopeInfo() const709 bool ScopeInfo::HasOuterScopeInfo() const {
710 if (length() == 0) return false;
711 return HasOuterScopeInfoBit::decode(Flags());
712 }
713
IsDebugEvaluateScope() const714 bool ScopeInfo::IsDebugEvaluateScope() const {
715 if (length() == 0) return false;
716 return IsDebugEvaluateScopeBit::decode(Flags());
717 }
718
SetIsDebugEvaluateScope()719 void ScopeInfo::SetIsDebugEvaluateScope() {
720 if (length() > 0) {
721 DCHECK_EQ(scope_type(), WITH_SCOPE);
722 SetFlags(Flags() | IsDebugEvaluateScopeBit::encode(true));
723 } else {
724 UNREACHABLE();
725 }
726 }
727
PrivateNameLookupSkipsOuterClass() const728 bool ScopeInfo::PrivateNameLookupSkipsOuterClass() const {
729 if (length() == 0) return false;
730 return PrivateNameLookupSkipsOuterClassBit::decode(Flags());
731 }
732
IsReplModeScope() const733 bool ScopeInfo::IsReplModeScope() const {
734 if (length() == 0) return false;
735 return IsReplModeScopeBit::decode(Flags());
736 }
737
HasLocalsBlockList() const738 bool ScopeInfo::HasLocalsBlockList() const {
739 if (length() == 0) return false;
740 return HasLocalsBlockListBit::decode(Flags());
741 }
742
LocalsBlockList() const743 StringSet ScopeInfo::LocalsBlockList() const {
744 DCHECK(HasLocalsBlockList());
745 return StringSet::cast(get(LocalsBlockListIndex()));
746 }
747
HasContext() const748 bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
749
FunctionName() const750 Object ScopeInfo::FunctionName() const {
751 DCHECK(HasFunctionName());
752 return get(FunctionNameInfoIndex());
753 }
754
InferredFunctionName() const755 Object ScopeInfo::InferredFunctionName() const {
756 DCHECK(HasInferredFunctionName());
757 return get(InferredFunctionNameIndex());
758 }
759
FunctionDebugName() const760 String ScopeInfo::FunctionDebugName() const {
761 if (!HasFunctionName()) return GetReadOnlyRoots().empty_string();
762 Object name = FunctionName();
763 if (name.IsString() && String::cast(name).length() > 0) {
764 return String::cast(name);
765 }
766 if (HasInferredFunctionName()) {
767 name = InferredFunctionName();
768 if (name.IsString()) return String::cast(name);
769 }
770 return GetReadOnlyRoots().empty_string();
771 }
772
StartPosition() const773 int ScopeInfo::StartPosition() const {
774 DCHECK(HasPositionInfo());
775 return Smi::ToInt(get(PositionInfoIndex()));
776 }
777
EndPosition() const778 int ScopeInfo::EndPosition() const {
779 DCHECK(HasPositionInfo());
780 return Smi::ToInt(get(PositionInfoIndex() + 1));
781 }
782
SetPositionInfo(int start,int end)783 void ScopeInfo::SetPositionInfo(int start, int end) {
784 DCHECK(HasPositionInfo());
785 DCHECK_LE(start, end);
786 set(PositionInfoIndex(), Smi::FromInt(start));
787 set(PositionInfoIndex() + 1, Smi::FromInt(end));
788 }
789
OuterScopeInfo() const790 ScopeInfo ScopeInfo::OuterScopeInfo() const {
791 DCHECK(HasOuterScopeInfo());
792 return ScopeInfo::cast(get(OuterScopeInfoIndex()));
793 }
794
ModuleDescriptorInfo() const795 SourceTextModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
796 DCHECK(scope_type() == MODULE_SCOPE);
797 return SourceTextModuleInfo::cast(get(ModuleInfoIndex()));
798 }
799
ContextLocalName(int var) const800 String ScopeInfo::ContextLocalName(int var) const {
801 DCHECK_LE(0, var);
802 DCHECK_LT(var, ContextLocalCount());
803 int info_index = ContextLocalNamesIndex() + var;
804 return String::cast(get(info_index));
805 }
806
ContextLocalMode(int var) const807 VariableMode ScopeInfo::ContextLocalMode(int var) const {
808 DCHECK_LE(0, var);
809 DCHECK_LT(var, ContextLocalCount());
810 int info_index = ContextLocalInfosIndex() + var;
811 int value = Smi::ToInt(get(info_index));
812 return VariableModeField::decode(value);
813 }
814
ContextLocalIsStaticFlag(int var) const815 IsStaticFlag ScopeInfo::ContextLocalIsStaticFlag(int var) const {
816 DCHECK_LE(0, var);
817 DCHECK_LT(var, ContextLocalCount());
818 int info_index = ContextLocalInfosIndex() + var;
819 int value = Smi::ToInt(get(info_index));
820 return IsStaticFlagField::decode(value);
821 }
822
ContextLocalInitFlag(int var) const823 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
824 DCHECK_LE(0, var);
825 DCHECK_LT(var, ContextLocalCount());
826 int info_index = ContextLocalInfosIndex() + var;
827 int value = Smi::ToInt(get(info_index));
828 return InitFlagField::decode(value);
829 }
830
ContextLocalIsParameter(int var) const831 bool ScopeInfo::ContextLocalIsParameter(int var) const {
832 DCHECK_LE(0, var);
833 DCHECK_LT(var, ContextLocalCount());
834 int info_index = ContextLocalInfosIndex() + var;
835 int value = Smi::ToInt(get(info_index));
836 return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
837 }
838
ContextLocalParameterNumber(int var) const839 uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
840 DCHECK(ContextLocalIsParameter(var));
841 int info_index = ContextLocalInfosIndex() + var;
842 int value = Smi::ToInt(get(info_index));
843 return ParameterNumberField::decode(value);
844 }
845
ContextLocalMaybeAssignedFlag(int var) const846 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
847 DCHECK_LE(0, var);
848 DCHECK_LT(var, ContextLocalCount());
849 int info_index = ContextLocalInfosIndex() + var;
850 int value = Smi::ToInt(get(info_index));
851 return MaybeAssignedFlagField::decode(value);
852 }
853
854 // static
VariableIsSynthetic(String name)855 bool ScopeInfo::VariableIsSynthetic(String name) {
856 // There's currently no flag stored on the ScopeInfo to indicate that a
857 // variable is a compiler-introduced temporary. However, to avoid conflict
858 // with user declarations, the current temporaries like .generator_object and
859 // .result start with a dot, so we can use that as a flag. It's a hack!
860 return name.length() == 0 || name.Get(0) == '.' || name.Get(0) == '#' ||
861 name.Equals(name.GetReadOnlyRoots().this_string());
862 }
863
ModuleIndex(String name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)864 int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
865 InitializationFlag* init_flag,
866 MaybeAssignedFlag* maybe_assigned_flag) {
867 DisallowHeapAllocation no_gc;
868 DCHECK(name.IsInternalizedString());
869 DCHECK_EQ(scope_type(), MODULE_SCOPE);
870 DCHECK_NOT_NULL(mode);
871 DCHECK_NOT_NULL(init_flag);
872 DCHECK_NOT_NULL(maybe_assigned_flag);
873
874 int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
875 int entry = ModuleVariablesIndex();
876 for (int i = 0; i < module_vars_count; ++i) {
877 String var_name = String::cast(get(entry + kModuleVariableNameOffset));
878 if (name.Equals(var_name)) {
879 int index;
880 ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
881 return index;
882 }
883 entry += kModuleVariableEntryLength;
884 }
885
886 return 0;
887 }
888
889 // static
ContextSlotIndex(ScopeInfo scope_info,String name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag,IsStaticFlag * is_static_flag)890 int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
891 VariableMode* mode,
892 InitializationFlag* init_flag,
893 MaybeAssignedFlag* maybe_assigned_flag,
894 IsStaticFlag* is_static_flag) {
895 DisallowHeapAllocation no_gc;
896 DCHECK(name.IsInternalizedString());
897 DCHECK_NOT_NULL(mode);
898 DCHECK_NOT_NULL(init_flag);
899 DCHECK_NOT_NULL(maybe_assigned_flag);
900
901 if (scope_info.length() == 0) return -1;
902
903 int start = scope_info.ContextLocalNamesIndex();
904 int end = start + scope_info.ContextLocalCount();
905 for (int i = start; i < end; ++i) {
906 if (name != scope_info.get(i)) continue;
907 int var = i - start;
908 *mode = scope_info.ContextLocalMode(var);
909 *is_static_flag = scope_info.ContextLocalIsStaticFlag(var);
910 *init_flag = scope_info.ContextLocalInitFlag(var);
911 *maybe_assigned_flag = scope_info.ContextLocalMaybeAssignedFlag(var);
912 int result = scope_info.ContextHeaderLength() + var;
913
914 DCHECK_LT(result, scope_info.ContextLength());
915 return result;
916 }
917
918 return -1;
919 }
920
SavedClassVariableContextLocalIndex() const921 int ScopeInfo::SavedClassVariableContextLocalIndex() const {
922 if (length() > 0 && HasSavedClassVariableIndexBit::decode(Flags())) {
923 int index = Smi::ToInt(get(SavedClassVariableInfoIndex()));
924 return index - Context::MIN_CONTEXT_SLOTS;
925 }
926 return -1;
927 }
928
ReceiverContextSlotIndex() const929 int ScopeInfo::ReceiverContextSlotIndex() const {
930 if (length() > 0 && ReceiverVariableBits::decode(Flags()) ==
931 VariableAllocationInfo::CONTEXT) {
932 return Smi::ToInt(get(ReceiverInfoIndex()));
933 }
934 return -1;
935 }
936
FunctionContextSlotIndex(String name) const937 int ScopeInfo::FunctionContextSlotIndex(String name) const {
938 DCHECK(name.IsInternalizedString());
939 if (length() > 0) {
940 if (FunctionVariableBits::decode(Flags()) ==
941 VariableAllocationInfo::CONTEXT &&
942 FunctionName() == name) {
943 return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
944 }
945 }
946 return -1;
947 }
948
function_kind() const949 FunctionKind ScopeInfo::function_kind() const {
950 return FunctionKindBits::decode(Flags());
951 }
952
ContextLocalNamesIndex() const953 int ScopeInfo::ContextLocalNamesIndex() const {
954 DCHECK_LT(0, length());
955 return kVariablePartIndex;
956 }
957
ContextLocalInfosIndex() const958 int ScopeInfo::ContextLocalInfosIndex() const {
959 return ContextLocalNamesIndex() + ContextLocalCount();
960 }
961
SavedClassVariableInfoIndex() const962 int ScopeInfo::SavedClassVariableInfoIndex() const {
963 return ContextLocalInfosIndex() + ContextLocalCount();
964 }
965
ReceiverInfoIndex() const966 int ScopeInfo::ReceiverInfoIndex() const {
967 return SavedClassVariableInfoIndex() + (HasSavedClassVariableIndex() ? 1 : 0);
968 }
969
FunctionNameInfoIndex() const970 int ScopeInfo::FunctionNameInfoIndex() const {
971 return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
972 }
973
InferredFunctionNameIndex() const974 int ScopeInfo::InferredFunctionNameIndex() const {
975 return FunctionNameInfoIndex() +
976 (HasFunctionName() ? kFunctionNameEntries : 0);
977 }
978
PositionInfoIndex() const979 int ScopeInfo::PositionInfoIndex() const {
980 return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
981 }
982
OuterScopeInfoIndex() const983 int ScopeInfo::OuterScopeInfoIndex() const {
984 return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
985 }
986
LocalsBlockListIndex() const987 int ScopeInfo::LocalsBlockListIndex() const {
988 return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
989 }
990
ModuleInfoIndex() const991 int ScopeInfo::ModuleInfoIndex() const {
992 return LocalsBlockListIndex() + (HasLocalsBlockList() ? 1 : 0);
993 }
994
ModuleVariableCountIndex() const995 int ScopeInfo::ModuleVariableCountIndex() const {
996 return ModuleInfoIndex() + 1;
997 }
998
ModuleVariablesIndex() const999 int ScopeInfo::ModuleVariablesIndex() const {
1000 return ModuleVariableCountIndex() + 1;
1001 }
1002
ModuleVariable(int i,String * name,int * index,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)1003 void ScopeInfo::ModuleVariable(int i, String* name, int* index,
1004 VariableMode* mode,
1005 InitializationFlag* init_flag,
1006 MaybeAssignedFlag* maybe_assigned_flag) {
1007 DCHECK_LE(0, i);
1008 DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
1009
1010 int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
1011 int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
1012
1013 if (name != nullptr) {
1014 *name = String::cast(get(entry + kModuleVariableNameOffset));
1015 }
1016 if (index != nullptr) {
1017 *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
1018 DCHECK_NE(*index, 0);
1019 }
1020 if (mode != nullptr) {
1021 *mode = VariableModeField::decode(properties);
1022 }
1023 if (init_flag != nullptr) {
1024 *init_flag = InitFlagField::decode(properties);
1025 }
1026 if (maybe_assigned_flag != nullptr) {
1027 *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
1028 }
1029 }
1030
operator <<(std::ostream & os,VariableAllocationInfo var_info)1031 std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var_info) {
1032 switch (var_info) {
1033 case VariableAllocationInfo::NONE:
1034 return os << "NONE";
1035 case VariableAllocationInfo::STACK:
1036 return os << "STACK";
1037 case VariableAllocationInfo::CONTEXT:
1038 return os << "CONTEXT";
1039 case VariableAllocationInfo::UNUSED:
1040 return os << "UNUSED";
1041 }
1042 UNREACHABLE();
1043 return os;
1044 }
1045
1046 template <typename LocalIsolate>
New(LocalIsolate * isolate,Handle<String> specifier,Handle<FixedArray> import_assertions)1047 Handle<ModuleRequest> ModuleRequest::New(LocalIsolate* isolate,
1048 Handle<String> specifier,
1049 Handle<FixedArray> import_assertions) {
1050 Handle<ModuleRequest> result = Handle<ModuleRequest>::cast(
1051 isolate->factory()->NewStruct(MODULE_REQUEST_TYPE, AllocationType::kOld));
1052 result->set_specifier(*specifier);
1053 result->set_import_assertions(*import_assertions);
1054 return result;
1055 }
1056
1057 template Handle<ModuleRequest> ModuleRequest::New(
1058 Isolate* isolate, Handle<String> specifier,
1059 Handle<FixedArray> import_assertions);
1060 template Handle<ModuleRequest> ModuleRequest::New(
1061 LocalIsolate* isolate, Handle<String> specifier,
1062 Handle<FixedArray> import_assertions);
1063
1064 template <typename LocalIsolate>
New(LocalIsolate * isolate,Handle<PrimitiveHeapObject> export_name,Handle<PrimitiveHeapObject> local_name,Handle<PrimitiveHeapObject> import_name,int module_request,int cell_index,int beg_pos,int end_pos)1065 Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1066 LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
1067 Handle<PrimitiveHeapObject> local_name,
1068 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1069 int beg_pos, int end_pos) {
1070 Handle<SourceTextModuleInfoEntry> result =
1071 Handle<SourceTextModuleInfoEntry>::cast(isolate->factory()->NewStruct(
1072 SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE, AllocationType::kOld));
1073 result->set_export_name(*export_name);
1074 result->set_local_name(*local_name);
1075 result->set_import_name(*import_name);
1076 result->set_module_request(module_request);
1077 result->set_cell_index(cell_index);
1078 result->set_beg_pos(beg_pos);
1079 result->set_end_pos(end_pos);
1080 return result;
1081 }
1082
1083 template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1084 Isolate* isolate, Handle<PrimitiveHeapObject> export_name,
1085 Handle<PrimitiveHeapObject> local_name,
1086 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1087 int beg_pos, int end_pos);
1088 template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1089 LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
1090 Handle<PrimitiveHeapObject> local_name,
1091 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1092 int beg_pos, int end_pos);
1093
1094 template <typename LocalIsolate>
New(LocalIsolate * isolate,Zone * zone,SourceTextModuleDescriptor * descr)1095 Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1096 LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr) {
1097 // Serialize module requests.
1098 int size = static_cast<int>(descr->module_requests().size());
1099 Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(size);
1100 Handle<FixedArray> module_request_positions =
1101 isolate->factory()->NewFixedArray(size);
1102 for (const auto& elem : descr->module_requests()) {
1103 Handle<ModuleRequest> serialized_module_request =
1104 elem.first->Serialize(isolate);
1105 module_requests->set(elem.second.index, *serialized_module_request);
1106 module_request_positions->set(elem.second.index,
1107 Smi::FromInt(elem.second.position));
1108 }
1109
1110 // Serialize special exports.
1111 Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
1112 static_cast<int>(descr->special_exports().size()));
1113 {
1114 int i = 0;
1115 for (auto entry : descr->special_exports()) {
1116 Handle<SourceTextModuleInfoEntry> serialized_entry =
1117 entry->Serialize(isolate);
1118 special_exports->set(i++, *serialized_entry);
1119 }
1120 }
1121
1122 // Serialize namespace imports.
1123 Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
1124 static_cast<int>(descr->namespace_imports().size()));
1125 {
1126 int i = 0;
1127 for (auto entry : descr->namespace_imports()) {
1128 Handle<SourceTextModuleInfoEntry> serialized_entry =
1129 entry->Serialize(isolate);
1130 namespace_imports->set(i++, *serialized_entry);
1131 }
1132 }
1133
1134 // Serialize regular exports.
1135 Handle<FixedArray> regular_exports =
1136 descr->SerializeRegularExports(isolate, zone);
1137
1138 // Serialize regular imports.
1139 Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
1140 static_cast<int>(descr->regular_imports().size()));
1141 {
1142 int i = 0;
1143 for (const auto& elem : descr->regular_imports()) {
1144 Handle<SourceTextModuleInfoEntry> serialized_entry =
1145 elem.second->Serialize(isolate);
1146 regular_imports->set(i++, *serialized_entry);
1147 }
1148 }
1149
1150 Handle<SourceTextModuleInfo> result =
1151 isolate->factory()->NewSourceTextModuleInfo();
1152 result->set(kModuleRequestsIndex, *module_requests);
1153 result->set(kSpecialExportsIndex, *special_exports);
1154 result->set(kRegularExportsIndex, *regular_exports);
1155 result->set(kNamespaceImportsIndex, *namespace_imports);
1156 result->set(kRegularImportsIndex, *regular_imports);
1157 result->set(kModuleRequestPositionsIndex, *module_request_positions);
1158 return result;
1159 }
1160 template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1161 Isolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1162 template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1163 LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1164
RegularExportCount() const1165 int SourceTextModuleInfo::RegularExportCount() const {
1166 DCHECK_EQ(regular_exports().length() % kRegularExportLength, 0);
1167 return regular_exports().length() / kRegularExportLength;
1168 }
1169
RegularExportLocalName(int i) const1170 String SourceTextModuleInfo::RegularExportLocalName(int i) const {
1171 return String::cast(regular_exports().get(i * kRegularExportLength +
1172 kRegularExportLocalNameOffset));
1173 }
1174
RegularExportCellIndex(int i) const1175 int SourceTextModuleInfo::RegularExportCellIndex(int i) const {
1176 return Smi::ToInt(regular_exports().get(i * kRegularExportLength +
1177 kRegularExportCellIndexOffset));
1178 }
1179
RegularExportExportNames(int i) const1180 FixedArray SourceTextModuleInfo::RegularExportExportNames(int i) const {
1181 return FixedArray::cast(regular_exports().get(
1182 i * kRegularExportLength + kRegularExportExportNamesOffset));
1183 }
1184
1185 } // namespace internal
1186 } // namespace v8
1187