OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 return NULL; | 105 return NULL; |
106 } | 106 } |
107 | 107 |
108 | 108 |
109 // ---------------------------------------------------------------------------- | 109 // ---------------------------------------------------------------------------- |
110 // Implementation of Scope | 110 // Implementation of Scope |
111 | 111 |
112 | 112 |
113 // Dummy constructor | 113 // Dummy constructor |
114 Scope::Scope(Type type) | 114 Scope::Scope(Type type) |
115 : outer_scope_(NULL), | 115 : inner_scopes_(0), |
116 inner_scopes_(0), | |
117 type_(type), | |
118 scope_name_(Factory::empty_symbol()), | |
119 variables_(false), | 116 variables_(false), |
120 temps_(0), | 117 temps_(0), |
121 params_(0), | 118 params_(0), |
122 dynamics_(NULL), | |
123 unresolved_(0), | 119 unresolved_(0), |
124 decls_(0), | 120 decls_(0) { |
125 receiver_(NULL), | 121 SetDefaults(type, NULL, NULL); |
126 function_(NULL), | 122 ASSERT(!resolved()); |
127 arguments_(NULL), | |
128 arguments_shadow_(NULL), | |
129 illegal_redecl_(NULL), | |
130 scope_inside_with_(false), | |
131 scope_contains_with_(false), | |
132 scope_calls_eval_(false), | |
133 outer_scope_calls_eval_(false), | |
134 inner_scope_calls_eval_(false), | |
135 outer_scope_is_eval_scope_(false), | |
136 force_eager_compilation_(false), | |
137 num_stack_slots_(0), | |
138 num_heap_slots_(0) { | |
139 } | 123 } |
140 | 124 |
141 | 125 |
142 Scope::Scope(Scope* outer_scope, Type type) | 126 Scope::Scope(Scope* outer_scope, Type type) |
143 : outer_scope_(outer_scope), | 127 : inner_scopes_(4), |
144 inner_scopes_(4), | 128 variables_(), |
145 type_(type), | |
146 scope_name_(Factory::empty_symbol()), | |
147 temps_(4), | 129 temps_(4), |
148 params_(4), | 130 params_(4), |
149 dynamics_(NULL), | |
150 unresolved_(16), | 131 unresolved_(16), |
151 decls_(4), | 132 decls_(4) { |
152 receiver_(NULL), | |
153 function_(NULL), | |
154 arguments_(NULL), | |
155 arguments_shadow_(NULL), | |
156 illegal_redecl_(NULL), | |
157 scope_inside_with_(false), | |
158 scope_contains_with_(false), | |
159 scope_calls_eval_(false), | |
160 outer_scope_calls_eval_(false), | |
161 inner_scope_calls_eval_(false), | |
162 outer_scope_is_eval_scope_(false), | |
163 force_eager_compilation_(false), | |
164 num_stack_slots_(0), | |
165 num_heap_slots_(0) { | |
166 // At some point we might want to provide outer scopes to | 133 // At some point we might want to provide outer scopes to |
167 // eval scopes (by walking the stack and reading the scope info). | 134 // eval scopes (by walking the stack and reading the scope info). |
168 // In that case, the ASSERT below needs to be adjusted. | 135 // In that case, the ASSERT below needs to be adjusted. |
| 136 SetDefaults(type, outer_scope, NULL); |
169 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); | 137 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); |
170 ASSERT(!HasIllegalRedeclaration()); | 138 ASSERT(!HasIllegalRedeclaration()); |
| 139 ASSERT(!resolved()); |
171 } | 140 } |
172 | 141 |
173 | 142 |
| 143 Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info) |
| 144 : inner_scopes_(4), |
| 145 variables_(), |
| 146 temps_(4), |
| 147 params_(4), |
| 148 unresolved_(16), |
| 149 decls_(4) { |
| 150 ASSERT(scope_info != NULL); |
| 151 SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info); |
| 152 ASSERT(resolved()); |
| 153 InsertAfterScope(inner_scope); |
| 154 if (scope_info->HasHeapAllocatedLocals()) { |
| 155 num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
| 156 } |
| 157 } |
| 158 |
| 159 |
| 160 |
174 bool Scope::Analyze(CompilationInfo* info) { | 161 bool Scope::Analyze(CompilationInfo* info) { |
175 ASSERT(info->function() != NULL); | 162 ASSERT(info->function() != NULL); |
176 Scope* top = info->function()->scope(); | 163 Scope* top = info->function()->scope(); |
| 164 |
| 165 // If we have a serialized scope info, reuse it. |
| 166 if (!info->closure().is_null()) { |
| 167 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); |
| 168 if (scope_info != SerializedScopeInfo::Empty()) { |
| 169 Scope* scope = top; |
| 170 JSFunction* current = *info->closure(); |
| 171 do { |
| 172 current = current->context()->closure(); |
| 173 SerializedScopeInfo* scope_info = current->shared()->scope_info(); |
| 174 if (scope_info != SerializedScopeInfo::Empty()) { |
| 175 scope = new Scope(scope, scope_info); |
| 176 } else { |
| 177 ASSERT(current->context()->IsGlobalContext()); |
| 178 } |
| 179 } while (!current->context()->IsGlobalContext()); |
| 180 } |
| 181 } |
| 182 |
177 while (top->outer_scope() != NULL) top = top->outer_scope(); | 183 while (top->outer_scope() != NULL) top = top->outer_scope(); |
178 top->AllocateVariables(info->calling_context()); | 184 top->AllocateVariables(info->calling_context()); |
179 | 185 |
180 #ifdef DEBUG | 186 #ifdef DEBUG |
181 if (Bootstrapper::IsActive() | 187 if (Bootstrapper::IsActive() |
182 ? FLAG_print_builtin_scopes | 188 ? FLAG_print_builtin_scopes |
183 : FLAG_print_scopes) { | 189 : FLAG_print_scopes) { |
184 info->function()->scope()->Print(); | 190 info->function()->scope()->Print(); |
185 } | 191 } |
186 #endif | 192 #endif |
187 | 193 |
188 info->SetScope(info->function()->scope()); | 194 info->SetScope(info->function()->scope()); |
189 return true; // Can not fail. | 195 return true; // Can not fail. |
190 } | 196 } |
191 | 197 |
192 | 198 |
193 void Scope::Initialize(bool inside_with) { | 199 void Scope::Initialize(bool inside_with) { |
| 200 ASSERT(!resolved()); |
| 201 |
194 // Add this scope as a new inner scope of the outer scope. | 202 // Add this scope as a new inner scope of the outer scope. |
195 if (outer_scope_ != NULL) { | 203 if (outer_scope_ != NULL) { |
196 outer_scope_->inner_scopes_.Add(this); | 204 outer_scope_->inner_scopes_.Add(this); |
197 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; | 205 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; |
198 } else { | 206 } else { |
199 scope_inside_with_ = inside_with; | 207 scope_inside_with_ = inside_with; |
200 } | 208 } |
201 | 209 |
202 // Declare convenience variables. | 210 // Declare convenience variables. |
203 // Declare and allocate receiver (even for the global scope, and even | 211 // Declare and allocate receiver (even for the global scope, and even |
204 // if naccesses_ == 0). | 212 // if naccesses_ == 0). |
205 // NOTE: When loading parameters in the global scope, we must take | 213 // NOTE: When loading parameters in the global scope, we must take |
206 // care not to access them as properties of the global object, but | 214 // care not to access them as properties of the global object, but |
207 // instead load them directly from the stack. Currently, the only | 215 // instead load them directly from the stack. Currently, the only |
208 // such parameter is 'this' which is passed on the stack when | 216 // such parameter is 'this' which is passed on the stack when |
209 // invoking scripts | 217 // invoking scripts |
210 Variable* var = | 218 Variable* var = |
211 variables_.Declare(this, Factory::this_symbol(), Variable::VAR, | 219 variables_.Declare(this, Factory::this_symbol(), Variable::VAR, |
212 false, Variable::THIS); | 220 false, Variable::THIS); |
213 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 221 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1)); |
214 receiver_ = var; | 222 receiver_ = var; |
215 | 223 |
216 if (is_function_scope()) { | 224 if (is_function_scope()) { |
217 // Declare 'arguments' variable which exists in all functions. | 225 // Declare 'arguments' variable which exists in all functions. |
218 // Note that it might never be accessed, in which case it won't be | 226 // Note that it might never be accessed, in which case it won't be |
219 // allocated during variable allocation. | 227 // allocated during variable allocation. |
220 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, | 228 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, |
221 true, Variable::ARGUMENTS); | 229 true, Variable::ARGUMENTS); |
222 } | 230 } |
223 } | 231 } |
224 | 232 |
225 | 233 |
226 Variable* Scope::LocalLookup(Handle<String> name) { | 234 Variable* Scope::LocalLookup(Handle<String> name) { |
227 return variables_.Lookup(name); | 235 if (!resolved()) { |
| 236 return variables_.Lookup(name); |
| 237 } |
| 238 |
| 239 // Check arguments object lookup. |
| 240 if (*name == *Factory::arguments_symbol()) { |
| 241 return new Variable(this, name, Variable::VAR, true, Variable::ARGUMENTS); |
| 242 } |
| 243 |
| 244 // Check context slot lookup. |
| 245 Variable::Mode mode; |
| 246 int index = scope_info_->ContextSlotIndex(*name, &mode); |
| 247 if (index < 0) { |
| 248 return NULL; |
| 249 } |
| 250 |
| 251 Variable* var = new Variable(this, name, mode, true, Variable::NORMAL); |
| 252 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
| 253 return var; |
228 } | 254 } |
229 | 255 |
230 | 256 |
231 Variable* Scope::Lookup(Handle<String> name) { | 257 Variable* Scope::Lookup(Handle<String> name) { |
232 for (Scope* scope = this; | 258 for (Scope* scope = this; |
233 scope != NULL; | 259 scope != NULL; |
234 scope = scope->outer_scope()) { | 260 scope = scope->outer_scope()) { |
235 Variable* var = scope->LocalLookup(name); | 261 Variable* var = scope->LocalLookup(name); |
236 if (var != NULL) return var; | 262 if (var != NULL) return var; |
237 } | 263 } |
238 return NULL; | 264 return NULL; |
239 } | 265 } |
240 | 266 |
241 | 267 |
242 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 268 Variable* Scope::DeclareFunctionVar(Handle<String> name) { |
243 ASSERT(is_function_scope() && function_ == NULL); | 269 ASSERT(is_function_scope() && function_ == NULL); |
244 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 270 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); |
245 return function_; | 271 return function_; |
246 } | 272 } |
247 | 273 |
248 | 274 |
249 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { | 275 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { |
250 // DYNAMIC variables are introduces during variable allocation, | 276 // DYNAMIC variables are introduces during variable allocation, |
251 // INTERNAL variables are allocated explicitly, and TEMPORARY | 277 // INTERNAL variables are allocated explicitly, and TEMPORARY |
252 // variables are allocated via NewTemporary(). | 278 // variables are allocated via NewTemporary(). |
| 279 ASSERT(!resolved()); |
253 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 280 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
254 return variables_.Declare(this, name, mode, true, Variable::NORMAL); | 281 return variables_.Declare(this, name, mode, true, Variable::NORMAL); |
255 } | 282 } |
256 | 283 |
257 | 284 |
258 Variable* Scope::DeclareGlobal(Handle<String> name) { | 285 Variable* Scope::DeclareGlobal(Handle<String> name) { |
259 ASSERT(is_global_scope()); | 286 ASSERT(is_global_scope()); |
260 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, | 287 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, |
261 Variable::NORMAL); | 288 Variable::NORMAL); |
262 } | 289 } |
263 | 290 |
264 | 291 |
265 void Scope::AddParameter(Variable* var) { | 292 void Scope::AddParameter(Variable* var) { |
266 ASSERT(is_function_scope()); | 293 ASSERT(is_function_scope()); |
267 ASSERT(LocalLookup(var->name()) == var); | 294 ASSERT(LocalLookup(var->name()) == var); |
268 params_.Add(var); | 295 params_.Add(var); |
269 } | 296 } |
270 | 297 |
271 | 298 |
272 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { | 299 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { |
273 // Note that we must not share the unresolved variables with | 300 // Note that we must not share the unresolved variables with |
274 // the same name because they may be removed selectively via | 301 // the same name because they may be removed selectively via |
275 // RemoveUnresolved(). | 302 // RemoveUnresolved(). |
| 303 ASSERT(!resolved()); |
276 VariableProxy* proxy = new VariableProxy(name, false, inside_with); | 304 VariableProxy* proxy = new VariableProxy(name, false, inside_with); |
277 unresolved_.Add(proxy); | 305 unresolved_.Add(proxy); |
278 return proxy; | 306 return proxy; |
279 } | 307 } |
280 | 308 |
281 | 309 |
282 void Scope::RemoveUnresolved(VariableProxy* var) { | 310 void Scope::RemoveUnresolved(VariableProxy* var) { |
283 // Most likely (always?) any variable we want to remove | 311 // Most likely (always?) any variable we want to remove |
284 // was just added before, so we search backwards. | 312 // was just added before, so we search backwards. |
285 for (int i = unresolved_.length(); i-- > 0;) { | 313 for (int i = unresolved_.length(); i-- > 0;) { |
286 if (unresolved_[i] == var) { | 314 if (unresolved_[i] == var) { |
287 unresolved_.Remove(i); | 315 unresolved_.Remove(i); |
288 return; | 316 return; |
289 } | 317 } |
290 } | 318 } |
291 } | 319 } |
292 | 320 |
293 | 321 |
294 Variable* Scope::NewTemporary(Handle<String> name) { | 322 Variable* Scope::NewTemporary(Handle<String> name) { |
| 323 ASSERT(!resolved()); |
295 Variable* var = | 324 Variable* var = |
296 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); | 325 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); |
297 temps_.Add(var); | 326 temps_.Add(var); |
298 return var; | 327 return var; |
299 } | 328 } |
300 | 329 |
301 | 330 |
302 void Scope::AddDeclaration(Declaration* declaration) { | 331 void Scope::AddDeclaration(Declaration* declaration) { |
303 decls_.Add(declaration); | 332 decls_.Add(declaration); |
304 } | 333 } |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 | 572 |
544 | 573 |
545 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 574 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
546 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 575 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); |
547 VariableMap* map = dynamics_->GetMap(mode); | 576 VariableMap* map = dynamics_->GetMap(mode); |
548 Variable* var = map->Lookup(name); | 577 Variable* var = map->Lookup(name); |
549 if (var == NULL) { | 578 if (var == NULL) { |
550 // Declare a new non-local. | 579 // Declare a new non-local. |
551 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 580 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
552 // Allocate it by giving it a dynamic lookup. | 581 // Allocate it by giving it a dynamic lookup. |
553 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 582 var->set_rewrite(new Slot(var, Slot::LOOKUP, -1)); |
554 } | 583 } |
555 return var; | 584 return var; |
556 } | 585 } |
557 | 586 |
558 | 587 |
559 // Lookup a variable starting with this scope. The result is either | 588 // Lookup a variable starting with this scope. The result is either |
560 // the statically resolved variable belonging to an outer scope, or | 589 // the statically resolved variable belonging to an outer scope, or |
561 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 590 // NULL. It may be NULL because a) we couldn't find a variable, or b) |
562 // because the variable is just a guess (and may be shadowed by | 591 // because the variable is just a guess (and may be shadowed by |
563 // another variable that is introduced dynamically via an 'eval' call | 592 // another variable that is introduced dynamically via an 'eval' call |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 } | 634 } |
606 | 635 |
607 // If we did not find a variable, we are done. | 636 // If we did not find a variable, we are done. |
608 if (var == NULL) | 637 if (var == NULL) |
609 return NULL; | 638 return NULL; |
610 } | 639 } |
611 | 640 |
612 ASSERT(var != NULL); | 641 ASSERT(var != NULL); |
613 | 642 |
614 // If this is a lookup from an inner scope, mark the variable. | 643 // If this is a lookup from an inner scope, mark the variable. |
615 if (inner_lookup) | 644 if (inner_lookup) { |
616 var->is_accessed_from_inner_scope_ = true; | 645 var->MarkAsAccessedFromInnerScope(); |
| 646 } |
617 | 647 |
618 // If the variable we have found is just a guess, invalidate the | 648 // If the variable we have found is just a guess, invalidate the |
619 // result. If the found variable is local, record that fact so we | 649 // result. If the found variable is local, record that fact so we |
620 // can generate fast code to get it if it is not shadowed by eval. | 650 // can generate fast code to get it if it is not shadowed by eval. |
621 if (guess) { | 651 if (guess) { |
622 if (!var->is_global()) *invalidated_local = var; | 652 if (!var->is_global()) *invalidated_local = var; |
623 var = NULL; | 653 var = NULL; |
624 } | 654 } |
625 | 655 |
626 return var; | 656 return var; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 | 776 |
747 return scope_calls_eval_ || inner_scope_calls_eval_; | 777 return scope_calls_eval_ || inner_scope_calls_eval_; |
748 } | 778 } |
749 | 779 |
750 | 780 |
751 bool Scope::MustAllocate(Variable* var) { | 781 bool Scope::MustAllocate(Variable* var) { |
752 // Give var a read/write use if there is a chance it might be accessed | 782 // Give var a read/write use if there is a chance it might be accessed |
753 // via an eval() call. This is only possible if the variable has a | 783 // via an eval() call. This is only possible if the variable has a |
754 // visible name. | 784 // visible name. |
755 if ((var->is_this() || var->name()->length() > 0) && | 785 if ((var->is_this() || var->name()->length() > 0) && |
756 (var->is_accessed_from_inner_scope_ || | 786 (var->is_accessed_from_inner_scope() || |
757 scope_calls_eval_ || inner_scope_calls_eval_ || | 787 scope_calls_eval_ || inner_scope_calls_eval_ || |
758 scope_contains_with_)) { | 788 scope_contains_with_)) { |
759 var->set_is_used(true); | 789 var->set_is_used(true); |
760 } | 790 } |
761 // Global variables do not need to be allocated. | 791 // Global variables do not need to be allocated. |
762 return !var->is_global() && var->is_used(); | 792 return !var->is_global() && var->is_used(); |
763 } | 793 } |
764 | 794 |
765 | 795 |
766 bool Scope::MustAllocateInContext(Variable* var) { | 796 bool Scope::MustAllocateInContext(Variable* var) { |
767 // If var is accessed from an inner scope, or if there is a | 797 // If var is accessed from an inner scope, or if there is a |
768 // possibility that it might be accessed from the current or an inner | 798 // possibility that it might be accessed from the current or an inner |
769 // scope (through an eval() call), it must be allocated in the | 799 // scope (through an eval() call), it must be allocated in the |
770 // context. Exception: temporary variables are not allocated in the | 800 // context. Exception: temporary variables are not allocated in the |
771 // context. | 801 // context. |
772 return | 802 return |
773 var->mode() != Variable::TEMPORARY && | 803 var->mode() != Variable::TEMPORARY && |
774 (var->is_accessed_from_inner_scope_ || | 804 (var->is_accessed_from_inner_scope() || |
775 scope_calls_eval_ || inner_scope_calls_eval_ || | 805 scope_calls_eval_ || inner_scope_calls_eval_ || |
776 scope_contains_with_ || var->is_global()); | 806 scope_contains_with_ || var->is_global()); |
777 } | 807 } |
778 | 808 |
779 | 809 |
780 bool Scope::HasArgumentsParameter() { | 810 bool Scope::HasArgumentsParameter() { |
781 for (int i = 0; i < params_.length(); i++) { | 811 for (int i = 0; i < params_.length(); i++) { |
782 if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) | 812 if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) |
783 return true; | 813 return true; |
784 } | 814 } |
785 return false; | 815 return false; |
786 } | 816 } |
787 | 817 |
788 | 818 |
789 void Scope::AllocateStackSlot(Variable* var) { | 819 void Scope::AllocateStackSlot(Variable* var) { |
790 var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); | 820 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++)); |
791 } | 821 } |
792 | 822 |
793 | 823 |
794 void Scope::AllocateHeapSlot(Variable* var) { | 824 void Scope::AllocateHeapSlot(Variable* var) { |
795 var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); | 825 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); |
796 } | 826 } |
797 | 827 |
798 | 828 |
799 void Scope::AllocateParameterLocals() { | 829 void Scope::AllocateParameterLocals() { |
800 ASSERT(is_function_scope()); | 830 ASSERT(is_function_scope()); |
801 Variable* arguments = LocalLookup(Factory::arguments_symbol()); | 831 Variable* arguments = LocalLookup(Factory::arguments_symbol()); |
802 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 832 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
803 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 833 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
804 // 'arguments' is used. Unless there is also a parameter called | 834 // 'arguments' is used. Unless there is also a parameter called |
805 // 'arguments', we must be conservative and access all parameters via | 835 // 'arguments', we must be conservative and access all parameters via |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 | 880 |
851 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. | 881 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. |
852 for (int i = 0; i < params_.length(); i++) { | 882 for (int i = 0; i < params_.length(); i++) { |
853 Variable* var = params_[i]; | 883 Variable* var = params_[i]; |
854 ASSERT(var->scope() == this); | 884 ASSERT(var->scope() == this); |
855 if (MustAllocate(var)) { | 885 if (MustAllocate(var)) { |
856 if (MustAllocateInContext(var)) { | 886 if (MustAllocateInContext(var)) { |
857 // It is ok to set this only now, because arguments is a local | 887 // It is ok to set this only now, because arguments is a local |
858 // variable that is allocated after the parameters have been | 888 // variable that is allocated after the parameters have been |
859 // allocated. | 889 // allocated. |
860 arguments_shadow_->is_accessed_from_inner_scope_ = true; | 890 arguments_shadow_->MarkAsAccessedFromInnerScope(); |
861 } | 891 } |
862 Property* rewrite = | 892 Property* rewrite = |
863 new Property(new VariableProxy(arguments_shadow_), | 893 new Property(new VariableProxy(arguments_shadow_), |
864 new Literal(Handle<Object>(Smi::FromInt(i))), | 894 new Literal(Handle<Object>(Smi::FromInt(i))), |
865 RelocInfo::kNoPosition, | 895 RelocInfo::kNoPosition, |
866 Property::SYNTHETIC); | 896 Property::SYNTHETIC); |
867 rewrite->set_is_arguments_access(true); | 897 rewrite->set_is_arguments_access(true); |
868 var->rewrite_ = rewrite; | 898 var->set_rewrite(rewrite); |
869 } | 899 } |
870 } | 900 } |
871 | 901 |
872 } else { | 902 } else { |
873 // The arguments object is not used, so we can access parameters directly. | 903 // The arguments object is not used, so we can access parameters directly. |
874 // The same parameter may occur multiple times in the parameters_ list. | 904 // The same parameter may occur multiple times in the parameters_ list. |
875 // If it does, and if it is not copied into the context object, it must | 905 // If it does, and if it is not copied into the context object, it must |
876 // receive the highest parameter index for that parameter; thus iteration | 906 // receive the highest parameter index for that parameter; thus iteration |
877 // order is relevant! | 907 // order is relevant! |
878 for (int i = 0; i < params_.length(); i++) { | 908 for (int i = 0; i < params_.length(); i++) { |
879 Variable* var = params_[i]; | 909 Variable* var = params_[i]; |
880 ASSERT(var->scope() == this); | 910 ASSERT(var->scope() == this); |
881 if (MustAllocate(var)) { | 911 if (MustAllocate(var)) { |
882 if (MustAllocateInContext(var)) { | 912 if (MustAllocateInContext(var)) { |
883 ASSERT(var->rewrite_ == NULL || | 913 ASSERT(var->rewrite() == NULL || |
884 (var->AsSlot() != NULL && | 914 (var->AsSlot() != NULL && |
885 var->AsSlot()->type() == Slot::CONTEXT)); | 915 var->AsSlot()->type() == Slot::CONTEXT)); |
886 if (var->rewrite_ == NULL) { | 916 if (var->rewrite() == NULL) { |
887 // Only set the heap allocation if the parameter has not | 917 // Only set the heap allocation if the parameter has not |
888 // been allocated yet. | 918 // been allocated yet. |
889 AllocateHeapSlot(var); | 919 AllocateHeapSlot(var); |
890 } | 920 } |
891 } else { | 921 } else { |
892 ASSERT(var->rewrite_ == NULL || | 922 ASSERT(var->rewrite() == NULL || |
893 (var->AsSlot() != NULL && | 923 (var->AsSlot() != NULL && |
894 var->AsSlot()->type() == Slot::PARAMETER)); | 924 var->AsSlot()->type() == Slot::PARAMETER)); |
895 // Set the parameter index always, even if the parameter | 925 // Set the parameter index always, even if the parameter |
896 // was seen before! (We need to access the actual parameter | 926 // was seen before! (We need to access the actual parameter |
897 // supplied for the last occurrence of a multiply declared | 927 // supplied for the last occurrence of a multiply declared |
898 // parameter.) | 928 // parameter.) |
899 var->rewrite_ = new Slot(var, Slot::PARAMETER, i); | 929 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); |
900 } | 930 } |
901 } | 931 } |
902 } | 932 } |
903 } | 933 } |
904 } | 934 } |
905 | 935 |
906 | 936 |
907 void Scope::AllocateNonParameterLocal(Variable* var) { | 937 void Scope::AllocateNonParameterLocal(Variable* var) { |
908 ASSERT(var->scope() == this); | 938 ASSERT(var->scope() == this); |
909 ASSERT(var->rewrite_ == NULL || | 939 ASSERT(var->rewrite() == NULL || |
910 (!var->IsVariable(Factory::result_symbol())) || | 940 (!var->IsVariable(Factory::result_symbol())) || |
911 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); | 941 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); |
912 if (var->rewrite_ == NULL && MustAllocate(var)) { | 942 if (var->rewrite() == NULL && MustAllocate(var)) { |
913 if (MustAllocateInContext(var)) { | 943 if (MustAllocateInContext(var)) { |
914 AllocateHeapSlot(var); | 944 AllocateHeapSlot(var); |
915 } else { | 945 } else { |
916 AllocateStackSlot(var); | 946 AllocateStackSlot(var); |
917 } | 947 } |
918 } | 948 } |
919 } | 949 } |
920 | 950 |
921 | 951 |
922 void Scope::AllocateNonParameterLocals() { | 952 void Scope::AllocateNonParameterLocals() { |
(...skipping 13 matching lines...) Expand all Loading... |
936 // allocated in the context, it must be the last slot in the context, | 966 // allocated in the context, it must be the last slot in the context, |
937 // because of the current ScopeInfo implementation (see | 967 // because of the current ScopeInfo implementation (see |
938 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 968 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
939 if (function_ != NULL) { | 969 if (function_ != NULL) { |
940 AllocateNonParameterLocal(function_); | 970 AllocateNonParameterLocal(function_); |
941 } | 971 } |
942 } | 972 } |
943 | 973 |
944 | 974 |
945 void Scope::AllocateVariablesRecursively() { | 975 void Scope::AllocateVariablesRecursively() { |
946 // The number of slots required for variables. | |
947 num_stack_slots_ = 0; | |
948 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | |
949 | |
950 // Allocate variables for inner scopes. | 976 // Allocate variables for inner scopes. |
951 for (int i = 0; i < inner_scopes_.length(); i++) { | 977 for (int i = 0; i < inner_scopes_.length(); i++) { |
952 inner_scopes_[i]->AllocateVariablesRecursively(); | 978 inner_scopes_[i]->AllocateVariablesRecursively(); |
953 } | 979 } |
954 | 980 |
| 981 // If scope is already resolved, we still need to allocate |
| 982 // variables in inner scopes which might not had been resolved yet. |
| 983 if (resolved()) return; |
| 984 // The number of slots required for variables. |
| 985 num_stack_slots_ = 0; |
| 986 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 987 |
955 // Allocate variables for this scope. | 988 // Allocate variables for this scope. |
956 // Parameters must be allocated first, if any. | 989 // Parameters must be allocated first, if any. |
957 if (is_function_scope()) AllocateParameterLocals(); | 990 if (is_function_scope()) AllocateParameterLocals(); |
958 AllocateNonParameterLocals(); | 991 AllocateNonParameterLocals(); |
959 | 992 |
960 // Allocate context if necessary. | 993 // Allocate context if necessary. |
961 bool must_have_local_context = false; | 994 bool must_have_local_context = false; |
962 if (scope_calls_eval_ || scope_contains_with_) { | 995 if (scope_calls_eval_ || scope_contains_with_) { |
963 // The context for the eval() call or 'with' statement in this scope. | 996 // The context for the eval() call or 'with' statement in this scope. |
964 // Unless we are in the global or an eval scope, we need a local | 997 // Unless we are in the global or an eval scope, we need a local |
965 // context even if we didn't statically allocate any locals in it, | 998 // context even if we didn't statically allocate any locals in it, |
966 // and the compiler will access the context variable. If we are | 999 // and the compiler will access the context variable. If we are |
967 // not in an inner scope, the scope is provided from the outside. | 1000 // not in an inner scope, the scope is provided from the outside. |
968 must_have_local_context = is_function_scope(); | 1001 must_have_local_context = is_function_scope(); |
969 } | 1002 } |
970 | 1003 |
971 // If we didn't allocate any locals in the local context, then we only | 1004 // If we didn't allocate any locals in the local context, then we only |
972 // need the minimal number of slots if we must have a local context. | 1005 // need the minimal number of slots if we must have a local context. |
973 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1006 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
974 !must_have_local_context) { | 1007 !must_have_local_context) { |
975 num_heap_slots_ = 0; | 1008 num_heap_slots_ = 0; |
976 } | 1009 } |
977 | 1010 |
978 // Allocation done. | 1011 // Allocation done. |
979 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1012 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
980 } | 1013 } |
981 | 1014 |
982 } } // namespace v8::internal | 1015 } } // namespace v8::internal |
OLD | NEW |