OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 1524 __ b(cc, chunk_->GetAssemblyLabel(left_block)); |
1525 __ b(chunk_->GetAssemblyLabel(right_block)); | 1525 __ b(chunk_->GetAssemblyLabel(right_block)); |
1526 } | 1526 } |
1527 } | 1527 } |
1528 | 1528 |
1529 | 1529 |
1530 void LCodeGen::DoBranch(LBranch* instr) { | 1530 void LCodeGen::DoBranch(LBranch* instr) { |
1531 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1531 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1532 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1532 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1533 | 1533 |
1534 Representation r = instr->hydrogen()->representation(); | 1534 Representation r = instr->hydrogen()->value()->representation(); |
1535 if (r.IsInteger32()) { | 1535 if (r.IsInteger32()) { |
1536 Register reg = ToRegister(instr->InputAt(0)); | 1536 Register reg = ToRegister(instr->InputAt(0)); |
1537 __ cmp(reg, Operand(0)); | 1537 __ cmp(reg, Operand(0)); |
1538 EmitBranch(true_block, false_block, ne); | 1538 EmitBranch(true_block, false_block, ne); |
1539 } else if (r.IsDouble()) { | 1539 } else if (r.IsDouble()) { |
1540 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1540 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); |
1541 Register scratch = scratch0(); | 1541 Register scratch = scratch0(); |
1542 | 1542 |
1543 // Test the double value. Zero and NaN are false. | 1543 // Test the double value. Zero and NaN are false. |
1544 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1544 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
1545 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1545 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
1546 EmitBranch(true_block, false_block, ne); | 1546 EmitBranch(true_block, false_block, ne); |
1547 } else { | 1547 } else { |
1548 ASSERT(r.IsTagged()); | 1548 ASSERT(r.IsTagged()); |
1549 Register reg = ToRegister(instr->InputAt(0)); | 1549 Register reg = ToRegister(instr->InputAt(0)); |
1550 if (instr->hydrogen()->type().IsBoolean()) { | 1550 if (instr->hydrogen()->value()->type().IsBoolean()) { |
1551 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1551 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
1552 __ cmp(reg, ip); | 1552 __ cmp(reg, ip); |
1553 EmitBranch(true_block, false_block, eq); | 1553 EmitBranch(true_block, false_block, eq); |
1554 } else { | 1554 } else { |
1555 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1555 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1556 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1556 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1557 | 1557 |
1558 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1558 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
1559 __ cmp(reg, ip); | 1559 __ cmp(reg, ip); |
1560 __ b(eq, false_label); | 1560 __ b(eq, false_label); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 } | 1638 } |
1639 return cond; | 1639 return cond; |
1640 } | 1640 } |
1641 | 1641 |
1642 | 1642 |
1643 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1643 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
1644 __ cmp(ToRegister(left), ToRegister(right)); | 1644 __ cmp(ToRegister(left), ToRegister(right)); |
1645 } | 1645 } |
1646 | 1646 |
1647 | 1647 |
1648 void LCodeGen::DoCmpID(LCmpID* instr) { | |
1649 LOperand* left = instr->InputAt(0); | |
1650 LOperand* right = instr->InputAt(1); | |
1651 LOperand* result = instr->result(); | |
1652 Register scratch = scratch0(); | |
1653 | |
1654 Label unordered, done; | |
1655 if (instr->is_double()) { | |
1656 // Compare left and right as doubles and load the | |
1657 // resulting flags into the normal status register. | |
1658 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); | |
1659 // If a NaN is involved, i.e. the result is unordered (V set), | |
1660 // jump to unordered to return false. | |
1661 __ b(vs, &unordered); | |
1662 } else { | |
1663 EmitCmpI(left, right); | |
1664 } | |
1665 | |
1666 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | |
1667 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex); | |
1668 __ b(cc, &done); | |
1669 | |
1670 __ bind(&unordered); | |
1671 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex); | |
1672 __ bind(&done); | |
1673 } | |
1674 | |
1675 | |
1676 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1648 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1677 LOperand* left = instr->InputAt(0); | 1649 LOperand* left = instr->InputAt(0); |
1678 LOperand* right = instr->InputAt(1); | 1650 LOperand* right = instr->InputAt(1); |
1679 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1651 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1680 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1652 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1681 | 1653 |
1682 if (instr->is_double()) { | 1654 if (instr->is_double()) { |
1683 // Compare left and right as doubles and load the | 1655 // Compare left and right as doubles and load the |
1684 // resulting flags into the normal status register. | 1656 // resulting flags into the normal status register. |
1685 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); | 1657 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); |
1686 // If a NaN is involved, i.e. the result is unordered (V set), | 1658 // If a NaN is involved, i.e. the result is unordered (V set), |
1687 // jump to false block label. | 1659 // jump to false block label. |
1688 __ b(vs, chunk_->GetAssemblyLabel(false_block)); | 1660 __ b(vs, chunk_->GetAssemblyLabel(false_block)); |
1689 } else { | 1661 } else { |
1690 EmitCmpI(left, right); | 1662 EmitCmpI(left, right); |
1691 } | 1663 } |
1692 | 1664 |
1693 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1665 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1694 EmitBranch(true_block, false_block, cc); | 1666 EmitBranch(true_block, false_block, cc); |
1695 } | 1667 } |
1696 | 1668 |
1697 | 1669 |
1698 void LCodeGen::DoCmpObjectEq(LCmpObjectEq* instr) { | |
1699 Register left = ToRegister(instr->InputAt(0)); | |
1700 Register right = ToRegister(instr->InputAt(1)); | |
1701 Register result = ToRegister(instr->result()); | |
1702 | |
1703 __ cmp(left, Operand(right)); | |
1704 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | |
1705 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | |
1706 } | |
1707 | |
1708 | |
1709 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1670 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1710 Register left = ToRegister(instr->InputAt(0)); | 1671 Register left = ToRegister(instr->InputAt(0)); |
1711 Register right = ToRegister(instr->InputAt(1)); | 1672 Register right = ToRegister(instr->InputAt(1)); |
1712 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1673 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1713 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1674 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1714 | 1675 |
1715 __ cmp(left, Operand(right)); | 1676 __ cmp(left, Operand(right)); |
1716 EmitBranch(true_block, false_block, eq); | 1677 EmitBranch(true_block, false_block, eq); |
1717 } | 1678 } |
1718 | 1679 |
1719 | 1680 |
1720 void LCodeGen::DoCmpConstantEq(LCmpConstantEq* instr) { | |
1721 Register left = ToRegister(instr->InputAt(0)); | |
1722 Register result = ToRegister(instr->result()); | |
1723 | |
1724 Label done; | |
1725 __ cmp(left, Operand(instr->hydrogen()->right())); | |
1726 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | |
1727 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | |
1728 } | |
1729 | |
1730 | |
1731 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1681 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1732 Register left = ToRegister(instr->InputAt(0)); | 1682 Register left = ToRegister(instr->InputAt(0)); |
1733 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1683 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1734 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1684 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1735 | 1685 |
1736 __ cmp(left, Operand(instr->hydrogen()->right())); | 1686 __ cmp(left, Operand(instr->hydrogen()->right())); |
1737 EmitBranch(true_block, false_block, eq); | 1687 EmitBranch(true_block, false_block, eq); |
1738 } | 1688 } |
1739 | 1689 |
1740 | 1690 |
1741 void LCodeGen::DoIsNull(LIsNull* instr) { | |
1742 Register reg = ToRegister(instr->InputAt(0)); | |
1743 Register result = ToRegister(instr->result()); | |
1744 | |
1745 __ LoadRoot(ip, Heap::kNullValueRootIndex); | |
1746 __ cmp(reg, ip); | |
1747 if (instr->is_strict()) { | |
1748 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | |
1749 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | |
1750 } else { | |
1751 Label true_value, false_value, done; | |
1752 __ b(eq, &true_value); | |
1753 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | |
1754 __ cmp(ip, reg); | |
1755 __ b(eq, &true_value); | |
1756 __ JumpIfSmi(reg, &false_value); | |
1757 // Check for undetectable objects by looking in the bit field in | |
1758 // the map. The object has already been smi checked. | |
1759 Register scratch = result; | |
1760 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1761 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | |
1762 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); | |
1763 __ b(ne, &true_value); | |
1764 __ bind(&false_value); | |
1765 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1766 __ jmp(&done); | |
1767 __ bind(&true_value); | |
1768 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1769 __ bind(&done); | |
1770 } | |
1771 } | |
1772 | |
1773 | |
1774 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1691 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1775 Register scratch = scratch0(); | 1692 Register scratch = scratch0(); |
1776 Register reg = ToRegister(instr->InputAt(0)); | 1693 Register reg = ToRegister(instr->InputAt(0)); |
1777 | 1694 |
1778 // TODO(fsc): If the expression is known to be a smi, then it's | 1695 // TODO(fsc): If the expression is known to be a smi, then it's |
1779 // definitely not null. Jump to the false block. | 1696 // definitely not null. Jump to the false block. |
1780 | 1697 |
1781 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1698 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1782 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1699 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1783 | 1700 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1823 | 1740 |
1824 // Load instance type and check that it is in object type range. | 1741 // Load instance type and check that it is in object type range. |
1825 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); | 1742 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); |
1826 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1743 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1827 __ b(lt, is_not_object); | 1744 __ b(lt, is_not_object); |
1828 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1745 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1829 return le; | 1746 return le; |
1830 } | 1747 } |
1831 | 1748 |
1832 | 1749 |
1833 void LCodeGen::DoIsObject(LIsObject* instr) { | |
1834 Register reg = ToRegister(instr->InputAt(0)); | |
1835 Register result = ToRegister(instr->result()); | |
1836 Label is_false, is_true, done; | |
1837 | |
1838 Condition true_cond = EmitIsObject(reg, result, &is_false, &is_true); | |
1839 __ b(true_cond, &is_true); | |
1840 | |
1841 __ bind(&is_false); | |
1842 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1843 __ b(&done); | |
1844 | |
1845 __ bind(&is_true); | |
1846 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1847 | |
1848 __ bind(&done); | |
1849 } | |
1850 | |
1851 | |
1852 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1750 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1853 Register reg = ToRegister(instr->InputAt(0)); | 1751 Register reg = ToRegister(instr->InputAt(0)); |
1854 Register temp1 = ToRegister(instr->TempAt(0)); | 1752 Register temp1 = ToRegister(instr->TempAt(0)); |
1855 Register temp2 = scratch0(); | 1753 Register temp2 = scratch0(); |
1856 | 1754 |
1857 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1755 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1858 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1756 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1859 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1757 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1860 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1758 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1861 | 1759 |
1862 Condition true_cond = | 1760 Condition true_cond = |
1863 EmitIsObject(reg, temp1, false_label, true_label); | 1761 EmitIsObject(reg, temp1, false_label, true_label); |
1864 | 1762 |
1865 EmitBranch(true_block, false_block, true_cond); | 1763 EmitBranch(true_block, false_block, true_cond); |
1866 } | 1764 } |
1867 | 1765 |
1868 | 1766 |
1869 void LCodeGen::DoIsSmi(LIsSmi* instr) { | |
1870 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1871 Register result = ToRegister(instr->result()); | |
1872 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | |
1873 Label done; | |
1874 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1875 __ JumpIfSmi(input_reg, &done); | |
1876 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1877 __ bind(&done); | |
1878 } | |
1879 | |
1880 | |
1881 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1767 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1882 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1768 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1883 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1769 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1884 | 1770 |
1885 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 1771 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
1886 __ tst(input_reg, Operand(kSmiTagMask)); | 1772 __ tst(input_reg, Operand(kSmiTagMask)); |
1887 EmitBranch(true_block, false_block, eq); | 1773 EmitBranch(true_block, false_block, eq); |
1888 } | 1774 } |
1889 | 1775 |
1890 | 1776 |
1891 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) { | |
1892 Register input = ToRegister(instr->InputAt(0)); | |
1893 Register result = ToRegister(instr->result()); | |
1894 | |
1895 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1896 Label false_label, done; | |
1897 __ JumpIfSmi(input, &false_label); | |
1898 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | |
1899 __ ldrb(result, FieldMemOperand(result, Map::kBitFieldOffset)); | |
1900 __ tst(result, Operand(1 << Map::kIsUndetectable)); | |
1901 __ b(eq, &false_label); | |
1902 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1903 __ jmp(&done); | |
1904 __ bind(&false_label); | |
1905 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1906 __ bind(&done); | |
1907 } | |
1908 | |
1909 | |
1910 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1777 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
1911 Register input = ToRegister(instr->InputAt(0)); | 1778 Register input = ToRegister(instr->InputAt(0)); |
1912 Register temp = ToRegister(instr->TempAt(0)); | 1779 Register temp = ToRegister(instr->TempAt(0)); |
1913 | 1780 |
1914 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1781 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1915 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1782 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1916 | 1783 |
1917 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1784 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
1918 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 1785 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
1919 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 1786 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
1920 __ tst(temp, Operand(1 << Map::kIsUndetectable)); | 1787 __ tst(temp, Operand(1 << Map::kIsUndetectable)); |
1921 EmitBranch(true_block, false_block, ne); | 1788 EmitBranch(true_block, false_block, ne); |
1922 } | 1789 } |
1923 | 1790 |
1924 | 1791 |
1925 static InstanceType TestType(HHasInstanceType* instr) { | 1792 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
1926 InstanceType from = instr->from(); | 1793 InstanceType from = instr->from(); |
1927 InstanceType to = instr->to(); | 1794 InstanceType to = instr->to(); |
1928 if (from == FIRST_TYPE) return to; | 1795 if (from == FIRST_TYPE) return to; |
1929 ASSERT(from == to || to == LAST_TYPE); | 1796 ASSERT(from == to || to == LAST_TYPE); |
1930 return from; | 1797 return from; |
1931 } | 1798 } |
1932 | 1799 |
1933 | 1800 |
1934 static Condition BranchCondition(HHasInstanceType* instr) { | 1801 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
1935 InstanceType from = instr->from(); | 1802 InstanceType from = instr->from(); |
1936 InstanceType to = instr->to(); | 1803 InstanceType to = instr->to(); |
1937 if (from == to) return eq; | 1804 if (from == to) return eq; |
1938 if (to == LAST_TYPE) return hs; | 1805 if (to == LAST_TYPE) return hs; |
1939 if (from == FIRST_TYPE) return ls; | 1806 if (from == FIRST_TYPE) return ls; |
1940 UNREACHABLE(); | 1807 UNREACHABLE(); |
1941 return eq; | 1808 return eq; |
1942 } | 1809 } |
1943 | 1810 |
1944 | 1811 |
1945 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | |
1946 Register input = ToRegister(instr->InputAt(0)); | |
1947 Register result = ToRegister(instr->result()); | |
1948 | |
1949 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1950 Label done; | |
1951 __ tst(input, Operand(kSmiTagMask)); | |
1952 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq); | |
1953 __ b(eq, &done); | |
1954 __ CompareObjectType(input, result, result, TestType(instr->hydrogen())); | |
1955 Condition cond = BranchCondition(instr->hydrogen()); | |
1956 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond); | |
1957 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond)); | |
1958 __ bind(&done); | |
1959 } | |
1960 | |
1961 | |
1962 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1812 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1963 Register scratch = scratch0(); | 1813 Register scratch = scratch0(); |
1964 Register input = ToRegister(instr->InputAt(0)); | 1814 Register input = ToRegister(instr->InputAt(0)); |
1965 | 1815 |
1966 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1816 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1967 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1817 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1968 | 1818 |
1969 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1819 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1970 | 1820 |
1971 __ JumpIfSmi(input, false_label); | 1821 __ JumpIfSmi(input, false_label); |
1972 | 1822 |
1973 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); | 1823 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
1974 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 1824 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1975 } | 1825 } |
1976 | 1826 |
1977 | 1827 |
1978 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 1828 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
1979 Register input = ToRegister(instr->InputAt(0)); | 1829 Register input = ToRegister(instr->InputAt(0)); |
1980 Register result = ToRegister(instr->result()); | 1830 Register result = ToRegister(instr->result()); |
1981 | 1831 |
1982 if (FLAG_debug_code) { | 1832 if (FLAG_debug_code) { |
1983 __ AbortIfNotString(input); | 1833 __ AbortIfNotString(input); |
1984 } | 1834 } |
1985 | 1835 |
1986 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); | 1836 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); |
1987 __ IndexFromHash(result, result); | 1837 __ IndexFromHash(result, result); |
1988 } | 1838 } |
1989 | 1839 |
1990 | 1840 |
1991 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | |
1992 Register input = ToRegister(instr->InputAt(0)); | |
1993 Register result = ToRegister(instr->result()); | |
1994 Register scratch = scratch0(); | |
1995 | |
1996 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1997 __ ldr(scratch, | |
1998 FieldMemOperand(input, String::kHashFieldOffset)); | |
1999 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); | |
2000 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | |
2001 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | |
2002 } | |
2003 | |
2004 | |
2005 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1841 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2006 LHasCachedArrayIndexAndBranch* instr) { | 1842 LHasCachedArrayIndexAndBranch* instr) { |
2007 Register input = ToRegister(instr->InputAt(0)); | 1843 Register input = ToRegister(instr->InputAt(0)); |
2008 Register scratch = scratch0(); | 1844 Register scratch = scratch0(); |
2009 | 1845 |
2010 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1846 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2011 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1847 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2012 | 1848 |
2013 __ ldr(scratch, | 1849 __ ldr(scratch, |
2014 FieldMemOperand(input, String::kHashFieldOffset)); | 1850 FieldMemOperand(input, String::kHashFieldOffset)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2067 // The name in the constructor is a symbol because of the way the context is | 1903 // The name in the constructor is a symbol because of the way the context is |
2068 // booted. This routine isn't expected to work for random API-created | 1904 // booted. This routine isn't expected to work for random API-created |
2069 // classes and it doesn't have to because you can't access it with natives | 1905 // classes and it doesn't have to because you can't access it with natives |
2070 // syntax. Since both sides are symbols it is sufficient to use an identity | 1906 // syntax. Since both sides are symbols it is sufficient to use an identity |
2071 // comparison. | 1907 // comparison. |
2072 __ cmp(temp, Operand(class_name)); | 1908 __ cmp(temp, Operand(class_name)); |
2073 // End with the answer in flags. | 1909 // End with the answer in flags. |
2074 } | 1910 } |
2075 | 1911 |
2076 | 1912 |
2077 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | |
2078 Register input = ToRegister(instr->InputAt(0)); | |
2079 Register result = ToRegister(instr->result()); | |
2080 ASSERT(input.is(result)); | |
2081 Handle<String> class_name = instr->hydrogen()->class_name(); | |
2082 | |
2083 Label done, is_true, is_false; | |
2084 | |
2085 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); | |
2086 __ b(ne, &is_false); | |
2087 | |
2088 __ bind(&is_true); | |
2089 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
2090 __ jmp(&done); | |
2091 | |
2092 __ bind(&is_false); | |
2093 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
2094 __ bind(&done); | |
2095 } | |
2096 | |
2097 | |
2098 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1913 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2099 Register input = ToRegister(instr->InputAt(0)); | 1914 Register input = ToRegister(instr->InputAt(0)); |
2100 Register temp = scratch0(); | 1915 Register temp = scratch0(); |
2101 Register temp2 = ToRegister(instr->TempAt(0)); | 1916 Register temp2 = ToRegister(instr->TempAt(0)); |
2102 Handle<String> class_name = instr->hydrogen()->class_name(); | 1917 Handle<String> class_name = instr->hydrogen()->class_name(); |
2103 | 1918 |
2104 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1919 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2105 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1920 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2106 | 1921 |
2107 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1922 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
(...skipping 2234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4342 } | 4157 } |
4343 | 4158 |
4344 | 4159 |
4345 void LCodeGen::DoTypeof(LTypeof* instr) { | 4160 void LCodeGen::DoTypeof(LTypeof* instr) { |
4346 Register input = ToRegister(instr->InputAt(0)); | 4161 Register input = ToRegister(instr->InputAt(0)); |
4347 __ push(input); | 4162 __ push(input); |
4348 CallRuntime(Runtime::kTypeof, 1, instr); | 4163 CallRuntime(Runtime::kTypeof, 1, instr); |
4349 } | 4164 } |
4350 | 4165 |
4351 | 4166 |
4352 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | |
4353 Register input = ToRegister(instr->InputAt(0)); | |
4354 Register result = ToRegister(instr->result()); | |
4355 Label true_label; | |
4356 Label false_label; | |
4357 Label done; | |
4358 | |
4359 Condition final_branch_condition = EmitTypeofIs(&true_label, | |
4360 &false_label, | |
4361 input, | |
4362 instr->type_literal()); | |
4363 __ b(final_branch_condition, &true_label); | |
4364 __ bind(&false_label); | |
4365 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
4366 __ b(&done); | |
4367 | |
4368 __ bind(&true_label); | |
4369 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
4370 | |
4371 __ bind(&done); | |
4372 } | |
4373 | |
4374 | |
4375 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4167 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4376 Register input = ToRegister(instr->InputAt(0)); | 4168 Register input = ToRegister(instr->InputAt(0)); |
4377 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4169 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4378 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4170 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4379 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4171 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4380 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4172 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4381 | 4173 |
4382 Condition final_branch_condition = EmitTypeofIs(true_label, | 4174 Condition final_branch_condition = EmitTypeofIs(true_label, |
4383 false_label, | 4175 false_label, |
4384 input, | 4176 input, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4448 } else { | 4240 } else { |
4449 final_branch_condition = ne; | 4241 final_branch_condition = ne; |
4450 __ b(false_label); | 4242 __ b(false_label); |
4451 // A dead branch instruction will be generated after this point. | 4243 // A dead branch instruction will be generated after this point. |
4452 } | 4244 } |
4453 | 4245 |
4454 return final_branch_condition; | 4246 return final_branch_condition; |
4455 } | 4247 } |
4456 | 4248 |
4457 | 4249 |
4458 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | |
4459 Register result = ToRegister(instr->result()); | |
4460 Label true_label; | |
4461 Label false_label; | |
4462 Label done; | |
4463 | |
4464 EmitIsConstructCall(result, scratch0()); | |
4465 __ b(eq, &true_label); | |
4466 | |
4467 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
4468 __ b(&done); | |
4469 | |
4470 | |
4471 __ bind(&true_label); | |
4472 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
4473 | |
4474 __ bind(&done); | |
4475 } | |
4476 | |
4477 | |
4478 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4250 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4479 Register temp1 = ToRegister(instr->TempAt(0)); | 4251 Register temp1 = ToRegister(instr->TempAt(0)); |
4480 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4252 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4481 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4253 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4482 | 4254 |
4483 EmitIsConstructCall(temp1, scratch0()); | 4255 EmitIsConstructCall(temp1, scratch0()); |
4484 EmitBranch(true_block, false_block, eq); | 4256 EmitBranch(true_block, false_block, eq); |
4485 } | 4257 } |
4486 | 4258 |
4487 | 4259 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4603 ASSERT(osr_pc_offset_ == -1); | 4375 ASSERT(osr_pc_offset_ == -1); |
4604 osr_pc_offset_ = masm()->pc_offset(); | 4376 osr_pc_offset_ = masm()->pc_offset(); |
4605 } | 4377 } |
4606 | 4378 |
4607 | 4379 |
4608 | 4380 |
4609 | 4381 |
4610 #undef __ | 4382 #undef __ |
4611 | 4383 |
4612 } } // namespace v8::internal | 4384 } } // namespace v8::internal |
OLD | NEW |