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 "src/ast/scopeinfo.h"
      6 
      7 #include <stdlib.h>
      8 
      9 #include "src/ast/scopes.h"
     10 #include "src/bootstrapper.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 
     16 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
     17                                     Scope* scope) {
     18   // Collect stack and context locals.
     19   ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
     20   ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
     21   ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
     22   ZoneList<Variable*> strong_mode_free_variables(0, zone);
     23 
     24   scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
     25                                       &context_globals,
     26                                       &strong_mode_free_variables);
     27   const int stack_local_count = stack_locals.length();
     28   const int context_local_count = context_locals.length();
     29   const int context_global_count = context_globals.length();
     30   const int strong_mode_free_variable_count =
     31       strong_mode_free_variables.length();
     32   // Make sure we allocate the correct amount.
     33   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
     34   DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
     35 
     36   // Determine use and location of the "this" binding if it is present.
     37   VariableAllocationInfo receiver_info;
     38   if (scope->has_this_declaration()) {
     39     Variable* var = scope->receiver();
     40     if (!var->is_used()) {
     41       receiver_info = UNUSED;
     42     } else if (var->IsContextSlot()) {
     43       receiver_info = CONTEXT;
     44     } else {
     45       DCHECK(var->IsParameter());
     46       receiver_info = STACK;
     47     }
     48   } else {
     49     receiver_info = NONE;
     50   }
     51 
     52   bool has_new_target = scope->new_target_var() != nullptr;
     53 
     54   // Determine use and location of the function variable if it is present.
     55   VariableAllocationInfo function_name_info;
     56   VariableMode function_variable_mode;
     57   if (scope->is_function_scope() && scope->function() != NULL) {
     58     Variable* var = scope->function()->proxy()->var();
     59     if (!var->is_used()) {
     60       function_name_info = UNUSED;
     61     } else if (var->IsContextSlot()) {
     62       function_name_info = CONTEXT;
     63     } else {
     64       DCHECK(var->IsStackLocal());
     65       function_name_info = STACK;
     66     }
     67     function_variable_mode = var->mode();
     68   } else {
     69     function_name_info = NONE;
     70     function_variable_mode = VAR;
     71   }
     72   DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
     73 
     74   const bool has_function_name = function_name_info != NONE;
     75   const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
     76   const int parameter_count = scope->num_parameters();
     77   const int length = kVariablePartIndex + parameter_count +
     78                      (1 + stack_local_count) + 2 * context_local_count +
     79                      2 * context_global_count +
     80                      3 * strong_mode_free_variable_count +
     81                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
     82 
     83   Factory* factory = isolate->factory();
     84   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
     85 
     86   bool has_simple_parameters =
     87       scope->is_function_scope() && scope->has_simple_parameters();
     88 
     89   // Encode the flags.
     90   int flags = ScopeTypeField::encode(scope->scope_type()) |
     91               CallsEvalField::encode(scope->calls_eval()) |
     92               LanguageModeField::encode(scope->language_mode()) |
     93               DeclarationScopeField::encode(scope->is_declaration_scope()) |
     94               ReceiverVariableField::encode(receiver_info) |
     95               HasNewTargetField::encode(has_new_target) |
     96               FunctionVariableField::encode(function_name_info) |
     97               FunctionVariableMode::encode(function_variable_mode) |
     98               AsmModuleField::encode(scope->asm_module()) |
     99               AsmFunctionField::encode(scope->asm_function()) |
    100               HasSimpleParametersField::encode(has_simple_parameters) |
    101               FunctionKindField::encode(scope->function_kind());
    102   scope_info->SetFlags(flags);
    103   scope_info->SetParameterCount(parameter_count);
    104   scope_info->SetStackLocalCount(stack_local_count);
    105   scope_info->SetContextLocalCount(context_local_count);
    106   scope_info->SetContextGlobalCount(context_global_count);
    107   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
    108 
    109   int index = kVariablePartIndex;
    110   // Add parameters.
    111   DCHECK(index == scope_info->ParameterEntriesIndex());
    112   for (int i = 0; i < parameter_count; ++i) {
    113     scope_info->set(index++, *scope->parameter(i)->name());
    114   }
    115 
    116   // Add stack locals' names. We are assuming that the stack locals'
    117   // slots are allocated in increasing order, so we can simply add
    118   // them to the ScopeInfo object.
    119   int first_slot_index;
    120   if (stack_local_count > 0) {
    121     first_slot_index = stack_locals[0]->index();
    122   } else {
    123     first_slot_index = 0;
    124   }
    125   DCHECK(index == scope_info->StackLocalFirstSlotIndex());
    126   scope_info->set(index++, Smi::FromInt(first_slot_index));
    127   DCHECK(index == scope_info->StackLocalEntriesIndex());
    128   for (int i = 0; i < stack_local_count; ++i) {
    129     DCHECK(stack_locals[i]->index() == first_slot_index + i);
    130     scope_info->set(index++, *stack_locals[i]->name());
    131   }
    132 
    133   // Due to usage analysis, context-allocated locals are not necessarily in
    134   // increasing order: Some of them may be parameters which are allocated before
    135   // the non-parameter locals. When the non-parameter locals are sorted
    136   // according to usage, the allocated slot indices may not be in increasing
    137   // order with the variable list anymore. Thus, we first need to sort them by
    138   // context slot index before adding them to the ScopeInfo object.
    139   context_locals.Sort(&Variable::CompareIndex);
    140 
    141   // Add context locals' names.
    142   DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
    143   for (int i = 0; i < context_local_count; ++i) {
    144     scope_info->set(index++, *context_locals[i]->name());
    145   }
    146 
    147   // Add context globals' names.
    148   DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
    149   for (int i = 0; i < context_global_count; ++i) {
    150     scope_info->set(index++, *context_globals[i]->name());
    151   }
    152 
    153   // Add context locals' info.
    154   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
    155   for (int i = 0; i < context_local_count; ++i) {
    156     Variable* var = context_locals[i];
    157     uint32_t value =
    158         ContextLocalMode::encode(var->mode()) |
    159         ContextLocalInitFlag::encode(var->initialization_flag()) |
    160         ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
    161     scope_info->set(index++, Smi::FromInt(value));
    162   }
    163 
    164   // Add context globals' info.
    165   DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
    166   for (int i = 0; i < context_global_count; ++i) {
    167     Variable* var = context_globals[i];
    168     // TODO(ishell): do we need this kind of info for globals here?
    169     uint32_t value =
    170         ContextLocalMode::encode(var->mode()) |
    171         ContextLocalInitFlag::encode(var->initialization_flag()) |
    172         ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
    173     scope_info->set(index++, Smi::FromInt(value));
    174   }
    175 
    176   DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
    177   for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    178     scope_info->set(index++, *strong_mode_free_variables[i]->name());
    179   }
    180 
    181   DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
    182   for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    183     // Unfortunately, the source code positions are stored as int even though
    184     // int32_t would be enough (given the maximum source code length).
    185     Handle<Object> start_position = factory->NewNumberFromInt(
    186         static_cast<int32_t>(strong_mode_free_variables[i]
    187                                  ->strong_mode_reference_start_position()));
    188     scope_info->set(index++, *start_position);
    189     Handle<Object> end_position = factory->NewNumberFromInt(
    190         static_cast<int32_t>(strong_mode_free_variables[i]
    191                                  ->strong_mode_reference_end_position()));
    192     scope_info->set(index++, *end_position);
    193   }
    194 
    195   // If the receiver is allocated, add its index.
    196   DCHECK(index == scope_info->ReceiverEntryIndex());
    197   if (has_receiver) {
    198     int var_index = scope->receiver()->index();
    199     scope_info->set(index++, Smi::FromInt(var_index));
    200     // ?? DCHECK(receiver_info != CONTEXT || var_index ==
    201     // scope_info->ContextLength() - 1);
    202   }
    203 
    204   // If present, add the function variable name and its index.
    205   DCHECK(index == scope_info->FunctionNameEntryIndex());
    206   if (has_function_name) {
    207     int var_index = scope->function()->proxy()->var()->index();
    208     scope_info->set(index++, *scope->function()->proxy()->name());
    209     scope_info->set(index++, Smi::FromInt(var_index));
    210     DCHECK(function_name_info != CONTEXT ||
    211            var_index == scope_info->ContextLength() - 1);
    212   }
    213 
    214   DCHECK(index == scope_info->length());
    215   DCHECK(scope->num_parameters() == scope_info->ParameterCount());
    216   DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
    217          (scope->num_heap_slots() == kVariablePartIndex &&
    218           scope_info->ContextLength() == 0));
    219   return scope_info;
    220 }
    221 
    222 
    223 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
    224   DCHECK(isolate->bootstrapper()->IsActive());
    225 
    226   const int stack_local_count = 0;
    227   const int context_local_count = 1;
    228   const int context_global_count = 0;
    229   const int strong_mode_free_variable_count = 0;
    230   const bool has_simple_parameters = true;
    231   const VariableAllocationInfo receiver_info = CONTEXT;
    232   const VariableAllocationInfo function_name_info = NONE;
    233   const VariableMode function_variable_mode = VAR;
    234   const bool has_function_name = false;
    235   const bool has_receiver = true;
    236   const int parameter_count = 0;
    237   const int length = kVariablePartIndex + parameter_count +
    238                      (1 + stack_local_count) + 2 * context_local_count +
    239                      2 * context_global_count +
    240                      3 * strong_mode_free_variable_count +
    241                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
    242 
    243   Factory* factory = isolate->factory();
    244   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
    245 
    246   // Encode the flags.
    247   int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
    248               CallsEvalField::encode(false) |
    249               LanguageModeField::encode(SLOPPY) |
    250               DeclarationScopeField::encode(true) |
    251               ReceiverVariableField::encode(receiver_info) |
    252               FunctionVariableField::encode(function_name_info) |
    253               FunctionVariableMode::encode(function_variable_mode) |
    254               AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
    255               HasSimpleParametersField::encode(has_simple_parameters) |
    256               FunctionKindField::encode(FunctionKind::kNormalFunction);
    257   scope_info->SetFlags(flags);
    258   scope_info->SetParameterCount(parameter_count);
    259   scope_info->SetStackLocalCount(stack_local_count);
    260   scope_info->SetContextLocalCount(context_local_count);
    261   scope_info->SetContextGlobalCount(context_global_count);
    262   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
    263 
    264   int index = kVariablePartIndex;
    265   const int first_slot_index = 0;
    266   DCHECK(index == scope_info->StackLocalFirstSlotIndex());
    267   scope_info->set(index++, Smi::FromInt(first_slot_index));
    268   DCHECK(index == scope_info->StackLocalEntriesIndex());
    269 
    270   // Here we add info for context-allocated "this".
    271   DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
    272   scope_info->set(index++, *isolate->factory()->this_string());
    273   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
    274   const uint32_t value = ContextLocalMode::encode(CONST) |
    275                          ContextLocalInitFlag::encode(kCreatedInitialized) |
    276                          ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
    277   scope_info->set(index++, Smi::FromInt(value));
    278 
    279   DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
    280   DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
    281 
    282   // And here we record that this scopeinfo binds a receiver.
    283   DCHECK(index == scope_info->ReceiverEntryIndex());
    284   const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
    285   scope_info->set(index++, Smi::FromInt(receiver_index));
    286 
    287   DCHECK(index == scope_info->FunctionNameEntryIndex());
    288 
    289   DCHECK_EQ(index, scope_info->length());
    290   DCHECK_EQ(scope_info->ParameterCount(), 0);
    291   DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
    292 
    293   return scope_info;
    294 }
    295 
    296 
    297 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
    298   return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
    299 }
    300 
    301 
    302 ScopeType ScopeInfo::scope_type() {
    303   DCHECK(length() > 0);
    304   return ScopeTypeField::decode(Flags());
    305 }
    306 
    307 
    308 bool ScopeInfo::CallsEval() {
    309   return length() > 0 && CallsEvalField::decode(Flags());
    310 }
    311 
    312 
    313 LanguageMode ScopeInfo::language_mode() {
    314   return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
    315 }
    316 
    317 
    318 bool ScopeInfo::is_declaration_scope() {
    319   return DeclarationScopeField::decode(Flags());
    320 }
    321 
    322 
    323 int ScopeInfo::LocalCount() {
    324   return StackLocalCount() + ContextLocalCount();
    325 }
    326 
    327 
    328 int ScopeInfo::StackSlotCount() {
    329   if (length() > 0) {
    330     bool function_name_stack_slot =
    331         FunctionVariableField::decode(Flags()) == STACK;
    332     return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
    333   }
    334   return 0;
    335 }
    336 
    337 
    338 int ScopeInfo::ContextLength() {
    339   if (length() > 0) {
    340     int context_locals = ContextLocalCount();
    341     int context_globals = ContextGlobalCount();
    342     bool function_name_context_slot =
    343         FunctionVariableField::decode(Flags()) == CONTEXT;
    344     bool has_context = context_locals > 0 || context_globals > 0 ||
    345                        function_name_context_slot ||
    346                        scope_type() == WITH_SCOPE ||
    347                        (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
    348                            is_declaration_scope()) ||
    349                        (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
    350                        scope_type() == MODULE_SCOPE;
    351 
    352     if (has_context) {
    353       return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals +
    354              (function_name_context_slot ? 1 : 0);
    355     }
    356   }
    357   return 0;
    358 }
    359 
    360 
    361 bool ScopeInfo::HasReceiver() {
    362   if (length() > 0) {
    363     return NONE != ReceiverVariableField::decode(Flags());
    364   } else {
    365     return false;
    366   }
    367 }
    368 
    369 
    370 bool ScopeInfo::HasAllocatedReceiver() {
    371   if (length() > 0) {
    372     VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
    373     return allocation == STACK || allocation == CONTEXT;
    374   } else {
    375     return false;
    376   }
    377 }
    378 
    379 
    380 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
    381 
    382 
    383 bool ScopeInfo::HasFunctionName() {
    384   if (length() > 0) {
    385     return NONE != FunctionVariableField::decode(Flags());
    386   } else {
    387     return false;
    388   }
    389 }
    390 
    391 
    392 bool ScopeInfo::HasHeapAllocatedLocals() {
    393   if (length() > 0) {
    394     return ContextLocalCount() > 0;
    395   } else {
    396     return false;
    397   }
    398 }
    399 
    400 
    401 bool ScopeInfo::HasContext() {
    402   return ContextLength() > 0;
    403 }
    404 
    405 
    406 String* ScopeInfo::FunctionName() {
    407   DCHECK(HasFunctionName());
    408   return String::cast(get(FunctionNameEntryIndex()));
    409 }
    410 
    411 
    412 String* ScopeInfo::ParameterName(int var) {
    413   DCHECK(0 <= var && var < ParameterCount());
    414   int info_index = ParameterEntriesIndex() + var;
    415   return String::cast(get(info_index));
    416 }
    417 
    418 
    419 String* ScopeInfo::LocalName(int var) {
    420   DCHECK(0 <= var && var < LocalCount());
    421   DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
    422          ContextLocalNameEntriesIndex());
    423   int info_index = StackLocalEntriesIndex() + var;
    424   return String::cast(get(info_index));
    425 }
    426 
    427 
    428 String* ScopeInfo::StackLocalName(int var) {
    429   DCHECK(0 <= var && var < StackLocalCount());
    430   int info_index = StackLocalEntriesIndex() + var;
    431   return String::cast(get(info_index));
    432 }
    433 
    434 
    435 int ScopeInfo::StackLocalIndex(int var) {
    436   DCHECK(0 <= var && var < StackLocalCount());
    437   int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
    438   return first_slot_index + var;
    439 }
    440 
    441 
    442 String* ScopeInfo::ContextLocalName(int var) {
    443   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
    444   int info_index = ContextLocalNameEntriesIndex() + var;
    445   return String::cast(get(info_index));
    446 }
    447 
    448 
    449 VariableMode ScopeInfo::ContextLocalMode(int var) {
    450   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
    451   int info_index = ContextLocalInfoEntriesIndex() + var;
    452   int value = Smi::cast(get(info_index))->value();
    453   return ContextLocalMode::decode(value);
    454 }
    455 
    456 
    457 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
    458   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
    459   int info_index = ContextLocalInfoEntriesIndex() + var;
    460   int value = Smi::cast(get(info_index))->value();
    461   return ContextLocalInitFlag::decode(value);
    462 }
    463 
    464 
    465 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
    466   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
    467   int info_index = ContextLocalInfoEntriesIndex() + var;
    468   int value = Smi::cast(get(info_index))->value();
    469   return ContextLocalMaybeAssignedFlag::decode(value);
    470 }
    471 
    472 
    473 bool ScopeInfo::LocalIsSynthetic(int var) {
    474   DCHECK(0 <= var && var < LocalCount());
    475   // There's currently no flag stored on the ScopeInfo to indicate that a
    476   // variable is a compiler-introduced temporary. However, to avoid conflict
    477   // with user declarations, the current temporaries like .generator_object and
    478   // .result start with a dot, so we can use that as a flag. It's a hack!
    479   Handle<String> name(LocalName(var));
    480   return (name->length() > 0 && name->Get(0) == '.') ||
    481          name->Equals(*GetIsolate()->factory()->this_string());
    482 }
    483 
    484 
    485 String* ScopeInfo::StrongModeFreeVariableName(int var) {
    486   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
    487   int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
    488   return String::cast(get(info_index));
    489 }
    490 
    491 
    492 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
    493   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
    494   int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
    495   int32_t value = 0;
    496   bool ok = get(info_index)->ToInt32(&value);
    497   USE(ok);
    498   DCHECK(ok);
    499   return value;
    500 }
    501 
    502 
    503 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
    504   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
    505   int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
    506   int32_t value = 0;
    507   bool ok = get(info_index)->ToInt32(&value);
    508   USE(ok);
    509   DCHECK(ok);
    510   return value;
    511 }
    512 
    513 
    514 int ScopeInfo::StackSlotIndex(String* name) {
    515   DCHECK(name->IsInternalizedString());
    516   if (length() > 0) {
    517     int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
    518     int start = StackLocalEntriesIndex();
    519     int end = StackLocalEntriesIndex() + StackLocalCount();
    520     for (int i = start; i < end; ++i) {
    521       if (name == get(i)) {
    522         return i - start + first_slot_index;
    523       }
    524     }
    525   }
    526   return -1;
    527 }
    528 
    529 
    530 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
    531                                 Handle<String> name, VariableMode* mode,
    532                                 InitializationFlag* init_flag,
    533                                 MaybeAssignedFlag* maybe_assigned_flag) {
    534   DCHECK(name->IsInternalizedString());
    535   DCHECK(mode != NULL);
    536   DCHECK(init_flag != NULL);
    537   if (scope_info->length() > 0) {
    538     ContextSlotCache* context_slot_cache =
    539         scope_info->GetIsolate()->context_slot_cache();
    540     int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
    541                                             maybe_assigned_flag);
    542     if (result != ContextSlotCache::kNotFound) {
    543       DCHECK(result < scope_info->ContextLength());
    544       return result;
    545     }
    546 
    547     int start = scope_info->ContextLocalNameEntriesIndex();
    548     int end = scope_info->ContextLocalNameEntriesIndex() +
    549               scope_info->ContextLocalCount();
    550     for (int i = start; i < end; ++i) {
    551       if (*name == scope_info->get(i)) {
    552         int var = i - start;
    553         *mode = scope_info->ContextLocalMode(var);
    554         *init_flag = scope_info->ContextLocalInitFlag(var);
    555         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
    556         result = Context::MIN_CONTEXT_SLOTS + var;
    557 
    558         context_slot_cache->Update(scope_info, name, *mode, *init_flag,
    559                                    *maybe_assigned_flag, result);
    560         DCHECK(result < scope_info->ContextLength());
    561         return result;
    562       }
    563     }
    564     // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
    565     context_slot_cache->Update(scope_info, name, TEMPORARY,
    566                                kNeedsInitialization, kNotAssigned, -1);
    567   }
    568   return -1;
    569 }
    570 
    571 
    572 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info,
    573                                       Handle<String> name, VariableMode* mode,
    574                                       InitializationFlag* init_flag,
    575                                       MaybeAssignedFlag* maybe_assigned_flag) {
    576   DCHECK(name->IsInternalizedString());
    577   DCHECK(mode != NULL);
    578   DCHECK(init_flag != NULL);
    579   if (scope_info->length() > 0) {
    580     // This is to ensure that ContextLocalMode() and co. queries would work.
    581     DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
    582               scope_info->ContextLocalNameEntriesIndex() +
    583                   scope_info->ContextLocalCount());
    584     int base = scope_info->ContextLocalNameEntriesIndex();
    585     int start = scope_info->ContextGlobalNameEntriesIndex();
    586     int end = scope_info->ContextGlobalNameEntriesIndex() +
    587               scope_info->ContextGlobalCount();
    588     for (int i = start; i < end; ++i) {
    589       if (*name == scope_info->get(i)) {
    590         int var = i - base;
    591         *mode = scope_info->ContextLocalMode(var);
    592         *init_flag = scope_info->ContextLocalInitFlag(var);
    593         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
    594         int result = Context::MIN_CONTEXT_SLOTS + var;
    595         DCHECK(result < scope_info->ContextLength());
    596         return result;
    597       }
    598     }
    599   }
    600   return -1;
    601 }
    602 
    603 
    604 String* ScopeInfo::ContextSlotName(int slot_index) {
    605   int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
    606   DCHECK_LE(0, var);
    607   DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount());
    608   return ContextLocalName(var);
    609 }
    610 
    611 
    612 int ScopeInfo::ParameterIndex(String* name) {
    613   DCHECK(name->IsInternalizedString());
    614   if (length() > 0) {
    615     // We must read parameters from the end since for
    616     // multiply declared parameters the value of the
    617     // last declaration of that parameter is used
    618     // inside a function (and thus we need to look
    619     // at the last index). Was bug# 1110337.
    620     int start = ParameterEntriesIndex();
    621     int end = ParameterEntriesIndex() + ParameterCount();
    622     for (int i = end - 1; i >= start; --i) {
    623       if (name == get(i)) {
    624         return i - start;
    625       }
    626     }
    627   }
    628   return -1;
    629 }
    630 
    631 
    632 int ScopeInfo::ReceiverContextSlotIndex() {
    633   if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
    634     return Smi::cast(get(ReceiverEntryIndex()))->value();
    635   return -1;
    636 }
    637 
    638 
    639 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
    640   DCHECK(name->IsInternalizedString());
    641   DCHECK(mode != NULL);
    642   if (length() > 0) {
    643     if (FunctionVariableField::decode(Flags()) == CONTEXT &&
    644         FunctionName() == name) {
    645       *mode = FunctionVariableMode::decode(Flags());
    646       return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
    647     }
    648   }
    649   return -1;
    650 }
    651 
    652 
    653 FunctionKind ScopeInfo::function_kind() {
    654   return FunctionKindField::decode(Flags());
    655 }
    656 
    657 
    658 int ScopeInfo::ParameterEntriesIndex() {
    659   DCHECK(length() > 0);
    660   return kVariablePartIndex;
    661 }
    662 
    663 
    664 int ScopeInfo::StackLocalFirstSlotIndex() {
    665   return ParameterEntriesIndex() + ParameterCount();
    666 }
    667 
    668 
    669 int ScopeInfo::StackLocalEntriesIndex() {
    670   return StackLocalFirstSlotIndex() + 1;
    671 }
    672 
    673 
    674 int ScopeInfo::ContextLocalNameEntriesIndex() {
    675   return StackLocalEntriesIndex() + StackLocalCount();
    676 }
    677 
    678 
    679 int ScopeInfo::ContextGlobalNameEntriesIndex() {
    680   return ContextLocalNameEntriesIndex() + ContextLocalCount();
    681 }
    682 
    683 
    684 int ScopeInfo::ContextLocalInfoEntriesIndex() {
    685   return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
    686 }
    687 
    688 
    689 int ScopeInfo::ContextGlobalInfoEntriesIndex() {
    690   return ContextLocalInfoEntriesIndex() + ContextLocalCount();
    691 }
    692 
    693 
    694 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
    695   return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
    696 }
    697 
    698 
    699 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
    700   return StrongModeFreeVariableNameEntriesIndex() +
    701          StrongModeFreeVariableCount();
    702 }
    703 
    704 
    705 int ScopeInfo::ReceiverEntryIndex() {
    706   return StrongModeFreeVariablePositionEntriesIndex() +
    707          2 * StrongModeFreeVariableCount();
    708 }
    709 
    710 
    711 int ScopeInfo::FunctionNameEntryIndex() {
    712   return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
    713 }
    714 
    715 
    716 int ContextSlotCache::Hash(Object* data, String* name) {
    717   // Uses only lower 32 bits if pointers are larger.
    718   uintptr_t addr_hash =
    719       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
    720   return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
    721 }
    722 
    723 
    724 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
    725                              InitializationFlag* init_flag,
    726                              MaybeAssignedFlag* maybe_assigned_flag) {
    727   int index = Hash(data, name);
    728   Key& key = keys_[index];
    729   if ((key.data == data) && key.name->Equals(name)) {
    730     Value result(values_[index]);
    731     if (mode != NULL) *mode = result.mode();
    732     if (init_flag != NULL) *init_flag = result.initialization_flag();
    733     if (maybe_assigned_flag != NULL)
    734       *maybe_assigned_flag = result.maybe_assigned_flag();
    735     return result.index() + kNotFound;
    736   }
    737   return kNotFound;
    738 }
    739 
    740 
    741 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
    742                               VariableMode mode, InitializationFlag init_flag,
    743                               MaybeAssignedFlag maybe_assigned_flag,
    744                               int slot_index) {
    745   DisallowHeapAllocation no_gc;
    746   Handle<String> internalized_name;
    747   DCHECK(slot_index > kNotFound);
    748   if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
    749       ToHandle(&internalized_name)) {
    750     int index = Hash(*data, *internalized_name);
    751     Key& key = keys_[index];
    752     key.data = *data;
    753     key.name = *internalized_name;
    754     // Please note value only takes a uint as index.
    755     values_[index] = Value(mode, init_flag, maybe_assigned_flag,
    756                            slot_index - kNotFound).raw();
    757 #ifdef DEBUG
    758     ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
    759 #endif
    760   }
    761 }
    762 
    763 
    764 void ContextSlotCache::Clear() {
    765   for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
    766 }
    767 
    768 
    769 #ifdef DEBUG
    770 
    771 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
    772                                      VariableMode mode,
    773                                      InitializationFlag init_flag,
    774                                      MaybeAssignedFlag maybe_assigned_flag,
    775                                      int slot_index) {
    776   DisallowHeapAllocation no_gc;
    777   Handle<String> internalized_name;
    778   if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
    779       ToHandle(&internalized_name)) {
    780     int index = Hash(*data, *name);
    781     Key& key = keys_[index];
    782     DCHECK(key.data == *data);
    783     DCHECK(key.name->Equals(*name));
    784     Value result(values_[index]);
    785     DCHECK(result.mode() == mode);
    786     DCHECK(result.initialization_flag() == init_flag);
    787     DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
    788     DCHECK(result.index() + kNotFound == slot_index);
    789   }
    790 }
    791 
    792 
    793 static void PrintList(const char* list_name,
    794                       int nof_internal_slots,
    795                       int start,
    796                       int end,
    797                       ScopeInfo* scope_info) {
    798   if (start < end) {
    799     PrintF("\n  // %s\n", list_name);
    800     if (nof_internal_slots > 0) {
    801       PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
    802     }
    803     for (int i = nof_internal_slots; start < end; ++i, ++start) {
    804       PrintF("  %2d ", i);
    805       String::cast(scope_info->get(start))->ShortPrint();
    806       PrintF("\n");
    807     }
    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, ParameterEntriesIndex(),
    823               ParameterEntriesIndex() + ParameterCount(), this);
    824     PrintList("stack slots", 0, StackLocalEntriesIndex(),
    825               StackLocalEntriesIndex() + StackLocalCount(), this);
    826     PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
    827               ContextLocalNameEntriesIndex(),
    828               ContextLocalNameEntriesIndex() + ContextLocalCount(), this);
    829   }
    830 
    831   PrintF("}\n");
    832 }
    833 #endif  // DEBUG
    834 
    835 
    836 //---------------------------------------------------------------------------
    837 // ModuleInfo.
    838 
    839 Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
    840                                       ModuleDescriptor* descriptor,
    841                                       Scope* scope) {
    842   Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
    843   info->set_host_index(descriptor->Index());
    844   int i = 0;
    845   for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
    846        it.Advance(), ++i) {
    847     Variable* var = scope->LookupLocal(it.local_name());
    848     info->set_name(i, *(it.export_name()->string()));
    849     info->set_mode(i, var->mode());
    850     DCHECK(var->index() >= 0);
    851     info->set_index(i, var->index());
    852   }
    853   DCHECK(i == info->length());
    854   return info;
    855 }
    856 
    857 }  // namespace internal
    858 }  // namespace v8
    859