OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/scopes.h" | 7 #include "src/scopes.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 AstValueFactory* ast_value_factory, Zone* zone) | 71 AstValueFactory* ast_value_factory, Zone* zone) |
72 : isolate_(zone->isolate()), | 72 : isolate_(zone->isolate()), |
73 inner_scopes_(4, zone), | 73 inner_scopes_(4, zone), |
74 variables_(zone), | 74 variables_(zone), |
75 internals_(4, zone), | 75 internals_(4, zone), |
76 temps_(4, zone), | 76 temps_(4, zone), |
77 params_(4, zone), | 77 params_(4, zone), |
78 unresolved_(16, zone), | 78 unresolved_(16, zone), |
79 decls_(4, zone), | 79 decls_(4, zone), |
80 interface_(FLAG_harmony_modules && | 80 interface_(FLAG_harmony_modules && |
81 (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE) | 81 (scope_type == MODULE_SCOPE || scope_type == SCRIPT_SCOPE) |
82 ? Interface::NewModule(zone) : NULL), | 82 ? Interface::NewModule(zone) : NULL), |
83 already_resolved_(false), | 83 already_resolved_(false), |
84 ast_value_factory_(ast_value_factory), | 84 ast_value_factory_(ast_value_factory), |
85 zone_(zone) { | 85 zone_(zone) { |
86 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); | 86 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); |
87 // The outermost scope must be a global scope. | 87 // The outermost scope must be a script scope. |
88 DCHECK(scope_type == GLOBAL_SCOPE || outer_scope != NULL); | 88 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); |
89 DCHECK(!HasIllegalRedeclaration()); | 89 DCHECK(!HasIllegalRedeclaration()); |
90 } | 90 } |
91 | 91 |
92 | 92 |
93 Scope::Scope(Scope* inner_scope, | 93 Scope::Scope(Scope* inner_scope, |
94 ScopeType scope_type, | 94 ScopeType scope_type, |
95 Handle<ScopeInfo> scope_info, | 95 Handle<ScopeInfo> scope_info, |
96 AstValueFactory* value_factory, | 96 AstValueFactory* value_factory, |
97 Zone* zone) | 97 Zone* zone) |
98 : isolate_(zone->isolate()), | 98 : isolate_(zone->isolate()), |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 scope_info_ = scope_info; | 183 scope_info_ = scope_info; |
184 start_position_ = RelocInfo::kNoPosition; | 184 start_position_ = RelocInfo::kNoPosition; |
185 end_position_ = RelocInfo::kNoPosition; | 185 end_position_ = RelocInfo::kNoPosition; |
186 if (!scope_info.is_null()) { | 186 if (!scope_info.is_null()) { |
187 scope_calls_eval_ = scope_info->CallsEval(); | 187 scope_calls_eval_ = scope_info->CallsEval(); |
188 strict_mode_ = scope_info->strict_mode(); | 188 strict_mode_ = scope_info->strict_mode(); |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 | 192 |
193 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, | 193 Scope* Scope::DeserializeScopeChain(Context* context, Scope* script_scope, |
194 Zone* zone) { | 194 Zone* zone) { |
195 // Reconstruct the outer scope chain from a closure's context chain. | 195 // Reconstruct the outer scope chain from a closure's context chain. |
196 Scope* current_scope = NULL; | 196 Scope* current_scope = NULL; |
197 Scope* innermost_scope = NULL; | 197 Scope* innermost_scope = NULL; |
198 bool contains_with = false; | 198 bool contains_with = false; |
199 while (!context->IsNativeContext()) { | 199 while (!context->IsNativeContext()) { |
200 if (context->IsWithContext()) { | 200 if (context->IsWithContext()) { |
201 Scope* with_scope = new(zone) Scope(current_scope, | 201 Scope* with_scope = new(zone) Scope(current_scope, |
202 WITH_SCOPE, | 202 WITH_SCOPE, |
203 Handle<ScopeInfo>::null(), | 203 Handle<ScopeInfo>::null(), |
204 global_scope->ast_value_factory_, | 204 script_scope->ast_value_factory_, |
205 zone); | 205 zone); |
206 current_scope = with_scope; | 206 current_scope = with_scope; |
207 // All the inner scopes are inside a with. | 207 // All the inner scopes are inside a with. |
208 contains_with = true; | 208 contains_with = true; |
209 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 209 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
210 s->scope_inside_with_ = true; | 210 s->scope_inside_with_ = true; |
211 } | 211 } |
212 } else if (context->IsGlobalContext()) { | 212 } else if (context->IsScriptContext()) { |
213 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); | 213 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); |
214 current_scope = new(zone) Scope(current_scope, | 214 current_scope = new(zone) Scope(current_scope, |
215 GLOBAL_SCOPE, | 215 SCRIPT_SCOPE, |
216 Handle<ScopeInfo>(scope_info), | 216 Handle<ScopeInfo>(scope_info), |
217 global_scope->ast_value_factory_, | 217 script_scope->ast_value_factory_, |
218 zone); | 218 zone); |
219 } else if (context->IsModuleContext()) { | 219 } else if (context->IsModuleContext()) { |
220 ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); | 220 ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); |
221 current_scope = new(zone) Scope(current_scope, | 221 current_scope = new(zone) Scope(current_scope, |
222 MODULE_SCOPE, | 222 MODULE_SCOPE, |
223 Handle<ScopeInfo>(scope_info), | 223 Handle<ScopeInfo>(scope_info), |
224 global_scope->ast_value_factory_, | 224 script_scope->ast_value_factory_, |
225 zone); | 225 zone); |
226 } else if (context->IsFunctionContext()) { | 226 } else if (context->IsFunctionContext()) { |
227 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); | 227 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
228 current_scope = new(zone) Scope(current_scope, | 228 current_scope = new(zone) Scope(current_scope, |
229 FUNCTION_SCOPE, | 229 FUNCTION_SCOPE, |
230 Handle<ScopeInfo>(scope_info), | 230 Handle<ScopeInfo>(scope_info), |
231 global_scope->ast_value_factory_, | 231 script_scope->ast_value_factory_, |
232 zone); | 232 zone); |
233 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; | 233 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; |
234 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; | 234 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; |
235 } else if (context->IsBlockContext()) { | 235 } else if (context->IsBlockContext()) { |
236 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); | 236 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); |
237 current_scope = new(zone) Scope(current_scope, | 237 current_scope = new(zone) Scope(current_scope, |
238 BLOCK_SCOPE, | 238 BLOCK_SCOPE, |
239 Handle<ScopeInfo>(scope_info), | 239 Handle<ScopeInfo>(scope_info), |
240 global_scope->ast_value_factory_, | 240 script_scope->ast_value_factory_, |
241 zone); | 241 zone); |
242 } else { | 242 } else { |
243 DCHECK(context->IsCatchContext()); | 243 DCHECK(context->IsCatchContext()); |
244 String* name = String::cast(context->extension()); | 244 String* name = String::cast(context->extension()); |
245 current_scope = new (zone) Scope( | 245 current_scope = new (zone) Scope( |
246 current_scope, | 246 current_scope, |
247 global_scope->ast_value_factory_->GetString(Handle<String>(name)), | 247 script_scope->ast_value_factory_->GetString(Handle<String>(name)), |
248 global_scope->ast_value_factory_, zone); | 248 script_scope->ast_value_factory_, zone); |
249 } | 249 } |
250 if (contains_with) current_scope->RecordWithStatement(); | 250 if (contains_with) current_scope->RecordWithStatement(); |
251 if (innermost_scope == NULL) innermost_scope = current_scope; | 251 if (innermost_scope == NULL) innermost_scope = current_scope; |
252 | 252 |
253 // Forget about a with when we move to a context for a different function. | 253 // Forget about a with when we move to a context for a different function. |
254 if (context->previous()->closure() != context->closure()) { | 254 if (context->previous()->closure() != context->closure()) { |
255 contains_with = false; | 255 contains_with = false; |
256 } | 256 } |
257 context = context->previous(); | 257 context = context->previous(); |
258 } | 258 } |
259 | 259 |
260 global_scope->AddInnerScope(current_scope); | 260 script_scope->AddInnerScope(current_scope); |
261 global_scope->PropagateScopeInfo(false); | 261 script_scope->PropagateScopeInfo(false); |
262 return (innermost_scope == NULL) ? global_scope : innermost_scope; | 262 return (innermost_scope == NULL) ? script_scope : innermost_scope; |
263 } | 263 } |
264 | 264 |
265 | 265 |
266 bool Scope::Analyze(CompilationInfo* info) { | 266 bool Scope::Analyze(CompilationInfo* info) { |
267 DCHECK(info->function() != NULL); | 267 DCHECK(info->function() != NULL); |
268 Scope* scope = info->function()->scope(); | 268 Scope* scope = info->function()->scope(); |
269 Scope* top = scope; | 269 Scope* top = scope; |
270 | 270 |
271 // Traverse the scope tree up to the first unresolved scope or the global | 271 // Traverse the scope tree up to the first unresolved scope or the global |
272 // scope and start scope resolution and variable allocation from that scope. | 272 // scope and start scope resolution and variable allocation from that scope. |
273 while (!top->is_global_scope() && | 273 while (!top->is_script_scope() && |
274 !top->outer_scope()->already_resolved()) { | 274 !top->outer_scope()->already_resolved()) { |
275 top = top->outer_scope(); | 275 top = top->outer_scope(); |
276 } | 276 } |
277 | 277 |
278 // Allocate the variables. | 278 // Allocate the variables. |
279 { | 279 { |
280 AstNodeFactory<AstNullVisitor> ast_node_factory(info->ast_value_factory()); | 280 AstNodeFactory<AstNullVisitor> ast_node_factory(info->ast_value_factory()); |
281 if (!top->AllocateVariables(info, &ast_node_factory)) return false; | 281 if (!top->AllocateVariables(info, &ast_node_factory)) return false; |
282 } | 282 } |
283 | 283 |
284 #ifdef DEBUG | 284 #ifdef DEBUG |
285 if (info->isolate()->bootstrapper()->IsActive() | 285 if (info->isolate()->bootstrapper()->IsActive() |
286 ? FLAG_print_builtin_scopes | 286 ? FLAG_print_builtin_scopes |
287 : FLAG_print_scopes) { | 287 : FLAG_print_scopes) { |
288 scope->Print(); | 288 scope->Print(); |
289 } | 289 } |
290 | 290 |
291 if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) { | 291 if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_script_scope()) { |
292 PrintF("global : "); | 292 PrintF("global : "); |
293 top->interface()->Print(); | 293 top->interface()->Print(); |
294 } | 294 } |
295 #endif | 295 #endif |
296 | 296 |
297 info->PrepareForCompilation(scope); | 297 info->PrepareForCompilation(scope); |
298 return true; | 298 return true; |
299 } | 299 } |
300 | 300 |
301 | 301 |
302 void Scope::Initialize() { | 302 void Scope::Initialize() { |
303 DCHECK(!already_resolved()); | 303 DCHECK(!already_resolved()); |
304 | 304 |
305 // Add this scope as a new inner scope of the outer scope. | 305 // Add this scope as a new inner scope of the outer scope. |
306 if (outer_scope_ != NULL) { | 306 if (outer_scope_ != NULL) { |
307 outer_scope_->inner_scopes_.Add(this, zone()); | 307 outer_scope_->inner_scopes_.Add(this, zone()); |
308 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); | 308 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); |
309 } else { | 309 } else { |
310 scope_inside_with_ = is_with_scope(); | 310 scope_inside_with_ = is_with_scope(); |
311 } | 311 } |
312 | 312 |
313 // Declare convenience variables. | 313 // Declare convenience variables. |
314 // Declare and allocate receiver (even for the global scope, and even | 314 // Declare and allocate receiver (even for the script scope, and even |
315 // if naccesses_ == 0). | 315 // if naccesses_ == 0). |
316 // NOTE: When loading parameters in the global scope, we must take | 316 // NOTE: When loading parameters in the script scope, we must take |
317 // care not to access them as properties of the global object, but | 317 // care not to access them as properties of the global object, but |
318 // instead load them directly from the stack. Currently, the only | 318 // instead load them directly from the stack. Currently, the only |
319 // such parameter is 'this' which is passed on the stack when | 319 // such parameter is 'this' which is passed on the stack when |
320 // invoking scripts | 320 // invoking scripts |
321 if (is_declaration_scope()) { | 321 if (is_declaration_scope()) { |
322 Variable* var = | 322 Variable* var = |
323 variables_.Declare(this, | 323 variables_.Declare(this, |
324 ast_value_factory_->this_string(), | 324 ast_value_factory_->this_string(), |
325 VAR, | 325 VAR, |
326 false, | 326 false, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 // introduces during variable allocation, INTERNAL variables are allocated | 472 // introduces during variable allocation, INTERNAL variables are allocated |
473 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 473 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
474 DCHECK(IsDeclaredVariableMode(mode)); | 474 DCHECK(IsDeclaredVariableMode(mode)); |
475 ++num_var_or_const_; | 475 ++num_var_or_const_; |
476 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 476 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, |
477 maybe_assigned_flag, interface); | 477 maybe_assigned_flag, interface); |
478 } | 478 } |
479 | 479 |
480 | 480 |
481 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 481 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
482 DCHECK(is_global_scope()); | 482 DCHECK(is_script_scope()); |
483 return variables_.Declare(this, | 483 return variables_.Declare(this, |
484 name, | 484 name, |
485 DYNAMIC_GLOBAL, | 485 DYNAMIC_GLOBAL, |
486 true, | 486 true, |
487 Variable::NORMAL, | 487 Variable::NORMAL, |
488 kCreatedInitialized); | 488 kCreatedInitialized); |
489 } | 489 } |
490 | 490 |
491 | 491 |
492 void Scope::RemoveUnresolved(VariableProxy* var) { | 492 void Scope::RemoveUnresolved(VariableProxy* var) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 // 1) Propagate scope information. | 643 // 1) Propagate scope information. |
644 bool outer_scope_calls_sloppy_eval = false; | 644 bool outer_scope_calls_sloppy_eval = false; |
645 if (outer_scope_ != NULL) { | 645 if (outer_scope_ != NULL) { |
646 outer_scope_calls_sloppy_eval = | 646 outer_scope_calls_sloppy_eval = |
647 outer_scope_->outer_scope_calls_sloppy_eval() | | 647 outer_scope_->outer_scope_calls_sloppy_eval() | |
648 outer_scope_->calls_sloppy_eval(); | 648 outer_scope_->calls_sloppy_eval(); |
649 } | 649 } |
650 PropagateScopeInfo(outer_scope_calls_sloppy_eval); | 650 PropagateScopeInfo(outer_scope_calls_sloppy_eval); |
651 | 651 |
652 // 2) Allocate module instances. | 652 // 2) Allocate module instances. |
653 if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { | 653 if (FLAG_harmony_modules && (is_script_scope() || is_module_scope())) { |
654 DCHECK(num_modules_ == 0); | 654 DCHECK(num_modules_ == 0); |
655 AllocateModulesRecursively(this); | 655 AllocateModulesRecursively(this); |
656 } | 656 } |
657 | 657 |
658 // 3) Resolve variables. | 658 // 3) Resolve variables. |
659 if (!ResolveVariablesRecursively(info, factory)) return false; | 659 if (!ResolveVariablesRecursively(info, factory)) return false; |
660 | 660 |
661 // 4) Allocate variables. | 661 // 4) Allocate variables. |
662 AllocateVariablesRecursively(); | 662 AllocateVariablesRecursively(); |
663 | 663 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 DCHECK(s != NULL); // scope must be in the scope chain | 723 DCHECK(s != NULL); // scope must be in the scope chain |
724 if (s->is_with_scope() || s->num_heap_slots() > 0) n++; | 724 if (s->is_with_scope() || s->num_heap_slots() > 0) n++; |
725 // Catch and module scopes always have heap slots. | 725 // Catch and module scopes always have heap slots. |
726 DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0); | 726 DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0); |
727 DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0); | 727 DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0); |
728 } | 728 } |
729 return n; | 729 return n; |
730 } | 730 } |
731 | 731 |
732 | 732 |
733 Scope* Scope::GlobalScope() { | 733 Scope* Scope::ScriptScope() { |
734 Scope* scope = this; | 734 Scope* scope = this; |
735 while (!scope->is_global_scope()) { | 735 while (!scope->is_script_scope()) { |
736 scope = scope->outer_scope(); | 736 scope = scope->outer_scope(); |
737 } | 737 } |
738 return scope; | 738 return scope; |
739 } | 739 } |
740 | 740 |
741 | 741 |
742 Scope* Scope::DeclarationScope() { | 742 Scope* Scope::DeclarationScope() { |
743 Scope* scope = this; | 743 Scope* scope = this; |
744 while (!scope->is_declaration_scope()) { | 744 while (!scope->is_declaration_scope()) { |
745 scope = scope->outer_scope(); | 745 scope = scope->outer_scope(); |
(...skipping 27 matching lines...) Expand all Loading... |
773 } | 773 } |
774 } | 774 } |
775 | 775 |
776 | 776 |
777 #ifdef DEBUG | 777 #ifdef DEBUG |
778 static const char* Header(ScopeType scope_type) { | 778 static const char* Header(ScopeType scope_type) { |
779 switch (scope_type) { | 779 switch (scope_type) { |
780 case EVAL_SCOPE: return "eval"; | 780 case EVAL_SCOPE: return "eval"; |
781 case FUNCTION_SCOPE: return "function"; | 781 case FUNCTION_SCOPE: return "function"; |
782 case MODULE_SCOPE: return "module"; | 782 case MODULE_SCOPE: return "module"; |
783 case GLOBAL_SCOPE: return "global"; | 783 case SCRIPT_SCOPE: return "global"; |
784 case CATCH_SCOPE: return "catch"; | 784 case CATCH_SCOPE: return "catch"; |
785 case BLOCK_SCOPE: return "block"; | 785 case BLOCK_SCOPE: return "block"; |
786 case WITH_SCOPE: return "with"; | 786 case WITH_SCOPE: return "with"; |
787 case ARROW_SCOPE: return "arrow"; | 787 case ARROW_SCOPE: return "arrow"; |
788 } | 788 } |
789 UNREACHABLE(); | 789 UNREACHABLE(); |
790 return NULL; | 790 return NULL; |
791 } | 791 } |
792 | 792 |
793 | 793 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 *binding_kind = UNBOUND; | 1002 *binding_kind = UNBOUND; |
1003 var = LookupFunctionVar(proxy->raw_name(), factory); | 1003 var = LookupFunctionVar(proxy->raw_name(), factory); |
1004 if (var != NULL) { | 1004 if (var != NULL) { |
1005 *binding_kind = BOUND; | 1005 *binding_kind = BOUND; |
1006 } else if (outer_scope_ != NULL) { | 1006 } else if (outer_scope_ != NULL) { |
1007 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); | 1007 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); |
1008 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 1008 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
1009 var->ForceContextAllocation(); | 1009 var->ForceContextAllocation(); |
1010 } | 1010 } |
1011 } else { | 1011 } else { |
1012 DCHECK(is_global_scope()); | 1012 DCHECK(is_script_scope()); |
1013 } | 1013 } |
1014 | 1014 |
1015 if (is_with_scope()) { | 1015 if (is_with_scope()) { |
1016 DCHECK(!already_resolved()); | 1016 DCHECK(!already_resolved()); |
1017 // The current scope is a with scope, so the variable binding can not be | 1017 // The current scope is a with scope, so the variable binding can not be |
1018 // statically resolved. However, note that it was necessary to do a lookup | 1018 // statically resolved. However, note that it was necessary to do a lookup |
1019 // in the outer scope anyway, because if a binding exists in an outer scope, | 1019 // in the outer scope anyway, because if a binding exists in an outer scope, |
1020 // the associated variable has to be marked as potentially being accessed | 1020 // the associated variable has to be marked as potentially being accessed |
1021 // from inside of an inner with scope (the property may not be in the 'with' | 1021 // from inside of an inner with scope (the property may not be in the 'with' |
1022 // object). | 1022 // object). |
(...skipping 11 matching lines...) Expand all Loading... |
1034 *binding_kind = UNBOUND_EVAL_SHADOWED; | 1034 *binding_kind = UNBOUND_EVAL_SHADOWED; |
1035 } | 1035 } |
1036 } | 1036 } |
1037 return var; | 1037 return var; |
1038 } | 1038 } |
1039 | 1039 |
1040 | 1040 |
1041 bool Scope::ResolveVariable(CompilationInfo* info, | 1041 bool Scope::ResolveVariable(CompilationInfo* info, |
1042 VariableProxy* proxy, | 1042 VariableProxy* proxy, |
1043 AstNodeFactory<AstNullVisitor>* factory) { | 1043 AstNodeFactory<AstNullVisitor>* factory) { |
1044 DCHECK(info->global_scope()->is_global_scope()); | 1044 DCHECK(info->script_scope()->is_script_scope()); |
1045 | 1045 |
1046 // If the proxy is already resolved there's nothing to do | 1046 // If the proxy is already resolved there's nothing to do |
1047 // (functions and consts may be resolved by the parser). | 1047 // (functions and consts may be resolved by the parser). |
1048 if (proxy->is_resolved()) return true; | 1048 if (proxy->is_resolved()) return true; |
1049 | 1049 |
1050 // Otherwise, try to resolve the variable. | 1050 // Otherwise, try to resolve the variable. |
1051 BindingKind binding_kind; | 1051 BindingKind binding_kind; |
1052 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1052 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
1053 switch (binding_kind) { | 1053 switch (binding_kind) { |
1054 case BOUND: | 1054 case BOUND: |
(...skipping 11 matching lines...) Expand all Loading... |
1066 var = NonLocal(proxy->raw_name(), DYNAMIC); | 1066 var = NonLocal(proxy->raw_name(), DYNAMIC); |
1067 } else { | 1067 } else { |
1068 Variable* invalidated = var; | 1068 Variable* invalidated = var; |
1069 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); | 1069 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); |
1070 var->set_local_if_not_shadowed(invalidated); | 1070 var->set_local_if_not_shadowed(invalidated); |
1071 } | 1071 } |
1072 break; | 1072 break; |
1073 | 1073 |
1074 case UNBOUND: | 1074 case UNBOUND: |
1075 // No binding has been found. Declare a variable on the global object. | 1075 // No binding has been found. Declare a variable on the global object. |
1076 var = info->global_scope()->DeclareDynamicGlobal(proxy->raw_name()); | 1076 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name()); |
1077 break; | 1077 break; |
1078 | 1078 |
1079 case UNBOUND_EVAL_SHADOWED: | 1079 case UNBOUND_EVAL_SHADOWED: |
1080 // No binding has been found. But some scope makes a sloppy 'eval' call. | 1080 // No binding has been found. But some scope makes a sloppy 'eval' call. |
1081 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 1081 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1082 break; | 1082 break; |
1083 | 1083 |
1084 case DYNAMIC_LOOKUP: | 1084 case DYNAMIC_LOOKUP: |
1085 // The variable could not be resolved statically. | 1085 // The variable could not be resolved statically. |
1086 var = NonLocal(proxy->raw_name(), DYNAMIC); | 1086 var = NonLocal(proxy->raw_name(), DYNAMIC); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 | 1143 |
1144 proxy->BindTo(var); | 1144 proxy->BindTo(var); |
1145 | 1145 |
1146 return true; | 1146 return true; |
1147 } | 1147 } |
1148 | 1148 |
1149 | 1149 |
1150 bool Scope::ResolveVariablesRecursively( | 1150 bool Scope::ResolveVariablesRecursively( |
1151 CompilationInfo* info, | 1151 CompilationInfo* info, |
1152 AstNodeFactory<AstNullVisitor>* factory) { | 1152 AstNodeFactory<AstNullVisitor>* factory) { |
1153 DCHECK(info->global_scope()->is_global_scope()); | 1153 DCHECK(info->script_scope()->is_script_scope()); |
1154 | 1154 |
1155 // Resolve unresolved variables for this scope. | 1155 // Resolve unresolved variables for this scope. |
1156 for (int i = 0; i < unresolved_.length(); i++) { | 1156 for (int i = 0; i < unresolved_.length(); i++) { |
1157 if (!ResolveVariable(info, unresolved_[i], factory)) return false; | 1157 if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
1158 } | 1158 } |
1159 | 1159 |
1160 // Resolve unresolved variables for inner scopes. | 1160 // Resolve unresolved variables for inner scopes. |
1161 for (int i = 0; i < inner_scopes_.length(); i++) { | 1161 for (int i = 0; i < inner_scopes_.length(); i++) { |
1162 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) | 1162 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) |
1163 return false; | 1163 return false; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 // via an eval() call. This is only possible if the variable has a | 1209 // via an eval() call. This is only possible if the variable has a |
1210 // visible name. | 1210 // visible name. |
1211 if ((var->is_this() || !var->raw_name()->IsEmpty()) && | 1211 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
1212 (var->has_forced_context_allocation() || | 1212 (var->has_forced_context_allocation() || |
1213 scope_calls_eval_ || | 1213 scope_calls_eval_ || |
1214 inner_scope_calls_eval_ || | 1214 inner_scope_calls_eval_ || |
1215 scope_contains_with_ || | 1215 scope_contains_with_ || |
1216 is_catch_scope() || | 1216 is_catch_scope() || |
1217 is_block_scope() || | 1217 is_block_scope() || |
1218 is_module_scope() || | 1218 is_module_scope() || |
1219 is_global_scope())) { | 1219 is_script_scope())) { |
1220 var->set_is_used(); | 1220 var->set_is_used(); |
1221 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1221 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
1222 } | 1222 } |
1223 // Global variables do not need to be allocated. | 1223 // Global variables do not need to be allocated. |
1224 return !var->IsGlobalObjectProperty() && var->is_used(); | 1224 return !var->IsGlobalObjectProperty() && var->is_used(); |
1225 } | 1225 } |
1226 | 1226 |
1227 | 1227 |
1228 bool Scope::MustAllocateInContext(Variable* var) { | 1228 bool Scope::MustAllocateInContext(Variable* var) { |
1229 // If var is accessed from an inner scope, or if there is a possibility | 1229 // If var is accessed from an inner scope, or if there is a possibility |
1230 // that it might be accessed from the current or an inner scope (through | 1230 // that it might be accessed from the current or an inner scope (through |
1231 // an eval() call or a runtime with lookup), it must be allocated in the | 1231 // an eval() call or a runtime with lookup), it must be allocated in the |
1232 // context. | 1232 // context. |
1233 // | 1233 // |
1234 // Exceptions: If the scope as a whole has forced context allocation, all | 1234 // Exceptions: If the scope as a whole has forced context allocation, all |
1235 // variables will have context allocation, even temporaries. Otherwise | 1235 // variables will have context allocation, even temporaries. Otherwise |
1236 // temporary variables are always stack-allocated. Catch-bound variables are | 1236 // temporary variables are always stack-allocated. Catch-bound variables are |
1237 // always context-allocated. | 1237 // always context-allocated. |
1238 if (has_forced_context_allocation()) return true; | 1238 if (has_forced_context_allocation()) return true; |
1239 if (var->mode() == TEMPORARY) return false; | 1239 if (var->mode() == TEMPORARY) return false; |
1240 if (var->mode() == INTERNAL) return true; | 1240 if (var->mode() == INTERNAL) return true; |
1241 if (is_catch_scope() || is_block_scope() || is_module_scope()) return true; | 1241 if (is_catch_scope() || is_block_scope() || is_module_scope()) return true; |
1242 if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true; | 1242 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; |
1243 return var->has_forced_context_allocation() || | 1243 return var->has_forced_context_allocation() || |
1244 scope_calls_eval_ || | 1244 scope_calls_eval_ || |
1245 inner_scope_calls_eval_ || | 1245 inner_scope_calls_eval_ || |
1246 scope_contains_with_; | 1246 scope_contains_with_; |
1247 } | 1247 } |
1248 | 1248 |
1249 | 1249 |
1250 bool Scope::HasArgumentsParameter() { | 1250 bool Scope::HasArgumentsParameter() { |
1251 for (int i = 0; i < params_.length(); i++) { | 1251 for (int i = 0; i < params_.length(); i++) { |
1252 if (params_[i]->name().is_identical_to( | 1252 if (params_[i]->name().is_identical_to( |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1430 } | 1430 } |
1431 | 1431 |
1432 | 1432 |
1433 int Scope::ContextLocalCount() const { | 1433 int Scope::ContextLocalCount() const { |
1434 if (num_heap_slots() == 0) return 0; | 1434 if (num_heap_slots() == 0) return 0; |
1435 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1435 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1436 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1436 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1437 } | 1437 } |
1438 | 1438 |
1439 } } // namespace v8::internal | 1439 } } // namespace v8::internal |
OLD | NEW |