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

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

Issue 2411873004: [ignition] Eliminate hole checks where statically possible for loads and stores (Closed)
Patch Set: Rebased 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
« no previous file with comments | « src/ast/scopes.h ('k') | src/ast/variables.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 // We don't know what the (potentially lazy parsed) inner function 1628 // We don't know what the (potentially lazy parsed) inner function
1629 // does with the variable; pessimistically assume that it's assigned. 1629 // does with the variable; pessimistically assume that it's assigned.
1630 var->set_maybe_assigned(); 1630 var->set_maybe_assigned();
1631 } 1631 }
1632 } 1632 }
1633 scope = scope->outer_scope_; 1633 scope = scope->outer_scope_;
1634 } 1634 }
1635 } 1635 }
1636 } 1636 }
1637 1637
1638 namespace {
1639
1640 bool AccessNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1641 if (!var->binding_needs_init()) {
1642 return false;
1643 }
1644
1645 // It's impossible to eliminate module import hole checks here, because it's
1646 // unknown at compilation time whether the binding referred to in the
1647 // exporting module itself requires hole checks.
1648 if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
1649 return true;
1650 }
1651
1652 // Check if the binding really needs an initialization check. The check
1653 // can be skipped in the following situation: we have a LET or CONST
1654 // binding, both the Variable and the VariableProxy have the same
1655 // declaration scope (i.e. they are both in global code, in the
1656 // same function or in the same eval code), the VariableProxy is in
1657 // the source physically located after the initializer of the variable,
1658 // and that the initializer cannot be skipped due to a nonlinear scope.
1659 //
1660 // The condition on the declaration scopes is a conservative check for
1661 // nested functions that access a binding and are called before the
1662 // binding is initialized:
1663 // function() { f(); let x = 1; function f() { x = 2; } }
1664 //
1665 // The check cannot be skipped on non-linear scopes, namely switch
1666 // scopes, to ensure tests are done in cases like the following:
1667 // switch (1) { case 0: let x = 2; case 1: f(x); }
1668 // The scope of the variable needs to be checked, in case the use is
1669 // in a sub-block which may be linear.
1670 if (var->scope()->GetDeclarationScope() != scope->GetDeclarationScope()) {
1671 return true;
1672 }
1673
1674 if (var->is_this()) {
1675 DCHECK(
1676 IsSubclassConstructor(scope->GetDeclarationScope()->function_kind()));
1677 // TODO(littledan): implement 'this' hole check elimination.
1678 return true;
1679 }
1680
1681 // We should always have valid source positions.
1682 DCHECK(var->initializer_position() != kNoSourcePosition);
1683 DCHECK(proxy->position() != kNoSourcePosition);
1684
1685 return var->scope()->is_nonlinear() ||
1686 var->initializer_position() >= proxy->position();
1687 }
1688
1689 } // anonymous namespace
1690
1638 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) { 1691 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1639 #ifdef DEBUG 1692 #ifdef DEBUG
1640 if (info->script_is_native()) { 1693 if (info->script_is_native()) {
1641 // To avoid polluting the global object in native scripts 1694 // To avoid polluting the global object in native scripts
1642 // - Variables must not be allocated to the global scope. 1695 // - Variables must not be allocated to the global scope.
1643 CHECK_NOT_NULL(outer_scope()); 1696 CHECK_NOT_NULL(outer_scope());
1644 // - Variables must be bound locally or unallocated. 1697 // - Variables must be bound locally or unallocated.
1645 if (var->IsGlobalObjectProperty()) { 1698 if (var->IsGlobalObjectProperty()) {
1646 // The following variable name may be minified. If so, disable 1699 // The following variable name may be minified. If so, disable
1647 // minification in js2c.py for better output. 1700 // minification in js2c.py for better output.
1648 Handle<String> name = proxy->raw_name()->string(); 1701 Handle<String> name = proxy->raw_name()->string();
1649 V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.", 1702 V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.",
1650 name->ToCString().get()); 1703 name->ToCString().get());
1651 } 1704 }
1652 VariableLocation location = var->location(); 1705 VariableLocation location = var->location();
1653 CHECK(location == VariableLocation::LOCAL || 1706 CHECK(location == VariableLocation::LOCAL ||
1654 location == VariableLocation::CONTEXT || 1707 location == VariableLocation::CONTEXT ||
1655 location == VariableLocation::PARAMETER || 1708 location == VariableLocation::PARAMETER ||
1656 location == VariableLocation::UNALLOCATED); 1709 location == VariableLocation::UNALLOCATED);
1657 } 1710 }
1658 #endif 1711 #endif
1659 1712
1660 DCHECK_NOT_NULL(var); 1713 DCHECK_NOT_NULL(var);
1661 if (proxy->is_assigned()) var->set_maybe_assigned(); 1714 if (proxy->is_assigned()) var->set_maybe_assigned();
1715 if (AccessNeedsHoleCheck(var, proxy, this)) proxy->set_needs_hole_check();
1662 proxy->BindTo(var); 1716 proxy->BindTo(var);
1663 } 1717 }
1664 1718
1665 void Scope::ResolveVariablesRecursively(ParseInfo* info) { 1719 void Scope::ResolveVariablesRecursively(ParseInfo* info) {
1666 DCHECK(info->script_scope()->is_script_scope()); 1720 DCHECK(info->script_scope()->is_script_scope());
1667 1721
1668 // Resolve unresolved variables for this scope. 1722 // Resolve unresolved variables for this scope.
1669 for (VariableProxy* proxy = unresolved_; proxy != nullptr; 1723 for (VariableProxy* proxy = unresolved_; proxy != nullptr;
1670 proxy = proxy->next_unresolved()) { 1724 proxy = proxy->next_unresolved()) {
1671 ResolveVariable(info, proxy); 1725 ResolveVariable(info, proxy);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 1913
1860 if (new_target_ != nullptr && !MustAllocate(new_target_)) { 1914 if (new_target_ != nullptr && !MustAllocate(new_target_)) {
1861 new_target_ = nullptr; 1915 new_target_ = nullptr;
1862 } 1916 }
1863 1917
1864 if (this_function_ != nullptr && !MustAllocate(this_function_)) { 1918 if (this_function_ != nullptr && !MustAllocate(this_function_)) {
1865 this_function_ = nullptr; 1919 this_function_ = nullptr;
1866 } 1920 }
1867 } 1921 }
1868 1922
1869 void ModuleScope::AllocateModuleVariables() { 1923 void ModuleScope::AllocateModuleExports() {
1870 for (const auto& it : module()->regular_imports()) {
1871 Variable* var = LookupLocal(it.first);
1872 // TODO(neis): Use a meaningful index.
1873 var->AllocateTo(VariableLocation::MODULE, 42);
1874 }
1875
1876 for (const auto& it : module()->regular_exports()) { 1924 for (const auto& it : module()->regular_exports()) {
1877 Variable* var = LookupLocal(it.first); 1925 Variable* var = LookupLocal(it.first);
1878 var->AllocateTo(VariableLocation::MODULE, 0); 1926 var->AllocateTo(VariableLocation::MODULE, Variable::kModuleExportIndex);
1879 } 1927 }
1880 } 1928 }
1881 1929
1882 void Scope::AllocateVariablesRecursively() { 1930 void Scope::AllocateVariablesRecursively() {
1883 DCHECK(!already_resolved_); 1931 DCHECK(!already_resolved_);
1884 DCHECK_EQ(0, num_stack_slots_); 1932 DCHECK_EQ(0, num_stack_slots_);
1885 // Don't allocate variables of preparsed scopes. 1933 // Don't allocate variables of preparsed scopes.
1886 if (is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()) { 1934 if (is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()) {
1887 return; 1935 return;
1888 } 1936 }
1889 1937
1890 // Allocate variables for inner scopes. 1938 // Allocate variables for inner scopes.
1891 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1939 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1892 scope->AllocateVariablesRecursively(); 1940 scope->AllocateVariablesRecursively();
1893 } 1941 }
1894 1942
1895 DCHECK(!already_resolved_); 1943 DCHECK(!already_resolved_);
1896 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_); 1944 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
1897 1945
1898 // Allocate variables for this scope. 1946 // Allocate variables for this scope.
1899 // Parameters must be allocated first, if any. 1947 // Parameters must be allocated first, if any.
1900 if (is_declaration_scope()) { 1948 if (is_declaration_scope()) {
1901 if (is_module_scope()) { 1949 if (is_module_scope()) {
1902 AsModuleScope()->AllocateModuleVariables(); 1950 AsModuleScope()->AllocateModuleExports();
1903 } else if (is_function_scope()) { 1951 } else if (is_function_scope()) {
1904 AsDeclarationScope()->AllocateParameterLocals(); 1952 AsDeclarationScope()->AllocateParameterLocals();
1905 } 1953 }
1906 AsDeclarationScope()->AllocateReceiver(); 1954 AsDeclarationScope()->AllocateReceiver();
1907 } 1955 }
1908 AllocateNonParameterLocalsAndDeclaredGlobals(); 1956 AllocateNonParameterLocalsAndDeclaredGlobals();
1909 1957
1910 // Force allocation of a context for this scope if necessary. For a 'with' 1958 // Force allocation of a context for this scope if necessary. For a 'with'
1911 // scope and for a function scope that makes an 'eval' call we need a context, 1959 // scope and for a function scope that makes an 'eval' call we need a context,
1912 // even if no local variables were statically allocated in the scope. 1960 // even if no local variables were statically allocated in the scope.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 Variable* function = 2020 Variable* function =
1973 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 2021 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
1974 bool is_function_var_in_context = 2022 bool is_function_var_in_context =
1975 function != nullptr && function->IsContextSlot(); 2023 function != nullptr && function->IsContextSlot();
1976 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 2024 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1977 (is_function_var_in_context ? 1 : 0); 2025 (is_function_var_in_context ? 1 : 0);
1978 } 2026 }
1979 2027
1980 } // namespace internal 2028 } // namespace internal
1981 } // namespace v8 2029 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | src/ast/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698