• 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 <stdlib.h>
6 
7 #include "src/objects/scope-info.h"
8 
9 #include "src/ast/context-slot-cache.h"
10 #include "src/ast/scopes.h"
11 #include "src/ast/variables.h"
12 #include "src/bootstrapper.h"
13 #include "src/heap/heap-inl.h"
14 #include "src/objects-inl.h"
15 #include "src/objects/module-inl.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->IsModuleInfo()) {
50         if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
51           return false;
52         }
53       } else {
54         UNREACHABLE();
55       }
56     }
57   }
58   return true;
59 }
60 #endif
61 
62 // static
Create(Isolate * isolate,Zone * zone,Scope * scope,MaybeHandle<ScopeInfo> outer_scope)63 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
64                                     MaybeHandle<ScopeInfo> outer_scope) {
65   // Collect variables.
66   int context_local_count = 0;
67   int module_vars_count = 0;
68   // Stack allocated block scope variables are allocated in the parent
69   // declaration scope, but are recorded in the block scope's scope info. First
70   // slot index indicates at which offset a particular scope starts in the
71   // parent declaration scope.
72   for (Variable* var : *scope->locals()) {
73     switch (var->location()) {
74       case VariableLocation::CONTEXT:
75         context_local_count++;
76         break;
77       case VariableLocation::MODULE:
78         module_vars_count++;
79         break;
80       default:
81         break;
82     }
83   }
84   DCHECK(module_vars_count == 0 || scope->is_module_scope());
85 
86   // Make sure we allocate the correct amount.
87   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
88 
89   // Determine use and location of the "this" binding if it is present.
90   VariableAllocationInfo receiver_info;
91   if (scope->is_declaration_scope() &&
92       scope->AsDeclarationScope()->has_this_declaration()) {
93     Variable* var = scope->AsDeclarationScope()->receiver();
94     if (!var->is_used()) {
95       receiver_info = UNUSED;
96     } else if (var->IsContextSlot()) {
97       receiver_info = CONTEXT;
98     } else {
99       DCHECK(var->IsParameter());
100       receiver_info = STACK;
101     }
102   } else {
103     receiver_info = NONE;
104   }
105 
106   const bool has_new_target =
107       scope->is_declaration_scope() &&
108       scope->AsDeclarationScope()->new_target_var() != nullptr;
109   // TODO(cbruni): Don't always waste a field for the inferred name.
110   const bool has_inferred_function_name = scope->is_function_scope();
111 
112   // Determine use and location of the function variable if it is present.
113   VariableAllocationInfo function_name_info;
114   if (scope->is_function_scope()) {
115     if (scope->AsDeclarationScope()->function_var() != nullptr) {
116       Variable* var = scope->AsDeclarationScope()->function_var();
117       if (!var->is_used()) {
118         function_name_info = UNUSED;
119       } else if (var->IsContextSlot()) {
120         function_name_info = CONTEXT;
121       } else {
122         DCHECK(var->IsStackLocal());
123         function_name_info = STACK;
124       }
125     } else {
126       // Always reserve space for the debug name in the scope info.
127       function_name_info = UNUSED;
128     }
129   } else if (scope->is_module_scope() || scope->is_script_scope() ||
130              scope->is_eval_scope()) {
131     // Always reserve space for the debug name in the scope info.
132     function_name_info = UNUSED;
133   } else {
134     function_name_info = NONE;
135   }
136 
137   const bool has_function_name = function_name_info != NONE;
138   const bool has_position_info = NeedsPositionInfo(scope->scope_type());
139   const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
140   const int parameter_count = scope->num_parameters();
141   const bool has_outer_scope_info = !outer_scope.is_null();
142   const int length = kVariablePartIndex + 2 * context_local_count +
143                      (has_receiver ? 1 : 0) +
144                      (has_function_name ? kFunctionNameEntries : 0) +
145                      (has_inferred_function_name ? 1 : 0) +
146                      (has_position_info ? kPositionInfoEntries : 0) +
147                      (has_outer_scope_info ? 1 : 0) +
148                      (scope->is_module_scope()
149                           ? 2 + kModuleVariableEntryLength * module_vars_count
150                           : 0);
151 
152   Factory* factory = isolate->factory();
153   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
154 
155   bool has_simple_parameters = false;
156   bool asm_module = false;
157   bool calls_sloppy_eval = false;
158   if (scope->is_function_scope()) {
159     DeclarationScope* function_scope = scope->AsDeclarationScope();
160     has_simple_parameters = function_scope->has_simple_parameters();
161     asm_module = function_scope->asm_module();
162   }
163   FunctionKind function_kind = kNormalFunction;
164   if (scope->is_declaration_scope()) {
165     function_kind = scope->AsDeclarationScope()->function_kind();
166     calls_sloppy_eval = scope->AsDeclarationScope()->calls_sloppy_eval();
167   }
168 
169   // Encode the flags.
170   int flags =
171       ScopeTypeField::encode(scope->scope_type()) |
172       CallsSloppyEvalField::encode(calls_sloppy_eval) |
173       LanguageModeField::encode(scope->language_mode()) |
174       DeclarationScopeField::encode(scope->is_declaration_scope()) |
175       ReceiverVariableField::encode(receiver_info) |
176       HasNewTargetField::encode(has_new_target) |
177       FunctionVariableField::encode(function_name_info) |
178       HasInferredFunctionNameField::encode(has_inferred_function_name) |
179       AsmModuleField::encode(asm_module) |
180       HasSimpleParametersField::encode(has_simple_parameters) |
181       FunctionKindField::encode(function_kind) |
182       HasOuterScopeInfoField::encode(has_outer_scope_info) |
183       IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
184   scope_info->SetFlags(flags);
185 
186   scope_info->SetParameterCount(parameter_count);
187   scope_info->SetContextLocalCount(context_local_count);
188 
189   int index = kVariablePartIndex;
190 
191   // Add context locals' names and info, module variables' names and info.
192   // Context locals are added using their index.
193   int context_local_base = index;
194   int context_local_info_base = context_local_base + context_local_count;
195   int module_var_entry = scope_info->ModuleVariablesIndex();
196 
197   for (Variable* var : *scope->locals()) {
198     switch (var->location()) {
199       case VariableLocation::CONTEXT: {
200         // Due to duplicate parameters, context locals aren't guaranteed to come
201         // in order.
202         int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
203         DCHECK_LE(0, local_index);
204         DCHECK_LT(local_index, context_local_count);
205         uint32_t info =
206             VariableModeField::encode(var->mode()) |
207             InitFlagField::encode(var->initialization_flag()) |
208             MaybeAssignedFlagField::encode(var->maybe_assigned()) |
209             ParameterNumberField::encode(ParameterNumberField::kMax);
210         scope_info->set(context_local_base + local_index, *var->name());
211         scope_info->set(context_local_info_base + local_index,
212                         Smi::FromInt(info));
213         break;
214       }
215       case VariableLocation::MODULE: {
216         scope_info->set(module_var_entry + kModuleVariableNameOffset,
217                         *var->name());
218         scope_info->set(module_var_entry + kModuleVariableIndexOffset,
219                         Smi::FromInt(var->index()));
220         uint32_t properties =
221             VariableModeField::encode(var->mode()) |
222             InitFlagField::encode(var->initialization_flag()) |
223             MaybeAssignedFlagField::encode(var->maybe_assigned()) |
224             ParameterNumberField::encode(ParameterNumberField::kMax);
225         scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
226                         Smi::FromInt(properties));
227         module_var_entry += kModuleVariableEntryLength;
228         break;
229       }
230       default:
231         break;
232     }
233   }
234 
235   if (scope->is_declaration_scope()) {
236     // Mark contexts slots with the parameter number they represent. We walk the
237     // list of parameters. That can include duplicate entries if a parameter
238     // name is repeated. By walking upwards, we'll automatically mark the
239     // context slot with the highest parameter number that uses this variable.
240     // That will be the parameter number that is represented by the context
241     // slot. All lower parameters will only be available on the stack through
242     // the arguments object.
243     for (int i = 0; i < parameter_count; i++) {
244       Variable* parameter = scope->AsDeclarationScope()->parameter(i);
245       if (parameter->location() != VariableLocation::CONTEXT) continue;
246       int index = parameter->index() - Context::MIN_CONTEXT_SLOTS;
247       int info_index = context_local_info_base + index;
248       int info = Smi::ToInt(scope_info->get(info_index));
249       info = ParameterNumberField::update(info, i);
250       scope_info->set(info_index, Smi::FromInt(info));
251     }
252   }
253 
254   index += 2 * context_local_count;
255 
256   // If the receiver is allocated, add its index.
257   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
258   if (has_receiver) {
259     int var_index = scope->AsDeclarationScope()->receiver()->index();
260     scope_info->set(index++, Smi::FromInt(var_index));
261     // ?? DCHECK(receiver_info != CONTEXT || var_index ==
262     // scope_info->ContextLength() - 1);
263   }
264 
265   // If present, add the function variable name and its index.
266   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
267   if (has_function_name) {
268     DisallowHeapAllocation no_gc;
269     Variable* var = scope->AsDeclarationScope()->function_var();
270     int var_index = -1;
271     Object* name = Smi::kZero;
272     if (var != nullptr) {
273       var_index = var->index();
274       name = *var->name();
275     }
276     scope_info->set(index++, name);
277     scope_info->set(index++, Smi::FromInt(var_index));
278     DCHECK(function_name_info != CONTEXT ||
279            var_index == scope_info->ContextLength() - 1);
280   }
281 
282   DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
283   if (has_inferred_function_name) {
284     // The inferred function name is taken from the SFI.
285     index++;
286   }
287 
288   DCHECK_EQ(index, scope_info->PositionInfoIndex());
289   if (has_position_info) {
290     scope_info->set(index++, Smi::FromInt(scope->start_position()));
291     scope_info->set(index++, Smi::FromInt(scope->end_position()));
292   }
293 
294   // If present, add the outer scope info.
295   DCHECK(index == scope_info->OuterScopeInfoIndex());
296   if (has_outer_scope_info) {
297     scope_info->set(index++, *outer_scope.ToHandleChecked());
298   }
299 
300   // Module-specific information (only for module scopes).
301   if (scope->is_module_scope()) {
302     Handle<ModuleInfo> module_info =
303         ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
304     DCHECK_EQ(index, scope_info->ModuleInfoIndex());
305     scope_info->set(index++, *module_info);
306     DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
307     scope_info->set(index++, Smi::FromInt(module_vars_count));
308     DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
309     // The variable entries themselves have already been written above.
310     index += kModuleVariableEntryLength * module_vars_count;
311   }
312 
313   DCHECK_EQ(index, scope_info->length());
314   DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
315   DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
316   return scope_info;
317 }
318 
319 // static
CreateForWithScope(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)320 Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
321     Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
322   const bool has_outer_scope_info = !outer_scope.is_null();
323   const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
324 
325   Factory* factory = isolate->factory();
326   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
327 
328   // Encode the flags.
329   int flags =
330       ScopeTypeField::encode(WITH_SCOPE) | CallsSloppyEvalField::encode(false) |
331       LanguageModeField::encode(LanguageMode::kSloppy) |
332       DeclarationScopeField::encode(false) |
333       ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
334       FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
335       HasSimpleParametersField::encode(true) |
336       FunctionKindField::encode(kNormalFunction) |
337       HasOuterScopeInfoField::encode(has_outer_scope_info) |
338       IsDebugEvaluateScopeField::encode(false);
339   scope_info->SetFlags(flags);
340 
341   scope_info->SetParameterCount(0);
342   scope_info->SetContextLocalCount(0);
343 
344   int index = kVariablePartIndex;
345   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
346   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
347   DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
348   DCHECK_EQ(index, scope_info->PositionInfoIndex());
349   DCHECK(index == scope_info->OuterScopeInfoIndex());
350   if (has_outer_scope_info) {
351     scope_info->set(index++, *outer_scope.ToHandleChecked());
352   }
353   DCHECK_EQ(index, scope_info->length());
354   DCHECK_EQ(0, scope_info->ParameterCount());
355   DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
356   return scope_info;
357 }
358 
359 // static
CreateGlobalThisBinding(Isolate * isolate)360 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
361   return CreateForBootstrapping(isolate, SCRIPT_SCOPE);
362 }
363 
364 // static
CreateForEmptyFunction(Isolate * isolate)365 Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
366   return CreateForBootstrapping(isolate, FUNCTION_SCOPE);
367 }
368 
369 // static
CreateForBootstrapping(Isolate * isolate,ScopeType type)370 Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
371                                                     ScopeType type) {
372   DCHECK(isolate->bootstrapper()->IsActive());
373   DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);
374 
375   const int parameter_count = 0;
376   const bool is_empty_function = type == FUNCTION_SCOPE;
377   const int context_local_count = is_empty_function ? 0 : 1;
378   const bool has_receiver = !is_empty_function;
379   const bool has_inferred_function_name = is_empty_function;
380   const bool has_position_info = true;
381   const int length = kVariablePartIndex + 2 * context_local_count +
382                      (has_receiver ? 1 : 0) +
383                      (is_empty_function ? kFunctionNameEntries : 0) +
384                      (has_inferred_function_name ? 1 : 0) +
385                      (has_position_info ? kPositionInfoEntries : 0);
386 
387   Factory* factory = isolate->factory();
388   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
389 
390   // Encode the flags.
391   int flags =
392       ScopeTypeField::encode(type) | CallsSloppyEvalField::encode(false) |
393       LanguageModeField::encode(LanguageMode::kSloppy) |
394       DeclarationScopeField::encode(true) |
395       ReceiverVariableField::encode(is_empty_function ? UNUSED : CONTEXT) |
396       HasNewTargetField::encode(false) |
397       FunctionVariableField::encode(is_empty_function ? UNUSED : NONE) |
398       HasInferredFunctionNameField::encode(has_inferred_function_name) |
399       AsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
400       FunctionKindField::encode(FunctionKind::kNormalFunction) |
401       HasOuterScopeInfoField::encode(false) |
402       IsDebugEvaluateScopeField::encode(false);
403   scope_info->SetFlags(flags);
404   scope_info->SetParameterCount(parameter_count);
405   scope_info->SetContextLocalCount(context_local_count);
406 
407   int index = kVariablePartIndex;
408 
409   // Here we add info for context-allocated "this".
410   DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
411   if (context_local_count) {
412     scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
413   }
414   DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
415   if (context_local_count) {
416     const uint32_t value =
417         VariableModeField::encode(VariableMode::kConst) |
418         InitFlagField::encode(kCreatedInitialized) |
419         MaybeAssignedFlagField::encode(kNotAssigned) |
420         ParameterNumberField::encode(ParameterNumberField::kMax);
421     scope_info->set(index++, Smi::FromInt(value));
422   }
423 
424   // And here we record that this scopeinfo binds a receiver.
425   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
426   const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
427   if (!is_empty_function) {
428     scope_info->set(index++, Smi::FromInt(receiver_index));
429   }
430 
431   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
432   if (is_empty_function) {
433     scope_info->set(index++, *isolate->factory()->empty_string());
434     scope_info->set(index++, Smi::kZero);
435   }
436   DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
437   if (has_inferred_function_name) {
438     scope_info->set(index++, *isolate->factory()->empty_string());
439   }
440   DCHECK_EQ(index, scope_info->PositionInfoIndex());
441   // Store dummy position to be in sync with the {scope_type}.
442   scope_info->set(index++, Smi::kZero);
443   scope_info->set(index++, Smi::kZero);
444   DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
445   DCHECK_EQ(index, scope_info->length());
446   DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
447   if (type == FUNCTION_SCOPE) {
448     DCHECK_EQ(scope_info->ContextLength(), 0);
449   } else {
450     DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
451   }
452 
453   return scope_info;
454 }
455 
Empty(Isolate * isolate)456 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
457   return ReadOnlyRoots(isolate).empty_scope_info();
458 }
459 
scope_type() const460 ScopeType ScopeInfo::scope_type() const {
461   DCHECK_LT(0, length());
462   return ScopeTypeField::decode(Flags());
463 }
464 
CallsSloppyEval() const465 bool ScopeInfo::CallsSloppyEval() const {
466   bool calls_sloppy_eval =
467       length() > 0 && CallsSloppyEvalField::decode(Flags());
468   DCHECK_IMPLIES(calls_sloppy_eval, is_sloppy(language_mode()));
469   DCHECK_IMPLIES(calls_sloppy_eval, is_declaration_scope());
470   return calls_sloppy_eval;
471 }
472 
language_mode() const473 LanguageMode ScopeInfo::language_mode() const {
474   return length() > 0 ? LanguageModeField::decode(Flags())
475                       : LanguageMode::kSloppy;
476 }
477 
is_declaration_scope() const478 bool ScopeInfo::is_declaration_scope() const {
479   return DeclarationScopeField::decode(Flags());
480 }
481 
ContextLength() const482 int ScopeInfo::ContextLength() const {
483   if (length() > 0) {
484     int context_locals = ContextLocalCount();
485     bool function_name_context_slot =
486         FunctionVariableField::decode(Flags()) == CONTEXT;
487     bool has_context = context_locals > 0 || function_name_context_slot ||
488                        scope_type() == WITH_SCOPE ||
489                        (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
490                         is_declaration_scope()) ||
491                        (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
492                        (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
493                        scope_type() == MODULE_SCOPE;
494 
495     if (has_context) {
496       return Context::MIN_CONTEXT_SLOTS + context_locals +
497              (function_name_context_slot ? 1 : 0);
498     }
499   }
500   return 0;
501 }
502 
HasReceiver() const503 bool ScopeInfo::HasReceiver() const {
504   if (length() == 0) return false;
505   return NONE != ReceiverVariableField::decode(Flags());
506 }
507 
HasAllocatedReceiver() const508 bool ScopeInfo::HasAllocatedReceiver() const {
509   if (length() == 0) return false;
510   VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
511   return allocation == STACK || allocation == CONTEXT;
512 }
513 
HasNewTarget() const514 bool ScopeInfo::HasNewTarget() const {
515   return HasNewTargetField::decode(Flags());
516 }
517 
HasFunctionName() const518 bool ScopeInfo::HasFunctionName() const {
519   if (length() == 0) return false;
520   return NONE != FunctionVariableField::decode(Flags());
521 }
522 
HasInferredFunctionName() const523 bool ScopeInfo::HasInferredFunctionName() const {
524   if (length() == 0) return false;
525   return HasInferredFunctionNameField::decode(Flags());
526 }
527 
HasPositionInfo() const528 bool ScopeInfo::HasPositionInfo() const {
529   if (length() == 0) return false;
530   return NeedsPositionInfo(scope_type());
531 }
532 
533 // static
NeedsPositionInfo(ScopeType type)534 bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
535   return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
536          type == MODULE_SCOPE;
537 }
538 
HasSharedFunctionName() const539 bool ScopeInfo::HasSharedFunctionName() const {
540   return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
541 }
542 
SetFunctionName(Object * name)543 void ScopeInfo::SetFunctionName(Object* name) {
544   DCHECK(HasFunctionName());
545   DCHECK(name->IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
546   set(FunctionNameInfoIndex(), name);
547 }
548 
SetInferredFunctionName(String * name)549 void ScopeInfo::SetInferredFunctionName(String* name) {
550   DCHECK(HasInferredFunctionName());
551   set(InferredFunctionNameIndex(), name);
552 }
553 
HasOuterScopeInfo() const554 bool ScopeInfo::HasOuterScopeInfo() const {
555   if (length() == 0) return false;
556   return HasOuterScopeInfoField::decode(Flags());
557 }
558 
IsDebugEvaluateScope() const559 bool ScopeInfo::IsDebugEvaluateScope() const {
560   if (length() == 0) return false;
561   return IsDebugEvaluateScopeField::decode(Flags());
562 }
563 
SetIsDebugEvaluateScope()564 void ScopeInfo::SetIsDebugEvaluateScope() {
565   if (length() > 0) {
566     DCHECK_EQ(scope_type(), WITH_SCOPE);
567     SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
568   } else {
569     UNREACHABLE();
570   }
571 }
572 
HasContext() const573 bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
574 
FunctionName() const575 Object* ScopeInfo::FunctionName() const {
576   DCHECK(HasFunctionName());
577   return get(FunctionNameInfoIndex());
578 }
579 
InferredFunctionName() const580 Object* ScopeInfo::InferredFunctionName() const {
581   DCHECK(HasInferredFunctionName());
582   return get(InferredFunctionNameIndex());
583 }
584 
FunctionDebugName() const585 String* ScopeInfo::FunctionDebugName() const {
586   Object* name = FunctionName();
587   if (name->IsString() && String::cast(name)->length() > 0) {
588     return String::cast(name);
589   }
590   if (HasInferredFunctionName()) {
591     name = InferredFunctionName();
592     if (name->IsString()) return String::cast(name);
593   }
594   return GetReadOnlyRoots().empty_string();
595 }
596 
StartPosition() const597 int ScopeInfo::StartPosition() const {
598   DCHECK(HasPositionInfo());
599   return Smi::ToInt(get(PositionInfoIndex()));
600 }
601 
EndPosition() const602 int ScopeInfo::EndPosition() const {
603   DCHECK(HasPositionInfo());
604   return Smi::ToInt(get(PositionInfoIndex() + 1));
605 }
606 
SetPositionInfo(int start,int end)607 void ScopeInfo::SetPositionInfo(int start, int end) {
608   DCHECK(HasPositionInfo());
609   DCHECK_LE(start, end);
610   set(PositionInfoIndex(), Smi::FromInt(start));
611   set(PositionInfoIndex() + 1, Smi::FromInt(end));
612 }
613 
OuterScopeInfo() const614 ScopeInfo* ScopeInfo::OuterScopeInfo() const {
615   DCHECK(HasOuterScopeInfo());
616   return ScopeInfo::cast(get(OuterScopeInfoIndex()));
617 }
618 
ModuleDescriptorInfo() const619 ModuleInfo* ScopeInfo::ModuleDescriptorInfo() const {
620   DCHECK(scope_type() == MODULE_SCOPE);
621   return ModuleInfo::cast(get(ModuleInfoIndex()));
622 }
623 
ContextLocalName(int var) const624 String* ScopeInfo::ContextLocalName(int var) const {
625   DCHECK_LE(0, var);
626   DCHECK_LT(var, ContextLocalCount());
627   int info_index = ContextLocalNamesIndex() + var;
628   return String::cast(get(info_index));
629 }
630 
ContextLocalMode(int var) const631 VariableMode ScopeInfo::ContextLocalMode(int var) const {
632   DCHECK_LE(0, var);
633   DCHECK_LT(var, ContextLocalCount());
634   int info_index = ContextLocalInfosIndex() + var;
635   int value = Smi::ToInt(get(info_index));
636   return VariableModeField::decode(value);
637 }
638 
ContextLocalInitFlag(int var) const639 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
640   DCHECK_LE(0, var);
641   DCHECK_LT(var, ContextLocalCount());
642   int info_index = ContextLocalInfosIndex() + var;
643   int value = Smi::ToInt(get(info_index));
644   return InitFlagField::decode(value);
645 }
646 
ContextLocalIsParameter(int var) const647 bool ScopeInfo::ContextLocalIsParameter(int var) const {
648   DCHECK_LE(0, var);
649   DCHECK_LT(var, ContextLocalCount());
650   int info_index = ContextLocalInfosIndex() + var;
651   int value = Smi::ToInt(get(info_index));
652   return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
653 }
654 
ContextLocalParameterNumber(int var) const655 uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
656   DCHECK(ContextLocalIsParameter(var));
657   int info_index = ContextLocalInfosIndex() + var;
658   int value = Smi::ToInt(get(info_index));
659   return ParameterNumberField::decode(value);
660 }
661 
ContextLocalMaybeAssignedFlag(int var) const662 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
663   DCHECK_LE(0, var);
664   DCHECK_LT(var, ContextLocalCount());
665   int info_index = ContextLocalInfosIndex() + var;
666   int value = Smi::ToInt(get(info_index));
667   return MaybeAssignedFlagField::decode(value);
668 }
669 
670 // static
VariableIsSynthetic(String * name)671 bool ScopeInfo::VariableIsSynthetic(String* name) {
672   // There's currently no flag stored on the ScopeInfo to indicate that a
673   // variable is a compiler-introduced temporary. However, to avoid conflict
674   // with user declarations, the current temporaries like .generator_object and
675   // .result start with a dot, so we can use that as a flag. It's a hack!
676   return name->length() == 0 || name->Get(0) == '.' ||
677          name->Equals(name->GetReadOnlyRoots().this_string());
678 }
679 
ModuleIndex(Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)680 int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
681                            InitializationFlag* init_flag,
682                            MaybeAssignedFlag* maybe_assigned_flag) {
683   DCHECK(name->IsInternalizedString());
684   DCHECK_EQ(scope_type(), MODULE_SCOPE);
685   DCHECK_NOT_NULL(mode);
686   DCHECK_NOT_NULL(init_flag);
687   DCHECK_NOT_NULL(maybe_assigned_flag);
688 
689   int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
690   int entry = ModuleVariablesIndex();
691   for (int i = 0; i < module_vars_count; ++i) {
692     String* var_name = String::cast(get(entry + kModuleVariableNameOffset));
693     if (name->Equals(var_name)) {
694       int index;
695       ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
696       return index;
697     }
698     entry += kModuleVariableEntryLength;
699   }
700 
701   return 0;
702 }
703 
704 // static
ContextSlotIndex(Handle<ScopeInfo> scope_info,Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)705 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
706                                 Handle<String> name, VariableMode* mode,
707                                 InitializationFlag* init_flag,
708                                 MaybeAssignedFlag* maybe_assigned_flag) {
709   DCHECK(name->IsInternalizedString());
710   DCHECK_NOT_NULL(mode);
711   DCHECK_NOT_NULL(init_flag);
712   DCHECK_NOT_NULL(maybe_assigned_flag);
713 
714   if (scope_info->length() == 0) return -1;
715 
716   // Get the Isolate via the heap.
717   //
718   // Ideally we'd pass Isolate* through to this function, however this is mostly
719   // called from the parser, which is otherwise isolate independent. We can't
720   // assume that all scope infos are never RO space (like we can with JSReceiver
721   // or Context), but we can assume that *non-empty* scope infos are.
722   //
723   // So, we take the least-ugly approach of manually getting the isolate to be
724   // able to remove GetIsolate from ScopeInfo in the general case, while
725   // allowing it in this one particular case.
726   Isolate* isolate = Heap::FromWritableHeapObject(*scope_info)->isolate();
727 
728   ContextSlotCache* context_slot_cache = isolate->context_slot_cache();
729   int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
730                                           maybe_assigned_flag);
731   if (result != ContextSlotCache::kNotFound) {
732     DCHECK_LT(result, scope_info->ContextLength());
733     return result;
734   }
735 
736   int start = scope_info->ContextLocalNamesIndex();
737   int end = start + scope_info->ContextLocalCount();
738   for (int i = start; i < end; ++i) {
739     if (*name == scope_info->get(i)) {
740       int var = i - start;
741       *mode = scope_info->ContextLocalMode(var);
742       *init_flag = scope_info->ContextLocalInitFlag(var);
743       *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
744       result = Context::MIN_CONTEXT_SLOTS + var;
745 
746       context_slot_cache->Update(scope_info, name, *mode, *init_flag,
747                                  *maybe_assigned_flag, result);
748       DCHECK_LT(result, scope_info->ContextLength());
749       return result;
750     }
751   }
752   // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
753   context_slot_cache->Update(scope_info, name, VariableMode::kTemporary,
754                              kNeedsInitialization, kNotAssigned, -1);
755 
756   return -1;
757 }
758 
ReceiverContextSlotIndex() const759 int ScopeInfo::ReceiverContextSlotIndex() const {
760   if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
761     return Smi::ToInt(get(ReceiverInfoIndex()));
762   }
763   return -1;
764 }
765 
FunctionContextSlotIndex(String * name) const766 int ScopeInfo::FunctionContextSlotIndex(String* name) const {
767   DCHECK(name->IsInternalizedString());
768   if (length() > 0) {
769     if (FunctionVariableField::decode(Flags()) == CONTEXT &&
770         FunctionName() == name) {
771       return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
772     }
773   }
774   return -1;
775 }
776 
function_kind() const777 FunctionKind ScopeInfo::function_kind() const {
778   return FunctionKindField::decode(Flags());
779 }
780 
ContextLocalNamesIndex() const781 int ScopeInfo::ContextLocalNamesIndex() const {
782   DCHECK_LT(0, length());
783   return kVariablePartIndex;
784 }
785 
ContextLocalInfosIndex() const786 int ScopeInfo::ContextLocalInfosIndex() const {
787   return ContextLocalNamesIndex() + ContextLocalCount();
788 }
789 
ReceiverInfoIndex() const790 int ScopeInfo::ReceiverInfoIndex() const {
791   return ContextLocalInfosIndex() + ContextLocalCount();
792 }
793 
FunctionNameInfoIndex() const794 int ScopeInfo::FunctionNameInfoIndex() const {
795   return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
796 }
797 
InferredFunctionNameIndex() const798 int ScopeInfo::InferredFunctionNameIndex() const {
799   return FunctionNameInfoIndex() +
800          (HasFunctionName() ? kFunctionNameEntries : 0);
801 }
802 
PositionInfoIndex() const803 int ScopeInfo::PositionInfoIndex() const {
804   return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
805 }
806 
OuterScopeInfoIndex() const807 int ScopeInfo::OuterScopeInfoIndex() const {
808   return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
809 }
810 
ModuleInfoIndex() const811 int ScopeInfo::ModuleInfoIndex() const {
812   return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
813 }
814 
ModuleVariableCountIndex() const815 int ScopeInfo::ModuleVariableCountIndex() const {
816   return ModuleInfoIndex() + 1;
817 }
818 
ModuleVariablesIndex() const819 int ScopeInfo::ModuleVariablesIndex() const {
820   return ModuleVariableCountIndex() + 1;
821 }
822 
ModuleVariable(int i,String ** name,int * index,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)823 void ScopeInfo::ModuleVariable(int i, String** name, int* index,
824                                VariableMode* mode,
825                                InitializationFlag* init_flag,
826                                MaybeAssignedFlag* maybe_assigned_flag) {
827   DCHECK_LE(0, i);
828   DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
829 
830   int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
831   int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
832 
833   if (name != nullptr) {
834     *name = String::cast(get(entry + kModuleVariableNameOffset));
835   }
836   if (index != nullptr) {
837     *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
838     DCHECK_NE(*index, 0);
839   }
840   if (mode != nullptr) {
841     *mode = VariableModeField::decode(properties);
842   }
843   if (init_flag != nullptr) {
844     *init_flag = InitFlagField::decode(properties);
845   }
846   if (maybe_assigned_flag != nullptr) {
847     *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
848   }
849 }
850 
operator <<(std::ostream & os,ScopeInfo::VariableAllocationInfo var_info)851 std::ostream& operator<<(std::ostream& os,
852                          ScopeInfo::VariableAllocationInfo var_info) {
853   switch (var_info) {
854     case ScopeInfo::VariableAllocationInfo::NONE:
855       return os << "NONE";
856     case ScopeInfo::VariableAllocationInfo::STACK:
857       return os << "STACK";
858     case ScopeInfo::VariableAllocationInfo::CONTEXT:
859       return os << "CONTEXT";
860     case ScopeInfo::VariableAllocationInfo::UNUSED:
861       return os << "UNUSED";
862   }
863   UNREACHABLE();
864   return os;
865 }
866 
New(Isolate * isolate,Handle<Object> export_name,Handle<Object> local_name,Handle<Object> import_name,int module_request,int cell_index,int beg_pos,int end_pos)867 Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
868                                              Handle<Object> export_name,
869                                              Handle<Object> local_name,
870                                              Handle<Object> import_name,
871                                              int module_request, int cell_index,
872                                              int beg_pos, int end_pos) {
873   Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
874       isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE, TENURED));
875   result->set_export_name(*export_name);
876   result->set_local_name(*local_name);
877   result->set_import_name(*import_name);
878   result->set_module_request(module_request);
879   result->set_cell_index(cell_index);
880   result->set_beg_pos(beg_pos);
881   result->set_end_pos(end_pos);
882   return result;
883 }
884 
New(Isolate * isolate,Zone * zone,ModuleDescriptor * descr)885 Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
886                                    ModuleDescriptor* descr) {
887   // Serialize module requests.
888   int size = static_cast<int>(descr->module_requests().size());
889   Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(size);
890   Handle<FixedArray> module_request_positions =
891       isolate->factory()->NewFixedArray(size);
892   for (const auto& elem : descr->module_requests()) {
893     module_requests->set(elem.second.index, *elem.first->string());
894     module_request_positions->set(elem.second.index,
895                                   Smi::FromInt(elem.second.position));
896   }
897 
898   // Serialize special exports.
899   Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
900       static_cast<int>(descr->special_exports().size()));
901   {
902     int i = 0;
903     for (auto entry : descr->special_exports()) {
904       Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
905       special_exports->set(i++, *serialized_entry);
906     }
907   }
908 
909   // Serialize namespace imports.
910   Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
911       static_cast<int>(descr->namespace_imports().size()));
912   {
913     int i = 0;
914     for (auto entry : descr->namespace_imports()) {
915       Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
916       namespace_imports->set(i++, *serialized_entry);
917     }
918   }
919 
920   // Serialize regular exports.
921   Handle<FixedArray> regular_exports =
922       descr->SerializeRegularExports(isolate, zone);
923 
924   // Serialize regular imports.
925   Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
926       static_cast<int>(descr->regular_imports().size()));
927   {
928     int i = 0;
929     for (const auto& elem : descr->regular_imports()) {
930       Handle<ModuleInfoEntry> serialized_entry =
931           elem.second->Serialize(isolate);
932       regular_imports->set(i++, *serialized_entry);
933     }
934   }
935 
936   Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
937   result->set(kModuleRequestsIndex, *module_requests);
938   result->set(kSpecialExportsIndex, *special_exports);
939   result->set(kRegularExportsIndex, *regular_exports);
940   result->set(kNamespaceImportsIndex, *namespace_imports);
941   result->set(kRegularImportsIndex, *regular_imports);
942   result->set(kModuleRequestPositionsIndex, *module_request_positions);
943   return result;
944 }
945 
RegularExportCount() const946 int ModuleInfo::RegularExportCount() const {
947   DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
948   return regular_exports()->length() / kRegularExportLength;
949 }
950 
RegularExportLocalName(int i) const951 String* ModuleInfo::RegularExportLocalName(int i) const {
952   return String::cast(regular_exports()->get(i * kRegularExportLength +
953                                              kRegularExportLocalNameOffset));
954 }
955 
RegularExportCellIndex(int i) const956 int ModuleInfo::RegularExportCellIndex(int i) const {
957   return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
958                                            kRegularExportCellIndexOffset));
959 }
960 
RegularExportExportNames(int i) const961 FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
962   return FixedArray::cast(regular_exports()->get(
963       i * kRegularExportLength + kRegularExportExportNamesOffset));
964 }
965 
966 }  // namespace internal
967 }  // namespace v8
968