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/ast/ast.h" | 10 #include "src/ast/ast.h" |
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 AllocateScopeInfosRecursively(info->isolate(), mode, outer_scope); | 1069 AllocateScopeInfosRecursively(info->isolate(), mode, outer_scope); |
1070 // The debugger expects all shared function infos to contain a scope info. | 1070 // The debugger expects all shared function infos to contain a scope info. |
1071 // Since the top-most scope will end up in a shared function info, make sure | 1071 // Since the top-most scope will end up in a shared function info, make sure |
1072 // it has one, even if it doesn't need a scope info. | 1072 // it has one, even if it doesn't need a scope info. |
1073 // TODO(jochen|yangguo): Remove this requirement. | 1073 // TODO(jochen|yangguo): Remove this requirement. |
1074 if (scope_info_.is_null()) { | 1074 if (scope_info_.is_null()) { |
1075 scope_info_ = ScopeInfo::Create(info->isolate(), zone(), this, outer_scope); | 1075 scope_info_ = ScopeInfo::Create(info->isolate(), zone(), this, outer_scope); |
1076 } | 1076 } |
1077 } | 1077 } |
1078 | 1078 |
1079 bool Scope::AllowsLazyParsing() const { | 1079 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables() const { |
1080 // If we are inside a block scope, we must parse eagerly to find out how | 1080 // If we are inside a block scope, we must find unresolved variables in the |
1081 // to allocate variables on the block scope. At this point, declarations may | 1081 // inner scopes to find out how to allocate variables on the block scope. At |
1082 // not have yet been parsed. | 1082 // this point, declarations may not have yet been parsed. |
1083 for (const Scope* s = this; s != nullptr; s = s->outer_scope_) { | 1083 for (const Scope* s = this; s != nullptr; s = s->outer_scope_) { |
1084 if (s->is_block_scope()) return false; | 1084 if (s->is_block_scope()) return false; |
| 1085 // TODO(marja): Refactor parsing modes: also add s->is_function_scope() |
| 1086 // here. |
1085 } | 1087 } |
1086 return true; | 1088 return true; |
1087 } | 1089 } |
1088 | 1090 |
1089 bool DeclarationScope::AllowsLazyCompilation() const { | 1091 bool DeclarationScope::AllowsLazyCompilation() const { |
1090 return !force_eager_compilation_; | 1092 return !force_eager_compilation_; |
1091 } | 1093 } |
1092 | 1094 |
1093 bool DeclarationScope::AllowsLazyCompilationWithoutContext() const { | 1095 bool DeclarationScope::AllowsLazyCompilationWithoutContext() const { |
1094 if (force_eager_compilation_) return false; | 1096 if (force_eager_compilation_) return false; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 Scope* Scope::GetOuterScopeWithContext() { | 1176 Scope* Scope::GetOuterScopeWithContext() { |
1175 Scope* scope = outer_scope_; | 1177 Scope* scope = outer_scope_; |
1176 while (scope && !scope->NeedsContext()) { | 1178 while (scope && !scope->NeedsContext()) { |
1177 scope = scope->outer_scope(); | 1179 scope = scope->outer_scope(); |
1178 } | 1180 } |
1179 return scope; | 1181 return scope; |
1180 } | 1182 } |
1181 | 1183 |
1182 Handle<StringSet> DeclarationScope::CollectNonLocals( | 1184 Handle<StringSet> DeclarationScope::CollectNonLocals( |
1183 ParseInfo* info, Handle<StringSet> non_locals) { | 1185 ParseInfo* info, Handle<StringSet> non_locals) { |
1184 VariableProxy* free_variables = FetchFreeVariables(this, info); | 1186 VariableProxy* free_variables = FetchFreeVariables(this, true, info); |
1185 for (VariableProxy* proxy = free_variables; proxy != nullptr; | 1187 for (VariableProxy* proxy = free_variables; proxy != nullptr; |
1186 proxy = proxy->next_unresolved()) { | 1188 proxy = proxy->next_unresolved()) { |
1187 non_locals = StringSet::Add(non_locals, proxy->name()); | 1189 non_locals = StringSet::Add(non_locals, proxy->name()); |
1188 } | 1190 } |
1189 return non_locals; | 1191 return non_locals; |
1190 } | 1192 } |
1191 | 1193 |
1192 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, | 1194 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, |
1193 AstNodeFactory* ast_node_factory) { | 1195 AstNodeFactory* ast_node_factory) { |
1194 // Try to resolve unresolved variables for this Scope and migrate those which | 1196 // Try to resolve unresolved variables for this Scope and migrate those which |
1195 // cannot be resolved inside. It doesn't make sense to try to resolve them in | 1197 // cannot be resolved inside. It doesn't make sense to try to resolve them in |
1196 // the outer Scopes here, because they are incomplete. | 1198 // the outer Scopes here, because they are incomplete. |
1197 for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr; | 1199 for (VariableProxy* proxy = |
1198 proxy = proxy->next_unresolved()) { | 1200 FetchFreeVariables(this, !FLAG_lazy_inner_functions); |
| 1201 proxy != nullptr; proxy = proxy->next_unresolved()) { |
1199 DCHECK(!proxy->is_resolved()); | 1202 DCHECK(!proxy->is_resolved()); |
1200 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); | 1203 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); |
1201 migrate_to->AddUnresolved(copy); | 1204 migrate_to->AddUnresolved(copy); |
1202 } | 1205 } |
1203 | 1206 |
1204 // Push scope data up to migrate_to. Note that migrate_to and this Scope | 1207 // Push scope data up to migrate_to. Note that migrate_to and this Scope |
1205 // describe the same Scope, just in different Zones. | 1208 // describe the same Scope, just in different Zones. |
1206 PropagateUsageFlagsToScope(migrate_to); | 1209 PropagateUsageFlagsToScope(migrate_to); |
1207 if (scope_uses_super_property_) migrate_to->scope_uses_super_property_ = true; | 1210 if (scope_uses_super_property_) migrate_to->scope_uses_super_property_ = true; |
1208 if (inner_scope_calls_eval_) migrate_to->inner_scope_calls_eval_ = true; | 1211 if (inner_scope_calls_eval_) migrate_to->inner_scope_calls_eval_ = true; |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 } | 1514 } |
1512 | 1515 |
1513 return var; | 1516 return var; |
1514 } | 1517 } |
1515 | 1518 |
1516 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) { | 1519 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) { |
1517 DCHECK(info->script_scope()->is_script_scope()); | 1520 DCHECK(info->script_scope()->is_script_scope()); |
1518 DCHECK(!proxy->is_resolved()); | 1521 DCHECK(!proxy->is_resolved()); |
1519 Variable* var = LookupRecursive(proxy, nullptr); | 1522 Variable* var = LookupRecursive(proxy, nullptr); |
1520 ResolveTo(info, proxy, var); | 1523 ResolveTo(info, proxy, var); |
| 1524 |
| 1525 if (FLAG_lazy_inner_functions) { |
| 1526 if (info != nullptr && info->is_native()) return; |
| 1527 // Pessimistically force context allocation for all variables to which inner |
| 1528 // scope variables could potentially resolve to. |
| 1529 Scope* scope = GetClosureScope()->outer_scope_; |
| 1530 while (scope != nullptr && scope->scope_info_.is_null()) { |
| 1531 var = scope->LookupLocal(proxy->raw_name()); |
| 1532 if (var != nullptr) { |
| 1533 if (!var->is_dynamic() && !var->is_this() && |
| 1534 !var->has_forced_context_allocation() && !var->is_arguments()) { |
| 1535 var->ForceContextAllocation(); |
| 1536 var->set_is_used(); |
| 1537 // We don't know what the (potentially lazy parsed) inner function |
| 1538 // does with the variable; pessimistically assume that it's assigned. |
| 1539 var->set_maybe_assigned(); |
| 1540 } |
| 1541 } |
| 1542 scope = scope->outer_scope_; |
| 1543 } |
| 1544 } |
1521 } | 1545 } |
1522 | 1546 |
1523 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) { | 1547 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) { |
1524 #ifdef DEBUG | 1548 #ifdef DEBUG |
1525 if (info->script_is_native()) { | 1549 if (info->script_is_native()) { |
1526 // To avoid polluting the global object in native scripts | 1550 // To avoid polluting the global object in native scripts |
1527 // - Variables must not be allocated to the global scope. | 1551 // - Variables must not be allocated to the global scope. |
1528 CHECK_NOT_NULL(outer_scope()); | 1552 CHECK_NOT_NULL(outer_scope()); |
1529 // - Variables must be bound locally or unallocated. | 1553 // - Variables must be bound locally or unallocated. |
1530 if (var->IsGlobalObjectProperty()) { | 1554 if (var->IsGlobalObjectProperty()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1556 ResolveVariable(info, proxy); | 1580 ResolveVariable(info, proxy); |
1557 } | 1581 } |
1558 | 1582 |
1559 // Resolve unresolved variables for inner scopes. | 1583 // Resolve unresolved variables for inner scopes. |
1560 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1584 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1561 scope->ResolveVariablesRecursively(info); | 1585 scope->ResolveVariablesRecursively(info); |
1562 } | 1586 } |
1563 } | 1587 } |
1564 | 1588 |
1565 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, | 1589 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
1566 ParseInfo* info, | 1590 bool try_to_resolve, ParseInfo* info, |
1567 VariableProxy* stack) { | 1591 VariableProxy* stack) { |
1568 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | 1592 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
1569 proxy = next) { | 1593 proxy = next) { |
1570 next = proxy->next_unresolved(); | 1594 next = proxy->next_unresolved(); |
1571 DCHECK(!proxy->is_resolved()); | 1595 DCHECK(!proxy->is_resolved()); |
1572 Variable* var = LookupRecursive(proxy, max_outer_scope->outer_scope()); | 1596 Variable* var = nullptr; |
| 1597 if (try_to_resolve) { |
| 1598 var = LookupRecursive(proxy, max_outer_scope->outer_scope()); |
| 1599 } |
1573 if (var == nullptr) { | 1600 if (var == nullptr) { |
1574 proxy->set_next_unresolved(stack); | 1601 proxy->set_next_unresolved(stack); |
1575 stack = proxy; | 1602 stack = proxy; |
1576 } else if (info != nullptr) { | 1603 } else if (info != nullptr) { |
1577 ResolveTo(info, proxy, var); | 1604 ResolveTo(info, proxy, var); |
1578 } | 1605 } |
1579 } | 1606 } |
1580 | 1607 |
1581 // Clear unresolved_ as it's in an inconsistent state. | 1608 // Clear unresolved_ as it's in an inconsistent state. |
1582 unresolved_ = nullptr; | 1609 unresolved_ = nullptr; |
1583 | 1610 |
1584 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1611 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1585 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); | 1612 stack = |
| 1613 scope->FetchFreeVariables(max_outer_scope, try_to_resolve, info, stack); |
1586 } | 1614 } |
1587 | 1615 |
1588 return stack; | 1616 return stack; |
1589 } | 1617 } |
1590 | 1618 |
1591 bool Scope::MustAllocate(Variable* var) { | 1619 bool Scope::MustAllocate(Variable* var) { |
1592 DCHECK(var->location() != VariableLocation::MODULE); | 1620 DCHECK(var->location() != VariableLocation::MODULE); |
1593 // Give var a read/write use if there is a chance it might be accessed | 1621 // Give var a read/write use if there is a chance it might be accessed |
1594 // via an eval() call. This is only possible if the variable has a | 1622 // via an eval() call. This is only possible if the variable has a |
1595 // visible name. | 1623 // visible name. |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1831 Variable* function = | 1859 Variable* function = |
1832 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 1860 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
1833 bool is_function_var_in_context = | 1861 bool is_function_var_in_context = |
1834 function != nullptr && function->IsContextSlot(); | 1862 function != nullptr && function->IsContextSlot(); |
1835 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1863 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1836 (is_function_var_in_context ? 1 : 0); | 1864 (is_function_var_in_context ? 1 : 0); |
1837 } | 1865 } |
1838 | 1866 |
1839 } // namespace internal | 1867 } // namespace internal |
1840 } // namespace v8 | 1868 } // namespace v8 |
OLD | NEW |