Home | History | Annotate | Download | only in ast
      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
     24 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 
     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 
    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 
    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 
    395 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
    396   return isolate->heap()->empty_scope_info();
    397 }
    398 
    399 
    400 ScopeType ScopeInfo::scope_type() {
    401   DCHECK_LT(0, length());
    402   return ScopeTypeField::decode(Flags());
    403 }
    404 
    405 
    406 bool ScopeInfo::CallsEval() {
    407   return length() > 0 && CallsEvalField::decode(Flags());
    408 }
    409 
    410 
    411 LanguageMode ScopeInfo::language_mode() {
    412   return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
    413 }
    414 
    415 
    416 bool ScopeInfo::is_declaration_scope() {
    417   return DeclarationScopeField::decode(Flags());
    418 }
    419 
    420 
    421 int ScopeInfo::LocalCount() {
    422   return StackLocalCount() + ContextLocalCount();
    423 }
    424 
    425 
    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 
    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 
    457 bool ScopeInfo::HasReceiver() {
    458   if (length() > 0) {
    459     return NONE != ReceiverVariableField::decode(Flags());
    460   } else {
    461     return false;
    462   }
    463 }
    464 
    465 
    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 
    476 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
    477 
    478 
    479 bool ScopeInfo::HasFunctionName() {
    480   if (length() > 0) {
    481     return NONE != FunctionVariableField::decode(Flags());
    482   } else {
    483     return false;
    484   }
    485 }
    486 
    487 bool ScopeInfo::HasOuterScopeInfo() {
    488   if (length() > 0) {
    489     return HasOuterScopeInfoField::decode(Flags());
    490   } else {
    491     return false;
    492   }
    493 }
    494 
    495 bool ScopeInfo::IsDebugEvaluateScope() {
    496   if (length() > 0) {
    497     return IsDebugEvaluateScopeField::decode(Flags());
    498   } else {
    499     return false;
    500   }
    501 }
    502 
    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 
    512 bool ScopeInfo::HasHeapAllocatedLocals() {
    513   if (length() > 0) {
    514     return ContextLocalCount() > 0;
    515   } else {
    516     return false;
    517   }
    518 }
    519 
    520 
    521 bool ScopeInfo::HasContext() {
    522   return ContextLength() > 0;
    523 }
    524 
    525 
    526 String* ScopeInfo::FunctionName() {
    527   DCHECK(HasFunctionName());
    528   return String::cast(get(FunctionNameInfoIndex()));
    529 }
    530 
    531 ScopeInfo* ScopeInfo::OuterScopeInfo() {
    532   DCHECK(HasOuterScopeInfo());
    533   return ScopeInfo::cast(get(OuterScopeInfoIndex()));
    534 }
    535 
    536 ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
    537   DCHECK(scope_type() == MODULE_SCOPE);
    538   return ModuleInfo::cast(get(ModuleInfoIndex()));
    539 }
    540 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    728 int ScopeInfo::ReceiverContextSlotIndex() {
    729   if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
    730     return Smi::cast(get(ReceiverInfoIndex()))->value();
    731   return -1;
    732 }
    733 
    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 
    746 FunctionKind ScopeInfo::function_kind() {
    747   return FunctionKindField::decode(Flags());
    748 }
    749 
    750 int ScopeInfo::ParameterNamesIndex() {
    751   DCHECK_LT(0, length());
    752   return kVariablePartIndex;
    753 }
    754 
    755 
    756 int ScopeInfo::StackLocalFirstSlotIndex() {
    757   return ParameterNamesIndex() + ParameterCount();
    758 }
    759 
    760 int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
    761 
    762 int ScopeInfo::ContextLocalNamesIndex() {
    763   return StackLocalNamesIndex() + StackLocalCount();
    764 }
    765 
    766 int ScopeInfo::ContextLocalInfosIndex() {
    767   return ContextLocalNamesIndex() + ContextLocalCount();
    768 }
    769 
    770 int ScopeInfo::ReceiverInfoIndex() {
    771   return ContextLocalInfosIndex() + ContextLocalCount();
    772 }
    773 
    774 int ScopeInfo::FunctionNameInfoIndex() {
    775   return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
    776 }
    777 
    778 int ScopeInfo::OuterScopeInfoIndex() {
    779   return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
    780 }
    781 
    782 int ScopeInfo::ModuleInfoIndex() {
    783   return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
    784 }
    785 
    786 int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
    787 
    788 int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
    789 
    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 
    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 
    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 
    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 
    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 
    938 int ModuleInfo::RegularExportCount() const {
    939   DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
    940   return regular_exports()->length() / kRegularExportLength;
    941 }
    942 
    943 String* ModuleInfo::RegularExportLocalName(int i) const {
    944   return String::cast(regular_exports()->get(i * kRegularExportLength +
    945                                              kRegularExportLocalNameOffset));
    946 }
    947 
    948 int ModuleInfo::RegularExportCellIndex(int i) const {
    949   return Smi::cast(regular_exports()->get(i * kRegularExportLength +
    950                                           kRegularExportCellIndexOffset))
    951       ->value();
    952 }
    953 
    954 FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
    955   return FixedArray::cast(regular_exports()->get(
    956       i * kRegularExportLength + kRegularExportExportNamesOffset));
    957 }
    958 
    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