| 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 |