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 |