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