• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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