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