| 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 1680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 | 1691 |
| 1692 | 1692 |
| 1693 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1693 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1694 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1694 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1695 } | 1695 } |
| 1696 | 1696 |
| 1697 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | 1697 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, |
| 1698 Handle<String> name) { | 1698 Handle<String> name) { |
| 1699 if (mode == CONST_LEGACY) { | 1699 if (mode == CONST_LEGACY) { |
| 1700 BytecodeLabel end_label; | 1700 BytecodeLabel end_label; |
| 1701 builder()->JumpIfNotHole(&end_label); | 1701 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label); |
| 1702 builder()->LoadUndefined(); | |
| 1703 builder()->Bind(&end_label); | |
| 1704 } else if (mode == LET || mode == CONST) { | 1702 } else if (mode == LET || mode == CONST) { |
| 1705 BuildThrowIfHole(name); | 1703 BuildThrowIfHole(name); |
| 1706 } | 1704 } |
| 1707 } | 1705 } |
| 1708 | 1706 |
| 1709 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1707 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
| 1710 FeedbackVectorSlot slot, | 1708 FeedbackVectorSlot slot, |
| 1711 TypeofMode typeof_mode) { | 1709 TypeofMode typeof_mode) { |
| 1712 VariableMode mode = variable->mode(); | 1710 VariableMode mode = variable->mode(); |
| 1713 switch (variable->location()) { | 1711 switch (variable->location()) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 break; | 1761 break; |
| 1764 } | 1762 } |
| 1765 case VariableLocation::LOOKUP: { | 1763 case VariableLocation::LOOKUP: { |
| 1766 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1764 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| 1767 execution_result()->SetResultInAccumulator(); | 1765 execution_result()->SetResultInAccumulator(); |
| 1768 break; | 1766 break; |
| 1769 } | 1767 } |
| 1770 } | 1768 } |
| 1771 } | 1769 } |
| 1772 | 1770 |
| 1773 | |
| 1774 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1771 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
| 1775 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1772 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 1776 AccumulatorResultScope accumulator_result(this); | 1773 AccumulatorResultScope accumulator_result(this); |
| 1777 VisitVariableLoad(variable, slot, typeof_mode); | 1774 VisitVariableLoad(variable, slot, typeof_mode); |
| 1778 } | 1775 } |
| 1779 | 1776 |
| 1780 | |
| 1781 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( | 1777 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( |
| 1782 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1778 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 1783 RegisterResultScope register_scope(this); | 1779 RegisterResultScope register_scope(this); |
| 1784 VisitVariableLoad(variable, slot, typeof_mode); | 1780 VisitVariableLoad(variable, slot, typeof_mode); |
| 1785 return register_scope.ResultRegister(); | 1781 return register_scope.ResultRegister(); |
| 1786 } | 1782 } |
| 1787 | 1783 |
| 1784 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) { |
| 1785 RegisterAllocationScope register_scope(this); |
| 1786 Register name_reg = register_allocator()->NewRegister(); |
| 1787 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime( |
| 1788 Runtime::kThrowReferenceError, name_reg, 1); |
| 1789 } |
| 1790 |
| 1788 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { | 1791 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { |
| 1789 Register name_reg = register_allocator()->NewRegister(); | 1792 // TODO(interpreter): Can the parser reduce the number of checks |
| 1790 BytecodeLabel end_label; | 1793 // performed? Or should there be a ThrowIfHole bytecode. |
| 1791 // TODO(mythria): This will be replaced by a new bytecode that throws an | 1794 BytecodeLabel no_reference_error; |
| 1792 // error if the value is the hole. | 1795 builder()->JumpIfNotHole(&no_reference_error); |
| 1793 builder() | 1796 BuildThrowReferenceError(name); |
| 1794 ->JumpIfNotHole(&end_label) | 1797 builder()->Bind(&no_reference_error); |
| 1795 .LoadLiteral(name) | |
| 1796 .StoreAccumulatorInRegister(name_reg) | |
| 1797 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
| 1798 .Bind(&end_label); | |
| 1799 } | 1798 } |
| 1800 | 1799 |
| 1801 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) { | 1800 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) { |
| 1802 Register name_reg = register_allocator()->NewRegister(); | 1801 // TODO(interpreter): Can the parser reduce the number of checks |
| 1803 BytecodeLabel end_label; | 1802 // performed? Or should there be a ThrowIfNotHole bytecode. |
| 1804 // TODO(mythria): This will be replaced by a new bytecode that throws an | 1803 BytecodeLabel no_reference_error, reference_error; |
| 1805 // error if the value is not the hole. | |
| 1806 builder() | 1804 builder() |
| 1807 ->JumpIfHole(&end_label) | 1805 ->JumpIfNotHole(&reference_error) |
| 1808 .LoadLiteral(name) | 1806 .Jump(&no_reference_error) |
| 1809 .StoreAccumulatorInRegister(name_reg) | 1807 .Bind(&reference_error); |
| 1810 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | 1808 BuildThrowReferenceError(name); |
| 1811 .Bind(&end_label); | 1809 builder()->Bind(&no_reference_error); |
| 1812 } | 1810 } |
| 1813 | 1811 |
| 1814 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) { | 1812 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) { |
| 1815 Register name_reg = register_allocator()->NewRegister(); | |
| 1816 BytecodeLabel else_label; | |
| 1817 // TODO(mythria): This will be replaced by a new bytecode that throws an | 1813 // TODO(mythria): This will be replaced by a new bytecode that throws an |
| 1818 // appropriate error depending on the whether the value is a hole or not. | 1814 // appropriate error depending on the whether the value is a hole or not. |
| 1815 BytecodeLabel const_assign_error; |
| 1816 builder()->JumpIfNotHole(&const_assign_error); |
| 1817 BuildThrowReferenceError(name); |
| 1819 builder() | 1818 builder() |
| 1820 ->JumpIfNotHole(&else_label) | 1819 ->Bind(&const_assign_error) |
| 1821 .LoadLiteral(name) | |
| 1822 .StoreAccumulatorInRegister(name_reg) | |
| 1823 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
| 1824 .Bind(&else_label) | |
| 1825 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 1820 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 1826 } | 1821 } |
| 1827 | 1822 |
| 1828 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, | 1823 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, |
| 1829 Token::Value op) { | 1824 Token::Value op) { |
| 1830 VariableMode mode = variable->mode(); | 1825 VariableMode mode = variable->mode(); |
| 1831 DCHECK(mode != CONST_LEGACY); | 1826 DCHECK(mode != CONST_LEGACY); |
| 1832 if (mode == CONST && op != Token::INIT) { | 1827 if (mode == CONST && op != Token::INIT) { |
| 1833 // Non-intializing assignments to constant is not allowed. | 1828 // Non-intializing assignments to constant is not allowed. |
| 1834 BuildThrowReassignConstant(variable->name()); | 1829 BuildThrowReassignConstant(variable->name()); |
| 1835 } else if (mode == LET && op != Token::INIT) { | 1830 } else if (mode == LET && op != Token::INIT) { |
| 1836 // Perform an initialization check for let declared variables. | 1831 // Perform an initialization check for let declared variables. |
| 1837 // E.g. let x = (x = 20); is not allowed. | 1832 // E.g. let x = (x = 20); is not allowed. |
| 1838 BuildThrowIfHole(variable->name()); | 1833 BuildThrowIfHole(variable->name()); |
| 1839 } else { | 1834 } else { |
| 1840 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT); | 1835 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT); |
| 1841 // Perform an initialization check for 'this'. 'this' variable is the | 1836 // Perform an initialization check for 'this'. 'this' variable is the |
| 1842 // only variable able to trigger bind operations outside the TDZ | 1837 // only variable able to trigger bind operations outside the TDZ |
| 1843 // via 'super' calls. | 1838 // via 'super' calls. |
| 1844 BuildThrowIfNotHole(variable->name()); | 1839 BuildThrowIfHole(variable->name()); |
| 1845 } | 1840 } |
| 1846 } | 1841 } |
| 1847 | 1842 |
| 1848 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1843 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
| 1849 Token::Value op, | 1844 Token::Value op, |
| 1850 FeedbackVectorSlot slot) { | 1845 FeedbackVectorSlot slot) { |
| 1851 VariableMode mode = variable->mode(); | 1846 VariableMode mode = variable->mode(); |
| 1852 RegisterAllocationScope assignment_register_scope(this); | 1847 RegisterAllocationScope assignment_register_scope(this); |
| 1853 BytecodeLabel end_label; | 1848 BytecodeLabel end_label; |
| 1854 bool hole_check_required = | 1849 bool hole_check_required = |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2891 } | 2886 } |
| 2892 | 2887 |
| 2893 | 2888 |
| 2894 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2889 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2895 return info()->feedback_vector()->GetIndex(slot); | 2890 return info()->feedback_vector()->GetIndex(slot); |
| 2896 } | 2891 } |
| 2897 | 2892 |
| 2898 } // namespace interpreter | 2893 } // namespace interpreter |
| 2899 } // namespace internal | 2894 } // namespace internal |
| 2900 } // namespace v8 | 2895 } // namespace v8 |
| OLD | NEW |