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/scope-info-inl.h"
15 #include "src/objects/string-set-inl.h"
16 #include "src/roots/roots.h"
17
18 // Has to be the last include (doesn't have include guards):
19 #include "src/objects/object-macros.h"
20
21 namespace v8 {
22 namespace internal {
23
24 #ifdef DEBUG
Equals(ScopeInfo other) const25 bool ScopeInfo::Equals(ScopeInfo other) const {
26 if (length() != other.length()) return false;
27 for (int index = 0; index < length(); ++index) {
28 Object entry = get(index);
29 Object other_entry = other.get(index);
30 if (entry.IsSmi()) {
31 if (entry != other_entry) return false;
32 } else {
33 if (HeapObject::cast(entry).map().instance_type() !=
34 HeapObject::cast(other_entry).map().instance_type()) {
35 return false;
36 }
37 if (entry.IsString()) {
38 if (!String::cast(entry).Equals(String::cast(other_entry))) {
39 return false;
40 }
41 } else if (entry.IsScopeInfo()) {
42 if (!ScopeInfo::cast(entry).Equals(ScopeInfo::cast(other_entry))) {
43 return false;
44 }
45 } else if (entry.IsSourceTextModuleInfo()) {
46 if (!SourceTextModuleInfo::cast(entry).Equals(
47 SourceTextModuleInfo::cast(other_entry))) {
48 return false;
49 }
50 } else {
51 UNREACHABLE();
52 }
53 }
54 }
55 return true;
56 }
57 #endif
58
59 // static
60 template <typename IsolateT>
Create(IsolateT * isolate,Zone * zone,Scope * scope,MaybeHandle<ScopeInfo> outer_scope)61 Handle<ScopeInfo> ScopeInfo::Create(IsolateT* isolate, Zone* zone, Scope* scope,
62 MaybeHandle<ScopeInfo> outer_scope) {
63 // Collect variables.
64 int context_local_count = 0;
65 int module_vars_count = 0;
66 // Stack allocated block scope variables are allocated in the parent
67 // declaration scope, but are recorded in the block scope's scope info. First
68 // slot index indicates at which offset a particular scope starts in the
69 // parent declaration scope.
70 for (Variable* var : *scope->locals()) {
71 switch (var->location()) {
72 case VariableLocation::CONTEXT:
73 case VariableLocation::REPL_GLOBAL:
74 context_local_count++;
75 break;
76 case VariableLocation::MODULE:
77 module_vars_count++;
78 break;
79 default:
80 break;
81 }
82 }
83 // Determine use and location of the "this" binding if it is present.
84 VariableAllocationInfo receiver_info;
85 if (scope->is_declaration_scope() &&
86 scope->AsDeclarationScope()->has_this_declaration()) {
87 Variable* var = scope->AsDeclarationScope()->receiver();
88 if (!var->is_used()) {
89 receiver_info = VariableAllocationInfo::UNUSED;
90 } else if (var->IsContextSlot()) {
91 receiver_info = VariableAllocationInfo::CONTEXT;
92 } else {
93 DCHECK(var->IsParameter());
94 receiver_info = VariableAllocationInfo::STACK;
95 }
96 } else {
97 receiver_info = VariableAllocationInfo::NONE;
98 }
99
100 DCHECK(module_vars_count == 0 || scope->is_module_scope());
101
102 // Make sure we allocate the correct amount.
103 DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
104
105 // If the number of locals is small, we inline directly
106 // in the scope info object.
107 bool has_inlined_local_names =
108 context_local_count < kScopeInfoMaxInlinedLocalNamesSize;
109
110 const bool has_new_target =
111 scope->is_declaration_scope() &&
112 scope->AsDeclarationScope()->new_target_var() != nullptr;
113 // TODO(cbruni): Don't always waste a field for the inferred name.
114 const bool has_inferred_function_name = scope->is_function_scope();
115
116 // Determine use and location of the function variable if it is present.
117 VariableAllocationInfo function_name_info;
118 if (scope->is_function_scope()) {
119 if (scope->AsDeclarationScope()->function_var() != nullptr) {
120 Variable* var = scope->AsDeclarationScope()->function_var();
121 if (!var->is_used()) {
122 function_name_info = VariableAllocationInfo::UNUSED;
123 } else if (var->IsContextSlot()) {
124 function_name_info = VariableAllocationInfo::CONTEXT;
125 } else {
126 DCHECK(var->IsStackLocal());
127 function_name_info = VariableAllocationInfo::STACK;
128 }
129 } else {
130 // Always reserve space for the debug name in the scope info.
131 function_name_info = VariableAllocationInfo::UNUSED;
132 }
133 } else if (scope->is_module_scope() || scope->is_script_scope() ||
134 scope->is_eval_scope()) {
135 // Always reserve space for the debug name in the scope info.
136 function_name_info = VariableAllocationInfo::UNUSED;
137 } else {
138 function_name_info = VariableAllocationInfo::NONE;
139 }
140
141 const bool has_brand =
142 scope->is_class_scope()
143 ? scope->AsClassScope()->brand() != nullptr
144 : scope->IsConstructorScope() &&
145 scope->AsDeclarationScope()->class_scope_has_private_brand();
146 const bool should_save_class_variable_index =
147 scope->is_class_scope()
148 ? scope->AsClassScope()->should_save_class_variable_index()
149 : false;
150 const bool has_function_name =
151 function_name_info != VariableAllocationInfo::NONE;
152 const bool has_position_info = NeedsPositionInfo(scope->scope_type());
153 const int parameter_count =
154 scope->is_declaration_scope()
155 ? scope->AsDeclarationScope()->num_parameters()
156 : 0;
157 const bool has_outer_scope_info = !outer_scope.is_null();
158
159 Handle<SourceTextModuleInfo> module_info;
160 if (scope->is_module_scope()) {
161 module_info = SourceTextModuleInfo::New(isolate, zone,
162 scope->AsModuleScope()->module());
163 }
164
165 // Make sure the Fields enum agrees with Torque-generated offsets.
166 #define ASSERT_MATCHED_FIELD(name) \
167 STATIC_ASSERT(OffsetOfElementAt(k##name) == k##name##Offset);
168 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(ASSERT_MATCHED_FIELD)
169 #undef ASSERT_MATCHED_FIELD
170
171 const int local_names_container_size =
172 has_inlined_local_names ? context_local_count : 1;
173
174 const int length = kVariablePartIndex + local_names_container_size +
175 context_local_count +
176 (should_save_class_variable_index ? 1 : 0) +
177 (has_function_name ? kFunctionNameEntries : 0) +
178 (has_inferred_function_name ? 1 : 0) +
179 (has_position_info ? kPositionInfoEntries : 0) +
180 (has_outer_scope_info ? 1 : 0) +
181 (scope->is_module_scope()
182 ? 2 + kModuleVariableEntryLength * module_vars_count
183 : 0);
184
185 // Create hash table if local names are not inlined.
186 Handle<NameToIndexHashTable> local_names_hashtable;
187 if (!has_inlined_local_names) {
188 local_names_hashtable = NameToIndexHashTable::New(
189 isolate, context_local_count, AllocationType::kOld);
190 }
191
192 Handle<ScopeInfo> scope_info_handle =
193 isolate->factory()->NewScopeInfo(length);
194 int index = kVariablePartIndex;
195 {
196 DisallowGarbageCollection no_gc;
197 ScopeInfo scope_info = *scope_info_handle;
198 WriteBarrierMode mode = scope_info.GetWriteBarrierMode(no_gc);
199
200 bool has_simple_parameters = false;
201 bool is_asm_module = false;
202 bool sloppy_eval_can_extend_vars = false;
203 if (scope->is_function_scope()) {
204 DeclarationScope* function_scope = scope->AsDeclarationScope();
205 has_simple_parameters = function_scope->has_simple_parameters();
206 #if V8_ENABLE_WEBASSEMBLY
207 is_asm_module = function_scope->is_asm_module();
208 #endif // V8_ENABLE_WEBASSEMBLY
209 }
210 FunctionKind function_kind = FunctionKind::kNormalFunction;
211 if (scope->is_declaration_scope()) {
212 function_kind = scope->AsDeclarationScope()->function_kind();
213 sloppy_eval_can_extend_vars =
214 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars();
215 }
216
217 // Encode the flags.
218 int flags =
219 ScopeTypeBits::encode(scope->scope_type()) |
220 SloppyEvalCanExtendVarsBit::encode(sloppy_eval_can_extend_vars) |
221 LanguageModeBit::encode(scope->language_mode()) |
222 DeclarationScopeBit::encode(scope->is_declaration_scope()) |
223 ReceiverVariableBits::encode(receiver_info) |
224 ClassScopeHasPrivateBrandBit::encode(has_brand) |
225 HasSavedClassVariableBit::encode(should_save_class_variable_index) |
226 HasNewTargetBit::encode(has_new_target) |
227 FunctionVariableBits::encode(function_name_info) |
228 HasInferredFunctionNameBit::encode(has_inferred_function_name) |
229 IsAsmModuleBit::encode(is_asm_module) |
230 HasSimpleParametersBit::encode(has_simple_parameters) |
231 FunctionKindBits::encode(function_kind) |
232 HasOuterScopeInfoBit::encode(has_outer_scope_info) |
233 IsDebugEvaluateScopeBit::encode(scope->is_debug_evaluate_scope()) |
234 ForceContextAllocationBit::encode(
235 scope->ForceContextForLanguageMode()) |
236 PrivateNameLookupSkipsOuterClassBit::encode(
237 scope->private_name_lookup_skips_outer_class()) |
238 HasContextExtensionSlotBit::encode(scope->HasContextExtensionSlot()) |
239 IsReplModeScopeBit::encode(scope->is_repl_mode_scope()) |
240 HasLocalsBlockListBit::encode(false);
241 scope_info.set_flags(flags);
242
243 scope_info.set_parameter_count(parameter_count);
244 scope_info.set_context_local_count(context_local_count);
245
246 // Jump ahead to set the number of module variables so that we can use range
247 // DCHECKs in future steps.
248 if (scope->is_module_scope()) {
249 scope_info.set_module_variable_count(module_vars_count);
250 }
251 if (!has_inlined_local_names) {
252 scope_info.set_context_local_names_hashtable(*local_names_hashtable);
253 }
254
255 // Add context locals' names and info, module variables' names and info.
256 // Context locals are added using their index.
257 int context_local_base = index;
258 int context_local_info_base =
259 context_local_base + local_names_container_size;
260 int module_var_entry = scope_info.ModuleVariableCountIndex() + 1;
261
262 for (Variable* var : *scope->locals()) {
263 switch (var->location()) {
264 case VariableLocation::CONTEXT:
265 case VariableLocation::REPL_GLOBAL: {
266 // Due to duplicate parameters, context locals aren't guaranteed to
267 // come in order.
268 int local_index = var->index() - scope->ContextHeaderLength();
269 DCHECK_LE(0, local_index);
270 DCHECK_LT(local_index, context_local_count);
271 uint32_t info =
272 VariableModeBits::encode(var->mode()) |
273 InitFlagBit::encode(var->initialization_flag()) |
274 MaybeAssignedFlagBit::encode(var->maybe_assigned()) |
275 ParameterNumberBits::encode(ParameterNumberBits::kMax) |
276 IsStaticFlagBit::encode(var->is_static_flag());
277 if (has_inlined_local_names) {
278 scope_info.set(context_local_base + local_index, *var->name(),
279 mode);
280 } else {
281 Handle<NameToIndexHashTable> new_table = NameToIndexHashTable::Add(
282 isolate, local_names_hashtable, var->name(), local_index);
283 DCHECK_EQ(*new_table, *local_names_hashtable);
284 USE(new_table);
285 }
286 scope_info.set(context_local_info_base + local_index,
287 Smi::FromInt(info));
288 break;
289 }
290 case VariableLocation::MODULE: {
291 scope_info.set(module_var_entry +
292 TorqueGeneratedModuleVariableOffsets::kNameOffset /
293 kTaggedSize,
294 *var->name(), mode);
295 scope_info.set(
296 module_var_entry +
297 TorqueGeneratedModuleVariableOffsets::kIndexOffset /
298 kTaggedSize,
299 Smi::FromInt(var->index()));
300 uint32_t properties =
301 VariableModeBits::encode(var->mode()) |
302 InitFlagBit::encode(var->initialization_flag()) |
303 MaybeAssignedFlagBit::encode(var->maybe_assigned()) |
304 ParameterNumberBits::encode(ParameterNumberBits::kMax) |
305 IsStaticFlagBit::encode(var->is_static_flag());
306 scope_info.set(
307 module_var_entry +
308 TorqueGeneratedModuleVariableOffsets::kPropertiesOffset /
309 kTaggedSize,
310 Smi::FromInt(properties));
311 module_var_entry += kModuleVariableEntryLength;
312 break;
313 }
314 default:
315 break;
316 }
317 }
318
319 if (scope->is_declaration_scope()) {
320 // Mark contexts slots with the parameter number they represent. We walk
321 // the list of parameters. That can include duplicate entries if a
322 // parameter name is repeated. By walking upwards, we'll automatically
323 // mark the context slot with the highest parameter number that uses this
324 // variable. That will be the parameter number that is represented by the
325 // context slot. All lower parameters will only be available on the stack
326 // through the arguments object.
327 for (int i = 0; i < parameter_count; i++) {
328 Variable* parameter = scope->AsDeclarationScope()->parameter(i);
329 if (parameter->location() != VariableLocation::CONTEXT) continue;
330 int param_index = parameter->index() - scope->ContextHeaderLength();
331 int info_index = context_local_info_base + param_index;
332 int info = Smi::ToInt(scope_info.get(info_index));
333 info = ParameterNumberBits::update(info, i);
334 scope_info.set(info_index, Smi::FromInt(info));
335 }
336 }
337
338 // Advance past local names and local names info.
339 index += local_names_container_size + context_local_count;
340
341 DCHECK_EQ(index, scope_info.SavedClassVariableInfoIndex());
342 // If the scope is a class scope and has used static private methods, save
343 // the context slot index of the class variable.
344 // Store the class variable index.
345 if (should_save_class_variable_index) {
346 Variable* class_variable = scope->AsClassScope()->class_variable();
347 DCHECK_EQ(class_variable->location(), VariableLocation::CONTEXT);
348 int local_index;
349 if (has_inlined_local_names) {
350 local_index = class_variable->index();
351 } else {
352 Handle<Name> name = class_variable->name();
353 InternalIndex entry = local_names_hashtable->FindEntry(isolate, name);
354 local_index = entry.as_int();
355 }
356 scope_info.set(index++, Smi::FromInt(local_index));
357 }
358
359 // If present, add the function variable name and its index.
360 DCHECK_EQ(index, scope_info.FunctionVariableInfoIndex());
361 if (has_function_name) {
362 Variable* var = scope->AsDeclarationScope()->function_var();
363 int var_index = -1;
364 Object name = Smi::zero();
365 if (var != nullptr) {
366 var_index = var->index();
367 name = *var->name();
368 }
369 scope_info.set(index++, name, mode);
370 scope_info.set(index++, Smi::FromInt(var_index));
371 DCHECK(function_name_info != VariableAllocationInfo::CONTEXT ||
372 var_index == scope_info.ContextLength() - 1);
373 }
374
375 DCHECK_EQ(index, scope_info.InferredFunctionNameIndex());
376 if (has_inferred_function_name) {
377 // The inferred function name is taken from the SFI.
378 index++;
379 }
380
381 DCHECK_EQ(index, scope_info.PositionInfoIndex());
382 if (has_position_info) {
383 scope_info.set(index++, Smi::FromInt(scope->start_position()));
384 scope_info.set(index++, Smi::FromInt(scope->end_position()));
385 }
386
387 // If present, add the outer scope info.
388 DCHECK(index == scope_info.OuterScopeInfoIndex());
389 if (has_outer_scope_info) {
390 scope_info.set(index++, *outer_scope.ToHandleChecked(), mode);
391 }
392
393 // Module-specific information (only for module scopes).
394 if (scope->is_module_scope()) {
395 DCHECK_EQ(index, scope_info.ModuleInfoIndex());
396 scope_info.set(index++, *module_info);
397 DCHECK_EQ(index, scope_info.ModuleVariableCountIndex());
398 // Module variable count was already written above.
399 index++;
400 DCHECK_EQ(index, scope_info.ModuleVariablesIndex());
401 // The variable entries themselves have already been written above.
402 index += kModuleVariableEntryLength * module_vars_count;
403 }
404 }
405
406 DCHECK_EQ(index, scope_info_handle->length());
407 DCHECK_EQ(parameter_count, scope_info_handle->ParameterCount());
408 DCHECK_EQ(scope->num_heap_slots(), scope_info_handle->ContextLength());
409
410 return scope_info_handle;
411 }
412
413 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
414 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
415 Scope* scope,
416 MaybeHandle<ScopeInfo> outer_scope);
417 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
418 Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
419 Scope* scope,
420 MaybeHandle<ScopeInfo> outer_scope);
421
422 // static
CreateForWithScope(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)423 Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
424 Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
425 const bool has_outer_scope_info = !outer_scope.is_null();
426 const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
427
428 Factory* factory = isolate->factory();
429 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
430
431 // Encode the flags.
432 int flags =
433 ScopeTypeBits::encode(WITH_SCOPE) |
434 SloppyEvalCanExtendVarsBit::encode(false) |
435 LanguageModeBit::encode(LanguageMode::kSloppy) |
436 DeclarationScopeBit::encode(false) |
437 ReceiverVariableBits::encode(VariableAllocationInfo::NONE) |
438 ClassScopeHasPrivateBrandBit::encode(false) |
439 HasSavedClassVariableBit::encode(false) | HasNewTargetBit::encode(false) |
440 FunctionVariableBits::encode(VariableAllocationInfo::NONE) |
441 IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
442 FunctionKindBits::encode(FunctionKind::kNormalFunction) |
443 HasOuterScopeInfoBit::encode(has_outer_scope_info) |
444 IsDebugEvaluateScopeBit::encode(false) |
445 ForceContextAllocationBit::encode(false) |
446 PrivateNameLookupSkipsOuterClassBit::encode(false) |
447 HasContextExtensionSlotBit::encode(true) |
448 IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
449 scope_info->set_flags(flags);
450
451 scope_info->set_parameter_count(0);
452 scope_info->set_context_local_count(0);
453
454 int index = kVariablePartIndex;
455 DCHECK_EQ(index, scope_info->FunctionVariableInfoIndex());
456 DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
457 DCHECK_EQ(index, scope_info->PositionInfoIndex());
458 DCHECK(index == scope_info->OuterScopeInfoIndex());
459 if (has_outer_scope_info) {
460 scope_info->set(index++, *outer_scope.ToHandleChecked());
461 }
462 DCHECK_EQ(index, scope_info->length());
463 DCHECK_EQ(0, scope_info->ParameterCount());
464 DCHECK_EQ(scope_info->ContextHeaderLength(), scope_info->ContextLength());
465 return scope_info;
466 }
467
468 // static
CreateGlobalThisBinding(Isolate * isolate)469 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
470 return CreateForBootstrapping(isolate, BootstrappingType::kScript);
471 }
472
473 // static
CreateForEmptyFunction(Isolate * isolate)474 Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
475 return CreateForBootstrapping(isolate, BootstrappingType::kFunction);
476 }
477
478 // static
CreateForNativeContext(Isolate * isolate)479 Handle<ScopeInfo> ScopeInfo::CreateForNativeContext(Isolate* isolate) {
480 return CreateForBootstrapping(isolate, BootstrappingType::kNative);
481 }
482
483 // static
CreateForBootstrapping(Isolate * isolate,BootstrappingType type)484 Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
485 BootstrappingType type) {
486 const int parameter_count = 0;
487 const bool is_empty_function = type == BootstrappingType::kFunction;
488 const bool is_native_context = type == BootstrappingType::kNative;
489 const bool is_script = type == BootstrappingType::kScript;
490 const int context_local_count =
491 is_empty_function || is_native_context ? 0 : 1;
492 const bool has_inferred_function_name = is_empty_function;
493 const bool has_position_info = true;
494 // NOTE: Local names are always inlined here, since context_local_count < 2.
495 DCHECK_LT(context_local_count, kScopeInfoMaxInlinedLocalNamesSize);
496 const int length = kVariablePartIndex + 2 * context_local_count +
497 (is_empty_function ? kFunctionNameEntries : 0) +
498 (has_inferred_function_name ? 1 : 0) +
499 (has_position_info ? kPositionInfoEntries : 0);
500
501 Factory* factory = isolate->factory();
502 Handle<ScopeInfo> scope_info =
503 factory->NewScopeInfo(length, AllocationType::kReadOnly);
504
505 // Encode the flags.
506 int flags =
507 ScopeTypeBits::encode(is_empty_function ? FUNCTION_SCOPE : SCRIPT_SCOPE) |
508 SloppyEvalCanExtendVarsBit::encode(false) |
509 LanguageModeBit::encode(LanguageMode::kSloppy) |
510 DeclarationScopeBit::encode(true) |
511 ReceiverVariableBits::encode(is_script ? VariableAllocationInfo::CONTEXT
512 : VariableAllocationInfo::UNUSED) |
513 ClassScopeHasPrivateBrandBit::encode(false) |
514 HasSavedClassVariableBit::encode(false) | HasNewTargetBit::encode(false) |
515 FunctionVariableBits::encode(is_empty_function
516 ? VariableAllocationInfo::UNUSED
517 : VariableAllocationInfo::NONE) |
518 HasInferredFunctionNameBit::encode(has_inferred_function_name) |
519 IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
520 FunctionKindBits::encode(FunctionKind::kNormalFunction) |
521 HasOuterScopeInfoBit::encode(false) |
522 IsDebugEvaluateScopeBit::encode(false) |
523 ForceContextAllocationBit::encode(false) |
524 PrivateNameLookupSkipsOuterClassBit::encode(false) |
525 HasContextExtensionSlotBit::encode(is_native_context) |
526 IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
527 scope_info->set_flags(flags);
528 scope_info->set_parameter_count(parameter_count);
529 scope_info->set_context_local_count(context_local_count);
530
531 int index = kVariablePartIndex;
532
533 // Here we add info for context-allocated "this".
534 DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
535 if (context_local_count) {
536 scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
537 }
538 DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
539 if (context_local_count > 0) {
540 const uint32_t value =
541 VariableModeBits::encode(VariableMode::kConst) |
542 InitFlagBit::encode(kCreatedInitialized) |
543 MaybeAssignedFlagBit::encode(kNotAssigned) |
544 ParameterNumberBits::encode(ParameterNumberBits::kMax) |
545 IsStaticFlagBit::encode(IsStaticFlag::kNotStatic);
546 scope_info->set(index++, Smi::FromInt(value));
547 }
548
549 DCHECK_EQ(index, scope_info->FunctionVariableInfoIndex());
550 if (is_empty_function) {
551 scope_info->set(index++, *isolate->factory()->empty_string());
552 scope_info->set(index++, Smi::zero());
553 }
554 DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
555 if (has_inferred_function_name) {
556 scope_info->set(index++, *isolate->factory()->empty_string());
557 }
558 DCHECK_EQ(index, scope_info->PositionInfoIndex());
559 // Store dummy position to be in sync with the {scope_type}.
560 scope_info->set(index++, Smi::zero());
561 scope_info->set(index++, Smi::zero());
562 DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
563 DCHECK_EQ(index, scope_info->length());
564 DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
565 if (is_empty_function || is_native_context) {
566 DCHECK_EQ(scope_info->ContextLength(), 0);
567 } else {
568 DCHECK_EQ(scope_info->ContextLength(),
569 scope_info->ContextHeaderLength() + 1);
570 }
571
572 return scope_info;
573 }
574
get(int index) const575 Object ScopeInfo::get(int index) const {
576 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
577 return get(cage_base, index);
578 }
579
get(PtrComprCageBase cage_base,int index) const580 Object ScopeInfo::get(PtrComprCageBase cage_base, int index) const {
581 DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
582 return TaggedField<Object>::Relaxed_Load(cage_base, *this,
583 OffsetOfElementAt(index));
584 }
585
set(int index,Smi value)586 void ScopeInfo::set(int index, Smi value) {
587 DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
588 DCHECK(Object(value).IsSmi());
589 int offset = OffsetOfElementAt(index);
590 RELAXED_WRITE_FIELD(*this, offset, value);
591 }
592
set(int index,Object value,WriteBarrierMode mode)593 void ScopeInfo::set(int index, Object value, WriteBarrierMode mode) {
594 DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
595 int offset = OffsetOfElementAt(index);
596 RELAXED_WRITE_FIELD(*this, offset, value);
597 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
598 }
599
CopyElements(Isolate * isolate,int dst_index,ScopeInfo src,int src_index,int len,WriteBarrierMode mode)600 void ScopeInfo::CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
601 int src_index, int len, WriteBarrierMode mode) {
602 if (len == 0) return;
603 DCHECK_LE(src_index + len, src.length());
604 DisallowGarbageCollection no_gc;
605
606 ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
607 ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
608 isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
609 }
610
RawFieldOfElementAt(int index)611 ObjectSlot ScopeInfo::RawFieldOfElementAt(int index) {
612 return RawField(OffsetOfElementAt(index));
613 }
614
length() const615 int ScopeInfo::length() const {
616 // AllocatedSize() is generated by Torque and represents the size in bytes of
617 // the object, as computed from flags, context_local_count, and possibly
618 // module_variable_count. Convert that size into a number of slots.
619 return (AllocatedSize() - HeapObject::kHeaderSize) / kTaggedSize;
620 }
621
622 // static
RecreateWithBlockList(Isolate * isolate,Handle<ScopeInfo> original,Handle<StringSet> blocklist)623 Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
624 Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blocklist) {
625 DCHECK(!original.is_null());
626 if (original->HasLocalsBlockList()) return original;
627
628 int length = original->length() + 1;
629 Handle<ScopeInfo> scope_info = isolate->factory()->NewScopeInfo(length);
630
631 // Copy the static part first and update the flags to include the
632 // blocklist field, so {LocalsBlockListIndex} returns the correct value.
633 scope_info->CopyElements(isolate, 0, *original, 0, kVariablePartIndex,
634 WriteBarrierMode::UPDATE_WRITE_BARRIER);
635 scope_info->set_flags(
636 HasLocalsBlockListBit::update(scope_info->Flags(), true));
637
638 // Copy the dynamic part including the provided blocklist:
639 // 1) copy all the fields up to the blocklist index
640 // 2) add the blocklist
641 // 3) copy the remaining fields
642 scope_info->CopyElements(
643 isolate, kVariablePartIndex, *original, kVariablePartIndex,
644 scope_info->LocalsBlockListIndex() - kVariablePartIndex,
645 WriteBarrierMode::UPDATE_WRITE_BARRIER);
646 scope_info->set_locals_block_list(*blocklist);
647 scope_info->CopyElements(isolate, scope_info->LocalsBlockListIndex() + 1,
648 *original, scope_info->LocalsBlockListIndex(),
649 length - scope_info->LocalsBlockListIndex() - 1,
650 WriteBarrierMode::UPDATE_WRITE_BARRIER);
651 return scope_info;
652 }
653
Empty(Isolate * isolate)654 ScopeInfo ScopeInfo::Empty(Isolate* isolate) {
655 return ReadOnlyRoots(isolate).empty_scope_info();
656 }
657
IsEmpty() const658 bool ScopeInfo::IsEmpty() const { return IsEmptyBit::decode(Flags()); }
659
scope_type() const660 ScopeType ScopeInfo::scope_type() const {
661 DCHECK(!IsEmpty());
662 return ScopeTypeBits::decode(Flags());
663 }
664
is_script_scope() const665 bool ScopeInfo::is_script_scope() const {
666 return !IsEmpty() && scope_type() == SCRIPT_SCOPE;
667 }
668
SloppyEvalCanExtendVars() const669 bool ScopeInfo::SloppyEvalCanExtendVars() const {
670 bool sloppy_eval_can_extend_vars =
671 SloppyEvalCanExtendVarsBit::decode(Flags());
672 DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_sloppy(language_mode()));
673 DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_declaration_scope());
674 return sloppy_eval_can_extend_vars;
675 }
676
language_mode() const677 LanguageMode ScopeInfo::language_mode() const {
678 return LanguageModeBit::decode(Flags());
679 }
680
is_declaration_scope() const681 bool ScopeInfo::is_declaration_scope() const {
682 return DeclarationScopeBit::decode(Flags());
683 }
684
ContextLength() const685 int ScopeInfo::ContextLength() const {
686 if (IsEmpty()) return 0;
687 int context_locals = ContextLocalCount();
688 bool function_name_context_slot = HasContextAllocatedFunctionName();
689 bool force_context = ForceContextAllocationBit::decode(Flags());
690 bool has_context =
691 context_locals > 0 || force_context || function_name_context_slot ||
692 scope_type() == WITH_SCOPE || scope_type() == CLASS_SCOPE ||
693 (scope_type() == BLOCK_SCOPE && SloppyEvalCanExtendVars() &&
694 is_declaration_scope()) ||
695 (scope_type() == FUNCTION_SCOPE && SloppyEvalCanExtendVars()) ||
696 (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
697 scope_type() == MODULE_SCOPE;
698
699 if (!has_context) return 0;
700 return ContextHeaderLength() + context_locals +
701 (function_name_context_slot ? 1 : 0);
702 }
703
HasContextExtensionSlot() const704 bool ScopeInfo::HasContextExtensionSlot() const {
705 return HasContextExtensionSlotBit::decode(Flags());
706 }
707
ContextHeaderLength() const708 int ScopeInfo::ContextHeaderLength() const {
709 return HasContextExtensionSlot() ? Context::MIN_CONTEXT_EXTENDED_SLOTS
710 : Context::MIN_CONTEXT_SLOTS;
711 }
712
HasReceiver() const713 bool ScopeInfo::HasReceiver() const {
714 return VariableAllocationInfo::NONE != ReceiverVariableBits::decode(Flags());
715 }
716
HasAllocatedReceiver() const717 bool ScopeInfo::HasAllocatedReceiver() const {
718 VariableAllocationInfo allocation = ReceiverVariableBits::decode(Flags());
719 return allocation == VariableAllocationInfo::STACK ||
720 allocation == VariableAllocationInfo::CONTEXT;
721 }
722
ClassScopeHasPrivateBrand() const723 bool ScopeInfo::ClassScopeHasPrivateBrand() const {
724 return ClassScopeHasPrivateBrandBit::decode(Flags());
725 }
726
HasSavedClassVariable() const727 bool ScopeInfo::HasSavedClassVariable() const {
728 return HasSavedClassVariableBit::decode(Flags());
729 }
730
HasNewTarget() const731 bool ScopeInfo::HasNewTarget() const {
732 return HasNewTargetBit::decode(Flags());
733 }
734
HasFunctionName() const735 bool ScopeInfo::HasFunctionName() const {
736 return VariableAllocationInfo::NONE != FunctionVariableBits::decode(Flags());
737 }
738
HasContextAllocatedFunctionName() const739 bool ScopeInfo::HasContextAllocatedFunctionName() const {
740 return VariableAllocationInfo::CONTEXT ==
741 FunctionVariableBits::decode(Flags());
742 }
743
HasInferredFunctionName() const744 bool ScopeInfo::HasInferredFunctionName() const {
745 return HasInferredFunctionNameBit::decode(Flags());
746 }
747
HasPositionInfo() const748 bool ScopeInfo::HasPositionInfo() const {
749 if (IsEmpty()) return false;
750 return NeedsPositionInfo(scope_type());
751 }
752
753 // static
NeedsPositionInfo(ScopeType type)754 bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
755 return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
756 type == MODULE_SCOPE || type == CLASS_SCOPE;
757 }
758
HasSharedFunctionName() const759 bool ScopeInfo::HasSharedFunctionName() const {
760 return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
761 }
762
SetFunctionName(Object name)763 void ScopeInfo::SetFunctionName(Object name) {
764 DCHECK(HasFunctionName());
765 DCHECK(name.IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
766 DCHECK_IMPLIES(HasContextAllocatedFunctionName(),
767 name.IsInternalizedString());
768 set_function_variable_info_name(name);
769 }
770
SetInferredFunctionName(String name)771 void ScopeInfo::SetInferredFunctionName(String name) {
772 DCHECK(HasInferredFunctionName());
773 set_inferred_function_name(name);
774 }
775
HasOuterScopeInfo() const776 bool ScopeInfo::HasOuterScopeInfo() const {
777 return HasOuterScopeInfoBit::decode(Flags());
778 }
779
IsDebugEvaluateScope() const780 bool ScopeInfo::IsDebugEvaluateScope() const {
781 return IsDebugEvaluateScopeBit::decode(Flags());
782 }
783
SetIsDebugEvaluateScope()784 void ScopeInfo::SetIsDebugEvaluateScope() {
785 CHECK(!IsEmpty());
786 DCHECK_EQ(scope_type(), WITH_SCOPE);
787 set_flags(Flags() | IsDebugEvaluateScopeBit::encode(true));
788 }
789
PrivateNameLookupSkipsOuterClass() const790 bool ScopeInfo::PrivateNameLookupSkipsOuterClass() const {
791 return PrivateNameLookupSkipsOuterClassBit::decode(Flags());
792 }
793
IsReplModeScope() const794 bool ScopeInfo::IsReplModeScope() const {
795 return IsReplModeScopeBit::decode(Flags());
796 }
797
HasLocalsBlockList() const798 bool ScopeInfo::HasLocalsBlockList() const {
799 return HasLocalsBlockListBit::decode(Flags());
800 }
801
LocalsBlockList() const802 StringSet ScopeInfo::LocalsBlockList() const {
803 DCHECK(HasLocalsBlockList());
804 return StringSet::cast(locals_block_list());
805 }
806
HasContext() const807 bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
808
FunctionName() const809 Object ScopeInfo::FunctionName() const {
810 DCHECK(HasFunctionName());
811 return function_variable_info_name();
812 }
813
InferredFunctionName() const814 Object ScopeInfo::InferredFunctionName() const {
815 DCHECK(HasInferredFunctionName());
816 return inferred_function_name();
817 }
818
FunctionDebugName() const819 String ScopeInfo::FunctionDebugName() const {
820 if (!HasFunctionName()) return GetReadOnlyRoots().empty_string();
821 Object name = FunctionName();
822 if (name.IsString() && String::cast(name).length() > 0) {
823 return String::cast(name);
824 }
825 if (HasInferredFunctionName()) {
826 name = InferredFunctionName();
827 if (name.IsString()) return String::cast(name);
828 }
829 return GetReadOnlyRoots().empty_string();
830 }
831
StartPosition() const832 int ScopeInfo::StartPosition() const {
833 DCHECK(HasPositionInfo());
834 return position_info_start();
835 }
836
EndPosition() const837 int ScopeInfo::EndPosition() const {
838 DCHECK(HasPositionInfo());
839 return position_info_end();
840 }
841
SetPositionInfo(int start,int end)842 void ScopeInfo::SetPositionInfo(int start, int end) {
843 DCHECK(HasPositionInfo());
844 DCHECK_LE(start, end);
845 set_position_info_start(start);
846 set_position_info_end(end);
847 }
848
OuterScopeInfo() const849 ScopeInfo ScopeInfo::OuterScopeInfo() const {
850 DCHECK(HasOuterScopeInfo());
851 return ScopeInfo::cast(outer_scope_info());
852 }
853
ModuleDescriptorInfo() const854 SourceTextModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
855 DCHECK(scope_type() == MODULE_SCOPE);
856 return SourceTextModuleInfo::cast(module_info());
857 }
858
ContextInlinedLocalName(int var) const859 String ScopeInfo::ContextInlinedLocalName(int var) const {
860 DCHECK(HasInlinedLocalNames());
861 return context_local_names(var);
862 }
863
ContextInlinedLocalName(PtrComprCageBase cage_base,int var) const864 String ScopeInfo::ContextInlinedLocalName(PtrComprCageBase cage_base,
865 int var) const {
866 DCHECK(HasInlinedLocalNames());
867 return context_local_names(cage_base, var);
868 }
869
ContextLocalMode(int var) const870 VariableMode ScopeInfo::ContextLocalMode(int var) const {
871 int value = context_local_infos(var);
872 return VariableModeBits::decode(value);
873 }
874
ContextLocalIsStaticFlag(int var) const875 IsStaticFlag ScopeInfo::ContextLocalIsStaticFlag(int var) const {
876 int value = context_local_infos(var);
877 return IsStaticFlagBit::decode(value);
878 }
879
ContextLocalInitFlag(int var) const880 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
881 int value = context_local_infos(var);
882 return InitFlagBit::decode(value);
883 }
884
ContextLocalIsParameter(int var) const885 bool ScopeInfo::ContextLocalIsParameter(int var) const {
886 int value = context_local_infos(var);
887 return ParameterNumberBits::decode(value) != ParameterNumberBits::kMax;
888 }
889
ContextLocalParameterNumber(int var) const890 uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
891 DCHECK(ContextLocalIsParameter(var));
892 int value = context_local_infos(var);
893 return ParameterNumberBits::decode(value);
894 }
895
ContextLocalMaybeAssignedFlag(int var) const896 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
897 int value = context_local_infos(var);
898 return MaybeAssignedFlagBit::decode(value);
899 }
900
901 // static
VariableIsSynthetic(String name)902 bool ScopeInfo::VariableIsSynthetic(String name) {
903 // There's currently no flag stored on the ScopeInfo to indicate that a
904 // variable is a compiler-introduced temporary. However, to avoid conflict
905 // with user declarations, the current temporaries like .generator_object and
906 // .result start with a dot, so we can use that as a flag. It's a hack!
907 return name.length() == 0 || name.Get(0) == '.' || name.Get(0) == '#' ||
908 name.Equals(name.GetReadOnlyRoots().this_string());
909 }
910
ModuleVariableCount() const911 int ScopeInfo::ModuleVariableCount() const {
912 DCHECK_EQ(scope_type(), MODULE_SCOPE);
913 return module_variable_count();
914 }
915
ModuleIndex(String name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)916 int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
917 InitializationFlag* init_flag,
918 MaybeAssignedFlag* maybe_assigned_flag) {
919 DisallowGarbageCollection no_gc;
920 DCHECK(name.IsInternalizedString());
921 DCHECK_EQ(scope_type(), MODULE_SCOPE);
922 DCHECK_NOT_NULL(mode);
923 DCHECK_NOT_NULL(init_flag);
924 DCHECK_NOT_NULL(maybe_assigned_flag);
925
926 int module_vars_count = module_variable_count();
927 for (int i = 0; i < module_vars_count; ++i) {
928 String var_name = module_variables_name(i);
929 if (name.Equals(var_name)) {
930 int index;
931 ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
932 return index;
933 }
934 }
935
936 return 0;
937 }
938
InlinedLocalNamesLookup(String name)939 int ScopeInfo::InlinedLocalNamesLookup(String name) {
940 DisallowGarbageCollection no_gc;
941 PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
942 int local_count = context_local_count();
943 for (int i = 0; i < local_count; ++i) {
944 if (name == ContextInlinedLocalName(cage_base, i)) {
945 return i;
946 }
947 }
948 return -1;
949 }
950
ContextSlotIndex(Handle<String> name,VariableLookupResult * lookup_result)951 int ScopeInfo::ContextSlotIndex(Handle<String> name,
952 VariableLookupResult* lookup_result) {
953 DisallowGarbageCollection no_gc;
954 DCHECK(name->IsInternalizedString());
955 DCHECK_NOT_NULL(lookup_result);
956
957 if (IsEmpty()) return -1;
958
959 int index = HasInlinedLocalNames()
960 ? InlinedLocalNamesLookup(*name)
961 : context_local_names_hashtable().Lookup(name);
962
963 if (index != -1) {
964 lookup_result->mode = ContextLocalMode(index);
965 lookup_result->is_static_flag = ContextLocalIsStaticFlag(index);
966 lookup_result->init_flag = ContextLocalInitFlag(index);
967 lookup_result->maybe_assigned_flag = ContextLocalMaybeAssignedFlag(index);
968 lookup_result->is_repl_mode = IsReplModeScope();
969 int context_slot = ContextHeaderLength() + index;
970 DCHECK_LT(context_slot, ContextLength());
971 return context_slot;
972 }
973
974 return -1;
975 }
976
ContextSlotIndex(Handle<String> name)977 int ScopeInfo::ContextSlotIndex(Handle<String> name) {
978 VariableLookupResult lookup_result;
979 return ContextSlotIndex(name, &lookup_result);
980 }
981
SavedClassVariable() const982 std::pair<String, int> ScopeInfo::SavedClassVariable() const {
983 DCHECK(HasSavedClassVariableBit::decode(Flags()));
984 if (HasInlinedLocalNames()) {
985 // The saved class variable info corresponds to the context slot index.
986 int index = saved_class_variable_info() - Context::MIN_CONTEXT_SLOTS;
987 DCHECK_GE(index, 0);
988 DCHECK_LT(index, ContextLocalCount());
989 String name = ContextInlinedLocalName(index);
990 return std::make_pair(name, index);
991 } else {
992 // The saved class variable info corresponds to the offset in the hash
993 // table storage.
994 InternalIndex entry(saved_class_variable_info());
995 NameToIndexHashTable table = context_local_names_hashtable();
996 Object name = table.KeyAt(entry);
997 DCHECK(name.IsString());
998 return std::make_pair(String::cast(name), table.IndexAt(entry));
999 }
1000 }
1001
ReceiverContextSlotIndex() const1002 int ScopeInfo::ReceiverContextSlotIndex() const {
1003 if (ReceiverVariableBits::decode(Flags()) ==
1004 VariableAllocationInfo::CONTEXT) {
1005 return ContextHeaderLength();
1006 }
1007 return -1;
1008 }
1009
ParametersStartIndex() const1010 int ScopeInfo::ParametersStartIndex() const {
1011 if (ReceiverVariableBits::decode(Flags()) ==
1012 VariableAllocationInfo::CONTEXT) {
1013 return ContextHeaderLength() + 1;
1014 }
1015 return ContextHeaderLength();
1016 }
1017
FunctionContextSlotIndex(String name) const1018 int ScopeInfo::FunctionContextSlotIndex(String name) const {
1019 DCHECK(name.IsInternalizedString());
1020 if (HasContextAllocatedFunctionName()) {
1021 DCHECK_IMPLIES(HasFunctionName(), FunctionName().IsInternalizedString());
1022 if (FunctionName() == name) {
1023 return function_variable_info_context_or_stack_slot_index();
1024 }
1025 }
1026 return -1;
1027 }
1028
function_kind() const1029 FunctionKind ScopeInfo::function_kind() const {
1030 return FunctionKindBits::decode(Flags());
1031 }
1032
ContextLocalNamesIndex() const1033 int ScopeInfo::ContextLocalNamesIndex() const {
1034 return ConvertOffsetToIndex(kContextLocalNamesOffset);
1035 }
1036
ContextLocalInfosIndex() const1037 int ScopeInfo::ContextLocalInfosIndex() const {
1038 return ConvertOffsetToIndex(ContextLocalInfosOffset());
1039 }
1040
SavedClassVariableInfoIndex() const1041 int ScopeInfo::SavedClassVariableInfoIndex() const {
1042 return ConvertOffsetToIndex(SavedClassVariableInfoOffset());
1043 }
1044
FunctionVariableInfoIndex() const1045 int ScopeInfo::FunctionVariableInfoIndex() const {
1046 return ConvertOffsetToIndex(FunctionVariableInfoOffset());
1047 }
1048
InferredFunctionNameIndex() const1049 int ScopeInfo::InferredFunctionNameIndex() const {
1050 return ConvertOffsetToIndex(InferredFunctionNameOffset());
1051 }
1052
PositionInfoIndex() const1053 int ScopeInfo::PositionInfoIndex() const {
1054 return ConvertOffsetToIndex(PositionInfoOffset());
1055 }
1056
OuterScopeInfoIndex() const1057 int ScopeInfo::OuterScopeInfoIndex() const {
1058 return ConvertOffsetToIndex(OuterScopeInfoOffset());
1059 }
1060
LocalsBlockListIndex() const1061 int ScopeInfo::LocalsBlockListIndex() const {
1062 return ConvertOffsetToIndex(LocalsBlockListOffset());
1063 }
1064
ModuleInfoIndex() const1065 int ScopeInfo::ModuleInfoIndex() const {
1066 return ConvertOffsetToIndex(ModuleInfoOffset());
1067 }
1068
ModuleVariableCountIndex() const1069 int ScopeInfo::ModuleVariableCountIndex() const {
1070 return ConvertOffsetToIndex(ModuleVariableCountOffset());
1071 }
1072
ModuleVariablesIndex() const1073 int ScopeInfo::ModuleVariablesIndex() const {
1074 return ConvertOffsetToIndex(ModuleVariablesOffset());
1075 }
1076
ModuleVariable(int i,String * name,int * index,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)1077 void ScopeInfo::ModuleVariable(int i, String* name, int* index,
1078 VariableMode* mode,
1079 InitializationFlag* init_flag,
1080 MaybeAssignedFlag* maybe_assigned_flag) {
1081 int properties = module_variables_properties(i);
1082
1083 if (name != nullptr) {
1084 *name = module_variables_name(i);
1085 }
1086 if (index != nullptr) {
1087 *index = module_variables_index(i);
1088 DCHECK_NE(*index, 0);
1089 }
1090 if (mode != nullptr) {
1091 *mode = VariableModeBits::decode(properties);
1092 }
1093 if (init_flag != nullptr) {
1094 *init_flag = InitFlagBit::decode(properties);
1095 }
1096 if (maybe_assigned_flag != nullptr) {
1097 *maybe_assigned_flag = MaybeAssignedFlagBit::decode(properties);
1098 }
1099 }
1100
operator <<(std::ostream & os,VariableAllocationInfo var_info)1101 std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var_info) {
1102 switch (var_info) {
1103 case VariableAllocationInfo::NONE:
1104 return os << "NONE";
1105 case VariableAllocationInfo::STACK:
1106 return os << "STACK";
1107 case VariableAllocationInfo::CONTEXT:
1108 return os << "CONTEXT";
1109 case VariableAllocationInfo::UNUSED:
1110 return os << "UNUSED";
1111 }
1112 UNREACHABLE();
1113 }
1114
1115 template <typename IsolateT>
New(IsolateT * isolate,Handle<String> specifier,Handle<FixedArray> import_assertions,int position)1116 Handle<ModuleRequest> ModuleRequest::New(IsolateT* isolate,
1117 Handle<String> specifier,
1118 Handle<FixedArray> import_assertions,
1119 int position) {
1120 Handle<ModuleRequest> result = Handle<ModuleRequest>::cast(
1121 isolate->factory()->NewStruct(MODULE_REQUEST_TYPE, AllocationType::kOld));
1122 result->set_specifier(*specifier);
1123 result->set_import_assertions(*import_assertions);
1124 result->set_position(position);
1125 return result;
1126 }
1127
1128 template Handle<ModuleRequest> ModuleRequest::New(
1129 Isolate* isolate, Handle<String> specifier,
1130 Handle<FixedArray> import_assertions, int position);
1131 template Handle<ModuleRequest> ModuleRequest::New(
1132 LocalIsolate* isolate, Handle<String> specifier,
1133 Handle<FixedArray> import_assertions, int position);
1134
1135 template <typename IsolateT>
New(IsolateT * 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)1136 Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1137 IsolateT* isolate, Handle<PrimitiveHeapObject> export_name,
1138 Handle<PrimitiveHeapObject> local_name,
1139 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1140 int beg_pos, int end_pos) {
1141 Handle<SourceTextModuleInfoEntry> result =
1142 Handle<SourceTextModuleInfoEntry>::cast(isolate->factory()->NewStruct(
1143 SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE, AllocationType::kOld));
1144 result->set_export_name(*export_name);
1145 result->set_local_name(*local_name);
1146 result->set_import_name(*import_name);
1147 result->set_module_request(module_request);
1148 result->set_cell_index(cell_index);
1149 result->set_beg_pos(beg_pos);
1150 result->set_end_pos(end_pos);
1151 return result;
1152 }
1153
1154 template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1155 Isolate* isolate, Handle<PrimitiveHeapObject> export_name,
1156 Handle<PrimitiveHeapObject> local_name,
1157 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1158 int beg_pos, int end_pos);
1159 template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1160 LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
1161 Handle<PrimitiveHeapObject> local_name,
1162 Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
1163 int beg_pos, int end_pos);
1164
1165 template <typename IsolateT>
New(IsolateT * isolate,Zone * zone,SourceTextModuleDescriptor * descr)1166 Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1167 IsolateT* isolate, Zone* zone, SourceTextModuleDescriptor* descr) {
1168 // Serialize module requests.
1169 int size = static_cast<int>(descr->module_requests().size());
1170 Handle<FixedArray> module_requests =
1171 isolate->factory()->NewFixedArray(size, AllocationType::kOld);
1172 for (const auto& elem : descr->module_requests()) {
1173 Handle<ModuleRequest> serialized_module_request = elem->Serialize(isolate);
1174 module_requests->set(elem->index(), *serialized_module_request);
1175 }
1176
1177 // Serialize special exports.
1178 Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
1179 static_cast<int>(descr->special_exports().size()), AllocationType::kOld);
1180 {
1181 int i = 0;
1182 for (auto entry : descr->special_exports()) {
1183 Handle<SourceTextModuleInfoEntry> serialized_entry =
1184 entry->Serialize(isolate);
1185 special_exports->set(i++, *serialized_entry);
1186 }
1187 }
1188
1189 // Serialize namespace imports.
1190 Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
1191 static_cast<int>(descr->namespace_imports().size()),
1192 AllocationType::kOld);
1193 {
1194 int i = 0;
1195 for (auto entry : descr->namespace_imports()) {
1196 Handle<SourceTextModuleInfoEntry> serialized_entry =
1197 entry->Serialize(isolate);
1198 namespace_imports->set(i++, *serialized_entry);
1199 }
1200 }
1201
1202 // Serialize regular exports.
1203 Handle<FixedArray> regular_exports =
1204 descr->SerializeRegularExports(isolate, zone);
1205
1206 // Serialize regular imports.
1207 Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
1208 static_cast<int>(descr->regular_imports().size()), AllocationType::kOld);
1209 {
1210 int i = 0;
1211 for (const auto& elem : descr->regular_imports()) {
1212 Handle<SourceTextModuleInfoEntry> serialized_entry =
1213 elem.second->Serialize(isolate);
1214 regular_imports->set(i++, *serialized_entry);
1215 }
1216 }
1217
1218 Handle<SourceTextModuleInfo> result =
1219 isolate->factory()->NewSourceTextModuleInfo();
1220 result->set(kModuleRequestsIndex, *module_requests);
1221 result->set(kSpecialExportsIndex, *special_exports);
1222 result->set(kRegularExportsIndex, *regular_exports);
1223 result->set(kNamespaceImportsIndex, *namespace_imports);
1224 result->set(kRegularImportsIndex, *regular_imports);
1225 return result;
1226 }
1227 template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1228 Isolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1229 template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1230 LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1231
RegularExportCount() const1232 int SourceTextModuleInfo::RegularExportCount() const {
1233 DCHECK_EQ(regular_exports().length() % kRegularExportLength, 0);
1234 return regular_exports().length() / kRegularExportLength;
1235 }
1236
RegularExportLocalName(int i) const1237 String SourceTextModuleInfo::RegularExportLocalName(int i) const {
1238 return String::cast(regular_exports().get(i * kRegularExportLength +
1239 kRegularExportLocalNameOffset));
1240 }
1241
RegularExportCellIndex(int i) const1242 int SourceTextModuleInfo::RegularExportCellIndex(int i) const {
1243 return Smi::ToInt(regular_exports().get(i * kRegularExportLength +
1244 kRegularExportCellIndexOffset));
1245 }
1246
RegularExportExportNames(int i) const1247 FixedArray SourceTextModuleInfo::RegularExportExportNames(int i) const {
1248 return FixedArray::cast(regular_exports().get(
1249 i * kRegularExportLength + kRegularExportExportNamesOffset));
1250 }
1251
1252 } // namespace internal
1253 } // namespace v8
1254
1255 #include "src/objects/object-macros-undef.h"
1256