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