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