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" |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |