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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 return var; | 999 return var; |
1000 } | 1000 } |
1001 | 1001 |
1002 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory, | 1002 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory, |
1003 const AstRawString* name, | 1003 const AstRawString* name, |
1004 int start_position, VariableKind kind) { | 1004 int start_position, VariableKind kind) { |
1005 // Note that we must not share the unresolved variables with | 1005 // Note that we must not share the unresolved variables with |
1006 // the same name because they may be removed selectively via | 1006 // the same name because they may be removed selectively via |
1007 // RemoveUnresolved(). | 1007 // RemoveUnresolved(). |
1008 DCHECK(!already_resolved_); | 1008 DCHECK(!already_resolved_); |
1009 DCHECK_EQ(!needs_migration_, factory->zone() == zone()); | 1009 DCHECK_EQ(factory->zone(), zone()); |
1010 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_position); | 1010 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_position); |
1011 proxy->set_next_unresolved(unresolved_); | 1011 proxy->set_next_unresolved(unresolved_); |
1012 unresolved_ = proxy; | 1012 unresolved_ = proxy; |
1013 return proxy; | 1013 return proxy; |
1014 } | 1014 } |
1015 | 1015 |
1016 void Scope::AddUnresolved(VariableProxy* proxy) { | 1016 void Scope::AddUnresolved(VariableProxy* proxy) { |
1017 DCHECK(!already_resolved_); | 1017 DCHECK(!already_resolved_); |
1018 DCHECK(!proxy->is_resolved()); | 1018 DCHECK(!proxy->is_resolved()); |
1019 proxy->set_next_unresolved(unresolved_); | 1019 proxy->set_next_unresolved(unresolved_); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 } | 1282 } |
1283 | 1283 |
1284 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, | 1284 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, |
1285 bool aborted) { | 1285 bool aborted) { |
1286 DCHECK(is_function_scope()); | 1286 DCHECK(is_function_scope()); |
1287 | 1287 |
1288 // Reset all non-trivial members. | 1288 // Reset all non-trivial members. |
1289 params_.Clear(); | 1289 params_.Clear(); |
1290 decls_.Clear(); | 1290 decls_.Clear(); |
1291 locals_.Clear(); | 1291 locals_.Clear(); |
1292 sloppy_block_function_map_.Clear(); | |
1293 variables_.Clear(); | |
1294 // Make sure we won't walk the scope tree from here on. | |
1295 inner_scope_ = nullptr; | 1292 inner_scope_ = nullptr; |
1296 unresolved_ = nullptr; | 1293 unresolved_ = nullptr; |
1297 | 1294 |
1298 if (aborted && !IsArrowFunction(function_kind_)) { | 1295 if (aborted) { |
1299 DeclareDefaultFunctionVariables(ast_value_factory); | 1296 // Prepare scope for use in the outer zone. |
| 1297 zone_ = ast_value_factory->zone(); |
| 1298 variables_.Reset(ZoneAllocationPolicy(zone_)); |
| 1299 sloppy_block_function_map_.Reset(ZoneAllocationPolicy(zone_)); |
| 1300 if (!IsArrowFunction(function_kind_)) { |
| 1301 DeclareDefaultFunctionVariables(ast_value_factory); |
| 1302 } |
| 1303 } else { |
| 1304 // Make sure this scope isn't used for allocation anymore. |
| 1305 zone_ = nullptr; |
| 1306 variables_.Invalidate(); |
| 1307 sloppy_block_function_map_.Invalidate(); |
1300 } | 1308 } |
1301 | 1309 |
1302 #ifdef DEBUG | 1310 #ifdef DEBUG |
1303 needs_migration_ = false; | 1311 needs_migration_ = false; |
1304 #endif | 1312 #endif |
1305 | 1313 |
1306 is_lazily_parsed_ = !aborted; | 1314 is_lazily_parsed_ = !aborted; |
1307 } | 1315 } |
1308 | 1316 |
1309 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { | 1317 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 Indent(n1, "// "); | 1503 Indent(n1, "// "); |
1496 PrintF("%d heap slots\n", num_heap_slots_); | 1504 PrintF("%d heap slots\n", num_heap_slots_); |
1497 } | 1505 } |
1498 | 1506 |
1499 // Print locals. | 1507 // Print locals. |
1500 if (function != nullptr) { | 1508 if (function != nullptr) { |
1501 Indent(n1, "// function var:\n"); | 1509 Indent(n1, "// function var:\n"); |
1502 PrintVar(n1, function); | 1510 PrintVar(n1, function); |
1503 } | 1511 } |
1504 | 1512 |
1505 if (variables_.Start() != NULL) { | 1513 if (variables_.occupancy() != 0) { |
1506 Indent(n1, "// local vars:\n"); | 1514 Indent(n1, "// local vars:\n"); |
1507 PrintMap(n1, &variables_, true); | 1515 PrintMap(n1, &variables_, true); |
1508 | 1516 |
1509 Indent(n1, "// dynamic vars:\n"); | 1517 Indent(n1, "// dynamic vars:\n"); |
1510 PrintMap(n1, &variables_, false); | 1518 PrintMap(n1, &variables_, false); |
1511 } | 1519 } |
1512 | 1520 |
1513 // Print inner scopes (disable by providing negative n). | 1521 // Print inner scopes (disable by providing negative n). |
1514 if (n >= 0) { | 1522 if (n >= 0) { |
1515 for (Scope* scope = inner_scope_; scope != nullptr; | 1523 for (Scope* scope = inner_scope_; scope != nullptr; |
(...skipping 13 matching lines...) Expand all Loading... |
1529 CHECK_NE(kNoSourcePosition, end_position()); | 1537 CHECK_NE(kNoSourcePosition, end_position()); |
1530 } | 1538 } |
1531 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1539 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1532 scope->CheckScopePositions(); | 1540 scope->CheckScopePositions(); |
1533 } | 1541 } |
1534 } | 1542 } |
1535 | 1543 |
1536 void Scope::CheckZones() { | 1544 void Scope::CheckZones() { |
1537 DCHECK(!needs_migration_); | 1545 DCHECK(!needs_migration_); |
1538 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1546 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
| 1547 if (scope->is_declaration_scope() && |
| 1548 scope->AsDeclarationScope()->is_lazily_parsed()) { |
| 1549 DCHECK_NULL(scope->zone()); |
| 1550 DCHECK_NULL(scope->inner_scope_); |
| 1551 continue; |
| 1552 } |
1539 CHECK_EQ(scope->zone(), zone()); | 1553 CHECK_EQ(scope->zone(), zone()); |
1540 scope->CheckZones(); | 1554 scope->CheckZones(); |
1541 } | 1555 } |
1542 } | 1556 } |
1543 #endif // DEBUG | 1557 #endif // DEBUG |
1544 | 1558 |
1545 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { | 1559 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { |
1546 // Declare a new non-local. | 1560 // Declare a new non-local. |
1547 DCHECK(IsDynamicVariableMode(mode)); | 1561 DCHECK(IsDynamicVariableMode(mode)); |
1548 Variable* var = variables_.Declare(zone(), NULL, name, mode, NORMAL_VARIABLE, | 1562 Variable* var = variables_.Declare(zone(), NULL, name, mode, NORMAL_VARIABLE, |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 #endif | 1730 #endif |
1717 | 1731 |
1718 DCHECK_NOT_NULL(var); | 1732 DCHECK_NOT_NULL(var); |
1719 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1733 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1720 if (AccessNeedsHoleCheck(var, proxy, this)) proxy->set_needs_hole_check(); | 1734 if (AccessNeedsHoleCheck(var, proxy, this)) proxy->set_needs_hole_check(); |
1721 proxy->BindTo(var); | 1735 proxy->BindTo(var); |
1722 } | 1736 } |
1723 | 1737 |
1724 void Scope::ResolveVariablesRecursively(ParseInfo* info) { | 1738 void Scope::ResolveVariablesRecursively(ParseInfo* info) { |
1725 DCHECK(info->script_scope()->is_script_scope()); | 1739 DCHECK(info->script_scope()->is_script_scope()); |
| 1740 // Lazy parsed declaration scopes are already partially analyzed. If there are |
| 1741 // unresolved references remaining, they just need to be resolved in outer |
| 1742 // scopes. |
| 1743 if (is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()) { |
| 1744 DCHECK(variables_.occupancy() == 0); |
| 1745 for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
| 1746 proxy = proxy->next_unresolved()) { |
| 1747 Variable* var = outer_scope()->LookupRecursive(proxy, nullptr); |
| 1748 if (!var->is_dynamic()) { |
| 1749 var->set_is_used(); |
| 1750 var->ForceContextAllocation(); |
| 1751 if (proxy->is_assigned()) var->set_maybe_assigned(); |
| 1752 } |
| 1753 } |
| 1754 } else { |
| 1755 // Resolve unresolved variables for this scope. |
| 1756 for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
| 1757 proxy = proxy->next_unresolved()) { |
| 1758 ResolveVariable(info, proxy); |
| 1759 } |
1726 | 1760 |
1727 // Resolve unresolved variables for this scope. | 1761 // Resolve unresolved variables for inner scopes. |
1728 for (VariableProxy* proxy = unresolved_; proxy != nullptr; | 1762 for (Scope* scope = inner_scope_; scope != nullptr; |
1729 proxy = proxy->next_unresolved()) { | 1763 scope = scope->sibling_) { |
1730 ResolveVariable(info, proxy); | 1764 scope->ResolveVariablesRecursively(info); |
1731 } | 1765 } |
1732 | |
1733 // Resolve unresolved variables for inner scopes. | |
1734 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | |
1735 scope->ResolveVariablesRecursively(info); | |
1736 } | 1766 } |
1737 } | 1767 } |
1738 | 1768 |
1739 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, | 1769 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
1740 bool try_to_resolve, ParseInfo* info, | 1770 bool try_to_resolve, ParseInfo* info, |
1741 VariableProxy* stack) { | 1771 VariableProxy* stack) { |
| 1772 // Lazy parsed declaration scopes are already partially analyzed. If there are |
| 1773 // unresolved references remaining, they just need to be resolved in outer |
| 1774 // scopes. |
| 1775 Scope* lookup = |
| 1776 is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed() |
| 1777 ? outer_scope() |
| 1778 : this; |
1742 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | 1779 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
1743 proxy = next) { | 1780 proxy = next) { |
1744 next = proxy->next_unresolved(); | 1781 next = proxy->next_unresolved(); |
1745 DCHECK(!proxy->is_resolved()); | 1782 DCHECK(!proxy->is_resolved()); |
1746 Variable* var = nullptr; | 1783 Variable* var = nullptr; |
1747 if (try_to_resolve) { | 1784 if (try_to_resolve) { |
1748 var = LookupRecursive(proxy, max_outer_scope->outer_scope()); | 1785 var = lookup->LookupRecursive(proxy, max_outer_scope->outer_scope()); |
1749 } | 1786 } |
1750 if (var == nullptr) { | 1787 if (var == nullptr) { |
1751 proxy->set_next_unresolved(stack); | 1788 proxy->set_next_unresolved(stack); |
1752 stack = proxy; | 1789 stack = proxy; |
1753 } else if (info != nullptr) { | 1790 } else if (info != nullptr) { |
| 1791 // In this case we need to leave scopes in a way that they can be |
| 1792 // allocated. If we resolved variables from lazy parsed scopes, we need to |
| 1793 // context allocate the var. |
1754 ResolveTo(info, proxy, var); | 1794 ResolveTo(info, proxy, var); |
| 1795 if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation(); |
1755 } else { | 1796 } else { |
1756 var->set_is_used(); | 1797 var->set_is_used(); |
1757 } | 1798 } |
1758 } | 1799 } |
1759 | 1800 |
1760 // Clear unresolved_ as it's in an inconsistent state. | 1801 // Clear unresolved_ as it's in an inconsistent state. |
1761 unresolved_ = nullptr; | 1802 unresolved_ = nullptr; |
1762 | 1803 |
1763 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1804 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1764 stack = | 1805 stack = |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2030 Variable* function = | 2071 Variable* function = |
2031 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 2072 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
2032 bool is_function_var_in_context = | 2073 bool is_function_var_in_context = |
2033 function != nullptr && function->IsContextSlot(); | 2074 function != nullptr && function->IsContextSlot(); |
2034 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 2075 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
2035 (is_function_var_in_context ? 1 : 0); | 2076 (is_function_var_in_context ? 1 : 0); |
2036 } | 2077 } |
2037 | 2078 |
2038 } // namespace internal | 2079 } // namespace internal |
2039 } // namespace v8 | 2080 } // namespace v8 |
OLD | NEW |