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