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 |