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

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

Issue 2407163003: PreParser: track variable declarations and parameters (Closed)
Patch Set: fixing bad rebase Created 4 years 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"
11 #include "src/bootstrapper.h" 11 #include "src/bootstrapper.h"
12 #include "src/messages.h" 12 #include "src/messages.h"
13 #include "src/parsing/parse-info.h" 13 #include "src/parsing/parse-info.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 17
18 namespace {
19 void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
20 } // namespace
21
18 // ---------------------------------------------------------------------------- 22 // ----------------------------------------------------------------------------
19 // Implementation of LocalsMap 23 // Implementation of LocalsMap
20 // 24 //
21 // Note: We are storing the handle locations as key values in the hash map. 25 // Note: We are storing the handle locations as key values in the hash map.
22 // When inserting a new variable via Declare(), we rely on the fact that 26 // When inserting a new variable via Declare(), we rely on the fact that
23 // the handle location remains alive for the duration of that variable 27 // the handle location remains alive for the duration of that variable
24 // use. Because a Variable holding a handle with the same location exists 28 // use. Because a Variable holding a handle with the same location exists
25 // this is ensured. 29 // this is ensured.
26 30
27 VariableMap::VariableMap(Zone* zone) 31 VariableMap::VariableMap(Zone* zone)
(...skipping 14 matching lines...) Expand all
42 if (added) *added = p->value == nullptr; 46 if (added) *added = p->value == nullptr;
43 if (p->value == nullptr) { 47 if (p->value == nullptr) {
44 // The variable has not been declared yet -> insert it. 48 // The variable has not been declared yet -> insert it.
45 DCHECK_EQ(name, p->key); 49 DCHECK_EQ(name, p->key);
46 p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag, 50 p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag,
47 maybe_assigned_flag); 51 maybe_assigned_flag);
48 } 52 }
49 return reinterpret_cast<Variable*>(p->value); 53 return reinterpret_cast<Variable*>(p->value);
50 } 54 }
51 55
56 void VariableMap::DeclareName(Zone* zone, const AstRawString* name) {
Toon Verwaest 2016/12/01 10:50:56 We should probably have a debug mode flag to check
marja 2016/12/05 16:05:19 We already have is_lazily_parsed, but that's set t
57 Entry* p =
58 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
59 ZoneAllocationPolicy(zone));
60 if (p->value == nullptr) {
61 // The variable has not been declared yet -> insert it.
62 DCHECK_EQ(name, p->key);
63 p->value = kDummyPreParserVariable;
64 }
65 }
66
52 void VariableMap::Remove(Variable* var) { 67 void VariableMap::Remove(Variable* var) {
53 const AstRawString* name = var->raw_name(); 68 const AstRawString* name = var->raw_name();
54 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash()); 69 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash());
55 } 70 }
56 71
57 void VariableMap::Add(Zone* zone, Variable* var) { 72 void VariableMap::Add(Zone* zone, Variable* var) {
58 const AstRawString* name = var->raw_name(); 73 const AstRawString* name = var->raw_name();
59 Entry* p = 74 Entry* p =
60 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 75 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
61 ZoneAllocationPolicy(zone)); 76 ZoneAllocationPolicy(zone));
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 *is_duplicate = IsDeclaredParameter(name); 892 *is_duplicate = IsDeclaredParameter(name);
878 } 893 }
879 has_rest_ = is_rest; 894 has_rest_ = is_rest;
880 params_.Add(var, zone()); 895 params_.Add(var, zone());
881 if (name == ast_value_factory->arguments_string()) { 896 if (name == ast_value_factory->arguments_string()) {
882 has_arguments_parameter_ = true; 897 has_arguments_parameter_ = true;
883 } 898 }
884 return var; 899 return var;
885 } 900 }
886 901
902 void DeclarationScope::DeclareParameterName(
903 const AstRawString* name, bool is_optional, bool is_rest,
904 bool* is_duplicate, AstValueFactory* ast_value_factory) {
905 DCHECK(!already_resolved_);
906 DCHECK(is_function_scope() || is_module_scope());
907 DCHECK(!has_rest_);
908 DCHECK(!is_optional || !is_rest);
909 variables_.DeclareName(zone(), name);
910 // TODO(wingo): Avoid O(n^2) check.
Toon Verwaest 2016/12/01 10:50:56 Does it make sense to still add TODO's for wingo?
marja 2016/12/05 16:05:19 Was just copied over; but I deleted this whole fun
911 *is_duplicate = IsDeclaredParameter(name);
912 has_rest_ = is_rest;
Toon Verwaest 2016/12/01 10:50:56 Do we care about rest? Isn't that just used to dea
marja 2016/12/05 16:05:19 Ditto; the downside is that now preparsed scopes d
913 if (name == ast_value_factory->arguments_string()) {
Toon Verwaest 2016/12/01 10:50:56 Do we care about arguments? Isn't that just used t
marja 2016/12/05 16:05:19 Ditto
914 has_arguments_parameter_ = true;
915 }
916 }
917
887 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, 918 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
888 InitializationFlag init_flag, VariableKind kind, 919 InitializationFlag init_flag, VariableKind kind,
889 MaybeAssignedFlag maybe_assigned_flag) { 920 MaybeAssignedFlag maybe_assigned_flag) {
890 DCHECK(!already_resolved_); 921 DCHECK(!already_resolved_);
891 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are 922 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
892 // introduced during variable allocation, and TEMPORARY variables are 923 // introduced during variable allocation, and TEMPORARY variables are
893 // allocated via NewTemporary(). 924 // allocated via NewTemporary().
894 DCHECK(IsDeclaredVariableMode(mode)); 925 DCHECK(IsDeclaredVariableMode(mode));
895 return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag); 926 return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag);
896 } 927 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 // 1023 //
993 // This will lead to multiple declaration nodes for the 1024 // This will lead to multiple declaration nodes for the
994 // same variable if it is declared several times. This is not a 1025 // same variable if it is declared several times. This is not a
995 // semantic issue, but it may be a performance issue since it may 1026 // semantic issue, but it may be a performance issue since it may
996 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls. 1027 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
997 decls_.Add(declaration); 1028 decls_.Add(declaration);
998 proxy->BindTo(var); 1029 proxy->BindTo(var);
999 return var; 1030 return var;
1000 } 1031 }
1001 1032
1033 void Scope::DeclareVariableName(const AstRawString* name, VariableMode mode) {
1034 DCHECK(IsDeclaredVariableMode(mode));
1035 DCHECK(!already_resolved_);
1036
1037 if (mode == VAR && !is_declaration_scope()) {
1038 return GetDeclarationScope()->DeclareVariableName(name, mode);
1039 }
1040 DCHECK(!is_catch_scope());
1041 DCHECK(!is_with_scope());
1042 DCHECK(!is_eval_scope());
1043 DCHECK(is_declaration_scope() ||
1044 (IsLexicalVariableMode(mode) && is_block_scope()));
1045
1046 // Declare the variable in the declaration scope.
1047 if (LookupLocal(name) == nullptr) {
1048 variables_.DeclareName(zone(), name);
1049 }
1050 }
1051
1002 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory, 1052 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory,
1003 const AstRawString* name, 1053 const AstRawString* name,
1004 int start_position, VariableKind kind) { 1054 int start_position, VariableKind kind) {
1005 // Note that we must not share the unresolved variables with 1055 // Note that we must not share the unresolved variables with
1006 // the same name because they may be removed selectively via 1056 // the same name because they may be removed selectively via
1007 // RemoveUnresolved(). 1057 // RemoveUnresolved().
1008 DCHECK(!already_resolved_); 1058 DCHECK(!already_resolved_);
1009 DCHECK_EQ(factory->zone(), zone()); 1059 DCHECK_EQ(factory->zone(), zone());
1010 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_position); 1060 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_position);
1011 proxy->set_next_unresolved(unresolved_); 1061 proxy->set_next_unresolved(unresolved_);
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 Scope* Scope::GetOuterScopeWithContext() { 1316 Scope* Scope::GetOuterScopeWithContext() {
1267 Scope* scope = outer_scope_; 1317 Scope* scope = outer_scope_;
1268 while (scope && !scope->NeedsContext()) { 1318 while (scope && !scope->NeedsContext()) {
1269 scope = scope->outer_scope(); 1319 scope = scope->outer_scope();
1270 } 1320 }
1271 return scope; 1321 return scope;
1272 } 1322 }
1273 1323
1274 Handle<StringSet> DeclarationScope::CollectNonLocals( 1324 Handle<StringSet> DeclarationScope::CollectNonLocals(
1275 ParseInfo* info, Handle<StringSet> non_locals) { 1325 ParseInfo* info, Handle<StringSet> non_locals) {
1276 VariableProxy* free_variables = FetchFreeVariables(this, true, info); 1326 VariableProxy* free_variables = FetchFreeVariables(this, info);
1277 for (VariableProxy* proxy = free_variables; proxy != nullptr; 1327 for (VariableProxy* proxy = free_variables; proxy != nullptr;
1278 proxy = proxy->next_unresolved()) { 1328 proxy = proxy->next_unresolved()) {
1279 non_locals = StringSet::Add(non_locals, proxy->name()); 1329 non_locals = StringSet::Add(non_locals, proxy->name());
1280 } 1330 }
1281 return non_locals; 1331 return non_locals;
1282 } 1332 }
1283 1333
1284 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, 1334 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1285 bool aborted) { 1335 bool aborted) {
1286 DCHECK(is_function_scope()); 1336 DCHECK(is_function_scope());
(...skipping 28 matching lines...) Expand all
1315 } 1365 }
1316 1366
1317 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { 1367 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
1318 DCHECK(!force_eager_compilation_); 1368 DCHECK(!force_eager_compilation_);
1319 VariableProxy* unresolved = nullptr; 1369 VariableProxy* unresolved = nullptr;
1320 1370
1321 if (!outer_scope_->is_script_scope()) { 1371 if (!outer_scope_->is_script_scope()) {
1322 // Try to resolve unresolved variables for this Scope and migrate those 1372 // Try to resolve unresolved variables for this Scope and migrate those
1323 // which cannot be resolved inside. It doesn't make sense to try to resolve 1373 // which cannot be resolved inside. It doesn't make sense to try to resolve
1324 // them in the outer Scopes here, because they are incomplete. 1374 // them in the outer Scopes here, because they are incomplete.
1325 for (VariableProxy* proxy = 1375 for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr;
1326 FetchFreeVariables(this, !FLAG_lazy_inner_functions); 1376 proxy = proxy->next_unresolved()) {
1327 proxy != nullptr; proxy = proxy->next_unresolved()) {
1328 DCHECK(!proxy->is_resolved()); 1377 DCHECK(!proxy->is_resolved());
1329 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); 1378 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1330 copy->set_next_unresolved(unresolved); 1379 copy->set_next_unresolved(unresolved);
1331 unresolved = copy; 1380 unresolved = copy;
1332 } 1381 }
1333 1382
1334 // Clear arguments_ if unused. This is used as a signal for optimization. 1383 // Clear arguments_ if unused. This is used as a signal for optimization.
1335 if (arguments_ != nullptr && 1384 if (arguments_ != nullptr &&
1336 !(MustAllocate(arguments_) && !has_arguments_parameter_)) { 1385 !(MustAllocate(arguments_) && !has_arguments_parameter_)) {
1337 arguments_ = nullptr; 1386 arguments_ = nullptr;
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 NORMAL_VARIABLE); 1643 NORMAL_VARIABLE);
1595 } 1644 }
1596 1645
1597 DCHECK(!is_script_scope()); 1646 DCHECK(!is_script_scope());
1598 1647
1599 var = outer_scope_->LookupRecursive(proxy, outer_scope_end); 1648 var = outer_scope_->LookupRecursive(proxy, outer_scope_end);
1600 1649
1601 // The variable could not be resolved statically. 1650 // The variable could not be resolved statically.
1602 if (var == nullptr) return var; 1651 if (var == nullptr) return var;
1603 1652
1653 if (var == kDummyPreParserVariable) return var;
Toon Verwaest 2016/12/01 10:50:56 Mmh. We should probably stop sharing LookupRecursi
marja 2016/12/05 16:05:19 Ok, added a TODO about that. For that we should so
1654
1604 if (is_function_scope() && !var->is_dynamic()) { 1655 if (is_function_scope() && !var->is_dynamic()) {
1605 var->ForceContextAllocation(); 1656 var->ForceContextAllocation();
1606 } 1657 }
1607 // "this" can't be shadowed by "eval"-introduced bindings or by "with" 1658 // "this" can't be shadowed by "eval"-introduced bindings or by "with"
1608 // scopes. 1659 // scopes.
1609 // TODO(wingo): There are other variables in this category; add them. 1660 // TODO(wingo): There are other variables in this category; add them.
1610 if (var->is_this()) return var; 1661 if (var->is_this()) return var;
1611 1662
1612 if (is_with_scope()) { 1663 if (is_with_scope()) {
1613 // The current scope is a with scope, so the variable binding can not be 1664 // The current scope is a with scope, so the variable binding can not be
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 1811
1761 // Resolve unresolved variables for inner scopes. 1812 // Resolve unresolved variables for inner scopes.
1762 for (Scope* scope = inner_scope_; scope != nullptr; 1813 for (Scope* scope = inner_scope_; scope != nullptr;
1763 scope = scope->sibling_) { 1814 scope = scope->sibling_) {
1764 scope->ResolveVariablesRecursively(info); 1815 scope->ResolveVariablesRecursively(info);
1765 } 1816 }
1766 } 1817 }
1767 } 1818 }
1768 1819
1769 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, 1820 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
1770 bool try_to_resolve, ParseInfo* info, 1821 ParseInfo* info,
Toon Verwaest 2016/12/01 10:50:56 That obviously makes this slightly more complicate
marja 2016/12/05 16:05:19 I might need to introduce a new parameter here whi
1771 VariableProxy* stack) { 1822 VariableProxy* stack) {
1772 // Lazy parsed declaration scopes are already partially analyzed. If there are 1823 // Lazy parsed declaration scopes are already partially analyzed. If there are
1773 // unresolved references remaining, they just need to be resolved in outer 1824 // unresolved references remaining, they just need to be resolved in outer
1774 // scopes. 1825 // scopes.
1775 Scope* lookup = 1826 Scope* lookup =
1776 is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed() 1827 is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()
1777 ? outer_scope() 1828 ? outer_scope()
1778 : this; 1829 : this;
1779 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; 1830 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
1780 proxy = next) { 1831 proxy = next) {
1781 next = proxy->next_unresolved(); 1832 next = proxy->next_unresolved();
1782 DCHECK(!proxy->is_resolved()); 1833 DCHECK(!proxy->is_resolved());
1783 Variable* var = nullptr; 1834 Variable* var =
1784 if (try_to_resolve) { 1835 lookup->LookupRecursive(proxy, max_outer_scope->outer_scope());
1785 var = lookup->LookupRecursive(proxy, max_outer_scope->outer_scope());
1786 }
1787 if (var == nullptr) { 1836 if (var == nullptr) {
1788 proxy->set_next_unresolved(stack); 1837 proxy->set_next_unresolved(stack);
1789 stack = proxy; 1838 stack = proxy;
1790 } else if (info != nullptr) { 1839 } else if (var != kDummyPreParserVariable) {
1791 // In this case we need to leave scopes in a way that they can be 1840 if (info != nullptr) {
1792 // allocated. If we resolved variables from lazy parsed scopes, we need to 1841 // In this case we need to leave scopes in a way that they can be
1793 // context allocate the var. 1842 // allocated. If we resolved variables from lazy parsed scopes, we need
1794 ResolveTo(info, proxy, var); 1843 // to context allocate the var.
1795 if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation(); 1844 ResolveTo(info, proxy, var);
1796 } else { 1845 if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
1797 var->set_is_used(); 1846 } else {
1847 var->set_is_used();
1848 }
1798 } 1849 }
1799 } 1850 }
1800 1851
1801 // Clear unresolved_ as it's in an inconsistent state. 1852 // Clear unresolved_ as it's in an inconsistent state.
1802 unresolved_ = nullptr; 1853 unresolved_ = nullptr;
1803 1854
1804 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1855 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1805 stack = 1856 stack = scope->FetchFreeVariables(max_outer_scope, info, stack);
1806 scope->FetchFreeVariables(max_outer_scope, try_to_resolve, info, stack);
1807 } 1857 }
1808 1858
1809 return stack; 1859 return stack;
1810 } 1860 }
1811 1861
1812 bool Scope::MustAllocate(Variable* var) { 1862 bool Scope::MustAllocate(Variable* var) {
1813 DCHECK(var->location() != VariableLocation::MODULE); 1863 DCHECK(var->location() != VariableLocation::MODULE);
1814 // Give var a read/write use if there is a chance it might be accessed 1864 // Give var a read/write use if there is a chance it might be accessed
1815 // via an eval() call. This is only possible if the variable has a 1865 // via an eval() call. This is only possible if the variable has a
1816 // visible name. 1866 // visible name.
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
2071 Variable* function = 2121 Variable* function =
2072 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 2122 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2073 bool is_function_var_in_context = 2123 bool is_function_var_in_context =
2074 function != nullptr && function->IsContextSlot(); 2124 function != nullptr && function->IsContextSlot();
2075 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 2125 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2076 (is_function_var_in_context ? 1 : 0); 2126 (is_function_var_in_context ? 1 : 0);
2077 } 2127 }
2078 2128
2079 } // namespace internal 2129 } // namespace internal
2080 } // namespace v8 2130 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/parsing/preparser.h » ('j') | src/parsing/preparser.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698