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

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1634153002: [Interpreter] Adds support for const/let variables to interpreter. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased the patch. Created 4 years, 10 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/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 decl->fun(), info()->script(), info()); 714 decl->fun(), info()->script(), info());
715 // Check for stack-overflow exception. 715 // Check for stack-overflow exception.
716 if (function.is_null()) return SetStackOverflow(); 716 if (function.is_null()) return SetStackOverflow();
717 globals()->push_back(variable->name()); 717 globals()->push_back(variable->name());
718 globals()->push_back(function); 718 globals()->push_back(function);
719 break; 719 break;
720 } 720 }
721 case VariableLocation::PARAMETER: 721 case VariableLocation::PARAMETER:
722 case VariableLocation::LOCAL: { 722 case VariableLocation::LOCAL: {
723 VisitForAccumulatorValue(decl->fun()); 723 VisitForAccumulatorValue(decl->fun());
724 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 724 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
725 variable->mode() == CONST);
726 VisitVariableAssignment(variable, Token::INIT,
727 FeedbackVectorSlot::Invalid());
725 break; 728 break;
726 } 729 }
727 case VariableLocation::CONTEXT: { 730 case VariableLocation::CONTEXT: {
728 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); 731 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
729 VisitForAccumulatorValue(decl->fun()); 732 VisitForAccumulatorValue(decl->fun());
730 builder()->StoreContextSlot(execution_context()->reg(), 733 builder()->StoreContextSlot(execution_context()->reg(),
731 variable->index()); 734 variable->index());
732 break; 735 break;
733 } 736 }
734 case VariableLocation::LOOKUP: { 737 case VariableLocation::LOOKUP: {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 FeedbackVectorSlot slot) { 1003 FeedbackVectorSlot slot) {
1001 DCHECK(expr->IsValidReferenceExpression()); 1004 DCHECK(expr->IsValidReferenceExpression());
1002 1005
1003 // Evaluate assignment starting with the value to be stored in the 1006 // Evaluate assignment starting with the value to be stored in the
1004 // accumulator. 1007 // accumulator.
1005 Property* property = expr->AsProperty(); 1008 Property* property = expr->AsProperty();
1006 LhsKind assign_type = Property::GetAssignType(property); 1009 LhsKind assign_type = Property::GetAssignType(property);
1007 switch (assign_type) { 1010 switch (assign_type) {
1008 case VARIABLE: { 1011 case VARIABLE: {
1009 Variable* variable = expr->AsVariableProxy()->var(); 1012 Variable* variable = expr->AsVariableProxy()->var();
1010 VisitVariableAssignment(variable, slot); 1013 VisitVariableAssignment(variable, Token::ASSIGN, slot);
1011 break; 1014 break;
1012 } 1015 }
1013 case NAMED_PROPERTY: { 1016 case NAMED_PROPERTY: {
1014 RegisterAllocationScope register_scope(this); 1017 RegisterAllocationScope register_scope(this);
1015 Register value = register_allocator()->NewRegister(); 1018 Register value = register_allocator()->NewRegister();
1016 builder()->StoreAccumulatorInRegister(value); 1019 builder()->StoreAccumulatorInRegister(value);
1017 Register object = VisitForRegisterValue(property->obj()); 1020 Register object = VisitForRegisterValue(property->obj());
1018 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); 1021 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1019 builder()->LoadAccumulatorWithRegister(value); 1022 builder()->LoadAccumulatorWithRegister(value);
1020 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1023 builder()->StoreNamedProperty(object, name, feedback_index(slot),
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 .StoreAccumulatorInRegister(prototype); 1256 .StoreAccumulatorInRegister(prototype);
1254 1257
1255 VisitClassLiteralProperties(expr, literal, prototype); 1258 VisitClassLiteralProperties(expr, literal, prototype);
1256 builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2); 1259 builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2);
1257 // Assign to class variable. 1260 // Assign to class variable.
1258 if (expr->class_variable_proxy() != nullptr) { 1261 if (expr->class_variable_proxy() != nullptr) {
1259 Variable* var = expr->class_variable_proxy()->var(); 1262 Variable* var = expr->class_variable_proxy()->var();
1260 FeedbackVectorSlot slot = expr->NeedsProxySlot() 1263 FeedbackVectorSlot slot = expr->NeedsProxySlot()
1261 ? expr->ProxySlot() 1264 ? expr->ProxySlot()
1262 : FeedbackVectorSlot::Invalid(); 1265 : FeedbackVectorSlot::Invalid();
1263 VisitVariableAssignment(var, slot); 1266 VisitVariableAssignment(var, Token::INIT, slot);
1264 } 1267 }
1265 execution_result()->SetResultInAccumulator(); 1268 execution_result()->SetResultInAccumulator();
1266 } 1269 }
1267 1270
1268 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( 1271 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
1269 ClassLiteral* expr) { 1272 ClassLiteral* expr) {
1270 AccumulatorResultScope result_scope(this); 1273 AccumulatorResultScope result_scope(this);
1271 register_allocator()->PrepareForConsecutiveAllocations(4); 1274 register_allocator()->PrepareForConsecutiveAllocations(4);
1272 Register extends = register_allocator()->NextConsecutiveRegister(); 1275 Register extends = register_allocator()->NextConsecutiveRegister();
1273 Register constructor = register_allocator()->NextConsecutiveRegister(); 1276 Register constructor = register_allocator()->NextConsecutiveRegister();
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 builder()->LoadAccumulatorWithRegister(literal); 1670 builder()->LoadAccumulatorWithRegister(literal);
1668 } 1671 }
1669 execution_result()->SetResultInAccumulator(); 1672 execution_result()->SetResultInAccumulator();
1670 } 1673 }
1671 1674
1672 1675
1673 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1676 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1674 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1677 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1675 } 1678 }
1676 1679
1680 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1681 Handle<String> name) {
1682 if (mode == CONST_LEGACY) {
1683 BytecodeLabel end_label;
1684 builder()->JumpIfNotHole(&end_label);
1685 builder()->LoadUndefined();
1686 builder()->Bind(&end_label);
1687 } else if (mode == LET || mode == CONST) {
1688 BuildThrowIfHole(name);
1689 }
1690 }
1677 1691
1678 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1692 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1679 FeedbackVectorSlot slot, 1693 FeedbackVectorSlot slot,
1680 TypeofMode typeof_mode) { 1694 TypeofMode typeof_mode) {
1695 VariableMode mode = variable->mode();
1681 switch (variable->location()) { 1696 switch (variable->location()) {
1682 case VariableLocation::LOCAL: { 1697 case VariableLocation::LOCAL: {
1683 Register source(Register(variable->index())); 1698 Register source(Register(variable->index()));
1684 builder()->LoadAccumulatorWithRegister(source); 1699 builder()->LoadAccumulatorWithRegister(source);
1700 BuildHoleCheckForVariableLoad(mode, variable->name());
1685 execution_result()->SetResultInAccumulator(); 1701 execution_result()->SetResultInAccumulator();
1686 break; 1702 break;
1687 } 1703 }
1688 case VariableLocation::PARAMETER: { 1704 case VariableLocation::PARAMETER: {
1689 // The parameter indices are shifted by 1 (receiver is variable 1705 // The parameter indices are shifted by 1 (receiver is variable
1690 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1706 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1691 Register source = builder()->Parameter(variable->index() + 1); 1707 Register source = builder()->Parameter(variable->index() + 1);
1692 builder()->LoadAccumulatorWithRegister(source); 1708 builder()->LoadAccumulatorWithRegister(source);
1709 BuildHoleCheckForVariableLoad(mode, variable->name());
1693 execution_result()->SetResultInAccumulator(); 1710 execution_result()->SetResultInAccumulator();
1694 break; 1711 break;
1695 } 1712 }
1696 case VariableLocation::GLOBAL: 1713 case VariableLocation::GLOBAL:
1697 case VariableLocation::UNALLOCATED: { 1714 case VariableLocation::UNALLOCATED: {
1698 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1715 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1699 language_mode(), typeof_mode); 1716 language_mode(), typeof_mode);
1700 execution_result()->SetResultInAccumulator(); 1717 execution_result()->SetResultInAccumulator();
1701 break; 1718 break;
1702 } 1719 }
(...skipping 12 matching lines...) Expand all
1715 // when this changes. 1732 // when this changes.
1716 builder() 1733 builder()
1717 ->LoadAccumulatorWithRegister(execution_context()->reg()) 1734 ->LoadAccumulatorWithRegister(execution_context()->reg())
1718 .StoreAccumulatorInRegister(context_reg); 1735 .StoreAccumulatorInRegister(context_reg);
1719 for (int i = 0; i < depth; ++i) { 1736 for (int i = 0; i < depth; ++i) {
1720 builder() 1737 builder()
1721 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1738 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1722 .StoreAccumulatorInRegister(context_reg); 1739 .StoreAccumulatorInRegister(context_reg);
1723 } 1740 }
1724 } 1741 }
1742
1725 builder()->LoadContextSlot(context_reg, variable->index()); 1743 builder()->LoadContextSlot(context_reg, variable->index());
1744 BuildHoleCheckForVariableLoad(mode, variable->name());
1726 execution_result()->SetResultInAccumulator(); 1745 execution_result()->SetResultInAccumulator();
1727 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
1728 // let variables.
1729 break; 1746 break;
1730 } 1747 }
1731 case VariableLocation::LOOKUP: { 1748 case VariableLocation::LOOKUP: {
1732 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1749 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1733 execution_result()->SetResultInAccumulator(); 1750 execution_result()->SetResultInAccumulator();
1734 break; 1751 break;
1735 } 1752 }
1736 } 1753 }
1737 } 1754 }
1738 1755
1739 1756
1740 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( 1757 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1741 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1758 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1742 AccumulatorResultScope accumulator_result(this); 1759 AccumulatorResultScope accumulator_result(this);
1743 VisitVariableLoad(variable, slot, typeof_mode); 1760 VisitVariableLoad(variable, slot, typeof_mode);
1744 } 1761 }
1745 1762
1746 1763
1747 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( 1764 Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1748 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1765 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1749 RegisterResultScope register_scope(this); 1766 RegisterResultScope register_scope(this);
1750 VisitVariableLoad(variable, slot, typeof_mode); 1767 VisitVariableLoad(variable, slot, typeof_mode);
1751 return register_scope.ResultRegister(); 1768 return register_scope.ResultRegister();
1752 } 1769 }
1753 1770
1771 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1772 Register name_reg = register_allocator()->NewRegister();
1773 BytecodeLabel end_label;
1774 // TODO(mythria): This will be replaced by a new bytecode that throws an
1775 // error if the value is the hole.
1776 builder()
1777 ->JumpIfNotHole(&end_label)
1778 .LoadLiteral(name)
1779 .StoreAccumulatorInRegister(name_reg)
1780 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1781 .Bind(&end_label);
1782 }
1783
1784 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1785 Register name_reg = register_allocator()->NewRegister();
1786 BytecodeLabel end_label;
1787 // TODO(mythria): This will be replaced by a new bytecode that throws an
1788 // error if the value is not the hole.
1789 builder()
1790 ->JumpIfHole(&end_label)
1791 .LoadLiteral(name)
1792 .StoreAccumulatorInRegister(name_reg)
1793 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1794 .Bind(&end_label);
1795 }
1796
1797 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1798 Register name_reg = register_allocator()->NewRegister();
1799 BytecodeLabel else_label;
1800 // TODO(mythria): This will be replaced by a new bytecode that throws an
1801 // appropriate error depending on the whether the value is a hole or not.
1802 builder()
1803 ->JumpIfNotHole(&else_label)
1804 .LoadLiteral(name)
1805 .StoreAccumulatorInRegister(name_reg)
1806 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1807 .Bind(&else_label)
1808 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1809 }
1810
1811 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1812 Token::Value op) {
1813 VariableMode mode = variable->mode();
1814 DCHECK(mode != CONST_LEGACY);
1815 if (mode == CONST && op != Token::INIT) {
1816 // Non-intializing assignments to constant is not allowed.
1817 BuildThrowReassignConstant(variable->name());
1818 } else if (mode == LET && op != Token::INIT) {
1819 // Perform an initialization check for let declared variables.
1820 // E.g. let x = (x = 20); is not allowed.
1821 BuildThrowIfHole(variable->name());
1822 } else {
1823 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1824 // Perform an initialization check for 'this'. 'this' variable is the
1825 // only variable able to trigger bind operations outside the TDZ
1826 // via 'super' calls.
1827 BuildThrowIfNotHole(variable->name());
1828 }
1829 }
1754 1830
1755 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1831 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1832 Token::Value op,
1756 FeedbackVectorSlot slot) { 1833 FeedbackVectorSlot slot) {
1834 VariableMode mode = variable->mode();
1835 RegisterAllocationScope assignment_register_scope(this);
1836 BytecodeLabel end_label;
1837 bool hole_check_required =
1838 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
1839 (mode == CONST && op != Token::INIT) ||
1840 (mode == CONST && op == Token::INIT && variable->is_this());
1757 switch (variable->location()) { 1841 switch (variable->location()) {
1842 case VariableLocation::PARAMETER:
1758 case VariableLocation::LOCAL: { 1843 case VariableLocation::LOCAL: {
1759 // TODO(rmcilroy): support const mode initialization. 1844 Register destination;
1760 Register destination(variable->index()); 1845 if (VariableLocation::PARAMETER == variable->location()) {
1846 destination = Register(builder()->Parameter(variable->index() + 1));
1847 } else {
1848 destination = Register(variable->index());
1849 }
1850
1851 if (hole_check_required) {
1852 // Load destination to check for hole.
1853 Register value_temp = register_allocator()->NewRegister();
1854 builder()
1855 ->StoreAccumulatorInRegister(value_temp)
1856 .LoadAccumulatorWithRegister(destination);
1857
1858 if (mode == CONST_LEGACY && op == Token::INIT) {
1859 // Perform an intialization check for legacy constants.
1860 builder()
1861 ->JumpIfNotHole(&end_label)
1862 .MoveRegister(value_temp, destination)
1863 .Bind(&end_label)
1864 .LoadAccumulatorWithRegister(value_temp);
1865 // Break here because the value should not be stored unconditionally.
1866 break;
1867 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1868 DCHECK(!is_strict(language_mode()));
1869 // Ensure accumulator is in the correct state.
1870 builder()->LoadAccumulatorWithRegister(value_temp);
1871 // Break here, non-initializing assignments to legacy constants are
1872 // ignored.
1873 break;
1874 } else {
1875 BuildHoleCheckForVariableAssignment(variable, op);
1876 builder()->LoadAccumulatorWithRegister(value_temp);
1877 }
1878 }
1879
1761 builder()->StoreAccumulatorInRegister(destination); 1880 builder()->StoreAccumulatorInRegister(destination);
1762 break; 1881 break;
1763 } 1882 }
1764 case VariableLocation::PARAMETER: {
1765 // The parameter indices are shifted by 1 (receiver is variable
1766 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1767 Register destination(builder()->Parameter(variable->index() + 1));
1768 builder()->StoreAccumulatorInRegister(destination);
1769 break;
1770 }
1771 case VariableLocation::GLOBAL: 1883 case VariableLocation::GLOBAL:
1772 case VariableLocation::UNALLOCATED: { 1884 case VariableLocation::UNALLOCATED: {
1773 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1885 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1774 language_mode()); 1886 language_mode());
1775 break; 1887 break;
1776 } 1888 }
1777 case VariableLocation::CONTEXT: { 1889 case VariableLocation::CONTEXT: {
1778 // TODO(rmcilroy): support const mode initialization.
1779 int depth = execution_context()->ContextChainDepth(variable->scope()); 1890 int depth = execution_context()->ContextChainDepth(variable->scope());
1780 ContextScope* context = execution_context()->Previous(depth); 1891 ContextScope* context = execution_context()->Previous(depth);
1781 Register context_reg; 1892 Register context_reg;
1893
1782 if (context) { 1894 if (context) {
1783 context_reg = context->reg(); 1895 context_reg = context->reg();
1784 } else { 1896 } else {
1785 Register value_temp = register_allocator()->NewRegister(); 1897 Register value_temp = register_allocator()->NewRegister();
1786 context_reg = register_allocator()->NewRegister(); 1898 context_reg = register_allocator()->NewRegister();
1787 // Walk the context chain to find the context at the given depth. 1899 // Walk the context chain to find the context at the given depth.
1788 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1900 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1789 // a generic mechanism for performing jumps in interpreter.cc. 1901 // a generic mechanism for performing jumps in interpreter.cc.
1790 // TODO(mythria): Also update bytecode graph builder with correct depth 1902 // TODO(mythria): Also update bytecode graph builder with correct depth
1791 // when this changes. 1903 // when this changes.
1792 builder() 1904 builder()
1793 ->StoreAccumulatorInRegister(value_temp) 1905 ->StoreAccumulatorInRegister(value_temp)
1794 .LoadAccumulatorWithRegister(execution_context()->reg()) 1906 .LoadAccumulatorWithRegister(execution_context()->reg())
1795 .StoreAccumulatorInRegister(context_reg); 1907 .StoreAccumulatorInRegister(context_reg);
1796 for (int i = 0; i < depth; ++i) { 1908 for (int i = 0; i < depth; ++i) {
1797 builder() 1909 builder()
1798 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1910 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1799 .StoreAccumulatorInRegister(context_reg); 1911 .StoreAccumulatorInRegister(context_reg);
1800 } 1912 }
1801 builder()->LoadAccumulatorWithRegister(value_temp); 1913 builder()->LoadAccumulatorWithRegister(value_temp);
1802 } 1914 }
1915
1916 if (hole_check_required) {
1917 // Load destination to check for hole.
1918 Register value_temp = register_allocator()->NewRegister();
1919 builder()
1920 ->StoreAccumulatorInRegister(value_temp)
1921 .LoadContextSlot(context_reg, variable->index());
1922
1923 if (mode == CONST_LEGACY && op == Token::INIT) {
1924 // Perform an intialization check for legacy constants.
1925 builder()
1926 ->JumpIfNotHole(&end_label)
1927 .LoadAccumulatorWithRegister(value_temp)
1928 .StoreContextSlot(context_reg, variable->index())
1929 .Bind(&end_label);
1930 builder()->LoadAccumulatorWithRegister(value_temp);
1931 // Break here because the value should not be stored unconditionally.
1932 // The above code performs the store conditionally.
1933 break;
1934 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1935 DCHECK(!is_strict(language_mode()));
1936 // Ensure accumulator is in the correct state.
1937 builder()->LoadAccumulatorWithRegister(value_temp);
1938 // Break here, non-initializing assignments to legacy constants are
1939 // ignored.
1940 break;
1941 } else {
1942 BuildHoleCheckForVariableAssignment(variable, op);
1943 builder()->LoadAccumulatorWithRegister(value_temp);
1944 }
1945 }
1946
1803 builder()->StoreContextSlot(context_reg, variable->index()); 1947 builder()->StoreContextSlot(context_reg, variable->index());
1804 break; 1948 break;
1805 } 1949 }
1806 case VariableLocation::LOOKUP: { 1950 case VariableLocation::LOOKUP: {
1807 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for 1951 if (mode == CONST_LEGACY && op == Token::INIT) {
1808 // initializations of const declarations. 1952 register_allocator()->PrepareForConsecutiveAllocations(3);
1809 builder()->StoreLookupSlot(variable->name(), language_mode()); 1953 Register value = register_allocator()->NextConsecutiveRegister();
1954 Register context = register_allocator()->NextConsecutiveRegister();
1955 Register name = register_allocator()->NextConsecutiveRegister();
1956
1957 // InitializeLegacyConstLookupSlot runtime call returns the 'value'
1958 // passed to it. So, accumulator will have its original contents when
1959 // runtime call returns.
1960 builder()
1961 ->StoreAccumulatorInRegister(value)
1962 .MoveRegister(execution_context()->reg(), context)
1963 .LoadLiteral(variable->name())
1964 .StoreAccumulatorInRegister(name)
1965 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
1966 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1967 // Non-intializing assignments to legacy constants are ignored.
1968 DCHECK(!is_strict(language_mode()));
1969 } else {
1970 builder()->StoreLookupSlot(variable->name(), language_mode());
1971 }
1810 break; 1972 break;
1811 } 1973 }
1812 } 1974 }
1813 } 1975 }
1814 1976
1815 1977
1816 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1978 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
1817 DCHECK(expr->target()->IsValidReferenceExpression()); 1979 DCHECK(expr->target()->IsValidReferenceExpression());
1818 Register object, key; 1980 Register object, key;
1819 Handle<String> name; 1981 Handle<String> name;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 VisitForAccumulatorValue(expr->value()); 2054 VisitForAccumulatorValue(expr->value());
1893 } 2055 }
1894 2056
1895 // Store the value. 2057 // Store the value.
1896 FeedbackVectorSlot slot = expr->AssignmentSlot(); 2058 FeedbackVectorSlot slot = expr->AssignmentSlot();
1897 switch (assign_type) { 2059 switch (assign_type) {
1898 case VARIABLE: { 2060 case VARIABLE: {
1899 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. 2061 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
1900 // Is the value in the accumulator safe? Yes, but scary. 2062 // Is the value in the accumulator safe? Yes, but scary.
1901 Variable* variable = expr->target()->AsVariableProxy()->var(); 2063 Variable* variable = expr->target()->AsVariableProxy()->var();
1902 VisitVariableAssignment(variable, slot); 2064 VisitVariableAssignment(variable, expr->op(), slot);
1903 break; 2065 break;
1904 } 2066 }
1905 case NAMED_PROPERTY: 2067 case NAMED_PROPERTY:
1906 builder()->StoreNamedProperty(object, name, feedback_index(slot), 2068 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1907 language_mode()); 2069 language_mode());
1908 break; 2070 break;
1909 case KEYED_PROPERTY: 2071 case KEYED_PROPERTY:
1910 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 2072 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1911 language_mode()); 2073 language_mode());
1912 break; 2074 break;
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
2317 } 2479 }
2318 2480
2319 // Perform +1/-1 operation. 2481 // Perform +1/-1 operation.
2320 builder()->CountOperation(expr->binary_op(), language_mode_strength()); 2482 builder()->CountOperation(expr->binary_op(), language_mode_strength());
2321 2483
2322 // Store the value. 2484 // Store the value.
2323 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 2485 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2324 switch (assign_type) { 2486 switch (assign_type) {
2325 case VARIABLE: { 2487 case VARIABLE: {
2326 Variable* variable = expr->expression()->AsVariableProxy()->var(); 2488 Variable* variable = expr->expression()->AsVariableProxy()->var();
2327 VisitVariableAssignment(variable, feedback_slot); 2489 VisitVariableAssignment(variable, expr->op(), feedback_slot);
2328 break; 2490 break;
2329 } 2491 }
2330 case NAMED_PROPERTY: { 2492 case NAMED_PROPERTY: {
2331 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), 2493 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
2332 language_mode()); 2494 language_mode());
2333 break; 2495 break;
2334 } 2496 }
2335 case KEYED_PROPERTY: { 2497 case KEYED_PROPERTY: {
2336 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), 2498 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
2337 language_mode()); 2499 language_mode());
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
2594 2756
2595 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 2757 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
2596 2758
2597 // Allocate and initialize a new arguments object and assign to the 2759 // Allocate and initialize a new arguments object and assign to the
2598 // {arguments} variable. 2760 // {arguments} variable.
2599 CreateArgumentsType type = 2761 CreateArgumentsType type =
2600 is_strict(language_mode()) || !info()->has_simple_parameters() 2762 is_strict(language_mode()) || !info()->has_simple_parameters()
2601 ? CreateArgumentsType::kUnmappedArguments 2763 ? CreateArgumentsType::kUnmappedArguments
2602 : CreateArgumentsType::kMappedArguments; 2764 : CreateArgumentsType::kMappedArguments;
2603 builder()->CreateArguments(type); 2765 builder()->CreateArguments(type);
2604 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2766 VisitVariableAssignment(variable, Token::ASSIGN,
2767 FeedbackVectorSlot::Invalid());
2605 } 2768 }
2606 2769
2607 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { 2770 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
2608 if (rest == nullptr) return; 2771 if (rest == nullptr) return;
2609 2772
2610 // Allocate and initialize a new rest parameter and assign to the {rest} 2773 // Allocate and initialize a new rest parameter and assign to the {rest}
2611 // variable. 2774 // variable.
2612 builder()->CreateArguments(CreateArgumentsType::kRestParameter); 2775 builder()->CreateArguments(CreateArgumentsType::kRestParameter);
2613 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); 2776 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
2614 VisitVariableAssignment(rest, FeedbackVectorSlot::Invalid()); 2777 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
2615 } 2778 }
2616 2779
2617 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 2780 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
2618 if (variable == nullptr) return; 2781 if (variable == nullptr) return;
2619 2782
2620 // TODO(rmcilroy): Remove once we have tests which exercise this code path. 2783 // TODO(rmcilroy): Remove once we have tests which exercise this code path.
2621 UNIMPLEMENTED(); 2784 UNIMPLEMENTED();
2622 2785
2623 // Store the closure we were called with in the given variable. 2786 // Store the closure we were called with in the given variable.
2624 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2787 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2625 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2788 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2626 } 2789 }
2627 2790
2628 2791
2629 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 2792 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
2630 if (variable == nullptr) return; 2793 if (variable == nullptr) return;
2631 2794
2632 // Store the new target we were called with in the given variable. 2795 // Store the new target we were called with in the given variable.
2633 builder()->LoadAccumulatorWithRegister(Register::new_target()); 2796 builder()->LoadAccumulatorWithRegister(Register::new_target());
2634 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2797 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2635 } 2798 }
2636 2799
2637 2800
2638 void BytecodeGenerator::VisitFunctionClosureForContext() { 2801 void BytecodeGenerator::VisitFunctionClosureForContext() {
2639 AccumulatorResultScope accumulator_execution_result(this); 2802 AccumulatorResultScope accumulator_execution_result(this);
2640 Scope* closure_scope = execution_context()->scope()->ClosureScope(); 2803 Scope* closure_scope = execution_context()->scope()->ClosureScope();
2641 if (closure_scope->is_script_scope() || 2804 if (closure_scope->is_script_scope() ||
2642 closure_scope->is_module_scope()) { 2805 closure_scope->is_module_scope()) {
2643 // Contexts nested in the native context have a canonical empty function as 2806 // Contexts nested in the native context have a canonical empty function as
2644 // their closure, not the anonymous closure containing the global code. 2807 // their closure, not the anonymous closure containing the global code.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2709 } 2872 }
2710 2873
2711 2874
2712 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2875 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2713 return info()->feedback_vector()->GetIndex(slot); 2876 return info()->feedback_vector()->GetIndex(slot);
2714 } 2877 }
2715 2878
2716 } // namespace interpreter 2879 } // namespace interpreter
2717 } // namespace internal 2880 } // namespace internal
2718 } // namespace v8 2881 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698