| OLD | NEW | 
|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 64 static bool Match(void* key1, void* key2) { | 64 static bool Match(void* key1, void* key2) { | 
| 65   String* name1 = *reinterpret_cast<String**>(key1); | 65   String* name1 = *reinterpret_cast<String**>(key1); | 
| 66   String* name2 = *reinterpret_cast<String**>(key2); | 66   String* name2 = *reinterpret_cast<String**>(key2); | 
| 67   ASSERT(name1->IsSymbol()); | 67   ASSERT(name1->IsSymbol()); | 
| 68   ASSERT(name2->IsSymbol()); | 68   ASSERT(name2->IsSymbol()); | 
| 69   return name1 == name2; | 69   return name1 == name2; | 
| 70 } | 70 } | 
| 71 | 71 | 
| 72 | 72 | 
| 73 // Dummy constructor | 73 // Dummy constructor | 
| 74 LocalsMap::LocalsMap(bool gotta_love_static_overloading) : HashMap()  {} | 74 VariableMap::VariableMap(bool gotta_love_static_overloading) : HashMap() {} | 
| 75 | 75 | 
| 76 LocalsMap::LocalsMap() : HashMap(Match, &LocalsMapAllocator, 8)  {} | 76 VariableMap::VariableMap() : HashMap(Match, &LocalsMapAllocator, 8) {} | 
| 77 LocalsMap::~LocalsMap()  {} | 77 VariableMap::~VariableMap() {} | 
| 78 | 78 | 
| 79 | 79 | 
| 80 Variable* LocalsMap::Declare(Scope* scope, | 80 Variable* VariableMap::Declare(Scope* scope, | 
| 81                              Handle<String> name, | 81                                Handle<String> name, | 
| 82                              Variable::Mode mode, | 82                                Variable::Mode mode, | 
| 83                              bool is_valid_LHS, | 83                                bool is_valid_lhs, | 
| 84                              Variable::Kind kind) { | 84                                Variable::Kind kind) { | 
| 85   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); | 85   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); | 
| 86   if (p->value == NULL) { | 86   if (p->value == NULL) { | 
| 87     // The variable has not been declared yet -> insert it. | 87     // The variable has not been declared yet -> insert it. | 
| 88     ASSERT(p->key == name.location()); | 88     ASSERT(p->key == name.location()); | 
| 89     p->value = new Variable(scope, name, mode, is_valid_LHS, kind); | 89     p->value = new Variable(scope, name, mode, is_valid_lhs, kind); | 
| 90   } | 90   } | 
| 91   return reinterpret_cast<Variable*>(p->value); | 91   return reinterpret_cast<Variable*>(p->value); | 
| 92 } | 92 } | 
| 93 | 93 | 
| 94 | 94 | 
| 95 Variable* LocalsMap::Lookup(Handle<String> name) { | 95 Variable* VariableMap::Lookup(Handle<String> name) { | 
| 96   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); | 96   HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); | 
| 97   if (p != NULL) { | 97   if (p != NULL) { | 
| 98     ASSERT(*reinterpret_cast<String**>(p->key) == *name); | 98     ASSERT(*reinterpret_cast<String**>(p->key) == *name); | 
| 99     ASSERT(p->value != NULL); | 99     ASSERT(p->value != NULL); | 
| 100     return reinterpret_cast<Variable*>(p->value); | 100     return reinterpret_cast<Variable*>(p->value); | 
| 101   } | 101   } | 
| 102   return NULL; | 102   return NULL; | 
| 103 } | 103 } | 
| 104 | 104 | 
| 105 | 105 | 
| 106 // ---------------------------------------------------------------------------- | 106 // ---------------------------------------------------------------------------- | 
| 107 // Implementation of Scope | 107 // Implementation of Scope | 
| 108 | 108 | 
| 109 | 109 | 
| 110 // Dummy constructor | 110 // Dummy constructor | 
| 111 Scope::Scope() | 111 Scope::Scope() | 
| 112   : inner_scopes_(0), | 112   : inner_scopes_(0), | 
| 113     locals_(false), | 113     variables_(false), | 
| 114     temps_(0), | 114     temps_(0), | 
| 115     params_(0), | 115     params_(0), | 
| 116     dynamics_(NULL), | 116     dynamics_(NULL), | 
| 117     unresolved_(0), | 117     unresolved_(0), | 
| 118     decls_(0) { | 118     decls_(0) { | 
| 119 } | 119 } | 
| 120 | 120 | 
| 121 | 121 | 
| 122 Scope::Scope(Scope* outer_scope, Type type) | 122 Scope::Scope(Scope* outer_scope, Type type) | 
| 123   : outer_scope_(outer_scope), | 123   : outer_scope_(outer_scope), | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 161   } | 161   } | 
| 162 | 162 | 
| 163   // Declare convenience variables. | 163   // Declare convenience variables. | 
| 164   // Declare and allocate receiver (even for the global scope, and even | 164   // Declare and allocate receiver (even for the global scope, and even | 
| 165   // if naccesses_ == 0). | 165   // if naccesses_ == 0). | 
| 166   // NOTE: When loading parameters in the global scope, we must take | 166   // NOTE: When loading parameters in the global scope, we must take | 
| 167   // care not to access them as properties of the global object, but | 167   // care not to access them as properties of the global object, but | 
| 168   // instead load them directly from the stack. Currently, the only | 168   // instead load them directly from the stack. Currently, the only | 
| 169   // such parameter is 'this' which is passed on the stack when | 169   // such parameter is 'this' which is passed on the stack when | 
| 170   // invoking scripts | 170   // invoking scripts | 
| 171   { Variable* var = | 171   Variable* var = | 
| 172         locals_.Declare(this, Factory::this_symbol(), Variable::VAR, | 172       variables_.Declare(this, Factory::this_symbol(), Variable::VAR, | 
| 173                         false, Variable::THIS); | 173                          false, Variable::THIS); | 
| 174     var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 174   var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 
| 175     receiver_ = new VariableProxy(Factory::this_symbol(), true, false); | 175   receiver_ = new VariableProxy(Factory::this_symbol(), true, false); | 
| 176     receiver_->BindTo(var); | 176   receiver_->BindTo(var); | 
| 177   } |  | 
| 178 | 177 | 
| 179   if (is_function_scope()) { | 178   if (is_function_scope()) { | 
| 180     // Declare 'arguments' variable which exists in all functions. | 179     // Declare 'arguments' variable which exists in all functions. | 
| 181     // Note that it may never be accessed, in which case it won't | 180     // Note that it might never be accessed, in which case it won't be | 
| 182     // be allocated during variable allocation. | 181     // allocated during variable allocation. | 
| 183     locals_.Declare(this, Factory::arguments_symbol(), Variable::VAR, | 182     variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, | 
| 184                     true, Variable::ARGUMENTS); | 183                        true, Variable::ARGUMENTS); | 
| 185   } | 184   } | 
| 186 } | 185 } | 
| 187 | 186 | 
| 188 | 187 | 
| 189 | 188 | 
| 190 Variable* Scope::LookupLocal(Handle<String> name) { | 189 Variable* Scope::LocalLookup(Handle<String> name) { | 
| 191   return locals_.Lookup(name); | 190   return variables_.Lookup(name); | 
| 192 } | 191 } | 
| 193 | 192 | 
| 194 | 193 | 
| 195 Variable* Scope::Lookup(Handle<String> name) { | 194 Variable* Scope::Lookup(Handle<String> name) { | 
| 196   for (Scope* scope = this; | 195   for (Scope* scope = this; | 
| 197        scope != NULL; | 196        scope != NULL; | 
| 198        scope = scope->outer_scope()) { | 197        scope = scope->outer_scope()) { | 
| 199     Variable* var = scope->LookupLocal(name); | 198     Variable* var = scope->LocalLookup(name); | 
| 200     if (var != NULL) return var; | 199     if (var != NULL) return var; | 
| 201   } | 200   } | 
| 202   return NULL; | 201   return NULL; | 
| 203 } | 202 } | 
| 204 | 203 | 
| 205 | 204 | 
| 206 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 205 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 
| 207   ASSERT(is_function_scope() && function_ == NULL); | 206   ASSERT(is_function_scope() && function_ == NULL); | 
| 208   function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 207   function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 
| 209   return function_; | 208   return function_; | 
| 210 } | 209 } | 
| 211 | 210 | 
| 212 | 211 | 
| 213 Variable* Scope::Declare(Handle<String> name, Variable::Mode mode) { | 212 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { | 
| 214   // DYNAMIC variables are introduces during variable allocation, | 213   // DYNAMIC variables are introduces during variable allocation, | 
| 215   // INTERNAL variables are allocated explicitly, and TEMPORARY | 214   // INTERNAL variables are allocated explicitly, and TEMPORARY | 
| 216   // variables are allocated via NewTemporary(). | 215   // variables are allocated via NewTemporary(). | 
| 217   ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 216   ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 
| 218   return locals_.Declare(this, name, mode, true, Variable::NORMAL); | 217   return variables_.Declare(this, name, mode, true, Variable::NORMAL); | 
|  | 218 } | 
|  | 219 | 
|  | 220 | 
|  | 221 Variable* Scope::DeclareGlobal(Handle<String> name) { | 
|  | 222   ASSERT(is_global_scope()); | 
|  | 223   return variables_.Declare(this, name, Variable::DYNAMIC, true, | 
|  | 224                             Variable::NORMAL); | 
| 219 } | 225 } | 
| 220 | 226 | 
| 221 | 227 | 
| 222 void Scope::AddParameter(Variable* var) { | 228 void Scope::AddParameter(Variable* var) { | 
| 223   ASSERT(is_function_scope()); | 229   ASSERT(is_function_scope()); | 
| 224   ASSERT(LookupLocal(var->name()) == var); | 230   ASSERT(LocalLookup(var->name()) == var); | 
| 225   params_.Add(var); | 231   params_.Add(var); | 
| 226 } | 232 } | 
| 227 | 233 | 
| 228 | 234 | 
| 229 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { | 235 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { | 
| 230   // Note that we must not share the unresolved variables with | 236   // Note that we must not share the unresolved variables with | 
| 231   // the same name because they may be removed selectively via | 237   // the same name because they may be removed selectively via | 
| 232   // RemoveUnresolved(). | 238   // RemoveUnresolved(). | 
| 233   VariableProxy* proxy = new VariableProxy(name, false, inside_with); | 239   VariableProxy* proxy = new VariableProxy(name, false, inside_with); | 
| 234   unresolved_.Add(proxy); | 240   unresolved_.Add(proxy); | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 284   // Collect variables in this scope. | 290   // Collect variables in this scope. | 
| 285   // Note that the function_ variable - if present - is not | 291   // Note that the function_ variable - if present - is not | 
| 286   // collected here but handled separately in ScopeInfo | 292   // collected here but handled separately in ScopeInfo | 
| 287   // which is the current user of this function). | 293   // which is the current user of this function). | 
| 288   for (int i = 0; i < temps_.length(); i++) { | 294   for (int i = 0; i < temps_.length(); i++) { | 
| 289     Variable* var = temps_[i]; | 295     Variable* var = temps_[i]; | 
| 290     if (var->var_uses()->is_used()) { | 296     if (var->var_uses()->is_used()) { | 
| 291       locals->Add(var); | 297       locals->Add(var); | 
| 292     } | 298     } | 
| 293   } | 299   } | 
| 294   for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { | 300   for (VariableMap::Entry* p = variables_.Start(); | 
|  | 301        p != NULL; | 
|  | 302        p = variables_.Next(p)) { | 
| 295     Variable* var = reinterpret_cast<Variable*>(p->value); | 303     Variable* var = reinterpret_cast<Variable*>(p->value); | 
| 296     if (var->var_uses()->is_used()) { | 304     if (var->var_uses()->is_used()) { | 
| 297       locals->Add(var); | 305       locals->Add(var); | 
| 298     } | 306     } | 
| 299   } | 307   } | 
| 300 } | 308 } | 
| 301 | 309 | 
| 302 | 310 | 
| 303 // Make sure the method gets instantiated by the template system. | 311 // Make sure the method gets instantiated by the template system. | 
| 304 template void Scope::CollectUsedVariables( | 312 template void Scope::CollectUsedVariables( | 
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 403     if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, "); | 411     if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, "); | 
| 404     PrintF("var "); | 412     PrintF("var "); | 
| 405     var->var_uses()->Print(); | 413     var->var_uses()->Print(); | 
| 406     PrintF(", obj "); | 414     PrintF(", obj "); | 
| 407     var->obj_uses()->Print(); | 415     var->obj_uses()->Print(); | 
| 408     PrintF("\n"); | 416     PrintF("\n"); | 
| 409   } | 417   } | 
| 410 } | 418 } | 
| 411 | 419 | 
| 412 | 420 | 
| 413 static void PrintMap(PrettyPrinter* printer, int indent, LocalsMap* map) { | 421 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { | 
| 414   for (LocalsMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 422   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 
| 415     Variable* var = reinterpret_cast<Variable*>(p->value); | 423     Variable* var = reinterpret_cast<Variable*>(p->value); | 
| 416     PrintVar(printer, indent, var); | 424     PrintVar(printer, indent, var); | 
| 417   } | 425   } | 
| 418 } | 426 } | 
| 419 | 427 | 
| 420 | 428 | 
| 421 void Scope::Print(int n) { | 429 void Scope::Print(int n) { | 
| 422   int n0 = (n > 0 ? n : 0); | 430   int n0 = (n > 0 ? n : 0); | 
| 423   int n1 = n0 + 2;  // indentation | 431   int n1 = n0 + 2;  // indentation | 
| 424 | 432 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 471   if (function_ != NULL) { | 479   if (function_ != NULL) { | 
| 472     PrintVar(&printer, n1, function_); | 480     PrintVar(&printer, n1, function_); | 
| 473   } | 481   } | 
| 474 | 482 | 
| 475   Indent(n1, "// temporary vars\n"); | 483   Indent(n1, "// temporary vars\n"); | 
| 476   for (int i = 0; i < temps_.length(); i++) { | 484   for (int i = 0; i < temps_.length(); i++) { | 
| 477     PrintVar(&printer, n1, temps_[i]); | 485     PrintVar(&printer, n1, temps_[i]); | 
| 478   } | 486   } | 
| 479 | 487 | 
| 480   Indent(n1, "// local vars\n"); | 488   Indent(n1, "// local vars\n"); | 
| 481   PrintMap(&printer, n1, &locals_); | 489   PrintMap(&printer, n1, &variables_); | 
| 482 | 490 | 
| 483   Indent(n1, "// dynamic vars\n"); | 491   Indent(n1, "// dynamic vars\n"); | 
| 484   if (dynamics_ != NULL) { | 492   if (dynamics_ != NULL) { | 
| 485     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC)); | 493     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC)); | 
| 486     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); | 494     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); | 
| 487     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); | 495     PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); | 
| 488   } | 496   } | 
| 489 | 497 | 
| 490   // Print inner scopes (disable by providing negative n). | 498   // Print inner scopes (disable by providing negative n). | 
| 491   if (n >= 0) { | 499   if (n >= 0) { | 
| 492     for (int i = 0; i < inner_scopes_.length(); i++) { | 500     for (int i = 0; i < inner_scopes_.length(); i++) { | 
| 493       PrintF("\n"); | 501       PrintF("\n"); | 
| 494       inner_scopes_[i]->Print(n1); | 502       inner_scopes_[i]->Print(n1); | 
| 495     } | 503     } | 
| 496   } | 504   } | 
| 497 | 505 | 
| 498   Indent(n0, "}\n"); | 506   Indent(n0, "}\n"); | 
| 499 } | 507 } | 
| 500 #endif  // DEBUG | 508 #endif  // DEBUG | 
| 501 | 509 | 
| 502 | 510 | 
| 503 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 511 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 
| 504   if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 512   if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 
| 505   LocalsMap* map = dynamics_->GetMap(mode); | 513   VariableMap* map = dynamics_->GetMap(mode); | 
| 506   Variable* var = map->Lookup(name); | 514   Variable* var = map->Lookup(name); | 
| 507   if (var == NULL) { | 515   if (var == NULL) { | 
| 508     // Declare a new non-local. | 516     // Declare a new non-local. | 
| 509     var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 517     var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 
| 510     // Allocate it by giving it a dynamic lookup. | 518     // Allocate it by giving it a dynamic lookup. | 
| 511     var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 519     var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 
| 512   } | 520   } | 
| 513   return var; | 521   return var; | 
| 514 } | 522 } | 
| 515 | 523 | 
| 516 | 524 | 
| 517 // Lookup a variable starting with this scope. The result is either | 525 // Lookup a variable starting with this scope. The result is either | 
| 518 // the statically resolved (local!) variable belonging to an outer scope, | 526 // the statically resolved (local!) variable belonging to an outer scope, | 
| 519 // or NULL. It may be NULL because a) we couldn't find a variable, or b) | 527 // or NULL. It may be NULL because a) we couldn't find a variable, or b) | 
| 520 // because the variable is just a guess (and may be shadowed by another | 528 // because the variable is just a guess (and may be shadowed by another | 
| 521 // variable that is introduced dynamically via an 'eval' call or a 'with' | 529 // variable that is introduced dynamically via an 'eval' call or a 'with' | 
| 522 // statement). | 530 // statement). | 
| 523 Variable* Scope::LookupRecursive(Handle<String> name, | 531 Variable* Scope::LookupRecursive(Handle<String> name, | 
| 524                                  bool inner_lookup, | 532                                  bool inner_lookup, | 
| 525                                  Variable** invalidated_local) { | 533                                  Variable** invalidated_local) { | 
| 526   // If we find a variable, but the current scope calls 'eval', the found | 534   // If we find a variable, but the current scope calls 'eval', the found | 
| 527   // variable may not be the correct one (the 'eval' may introduce a | 535   // variable may not be the correct one (the 'eval' may introduce a | 
| 528   // property with the same name). In that case, remember that the variable | 536   // property with the same name). In that case, remember that the variable | 
| 529   // found is just a guess. | 537   // found is just a guess. | 
| 530   bool guess = scope_calls_eval_; | 538   bool guess = scope_calls_eval_; | 
| 531 | 539 | 
| 532   // Try to find the variable in this scope. | 540   // Try to find the variable in this scope. | 
| 533   Variable* var = LookupLocal(name); | 541   Variable* var = LocalLookup(name); | 
| 534 | 542 | 
| 535   if (var != NULL) { | 543   if (var != NULL) { | 
| 536     // We found a variable. If this is not an inner lookup, we are done. | 544     // We found a variable. If this is not an inner lookup, we are done. | 
| 537     // (Even if there is an 'eval' in this scope which introduces the | 545     // (Even if there is an 'eval' in this scope which introduces the | 
| 538     // same variable again, the resulting variable remains the same. | 546     // same variable again, the resulting variable remains the same. | 
| 539     // Note that enclosing 'with' statements are handled at the call site.) | 547     // Note that enclosing 'with' statements are handled at the call site.) | 
| 540     if (!inner_lookup) | 548     if (!inner_lookup) | 
| 541       return var; | 549       return var; | 
| 542 | 550 | 
| 543   } else { | 551   } else { | 
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 614       // are outside a 'with' statement) or if there is no way | 622       // are outside a 'with' statement) or if there is no way | 
| 615       // that the variable might be introduced dynamically (through | 623       // that the variable might be introduced dynamically (through | 
| 616       // a local or outer eval() call, or an outer 'with' statement), | 624       // a local or outer eval() call, or an outer 'with' statement), | 
| 617       // or we don't know about the outer scope (because we are | 625       // or we don't know about the outer scope (because we are | 
| 618       // in an eval scope). | 626       // in an eval scope). | 
| 619       if (is_global_scope() || | 627       if (is_global_scope() || | 
| 620           !(scope_inside_with_ || outer_scope_is_eval_scope_ || | 628           !(scope_inside_with_ || outer_scope_is_eval_scope_ || | 
| 621             scope_calls_eval_ || outer_scope_calls_eval_)) { | 629             scope_calls_eval_ || outer_scope_calls_eval_)) { | 
| 622         // We must have a global variable. | 630         // We must have a global variable. | 
| 623         ASSERT(global_scope != NULL); | 631         ASSERT(global_scope != NULL); | 
| 624         var = new Variable(global_scope, proxy->name(), | 632         var = global_scope->DeclareGlobal(proxy->name()); | 
| 625                            Variable::DYNAMIC, true, Variable::NORMAL); |  | 
| 626 | 633 | 
| 627       } else if (scope_inside_with_) { | 634       } else if (scope_inside_with_) { | 
| 628         // If we are inside a with statement we give up and look up | 635         // If we are inside a with statement we give up and look up | 
| 629         // the variable at runtime. | 636         // the variable at runtime. | 
| 630         var = NonLocal(proxy->name(), Variable::DYNAMIC); | 637         var = NonLocal(proxy->name(), Variable::DYNAMIC); | 
| 631 | 638 | 
| 632       } else if (invalidated_local != NULL) { | 639       } else if (invalidated_local != NULL) { | 
| 633         // No with statements are involved and we found a local | 640         // No with statements are involved and we found a local | 
| 634         // variable that might be shadowed by eval introduced | 641         // variable that might be shadowed by eval introduced | 
| 635         // variables. | 642         // variables. | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 699     if (inner_scope->force_eager_compilation_) { | 706     if (inner_scope->force_eager_compilation_) { | 
| 700       force_eager_compilation_ = true; | 707       force_eager_compilation_ = true; | 
| 701     } | 708     } | 
| 702   } | 709   } | 
| 703 | 710 | 
| 704   return scope_calls_eval_ || inner_scope_calls_eval_; | 711   return scope_calls_eval_ || inner_scope_calls_eval_; | 
| 705 } | 712 } | 
| 706 | 713 | 
| 707 | 714 | 
| 708 bool Scope::MustAllocate(Variable* var) { | 715 bool Scope::MustAllocate(Variable* var) { | 
| 709   // Give var a read/write use if there is a chance it might be | 716   // Give var a read/write use if there is a chance it might be accessed | 
| 710   // accessed via an eval() call, or if it is a global variable. | 717   // via an eval() call.  This is only possible if the variable has a | 
| 711   // This is only possible if the variable has a visible name. | 718   // visible name. | 
| 712   if ((var->is_this() || var->name()->length() > 0) && | 719   if ((var->is_this() || var->name()->length() > 0) && | 
| 713       (var->is_accessed_from_inner_scope_ || | 720       (var->is_accessed_from_inner_scope_ || | 
| 714        scope_calls_eval_ || inner_scope_calls_eval_ || | 721        scope_calls_eval_ || inner_scope_calls_eval_ || | 
| 715        scope_contains_with_ || var->is_global())) { | 722        scope_contains_with_)) { | 
| 716     var->var_uses()->RecordAccess(1); | 723     var->var_uses()->RecordAccess(1); | 
| 717   } | 724   } | 
| 718   return var->var_uses()->is_used(); | 725   // Global variables do not need to be allocated. | 
|  | 726   return !var->is_global() && var->var_uses()->is_used(); | 
| 719 } | 727 } | 
| 720 | 728 | 
| 721 | 729 | 
| 722 bool Scope::MustAllocateInContext(Variable* var) { | 730 bool Scope::MustAllocateInContext(Variable* var) { | 
| 723   // If var is accessed from an inner scope, or if there is a | 731   // If var is accessed from an inner scope, or if there is a | 
| 724   // possibility that it might be accessed from the current or | 732   // possibility that it might be accessed from the current or an inner | 
| 725   // an inner scope (through an eval() call), it must be allocated | 733   // scope (through an eval() call), it must be allocated in the | 
| 726   // in the context. | 734   // context.  Exception: temporary variables are not allocated in the | 
| 727   // Exceptions: Global variables and temporary variables must | 735   // context. | 
| 728   // never be allocated in the (FixedArray part of the) context. |  | 
| 729   return | 736   return | 
| 730     var->mode() != Variable::TEMPORARY && | 737     var->mode() != Variable::TEMPORARY && | 
| 731     (var->is_accessed_from_inner_scope_ || | 738     (var->is_accessed_from_inner_scope_ || | 
| 732      scope_calls_eval_ || inner_scope_calls_eval_ || | 739      scope_calls_eval_ || inner_scope_calls_eval_ || | 
| 733      scope_contains_with_ || var->is_global()); | 740      scope_contains_with_ || var->is_global()); | 
| 734 } | 741 } | 
| 735 | 742 | 
| 736 | 743 | 
| 737 bool Scope::HasArgumentsParameter() { | 744 bool Scope::HasArgumentsParameter() { | 
| 738   for (int i = 0; i < params_.length(); i++) { | 745   for (int i = 0; i < params_.length(); i++) { | 
| 739     if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) | 746     if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) | 
| 740       return true; | 747       return true; | 
| 741   } | 748   } | 
| 742   return false; | 749   return false; | 
| 743 } | 750 } | 
| 744 | 751 | 
| 745 | 752 | 
| 746 void Scope::AllocateStackSlot(Variable* var) { | 753 void Scope::AllocateStackSlot(Variable* var) { | 
| 747   var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); | 754   var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); | 
| 748 } | 755 } | 
| 749 | 756 | 
| 750 | 757 | 
| 751 void Scope::AllocateHeapSlot(Variable* var) { | 758 void Scope::AllocateHeapSlot(Variable* var) { | 
| 752   var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); | 759   var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); | 
| 753 } | 760 } | 
| 754 | 761 | 
| 755 | 762 | 
| 756 void Scope::AllocateParameterLocals() { | 763 void Scope::AllocateParameterLocals() { | 
| 757   ASSERT(is_function_scope()); | 764   ASSERT(is_function_scope()); | 
| 758   Variable* arguments = LookupLocal(Factory::arguments_symbol()); | 765   Variable* arguments = LocalLookup(Factory::arguments_symbol()); | 
| 759   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly | 766   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly | 
| 760   if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 767   if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 
| 761     // 'arguments' is used. Unless there is also a parameter called | 768     // 'arguments' is used. Unless there is also a parameter called | 
| 762     // 'arguments', we must be conservative and access all parameters via | 769     // 'arguments', we must be conservative and access all parameters via | 
| 763     // the arguments object: The i'th parameter is rewritten into | 770     // the arguments object: The i'th parameter is rewritten into | 
| 764     // '.arguments[i]' (*). If we have a parameter named 'arguments', a | 771     // '.arguments[i]' (*). If we have a parameter named 'arguments', a | 
| 765     // (new) value is always assigned to it via the function | 772     // (new) value is always assigned to it via the function | 
| 766     // invocation. Then 'arguments' denotes that specific parameter value | 773     // invocation. Then 'arguments' denotes that specific parameter value | 
| 767     // and cannot be used to access the parameters, which is why we don't | 774     // and cannot be used to access the parameters, which is why we don't | 
| 768     // need to rewrite in that case. | 775     // need to rewrite in that case. | 
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 858     } | 865     } | 
| 859   } | 866   } | 
| 860 } | 867 } | 
| 861 | 868 | 
| 862 | 869 | 
| 863 void Scope::AllocateNonParameterLocal(Variable* var) { | 870 void Scope::AllocateNonParameterLocal(Variable* var) { | 
| 864   ASSERT(var->scope() == this); | 871   ASSERT(var->scope() == this); | 
| 865   ASSERT(var->rewrite_ == NULL || | 872   ASSERT(var->rewrite_ == NULL || | 
| 866          (!var->IsVariable(Factory::result_symbol())) || | 873          (!var->IsVariable(Factory::result_symbol())) || | 
| 867          (var->slot() == NULL || var->slot()->type() != Slot::LOCAL)); | 874          (var->slot() == NULL || var->slot()->type() != Slot::LOCAL)); | 
| 868   if (MustAllocate(var) && var->rewrite_ == NULL) { | 875   if (var->rewrite_ == NULL && MustAllocate(var)) { | 
| 869     if (MustAllocateInContext(var)) { | 876     if (MustAllocateInContext(var)) { | 
| 870       AllocateHeapSlot(var); | 877       AllocateHeapSlot(var); | 
| 871     } else { | 878     } else { | 
| 872       AllocateStackSlot(var); | 879       AllocateStackSlot(var); | 
| 873     } | 880     } | 
| 874   } | 881   } | 
| 875 } | 882 } | 
| 876 | 883 | 
| 877 | 884 | 
| 878 void Scope::AllocateNonParameterLocals() { | 885 void Scope::AllocateNonParameterLocals() { | 
| 879   // Each variable occurs exactly once in the locals_ list; all | 886   // All variables that have no rewrite yet are non-parameter locals. | 
| 880   // variables that have no rewrite yet are non-parameter locals. |  | 
| 881 |  | 
| 882   // Sort them according to use such that the locals with more uses |  | 
| 883   // get allocated first. |  | 
| 884   if (FLAG_usage_computation) { |  | 
| 885     // This is currently not implemented. |  | 
| 886   } |  | 
| 887 |  | 
| 888   for (int i = 0; i < temps_.length(); i++) { | 887   for (int i = 0; i < temps_.length(); i++) { | 
| 889     AllocateNonParameterLocal(temps_[i]); | 888     AllocateNonParameterLocal(temps_[i]); | 
| 890   } | 889   } | 
| 891 | 890 | 
| 892   for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { | 891   for (VariableMap::Entry* p = variables_.Start(); | 
|  | 892        p != NULL; | 
|  | 893        p = variables_.Next(p)) { | 
| 893     Variable* var = reinterpret_cast<Variable*>(p->value); | 894     Variable* var = reinterpret_cast<Variable*>(p->value); | 
| 894     AllocateNonParameterLocal(var); | 895     AllocateNonParameterLocal(var); | 
| 895   } | 896   } | 
| 896 | 897 | 
| 897   // Note: For now, function_ must be allocated at the very end.  If | 898   // For now, function_ must be allocated at the very end.  If it gets | 
| 898   // it gets allocated in the context, it must be the last slot in the | 899   // allocated in the context, it must be the last slot in the context, | 
| 899   // context, because of the current ScopeInfo implementation (see | 900   // because of the current ScopeInfo implementation (see | 
| 900   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 901   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 
| 901   if (function_ != NULL) { | 902   if (function_ != NULL) { | 
| 902     AllocateNonParameterLocal(function_); | 903     AllocateNonParameterLocal(function_); | 
| 903   } | 904   } | 
| 904 } | 905 } | 
| 905 | 906 | 
| 906 | 907 | 
| 907 void Scope::AllocateVariablesRecursively() { | 908 void Scope::AllocateVariablesRecursively() { | 
| 908   // The number of slots required for variables. | 909   // The number of slots required for variables. | 
| 909   num_stack_slots_ = 0; | 910   num_stack_slots_ = 0; | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 935   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 936   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 
| 936       !must_have_local_context) { | 937       !must_have_local_context) { | 
| 937     num_heap_slots_ = 0; | 938     num_heap_slots_ = 0; | 
| 938   } | 939   } | 
| 939 | 940 | 
| 940   // Allocation done. | 941   // Allocation done. | 
| 941   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 942   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 
| 942 } | 943 } | 
| 943 | 944 | 
| 944 } }  // namespace v8::internal | 945 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|