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 |