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 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 | 972 |
973 | 973 |
974 | 974 |
975 Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) { | 975 Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) { |
976 if (scope_info_.is_null()) { | 976 if (scope_info_.is_null()) { |
977 scope_info_ = ScopeInfo::Create(isolate, zone(), this); | 977 scope_info_ = ScopeInfo::Create(isolate, zone(), this); |
978 } | 978 } |
979 return scope_info_; | 979 return scope_info_; |
980 } | 980 } |
981 | 981 |
982 Handle<StringSet> Scope::CollectNonLocals(Handle<StringSet> non_locals) { | 982 Handle<StringSet> DeclarationScope::CollectNonLocals( |
983 // Collect non-local variables referenced in the scope. | 983 ParseInfo* info, Handle<StringSet> non_locals) { |
984 // TODO(yangguo): store non-local variables explicitly if we can no longer | 984 VariableProxy* free_variables = FetchFreeVariables(this, info); |
985 // rely on unresolved_ to find them. | 985 for (VariableProxy* proxy = free_variables; proxy != nullptr; |
986 for (VariableProxy* proxy = unresolved_; proxy != nullptr; | |
987 proxy = proxy->next_unresolved()) { | 986 proxy = proxy->next_unresolved()) { |
988 if (proxy->is_resolved() && proxy->var()->IsStackAllocated()) continue; | 987 non_locals = StringSet::Add(non_locals, proxy->name()); |
989 Handle<String> name = proxy->name(); | |
990 non_locals = StringSet::Add(non_locals, name); | |
991 } | |
992 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | |
993 non_locals = scope->CollectNonLocals(non_locals); | |
994 } | 988 } |
995 return non_locals; | 989 return non_locals; |
996 } | 990 } |
997 | 991 |
998 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, | 992 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, |
999 AstNodeFactory* ast_node_factory) { | 993 AstNodeFactory* ast_node_factory) { |
1000 // Gather info from inner scopes. | 994 // Gather info from inner scopes. |
1001 PropagateScopeInfo(false); | 995 PropagateScopeInfo(false); |
1002 | 996 |
1003 // Try to resolve unresolved variables for this Scope and migrate those which | 997 // Try to resolve unresolved variables for this Scope and migrate those which |
1004 // cannot be resolved inside. It doesn't make sense to try to resolve them in | 998 // cannot be resolved inside. It doesn't make sense to try to resolve them in |
1005 // the outer Scopes here, because they are incomplete. | 999 // the outer Scopes here, because they are incomplete. |
1006 MigrateUnresolvableLocals(migrate_to, ast_node_factory, this); | 1000 for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr; |
| 1001 proxy = proxy->next_unresolved()) { |
| 1002 DCHECK(!proxy->is_resolved()); |
| 1003 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); |
| 1004 migrate_to->AddUnresolved(copy); |
| 1005 } |
1007 | 1006 |
1008 // Push scope data up to migrate_to. Note that migrate_to and this Scope | 1007 // Push scope data up to migrate_to. Note that migrate_to and this Scope |
1009 // describe the same Scope, just in different Zones. | 1008 // describe the same Scope, just in different Zones. |
1010 PropagateUsageFlagsToScope(migrate_to); | 1009 PropagateUsageFlagsToScope(migrate_to); |
1011 if (inner_scope_calls_eval_) { | 1010 if (inner_scope_calls_eval_) { |
1012 migrate_to->inner_scope_calls_eval_ = true; | 1011 migrate_to->inner_scope_calls_eval_ = true; |
1013 } | 1012 } |
1014 DCHECK(!force_eager_compilation_); | 1013 DCHECK(!force_eager_compilation_); |
1015 migrate_to->set_start_position(start_position_); | 1014 migrate_to->set_start_position(start_position_); |
1016 migrate_to->set_end_position(end_position_); | 1015 migrate_to->set_end_position(end_position_); |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 DCHECK(info->script_scope()->is_script_scope()); | 1351 DCHECK(info->script_scope()->is_script_scope()); |
1353 | 1352 |
1354 // If the proxy is already resolved there's nothing to do | 1353 // If the proxy is already resolved there's nothing to do |
1355 // (functions and consts may be resolved by the parser). | 1354 // (functions and consts may be resolved by the parser). |
1356 if (proxy->is_resolved()) return; | 1355 if (proxy->is_resolved()) return; |
1357 | 1356 |
1358 // Otherwise, try to resolve the variable. | 1357 // Otherwise, try to resolve the variable. |
1359 BindingKind binding_kind; | 1358 BindingKind binding_kind; |
1360 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1359 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
1361 | 1360 |
| 1361 ResolveTo(info, binding_kind, proxy, var); |
| 1362 } |
| 1363 |
| 1364 void Scope::ResolveTo(ParseInfo* info, BindingKind binding_kind, |
| 1365 VariableProxy* proxy, Variable* var) { |
1362 #ifdef DEBUG | 1366 #ifdef DEBUG |
1363 if (info->script_is_native()) { | 1367 if (info->script_is_native()) { |
1364 // To avoid polluting the global object in native scripts | 1368 // To avoid polluting the global object in native scripts |
1365 // - Variables must not be allocated to the global scope. | 1369 // - Variables must not be allocated to the global scope. |
1366 CHECK_NOT_NULL(outer_scope()); | 1370 CHECK_NOT_NULL(outer_scope()); |
1367 // - Variables must be bound locally or unallocated. | 1371 // - Variables must be bound locally or unallocated. |
1368 if (BOUND != binding_kind) { | 1372 if (BOUND != binding_kind) { |
1369 // The following variable name may be minified. If so, disable | 1373 // The following variable name may be minified. If so, disable |
1370 // minification in js2c.py for better output. | 1374 // minification in js2c.py for better output. |
1371 Handle<String> name = proxy->raw_name()->string(); | 1375 Handle<String> name = proxy->raw_name()->string(); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 proxy = proxy->next_unresolved()) { | 1435 proxy = proxy->next_unresolved()) { |
1432 ResolveVariable(info, proxy, factory); | 1436 ResolveVariable(info, proxy, factory); |
1433 } | 1437 } |
1434 | 1438 |
1435 // Resolve unresolved variables for inner scopes. | 1439 // Resolve unresolved variables for inner scopes. |
1436 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1440 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1437 scope->ResolveVariablesRecursively(info, factory); | 1441 scope->ResolveVariablesRecursively(info, factory); |
1438 } | 1442 } |
1439 } | 1443 } |
1440 | 1444 |
1441 void Scope::MigrateUnresolvableLocals(DeclarationScope* migrate_to, | 1445 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
1442 AstNodeFactory* ast_node_factory, | 1446 ParseInfo* info, |
1443 DeclarationScope* max_outer_scope) { | 1447 VariableProxy* stack) { |
1444 BindingKind binding_kind; | 1448 BindingKind binding_kind = BOUND; |
1445 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | 1449 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
1446 proxy = next) { | 1450 proxy = next) { |
1447 next = proxy->next_unresolved(); | 1451 next = proxy->next_unresolved(); |
| 1452 if (proxy->is_resolved()) continue; |
1448 // Note that we pass nullptr as AstNodeFactory: this phase should not create | 1453 // Note that we pass nullptr as AstNodeFactory: this phase should not create |
1449 // any new AstNodes, since none of the Scopes involved are backed up by | 1454 // any new AstNodes, since none of the Scopes involved are backed up by |
1450 // ScopeInfo. | 1455 // ScopeInfo. |
1451 if (LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope) == | 1456 Variable* var = |
1452 nullptr) { | 1457 LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope); |
1453 // Re-create the VariableProxies in the right Zone and insert them into | 1458 // Anything that was bound |
1454 // migrate_to. | 1459 if (var == nullptr) { |
1455 DCHECK(!proxy->is_resolved()); | 1460 proxy->set_next_unresolved(stack); |
1456 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); | 1461 stack = proxy; |
1457 migrate_to->AddUnresolved(copy); | 1462 } else if (info != nullptr) { |
| 1463 DCHECK_NE(UNBOUND, binding_kind); |
| 1464 DCHECK_NE(UNBOUND_EVAL_SHADOWED, binding_kind); |
| 1465 ResolveTo(info, binding_kind, proxy, var); |
1458 } | 1466 } |
1459 } | 1467 } |
1460 | 1468 |
| 1469 // Clear unresolved_ as it's in an inconsistent state. |
| 1470 unresolved_ = nullptr; |
| 1471 |
1461 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1472 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1462 scope->MigrateUnresolvableLocals(migrate_to, ast_node_factory, | 1473 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); |
1463 max_outer_scope); | |
1464 } | 1474 } |
| 1475 |
| 1476 return stack; |
1465 } | 1477 } |
1466 | 1478 |
1467 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval) { | 1479 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval) { |
1468 if (outer_scope_calls_sloppy_eval) { | 1480 if (outer_scope_calls_sloppy_eval) { |
1469 outer_scope_calls_sloppy_eval_ = true; | 1481 outer_scope_calls_sloppy_eval_ = true; |
1470 } | 1482 } |
1471 | 1483 |
1472 bool calls_sloppy_eval = | 1484 bool calls_sloppy_eval = |
1473 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; | 1485 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; |
1474 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { | 1486 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 function != NULL && function->proxy()->var()->IsContextSlot(); | 1791 function != NULL && function->proxy()->var()->IsContextSlot(); |
1780 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1792 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1781 (is_function_var_in_context ? 1 : 0); | 1793 (is_function_var_in_context ? 1 : 0); |
1782 } | 1794 } |
1783 | 1795 |
1784 | 1796 |
1785 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1797 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1786 | 1798 |
1787 } // namespace internal | 1799 } // namespace internal |
1788 } // namespace v8 | 1800 } // namespace v8 |
OLD | NEW |