Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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/v8.h"
      6 
      7 #include "src/scopes.h"
      8 
      9 #include "src/accessors.h"
     10 #include "src/bootstrapper.h"
     11 #include "src/compiler.h"
     12 #include "src/messages.h"
     13 #include "src/scopeinfo.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 // ----------------------------------------------------------------------------
     19 // Implementation of LocalsMap
     20 //
     21 // Note: We are storing the handle locations as key values in the hash map.
     22 //       When inserting a new variable via Declare(), we rely on the fact that
     23 //       the handle location remains alive for the duration of that variable
     24 //       use. Because a Variable holding a handle with the same location exists
     25 //       this is ensured.
     26 
     27 static bool Match(void* key1, void* key2) {
     28   String* name1 = *reinterpret_cast<String**>(key1);
     29   String* name2 = *reinterpret_cast<String**>(key2);
     30   ASSERT(name1->IsInternalizedString());
     31   ASSERT(name2->IsInternalizedString());
     32   return name1 == name2;
     33 }
     34 
     35 
     36 VariableMap::VariableMap(Zone* zone)
     37     : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
     38       zone_(zone) {}
     39 VariableMap::~VariableMap() {}
     40 
     41 
     42 Variable* VariableMap::Declare(
     43     Scope* scope,
     44     Handle<String> name,
     45     VariableMode mode,
     46     bool is_valid_lhs,
     47     Variable::Kind kind,
     48     InitializationFlag initialization_flag,
     49     Interface* interface) {
     50   Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
     51                                  ZoneAllocationPolicy(zone()));
     52   if (p->value == NULL) {
     53     // The variable has not been declared yet -> insert it.
     54     ASSERT(p->key == name.location());
     55     p->value = new(zone()) Variable(scope,
     56                                     name,
     57                                     mode,
     58                                     is_valid_lhs,
     59                                     kind,
     60                                     initialization_flag,
     61                                     interface);
     62   }
     63   return reinterpret_cast<Variable*>(p->value);
     64 }
     65 
     66 
     67 Variable* VariableMap::Lookup(Handle<String> name) {
     68   Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
     69                                  ZoneAllocationPolicy(NULL));
     70   if (p != NULL) {
     71     ASSERT(*reinterpret_cast<String**>(p->key) == *name);
     72     ASSERT(p->value != NULL);
     73     return reinterpret_cast<Variable*>(p->value);
     74   }
     75   return NULL;
     76 }
     77 
     78 
     79 // ----------------------------------------------------------------------------
     80 // Implementation of Scope
     81 
     82 Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
     83     : isolate_(zone->isolate()),
     84       inner_scopes_(4, zone),
     85       variables_(zone),
     86       internals_(4, zone),
     87       temps_(4, zone),
     88       params_(4, zone),
     89       unresolved_(16, zone),
     90       decls_(4, zone),
     91       interface_(FLAG_harmony_modules &&
     92                  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
     93                      ? Interface::NewModule(zone) : NULL),
     94       already_resolved_(false),
     95       zone_(zone) {
     96   SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
     97   // The outermost scope must be a global scope.
     98   ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL);
     99   ASSERT(!HasIllegalRedeclaration());
    100 }
    101 
    102 
    103 Scope::Scope(Scope* inner_scope,
    104              ScopeType scope_type,
    105              Handle<ScopeInfo> scope_info,
    106              Zone* zone)
    107     : isolate_(zone->isolate()),
    108       inner_scopes_(4, zone),
    109       variables_(zone),
    110       internals_(4, zone),
    111       temps_(4, zone),
    112       params_(4, zone),
    113       unresolved_(16, zone),
    114       decls_(4, zone),
    115       interface_(NULL),
    116       already_resolved_(true),
    117       zone_(zone) {
    118   SetDefaults(scope_type, NULL, scope_info);
    119   if (!scope_info.is_null()) {
    120     num_heap_slots_ = scope_info_->ContextLength();
    121   }
    122   // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
    123   num_heap_slots_ = Max(num_heap_slots_,
    124                         static_cast<int>(Context::MIN_CONTEXT_SLOTS));
    125   AddInnerScope(inner_scope);
    126 }
    127 
    128 
    129 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
    130     : isolate_(zone->isolate()),
    131       inner_scopes_(1, zone),
    132       variables_(zone),
    133       internals_(0, zone),
    134       temps_(0, zone),
    135       params_(0, zone),
    136       unresolved_(0, zone),
    137       decls_(0, zone),
    138       interface_(NULL),
    139       already_resolved_(true),
    140       zone_(zone) {
    141   SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
    142   AddInnerScope(inner_scope);
    143   ++num_var_or_const_;
    144   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
    145   Variable* variable = variables_.Declare(this,
    146                                           catch_variable_name,
    147                                           VAR,
    148                                           true,  // Valid left-hand side.
    149                                           Variable::NORMAL,
    150                                           kCreatedInitialized);
    151   AllocateHeapSlot(variable);
    152 }
    153 
    154 
    155 void Scope::SetDefaults(ScopeType scope_type,
    156                         Scope* outer_scope,
    157                         Handle<ScopeInfo> scope_info) {
    158   outer_scope_ = outer_scope;
    159   scope_type_ = scope_type;
    160   scope_name_ = isolate_->factory()->empty_string();
    161   dynamics_ = NULL;
    162   receiver_ = NULL;
    163   function_ = NULL;
    164   arguments_ = NULL;
    165   illegal_redecl_ = NULL;
    166   scope_inside_with_ = false;
    167   scope_contains_with_ = false;
    168   scope_calls_eval_ = false;
    169   // Inherit the strict mode from the parent scope.
    170   strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
    171   outer_scope_calls_sloppy_eval_ = false;
    172   inner_scope_calls_eval_ = false;
    173   force_eager_compilation_ = false;
    174   force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
    175       ? outer_scope->has_forced_context_allocation() : false;
    176   num_var_or_const_ = 0;
    177   num_stack_slots_ = 0;
    178   num_heap_slots_ = 0;
    179   num_modules_ = 0;
    180   module_var_ = NULL,
    181   scope_info_ = scope_info;
    182   start_position_ = RelocInfo::kNoPosition;
    183   end_position_ = RelocInfo::kNoPosition;
    184   if (!scope_info.is_null()) {
    185     scope_calls_eval_ = scope_info->CallsEval();
    186     strict_mode_ = scope_info->strict_mode();
    187   }
    188 }
    189 
    190 
    191 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
    192                                     Zone* zone) {
    193   // Reconstruct the outer scope chain from a closure's context chain.
    194   Scope* current_scope = NULL;
    195   Scope* innermost_scope = NULL;
    196   bool contains_with = false;
    197   while (!context->IsNativeContext()) {
    198     if (context->IsWithContext()) {
    199       Scope* with_scope = new(zone) Scope(current_scope,
    200                                           WITH_SCOPE,
    201                                           Handle<ScopeInfo>::null(),
    202                                           zone);
    203       current_scope = with_scope;
    204       // All the inner scopes are inside a with.
    205       contains_with = true;
    206       for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
    207         s->scope_inside_with_ = true;
    208       }
    209     } else if (context->IsGlobalContext()) {
    210       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
    211       current_scope = new(zone) Scope(current_scope,
    212                                       GLOBAL_SCOPE,
    213                                       Handle<ScopeInfo>(scope_info),
    214                                       zone);
    215     } else if (context->IsModuleContext()) {
    216       ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
    217       current_scope = new(zone) Scope(current_scope,
    218                                       MODULE_SCOPE,
    219                                       Handle<ScopeInfo>(scope_info),
    220                                       zone);
    221     } else if (context->IsFunctionContext()) {
    222       ScopeInfo* scope_info = context->closure()->shared()->scope_info();
    223       current_scope = new(zone) Scope(current_scope,
    224                                       FUNCTION_SCOPE,
    225                                       Handle<ScopeInfo>(scope_info),
    226                                       zone);
    227     } else if (context->IsBlockContext()) {
    228       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
    229       current_scope = new(zone) Scope(current_scope,
    230                                       BLOCK_SCOPE,
    231                                       Handle<ScopeInfo>(scope_info),
    232                                       zone);
    233     } else {
    234       ASSERT(context->IsCatchContext());
    235       String* name = String::cast(context->extension());
    236       current_scope = new(zone) Scope(
    237           current_scope, Handle<String>(name), zone);
    238     }
    239     if (contains_with) current_scope->RecordWithStatement();
    240     if (innermost_scope == NULL) innermost_scope = current_scope;
    241 
    242     // Forget about a with when we move to a context for a different function.
    243     if (context->previous()->closure() != context->closure()) {
    244       contains_with = false;
    245     }
    246     context = context->previous();
    247   }
    248 
    249   global_scope->AddInnerScope(current_scope);
    250   global_scope->PropagateScopeInfo(false);
    251   return (innermost_scope == NULL) ? global_scope : innermost_scope;
    252 }
    253 
    254 
    255 bool Scope::Analyze(CompilationInfo* info) {
    256   ASSERT(info->function() != NULL);
    257   Scope* scope = info->function()->scope();
    258   Scope* top = scope;
    259 
    260   // Traverse the scope tree up to the first unresolved scope or the global
    261   // scope and start scope resolution and variable allocation from that scope.
    262   while (!top->is_global_scope() &&
    263          !top->outer_scope()->already_resolved()) {
    264     top = top->outer_scope();
    265   }
    266 
    267   // Allocate the variables.
    268   {
    269     AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
    270     if (!top->AllocateVariables(info, &ast_node_factory)) return false;
    271   }
    272 
    273 #ifdef DEBUG
    274   if (info->isolate()->bootstrapper()->IsActive()
    275           ? FLAG_print_builtin_scopes
    276           : FLAG_print_scopes) {
    277     scope->Print();
    278   }
    279 
    280   if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
    281     PrintF("global : ");
    282     top->interface()->Print();
    283   }
    284 #endif
    285 
    286   info->PrepareForCompilation(scope);
    287   return true;
    288 }
    289 
    290 
    291 void Scope::Initialize() {
    292   ASSERT(!already_resolved());
    293 
    294   // Add this scope as a new inner scope of the outer scope.
    295   if (outer_scope_ != NULL) {
    296     outer_scope_->inner_scopes_.Add(this, zone());
    297     scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
    298   } else {
    299     scope_inside_with_ = is_with_scope();
    300   }
    301 
    302   // Declare convenience variables.
    303   // Declare and allocate receiver (even for the global scope, and even
    304   // if naccesses_ == 0).
    305   // NOTE: When loading parameters in the global scope, we must take
    306   // care not to access them as properties of the global object, but
    307   // instead load them directly from the stack. Currently, the only
    308   // such parameter is 'this' which is passed on the stack when
    309   // invoking scripts
    310   if (is_declaration_scope()) {
    311     Variable* var =
    312         variables_.Declare(this,
    313                            isolate_->factory()->this_string(),
    314                            VAR,
    315                            false,
    316                            Variable::THIS,
    317                            kCreatedInitialized);
    318     var->AllocateTo(Variable::PARAMETER, -1);
    319     receiver_ = var;
    320   } else {
    321     ASSERT(outer_scope() != NULL);
    322     receiver_ = outer_scope()->receiver();
    323   }
    324 
    325   if (is_function_scope()) {
    326     // Declare 'arguments' variable which exists in all functions.
    327     // Note that it might never be accessed, in which case it won't be
    328     // allocated during variable allocation.
    329     variables_.Declare(this,
    330                        isolate_->factory()->arguments_string(),
    331                        VAR,
    332                        true,
    333                        Variable::ARGUMENTS,
    334                        kCreatedInitialized);
    335   }
    336 }
    337 
    338 
    339 Scope* Scope::FinalizeBlockScope() {
    340   ASSERT(is_block_scope());
    341   ASSERT(internals_.is_empty());
    342   ASSERT(temps_.is_empty());
    343   ASSERT(params_.is_empty());
    344 
    345   if (num_var_or_const() > 0) return this;
    346 
    347   // Remove this scope from outer scope.
    348   for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
    349     if (outer_scope_->inner_scopes_[i] == this) {
    350       outer_scope_->inner_scopes_.Remove(i);
    351       break;
    352     }
    353   }
    354 
    355   // Reparent inner scopes.
    356   for (int i = 0; i < inner_scopes_.length(); i++) {
    357     outer_scope()->AddInnerScope(inner_scopes_[i]);
    358   }
    359 
    360   // Move unresolved variables
    361   for (int i = 0; i < unresolved_.length(); i++) {
    362     outer_scope()->unresolved_.Add(unresolved_[i], zone());
    363   }
    364 
    365   return NULL;
    366 }
    367 
    368 
    369 Variable* Scope::LookupLocal(Handle<String> name) {
    370   Variable* result = variables_.Lookup(name);
    371   if (result != NULL || scope_info_.is_null()) {
    372     return result;
    373   }
    374   // If we have a serialized scope info, we might find the variable there.
    375   // There should be no local slot with the given name.
    376   ASSERT(scope_info_->StackSlotIndex(*name) < 0);
    377 
    378   // Check context slot lookup.
    379   VariableMode mode;
    380   Variable::Location location = Variable::CONTEXT;
    381   InitializationFlag init_flag;
    382   int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag);
    383   if (index < 0) {
    384     // Check parameters.
    385     index = scope_info_->ParameterIndex(*name);
    386     if (index < 0) return NULL;
    387 
    388     mode = DYNAMIC;
    389     location = Variable::LOOKUP;
    390     init_flag = kCreatedInitialized;
    391   }
    392 
    393   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
    394                                      init_flag);
    395   var->AllocateTo(location, index);
    396   return var;
    397 }
    398 
    399 
    400 Variable* Scope::LookupFunctionVar(Handle<String> name,
    401                                    AstNodeFactory<AstNullVisitor>* factory) {
    402   if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
    403     return function_->proxy()->var();
    404   } else if (!scope_info_.is_null()) {
    405     // If we are backed by a scope info, try to lookup the variable there.
    406     VariableMode mode;
    407     int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
    408     if (index < 0) return NULL;
    409     Variable* var = new(zone()) Variable(
    410         this, name, mode, true /* is valid LHS */,
    411         Variable::NORMAL, kCreatedInitialized);
    412     VariableProxy* proxy = factory->NewVariableProxy(var);
    413     VariableDeclaration* declaration = factory->NewVariableDeclaration(
    414         proxy, mode, this, RelocInfo::kNoPosition);
    415     DeclareFunctionVar(declaration);
    416     var->AllocateTo(Variable::CONTEXT, index);
    417     return var;
    418   } else {
    419     return NULL;
    420   }
    421 }
    422 
    423 
    424 Variable* Scope::Lookup(Handle<String> name) {
    425   for (Scope* scope = this;
    426        scope != NULL;
    427        scope = scope->outer_scope()) {
    428     Variable* var = scope->LookupLocal(name);
    429     if (var != NULL) return var;
    430   }
    431   return NULL;
    432 }
    433 
    434 
    435 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
    436   ASSERT(!already_resolved());
    437   ASSERT(is_function_scope());
    438   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
    439                                      kCreatedInitialized);
    440   params_.Add(var, zone());
    441 }
    442 
    443 
    444 Variable* Scope::DeclareLocal(Handle<String> name,
    445                               VariableMode mode,
    446                               InitializationFlag init_flag,
    447                               Interface* interface) {
    448   ASSERT(!already_resolved());
    449   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are
    450   // introduces during variable allocation, INTERNAL variables are allocated
    451   // explicitly, and TEMPORARY variables are allocated via NewTemporary().
    452   ASSERT(IsDeclaredVariableMode(mode));
    453   ++num_var_or_const_;
    454   return variables_.Declare(
    455       this, name, mode, true, Variable::NORMAL, init_flag, interface);
    456 }
    457 
    458 
    459 Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
    460   ASSERT(is_global_scope());
    461   return variables_.Declare(this,
    462                             name,
    463                             DYNAMIC_GLOBAL,
    464                             true,
    465                             Variable::NORMAL,
    466                             kCreatedInitialized);
    467 }
    468 
    469 
    470 void Scope::RemoveUnresolved(VariableProxy* var) {
    471   // Most likely (always?) any variable we want to remove
    472   // was just added before, so we search backwards.
    473   for (int i = unresolved_.length(); i-- > 0;) {
    474     if (unresolved_[i] == var) {
    475       unresolved_.Remove(i);
    476       return;
    477     }
    478   }
    479 }
    480 
    481 
    482 Variable* Scope::NewInternal(Handle<String> name) {
    483   ASSERT(!already_resolved());
    484   Variable* var = new(zone()) Variable(this,
    485                                        name,
    486                                        INTERNAL,
    487                                        false,
    488                                        Variable::NORMAL,
    489                                        kCreatedInitialized);
    490   internals_.Add(var, zone());
    491   return var;
    492 }
    493 
    494 
    495 Variable* Scope::NewTemporary(Handle<String> name) {
    496   ASSERT(!already_resolved());
    497   Variable* var = new(zone()) Variable(this,
    498                                        name,
    499                                        TEMPORARY,
    500                                        true,
    501                                        Variable::NORMAL,
    502                                        kCreatedInitialized);
    503   temps_.Add(var, zone());
    504   return var;
    505 }
    506 
    507 
    508 void Scope::AddDeclaration(Declaration* declaration) {
    509   decls_.Add(declaration, zone());
    510 }
    511 
    512 
    513 void Scope::SetIllegalRedeclaration(Expression* expression) {
    514   // Record only the first illegal redeclaration.
    515   if (!HasIllegalRedeclaration()) {
    516     illegal_redecl_ = expression;
    517   }
    518   ASSERT(HasIllegalRedeclaration());
    519 }
    520 
    521 
    522 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
    523   ASSERT(HasIllegalRedeclaration());
    524   illegal_redecl_->Accept(visitor);
    525 }
    526 
    527 
    528 Declaration* Scope::CheckConflictingVarDeclarations() {
    529   int length = decls_.length();
    530   for (int i = 0; i < length; i++) {
    531     Declaration* decl = decls_[i];
    532     if (decl->mode() != VAR) continue;
    533     Handle<String> name = decl->proxy()->name();
    534 
    535     // Iterate through all scopes until and including the declaration scope.
    536     Scope* previous = NULL;
    537     Scope* current = decl->scope();
    538     do {
    539       // There is a conflict if there exists a non-VAR binding.
    540       Variable* other_var = current->variables_.Lookup(name);
    541       if (other_var != NULL && other_var->mode() != VAR) {
    542         return decl;
    543       }
    544       previous = current;
    545       current = current->outer_scope_;
    546     } while (!previous->is_declaration_scope());
    547   }
    548   return NULL;
    549 }
    550 
    551 
    552 class VarAndOrder {
    553  public:
    554   VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
    555   Variable* var() const { return var_; }
    556   int order() const { return order_; }
    557   static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
    558     return a->order_ - b->order_;
    559   }
    560 
    561  private:
    562   Variable* var_;
    563   int order_;
    564 };
    565 
    566 
    567 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
    568                                          ZoneList<Variable*>* context_locals) {
    569   ASSERT(stack_locals != NULL);
    570   ASSERT(context_locals != NULL);
    571 
    572   // Collect internals which are always allocated on the heap.
    573   for (int i = 0; i < internals_.length(); i++) {
    574     Variable* var = internals_[i];
    575     if (var->is_used()) {
    576       ASSERT(var->IsContextSlot());
    577       context_locals->Add(var, zone());
    578     }
    579   }
    580 
    581   // Collect temporaries which are always allocated on the stack, unless the
    582   // context as a whole has forced context allocation.
    583   for (int i = 0; i < temps_.length(); i++) {
    584     Variable* var = temps_[i];
    585     if (var->is_used()) {
    586       if (var->IsContextSlot()) {
    587         ASSERT(has_forced_context_allocation());
    588         context_locals->Add(var, zone());
    589       } else {
    590         ASSERT(var->IsStackLocal());
    591         stack_locals->Add(var, zone());
    592       }
    593     }
    594   }
    595 
    596   // Collect declared local variables.
    597   ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
    598   for (VariableMap::Entry* p = variables_.Start();
    599        p != NULL;
    600        p = variables_.Next(p)) {
    601     Variable* var = reinterpret_cast<Variable*>(p->value);
    602     if (var->is_used()) {
    603       vars.Add(VarAndOrder(var, p->order), zone());
    604     }
    605   }
    606   vars.Sort(VarAndOrder::Compare);
    607   int var_count = vars.length();
    608   for (int i = 0; i < var_count; i++) {
    609     Variable* var = vars[i].var();
    610     if (var->IsStackLocal()) {
    611       stack_locals->Add(var, zone());
    612     } else if (var->IsContextSlot()) {
    613       context_locals->Add(var, zone());
    614     }
    615   }
    616 }
    617 
    618 
    619 bool Scope::AllocateVariables(CompilationInfo* info,
    620                               AstNodeFactory<AstNullVisitor>* factory) {
    621   // 1) Propagate scope information.
    622   bool outer_scope_calls_sloppy_eval = false;
    623   if (outer_scope_ != NULL) {
    624     outer_scope_calls_sloppy_eval =
    625         outer_scope_->outer_scope_calls_sloppy_eval() |
    626         outer_scope_->calls_sloppy_eval();
    627   }
    628   PropagateScopeInfo(outer_scope_calls_sloppy_eval);
    629 
    630   // 2) Allocate module instances.
    631   if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
    632     ASSERT(num_modules_ == 0);
    633     AllocateModulesRecursively(this);
    634   }
    635 
    636   // 3) Resolve variables.
    637   if (!ResolveVariablesRecursively(info, factory)) return false;
    638 
    639   // 4) Allocate variables.
    640   AllocateVariablesRecursively();
    641 
    642   return true;
    643 }
    644 
    645 
    646 bool Scope::HasTrivialContext() const {
    647   // A function scope has a trivial context if it always is the global
    648   // context. We iteratively scan out the context chain to see if
    649   // there is anything that makes this scope non-trivial; otherwise we
    650   // return true.
    651   for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
    652     if (scope->is_eval_scope()) return false;
    653     if (scope->scope_inside_with_) return false;
    654     if (scope->num_heap_slots_ > 0) return false;
    655   }
    656   return true;
    657 }
    658 
    659 
    660 bool Scope::HasTrivialOuterContext() const {
    661   Scope* outer = outer_scope_;
    662   if (outer == NULL) return true;
    663   // Note that the outer context may be trivial in general, but the current
    664   // scope may be inside a 'with' statement in which case the outer context
    665   // for this scope is not trivial.
    666   return !scope_inside_with_ && outer->HasTrivialContext();
    667 }
    668 
    669 
    670 bool Scope::HasLazyCompilableOuterContext() const {
    671   Scope* outer = outer_scope_;
    672   if (outer == NULL) return true;
    673   // We have to prevent lazy compilation if this scope is inside a with scope
    674   // and all declaration scopes between them have empty contexts. Such
    675   // declaration scopes may become invisible during scope info deserialization.
    676   outer = outer->DeclarationScope();
    677   bool found_non_trivial_declarations = false;
    678   for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
    679     if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
    680     if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
    681       found_non_trivial_declarations = true;
    682     }
    683   }
    684   return true;
    685 }
    686 
    687 
    688 bool Scope::AllowsLazyCompilation() const {
    689   return !force_eager_compilation_ && HasLazyCompilableOuterContext();
    690 }
    691 
    692 
    693 bool Scope::AllowsLazyCompilationWithoutContext() const {
    694   return !force_eager_compilation_ && HasTrivialOuterContext();
    695 }
    696 
    697 
    698 int Scope::ContextChainLength(Scope* scope) {
    699   int n = 0;
    700   for (Scope* s = this; s != scope; s = s->outer_scope_) {
    701     ASSERT(s != NULL);  // scope must be in the scope chain
    702     if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
    703     // Catch and module scopes always have heap slots.
    704     ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0);
    705     ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0);
    706   }
    707   return n;
    708 }
    709 
    710 
    711 Scope* Scope::GlobalScope() {
    712   Scope* scope = this;
    713   while (!scope->is_global_scope()) {
    714     scope = scope->outer_scope();
    715   }
    716   return scope;
    717 }
    718 
    719 
    720 Scope* Scope::DeclarationScope() {
    721   Scope* scope = this;
    722   while (!scope->is_declaration_scope()) {
    723     scope = scope->outer_scope();
    724   }
    725   return scope;
    726 }
    727 
    728 
    729 Handle<ScopeInfo> Scope::GetScopeInfo() {
    730   if (scope_info_.is_null()) {
    731     scope_info_ = ScopeInfo::Create(this, zone());
    732   }
    733   return scope_info_;
    734 }
    735 
    736 
    737 void Scope::GetNestedScopeChain(
    738     List<Handle<ScopeInfo> >* chain,
    739     int position) {
    740   if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
    741 
    742   for (int i = 0; i < inner_scopes_.length(); i++) {
    743     Scope* scope = inner_scopes_[i];
    744     int beg_pos = scope->start_position();
    745     int end_pos = scope->end_position();
    746     ASSERT(beg_pos >= 0 && end_pos >= 0);
    747     if (beg_pos <= position && position < end_pos) {
    748       scope->GetNestedScopeChain(chain, position);
    749       return;
    750     }
    751   }
    752 }
    753 
    754 
    755 #ifdef DEBUG
    756 static const char* Header(ScopeType scope_type) {
    757   switch (scope_type) {
    758     case EVAL_SCOPE: return "eval";
    759     case FUNCTION_SCOPE: return "function";
    760     case MODULE_SCOPE: return "module";
    761     case GLOBAL_SCOPE: return "global";
    762     case CATCH_SCOPE: return "catch";
    763     case BLOCK_SCOPE: return "block";
    764     case WITH_SCOPE: return "with";
    765   }
    766   UNREACHABLE();
    767   return NULL;
    768 }
    769 
    770 
    771 static void Indent(int n, const char* str) {
    772   PrintF("%*s%s", n, "", str);
    773 }
    774 
    775 
    776 static void PrintName(Handle<String> name) {
    777   SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
    778   PrintF("%s", s.get());
    779 }
    780 
    781 
    782 static void PrintLocation(Variable* var) {
    783   switch (var->location()) {
    784     case Variable::UNALLOCATED:
    785       break;
    786     case Variable::PARAMETER:
    787       PrintF("parameter[%d]", var->index());
    788       break;
    789     case Variable::LOCAL:
    790       PrintF("local[%d]", var->index());
    791       break;
    792     case Variable::CONTEXT:
    793       PrintF("context[%d]", var->index());
    794       break;
    795     case Variable::LOOKUP:
    796       PrintF("lookup");
    797       break;
    798   }
    799 }
    800 
    801 
    802 static void PrintVar(int indent, Variable* var) {
    803   if (var->is_used() || !var->IsUnallocated()) {
    804     Indent(indent, Variable::Mode2String(var->mode()));
    805     PrintF(" ");
    806     PrintName(var->name());
    807     PrintF(";  // ");
    808     PrintLocation(var);
    809     if (var->has_forced_context_allocation()) {
    810       if (!var->IsUnallocated()) PrintF(", ");
    811       PrintF("forced context allocation");
    812     }
    813     PrintF("\n");
    814   }
    815 }
    816 
    817 
    818 static void PrintMap(int indent, VariableMap* map) {
    819   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
    820     Variable* var = reinterpret_cast<Variable*>(p->value);
    821     PrintVar(indent, var);
    822   }
    823 }
    824 
    825 
    826 void Scope::Print(int n) {
    827   int n0 = (n > 0 ? n : 0);
    828   int n1 = n0 + 2;  // indentation
    829 
    830   // Print header.
    831   Indent(n0, Header(scope_type_));
    832   if (scope_name_->length() > 0) {
    833     PrintF(" ");
    834     PrintName(scope_name_);
    835   }
    836 
    837   // Print parameters, if any.
    838   if (is_function_scope()) {
    839     PrintF(" (");
    840     for (int i = 0; i < params_.length(); i++) {
    841       if (i > 0) PrintF(", ");
    842       PrintName(params_[i]->name());
    843     }
    844     PrintF(")");
    845   }
    846 
    847   PrintF(" { // (%d, %d)\n", start_position(), end_position());
    848 
    849   // Function name, if any (named function literals, only).
    850   if (function_ != NULL) {
    851     Indent(n1, "// (local) function name: ");
    852     PrintName(function_->proxy()->name());
    853     PrintF("\n");
    854   }
    855 
    856   // Scope info.
    857   if (HasTrivialOuterContext()) {
    858     Indent(n1, "// scope has trivial outer context\n");
    859   }
    860   if (strict_mode() == STRICT) {
    861     Indent(n1, "// strict mode scope\n");
    862   }
    863   if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
    864   if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
    865   if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
    866   if (outer_scope_calls_sloppy_eval_) {
    867     Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
    868   }
    869   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
    870   if (num_stack_slots_ > 0) { Indent(n1, "// ");
    871   PrintF("%d stack slots\n", num_stack_slots_); }
    872   if (num_heap_slots_ > 0) { Indent(n1, "// ");
    873   PrintF("%d heap slots\n", num_heap_slots_); }
    874 
    875   // Print locals.
    876   if (function_ != NULL) {
    877     Indent(n1, "// function var:\n");
    878     PrintVar(n1, function_->proxy()->var());
    879   }
    880 
    881   if (temps_.length() > 0) {
    882     Indent(n1, "// temporary vars:\n");
    883     for (int i = 0; i < temps_.length(); i++) {
    884       PrintVar(n1, temps_[i]);
    885     }
    886   }
    887 
    888   if (internals_.length() > 0) {
    889     Indent(n1, "// internal vars:\n");
    890     for (int i = 0; i < internals_.length(); i++) {
    891       PrintVar(n1, internals_[i]);
    892     }
    893   }
    894 
    895   if (variables_.Start() != NULL) {
    896     Indent(n1, "// local vars:\n");
    897     PrintMap(n1, &variables_);
    898   }
    899 
    900   if (dynamics_ != NULL) {
    901     Indent(n1, "// dynamic vars:\n");
    902     PrintMap(n1, dynamics_->GetMap(DYNAMIC));
    903     PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
    904     PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
    905   }
    906 
    907   // Print inner scopes (disable by providing negative n).
    908   if (n >= 0) {
    909     for (int i = 0; i < inner_scopes_.length(); i++) {
    910       PrintF("\n");
    911       inner_scopes_[i]->Print(n1);
    912     }
    913   }
    914 
    915   Indent(n0, "}\n");
    916 }
    917 #endif  // DEBUG
    918 
    919 
    920 Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
    921   if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
    922   VariableMap* map = dynamics_->GetMap(mode);
    923   Variable* var = map->Lookup(name);
    924   if (var == NULL) {
    925     // Declare a new non-local.
    926     InitializationFlag init_flag = (mode == VAR)
    927         ? kCreatedInitialized : kNeedsInitialization;
    928     var = map->Declare(NULL,
    929                        name,
    930                        mode,
    931                        true,
    932                        Variable::NORMAL,
    933                        init_flag);
    934     // Allocate it by giving it a dynamic lookup.
    935     var->AllocateTo(Variable::LOOKUP, -1);
    936   }
    937   return var;
    938 }
    939 
    940 
    941 Variable* Scope::LookupRecursive(Handle<String> name,
    942                                  BindingKind* binding_kind,
    943                                  AstNodeFactory<AstNullVisitor>* factory) {
    944   ASSERT(binding_kind != NULL);
    945   if (already_resolved() && is_with_scope()) {
    946     // Short-cut: if the scope is deserialized from a scope info, variable
    947     // allocation is already fixed.  We can simply return with dynamic lookup.
    948     *binding_kind = DYNAMIC_LOOKUP;
    949     return NULL;
    950   }
    951 
    952   // Try to find the variable in this scope.
    953   Variable* var = LookupLocal(name);
    954 
    955   // We found a variable and we are done. (Even if there is an 'eval' in
    956   // this scope which introduces the same variable again, the resulting
    957   // variable remains the same.)
    958   if (var != NULL) {
    959     *binding_kind = BOUND;
    960     return var;
    961   }
    962 
    963   // We did not find a variable locally. Check against the function variable,
    964   // if any. We can do this for all scopes, since the function variable is
    965   // only present - if at all - for function scopes.
    966   *binding_kind = UNBOUND;
    967   var = LookupFunctionVar(name, factory);
    968   if (var != NULL) {
    969     *binding_kind = BOUND;
    970   } else if (outer_scope_ != NULL) {
    971     var = outer_scope_->LookupRecursive(name, binding_kind, factory);
    972     if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
    973       var->ForceContextAllocation();
    974     }
    975   } else {
    976     ASSERT(is_global_scope());
    977   }
    978 
    979   if (is_with_scope()) {
    980     ASSERT(!already_resolved());
    981     // The current scope is a with scope, so the variable binding can not be
    982     // statically resolved. However, note that it was necessary to do a lookup
    983     // in the outer scope anyway, because if a binding exists in an outer scope,
    984     // the associated variable has to be marked as potentially being accessed
    985     // from inside of an inner with scope (the property may not be in the 'with'
    986     // object).
    987     *binding_kind = DYNAMIC_LOOKUP;
    988     return NULL;
    989   } else if (calls_sloppy_eval()) {
    990     // A variable binding may have been found in an outer scope, but the current
    991     // scope makes a sloppy 'eval' call, so the found variable may not be
    992     // the correct one (the 'eval' may introduce a binding with the same name).
    993     // In that case, change the lookup result to reflect this situation.
    994     if (*binding_kind == BOUND) {
    995       *binding_kind = BOUND_EVAL_SHADOWED;
    996     } else if (*binding_kind == UNBOUND) {
    997       *binding_kind = UNBOUND_EVAL_SHADOWED;
    998     }
    999   }
   1000   return var;
   1001 }
   1002 
   1003 
   1004 bool Scope::ResolveVariable(CompilationInfo* info,
   1005                             VariableProxy* proxy,
   1006                             AstNodeFactory<AstNullVisitor>* factory) {
   1007   ASSERT(info->global_scope()->is_global_scope());
   1008 
   1009   // If the proxy is already resolved there's nothing to do
   1010   // (functions and consts may be resolved by the parser).
   1011   if (proxy->var() != NULL) return true;
   1012 
   1013   // Otherwise, try to resolve the variable.
   1014   BindingKind binding_kind;
   1015   Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
   1016   switch (binding_kind) {
   1017     case BOUND:
   1018       // We found a variable binding.
   1019       break;
   1020 
   1021     case BOUND_EVAL_SHADOWED:
   1022       // We either found a variable binding that might be shadowed by eval  or
   1023       // gave up on it (e.g. by encountering a local with the same in the outer
   1024       // scope which was not promoted to a context, this can happen if we use
   1025       // debugger to evaluate arbitrary expressions at a break point).
   1026       if (var->IsGlobalObjectProperty()) {
   1027         var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
   1028       } else if (var->is_dynamic()) {
   1029         var = NonLocal(proxy->name(), DYNAMIC);
   1030       } else {
   1031         Variable* invalidated = var;
   1032         var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
   1033         var->set_local_if_not_shadowed(invalidated);
   1034       }
   1035       break;
   1036 
   1037     case UNBOUND:
   1038       // No binding has been found. Declare a variable on the global object.
   1039       var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
   1040       break;
   1041 
   1042     case UNBOUND_EVAL_SHADOWED:
   1043       // No binding has been found. But some scope makes a sloppy 'eval' call.
   1044       var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
   1045       break;
   1046 
   1047     case DYNAMIC_LOOKUP:
   1048       // The variable could not be resolved statically.
   1049       var = NonLocal(proxy->name(), DYNAMIC);
   1050       break;
   1051   }
   1052 
   1053   ASSERT(var != NULL);
   1054 
   1055   if (FLAG_harmony_scoping && strict_mode() == STRICT &&
   1056       var->is_const_mode() && proxy->IsLValue()) {
   1057     // Assignment to const. Throw a syntax error.
   1058     MessageLocation location(
   1059         info->script(), proxy->position(), proxy->position());
   1060     Isolate* isolate = info->isolate();
   1061     Factory* factory = isolate->factory();
   1062     Handle<JSArray> array = factory->NewJSArray(0);
   1063     Handle<Object> result =
   1064         factory->NewSyntaxError("harmony_const_assign", array);
   1065     isolate->Throw(*result, &location);
   1066     return false;
   1067   }
   1068 
   1069   if (FLAG_harmony_modules) {
   1070     bool ok;
   1071 #ifdef DEBUG
   1072     if (FLAG_print_interface_details)
   1073       PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
   1074 #endif
   1075     proxy->interface()->Unify(var->interface(), zone(), &ok);
   1076     if (!ok) {
   1077 #ifdef DEBUG
   1078       if (FLAG_print_interfaces) {
   1079         PrintF("SCOPES TYPE ERROR\n");
   1080         PrintF("proxy: ");
   1081         proxy->interface()->Print();
   1082         PrintF("var: ");
   1083         var->interface()->Print();
   1084       }
   1085 #endif
   1086 
   1087       // Inconsistent use of module. Throw a syntax error.
   1088       // TODO(rossberg): generate more helpful error message.
   1089       MessageLocation location(
   1090           info->script(), proxy->position(), proxy->position());
   1091       Isolate* isolate = info->isolate();
   1092       Factory* factory = isolate->factory();
   1093       Handle<JSArray> array = factory->NewJSArray(1);
   1094       JSObject::SetElement(array, 0, var->name(), NONE, STRICT).Assert();
   1095       Handle<Object> result =
   1096           factory->NewSyntaxError("module_type_error", array);
   1097       isolate->Throw(*result, &location);
   1098       return false;
   1099     }
   1100   }
   1101 
   1102   proxy->BindTo(var);
   1103 
   1104   return true;
   1105 }
   1106 
   1107 
   1108 bool Scope::ResolveVariablesRecursively(
   1109     CompilationInfo* info,
   1110     AstNodeFactory<AstNullVisitor>* factory) {
   1111   ASSERT(info->global_scope()->is_global_scope());
   1112 
   1113   // Resolve unresolved variables for this scope.
   1114   for (int i = 0; i < unresolved_.length(); i++) {
   1115     if (!ResolveVariable(info, unresolved_[i], factory)) return false;
   1116   }
   1117 
   1118   // Resolve unresolved variables for inner scopes.
   1119   for (int i = 0; i < inner_scopes_.length(); i++) {
   1120     if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
   1121       return false;
   1122   }
   1123 
   1124   return true;
   1125 }
   1126 
   1127 
   1128 bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
   1129   if (outer_scope_calls_sloppy_eval) {
   1130     outer_scope_calls_sloppy_eval_ = true;
   1131   }
   1132 
   1133   bool calls_sloppy_eval =
   1134       this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
   1135   for (int i = 0; i < inner_scopes_.length(); i++) {
   1136     Scope* inner_scope = inner_scopes_[i];
   1137     if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) {
   1138       inner_scope_calls_eval_ = true;
   1139     }
   1140     if (inner_scope->force_eager_compilation_) {
   1141       force_eager_compilation_ = true;
   1142     }
   1143   }
   1144 
   1145   return scope_calls_eval_ || inner_scope_calls_eval_;
   1146 }
   1147 
   1148 
   1149 bool Scope::MustAllocate(Variable* var) {
   1150   // Give var a read/write use if there is a chance it might be accessed
   1151   // via an eval() call.  This is only possible if the variable has a
   1152   // visible name.
   1153   if ((var->is_this() || var->name()->length() > 0) &&
   1154       (var->has_forced_context_allocation() ||
   1155        scope_calls_eval_ ||
   1156        inner_scope_calls_eval_ ||
   1157        scope_contains_with_ ||
   1158        is_catch_scope() ||
   1159        is_block_scope() ||
   1160        is_module_scope() ||
   1161        is_global_scope())) {
   1162     var->set_is_used(true);
   1163   }
   1164   // Global variables do not need to be allocated.
   1165   return !var->IsGlobalObjectProperty() && var->is_used();
   1166 }
   1167 
   1168 
   1169 bool Scope::MustAllocateInContext(Variable* var) {
   1170   // If var is accessed from an inner scope, or if there is a possibility
   1171   // that it might be accessed from the current or an inner scope (through
   1172   // an eval() call or a runtime with lookup), it must be allocated in the
   1173   // context.
   1174   //
   1175   // Exceptions: If the scope as a whole has forced context allocation, all
   1176   // variables will have context allocation, even temporaries.  Otherwise
   1177   // temporary variables are always stack-allocated.  Catch-bound variables are
   1178   // always context-allocated.
   1179   if (has_forced_context_allocation()) return true;
   1180   if (var->mode() == TEMPORARY) return false;
   1181   if (var->mode() == INTERNAL) return true;
   1182   if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
   1183   if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true;
   1184   return var->has_forced_context_allocation() ||
   1185       scope_calls_eval_ ||
   1186       inner_scope_calls_eval_ ||
   1187       scope_contains_with_;
   1188 }
   1189 
   1190 
   1191 bool Scope::HasArgumentsParameter() {
   1192   for (int i = 0; i < params_.length(); i++) {
   1193     if (params_[i]->name().is_identical_to(
   1194             isolate_->factory()->arguments_string())) {
   1195       return true;
   1196     }
   1197   }
   1198   return false;
   1199 }
   1200 
   1201 
   1202 void Scope::AllocateStackSlot(Variable* var) {
   1203   var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
   1204 }
   1205 
   1206 
   1207 void Scope::AllocateHeapSlot(Variable* var) {
   1208   var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
   1209 }
   1210 
   1211 
   1212 void Scope::AllocateParameterLocals() {
   1213   ASSERT(is_function_scope());
   1214   Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
   1215   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
   1216 
   1217   bool uses_sloppy_arguments = false;
   1218 
   1219   if (MustAllocate(arguments) && !HasArgumentsParameter()) {
   1220     // 'arguments' is used. Unless there is also a parameter called
   1221     // 'arguments', we must be conservative and allocate all parameters to
   1222     // the context assuming they will be captured by the arguments object.
   1223     // If we have a parameter named 'arguments', a (new) value is always
   1224     // assigned to it via the function invocation. Then 'arguments' denotes
   1225     // that specific parameter value and cannot be used to access the
   1226     // parameters, which is why we don't need to allocate an arguments
   1227     // object in that case.
   1228 
   1229     // We are using 'arguments'. Tell the code generator that is needs to
   1230     // allocate the arguments object by setting 'arguments_'.
   1231     arguments_ = arguments;
   1232 
   1233     // In strict mode 'arguments' does not alias formal parameters.
   1234     // Therefore in strict mode we allocate parameters as if 'arguments'
   1235     // were not used.
   1236     uses_sloppy_arguments = strict_mode() == SLOPPY;
   1237   }
   1238 
   1239   // The same parameter may occur multiple times in the parameters_ list.
   1240   // If it does, and if it is not copied into the context object, it must
   1241   // receive the highest parameter index for that parameter; thus iteration
   1242   // order is relevant!
   1243   for (int i = params_.length() - 1; i >= 0; --i) {
   1244     Variable* var = params_[i];
   1245     ASSERT(var->scope() == this);
   1246     if (uses_sloppy_arguments || has_forced_context_allocation()) {
   1247       // Force context allocation of the parameter.
   1248       var->ForceContextAllocation();
   1249     }
   1250 
   1251     if (MustAllocate(var)) {
   1252       if (MustAllocateInContext(var)) {
   1253         ASSERT(var->IsUnallocated() || var->IsContextSlot());
   1254         if (var->IsUnallocated()) {
   1255           AllocateHeapSlot(var);
   1256         }
   1257       } else {
   1258         ASSERT(var->IsUnallocated() || var->IsParameter());
   1259         if (var->IsUnallocated()) {
   1260           var->AllocateTo(Variable::PARAMETER, i);
   1261         }
   1262       }
   1263     }
   1264   }
   1265 }
   1266 
   1267 
   1268 void Scope::AllocateNonParameterLocal(Variable* var) {
   1269   ASSERT(var->scope() == this);
   1270   ASSERT(!var->IsVariable(isolate_->factory()->dot_result_string()) ||
   1271          !var->IsStackLocal());
   1272   if (var->IsUnallocated() && MustAllocate(var)) {
   1273     if (MustAllocateInContext(var)) {
   1274       AllocateHeapSlot(var);
   1275     } else {
   1276       AllocateStackSlot(var);
   1277     }
   1278   }
   1279 }
   1280 
   1281 
   1282 void Scope::AllocateNonParameterLocals() {
   1283   // All variables that have no rewrite yet are non-parameter locals.
   1284   for (int i = 0; i < temps_.length(); i++) {
   1285     AllocateNonParameterLocal(temps_[i]);
   1286   }
   1287 
   1288   for (int i = 0; i < internals_.length(); i++) {
   1289     AllocateNonParameterLocal(internals_[i]);
   1290   }
   1291 
   1292   ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
   1293   for (VariableMap::Entry* p = variables_.Start();
   1294        p != NULL;
   1295        p = variables_.Next(p)) {
   1296     Variable* var = reinterpret_cast<Variable*>(p->value);
   1297     vars.Add(VarAndOrder(var, p->order), zone());
   1298   }
   1299   vars.Sort(VarAndOrder::Compare);
   1300   int var_count = vars.length();
   1301   for (int i = 0; i < var_count; i++) {
   1302     AllocateNonParameterLocal(vars[i].var());
   1303   }
   1304 
   1305   // For now, function_ must be allocated at the very end.  If it gets
   1306   // allocated in the context, it must be the last slot in the context,
   1307   // because of the current ScopeInfo implementation (see
   1308   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
   1309   if (function_ != NULL) {
   1310     AllocateNonParameterLocal(function_->proxy()->var());
   1311   }
   1312 }
   1313 
   1314 
   1315 void Scope::AllocateVariablesRecursively() {
   1316   // Allocate variables for inner scopes.
   1317   for (int i = 0; i < inner_scopes_.length(); i++) {
   1318     inner_scopes_[i]->AllocateVariablesRecursively();
   1319   }
   1320 
   1321   // If scope is already resolved, we still need to allocate
   1322   // variables in inner scopes which might not had been resolved yet.
   1323   if (already_resolved()) return;
   1324   // The number of slots required for variables.
   1325   num_stack_slots_ = 0;
   1326   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
   1327 
   1328   // Allocate variables for this scope.
   1329   // Parameters must be allocated first, if any.
   1330   if (is_function_scope()) AllocateParameterLocals();
   1331   AllocateNonParameterLocals();
   1332 
   1333   // Force allocation of a context for this scope if necessary. For a 'with'
   1334   // scope and for a function scope that makes an 'eval' call we need a context,
   1335   // even if no local variables were statically allocated in the scope.
   1336   // Likewise for modules.
   1337   bool must_have_context = is_with_scope() || is_module_scope() ||
   1338       (is_function_scope() && calls_eval());
   1339 
   1340   // If we didn't allocate any locals in the local context, then we only
   1341   // need the minimal number of slots if we must have a context.
   1342   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
   1343     num_heap_slots_ = 0;
   1344   }
   1345 
   1346   // Allocation done.
   1347   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
   1348 }
   1349 
   1350 
   1351 void Scope::AllocateModulesRecursively(Scope* host_scope) {
   1352   if (already_resolved()) return;
   1353   if (is_module_scope()) {
   1354     ASSERT(interface_->IsFrozen());
   1355     Handle<String> name = isolate_->factory()->InternalizeOneByteString(
   1356         STATIC_ASCII_VECTOR(".module"));
   1357     ASSERT(module_var_ == NULL);
   1358     module_var_ = host_scope->NewInternal(name);
   1359     ++host_scope->num_modules_;
   1360   }
   1361 
   1362   for (int i = 0; i < inner_scopes_.length(); i++) {
   1363     Scope* inner_scope = inner_scopes_.at(i);
   1364     inner_scope->AllocateModulesRecursively(host_scope);
   1365   }
   1366 }
   1367 
   1368 
   1369 int Scope::StackLocalCount() const {
   1370   return num_stack_slots() -
   1371       (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
   1372 }
   1373 
   1374 
   1375 int Scope::ContextLocalCount() const {
   1376   if (num_heap_slots() == 0) return 0;
   1377   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
   1378       (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
   1379 }
   1380 
   1381 } }  // namespace v8::internal
   1382