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/interpreter.h" | 5 #include "src/interpreter/interpreter.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
(...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 void Interpreter::DoToObject(InterpreterAssembler* assembler) { | 1560 void Interpreter::DoToObject(InterpreterAssembler* assembler) { |
1561 Node* result = BuildUnaryOp(CodeFactory::ToObject(isolate_), assembler); | 1561 Node* result = BuildUnaryOp(CodeFactory::ToObject(isolate_), assembler); |
1562 __ StoreRegister(result, __ BytecodeOperandReg(0)); | 1562 __ StoreRegister(result, __ BytecodeOperandReg(0)); |
1563 __ Dispatch(); | 1563 __ Dispatch(); |
1564 } | 1564 } |
1565 | 1565 |
1566 // Inc | 1566 // Inc |
1567 // | 1567 // |
1568 // Increments value in the accumulator by one. | 1568 // Increments value in the accumulator by one. |
1569 void Interpreter::DoInc(InterpreterAssembler* assembler) { | 1569 void Interpreter::DoInc(InterpreterAssembler* assembler) { |
1570 DoUnaryOpWithFeedback<IncStub>(assembler); | 1570 typedef CodeStubAssembler::Label Label; |
| 1571 typedef compiler::Node Node; |
| 1572 typedef CodeStubAssembler::Variable Variable; |
| 1573 |
| 1574 Node* value = __ GetAccumulator(); |
| 1575 Node* context = __ GetContext(); |
| 1576 Node* slot_index = __ BytecodeOperandIdx(0); |
| 1577 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1578 |
| 1579 // Shared entry for floating point increment. |
| 1580 Label do_finc(assembler), end(assembler); |
| 1581 Variable var_finc_value(assembler, MachineRepresentation::kFloat64); |
| 1582 |
| 1583 // We might need to try again due to ToNumber conversion. |
| 1584 Variable value_var(assembler, MachineRepresentation::kTagged); |
| 1585 Variable result_var(assembler, MachineRepresentation::kTagged); |
| 1586 Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1587 Variable* loop_vars[] = {&value_var, &var_type_feedback}; |
| 1588 Label start(assembler, 2, loop_vars); |
| 1589 value_var.Bind(value); |
| 1590 var_type_feedback.Bind( |
| 1591 assembler->Int32Constant(BinaryOperationFeedback::kNone)); |
| 1592 assembler->Goto(&start); |
| 1593 assembler->Bind(&start); |
| 1594 { |
| 1595 value = value_var.value(); |
| 1596 |
| 1597 Label if_issmi(assembler), if_isnotsmi(assembler); |
| 1598 assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); |
| 1599 |
| 1600 assembler->Bind(&if_issmi); |
| 1601 { |
| 1602 // Try fast Smi addition first. |
| 1603 Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
| 1604 Node* pair = assembler->IntPtrAddWithOverflow( |
| 1605 assembler->BitcastTaggedToWord(value), |
| 1606 assembler->BitcastTaggedToWord(one)); |
| 1607 Node* overflow = assembler->Projection(1, pair); |
| 1608 |
| 1609 // Check if the Smi addition overflowed. |
| 1610 Label if_overflow(assembler), if_notoverflow(assembler); |
| 1611 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 1612 |
| 1613 assembler->Bind(&if_notoverflow); |
| 1614 var_type_feedback.Bind(assembler->Word32Or( |
| 1615 var_type_feedback.value(), |
| 1616 assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); |
| 1617 result_var.Bind( |
| 1618 assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); |
| 1619 assembler->Goto(&end); |
| 1620 |
| 1621 assembler->Bind(&if_overflow); |
| 1622 { |
| 1623 var_finc_value.Bind(assembler->SmiToFloat64(value)); |
| 1624 assembler->Goto(&do_finc); |
| 1625 } |
| 1626 } |
| 1627 |
| 1628 assembler->Bind(&if_isnotsmi); |
| 1629 { |
| 1630 // Check if the value is a HeapNumber. |
| 1631 Label if_valueisnumber(assembler), |
| 1632 if_valuenotnumber(assembler, Label::kDeferred); |
| 1633 Node* value_map = assembler->LoadMap(value); |
| 1634 assembler->Branch(assembler->IsHeapNumberMap(value_map), |
| 1635 &if_valueisnumber, &if_valuenotnumber); |
| 1636 |
| 1637 assembler->Bind(&if_valueisnumber); |
| 1638 { |
| 1639 // Load the HeapNumber value. |
| 1640 var_finc_value.Bind(assembler->LoadHeapNumberValue(value)); |
| 1641 assembler->Goto(&do_finc); |
| 1642 } |
| 1643 |
| 1644 assembler->Bind(&if_valuenotnumber); |
| 1645 { |
| 1646 // We do not require an Or with earlier feedback here because once we |
| 1647 // convert the value to a number, we cannot reach this path. We can |
| 1648 // only reach this path on the first pass when the feedback is kNone. |
| 1649 CSA_ASSERT(assembler, |
| 1650 assembler->Word32Equal(var_type_feedback.value(), |
| 1651 assembler->Int32Constant( |
| 1652 BinaryOperationFeedback::kNone))); |
| 1653 |
| 1654 Label if_valueisoddball(assembler), if_valuenotoddball(assembler); |
| 1655 Node* instance_type = assembler->LoadMapInstanceType(value_map); |
| 1656 Node* is_oddball = assembler->Word32Equal( |
| 1657 instance_type, assembler->Int32Constant(ODDBALL_TYPE)); |
| 1658 assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); |
| 1659 |
| 1660 assembler->Bind(&if_valueisoddball); |
| 1661 { |
| 1662 // Convert Oddball to Number and check again. |
| 1663 value_var.Bind( |
| 1664 assembler->LoadObjectField(value, Oddball::kToNumberOffset)); |
| 1665 var_type_feedback.Bind(assembler->Int32Constant( |
| 1666 BinaryOperationFeedback::kNumberOrOddball)); |
| 1667 assembler->Goto(&start); |
| 1668 } |
| 1669 |
| 1670 assembler->Bind(&if_valuenotoddball); |
| 1671 { |
| 1672 // Convert to a Number first and try again. |
| 1673 Callable callable = |
| 1674 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1675 var_type_feedback.Bind( |
| 1676 assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
| 1677 value_var.Bind(assembler->CallStub(callable, context, value)); |
| 1678 assembler->Goto(&start); |
| 1679 } |
| 1680 } |
| 1681 } |
| 1682 } |
| 1683 |
| 1684 assembler->Bind(&do_finc); |
| 1685 { |
| 1686 Node* finc_value = var_finc_value.value(); |
| 1687 Node* one = assembler->Float64Constant(1.0); |
| 1688 Node* finc_result = assembler->Float64Add(finc_value, one); |
| 1689 var_type_feedback.Bind(assembler->Word32Or( |
| 1690 var_type_feedback.value(), |
| 1691 assembler->Int32Constant(BinaryOperationFeedback::kNumber))); |
| 1692 result_var.Bind(assembler->AllocateHeapNumberWithValue(finc_result)); |
| 1693 assembler->Goto(&end); |
| 1694 } |
| 1695 |
| 1696 assembler->Bind(&end); |
| 1697 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
| 1698 slot_index); |
| 1699 |
| 1700 __ SetAccumulator(result_var.value()); |
| 1701 __ Dispatch(); |
1571 } | 1702 } |
1572 | 1703 |
1573 // Dec | 1704 // Dec |
1574 // | 1705 // |
1575 // Decrements value in the accumulator by one. | 1706 // Decrements value in the accumulator by one. |
1576 void Interpreter::DoDec(InterpreterAssembler* assembler) { | 1707 void Interpreter::DoDec(InterpreterAssembler* assembler) { |
1577 DoUnaryOpWithFeedback<DecStub>(assembler); | 1708 typedef CodeStubAssembler::Label Label; |
| 1709 typedef compiler::Node Node; |
| 1710 typedef CodeStubAssembler::Variable Variable; |
| 1711 |
| 1712 Node* value = __ GetAccumulator(); |
| 1713 Node* context = __ GetContext(); |
| 1714 Node* slot_index = __ BytecodeOperandIdx(0); |
| 1715 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1716 |
| 1717 // Shared entry for floating point decrement. |
| 1718 Label do_fdec(assembler), end(assembler); |
| 1719 Variable var_fdec_value(assembler, MachineRepresentation::kFloat64); |
| 1720 |
| 1721 // We might need to try again due to ToNumber conversion. |
| 1722 Variable value_var(assembler, MachineRepresentation::kTagged); |
| 1723 Variable result_var(assembler, MachineRepresentation::kTagged); |
| 1724 Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1725 Variable* loop_vars[] = {&value_var, &var_type_feedback}; |
| 1726 Label start(assembler, 2, loop_vars); |
| 1727 var_type_feedback.Bind( |
| 1728 assembler->Int32Constant(BinaryOperationFeedback::kNone)); |
| 1729 value_var.Bind(value); |
| 1730 assembler->Goto(&start); |
| 1731 assembler->Bind(&start); |
| 1732 { |
| 1733 value = value_var.value(); |
| 1734 |
| 1735 Label if_issmi(assembler), if_isnotsmi(assembler); |
| 1736 assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); |
| 1737 |
| 1738 assembler->Bind(&if_issmi); |
| 1739 { |
| 1740 // Try fast Smi subtraction first. |
| 1741 Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
| 1742 Node* pair = assembler->IntPtrSubWithOverflow( |
| 1743 assembler->BitcastTaggedToWord(value), |
| 1744 assembler->BitcastTaggedToWord(one)); |
| 1745 Node* overflow = assembler->Projection(1, pair); |
| 1746 |
| 1747 // Check if the Smi subtraction overflowed. |
| 1748 Label if_overflow(assembler), if_notoverflow(assembler); |
| 1749 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 1750 |
| 1751 assembler->Bind(&if_notoverflow); |
| 1752 var_type_feedback.Bind(assembler->Word32Or( |
| 1753 var_type_feedback.value(), |
| 1754 assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); |
| 1755 result_var.Bind( |
| 1756 assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); |
| 1757 assembler->Goto(&end); |
| 1758 |
| 1759 assembler->Bind(&if_overflow); |
| 1760 { |
| 1761 var_fdec_value.Bind(assembler->SmiToFloat64(value)); |
| 1762 assembler->Goto(&do_fdec); |
| 1763 } |
| 1764 } |
| 1765 |
| 1766 assembler->Bind(&if_isnotsmi); |
| 1767 { |
| 1768 // Check if the value is a HeapNumber. |
| 1769 Label if_valueisnumber(assembler), |
| 1770 if_valuenotnumber(assembler, Label::kDeferred); |
| 1771 Node* value_map = assembler->LoadMap(value); |
| 1772 assembler->Branch(assembler->IsHeapNumberMap(value_map), |
| 1773 &if_valueisnumber, &if_valuenotnumber); |
| 1774 |
| 1775 assembler->Bind(&if_valueisnumber); |
| 1776 { |
| 1777 // Load the HeapNumber value. |
| 1778 var_fdec_value.Bind(assembler->LoadHeapNumberValue(value)); |
| 1779 assembler->Goto(&do_fdec); |
| 1780 } |
| 1781 |
| 1782 assembler->Bind(&if_valuenotnumber); |
| 1783 { |
| 1784 // We do not require an Or with earlier feedback here because once we |
| 1785 // convert the value to a number, we cannot reach this path. We can |
| 1786 // only reach this path on the first pass when the feedback is kNone. |
| 1787 CSA_ASSERT(assembler, |
| 1788 assembler->Word32Equal(var_type_feedback.value(), |
| 1789 assembler->Int32Constant( |
| 1790 BinaryOperationFeedback::kNone))); |
| 1791 |
| 1792 Label if_valueisoddball(assembler), if_valuenotoddball(assembler); |
| 1793 Node* instance_type = assembler->LoadMapInstanceType(value_map); |
| 1794 Node* is_oddball = assembler->Word32Equal( |
| 1795 instance_type, assembler->Int32Constant(ODDBALL_TYPE)); |
| 1796 assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); |
| 1797 |
| 1798 assembler->Bind(&if_valueisoddball); |
| 1799 { |
| 1800 // Convert Oddball to Number and check again. |
| 1801 value_var.Bind( |
| 1802 assembler->LoadObjectField(value, Oddball::kToNumberOffset)); |
| 1803 var_type_feedback.Bind(assembler->Int32Constant( |
| 1804 BinaryOperationFeedback::kNumberOrOddball)); |
| 1805 assembler->Goto(&start); |
| 1806 } |
| 1807 |
| 1808 assembler->Bind(&if_valuenotoddball); |
| 1809 { |
| 1810 // Convert to a Number first and try again. |
| 1811 Callable callable = |
| 1812 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1813 var_type_feedback.Bind( |
| 1814 assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
| 1815 value_var.Bind(assembler->CallStub(callable, context, value)); |
| 1816 assembler->Goto(&start); |
| 1817 } |
| 1818 } |
| 1819 } |
| 1820 } |
| 1821 |
| 1822 assembler->Bind(&do_fdec); |
| 1823 { |
| 1824 Node* fdec_value = var_fdec_value.value(); |
| 1825 Node* one = assembler->Float64Constant(1.0); |
| 1826 Node* fdec_result = assembler->Float64Sub(fdec_value, one); |
| 1827 var_type_feedback.Bind(assembler->Word32Or( |
| 1828 var_type_feedback.value(), |
| 1829 assembler->Int32Constant(BinaryOperationFeedback::kNumber))); |
| 1830 result_var.Bind(assembler->AllocateHeapNumberWithValue(fdec_result)); |
| 1831 assembler->Goto(&end); |
| 1832 } |
| 1833 |
| 1834 assembler->Bind(&end); |
| 1835 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
| 1836 slot_index); |
| 1837 |
| 1838 __ SetAccumulator(result_var.value()); |
| 1839 __ Dispatch(); |
1578 } | 1840 } |
1579 | 1841 |
1580 // LogicalNot | 1842 // LogicalNot |
1581 // | 1843 // |
1582 // Perform logical-not on the accumulator, first casting the | 1844 // Perform logical-not on the accumulator, first casting the |
1583 // accumulator to a boolean value if required. | 1845 // accumulator to a boolean value if required. |
1584 // ToBooleanLogicalNot | 1846 // ToBooleanLogicalNot |
1585 void Interpreter::DoToBooleanLogicalNot(InterpreterAssembler* assembler) { | 1847 void Interpreter::DoToBooleanLogicalNot(InterpreterAssembler* assembler) { |
1586 Node* value = __ GetAccumulator(); | 1848 Node* value = __ GetAccumulator(); |
1587 Variable result(assembler, MachineRepresentation::kTagged); | 1849 Variable result(assembler, MachineRepresentation::kTagged); |
(...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2906 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 3168 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
2907 __ SmiTag(new_state)); | 3169 __ SmiTag(new_state)); |
2908 __ SetAccumulator(old_state); | 3170 __ SetAccumulator(old_state); |
2909 | 3171 |
2910 __ Dispatch(); | 3172 __ Dispatch(); |
2911 } | 3173 } |
2912 | 3174 |
2913 } // namespace interpreter | 3175 } // namespace interpreter |
2914 } // namespace internal | 3176 } // namespace internal |
2915 } // namespace v8 | 3177 } // namespace v8 |
OLD | NEW |