Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: src/ast/scopes.cc

Issue 2352593002: Preparse inner functions (new try) (Closed)
Patch Set: rebased again Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/flag-definitions.h » ('j') | test/mjsunit/debug-function-scopes.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698