Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #include "prettyprinter.h"
     31 #include "scopeinfo.h"
     32 #include "scopes.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 // ----------------------------------------------------------------------------
     38 // A Zone allocator for use with LocalsMap.
     39 
     40 class ZoneAllocator: public Allocator {
     41  public:
     42   /* nothing to do */
     43   virtual ~ZoneAllocator()  {}
     44 
     45   virtual void* New(size_t size)  { return Zone::New(static_cast<int>(size)); }
     46 
     47   /* ignored - Zone is freed in one fell swoop */
     48   virtual void Delete(void* p)  {}
     49 };
     50 
     51 
     52 static ZoneAllocator LocalsMapAllocator;
     53 
     54 
     55 // ----------------------------------------------------------------------------
     56 // Implementation of LocalsMap
     57 //
     58 // Note: We are storing the handle locations as key values in the hash map.
     59 //       When inserting a new variable via Declare(), we rely on the fact that
     60 //       the handle location remains alive for the duration of that variable
     61 //       use. Because a Variable holding a handle with the same location exists
     62 //       this is ensured.
     63 
     64 static bool Match(void* key1, void* key2) {
     65   String* name1 = *reinterpret_cast<String**>(key1);
     66   String* name2 = *reinterpret_cast<String**>(key2);
     67   ASSERT(name1->IsSymbol());
     68   ASSERT(name2->IsSymbol());
     69   return name1 == name2;
     70 }
     71 
     72 
     73 // Dummy constructor
     74 VariableMap::VariableMap(bool gotta_love_static_overloading) : HashMap() {}
     75 
     76 VariableMap::VariableMap() : HashMap(Match, &LocalsMapAllocator, 8) {}
     77 VariableMap::~VariableMap() {}
     78 
     79 
     80 Variable* VariableMap::Declare(Scope* scope,
     81                                Handle<String> name,
     82                                Variable::Mode mode,
     83                                bool is_valid_lhs,
     84                                Variable::Kind kind) {
     85   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
     86   if (p->value == NULL) {
     87     // The variable has not been declared yet -> insert it.
     88     ASSERT(p->key == name.location());
     89     p->value = new Variable(scope, name, mode, is_valid_lhs, kind);
     90   }
     91   return reinterpret_cast<Variable*>(p->value);
     92 }
     93 
     94 
     95 Variable* VariableMap::Lookup(Handle<String> name) {
     96   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false);
     97   if (p != NULL) {
     98     ASSERT(*reinterpret_cast<String**>(p->key) == *name);
     99     ASSERT(p->value != NULL);
    100     return reinterpret_cast<Variable*>(p->value);
    101   }
    102   return NULL;
    103 }
    104 
    105 
    106 // ----------------------------------------------------------------------------
    107 // Implementation of Scope
    108 
    109 
    110 // Dummy constructor
    111 Scope::Scope(Type type)
    112   : outer_scope_(NULL),
    113     inner_scopes_(0),
    114     type_(type),
    115     scope_name_(Factory::empty_symbol()),
    116     variables_(false),
    117     temps_(0),
    118     params_(0),
    119     dynamics_(NULL),
    120     unresolved_(0),
    121     decls_(0),
    122     receiver_(NULL),
    123     function_(NULL),
    124     arguments_(NULL),
    125     arguments_shadow_(NULL),
    126     illegal_redecl_(NULL),
    127     scope_inside_with_(false),
    128     scope_contains_with_(false),
    129     scope_calls_eval_(false),
    130     outer_scope_calls_eval_(false),
    131     inner_scope_calls_eval_(false),
    132     outer_scope_is_eval_scope_(false),
    133     force_eager_compilation_(false),
    134     num_stack_slots_(0),
    135     num_heap_slots_(0) {
    136 }
    137 
    138 
    139 Scope::Scope(Scope* outer_scope, Type type)
    140   : outer_scope_(outer_scope),
    141     inner_scopes_(4),
    142     type_(type),
    143     scope_name_(Factory::empty_symbol()),
    144     temps_(4),
    145     params_(4),
    146     dynamics_(NULL),
    147     unresolved_(16),
    148     decls_(4),
    149     receiver_(NULL),
    150     function_(NULL),
    151     arguments_(NULL),
    152     arguments_shadow_(NULL),
    153     illegal_redecl_(NULL),
    154     scope_inside_with_(false),
    155     scope_contains_with_(false),
    156     scope_calls_eval_(false),
    157     outer_scope_calls_eval_(false),
    158     inner_scope_calls_eval_(false),
    159     outer_scope_is_eval_scope_(false),
    160     force_eager_compilation_(false),
    161     num_stack_slots_(0),
    162     num_heap_slots_(0) {
    163   // At some point we might want to provide outer scopes to
    164   // eval scopes (by walking the stack and reading the scope info).
    165   // In that case, the ASSERT below needs to be adjusted.
    166   ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
    167   ASSERT(!HasIllegalRedeclaration());
    168 }
    169 
    170 
    171 void Scope::Initialize(bool inside_with) {
    172   // Add this scope as a new inner scope of the outer scope.
    173   if (outer_scope_ != NULL) {
    174     outer_scope_->inner_scopes_.Add(this);
    175     scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with;
    176   } else {
    177     scope_inside_with_ = inside_with;
    178   }
    179 
    180   // Declare convenience variables.
    181   // Declare and allocate receiver (even for the global scope, and even
    182   // if naccesses_ == 0).
    183   // NOTE: When loading parameters in the global scope, we must take
    184   // care not to access them as properties of the global object, but
    185   // instead load them directly from the stack. Currently, the only
    186   // such parameter is 'this' which is passed on the stack when
    187   // invoking scripts
    188   Variable* var =
    189       variables_.Declare(this, Factory::this_symbol(), Variable::VAR,
    190                          false, Variable::THIS);
    191   var->rewrite_ = new Slot(var, Slot::PARAMETER, -1);
    192   receiver_ = var;
    193 
    194   if (is_function_scope()) {
    195     // Declare 'arguments' variable which exists in all functions.
    196     // Note that it might never be accessed, in which case it won't be
    197     // allocated during variable allocation.
    198     variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR,
    199                        true, Variable::ARGUMENTS);
    200   }
    201 }
    202 
    203 
    204 
    205 Variable* Scope::LocalLookup(Handle<String> name) {
    206   return variables_.Lookup(name);
    207 }
    208 
    209 
    210 Variable* Scope::Lookup(Handle<String> name) {
    211   for (Scope* scope = this;
    212        scope != NULL;
    213        scope = scope->outer_scope()) {
    214     Variable* var = scope->LocalLookup(name);
    215     if (var != NULL) return var;
    216   }
    217   return NULL;
    218 }
    219 
    220 
    221 Variable* Scope::DeclareFunctionVar(Handle<String> name) {
    222   ASSERT(is_function_scope() && function_ == NULL);
    223   function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
    224   return function_;
    225 }
    226 
    227 
    228 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
    229   // DYNAMIC variables are introduces during variable allocation,
    230   // INTERNAL variables are allocated explicitly, and TEMPORARY
    231   // variables are allocated via NewTemporary().
    232   ASSERT(mode == Variable::VAR || mode == Variable::CONST);
    233   return variables_.Declare(this, name, mode, true, Variable::NORMAL);
    234 }
    235 
    236 
    237 Variable* Scope::DeclareGlobal(Handle<String> name) {
    238   ASSERT(is_global_scope());
    239   return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true,
    240                             Variable::NORMAL);
    241 }
    242 
    243 
    244 void Scope::AddParameter(Variable* var) {
    245   ASSERT(is_function_scope());
    246   ASSERT(LocalLookup(var->name()) == var);
    247   params_.Add(var);
    248 }
    249 
    250 
    251 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) {
    252   // Note that we must not share the unresolved variables with
    253   // the same name because they may be removed selectively via
    254   // RemoveUnresolved().
    255   VariableProxy* proxy = new VariableProxy(name, false, inside_with);
    256   unresolved_.Add(proxy);
    257   return proxy;
    258 }
    259 
    260 
    261 void Scope::RemoveUnresolved(VariableProxy* var) {
    262   // Most likely (always?) any variable we want to remove
    263   // was just added before, so we search backwards.
    264   for (int i = unresolved_.length(); i-- > 0;) {
    265     if (unresolved_[i] == var) {
    266       unresolved_.Remove(i);
    267       return;
    268     }
    269   }
    270 }
    271 
    272 
    273 VariableProxy* Scope::NewTemporary(Handle<String> name) {
    274   Variable* var = new Variable(this, name, Variable::TEMPORARY, true,
    275                                Variable::NORMAL);
    276   VariableProxy* tmp = new VariableProxy(name, false, false);
    277   tmp->BindTo(var);
    278   temps_.Add(var);
    279   return tmp;
    280 }
    281 
    282 
    283 void Scope::AddDeclaration(Declaration* declaration) {
    284   decls_.Add(declaration);
    285 }
    286 
    287 
    288 void Scope::SetIllegalRedeclaration(Expression* expression) {
    289   // Only set the illegal redeclaration expression the
    290   // first time the function is called.
    291   if (!HasIllegalRedeclaration()) {
    292     illegal_redecl_ = expression;
    293   }
    294   ASSERT(HasIllegalRedeclaration());
    295 }
    296 
    297 
    298 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
    299   ASSERT(HasIllegalRedeclaration());
    300   illegal_redecl_->Accept(visitor);
    301 }
    302 
    303 
    304 template<class Allocator>
    305 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
    306   // Collect variables in this scope.
    307   // Note that the function_ variable - if present - is not
    308   // collected here but handled separately in ScopeInfo
    309   // which is the current user of this function).
    310   for (int i = 0; i < temps_.length(); i++) {
    311     Variable* var = temps_[i];
    312     if (var->var_uses()->is_used()) {
    313       locals->Add(var);
    314     }
    315   }
    316   for (VariableMap::Entry* p = variables_.Start();
    317        p != NULL;
    318        p = variables_.Next(p)) {
    319     Variable* var = reinterpret_cast<Variable*>(p->value);
    320     if (var->var_uses()->is_used()) {
    321       locals->Add(var);
    322     }
    323   }
    324 }
    325 
    326 
    327 // Make sure the method gets instantiated by the template system.
    328 template void Scope::CollectUsedVariables(
    329     List<Variable*, FreeStoreAllocationPolicy>* locals);
    330 template void Scope::CollectUsedVariables(
    331     List<Variable*, PreallocatedStorage>* locals);
    332 template void Scope::CollectUsedVariables(
    333     List<Variable*, ZoneListAllocationPolicy>* locals);
    334 
    335 
    336 void Scope::AllocateVariables(Handle<Context> context) {
    337   ASSERT(outer_scope_ == NULL);  // eval or global scopes only
    338 
    339   // 1) Propagate scope information.
    340   // If we are in an eval scope, we may have other outer scopes about
    341   // which we don't know anything at this point. Thus we must be conservative
    342   // and assume they may invoke eval themselves. Eventually we could capture
    343   // this information in the ScopeInfo and then use it here (by traversing
    344   // the call chain stack, at compile time).
    345   bool eval_scope = is_eval_scope();
    346   PropagateScopeInfo(eval_scope, eval_scope);
    347 
    348   // 2) Resolve variables.
    349   Scope* global_scope = NULL;
    350   if (is_global_scope()) global_scope = this;
    351   ResolveVariablesRecursively(global_scope, context);
    352 
    353   // 3) Allocate variables.
    354   AllocateVariablesRecursively();
    355 }
    356 
    357 
    358 bool Scope::AllowsLazyCompilation() const {
    359   return !force_eager_compilation_ && HasTrivialOuterContext();
    360 }
    361 
    362 
    363 bool Scope::HasTrivialContext() const {
    364   // A function scope has a trivial context if it always is the global
    365   // context. We iteratively scan out the context chain to see if
    366   // there is anything that makes this scope non-trivial; otherwise we
    367   // return true.
    368   for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
    369     if (scope->is_eval_scope()) return false;
    370     if (scope->scope_inside_with_) return false;
    371     if (scope->num_heap_slots_ > 0) return false;
    372   }
    373   return true;
    374 }
    375 
    376 
    377 bool Scope::HasTrivialOuterContext() const {
    378   Scope* outer = outer_scope_;
    379   if (outer == NULL) return true;
    380   // Note that the outer context may be trivial in general, but the current
    381   // scope may be inside a 'with' statement in which case the outer context
    382   // for this scope is not trivial.
    383   return !scope_inside_with_ && outer->HasTrivialContext();
    384 }
    385 
    386 
    387 int Scope::ContextChainLength(Scope* scope) {
    388   int n = 0;
    389   for (Scope* s = this; s != scope; s = s->outer_scope_) {
    390     ASSERT(s != NULL);  // scope must be in the scope chain
    391     if (s->num_heap_slots() > 0) n++;
    392   }
    393   return n;
    394 }
    395 
    396 
    397 #ifdef DEBUG
    398 static const char* Header(Scope::Type type) {
    399   switch (type) {
    400     case Scope::EVAL_SCOPE: return "eval";
    401     case Scope::FUNCTION_SCOPE: return "function";
    402     case Scope::GLOBAL_SCOPE: return "global";
    403   }
    404   UNREACHABLE();
    405   return NULL;
    406 }
    407 
    408 
    409 static void Indent(int n, const char* str) {
    410   PrintF("%*s%s", n, "", str);
    411 }
    412 
    413 
    414 static void PrintName(Handle<String> name) {
    415   SmartPointer<char> s = name->ToCString(DISALLOW_NULLS);
    416   PrintF("%s", *s);
    417 }
    418 
    419 
    420 static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
    421   if (var->var_uses()->is_used() || var->rewrite() != NULL) {
    422     Indent(indent, Variable::Mode2String(var->mode()));
    423     PrintF(" ");
    424     PrintName(var->name());
    425     PrintF(";  // ");
    426     if (var->rewrite() != NULL) PrintF("%s, ", printer->Print(var->rewrite()));
    427     if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, ");
    428     PrintF("var ");
    429     var->var_uses()->Print();
    430     PrintF(", obj ");
    431     var->obj_uses()->Print();
    432     PrintF("\n");
    433   }
    434 }
    435 
    436 
    437 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) {
    438   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
    439     Variable* var = reinterpret_cast<Variable*>(p->value);
    440     PrintVar(printer, indent, var);
    441   }
    442 }
    443 
    444 
    445 void Scope::Print(int n) {
    446   int n0 = (n > 0 ? n : 0);
    447   int n1 = n0 + 2;  // indentation
    448 
    449   // Print header.
    450   Indent(n0, Header(type_));
    451   if (scope_name_->length() > 0) {
    452     PrintF(" ");
    453     PrintName(scope_name_);
    454   }
    455 
    456   // Print parameters, if any.
    457   if (is_function_scope()) {
    458     PrintF(" (");
    459     for (int i = 0; i < params_.length(); i++) {
    460       if (i > 0) PrintF(", ");
    461       PrintName(params_[i]->name());
    462     }
    463     PrintF(")");
    464   }
    465 
    466   PrintF(" {\n");
    467 
    468   // Function name, if any (named function literals, only).
    469   if (function_ != NULL) {
    470     Indent(n1, "// (local) function name: ");
    471     PrintName(function_->name());
    472     PrintF("\n");
    473   }
    474 
    475   // Scope info.
    476   if (HasTrivialOuterContext()) {
    477     Indent(n1, "// scope has trivial outer context\n");
    478   }
    479   if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
    480   if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
    481   if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
    482   if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
    483   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
    484   if (outer_scope_is_eval_scope_) {
    485     Indent(n1, "// outer scope is 'eval' scope\n");
    486   }
    487   if (num_stack_slots_ > 0) { Indent(n1, "// ");
    488   PrintF("%d stack slots\n", num_stack_slots_); }
    489   if (num_heap_slots_ > 0) { Indent(n1, "// ");
    490   PrintF("%d heap slots\n", num_heap_slots_); }
    491 
    492   // Print locals.
    493   PrettyPrinter printer;
    494   Indent(n1, "// function var\n");
    495   if (function_ != NULL) {
    496     PrintVar(&printer, n1, function_);
    497   }
    498 
    499   Indent(n1, "// temporary vars\n");
    500   for (int i = 0; i < temps_.length(); i++) {
    501     PrintVar(&printer, n1, temps_[i]);
    502   }
    503 
    504   Indent(n1, "// local vars\n");
    505   PrintMap(&printer, n1, &variables_);
    506 
    507   Indent(n1, "// dynamic vars\n");
    508   if (dynamics_ != NULL) {
    509     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC));
    510     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
    511     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
    512   }
    513 
    514   // Print inner scopes (disable by providing negative n).
    515   if (n >= 0) {
    516     for (int i = 0; i < inner_scopes_.length(); i++) {
    517       PrintF("\n");
    518       inner_scopes_[i]->Print(n1);
    519     }
    520   }
    521 
    522   Indent(n0, "}\n");
    523 }
    524 #endif  // DEBUG
    525 
    526 
    527 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
    528   if (dynamics_ == NULL) dynamics_ = new DynamicScopePart();
    529   VariableMap* map = dynamics_->GetMap(mode);
    530   Variable* var = map->Lookup(name);
    531   if (var == NULL) {
    532     // Declare a new non-local.
    533     var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
    534     // Allocate it by giving it a dynamic lookup.
    535     var->rewrite_ = new Slot(var, Slot::LOOKUP, -1);
    536   }
    537   return var;
    538 }
    539 
    540 
    541 // Lookup a variable starting with this scope. The result is either
    542 // the statically resolved variable belonging to an outer scope, or
    543 // NULL. It may be NULL because a) we couldn't find a variable, or b)
    544 // because the variable is just a guess (and may be shadowed by
    545 // another variable that is introduced dynamically via an 'eval' call
    546 // or a 'with' statement).
    547 Variable* Scope::LookupRecursive(Handle<String> name,
    548                                  bool inner_lookup,
    549                                  Variable** invalidated_local) {
    550   // If we find a variable, but the current scope calls 'eval', the found
    551   // variable may not be the correct one (the 'eval' may introduce a
    552   // property with the same name). In that case, remember that the variable
    553   // found is just a guess.
    554   bool guess = scope_calls_eval_;
    555 
    556   // Try to find the variable in this scope.
    557   Variable* var = LocalLookup(name);
    558 
    559   if (var != NULL) {
    560     // We found a variable. If this is not an inner lookup, we are done.
    561     // (Even if there is an 'eval' in this scope which introduces the
    562     // same variable again, the resulting variable remains the same.
    563     // Note that enclosing 'with' statements are handled at the call site.)
    564     if (!inner_lookup)
    565       return var;
    566 
    567   } else {
    568     // We did not find a variable locally. Check against the function variable,
    569     // if any. We can do this for all scopes, since the function variable is
    570     // only present - if at all - for function scopes.
    571     //
    572     // This lookup corresponds to a lookup in the "intermediate" scope sitting
    573     // between this scope and the outer scope. (ECMA-262, 3rd., requires that
    574     // the name of named function literal is kept in an intermediate scope
    575     // in between this scope and the next outer scope.)
    576     if (function_ != NULL && function_->name().is_identical_to(name)) {
    577       var = function_;
    578 
    579     } else if (outer_scope_ != NULL) {
    580       var = outer_scope_->LookupRecursive(name, true, invalidated_local);
    581       // We may have found a variable in an outer scope. However, if
    582       // the current scope is inside a 'with', the actual variable may
    583       // be a property introduced via the 'with' statement. Then, the
    584       // variable we may have found is just a guess.
    585       if (scope_inside_with_)
    586         guess = true;
    587     }
    588 
    589     // If we did not find a variable, we are done.
    590     if (var == NULL)
    591       return NULL;
    592   }
    593 
    594   ASSERT(var != NULL);
    595 
    596   // If this is a lookup from an inner scope, mark the variable.
    597   if (inner_lookup)
    598     var->is_accessed_from_inner_scope_ = true;
    599 
    600   // If the variable we have found is just a guess, invalidate the
    601   // result. If the found variable is local, record that fact so we
    602   // can generate fast code to get it if it is not shadowed by eval.
    603   if (guess) {
    604     if (!var->is_global()) *invalidated_local = var;
    605     var = NULL;
    606   }
    607 
    608   return var;
    609 }
    610 
    611 
    612 void Scope::ResolveVariable(Scope* global_scope,
    613                             Handle<Context> context,
    614                             VariableProxy* proxy) {
    615   ASSERT(global_scope == NULL || global_scope->is_global_scope());
    616 
    617   // If the proxy is already resolved there's nothing to do
    618   // (functions and consts may be resolved by the parser).
    619   if (proxy->var() != NULL) return;
    620 
    621   // Otherwise, try to resolve the variable.
    622   Variable* invalidated_local = NULL;
    623   Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local);
    624 
    625   if (proxy->inside_with()) {
    626     // If we are inside a local 'with' statement, all bets are off
    627     // and we cannot resolve the proxy to a local variable even if
    628     // we found an outer matching variable.
    629     // Note that we must do a lookup anyway, because if we find one,
    630     // we must mark that variable as potentially accessed from this
    631     // inner scope (the property may not be in the 'with' object).
    632     var = NonLocal(proxy->name(), Variable::DYNAMIC);
    633 
    634   } else {
    635     // We are not inside a local 'with' statement.
    636 
    637     if (var == NULL) {
    638       // We did not find the variable. We have a global variable
    639       // if we are in the global scope (we know already that we
    640       // are outside a 'with' statement) or if there is no way
    641       // that the variable might be introduced dynamically (through
    642       // a local or outer eval() call, or an outer 'with' statement),
    643       // or we don't know about the outer scope (because we are
    644       // in an eval scope).
    645       if (is_global_scope() ||
    646           !(scope_inside_with_ || outer_scope_is_eval_scope_ ||
    647             scope_calls_eval_ || outer_scope_calls_eval_)) {
    648         // We must have a global variable.
    649         ASSERT(global_scope != NULL);
    650         var = global_scope->DeclareGlobal(proxy->name());
    651 
    652       } else if (scope_inside_with_) {
    653         // If we are inside a with statement we give up and look up
    654         // the variable at runtime.
    655         var = NonLocal(proxy->name(), Variable::DYNAMIC);
    656 
    657       } else if (invalidated_local != NULL) {
    658         // No with statements are involved and we found a local
    659         // variable that might be shadowed by eval introduced
    660         // variables.
    661         var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
    662         var->set_local_if_not_shadowed(invalidated_local);
    663 
    664       } else if (outer_scope_is_eval_scope_) {
    665         // No with statements and we did not find a local and the code
    666         // is executed with a call to eval.  The context contains
    667         // scope information that we can use to determine if the
    668         // variable is global if it is not shadowed by eval-introduced
    669         // variables.
    670         if (context->GlobalIfNotShadowedByEval(proxy->name())) {
    671           var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
    672 
    673         } else {
    674           var = NonLocal(proxy->name(), Variable::DYNAMIC);
    675         }
    676 
    677       } else {
    678         // No with statements and we did not find a local and the code
    679         // is not executed with a call to eval.  We know that this
    680         // variable is global unless it is shadowed by eval-introduced
    681         // variables.
    682         var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
    683       }
    684     }
    685   }
    686 
    687   proxy->BindTo(var);
    688 }
    689 
    690 
    691 void Scope::ResolveVariablesRecursively(Scope* global_scope,
    692                                         Handle<Context> context) {
    693   ASSERT(global_scope == NULL || global_scope->is_global_scope());
    694 
    695   // Resolve unresolved variables for this scope.
    696   for (int i = 0; i < unresolved_.length(); i++) {
    697     ResolveVariable(global_scope, context, unresolved_[i]);
    698   }
    699 
    700   // Resolve unresolved variables for inner scopes.
    701   for (int i = 0; i < inner_scopes_.length(); i++) {
    702     inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context);
    703   }
    704 }
    705 
    706 
    707 bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval,
    708                                bool outer_scope_is_eval_scope) {
    709   if (outer_scope_calls_eval) {
    710     outer_scope_calls_eval_ = true;
    711   }
    712 
    713   if (outer_scope_is_eval_scope) {
    714     outer_scope_is_eval_scope_ = true;
    715   }
    716 
    717   bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
    718   bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
    719   for (int i = 0; i < inner_scopes_.length(); i++) {
    720     Scope* inner_scope = inner_scopes_[i];
    721     if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) {
    722       inner_scope_calls_eval_ = true;
    723     }
    724     if (inner_scope->force_eager_compilation_) {
    725       force_eager_compilation_ = true;
    726     }
    727   }
    728 
    729   return scope_calls_eval_ || inner_scope_calls_eval_;
    730 }
    731 
    732 
    733 bool Scope::MustAllocate(Variable* var) {
    734   // Give var a read/write use if there is a chance it might be accessed
    735   // via an eval() call.  This is only possible if the variable has a
    736   // visible name.
    737   if ((var->is_this() || var->name()->length() > 0) &&
    738       (var->is_accessed_from_inner_scope_ ||
    739        scope_calls_eval_ || inner_scope_calls_eval_ ||
    740        scope_contains_with_)) {
    741     var->var_uses()->RecordAccess(1);
    742   }
    743   // Global variables do not need to be allocated.
    744   return !var->is_global() && var->var_uses()->is_used();
    745 }
    746 
    747 
    748 bool Scope::MustAllocateInContext(Variable* var) {
    749   // If var is accessed from an inner scope, or if there is a
    750   // possibility that it might be accessed from the current or an inner
    751   // scope (through an eval() call), it must be allocated in the
    752   // context.  Exception: temporary variables are not allocated in the
    753   // context.
    754   return
    755     var->mode() != Variable::TEMPORARY &&
    756     (var->is_accessed_from_inner_scope_ ||
    757      scope_calls_eval_ || inner_scope_calls_eval_ ||
    758      scope_contains_with_ || var->is_global());
    759 }
    760 
    761 
    762 bool Scope::HasArgumentsParameter() {
    763   for (int i = 0; i < params_.length(); i++) {
    764     if (params_[i]->name().is_identical_to(Factory::arguments_symbol()))
    765       return true;
    766   }
    767   return false;
    768 }
    769 
    770 
    771 void Scope::AllocateStackSlot(Variable* var) {
    772   var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++);
    773 }
    774 
    775 
    776 void Scope::AllocateHeapSlot(Variable* var) {
    777   var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++);
    778 }
    779 
    780 
    781 void Scope::AllocateParameterLocals() {
    782   ASSERT(is_function_scope());
    783   Variable* arguments = LocalLookup(Factory::arguments_symbol());
    784   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
    785   if (MustAllocate(arguments) && !HasArgumentsParameter()) {
    786     // 'arguments' is used. Unless there is also a parameter called
    787     // 'arguments', we must be conservative and access all parameters via
    788     // the arguments object: The i'th parameter is rewritten into
    789     // '.arguments[i]' (*). If we have a parameter named 'arguments', a
    790     // (new) value is always assigned to it via the function
    791     // invocation. Then 'arguments' denotes that specific parameter value
    792     // and cannot be used to access the parameters, which is why we don't
    793     // need to rewrite in that case.
    794     //
    795     // (*) Instead of having a parameter called 'arguments', we may have an
    796     // assignment to 'arguments' in the function body, at some arbitrary
    797     // point in time (possibly through an 'eval()' call!). After that
    798     // assignment any re-write of parameters would be invalid (was bug
    799     // 881452). Thus, we introduce a shadow '.arguments'
    800     // variable which also points to the arguments object. For rewrites we
    801     // use '.arguments' which remains valid even if we assign to
    802     // 'arguments'. To summarize: If we need to rewrite, we allocate an
    803     // 'arguments' object dynamically upon function invocation. The compiler
    804     // introduces 2 local variables 'arguments' and '.arguments', both of
    805     // which originally point to the arguments object that was
    806     // allocated. All parameters are rewritten into property accesses via
    807     // the '.arguments' variable. Thus, any changes to properties of
    808     // 'arguments' are reflected in the variables and vice versa. If the
    809     // 'arguments' variable is changed, '.arguments' still points to the
    810     // correct arguments object and the rewrites still work.
    811 
    812     // We are using 'arguments'. Tell the code generator that is needs to
    813     // allocate the arguments object by setting 'arguments_'.
    814     arguments_ = new VariableProxy(Factory::arguments_symbol(), false, false);
    815     arguments_->BindTo(arguments);
    816 
    817     // We also need the '.arguments' shadow variable. Declare it and create
    818     // and bind the corresponding proxy. It's ok to declare it only now
    819     // because it's a local variable that is allocated after the parameters
    820     // have been allocated.
    821     //
    822     // Note: This is "almost" at temporary variable but we cannot use
    823     // NewTemporary() because the mode needs to be INTERNAL since this
    824     // variable may be allocated in the heap-allocated context (temporaries
    825     // are never allocated in the context).
    826     Variable* arguments_shadow =
    827         new Variable(this, Factory::arguments_shadow_symbol(),
    828                      Variable::INTERNAL, true, Variable::ARGUMENTS);
    829     arguments_shadow_ =
    830         new VariableProxy(Factory::arguments_shadow_symbol(), false, false);
    831     arguments_shadow_->BindTo(arguments_shadow);
    832     temps_.Add(arguments_shadow);
    833 
    834     // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
    835     for (int i = 0; i < params_.length(); i++) {
    836       Variable* var = params_[i];
    837       ASSERT(var->scope() == this);
    838       if (MustAllocate(var)) {
    839         if (MustAllocateInContext(var)) {
    840           // It is ok to set this only now, because arguments is a local
    841           // variable that is allocated after the parameters have been
    842           // allocated.
    843           arguments_shadow->is_accessed_from_inner_scope_ = true;
    844         }
    845         var->rewrite_ =
    846           new Property(arguments_shadow_,
    847                        new Literal(Handle<Object>(Smi::FromInt(i))),
    848                        RelocInfo::kNoPosition,
    849                        Property::SYNTHETIC);
    850         arguments_shadow->var_uses()->RecordUses(var->var_uses());
    851       }
    852     }
    853 
    854   } else {
    855     // The arguments object is not used, so we can access parameters directly.
    856     // The same parameter may occur multiple times in the parameters_ list.
    857     // If it does, and if it is not copied into the context object, it must
    858     // receive the highest parameter index for that parameter; thus iteration
    859     // order is relevant!
    860     for (int i = 0; i < params_.length(); i++) {
    861       Variable* var = params_[i];
    862       ASSERT(var->scope() == this);
    863       if (MustAllocate(var)) {
    864         if (MustAllocateInContext(var)) {
    865           ASSERT(var->rewrite_ == NULL ||
    866                  (var->slot() != NULL && var->slot()->type() == Slot::CONTEXT));
    867           if (var->rewrite_ == NULL) {
    868             // Only set the heap allocation if the parameter has not
    869             // been allocated yet.
    870             AllocateHeapSlot(var);
    871           }
    872         } else {
    873           ASSERT(var->rewrite_ == NULL ||
    874                  (var->slot() != NULL &&
    875                   var->slot()->type() == Slot::PARAMETER));
    876           // Set the parameter index always, even if the parameter
    877           // was seen before! (We need to access the actual parameter
    878           // supplied for the last occurrence of a multiply declared
    879           // parameter.)
    880           var->rewrite_ = new Slot(var, Slot::PARAMETER, i);
    881         }
    882       }
    883     }
    884   }
    885 }
    886 
    887 
    888 void Scope::AllocateNonParameterLocal(Variable* var) {
    889   ASSERT(var->scope() == this);
    890   ASSERT(var->rewrite_ == NULL ||
    891          (!var->IsVariable(Factory::result_symbol())) ||
    892          (var->slot() == NULL || var->slot()->type() != Slot::LOCAL));
    893   if (var->rewrite_ == NULL && MustAllocate(var)) {
    894     if (MustAllocateInContext(var)) {
    895       AllocateHeapSlot(var);
    896     } else {
    897       AllocateStackSlot(var);
    898     }
    899   }
    900 }
    901 
    902 
    903 void Scope::AllocateNonParameterLocals() {
    904   // All variables that have no rewrite yet are non-parameter locals.
    905   for (int i = 0; i < temps_.length(); i++) {
    906     AllocateNonParameterLocal(temps_[i]);
    907   }
    908 
    909   for (VariableMap::Entry* p = variables_.Start();
    910        p != NULL;
    911        p = variables_.Next(p)) {
    912     Variable* var = reinterpret_cast<Variable*>(p->value);
    913     AllocateNonParameterLocal(var);
    914   }
    915 
    916   // For now, function_ must be allocated at the very end.  If it gets
    917   // allocated in the context, it must be the last slot in the context,
    918   // because of the current ScopeInfo implementation (see
    919   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
    920   if (function_ != NULL) {
    921     AllocateNonParameterLocal(function_);
    922   }
    923 }
    924 
    925 
    926 void Scope::AllocateVariablesRecursively() {
    927   // The number of slots required for variables.
    928   num_stack_slots_ = 0;
    929   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
    930 
    931   // Allocate variables for inner scopes.
    932   for (int i = 0; i < inner_scopes_.length(); i++) {
    933     inner_scopes_[i]->AllocateVariablesRecursively();
    934   }
    935 
    936   // Allocate variables for this scope.
    937   // Parameters must be allocated first, if any.
    938   if (is_function_scope()) AllocateParameterLocals();
    939   AllocateNonParameterLocals();
    940 
    941   // Allocate context if necessary.
    942   bool must_have_local_context = false;
    943   if (scope_calls_eval_ || scope_contains_with_) {
    944     // The context for the eval() call or 'with' statement in this scope.
    945     // Unless we are in the global or an eval scope, we need a local
    946     // context even if we didn't statically allocate any locals in it,
    947     // and the compiler will access the context variable. If we are
    948     // not in an inner scope, the scope is provided from the outside.
    949     must_have_local_context = is_function_scope();
    950   }
    951 
    952   // If we didn't allocate any locals in the local context, then we only
    953   // need the minimal number of slots if we must have a local context.
    954   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
    955       !must_have_local_context) {
    956     num_heap_slots_ = 0;
    957   }
    958 
    959   // Allocation done.
    960   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
    961 }
    962 
    963 } }  // namespace v8::internal
    964