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/ast/context-slot-cache.h"
8 #include "src/ast/scopes.h"
9 #include "src/ast/variables.h"
10 #include "src/bootstrapper.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 // An entry in ModuleVariableEntries consists of several slots:
16 enum ModuleVariableEntryOffset {
17   kModuleVariableNameOffset,
18   kModuleVariableIndexOffset,
19   kModuleVariablePropertiesOffset,
20   kModuleVariableEntryLength  // Sentinel value.
21 };
22 
23 #ifdef DEBUG
Equals(ScopeInfo * other) const24 bool ScopeInfo::Equals(ScopeInfo* other) const {
25   if (length() != other->length()) return false;
26   for (int index = 0; index < length(); ++index) {
27     Object* entry = get(index);
28     Object* other_entry = other->get(index);
29     if (entry->IsSmi()) {
30       if (entry != other_entry) return false;
31     } else {
32       if (HeapObject::cast(entry)->map()->instance_type() !=
33           HeapObject::cast(other_entry)->map()->instance_type()) {
34         return false;
35       }
36       if (entry->IsString()) {
37         if (!String::cast(entry)->Equals(String::cast(other_entry))) {
38           return false;
39         }
40       } else if (entry->IsScopeInfo()) {
41         if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
42           return false;
43         }
44       } else if (entry->IsModuleInfo()) {
45         if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
46           return false;
47         }
48       } else {
49         UNREACHABLE();
50         return false;
51       }
52     }
53   }
54   return true;
55 }
56 #endif
57 
Create(Isolate * isolate,Zone * zone,Scope * scope,MaybeHandle<ScopeInfo> outer_scope)58 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
59                                     MaybeHandle<ScopeInfo> outer_scope) {
60   // Collect variables.
61   int stack_local_count = 0;
62   int context_local_count = 0;
63   int module_vars_count = 0;
64   // Stack allocated block scope variables are allocated in the parent
65   // declaration scope, but are recorded in the block scope's scope info. First
66   // slot index indicates at which offset a particular scope starts in the
67   // parent declaration scope.
68   int first_slot_index = 0;
69   for (Variable* var : *scope->locals()) {
70     switch (var->location()) {
71       case VariableLocation::LOCAL:
72         if (stack_local_count == 0) first_slot_index = var->index();
73         stack_local_count++;
74         break;
75       case VariableLocation::CONTEXT:
76         context_local_count++;
77         break;
78       case VariableLocation::MODULE:
79         module_vars_count++;
80         break;
81       default:
82         break;
83     }
84   }
85   DCHECK(module_vars_count == 0 || scope->is_module_scope());
86 
87   // Make sure we allocate the correct amount.
88   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
89 
90   // Determine use and location of the "this" binding if it is present.
91   VariableAllocationInfo receiver_info;
92   if (scope->is_declaration_scope() &&
93       scope->AsDeclarationScope()->has_this_declaration()) {
94     Variable* var = scope->AsDeclarationScope()->receiver();
95     if (!var->is_used()) {
96       receiver_info = UNUSED;
97     } else if (var->IsContextSlot()) {
98       receiver_info = CONTEXT;
99     } else {
100       DCHECK(var->IsParameter());
101       receiver_info = STACK;
102     }
103   } else {
104     receiver_info = NONE;
105   }
106 
107   bool has_new_target =
108       scope->is_declaration_scope() &&
109       scope->AsDeclarationScope()->new_target_var() != nullptr;
110 
111   // Determine use and location of the function variable if it is present.
112   VariableAllocationInfo function_name_info;
113   if (scope->is_function_scope() &&
114       scope->AsDeclarationScope()->function_var() != nullptr) {
115     Variable* var = scope->AsDeclarationScope()->function_var();
116     if (!var->is_used()) {
117       function_name_info = UNUSED;
118     } else if (var->IsContextSlot()) {
119       function_name_info = CONTEXT;
120     } else {
121       DCHECK(var->IsStackLocal());
122       function_name_info = STACK;
123     }
124   } else {
125     function_name_info = NONE;
126   }
127 
128   const bool has_function_name = function_name_info != NONE;
129   const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
130   const int parameter_count = scope->num_parameters();
131   const bool has_outer_scope_info = !outer_scope.is_null();
132   const int length = kVariablePartIndex + parameter_count +
133                      (1 + stack_local_count) + 2 * context_local_count +
134                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
135                      (has_outer_scope_info ? 1 : 0) +
136                      (scope->is_module_scope()
137                           ? 2 + kModuleVariableEntryLength * module_vars_count
138                           : 0);
139 
140   Factory* factory = isolate->factory();
141   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
142 
143   bool has_simple_parameters = false;
144   bool asm_module = false;
145   bool asm_function = false;
146   FunctionKind function_kind = kNormalFunction;
147   if (scope->is_function_scope()) {
148     DeclarationScope* function_scope = scope->AsDeclarationScope();
149     has_simple_parameters = function_scope->has_simple_parameters();
150     asm_module = function_scope->asm_module();
151     asm_function = function_scope->asm_function();
152     function_kind = function_scope->function_kind();
153   }
154 
155   // Encode the flags.
156   int flags =
157       ScopeTypeField::encode(scope->scope_type()) |
158       CallsEvalField::encode(scope->calls_eval()) |
159       LanguageModeField::encode(scope->language_mode()) |
160       DeclarationScopeField::encode(scope->is_declaration_scope()) |
161       ReceiverVariableField::encode(receiver_info) |
162       HasNewTargetField::encode(has_new_target) |
163       FunctionVariableField::encode(function_name_info) |
164       AsmModuleField::encode(asm_module) |
165       AsmFunctionField::encode(asm_function) |
166       HasSimpleParametersField::encode(has_simple_parameters) |
167       FunctionKindField::encode(function_kind) |
168       HasOuterScopeInfoField::encode(has_outer_scope_info) |
169       IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
170   scope_info->SetFlags(flags);
171 
172   scope_info->SetParameterCount(parameter_count);
173   scope_info->SetStackLocalCount(stack_local_count);
174   scope_info->SetContextLocalCount(context_local_count);
175 
176   int index = kVariablePartIndex;
177   // Add parameters.
178   DCHECK_EQ(index, scope_info->ParameterNamesIndex());
179   if (scope->is_declaration_scope()) {
180     for (int i = 0; i < parameter_count; ++i) {
181       scope_info->set(index++,
182                       *scope->AsDeclarationScope()->parameter(i)->name());
183     }
184   }
185 
186   // Add stack locals' names, context locals' names and info, module variables'
187   // names and info. We are assuming that the stack locals' slots are allocated
188   // in increasing order, so we can simply add them to the ScopeInfo object.
189   // Context locals are added using their index.
190   DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
191   scope_info->set(index++, Smi::FromInt(first_slot_index));
192   DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
193 
194   int stack_local_base = index;
195   int context_local_base = stack_local_base + stack_local_count;
196   int context_local_info_base = context_local_base + context_local_count;
197   int module_var_entry = scope_info->ModuleVariablesIndex();
198 
199   for (Variable* var : *scope->locals()) {
200     switch (var->location()) {
201       case VariableLocation::LOCAL: {
202         int local_index = var->index() - first_slot_index;
203         DCHECK_LE(0, local_index);
204         DCHECK_LT(local_index, stack_local_count);
205         scope_info->set(stack_local_base + local_index, *var->name());
206         break;
207       }
208       case VariableLocation::CONTEXT: {
209         // Due to duplicate parameters, context locals aren't guaranteed to come
210         // in order.
211         int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
212         DCHECK_LE(0, local_index);
213         DCHECK_LT(local_index, context_local_count);
214         uint32_t info = VariableModeField::encode(var->mode()) |
215                         InitFlagField::encode(var->initialization_flag()) |
216                         MaybeAssignedFlagField::encode(var->maybe_assigned());
217         scope_info->set(context_local_base + local_index, *var->name());
218         scope_info->set(context_local_info_base + local_index,
219                         Smi::FromInt(info));
220         break;
221       }
222       case VariableLocation::MODULE: {
223         scope_info->set(module_var_entry + kModuleVariableNameOffset,
224                         *var->name());
225         scope_info->set(module_var_entry + kModuleVariableIndexOffset,
226                         Smi::FromInt(var->index()));
227         uint32_t properties =
228             VariableModeField::encode(var->mode()) |
229             InitFlagField::encode(var->initialization_flag()) |
230             MaybeAssignedFlagField::encode(var->maybe_assigned());
231         scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
232                         Smi::FromInt(properties));
233         module_var_entry += kModuleVariableEntryLength;
234         break;
235       }
236       default:
237         break;
238     }
239   }
240 
241   index += stack_local_count + 2 * context_local_count;
242 
243   // If the receiver is allocated, add its index.
244   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
245   if (has_receiver) {
246     int var_index = scope->AsDeclarationScope()->receiver()->index();
247     scope_info->set(index++, Smi::FromInt(var_index));
248     // ?? DCHECK(receiver_info != CONTEXT || var_index ==
249     // scope_info->ContextLength() - 1);
250   }
251 
252   // If present, add the function variable name and its index.
253   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
254   if (has_function_name) {
255     int var_index = scope->AsDeclarationScope()->function_var()->index();
256     scope_info->set(index++,
257                     *scope->AsDeclarationScope()->function_var()->name());
258     scope_info->set(index++, Smi::FromInt(var_index));
259     DCHECK(function_name_info != CONTEXT ||
260            var_index == scope_info->ContextLength() - 1);
261   }
262 
263   // If present, add the outer scope info.
264   DCHECK(index == scope_info->OuterScopeInfoIndex());
265   if (has_outer_scope_info) {
266     scope_info->set(index++, *outer_scope.ToHandleChecked());
267   }
268 
269   // Module-specific information (only for module scopes).
270   if (scope->is_module_scope()) {
271     Handle<ModuleInfo> module_info =
272         ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
273     DCHECK_EQ(index, scope_info->ModuleInfoIndex());
274     scope_info->set(index++, *module_info);
275     DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
276     scope_info->set(index++, Smi::FromInt(module_vars_count));
277     DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
278     // The variable entries themselves have already been written above.
279     index += kModuleVariableEntryLength * module_vars_count;
280   }
281 
282   DCHECK_EQ(index, scope_info->length());
283   DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
284   DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
285   return scope_info;
286 }
287 
CreateForWithScope(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)288 Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
289     Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
290   const bool has_outer_scope_info = !outer_scope.is_null();
291   const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0);
292 
293   Factory* factory = isolate->factory();
294   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
295 
296   // Encode the flags.
297   int flags =
298       ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
299       LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
300       ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
301       FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
302       AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
303       FunctionKindField::encode(kNormalFunction) |
304       HasOuterScopeInfoField::encode(has_outer_scope_info) |
305       IsDebugEvaluateScopeField::encode(false);
306   scope_info->SetFlags(flags);
307 
308   scope_info->SetParameterCount(0);
309   scope_info->SetStackLocalCount(0);
310   scope_info->SetContextLocalCount(0);
311 
312   int index = kVariablePartIndex;
313   DCHECK_EQ(index, scope_info->ParameterNamesIndex());
314   DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
315   scope_info->set(index++, Smi::kZero);
316   DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
317   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
318   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
319   DCHECK(index == scope_info->OuterScopeInfoIndex());
320   if (has_outer_scope_info) {
321     scope_info->set(index++, *outer_scope.ToHandleChecked());
322   }
323   DCHECK_EQ(index, scope_info->length());
324   DCHECK_EQ(0, scope_info->ParameterCount());
325   DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
326   return scope_info;
327 }
328 
CreateGlobalThisBinding(Isolate * isolate)329 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
330   DCHECK(isolate->bootstrapper()->IsActive());
331 
332   const int stack_local_count = 0;
333   const int context_local_count = 1;
334   const bool has_simple_parameters = true;
335   const VariableAllocationInfo receiver_info = CONTEXT;
336   const VariableAllocationInfo function_name_info = NONE;
337   const bool has_function_name = false;
338   const bool has_receiver = true;
339   const bool has_outer_scope_info = false;
340   const int parameter_count = 0;
341   const int length = kVariablePartIndex + parameter_count +
342                      (1 + stack_local_count) + 2 * context_local_count +
343                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
344                      (has_outer_scope_info ? 1 : 0);
345 
346   Factory* factory = isolate->factory();
347   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
348 
349   // Encode the flags.
350   int flags =
351       ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) |
352       LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) |
353       ReceiverVariableField::encode(receiver_info) |
354       FunctionVariableField::encode(function_name_info) |
355       AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
356       HasSimpleParametersField::encode(has_simple_parameters) |
357       FunctionKindField::encode(FunctionKind::kNormalFunction) |
358       HasOuterScopeInfoField::encode(has_outer_scope_info) |
359       IsDebugEvaluateScopeField::encode(false);
360   scope_info->SetFlags(flags);
361   scope_info->SetParameterCount(parameter_count);
362   scope_info->SetStackLocalCount(stack_local_count);
363   scope_info->SetContextLocalCount(context_local_count);
364 
365   int index = kVariablePartIndex;
366   const int first_slot_index = 0;
367   DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
368   scope_info->set(index++, Smi::FromInt(first_slot_index));
369   DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
370 
371   // Here we add info for context-allocated "this".
372   DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
373   scope_info->set(index++, isolate->heap()->this_string());
374   DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
375   const uint32_t value = VariableModeField::encode(CONST) |
376                          InitFlagField::encode(kCreatedInitialized) |
377                          MaybeAssignedFlagField::encode(kNotAssigned);
378   scope_info->set(index++, Smi::FromInt(value));
379 
380   // And here we record that this scopeinfo binds a receiver.
381   DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
382   const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
383   scope_info->set(index++, Smi::FromInt(receiver_index));
384 
385   DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
386   DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
387   DCHECK_EQ(index, scope_info->length());
388   DCHECK_EQ(scope_info->ParameterCount(), 0);
389   DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
390 
391   return scope_info;
392 }
393 
394 
Empty(Isolate * isolate)395 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
396   return isolate->heap()->empty_scope_info();
397 }
398 
399 
scope_type()400 ScopeType ScopeInfo::scope_type() {
401   DCHECK_LT(0, length());
402   return ScopeTypeField::decode(Flags());
403 }
404 
405 
CallsEval()406 bool ScopeInfo::CallsEval() {
407   return length() > 0 && CallsEvalField::decode(Flags());
408 }
409 
410 
language_mode()411 LanguageMode ScopeInfo::language_mode() {
412   return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
413 }
414 
415 
is_declaration_scope()416 bool ScopeInfo::is_declaration_scope() {
417   return DeclarationScopeField::decode(Flags());
418 }
419 
420 
LocalCount()421 int ScopeInfo::LocalCount() {
422   return StackLocalCount() + ContextLocalCount();
423 }
424 
425 
StackSlotCount()426 int ScopeInfo::StackSlotCount() {
427   if (length() > 0) {
428     bool function_name_stack_slot =
429         FunctionVariableField::decode(Flags()) == STACK;
430     return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
431   }
432   return 0;
433 }
434 
435 
ContextLength()436 int ScopeInfo::ContextLength() {
437   if (length() > 0) {
438     int context_locals = ContextLocalCount();
439     bool function_name_context_slot =
440         FunctionVariableField::decode(Flags()) == CONTEXT;
441     bool has_context = context_locals > 0 || function_name_context_slot ||
442                        scope_type() == WITH_SCOPE ||
443                        (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
444                         is_declaration_scope()) ||
445                        (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
446                        scope_type() == MODULE_SCOPE;
447 
448     if (has_context) {
449       return Context::MIN_CONTEXT_SLOTS + context_locals +
450              (function_name_context_slot ? 1 : 0);
451     }
452   }
453   return 0;
454 }
455 
456 
HasReceiver()457 bool ScopeInfo::HasReceiver() {
458   if (length() > 0) {
459     return NONE != ReceiverVariableField::decode(Flags());
460   } else {
461     return false;
462   }
463 }
464 
465 
HasAllocatedReceiver()466 bool ScopeInfo::HasAllocatedReceiver() {
467   if (length() > 0) {
468     VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
469     return allocation == STACK || allocation == CONTEXT;
470   } else {
471     return false;
472   }
473 }
474 
475 
HasNewTarget()476 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
477 
478 
HasFunctionName()479 bool ScopeInfo::HasFunctionName() {
480   if (length() > 0) {
481     return NONE != FunctionVariableField::decode(Flags());
482   } else {
483     return false;
484   }
485 }
486 
HasOuterScopeInfo()487 bool ScopeInfo::HasOuterScopeInfo() {
488   if (length() > 0) {
489     return HasOuterScopeInfoField::decode(Flags());
490   } else {
491     return false;
492   }
493 }
494 
IsDebugEvaluateScope()495 bool ScopeInfo::IsDebugEvaluateScope() {
496   if (length() > 0) {
497     return IsDebugEvaluateScopeField::decode(Flags());
498   } else {
499     return false;
500   }
501 }
502 
SetIsDebugEvaluateScope()503 void ScopeInfo::SetIsDebugEvaluateScope() {
504   if (length() > 0) {
505     DCHECK_EQ(scope_type(), WITH_SCOPE);
506     SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
507   } else {
508     UNREACHABLE();
509   }
510 }
511 
HasHeapAllocatedLocals()512 bool ScopeInfo::HasHeapAllocatedLocals() {
513   if (length() > 0) {
514     return ContextLocalCount() > 0;
515   } else {
516     return false;
517   }
518 }
519 
520 
HasContext()521 bool ScopeInfo::HasContext() {
522   return ContextLength() > 0;
523 }
524 
525 
FunctionName()526 String* ScopeInfo::FunctionName() {
527   DCHECK(HasFunctionName());
528   return String::cast(get(FunctionNameInfoIndex()));
529 }
530 
OuterScopeInfo()531 ScopeInfo* ScopeInfo::OuterScopeInfo() {
532   DCHECK(HasOuterScopeInfo());
533   return ScopeInfo::cast(get(OuterScopeInfoIndex()));
534 }
535 
ModuleDescriptorInfo()536 ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
537   DCHECK(scope_type() == MODULE_SCOPE);
538   return ModuleInfo::cast(get(ModuleInfoIndex()));
539 }
540 
ParameterName(int var)541 String* ScopeInfo::ParameterName(int var) {
542   DCHECK_LE(0, var);
543   DCHECK_LT(var, ParameterCount());
544   int info_index = ParameterNamesIndex() + var;
545   return String::cast(get(info_index));
546 }
547 
548 
LocalName(int var)549 String* ScopeInfo::LocalName(int var) {
550   DCHECK_LE(0, var);
551   DCHECK_LT(var, LocalCount());
552   DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
553          ContextLocalNamesIndex());
554   int info_index = StackLocalNamesIndex() + var;
555   return String::cast(get(info_index));
556 }
557 
558 
StackLocalName(int var)559 String* ScopeInfo::StackLocalName(int var) {
560   DCHECK_LE(0, var);
561   DCHECK_LT(var, StackLocalCount());
562   int info_index = StackLocalNamesIndex() + var;
563   return String::cast(get(info_index));
564 }
565 
566 
StackLocalIndex(int var)567 int ScopeInfo::StackLocalIndex(int var) {
568   DCHECK_LE(0, var);
569   DCHECK_LT(var, StackLocalCount());
570   int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
571   return first_slot_index + var;
572 }
573 
574 
ContextLocalName(int var)575 String* ScopeInfo::ContextLocalName(int var) {
576   DCHECK_LE(0, var);
577   DCHECK_LT(var, ContextLocalCount());
578   int info_index = ContextLocalNamesIndex() + var;
579   return String::cast(get(info_index));
580 }
581 
582 
ContextLocalMode(int var)583 VariableMode ScopeInfo::ContextLocalMode(int var) {
584   DCHECK_LE(0, var);
585   DCHECK_LT(var, ContextLocalCount());
586   int info_index = ContextLocalInfosIndex() + var;
587   int value = Smi::cast(get(info_index))->value();
588   return VariableModeField::decode(value);
589 }
590 
591 
ContextLocalInitFlag(int var)592 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
593   DCHECK_LE(0, var);
594   DCHECK_LT(var, ContextLocalCount());
595   int info_index = ContextLocalInfosIndex() + var;
596   int value = Smi::cast(get(info_index))->value();
597   return InitFlagField::decode(value);
598 }
599 
600 
ContextLocalMaybeAssignedFlag(int var)601 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
602   DCHECK_LE(0, var);
603   DCHECK_LT(var, ContextLocalCount());
604   int info_index = ContextLocalInfosIndex() + var;
605   int value = Smi::cast(get(info_index))->value();
606   return MaybeAssignedFlagField::decode(value);
607 }
608 
VariableIsSynthetic(String * name)609 bool ScopeInfo::VariableIsSynthetic(String* name) {
610   // There's currently no flag stored on the ScopeInfo to indicate that a
611   // variable is a compiler-introduced temporary. However, to avoid conflict
612   // with user declarations, the current temporaries like .generator_object and
613   // .result start with a dot, so we can use that as a flag. It's a hack!
614   return name->length() == 0 || name->Get(0) == '.' ||
615          name->Equals(name->GetHeap()->this_string());
616 }
617 
618 
StackSlotIndex(String * name)619 int ScopeInfo::StackSlotIndex(String* name) {
620   DCHECK(name->IsInternalizedString());
621   if (length() > 0) {
622     int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
623     int start = StackLocalNamesIndex();
624     int end = start + StackLocalCount();
625     for (int i = start; i < end; ++i) {
626       if (name == get(i)) {
627         return i - start + first_slot_index;
628       }
629     }
630   }
631   return -1;
632 }
633 
ModuleIndex(Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)634 int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
635                            InitializationFlag* init_flag,
636                            MaybeAssignedFlag* maybe_assigned_flag) {
637   DCHECK_EQ(scope_type(), MODULE_SCOPE);
638   DCHECK(name->IsInternalizedString());
639   DCHECK_NOT_NULL(mode);
640   DCHECK_NOT_NULL(init_flag);
641   DCHECK_NOT_NULL(maybe_assigned_flag);
642 
643   int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value();
644   int entry = ModuleVariablesIndex();
645   for (int i = 0; i < module_vars_count; ++i) {
646     if (*name == get(entry + kModuleVariableNameOffset)) {
647       int index;
648       ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
649       return index;
650     }
651     entry += kModuleVariableEntryLength;
652   }
653 
654   return 0;
655 }
656 
ContextSlotIndex(Handle<ScopeInfo> scope_info,Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)657 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
658                                 Handle<String> name, VariableMode* mode,
659                                 InitializationFlag* init_flag,
660                                 MaybeAssignedFlag* maybe_assigned_flag) {
661   DCHECK(name->IsInternalizedString());
662   DCHECK_NOT_NULL(mode);
663   DCHECK_NOT_NULL(init_flag);
664   DCHECK_NOT_NULL(maybe_assigned_flag);
665 
666   if (scope_info->length() > 0) {
667     ContextSlotCache* context_slot_cache =
668         scope_info->GetIsolate()->context_slot_cache();
669     int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
670                                             maybe_assigned_flag);
671     if (result != ContextSlotCache::kNotFound) {
672       DCHECK_LT(result, scope_info->ContextLength());
673       return result;
674     }
675 
676     int start = scope_info->ContextLocalNamesIndex();
677     int end = start + scope_info->ContextLocalCount();
678     for (int i = start; i < end; ++i) {
679       if (*name == scope_info->get(i)) {
680         int var = i - start;
681         *mode = scope_info->ContextLocalMode(var);
682         *init_flag = scope_info->ContextLocalInitFlag(var);
683         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
684         result = Context::MIN_CONTEXT_SLOTS + var;
685 
686         context_slot_cache->Update(scope_info, name, *mode, *init_flag,
687                                    *maybe_assigned_flag, result);
688         DCHECK_LT(result, scope_info->ContextLength());
689         return result;
690       }
691     }
692     // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
693     context_slot_cache->Update(scope_info, name, TEMPORARY,
694                                kNeedsInitialization, kNotAssigned, -1);
695   }
696 
697   return -1;
698 }
699 
ContextSlotName(int slot_index)700 String* ScopeInfo::ContextSlotName(int slot_index) {
701   int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
702   DCHECK_LE(0, var);
703   DCHECK_LT(var, ContextLocalCount());
704   return ContextLocalName(var);
705 }
706 
707 
ParameterIndex(String * name)708 int ScopeInfo::ParameterIndex(String* name) {
709   DCHECK(name->IsInternalizedString());
710   if (length() > 0) {
711     // We must read parameters from the end since for
712     // multiply declared parameters the value of the
713     // last declaration of that parameter is used
714     // inside a function (and thus we need to look
715     // at the last index). Was bug# 1110337.
716     int start = ParameterNamesIndex();
717     int end = start + ParameterCount();
718     for (int i = end - 1; i >= start; --i) {
719       if (name == get(i)) {
720         return i - start;
721       }
722     }
723   }
724   return -1;
725 }
726 
727 
ReceiverContextSlotIndex()728 int ScopeInfo::ReceiverContextSlotIndex() {
729   if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
730     return Smi::cast(get(ReceiverInfoIndex()))->value();
731   return -1;
732 }
733 
FunctionContextSlotIndex(String * name)734 int ScopeInfo::FunctionContextSlotIndex(String* name) {
735   DCHECK(name->IsInternalizedString());
736   if (length() > 0) {
737     if (FunctionVariableField::decode(Flags()) == CONTEXT &&
738         FunctionName() == name) {
739       return Smi::cast(get(FunctionNameInfoIndex() + 1))->value();
740     }
741   }
742   return -1;
743 }
744 
745 
function_kind()746 FunctionKind ScopeInfo::function_kind() {
747   return FunctionKindField::decode(Flags());
748 }
749 
ParameterNamesIndex()750 int ScopeInfo::ParameterNamesIndex() {
751   DCHECK_LT(0, length());
752   return kVariablePartIndex;
753 }
754 
755 
StackLocalFirstSlotIndex()756 int ScopeInfo::StackLocalFirstSlotIndex() {
757   return ParameterNamesIndex() + ParameterCount();
758 }
759 
StackLocalNamesIndex()760 int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
761 
ContextLocalNamesIndex()762 int ScopeInfo::ContextLocalNamesIndex() {
763   return StackLocalNamesIndex() + StackLocalCount();
764 }
765 
ContextLocalInfosIndex()766 int ScopeInfo::ContextLocalInfosIndex() {
767   return ContextLocalNamesIndex() + ContextLocalCount();
768 }
769 
ReceiverInfoIndex()770 int ScopeInfo::ReceiverInfoIndex() {
771   return ContextLocalInfosIndex() + ContextLocalCount();
772 }
773 
FunctionNameInfoIndex()774 int ScopeInfo::FunctionNameInfoIndex() {
775   return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
776 }
777 
OuterScopeInfoIndex()778 int ScopeInfo::OuterScopeInfoIndex() {
779   return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
780 }
781 
ModuleInfoIndex()782 int ScopeInfo::ModuleInfoIndex() {
783   return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
784 }
785 
ModuleVariableCountIndex()786 int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
787 
ModuleVariablesIndex()788 int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
789 
ModuleVariable(int i,String ** name,int * index,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)790 void ScopeInfo::ModuleVariable(int i, String** name, int* index,
791                                VariableMode* mode,
792                                InitializationFlag* init_flag,
793                                MaybeAssignedFlag* maybe_assigned_flag) {
794   DCHECK_LE(0, i);
795   DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value());
796 
797   int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
798   int properties =
799       Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value();
800 
801   if (name != nullptr) {
802     *name = String::cast(get(entry + kModuleVariableNameOffset));
803   }
804   if (index != nullptr) {
805     *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value();
806     DCHECK_NE(*index, 0);
807   }
808   if (mode != nullptr) {
809     *mode = VariableModeField::decode(properties);
810   }
811   if (init_flag != nullptr) {
812     *init_flag = InitFlagField::decode(properties);
813   }
814   if (maybe_assigned_flag != nullptr) {
815     *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
816   }
817 }
818 
819 #ifdef DEBUG
820 
PrintList(const char * list_name,int nof_internal_slots,int start,int end,ScopeInfo * scope_info)821 static void PrintList(const char* list_name,
822                       int nof_internal_slots,
823                       int start,
824                       int end,
825                       ScopeInfo* scope_info) {
826   if (start < end) {
827     PrintF("\n  // %s\n", list_name);
828     if (nof_internal_slots > 0) {
829       PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
830     }
831     for (int i = nof_internal_slots; start < end; ++i, ++start) {
832       PrintF("  %2d ", i);
833       String::cast(scope_info->get(start))->ShortPrint();
834       PrintF("\n");
835     }
836   }
837 }
838 
839 
Print()840 void ScopeInfo::Print() {
841   PrintF("ScopeInfo ");
842   if (HasFunctionName()) {
843     FunctionName()->ShortPrint();
844   } else {
845     PrintF("/* no function name */");
846   }
847   PrintF("{");
848 
849   if (length() > 0) {
850     PrintList("parameters", 0, ParameterNamesIndex(),
851               ParameterNamesIndex() + ParameterCount(), this);
852     PrintList("stack slots", 0, StackLocalNamesIndex(),
853               StackLocalNamesIndex() + StackLocalCount(), this);
854     PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
855               ContextLocalNamesIndex(),
856               ContextLocalNamesIndex() + ContextLocalCount(), this);
857     // TODO(neis): Print module stuff if present.
858   }
859 
860   PrintF("}\n");
861 }
862 #endif  // DEBUG
863 
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)864 Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
865                                              Handle<Object> export_name,
866                                              Handle<Object> local_name,
867                                              Handle<Object> import_name,
868                                              int module_request, int cell_index,
869                                              int beg_pos, int end_pos) {
870   Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
871       isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE));
872   result->set_export_name(*export_name);
873   result->set_local_name(*local_name);
874   result->set_import_name(*import_name);
875   result->set_module_request(module_request);
876   result->set_cell_index(cell_index);
877   result->set_beg_pos(beg_pos);
878   result->set_end_pos(end_pos);
879   return result;
880 }
881 
New(Isolate * isolate,Zone * zone,ModuleDescriptor * descr)882 Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
883                                    ModuleDescriptor* descr) {
884   // Serialize module requests.
885   Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
886       static_cast<int>(descr->module_requests().size()));
887   for (const auto& elem : descr->module_requests()) {
888     module_requests->set(elem.second, *elem.first->string());
889   }
890 
891   // Serialize special exports.
892   Handle<FixedArray> special_exports =
893       isolate->factory()->NewFixedArray(descr->special_exports().length());
894   {
895     int i = 0;
896     for (auto entry : descr->special_exports()) {
897       Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
898       special_exports->set(i++, *serialized_entry);
899     }
900   }
901 
902   // Serialize namespace imports.
903   Handle<FixedArray> namespace_imports =
904       isolate->factory()->NewFixedArray(descr->namespace_imports().length());
905   {
906     int i = 0;
907     for (auto entry : descr->namespace_imports()) {
908       Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
909       namespace_imports->set(i++, *serialized_entry);
910     }
911   }
912 
913   // Serialize regular exports.
914   Handle<FixedArray> regular_exports =
915       descr->SerializeRegularExports(isolate, zone);
916 
917   // Serialize regular imports.
918   Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
919       static_cast<int>(descr->regular_imports().size()));
920   {
921     int i = 0;
922     for (const auto& elem : descr->regular_imports()) {
923       Handle<ModuleInfoEntry> serialized_entry =
924           elem.second->Serialize(isolate);
925       regular_imports->set(i++, *serialized_entry);
926     }
927   }
928 
929   Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
930   result->set(kModuleRequestsIndex, *module_requests);
931   result->set(kSpecialExportsIndex, *special_exports);
932   result->set(kRegularExportsIndex, *regular_exports);
933   result->set(kNamespaceImportsIndex, *namespace_imports);
934   result->set(kRegularImportsIndex, *regular_imports);
935   return result;
936 }
937 
RegularExportCount() const938 int ModuleInfo::RegularExportCount() const {
939   DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
940   return regular_exports()->length() / kRegularExportLength;
941 }
942 
RegularExportLocalName(int i) const943 String* ModuleInfo::RegularExportLocalName(int i) const {
944   return String::cast(regular_exports()->get(i * kRegularExportLength +
945                                              kRegularExportLocalNameOffset));
946 }
947 
RegularExportCellIndex(int i) const948 int ModuleInfo::RegularExportCellIndex(int i) const {
949   return Smi::cast(regular_exports()->get(i * kRegularExportLength +
950                                           kRegularExportCellIndexOffset))
951       ->value();
952 }
953 
RegularExportExportNames(int i) const954 FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
955   return FixedArray::cast(regular_exports()->get(
956       i * kRegularExportLength + kRegularExportExportNamesOffset));
957 }
958 
LookupRegularImport(Handle<ModuleInfo> info,Handle<String> local_name)959 Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport(
960     Handle<ModuleInfo> info, Handle<String> local_name) {
961   Isolate* isolate = info->GetIsolate();
962   Handle<FixedArray> regular_imports(info->regular_imports(), isolate);
963   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
964     Handle<ModuleInfoEntry> entry(
965         ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
966     if (String::cast(entry->local_name())->Equals(*local_name)) {
967       return entry;
968     }
969   }
970   UNREACHABLE();
971   return Handle<ModuleInfoEntry>();
972 }
973 
974 }  // namespace internal
975 }  // namespace v8
976