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