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