| 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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 366 |
| 367 const DeclarationScope* Scope::AsDeclarationScope() const { | 367 const DeclarationScope* Scope::AsDeclarationScope() const { |
| 368 DCHECK(is_declaration_scope()); | 368 DCHECK(is_declaration_scope()); |
| 369 return static_cast<const DeclarationScope*>(this); | 369 return static_cast<const DeclarationScope*>(this); |
| 370 } | 370 } |
| 371 | 371 |
| 372 int Scope::num_parameters() const { | 372 int Scope::num_parameters() const { |
| 373 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; | 373 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; |
| 374 } | 374 } |
| 375 | 375 |
| 376 bool Scope::Analyze(ParseInfo* info) { | 376 void Scope::Analyze(ParseInfo* info) { |
| 377 DCHECK(info->literal() != NULL); | 377 DCHECK(info->literal() != NULL); |
| 378 DCHECK(info->scope() == NULL); | 378 DCHECK(info->scope() == NULL); |
| 379 DeclarationScope* scope = info->literal()->scope(); | 379 DeclarationScope* scope = info->literal()->scope(); |
| 380 DeclarationScope* top = scope; | 380 DeclarationScope* top = scope; |
| 381 | 381 |
| 382 // Traverse the scope tree up to the first unresolved scope or the global | 382 // Traverse the scope tree up to the first unresolved scope or the global |
| 383 // scope and start scope resolution and variable allocation from that scope. | 383 // scope and start scope resolution and variable allocation from that scope. |
| 384 // Such a scope is always a closure-scope, so always skip to the next closure | 384 // Such a scope is always a closure-scope, so always skip to the next closure |
| 385 // scope. | 385 // scope. |
| 386 while (!top->is_script_scope() && | 386 while (!top->is_script_scope() && |
| 387 !top->outer_scope()->already_resolved()) { | 387 !top->outer_scope()->already_resolved()) { |
| 388 top = top->outer_scope()->GetClosureScope(); | 388 top = top->outer_scope()->GetClosureScope(); |
| 389 } | 389 } |
| 390 | 390 |
| 391 // Allocate the variables. | 391 // Allocate the variables. |
| 392 { | 392 { |
| 393 AstNodeFactory ast_node_factory(info->ast_value_factory()); | 393 AstNodeFactory ast_node_factory(info->ast_value_factory()); |
| 394 if (!top->AllocateVariables(info, &ast_node_factory)) return false; | 394 top->AllocateVariables(info, &ast_node_factory); |
| 395 } | 395 } |
| 396 | 396 |
| 397 #ifdef DEBUG | 397 #ifdef DEBUG |
| 398 if (info->script_is_native() ? FLAG_print_builtin_scopes | 398 if (info->script_is_native() ? FLAG_print_builtin_scopes |
| 399 : FLAG_print_scopes) { | 399 : FLAG_print_scopes) { |
| 400 scope->Print(); | 400 scope->Print(); |
| 401 } | 401 } |
| 402 scope->CheckScopePositions(); | 402 scope->CheckScopePositions(); |
| 403 scope->CheckZones(); | 403 scope->CheckZones(); |
| 404 #endif | 404 #endif |
| 405 | 405 |
| 406 info->set_scope(scope); | 406 info->set_scope(scope); |
| 407 return true; | |
| 408 } | 407 } |
| 409 | 408 |
| 410 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) { | 409 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) { |
| 411 DCHECK(!already_resolved()); | 410 DCHECK(!already_resolved()); |
| 412 DCHECK(is_declaration_scope()); | 411 DCHECK(is_declaration_scope()); |
| 413 DCHECK(has_this_declaration()); | 412 DCHECK(has_this_declaration()); |
| 414 | 413 |
| 415 bool subclass_constructor = IsSubclassConstructor(function_kind_); | 414 bool subclass_constructor = IsSubclassConstructor(function_kind_); |
| 416 Variable* var = variables_.Declare( | 415 Variable* var = variables_.Declare( |
| 417 this, ast_value_factory->this_string(), | 416 this, ast_value_factory->this_string(), |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 if (var->IsStackLocal()) { | 865 if (var->IsStackLocal()) { |
| 867 stack_locals->Add(var, zone()); | 866 stack_locals->Add(var, zone()); |
| 868 } else if (var->IsContextSlot()) { | 867 } else if (var->IsContextSlot()) { |
| 869 context_locals->Add(var, zone()); | 868 context_locals->Add(var, zone()); |
| 870 } else if (var->IsGlobalSlot()) { | 869 } else if (var->IsGlobalSlot()) { |
| 871 context_globals->Add(var, zone()); | 870 context_globals->Add(var, zone()); |
| 872 } | 871 } |
| 873 } | 872 } |
| 874 } | 873 } |
| 875 | 874 |
| 876 bool DeclarationScope::AllocateVariables(ParseInfo* info, | 875 void DeclarationScope::AllocateVariables(ParseInfo* info, |
| 877 AstNodeFactory* factory) { | 876 AstNodeFactory* factory) { |
| 878 // 1) Propagate scope information. | 877 // 1) Propagate scope information. |
| 879 bool outer_scope_calls_sloppy_eval = false; | 878 bool outer_scope_calls_sloppy_eval = false; |
| 880 if (outer_scope_ != NULL) { | 879 if (outer_scope_ != NULL) { |
| 881 outer_scope_calls_sloppy_eval = | 880 outer_scope_calls_sloppy_eval = |
| 882 outer_scope_->outer_scope_calls_sloppy_eval() | | 881 outer_scope_->outer_scope_calls_sloppy_eval() | |
| 883 outer_scope_->calls_sloppy_eval(); | 882 outer_scope_->calls_sloppy_eval(); |
| 884 } | 883 } |
| 885 PropagateScopeInfo(outer_scope_calls_sloppy_eval); | 884 PropagateScopeInfo(outer_scope_calls_sloppy_eval); |
| 886 | 885 |
| 887 // 2) Resolve variables. | 886 // 2) Resolve variables. |
| 888 if (!ResolveVariablesRecursively(info, factory)) { | 887 ResolveVariablesRecursively(info, factory); |
| 889 DCHECK(pending_error_handler_.has_pending_error()); | |
| 890 pending_error_handler_.ThrowPendingError(info->isolate(), info->script()); | |
| 891 return false; | |
| 892 } | |
| 893 | 888 |
| 894 // 3) Allocate variables. | 889 // 3) Allocate variables. |
| 895 AllocateVariablesRecursively(info->ast_value_factory()); | 890 AllocateVariablesRecursively(info->ast_value_factory()); |
| 896 | |
| 897 return true; | |
| 898 } | 891 } |
| 899 | 892 |
| 900 | 893 |
| 901 bool Scope::HasTrivialContext() const { | 894 bool Scope::HasTrivialContext() const { |
| 902 // A function scope has a trivial context if it always is the global | 895 // A function scope has a trivial context if it always is the global |
| 903 // context. We iteratively scan out the context chain to see if | 896 // context. We iteratively scan out the context chain to see if |
| 904 // there is anything that makes this scope non-trivial; otherwise we | 897 // there is anything that makes this scope non-trivial; otherwise we |
| 905 // return true. | 898 // return true. |
| 906 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { | 899 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { |
| 907 if (scope->is_eval_scope()) return false; | 900 if (scope->is_eval_scope()) return false; |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 // lookups at script scope are always dynamic. | 1350 // lookups at script scope are always dynamic. |
| 1358 if (*binding_kind == BOUND) { | 1351 if (*binding_kind == BOUND) { |
| 1359 *binding_kind = BOUND_EVAL_SHADOWED; | 1352 *binding_kind = BOUND_EVAL_SHADOWED; |
| 1360 } else if (*binding_kind == UNBOUND) { | 1353 } else if (*binding_kind == UNBOUND) { |
| 1361 *binding_kind = UNBOUND_EVAL_SHADOWED; | 1354 *binding_kind = UNBOUND_EVAL_SHADOWED; |
| 1362 } | 1355 } |
| 1363 } | 1356 } |
| 1364 return var; | 1357 return var; |
| 1365 } | 1358 } |
| 1366 | 1359 |
| 1367 | 1360 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, |
| 1368 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, | |
| 1369 AstNodeFactory* factory) { | 1361 AstNodeFactory* factory) { |
| 1370 DCHECK(info->script_scope()->is_script_scope()); | 1362 DCHECK(info->script_scope()->is_script_scope()); |
| 1371 | 1363 |
| 1372 // If the proxy is already resolved there's nothing to do | 1364 // If the proxy is already resolved there's nothing to do |
| 1373 // (functions and consts may be resolved by the parser). | 1365 // (functions and consts may be resolved by the parser). |
| 1374 if (proxy->is_resolved()) return true; | 1366 if (proxy->is_resolved()) return; |
| 1375 | 1367 |
| 1376 // Otherwise, try to resolve the variable. | 1368 // Otherwise, try to resolve the variable. |
| 1377 BindingKind binding_kind; | 1369 BindingKind binding_kind; |
| 1378 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1370 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
| 1379 | 1371 |
| 1380 #ifdef DEBUG | 1372 #ifdef DEBUG |
| 1381 if (info->script_is_native()) { | 1373 if (info->script_is_native()) { |
| 1382 // To avoid polluting the global object in native scripts | 1374 // To avoid polluting the global object in native scripts |
| 1383 // - Variables must not be allocated to the global scope. | 1375 // - Variables must not be allocated to the global scope. |
| 1384 CHECK_NOT_NULL(outer_scope()); | 1376 CHECK_NOT_NULL(outer_scope()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1431 case DYNAMIC_LOOKUP: | 1423 case DYNAMIC_LOOKUP: |
| 1432 // The variable could not be resolved statically. | 1424 // The variable could not be resolved statically. |
| 1433 var = NonLocal(proxy->raw_name(), DYNAMIC); | 1425 var = NonLocal(proxy->raw_name(), DYNAMIC); |
| 1434 break; | 1426 break; |
| 1435 } | 1427 } |
| 1436 | 1428 |
| 1437 DCHECK(var != NULL); | 1429 DCHECK(var != NULL); |
| 1438 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1430 if (proxy->is_assigned()) var->set_maybe_assigned(); |
| 1439 | 1431 |
| 1440 proxy->BindTo(var); | 1432 proxy->BindTo(var); |
| 1441 | |
| 1442 return true; | |
| 1443 } | 1433 } |
| 1444 | 1434 |
| 1445 | 1435 void Scope::ResolveVariablesRecursively(ParseInfo* info, |
| 1446 bool Scope::ResolveVariablesRecursively(ParseInfo* info, | |
| 1447 AstNodeFactory* factory) { | 1436 AstNodeFactory* factory) { |
| 1448 DCHECK(info->script_scope()->is_script_scope()); | 1437 DCHECK(info->script_scope()->is_script_scope()); |
| 1449 | 1438 |
| 1450 // Resolve unresolved variables for this scope. | 1439 // Resolve unresolved variables for this scope. |
| 1451 for (VariableProxy* proxy = unresolved_; proxy != nullptr; | 1440 for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
| 1452 proxy = proxy->next_unresolved()) { | 1441 proxy = proxy->next_unresolved()) { |
| 1453 if (!ResolveVariable(info, proxy, factory)) return false; | 1442 ResolveVariable(info, proxy, factory); |
| 1454 } | 1443 } |
| 1455 | 1444 |
| 1456 // Resolve unresolved variables for inner scopes. | 1445 // Resolve unresolved variables for inner scopes. |
| 1457 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1446 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
| 1458 if (!scope->ResolveVariablesRecursively(info, factory)) return false; | 1447 scope->ResolveVariablesRecursively(info, factory); |
| 1459 } | 1448 } |
| 1460 | |
| 1461 return true; | |
| 1462 } | 1449 } |
| 1463 | 1450 |
| 1464 void Scope::MigrateUnresolvableLocals(DeclarationScope* migrate_to, | 1451 void Scope::MigrateUnresolvableLocals(DeclarationScope* migrate_to, |
| 1465 AstNodeFactory* ast_node_factory, | 1452 AstNodeFactory* ast_node_factory, |
| 1466 DeclarationScope* max_outer_scope) { | 1453 DeclarationScope* max_outer_scope) { |
| 1467 BindingKind binding_kind; | 1454 BindingKind binding_kind; |
| 1468 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | 1455 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
| 1469 proxy = next) { | 1456 proxy = next) { |
| 1470 next = proxy->next_unresolved(); | 1457 next = proxy->next_unresolved(); |
| 1471 // Note that we pass nullptr as AstNodeFactory: this phase should not create | 1458 // Note that we pass nullptr as AstNodeFactory: this phase should not create |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 function != NULL && function->proxy()->var()->IsContextSlot(); | 1775 function != NULL && function->proxy()->var()->IsContextSlot(); |
| 1789 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1776 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1790 (is_function_var_in_context ? 1 : 0); | 1777 (is_function_var_in_context ? 1 : 0); |
| 1791 } | 1778 } |
| 1792 | 1779 |
| 1793 | 1780 |
| 1794 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1781 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1795 | 1782 |
| 1796 } // namespace internal | 1783 } // namespace internal |
| 1797 } // namespace v8 | 1784 } // namespace v8 |
| OLD | NEW |