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

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

Issue 2352593002: Preparse inner functions (new try) (Closed)
Patch Set: style & cleanup Created 4 years, 2 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 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after
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::AllowsLazyParsing() const { 1076 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables() const {
1077 // If we are inside a block scope, we must parse eagerly to find out how 1077 // If we are inside a block scope, we must find unresolved variables in the
1078 // to allocate variables on the block scope. At this point, declarations may 1078 // inner scopes to find out how to allocate variables on the block scope. At
1079 // not have yet been parsed. 1079 // this point, declarations may 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.
1082 } 1084 }
1083 return true; 1085 return true;
1084 } 1086 }
1085 1087
1086 bool DeclarationScope::AllowsLazyCompilation() const { 1088 bool DeclarationScope::AllowsLazyCompilation() const {
1087 return !force_eager_compilation_; 1089 return !force_eager_compilation_;
1088 } 1090 }
1089 1091
1090 bool DeclarationScope::AllowsLazyCompilationWithoutContext() const { 1092 bool DeclarationScope::AllowsLazyCompilationWithoutContext() const {
1091 if (force_eager_compilation_) return false; 1093 if (force_eager_compilation_) return false;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 Scope* Scope::GetOuterScopeWithContext() { 1173 Scope* Scope::GetOuterScopeWithContext() {
1172 Scope* scope = outer_scope_; 1174 Scope* scope = outer_scope_;
1173 while (scope && !scope->NeedsContext()) { 1175 while (scope && !scope->NeedsContext()) {
1174 scope = scope->outer_scope(); 1176 scope = scope->outer_scope();
1175 } 1177 }
1176 return scope; 1178 return scope;
1177 } 1179 }
1178 1180
1179 Handle<StringSet> DeclarationScope::CollectNonLocals( 1181 Handle<StringSet> DeclarationScope::CollectNonLocals(
1180 ParseInfo* info, Handle<StringSet> non_locals) { 1182 ParseInfo* info, Handle<StringSet> non_locals) {
1181 VariableProxy* free_variables = FetchFreeVariables(this, info); 1183 VariableProxy* free_variables = FetchFreeVariables(this, true, info);
1182 for (VariableProxy* proxy = free_variables; proxy != nullptr; 1184 for (VariableProxy* proxy = free_variables; proxy != nullptr;
1183 proxy = proxy->next_unresolved()) { 1185 proxy = proxy->next_unresolved()) {
1184 non_locals = StringSet::Add(non_locals, proxy->name()); 1186 non_locals = StringSet::Add(non_locals, proxy->name());
1185 } 1187 }
1186 return non_locals; 1188 return non_locals;
1187 } 1189 }
1188 1190
1189 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, 1191 void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to,
1190 AstNodeFactory* ast_node_factory) { 1192 AstNodeFactory* ast_node_factory) {
1191 // Try to resolve unresolved variables for this Scope and migrate those which 1193 // Try to resolve unresolved variables for this Scope and migrate those which
1192 // cannot be resolved inside. It doesn't make sense to try to resolve them in 1194 // cannot be resolved inside. It doesn't make sense to try to resolve them in
1193 // the outer Scopes here, because they are incomplete. 1195 // the outer Scopes here, because they are incomplete.
1194 for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr; 1196 for (VariableProxy* proxy =
1195 proxy = proxy->next_unresolved()) { 1197 FetchFreeVariables(this, !FLAG_lazy_inner_functions);
1198 proxy != nullptr; proxy = proxy->next_unresolved()) {
1196 DCHECK(!proxy->is_resolved()); 1199 DCHECK(!proxy->is_resolved());
1197 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); 1200 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1198 migrate_to->AddUnresolved(copy); 1201 migrate_to->AddUnresolved(copy);
1199 } 1202 }
1200 1203
1201 // Push scope data up to migrate_to. Note that migrate_to and this Scope 1204 // Push scope data up to migrate_to. Note that migrate_to and this Scope
1202 // describe the same Scope, just in different Zones. 1205 // describe the same Scope, just in different Zones.
1203 PropagateUsageFlagsToScope(migrate_to); 1206 PropagateUsageFlagsToScope(migrate_to);
1204 if (scope_uses_super_property_) migrate_to->scope_uses_super_property_ = true; 1207 if (scope_uses_super_property_) migrate_to->scope_uses_super_property_ = true;
1205 if (inner_scope_calls_eval_) migrate_to->inner_scope_calls_eval_ = true; 1208 if (inner_scope_calls_eval_) migrate_to->inner_scope_calls_eval_ = true;
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 } 1512 }
1510 1513
1511 return var; 1514 return var;
1512 } 1515 }
1513 1516
1514 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) { 1517 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1515 DCHECK(info->script_scope()->is_script_scope()); 1518 DCHECK(info->script_scope()->is_script_scope());
1516 DCHECK(!proxy->is_resolved()); 1519 DCHECK(!proxy->is_resolved());
1517 Variable* var = LookupRecursive(proxy, nullptr); 1520 Variable* var = LookupRecursive(proxy, nullptr);
1518 ResolveTo(info, proxy, var); 1521 ResolveTo(info, proxy, var);
1522
1523 if (FLAG_lazy_inner_functions) {
1524 if (info != nullptr && info->is_native()) return;
1525 // Pessimistically force context allocation for all variables to which inner
1526 // scope variables could potentially resolve to.
1527 Scope* scope = GetClosureScope()->outer_scope_;
1528 while (scope != nullptr && scope->scope_info_.is_null()) {
1529 var = scope->LookupLocal(proxy->raw_name());
1530 if (var != nullptr) {
1531 if (!var->is_dynamic() && !var->is_this() &&
1532 !var->has_forced_context_allocation() && !var->is_arguments()) {
adamk 2016/09/23 18:21:30 I think is_arguments() is now dead. What's the is
marja 2016/09/26 07:14:41 Here I just wanted to be less pessimistic and whit
1533 var->ForceContextAllocation();
1534 var->set_is_used();
1535 // We don't know what the (potentially lazy parsed) inner function
1536 // does with the variable; pessimistically assume that it's assigned.
1537 var->set_maybe_assigned();
1538 }
1539 }
1540 scope = scope->outer_scope_;
1541 }
1542 }
1519 } 1543 }
1520 1544
1521 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) { 1545 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1522 #ifdef DEBUG 1546 #ifdef DEBUG
1523 if (info->script_is_native()) { 1547 if (info->script_is_native()) {
1524 // To avoid polluting the global object in native scripts 1548 // To avoid polluting the global object in native scripts
1525 // - Variables must not be allocated to the global scope. 1549 // - Variables must not be allocated to the global scope.
1526 CHECK_NOT_NULL(outer_scope()); 1550 CHECK_NOT_NULL(outer_scope());
1527 // - Variables must be bound locally or unallocated. 1551 // - Variables must be bound locally or unallocated.
1528 if (var->IsGlobalObjectProperty()) { 1552 if (var->IsGlobalObjectProperty()) {
(...skipping 25 matching lines...) Expand all
1554 ResolveVariable(info, proxy); 1578 ResolveVariable(info, proxy);
1555 } 1579 }
1556 1580
1557 // Resolve unresolved variables for inner scopes. 1581 // Resolve unresolved variables for inner scopes.
1558 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1582 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1559 scope->ResolveVariablesRecursively(info); 1583 scope->ResolveVariablesRecursively(info);
1560 } 1584 }
1561 } 1585 }
1562 1586
1563 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, 1587 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
1564 ParseInfo* info, 1588 bool try_to_resolve, ParseInfo* info,
1565 VariableProxy* stack) { 1589 VariableProxy* stack) {
1566 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; 1590 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
1567 proxy = next) { 1591 proxy = next) {
1568 next = proxy->next_unresolved(); 1592 next = proxy->next_unresolved();
1569 DCHECK(!proxy->is_resolved()); 1593 DCHECK(!proxy->is_resolved());
1570 Variable* var = LookupRecursive(proxy, max_outer_scope->outer_scope()); 1594 Variable* var = nullptr;
1595 if (try_to_resolve) {
Toon Verwaest 2016/09/23 11:51:18 Can't you just move !FLAG_lazy_inner_functions her
marja 2016/09/23 14:26:52 Offline discussion: If we don't resolve here, Col
1596 var = LookupRecursive(proxy, max_outer_scope->outer_scope());
1597 }
1571 if (var == nullptr) { 1598 if (var == nullptr) {
1572 proxy->set_next_unresolved(stack); 1599 proxy->set_next_unresolved(stack);
1573 stack = proxy; 1600 stack = proxy;
1574 } else if (info != nullptr) { 1601 } else if (info != nullptr) {
1575 ResolveTo(info, proxy, var); 1602 ResolveTo(info, proxy, var);
1576 } 1603 }
1577 } 1604 }
1578 1605
1579 // Clear unresolved_ as it's in an inconsistent state. 1606 // Clear unresolved_ as it's in an inconsistent state.
1580 unresolved_ = nullptr; 1607 unresolved_ = nullptr;
1581 1608
1582 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1609 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1583 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); 1610 stack =
1611 scope->FetchFreeVariables(max_outer_scope, try_to_resolve, info, stack);
1584 } 1612 }
1585 1613
1586 return stack; 1614 return stack;
1587 } 1615 }
1588 1616
1589 bool Scope::MustAllocate(Variable* var) { 1617 bool Scope::MustAllocate(Variable* var) {
1590 DCHECK(var->location() != VariableLocation::MODULE); 1618 DCHECK(var->location() != VariableLocation::MODULE);
1591 // Give var a read/write use if there is a chance it might be accessed 1619 // Give var a read/write use if there is a chance it might be accessed
1592 // via an eval() call. This is only possible if the variable has a 1620 // via an eval() call. This is only possible if the variable has a
1593 // visible name. 1621 // visible name.
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 Variable* function = 1857 Variable* function =
1830 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 1858 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
1831 bool is_function_var_in_context = 1859 bool is_function_var_in_context =
1832 function != nullptr && function->IsContextSlot(); 1860 function != nullptr && function->IsContextSlot();
1833 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1861 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1834 (is_function_var_in_context ? 1 : 0); 1862 (is_function_var_in_context ? 1 : 0);
1835 } 1863 }
1836 1864
1837 } // namespace internal 1865 } // namespace internal
1838 } // namespace v8 1866 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/flag-definitions.h » ('j') | src/parsing/parser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698