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