OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1678 isolate()->factory()->empty_string(), | 1678 isolate()->factory()->empty_string(), |
1679 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), | 1679 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
1680 1)); | 1680 1)); |
1681 } | 1681 } |
1682 if_found.End(); | 1682 if_found.End(); |
1683 | 1683 |
1684 return Pop(); | 1684 return Pop(); |
1685 } | 1685 } |
1686 | 1686 |
1687 | 1687 |
1688 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, | 1688 HAllocate* HGraphBuilder::BuildAllocate( |
Hannes Payer (out of office)
2013/12/11 13:12:22
I like that. Are you planning to refactor other pr
Benedikt Meurer
2013/12/11 13:55:43
Yep, that's the plan.
| |
1689 String::Encoding encoding) { | 1689 HValue* object_size, |
1690 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); | 1690 HType type, |
1691 HValue* size = length; | 1691 InstanceType instance_type, |
1692 if (encoding == String::TWO_BYTE_ENCODING) { | 1692 HAllocationMode allocation_mode) { |
1693 size = AddUncasted<HShl>(length, graph()->GetConstant1()); | 1693 // Compute the effective allocation size. |
1694 HValue* size = object_size; | |
1695 if (allocation_mode.CreateAllocationMementos()) { | |
1696 size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize)); | |
1694 size->ClearFlag(HValue::kCanOverflow); | 1697 size->ClearFlag(HValue::kCanOverflow); |
1695 size->SetFlag(HValue::kUint32); | |
1696 } | 1698 } |
1697 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( | 1699 |
1698 SeqString::kHeaderSize + kObjectAlignmentMask))); | 1700 // Perform the actual allocation. |
1699 size->ClearFlag(HValue::kCanOverflow); | 1701 HAllocate* object = Add<HAllocate>( |
1700 size = AddUncasted<HBitwise>( | 1702 size, type, allocation_mode.GetPretenureMode(), |
1701 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( | 1703 instance_type, allocation_mode.feedback_site()); |
1702 ~kObjectAlignmentMask))); | 1704 |
1703 return size; | 1705 // Setup the allocation memento. |
1706 if (allocation_mode.CreateAllocationMementos()) { | |
1707 BuildCreateAllocationMemento( | |
1708 object, object_size, allocation_mode.current_site()); | |
1709 } | |
1710 | |
1711 return object; | |
1704 } | 1712 } |
1705 | 1713 |
1706 | 1714 |
1715 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length, | |
1716 HValue* right_length) { | |
1717 // Compute the combined string length. If the result is larger than the max | |
1718 // supported string length, we bailout to the runtime. This is done implicitly | |
Hannes Payer (out of office)
2013/12/11 13:12:22
implicitly
Benedikt Meurer
2013/12/11 13:55:43
:-)
| |
1719 // when converting the result back to a smi in case the max string length | |
1720 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do | |
mvstanton
2013/12/11 14:14:20
value, not valie.
Benedikt Meurer
2013/12/11 17:50:45
Done.
| |
1721 HValue* length = AddUncasted<HAdd>(left_length, right_length); | |
1722 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | |
1723 if (String::kMaxLength != Smi::kMaxValue) { | |
1724 IfBuilder if_nooverflow(this); | |
1725 if_nooverflow.If<HCompareNumericAndBranch>( | |
1726 length, Add<HConstant>(String::kMaxLength), Token::LTE); | |
1727 if_nooverflow.Then(); | |
1728 if_nooverflow.ElseDeopt("String length exceeds limit"); | |
1729 } | |
1730 return length; | |
1731 } | |
1732 | |
1733 | |
1734 HValue* HGraphBuilder::BuildCreateConsString( | |
1735 HValue* length, | |
1736 HValue* left, | |
1737 HValue* right, | |
1738 HAllocationMode allocation_mode) { | |
1739 // Determine the string instance types. | |
1740 HInstruction* left_instance_type = AddLoadStringInstanceType(left); | |
1741 HInstruction* right_instance_type = AddLoadStringInstanceType(right); | |
1742 | |
1743 // Allocate the cons string object. HAllocate does not care whether we | |
1744 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | |
1745 // CONS_STRING_TYPE here. Below we decide whether the cons string is | |
1746 // one-byte or two-byte and set the appropriate map. | |
Hannes Payer (out of office)
2013/12/11 13:12:22
Allocate should have the right instance type and w
Benedikt Meurer
2013/12/11 13:55:43
We don't need to. Discussed offline.
mvstanton
2013/12/11 14:14:20
Here you'll add the assert that the HAllocate flag
| |
1747 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize), | |
1748 HType::String(), CONS_STRING_TYPE, | |
1749 allocation_mode); | |
1750 | |
1751 // Compute intersection and difference of instance types. | |
1752 HValue* anded_instance_types = AddUncasted<HBitwise>( | |
1753 Token::BIT_AND, left_instance_type, right_instance_type); | |
1754 HValue* xored_instance_types = AddUncasted<HBitwise>( | |
1755 Token::BIT_XOR, left_instance_type, right_instance_type); | |
1756 | |
1757 // We create a one-byte cons string if | |
1758 // 1. both strings are one-byte, or | |
1759 // 2. at least one of the strings is two-byte, but happens to contain only | |
1760 // one-byte characters. | |
1761 // To do this, we check | |
1762 // 1. if both strings are one-byte, or if the one-byte data hint is set in | |
1763 // both strings, or | |
1764 // 2. if one of the strings has the one-byte data hint set and the other | |
1765 // string is one-byte. | |
1766 IfBuilder if_onebyte(this); | |
1767 STATIC_ASSERT(kOneByteStringTag != 0); | |
1768 STATIC_ASSERT(kOneByteDataHintMask != 0); | |
1769 if_onebyte.If<HCompareNumericAndBranch>( | |
1770 AddUncasted<HBitwise>( | |
1771 Token::BIT_AND, anded_instance_types, | |
1772 Add<HConstant>(static_cast<int32_t>( | |
1773 kStringEncodingMask | kOneByteDataHintMask))), | |
1774 graph()->GetConstant0(), Token::NE); | |
1775 if_onebyte.Or(); | |
1776 STATIC_ASSERT(kOneByteStringTag != 0 && | |
1777 kOneByteDataHintTag != 0 && | |
1778 kOneByteDataHintTag != kOneByteStringTag); | |
1779 if_onebyte.If<HCompareNumericAndBranch>( | |
1780 AddUncasted<HBitwise>( | |
1781 Token::BIT_AND, xored_instance_types, | |
1782 Add<HConstant>(static_cast<int32_t>( | |
1783 kOneByteStringTag | kOneByteDataHintTag))), | |
1784 Add<HConstant>(static_cast<int32_t>( | |
1785 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | |
1786 if_onebyte.Then(); | |
1787 { | |
1788 // We can safely skip the write barrier for storing the map here. | |
1789 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | |
1790 AddStoreMapConstantNoWriteBarrier(result, map); | |
Hannes Payer (out of office)
2013/12/11 13:12:22
Why is there a write barrier emitted? We should be
Benedikt Meurer
2013/12/11 13:55:43
Not in case of pretenuring, unfortunately.
| |
1791 } | |
1792 if_onebyte.Else(); | |
1793 { | |
1794 // We can safely skip the write barrier for storing the map here. | |
1795 Handle<Map> map = isolate()->factory()->cons_string_map(); | |
Hannes Payer (out of office)
2013/12/11 13:12:22
Why is there a write barrier emitted?
Benedikt Meurer
2013/12/11 13:55:43
Not in case of pretenuring, unfortunately.
| |
1796 AddStoreMapConstantNoWriteBarrier(result, map); | |
1797 } | |
1798 if_onebyte.End(); | |
1799 | |
1800 // Initialize the cons string fields. | |
1801 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), | |
1802 Add<HConstant>(String::kEmptyHashField)); | |
1803 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); | |
1804 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left); | |
1805 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right); | |
1806 | |
1807 // Count the native string addition. | |
1808 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
1809 | |
1810 return result; | |
1811 } | |
1812 | |
1813 | |
1707 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, | 1814 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
1708 HValue* src_offset, | 1815 HValue* src_offset, |
1709 String::Encoding src_encoding, | 1816 String::Encoding src_encoding, |
1710 HValue* dst, | 1817 HValue* dst, |
1711 HValue* dst_offset, | 1818 HValue* dst_offset, |
1712 String::Encoding dst_encoding, | 1819 String::Encoding dst_encoding, |
1713 HValue* length) { | 1820 HValue* length) { |
1714 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 1821 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
1715 src_encoding == String::ONE_BYTE_ENCODING); | 1822 src_encoding == String::ONE_BYTE_ENCODING); |
1716 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1823 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
1717 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1824 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1718 { | 1825 { |
1719 HValue* src_index = AddUncasted<HAdd>(src_offset, index); | 1826 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
1720 HValue* value = | 1827 HValue* value = |
1721 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); | 1828 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); |
1722 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); | 1829 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
1723 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 1830 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
1724 } | 1831 } |
1725 loop.EndBody(); | 1832 loop.EndBody(); |
1726 } | 1833 } |
1727 | 1834 |
1728 | 1835 |
1729 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1836 HValue* HGraphBuilder::BuildUncheckedStringAdd( |
1730 HValue* right, | 1837 HValue* left, |
1731 PretenureFlag pretenure_flag) { | 1838 HValue* right, |
1839 HAllocationMode allocation_mode) { | |
1732 // Determine the string lengths. | 1840 // Determine the string lengths. |
1733 HValue* left_length = Add<HLoadNamedField>( | 1841 HValue* left_length = AddLoadStringLength(left); |
1734 left, HObjectAccess::ForStringLength()); | 1842 HValue* right_length = AddLoadStringLength(right); |
1735 HValue* right_length = Add<HLoadNamedField>( | |
1736 right, HObjectAccess::ForStringLength()); | |
1737 | 1843 |
1738 // Compute the combined string length. If the result is larger than the max | 1844 // Compute the combined string length. |
1739 // supported string length, we bailout to the runtime. This is done implicitly | 1845 HValue* length = BuildAddStringLengths(left_length, right_length); |
1740 // when converting the result back to a smi in case the max string length | 1846 |
1741 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do | 1847 // Do some manual constant folding here. |
1742 HValue* length = AddUncasted<HAdd>(left_length, right_length); | 1848 if (left_length->IsConstant()) { |
1743 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 1849 HConstant* c_left_length = HConstant::cast(left_length); |
1744 if (String::kMaxLength != Smi::kMaxValue) { | 1850 ASSERT_NE(0, c_left_length->Integer32Value()); |
1745 IfBuilder if_nooverflow(this); | 1851 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) { |
1746 if_nooverflow.If<HCompareNumericAndBranch>( | 1852 // The right string contains at least one character. |
1747 length, Add<HConstant>(String::kMaxLength), Token::LTE); | 1853 return BuildCreateConsString(length, left, right, allocation_mode); |
1748 if_nooverflow.Then(); | 1854 } |
1749 if_nooverflow.ElseDeopt("String length exceeds limit"); | 1855 } else if (right_length->IsConstant()) { |
1856 HConstant* c_right_length = HConstant::cast(right_length); | |
1857 ASSERT_NE(0, c_right_length->Integer32Value()); | |
1858 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) { | |
1859 // The left string contains at least one character. | |
1860 return BuildCreateConsString(length, left, right, allocation_mode); | |
1861 } | |
1750 } | 1862 } |
1751 | 1863 |
1752 // Determine the string instance types. | |
1753 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | |
1754 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | |
1755 HObjectAccess::ForMapInstanceType()); | |
1756 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | |
1757 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | |
1758 HObjectAccess::ForMapInstanceType()); | |
1759 | |
1760 // Compute difference of instance types. | |
1761 HValue* xored_instance_types = AddUncasted<HBitwise>( | |
1762 Token::BIT_XOR, left_instance_type, right_instance_type); | |
1763 | |
1764 // Check if we should create a cons string. | 1864 // Check if we should create a cons string. |
1765 IfBuilder if_createcons(this); | 1865 IfBuilder if_createcons(this); |
1766 if_createcons.If<HCompareNumericAndBranch>( | 1866 if_createcons.If<HCompareNumericAndBranch>( |
1767 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 1867 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
1768 if_createcons.Then(); | 1868 if_createcons.Then(); |
1769 { | 1869 { |
1770 // Allocate the cons string object. HAllocate does not care whether we | 1870 // Create a cons string. |
1771 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 1871 Push(BuildCreateConsString(length, left, right, allocation_mode)); |
1772 // CONS_STRING_TYPE here. Below we decide whether the cons string is | |
1773 // one-byte or two-byte and set the appropriate map. | |
1774 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | |
1775 HType::String(), pretenure_flag, | |
1776 CONS_STRING_TYPE); | |
1777 | |
1778 // Compute the intersection of instance types. | |
1779 HValue* anded_instance_types = AddUncasted<HBitwise>( | |
1780 Token::BIT_AND, left_instance_type, right_instance_type); | |
1781 | |
1782 // We create a one-byte cons string if | |
1783 // 1. both strings are one-byte, or | |
1784 // 2. at least one of the strings is two-byte, but happens to contain only | |
1785 // one-byte characters. | |
1786 // To do this, we check | |
1787 // 1. if both strings are one-byte, or if the one-byte data hint is set in | |
1788 // both strings, or | |
1789 // 2. if one of the strings has the one-byte data hint set and the other | |
1790 // string is one-byte. | |
1791 IfBuilder if_onebyte(this); | |
1792 STATIC_ASSERT(kOneByteStringTag != 0); | |
1793 STATIC_ASSERT(kOneByteDataHintMask != 0); | |
1794 if_onebyte.If<HCompareNumericAndBranch>( | |
1795 AddUncasted<HBitwise>( | |
1796 Token::BIT_AND, anded_instance_types, | |
1797 Add<HConstant>(static_cast<int32_t>( | |
1798 kStringEncodingMask | kOneByteDataHintMask))), | |
1799 graph()->GetConstant0(), Token::NE); | |
1800 if_onebyte.Or(); | |
1801 STATIC_ASSERT(kOneByteStringTag != 0 && | |
1802 kOneByteDataHintTag != 0 && | |
1803 kOneByteDataHintTag != kOneByteStringTag); | |
1804 if_onebyte.If<HCompareNumericAndBranch>( | |
1805 AddUncasted<HBitwise>( | |
1806 Token::BIT_AND, xored_instance_types, | |
1807 Add<HConstant>(static_cast<int32_t>( | |
1808 kOneByteStringTag | kOneByteDataHintTag))), | |
1809 Add<HConstant>(static_cast<int32_t>( | |
1810 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | |
1811 if_onebyte.Then(); | |
1812 { | |
1813 // We can safely skip the write barrier for storing the map here. | |
1814 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | |
1815 AddStoreMapConstantNoWriteBarrier(string, map); | |
1816 } | |
1817 if_onebyte.Else(); | |
1818 { | |
1819 // We can safely skip the write barrier for storing the map here. | |
1820 Handle<Map> map = isolate()->factory()->cons_string_map(); | |
1821 AddStoreMapConstantNoWriteBarrier(string, map); | |
1822 } | |
1823 if_onebyte.End(); | |
1824 | |
1825 // Initialize the cons string fields. | |
1826 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | |
1827 Add<HConstant>(String::kEmptyHashField)); | |
1828 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); | |
1829 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | |
1830 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | |
1831 right); | |
1832 | |
1833 // Count the native string addition. | |
1834 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
1835 | |
1836 // Cons string is result. | |
1837 Push(string); | |
1838 } | 1872 } |
1839 if_createcons.Else(); | 1873 if_createcons.Else(); |
1840 { | 1874 { |
1841 // Compute union of instance types. | 1875 // Determine the string instance types. |
1876 HValue* left_instance_type = AddLoadStringInstanceType(left); | |
1877 HValue* right_instance_type = AddLoadStringInstanceType(right); | |
1878 | |
1879 // Compute union and difference of instance types. | |
1842 HValue* ored_instance_types = AddUncasted<HBitwise>( | 1880 HValue* ored_instance_types = AddUncasted<HBitwise>( |
1843 Token::BIT_OR, left_instance_type, right_instance_type); | 1881 Token::BIT_OR, left_instance_type, right_instance_type); |
1882 HValue* xored_instance_types = AddUncasted<HBitwise>( | |
1883 Token::BIT_XOR, left_instance_type, right_instance_type); | |
1844 | 1884 |
1845 // Check if both strings have the same encoding and both are | 1885 // Check if both strings have the same encoding and both are |
1846 // sequential. | 1886 // sequential. |
1847 IfBuilder if_sameencodingandsequential(this); | 1887 IfBuilder if_sameencodingandsequential(this); |
1848 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1888 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
1849 AddUncasted<HBitwise>( | 1889 AddUncasted<HBitwise>( |
1850 Token::BIT_AND, xored_instance_types, | 1890 Token::BIT_AND, xored_instance_types, |
1851 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1891 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
1852 graph()->GetConstant0(), Token::EQ); | 1892 graph()->GetConstant0(), Token::EQ); |
1853 if_sameencodingandsequential.And(); | 1893 if_sameencodingandsequential.And(); |
1854 STATIC_ASSERT(kSeqStringTag == 0); | 1894 STATIC_ASSERT(kSeqStringTag == 0); |
1855 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1895 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
1856 AddUncasted<HBitwise>( | 1896 AddUncasted<HBitwise>( |
1857 Token::BIT_AND, ored_instance_types, | 1897 Token::BIT_AND, ored_instance_types, |
1858 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), | 1898 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |
1859 graph()->GetConstant0(), Token::EQ); | 1899 graph()->GetConstant0(), Token::EQ); |
1860 if_sameencodingandsequential.Then(); | 1900 if_sameencodingandsequential.Then(); |
1861 { | 1901 { |
1862 // Check if the result is a one-byte string. | 1902 HConstant* string_map = |
1903 Add<HConstant>(isolate()->factory()->string_map()); | |
1904 HConstant* ascii_string_map = | |
1905 Add<HConstant>(isolate()->factory()->ascii_string_map()); | |
1906 | |
1907 // Determine map and size depending on whether result is one-byte string. | |
1863 IfBuilder if_onebyte(this); | 1908 IfBuilder if_onebyte(this); |
1864 STATIC_ASSERT(kOneByteStringTag != 0); | 1909 STATIC_ASSERT(kOneByteStringTag != 0); |
1865 if_onebyte.If<HCompareNumericAndBranch>( | 1910 if_onebyte.If<HCompareNumericAndBranch>( |
1866 AddUncasted<HBitwise>( | 1911 AddUncasted<HBitwise>( |
1867 Token::BIT_AND, ored_instance_types, | 1912 Token::BIT_AND, ored_instance_types, |
1868 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1913 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
1869 graph()->GetConstant0(), Token::NE); | 1914 graph()->GetConstant0(), Token::NE); |
1870 if_onebyte.Then(); | 1915 if_onebyte.Then(); |
1871 { | 1916 { |
1872 // Calculate the number of bytes needed for the characters in the | 1917 // Allocate sequential one-byte string object. |
1873 // string while observing object alignment. | 1918 Push(length); |
1874 HValue* size = BuildSeqStringSizeFor( | 1919 Push(ascii_string_map); |
1875 length, String::ONE_BYTE_ENCODING); | |
1876 | |
1877 // Allocate the ASCII string object. | |
1878 Handle<Map> map = isolate()->factory()->ascii_string_map(); | |
1879 HAllocate* string = Add<HAllocate>(size, HType::String(), | |
1880 pretenure_flag, ASCII_STRING_TYPE); | |
1881 string->set_known_initial_map(map); | |
1882 | |
1883 // We can safely skip the write barrier for storing map here. | |
1884 AddStoreMapConstantNoWriteBarrier(string, map); | |
1885 | |
1886 // Length must be stored into the string before we copy characters to | |
1887 // make debug verification code happy. | |
1888 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
1889 length); | |
1890 | |
1891 // Copy bytes from the left string. | |
1892 BuildCopySeqStringChars( | |
1893 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1894 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1895 left_length); | |
1896 | |
1897 // Copy bytes from the right string. | |
1898 BuildCopySeqStringChars( | |
1899 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1900 string, left_length, String::ONE_BYTE_ENCODING, | |
1901 right_length); | |
1902 | |
1903 // Count the native string addition. | |
1904 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
1905 | |
1906 // Return the string. | |
1907 Push(string); | |
1908 } | 1920 } |
1909 if_onebyte.Else(); | 1921 if_onebyte.Else(); |
1910 { | 1922 { |
1911 // Calculate the number of bytes needed for the characters in the | 1923 // Allocate sequential two-byte string object. |
1912 // string while observing object alignment. | 1924 HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1()); |
mvstanton
2013/12/11 14:14:20
The shift instruction seems very low level. Any ch
Benedikt Meurer
2013/12/11 17:50:45
Using HMul generates less optimal code.
| |
1913 HValue* size = BuildSeqStringSizeFor( | 1925 size->ClearFlag(HValue::kCanOverflow); |
1914 length, String::TWO_BYTE_ENCODING); | 1926 size->SetFlag(HValue::kUint32); |
1927 Push(size); | |
1928 Push(string_map); | |
1929 } | |
1930 if_onebyte.End(); | |
1931 HValue* map = Pop(); | |
1915 | 1932 |
1916 // Allocate the two-byte string object. | 1933 // Calculate the number of bytes needed for the characters in the |
1917 Handle<Map> map = isolate()->factory()->string_map(); | 1934 // string while observing object alignment. |
1918 HAllocate* string = Add<HAllocate>(size, HType::String(), | 1935 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); |
1919 pretenure_flag, STRING_TYPE); | 1936 HValue* size = Pop(); |
1920 string->set_known_initial_map(map); | 1937 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( |
1938 SeqString::kHeaderSize + kObjectAlignmentMask))); | |
1939 size->ClearFlag(HValue::kCanOverflow); | |
1940 size = AddUncasted<HBitwise>( | |
1941 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( | |
1942 ~kObjectAlignmentMask))); | |
mvstanton
2013/12/11 14:14:20
Could this size computation be in a method, or is
Benedikt Meurer
2013/12/11 17:50:45
BuildSeqStringSizeFor() is gone. This is basically
| |
1921 | 1943 |
1922 // We can safely skip the write barrier for storing map here. | 1944 // Allocate the string object. HAllocate does not care whether we pass |
1923 AddStoreMapConstantNoWriteBarrier(string, map); | 1945 // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here. |
1946 HAllocate* result = BuildAllocate( | |
1947 size, HType::String(), STRING_TYPE, allocation_mode); | |
1924 | 1948 |
1925 // Length must be stored into the string before we copy characters to | 1949 // We can safely skip the write barrier for storing map here. |
1926 // make debug verification code happy. | 1950 AddStoreMapNoWriteBarrier(result, map); |
Hannes Payer (out of office)
2013/12/11 13:12:22
Why is there a write barrier emitted?
Benedikt Meurer
2013/12/11 13:55:43
I don't know.
| |
1927 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
1928 length); | |
1929 | 1951 |
1930 // Copy bytes from the left string. | 1952 // Initialize the string fields. |
1953 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), | |
1954 Add<HConstant>(String::kEmptyHashField)); | |
1955 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); | |
1956 | |
1957 // Copy characters to the result string. | |
1958 IfBuilder if_twobyte(this); | |
1959 if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map); | |
1960 if_twobyte.Then(); | |
1961 { | |
1962 // Copy characters from the left string. | |
1931 BuildCopySeqStringChars( | 1963 BuildCopySeqStringChars( |
1932 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1964 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1933 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1965 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1934 left_length); | 1966 left_length); |
1935 | 1967 |
1936 // Copy bytes from the right string. | 1968 // Copy characters from the right string. |
1937 BuildCopySeqStringChars( | 1969 BuildCopySeqStringChars( |
1938 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1970 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1939 string, left_length, String::TWO_BYTE_ENCODING, | 1971 result, left_length, String::TWO_BYTE_ENCODING, |
1940 right_length); | 1972 right_length); |
1973 } | |
1974 if_twobyte.Else(); | |
1975 { | |
1976 // Copy characters from the left string. | |
1977 BuildCopySeqStringChars( | |
1978 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1979 result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1980 left_length); | |
1941 | 1981 |
1942 // Return the string. | 1982 // Copy characters from the right string. |
1943 Push(string); | 1983 BuildCopySeqStringChars( |
1984 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1985 result, left_length, String::ONE_BYTE_ENCODING, | |
1986 right_length); | |
1944 } | 1987 } |
1945 if_onebyte.End(); | 1988 if_twobyte.End(); |
1946 | |
1947 // Initialize the (common) string fields. | |
1948 HValue* string = Pop(); | |
1949 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | |
1950 Add<HConstant>(String::kEmptyHashField)); | |
1951 | 1989 |
1952 // Count the native string addition. | 1990 // Count the native string addition. |
1953 AddIncrementCounter(isolate()->counters()->string_add_native()); | 1991 AddIncrementCounter(isolate()->counters()->string_add_native()); |
1954 | 1992 |
1955 Push(string); | 1993 // Return the sequential string. |
1994 Push(result); | |
1956 } | 1995 } |
1957 if_sameencodingandsequential.Else(); | 1996 if_sameencodingandsequential.Else(); |
1958 { | 1997 { |
1959 // Fallback to the runtime to add the two strings. | 1998 // Fallback to the runtime to add the two strings. |
1960 Add<HPushArgument>(left); | 1999 Add<HPushArgument>(left); |
1961 Add<HPushArgument>(right); | 2000 Add<HPushArgument>(right); |
1962 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | 2001 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), |
1963 Runtime::FunctionForId(Runtime::kStringAdd), | 2002 Runtime::FunctionForId(Runtime::kStringAdd), |
1964 2)); | 2003 2)); |
1965 } | 2004 } |
1966 if_sameencodingandsequential.End(); | 2005 if_sameencodingandsequential.End(); |
1967 } | 2006 } |
1968 if_createcons.End(); | 2007 if_createcons.End(); |
1969 | 2008 |
1970 return Pop(); | 2009 return Pop(); |
1971 } | 2010 } |
1972 | 2011 |
1973 | 2012 |
1974 HValue* HGraphBuilder::BuildStringAdd(HValue* left, | 2013 HValue* HGraphBuilder::BuildStringAdd( |
1975 HValue* right, | 2014 HValue* left, |
1976 PretenureFlag pretenure_flag) { | 2015 HValue* right, |
1977 // Determine the string lengths. | 2016 HAllocationMode allocation_mode) { |
1978 HValue* left_length = Add<HLoadNamedField>( | 2017 NoObservableSideEffectsScope no_effects(this); |
1979 left, HObjectAccess::ForStringLength()); | 2018 |
1980 HValue* right_length = Add<HLoadNamedField>( | 2019 // Determine string lengths. |
1981 right, HObjectAccess::ForStringLength()); | 2020 HValue* left_length = AddLoadStringLength(left); |
2021 HValue* right_length = AddLoadStringLength(right); | |
1982 | 2022 |
1983 // Check if left string is empty. | 2023 // Check if left string is empty. |
1984 IfBuilder if_leftisempty(this); | 2024 IfBuilder if_leftempty(this); |
1985 if_leftisempty.If<HCompareNumericAndBranch>( | 2025 if_leftempty.If<HCompareNumericAndBranch>( |
1986 left_length, graph()->GetConstant0(), Token::EQ); | 2026 left_length, graph()->GetConstant0(), Token::EQ); |
1987 if_leftisempty.Then(); | 2027 if_leftempty.Then(); |
1988 { | 2028 { |
1989 // Count the native string addition. | 2029 // Count the native string addition. |
1990 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2030 AddIncrementCounter(isolate()->counters()->string_add_native()); |
1991 | 2031 |
1992 // Just return the right string. | 2032 // Just return the right string. |
1993 Push(right); | 2033 Push(right); |
1994 } | 2034 } |
1995 if_leftisempty.Else(); | 2035 if_leftempty.Else(); |
1996 { | 2036 { |
1997 // Check if right string is empty. | 2037 // Check if right string is empty. |
1998 IfBuilder if_rightisempty(this); | 2038 IfBuilder if_rightempty(this); |
1999 if_rightisempty.If<HCompareNumericAndBranch>( | 2039 if_rightempty.If<HCompareNumericAndBranch>( |
2000 right_length, graph()->GetConstant0(), Token::EQ); | 2040 right_length, graph()->GetConstant0(), Token::EQ); |
2001 if_rightisempty.Then(); | 2041 if_rightempty.Then(); |
2002 { | 2042 { |
2003 // Count the native string addition. | 2043 // Count the native string addition. |
2004 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2044 AddIncrementCounter(isolate()->counters()->string_add_native()); |
2005 | 2045 |
2006 // Just return the left string. | 2046 // Just return the left string. |
2007 Push(left); | 2047 Push(left); |
2008 } | 2048 } |
2009 if_rightisempty.Else(); | 2049 if_rightempty.Else(); |
2010 { | 2050 { |
2011 // Concatenate the two non-empty strings. | 2051 // Add the two non-empty strings. |
2012 Push(BuildUncheckedStringAdd(left, right, pretenure_flag)); | 2052 Push(BuildUncheckedStringAdd(left, right, allocation_mode)); |
2013 } | 2053 } |
2014 if_rightisempty.End(); | 2054 if_rightempty.End(); |
2015 } | 2055 } |
2016 if_leftisempty.End(); | 2056 if_leftempty.End(); |
2017 | 2057 |
2018 return Pop(); | 2058 return Pop(); |
2019 } | 2059 } |
2020 | 2060 |
2021 | 2061 |
2022 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2062 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
2023 HValue* checked_object, | 2063 HValue* checked_object, |
2024 HValue* key, | 2064 HValue* key, |
2025 HValue* val, | 2065 HValue* val, |
2026 bool is_js_array, | 2066 bool is_js_array, |
(...skipping 4110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6137 return New<HLoadNamedField>(object, access); | 6177 return New<HLoadNamedField>(object, access); |
6138 } | 6178 } |
6139 | 6179 |
6140 | 6180 |
6141 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object, | 6181 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object, |
6142 HObjectAccess access) { | 6182 HObjectAccess access) { |
6143 return AddInstruction(BuildLoadNamedField(object, access)); | 6183 return AddInstruction(BuildLoadNamedField(object, access)); |
6144 } | 6184 } |
6145 | 6185 |
6146 | 6186 |
6147 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, | 6187 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) { |
6148 HValue* checked_string) { | 6188 if (string->IsConstant()) { |
6149 if (FLAG_fold_constants && object->IsConstant()) { | 6189 HConstant* c_string = HConstant::cast(string); |
6150 HConstant* constant = HConstant::cast(object); | 6190 if (c_string->HasStringValue()) { |
6151 if (constant->HasStringValue()) { | 6191 return Add<HConstant>(c_string->StringValue()->map()->instance_type()); |
6152 return New<HConstant>(constant->StringValue()->length()); | |
6153 } | 6192 } |
6154 } | 6193 } |
6155 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); | 6194 return AddLoadNamedField( |
6195 AddLoadNamedField(string, HObjectAccess::ForMap()), | |
6196 HObjectAccess::ForMapInstanceType()); | |
6156 } | 6197 } |
6157 | 6198 |
6158 | 6199 |
6200 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) { | |
6201 if (string->IsConstant()) { | |
6202 HConstant* c_string = HConstant::cast(string); | |
6203 if (c_string->HasStringValue()) { | |
6204 return Add<HConstant>(c_string->StringValue()->length()); | |
6205 } | |
6206 } | |
6207 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); | |
6208 } | |
6209 | |
6210 | |
6159 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6211 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
6160 HValue* object, | 6212 HValue* object, |
6161 Handle<String> name, | 6213 Handle<String> name, |
6162 Property* expr) { | 6214 Property* expr) { |
6163 if (expr->IsUninitialized()) { | 6215 if (expr->IsUninitialized()) { |
6164 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 6216 Add<HDeoptimize>("Insufficient type feedback for generic named load", |
6165 Deoptimizer::SOFT); | 6217 Deoptimizer::SOFT); |
6166 } | 6218 } |
6167 return New<HLoadNamedGeneric>(object, name); | 6219 return New<HLoadNamedGeneric>(object, name); |
6168 } | 6220 } |
(...skipping 2424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8593 HConstant* c_index = HConstant::cast(index); | 8645 HConstant* c_index = HConstant::cast(index); |
8594 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 8646 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
8595 int32_t i = c_index->NumberValueAsInteger32(); | 8647 int32_t i = c_index->NumberValueAsInteger32(); |
8596 Handle<String> s = c_string->StringValue(); | 8648 Handle<String> s = c_string->StringValue(); |
8597 if (i < 0 || i >= s->length()) { | 8649 if (i < 0 || i >= s->length()) { |
8598 return New<HConstant>(OS::nan_value()); | 8650 return New<HConstant>(OS::nan_value()); |
8599 } | 8651 } |
8600 return New<HConstant>(s->Get(i)); | 8652 return New<HConstant>(s->Get(i)); |
8601 } | 8653 } |
8602 } | 8654 } |
8603 BuildCheckHeapObject(string); | 8655 string = BuildCheckString(string); |
8604 HValue* checkstring = | 8656 index = Add<HBoundsCheck>(index, AddLoadStringLength(string)); |
8605 Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); | 8657 return New<HStringCharCodeAt>(string, index); |
8606 HInstruction* length = BuildLoadStringLength(string, checkstring); | |
8607 AddInstruction(length); | |
8608 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | |
8609 return New<HStringCharCodeAt>(string, checked_index); | |
8610 } | 8658 } |
8611 | 8659 |
8612 | 8660 |
8613 // Checks if the given shift amounts have following forms: | 8661 // Checks if the given shift amounts have following forms: |
8614 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). | 8662 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). |
8615 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8663 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
8616 HValue* const32_minus_sa) { | 8664 HValue* const32_minus_sa) { |
8617 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { | 8665 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { |
8618 const HConstant* c1 = HConstant::cast(sa); | 8666 const HConstant* c1 = HConstant::cast(sa); |
8619 const HConstant* c2 = HConstant::cast(const32_minus_sa); | 8667 const HConstant* c2 = HConstant::cast(const32_minus_sa); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8730 | 8778 |
8731 | 8779 |
8732 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8780 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
8733 BinaryOperation* expr, | 8781 BinaryOperation* expr, |
8734 HValue* left, | 8782 HValue* left, |
8735 HValue* right) { | 8783 HValue* right) { |
8736 Handle<Type> left_type = expr->left()->bounds().lower; | 8784 Handle<Type> left_type = expr->left()->bounds().lower; |
8737 Handle<Type> right_type = expr->right()->bounds().lower; | 8785 Handle<Type> right_type = expr->right()->bounds().lower; |
8738 Handle<Type> result_type = expr->bounds().lower; | 8786 Handle<Type> result_type = expr->bounds().lower; |
8739 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 8787 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
8788 Handle<AllocationSite> allocation_site = expr->allocation_site(); | |
8789 | |
8790 HAllocationMode allocation_mode = | |
8791 FLAG_allocation_site_pretenuring | |
8792 ? (allocation_site.is_null() | |
8793 ? HAllocationMode(NOT_TENURED) | |
8794 : HAllocationMode(allocation_site)) | |
8795 : HAllocationMode(isolate()->heap()->GetPretenureMode()); | |
8740 | 8796 |
8741 HValue* result = HGraphBuilder::BuildBinaryOperation( | 8797 HValue* result = HGraphBuilder::BuildBinaryOperation( |
8742 expr->op(), left, right, left_type, right_type, | 8798 expr->op(), left, right, left_type, right_type, result_type, |
8743 result_type, fixed_right_arg); | 8799 fixed_right_arg, allocation_mode); |
8744 // Add a simulate after instructions with observable side effects, and | 8800 // Add a simulate after instructions with observable side effects, and |
8745 // after phis, which are the result of BuildBinaryOperation when we | 8801 // after phis, which are the result of BuildBinaryOperation when we |
8746 // inlined some complex subgraph. | 8802 // inlined some complex subgraph. |
8747 if (result->HasObservableSideEffects() || result->IsPhi()) { | 8803 if (result->HasObservableSideEffects() || result->IsPhi()) { |
8748 Push(result); | 8804 Push(result); |
8749 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 8805 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
8750 Drop(1); | 8806 Drop(1); |
8751 } | 8807 } |
8752 return result; | 8808 return result; |
8753 } | 8809 } |
8754 | 8810 |
8755 | 8811 |
8756 HValue* HGraphBuilder::BuildBinaryOperation( | 8812 HValue* HGraphBuilder::BuildBinaryOperation( |
8757 Token::Value op, | 8813 Token::Value op, |
8758 HValue* left, | 8814 HValue* left, |
8759 HValue* right, | 8815 HValue* right, |
8760 Handle<Type> left_type, | 8816 Handle<Type> left_type, |
8761 Handle<Type> right_type, | 8817 Handle<Type> right_type, |
8762 Handle<Type> result_type, | 8818 Handle<Type> result_type, |
8763 Maybe<int> fixed_right_arg) { | 8819 Maybe<int> fixed_right_arg, |
8820 HAllocationMode allocation_mode) { | |
8764 | 8821 |
8765 Representation left_rep = Representation::FromType(left_type); | 8822 Representation left_rep = Representation::FromType(left_type); |
8766 Representation right_rep = Representation::FromType(right_type); | 8823 Representation right_rep = Representation::FromType(right_type); |
8767 | 8824 |
8768 bool maybe_string_add = op == Token::ADD && | 8825 bool maybe_string_add = op == Token::ADD && |
8769 (left_type->Maybe(Type::String()) || | 8826 (left_type->Maybe(Type::String()) || |
8770 right_type->Maybe(Type::String())); | 8827 right_type->Maybe(Type::String())); |
8771 | 8828 |
8772 if (left_type->Is(Type::None())) { | 8829 if (left_type->Is(Type::None())) { |
8773 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8830 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8819 ASSERT(left_type->Is(Type::String())); | 8876 ASSERT(left_type->Is(Type::String())); |
8820 right = BuildNumberToString(right, right_type); | 8877 right = BuildNumberToString(right, right_type); |
8821 } else if (!right_type->Is(Type::String())) { | 8878 } else if (!right_type->Is(Type::String())) { |
8822 ASSERT(left_type->Is(Type::String())); | 8879 ASSERT(left_type->Is(Type::String())); |
8823 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 8880 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
8824 Add<HPushArgument>(left); | 8881 Add<HPushArgument>(left); |
8825 Add<HPushArgument>(right); | 8882 Add<HPushArgument>(right); |
8826 return AddUncasted<HInvokeFunction>(function, 2); | 8883 return AddUncasted<HInvokeFunction>(function, 2); |
8827 } | 8884 } |
8828 | 8885 |
8829 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); | 8886 // Inline the string addition into the stub when creating allocation |
8887 // mementos to gather allocation site feedback. | |
8888 if (graph()->info()->IsStub() && | |
8889 allocation_mode.CreateAllocationMementos()) { | |
8890 return BuildStringAdd(left, right, allocation_mode); | |
mvstanton
2013/12/11 14:14:20
If you are building a stub, can you count on havin
Benedikt Meurer
2013/12/11 17:50:45
No, because this code is also used for the BinaryO
| |
8891 } | |
8892 | |
8893 // Register the dependent code with the allocation site. | |
8894 if (!allocation_mode.feedback_site().is_null()) { | |
8895 ASSERT(!graph()->info()->IsStub()); | |
8896 allocation_mode.feedback_site()->AddDependentCompilationInfo( | |
8897 AllocationSite::TENURING, top_info()); | |
8898 } | |
8899 | |
8900 // Inline string addition if we know that we'll create a cons string. | |
8901 if (left->IsConstant()) { | |
8902 HConstant* c_left = HConstant::cast(left); | |
8903 if (c_left->HasStringValue()) { | |
8904 if (c_left->StringValue()->length() + 1 >= ConsString::kMinLength) { | |
mvstanton
2013/12/11 14:14:20
nit: put the "base case" of empty left string firs
Benedikt Meurer
2013/12/11 17:50:45
Done.
| |
8905 return BuildStringAdd(left, right, allocation_mode); | |
8906 } else if (c_left->StringValue()->length() == 0) { | |
8907 return right; | |
8908 } | |
8909 } | |
8910 } | |
8911 if (right->IsConstant()) { | |
8912 HConstant* c_right = HConstant::cast(right); | |
8913 if (c_right->HasStringValue()) { | |
8914 if (c_right->StringValue()->length() + 1 >= ConsString::kMinLength) { | |
mvstanton
2013/12/11 14:14:20
Same here.
Benedikt Meurer
2013/12/11 17:50:45
Done.
| |
8915 return BuildStringAdd(left, right, allocation_mode); | |
8916 } else if (c_right->StringValue()->length() == 0) { | |
8917 return left; | |
8918 } | |
8919 } | |
8920 } | |
8921 | |
8922 // Fallback to using the string add stub. | |
8923 return AddUncasted<HStringAdd>( | |
8924 left, right, allocation_mode.GetPretenureMode(), | |
8925 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | |
8830 } | 8926 } |
8831 | 8927 |
8832 if (graph()->info()->IsStub()) { | 8928 if (graph()->info()->IsStub()) { |
8833 left = EnforceNumberType(left, left_type); | 8929 left = EnforceNumberType(left, left_type); |
8834 right = EnforceNumberType(right, right_type); | 8930 right = EnforceNumberType(right, right_type); |
8835 } | 8931 } |
8836 | 8932 |
8837 Representation result_rep = Representation::FromType(result_type); | 8933 Representation result_rep = Representation::FromType(result_type); |
8838 | 8934 |
8839 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 8935 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
(...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10022 } | 10118 } |
10023 | 10119 |
10024 | 10120 |
10025 // Fast support for StringAdd. | 10121 // Fast support for StringAdd. |
10026 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 10122 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
10027 ASSERT_EQ(2, call->arguments()->length()); | 10123 ASSERT_EQ(2, call->arguments()->length()); |
10028 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10124 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10029 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10125 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
10030 HValue* right = Pop(); | 10126 HValue* right = Pop(); |
10031 HValue* left = Pop(); | 10127 HValue* left = Pop(); |
10032 HInstruction* result = | 10128 HInstruction* result = NewUncasted<HStringAdd>(left, right); |
10033 NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); | |
10034 return ast_context()->ReturnInstruction(result, call->id()); | 10129 return ast_context()->ReturnInstruction(result, call->id()); |
10035 } | 10130 } |
10036 | 10131 |
10037 | 10132 |
10038 // Fast support for SubString. | 10133 // Fast support for SubString. |
10039 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 10134 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
10040 ASSERT_EQ(3, call->arguments()->length()); | 10135 ASSERT_EQ(3, call->arguments()->length()); |
10041 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10136 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
10042 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 10137 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
10043 Drop(3); | 10138 Drop(3); |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10813 if (ShouldProduceTraceOutput()) { | 10908 if (ShouldProduceTraceOutput()) { |
10814 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10909 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10815 } | 10910 } |
10816 | 10911 |
10817 #ifdef DEBUG | 10912 #ifdef DEBUG |
10818 graph_->Verify(false); // No full verify. | 10913 graph_->Verify(false); // No full verify. |
10819 #endif | 10914 #endif |
10820 } | 10915 } |
10821 | 10916 |
10822 } } // namespace v8::internal | 10917 } } // namespace v8::internal |
OLD | NEW |