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 |