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 1675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 isolate()->factory()->empty_string(), | 1686 isolate()->factory()->empty_string(), |
1687 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), | 1687 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
1688 1)); | 1688 1)); |
1689 } | 1689 } |
1690 if_found.End(); | 1690 if_found.End(); |
1691 | 1691 |
1692 return Pop(); | 1692 return Pop(); |
1693 } | 1693 } |
1694 | 1694 |
1695 | 1695 |
1696 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, | 1696 HAllocate* HGraphBuilder::BuildAllocate( |
1697 String::Encoding encoding) { | 1697 HValue* object_size, |
1698 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); | 1698 HType type, |
1699 HValue* size = length; | 1699 InstanceType instance_type, |
1700 if (encoding == String::TWO_BYTE_ENCODING) { | 1700 HAllocationMode allocation_mode) { |
1701 size = AddUncasted<HShl>(length, graph()->GetConstant1()); | 1701 // Compute the effective allocation size. |
| 1702 HValue* size = object_size; |
| 1703 if (allocation_mode.CreateAllocationMementos()) { |
| 1704 size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize)); |
1702 size->ClearFlag(HValue::kCanOverflow); | 1705 size->ClearFlag(HValue::kCanOverflow); |
1703 size->SetFlag(HValue::kUint32); | |
1704 } | 1706 } |
1705 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( | 1707 |
1706 SeqString::kHeaderSize + kObjectAlignmentMask))); | 1708 // Perform the actual allocation. |
1707 size->ClearFlag(HValue::kCanOverflow); | 1709 HAllocate* object = Add<HAllocate>( |
1708 size = AddUncasted<HBitwise>( | 1710 size, type, allocation_mode.GetPretenureMode(), |
1709 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( | 1711 instance_type, allocation_mode.feedback_site()); |
1710 ~kObjectAlignmentMask))); | 1712 |
1711 return size; | 1713 // Setup the allocation memento. |
| 1714 if (allocation_mode.CreateAllocationMementos()) { |
| 1715 BuildCreateAllocationMemento( |
| 1716 object, object_size, allocation_mode.current_site()); |
| 1717 } |
| 1718 |
| 1719 return object; |
1712 } | 1720 } |
1713 | 1721 |
1714 | 1722 |
| 1723 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length, |
| 1724 HValue* right_length) { |
| 1725 // Compute the combined string length. If the result is larger than the max |
| 1726 // supported string length, we bailout to the runtime. This is done implicitly |
| 1727 // when converting the result back to a smi in case the max string length |
| 1728 // equals the max smi value. Otherwise, for platforms with 32-bit smis, we do |
| 1729 HValue* length = AddUncasted<HAdd>(left_length, right_length); |
| 1730 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 1731 if (String::kMaxLength != Smi::kMaxValue) { |
| 1732 IfBuilder if_nooverflow(this); |
| 1733 if_nooverflow.If<HCompareNumericAndBranch>( |
| 1734 length, Add<HConstant>(String::kMaxLength), Token::LTE); |
| 1735 if_nooverflow.Then(); |
| 1736 if_nooverflow.ElseDeopt("String length exceeds limit"); |
| 1737 } |
| 1738 return length; |
| 1739 } |
| 1740 |
| 1741 |
| 1742 HValue* HGraphBuilder::BuildCreateConsString( |
| 1743 HValue* length, |
| 1744 HValue* left, |
| 1745 HValue* right, |
| 1746 HAllocationMode allocation_mode) { |
| 1747 // Determine the string instance types. |
| 1748 HInstruction* left_instance_type = AddLoadStringInstanceType(left); |
| 1749 HInstruction* right_instance_type = AddLoadStringInstanceType(right); |
| 1750 |
| 1751 // Allocate the cons string object. HAllocate does not care whether we |
| 1752 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use |
| 1753 // CONS_STRING_TYPE here. Below we decide whether the cons string is |
| 1754 // one-byte or two-byte and set the appropriate map. |
| 1755 ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE, |
| 1756 CONS_ASCII_STRING_TYPE)); |
| 1757 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize), |
| 1758 HType::String(), CONS_STRING_TYPE, |
| 1759 allocation_mode); |
| 1760 |
| 1761 // Compute intersection and difference of instance types. |
| 1762 HValue* anded_instance_types = AddUncasted<HBitwise>( |
| 1763 Token::BIT_AND, left_instance_type, right_instance_type); |
| 1764 HValue* xored_instance_types = AddUncasted<HBitwise>( |
| 1765 Token::BIT_XOR, left_instance_type, right_instance_type); |
| 1766 |
| 1767 // We create a one-byte cons string if |
| 1768 // 1. both strings are one-byte, or |
| 1769 // 2. at least one of the strings is two-byte, but happens to contain only |
| 1770 // one-byte characters. |
| 1771 // To do this, we check |
| 1772 // 1. if both strings are one-byte, or if the one-byte data hint is set in |
| 1773 // both strings, or |
| 1774 // 2. if one of the strings has the one-byte data hint set and the other |
| 1775 // string is one-byte. |
| 1776 IfBuilder if_onebyte(this); |
| 1777 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1778 STATIC_ASSERT(kOneByteDataHintMask != 0); |
| 1779 if_onebyte.If<HCompareNumericAndBranch>( |
| 1780 AddUncasted<HBitwise>( |
| 1781 Token::BIT_AND, anded_instance_types, |
| 1782 Add<HConstant>(static_cast<int32_t>( |
| 1783 kStringEncodingMask | kOneByteDataHintMask))), |
| 1784 graph()->GetConstant0(), Token::NE); |
| 1785 if_onebyte.Or(); |
| 1786 STATIC_ASSERT(kOneByteStringTag != 0 && |
| 1787 kOneByteDataHintTag != 0 && |
| 1788 kOneByteDataHintTag != kOneByteStringTag); |
| 1789 if_onebyte.If<HCompareNumericAndBranch>( |
| 1790 AddUncasted<HBitwise>( |
| 1791 Token::BIT_AND, xored_instance_types, |
| 1792 Add<HConstant>(static_cast<int32_t>( |
| 1793 kOneByteStringTag | kOneByteDataHintTag))), |
| 1794 Add<HConstant>(static_cast<int32_t>( |
| 1795 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); |
| 1796 if_onebyte.Then(); |
| 1797 { |
| 1798 // We can safely skip the write barrier for storing the map here. |
| 1799 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); |
| 1800 AddStoreMapConstantNoWriteBarrier(result, map); |
| 1801 } |
| 1802 if_onebyte.Else(); |
| 1803 { |
| 1804 // We can safely skip the write barrier for storing the map here. |
| 1805 Handle<Map> map = isolate()->factory()->cons_string_map(); |
| 1806 AddStoreMapConstantNoWriteBarrier(result, map); |
| 1807 } |
| 1808 if_onebyte.End(); |
| 1809 |
| 1810 // Initialize the cons string fields. |
| 1811 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), |
| 1812 Add<HConstant>(String::kEmptyHashField)); |
| 1813 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); |
| 1814 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left); |
| 1815 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right); |
| 1816 |
| 1817 // Count the native string addition. |
| 1818 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1819 |
| 1820 return result; |
| 1821 } |
| 1822 |
| 1823 |
1715 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, | 1824 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
1716 HValue* src_offset, | 1825 HValue* src_offset, |
1717 String::Encoding src_encoding, | 1826 String::Encoding src_encoding, |
1718 HValue* dst, | 1827 HValue* dst, |
1719 HValue* dst_offset, | 1828 HValue* dst_offset, |
1720 String::Encoding dst_encoding, | 1829 String::Encoding dst_encoding, |
1721 HValue* length) { | 1830 HValue* length) { |
1722 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 1831 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
1723 src_encoding == String::ONE_BYTE_ENCODING); | 1832 src_encoding == String::ONE_BYTE_ENCODING); |
1724 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1833 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
1725 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1834 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1726 { | 1835 { |
1727 HValue* src_index = AddUncasted<HAdd>(src_offset, index); | 1836 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
1728 HValue* value = | 1837 HValue* value = |
1729 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); | 1838 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); |
1730 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); | 1839 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
1731 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 1840 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
1732 } | 1841 } |
1733 loop.EndBody(); | 1842 loop.EndBody(); |
1734 } | 1843 } |
1735 | 1844 |
1736 | 1845 |
1737 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1846 HValue* HGraphBuilder::BuildUncheckedStringAdd( |
1738 HValue* right, | 1847 HValue* left, |
1739 PretenureFlag pretenure_flag) { | 1848 HValue* right, |
| 1849 HAllocationMode allocation_mode) { |
1740 // Determine the string lengths. | 1850 // Determine the string lengths. |
1741 HValue* left_length = Add<HLoadNamedField>( | 1851 HValue* left_length = AddLoadStringLength(left); |
1742 left, HObjectAccess::ForStringLength()); | 1852 HValue* right_length = AddLoadStringLength(right); |
1743 HValue* right_length = Add<HLoadNamedField>( | |
1744 right, HObjectAccess::ForStringLength()); | |
1745 | 1853 |
1746 // Compute the combined string length. If the result is larger than the max | 1854 // Compute the combined string length. |
1747 // supported string length, we bailout to the runtime. This is done implicitly | 1855 HValue* length = BuildAddStringLengths(left_length, right_length); |
1748 // when converting the result back to a smi in case the max string length | 1856 |
1749 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do | 1857 // Do some manual constant folding here. |
1750 HValue* length = AddUncasted<HAdd>(left_length, right_length); | 1858 if (left_length->IsConstant()) { |
1751 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 1859 HConstant* c_left_length = HConstant::cast(left_length); |
1752 if (String::kMaxLength != Smi::kMaxValue) { | 1860 ASSERT_NE(0, c_left_length->Integer32Value()); |
1753 IfBuilder if_nooverflow(this); | 1861 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) { |
1754 if_nooverflow.If<HCompareNumericAndBranch>( | 1862 // The right string contains at least one character. |
1755 length, Add<HConstant>(String::kMaxLength), Token::LTE); | 1863 return BuildCreateConsString(length, left, right, allocation_mode); |
1756 if_nooverflow.Then(); | 1864 } |
1757 if_nooverflow.ElseDeopt("String length exceeds limit"); | 1865 } else if (right_length->IsConstant()) { |
| 1866 HConstant* c_right_length = HConstant::cast(right_length); |
| 1867 ASSERT_NE(0, c_right_length->Integer32Value()); |
| 1868 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) { |
| 1869 // The left string contains at least one character. |
| 1870 return BuildCreateConsString(length, left, right, allocation_mode); |
| 1871 } |
1758 } | 1872 } |
1759 | 1873 |
1760 // Determine the string instance types. | |
1761 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | |
1762 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | |
1763 HObjectAccess::ForMapInstanceType()); | |
1764 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | |
1765 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | |
1766 HObjectAccess::ForMapInstanceType()); | |
1767 | |
1768 // Compute difference of instance types. | |
1769 HValue* xored_instance_types = AddUncasted<HBitwise>( | |
1770 Token::BIT_XOR, left_instance_type, right_instance_type); | |
1771 | |
1772 // Check if we should create a cons string. | 1874 // Check if we should create a cons string. |
1773 IfBuilder if_createcons(this); | 1875 IfBuilder if_createcons(this); |
1774 if_createcons.If<HCompareNumericAndBranch>( | 1876 if_createcons.If<HCompareNumericAndBranch>( |
1775 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 1877 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
1776 if_createcons.Then(); | 1878 if_createcons.Then(); |
1777 { | 1879 { |
1778 // Allocate the cons string object. HAllocate does not care whether we | 1880 // Create a cons string. |
1779 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 1881 Push(BuildCreateConsString(length, left, right, allocation_mode)); |
1780 // CONS_STRING_TYPE here. Below we decide whether the cons string is | |
1781 // one-byte or two-byte and set the appropriate map. | |
1782 ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE, | |
1783 CONS_ASCII_STRING_TYPE)); | |
1784 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | |
1785 HType::String(), pretenure_flag, | |
1786 CONS_STRING_TYPE); | |
1787 | |
1788 // Compute the intersection of instance types. | |
1789 HValue* anded_instance_types = AddUncasted<HBitwise>( | |
1790 Token::BIT_AND, left_instance_type, right_instance_type); | |
1791 | |
1792 // We create a one-byte cons string if | |
1793 // 1. both strings are one-byte, or | |
1794 // 2. at least one of the strings is two-byte, but happens to contain only | |
1795 // one-byte characters. | |
1796 // To do this, we check | |
1797 // 1. if both strings are one-byte, or if the one-byte data hint is set in | |
1798 // both strings, or | |
1799 // 2. if one of the strings has the one-byte data hint set and the other | |
1800 // string is one-byte. | |
1801 IfBuilder if_onebyte(this); | |
1802 STATIC_ASSERT(kOneByteStringTag != 0); | |
1803 STATIC_ASSERT(kOneByteDataHintMask != 0); | |
1804 if_onebyte.If<HCompareNumericAndBranch>( | |
1805 AddUncasted<HBitwise>( | |
1806 Token::BIT_AND, anded_instance_types, | |
1807 Add<HConstant>(static_cast<int32_t>( | |
1808 kStringEncodingMask | kOneByteDataHintMask))), | |
1809 graph()->GetConstant0(), Token::NE); | |
1810 if_onebyte.Or(); | |
1811 STATIC_ASSERT(kOneByteStringTag != 0 && | |
1812 kOneByteDataHintTag != 0 && | |
1813 kOneByteDataHintTag != kOneByteStringTag); | |
1814 if_onebyte.If<HCompareNumericAndBranch>( | |
1815 AddUncasted<HBitwise>( | |
1816 Token::BIT_AND, xored_instance_types, | |
1817 Add<HConstant>(static_cast<int32_t>( | |
1818 kOneByteStringTag | kOneByteDataHintTag))), | |
1819 Add<HConstant>(static_cast<int32_t>( | |
1820 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | |
1821 if_onebyte.Then(); | |
1822 { | |
1823 // We can safely skip the write barrier for storing the map here. | |
1824 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | |
1825 AddStoreMapConstantNoWriteBarrier(string, map); | |
1826 } | |
1827 if_onebyte.Else(); | |
1828 { | |
1829 // We can safely skip the write barrier for storing the map here. | |
1830 Handle<Map> map = isolate()->factory()->cons_string_map(); | |
1831 AddStoreMapConstantNoWriteBarrier(string, map); | |
1832 } | |
1833 if_onebyte.End(); | |
1834 | |
1835 // Initialize the cons string fields. | |
1836 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | |
1837 Add<HConstant>(String::kEmptyHashField)); | |
1838 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); | |
1839 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | |
1840 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | |
1841 right); | |
1842 | |
1843 // Count the native string addition. | |
1844 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
1845 | |
1846 // Cons string is result. | |
1847 Push(string); | |
1848 } | 1882 } |
1849 if_createcons.Else(); | 1883 if_createcons.Else(); |
1850 { | 1884 { |
1851 // Compute union of instance types. | 1885 // Determine the string instance types. |
| 1886 HValue* left_instance_type = AddLoadStringInstanceType(left); |
| 1887 HValue* right_instance_type = AddLoadStringInstanceType(right); |
| 1888 |
| 1889 // Compute union and difference of instance types. |
1852 HValue* ored_instance_types = AddUncasted<HBitwise>( | 1890 HValue* ored_instance_types = AddUncasted<HBitwise>( |
1853 Token::BIT_OR, left_instance_type, right_instance_type); | 1891 Token::BIT_OR, left_instance_type, right_instance_type); |
| 1892 HValue* xored_instance_types = AddUncasted<HBitwise>( |
| 1893 Token::BIT_XOR, left_instance_type, right_instance_type); |
1854 | 1894 |
1855 // Check if both strings have the same encoding and both are | 1895 // Check if both strings have the same encoding and both are |
1856 // sequential. | 1896 // sequential. |
1857 IfBuilder if_sameencodingandsequential(this); | 1897 IfBuilder if_sameencodingandsequential(this); |
1858 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1898 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
1859 AddUncasted<HBitwise>( | 1899 AddUncasted<HBitwise>( |
1860 Token::BIT_AND, xored_instance_types, | 1900 Token::BIT_AND, xored_instance_types, |
1861 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1901 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
1862 graph()->GetConstant0(), Token::EQ); | 1902 graph()->GetConstant0(), Token::EQ); |
1863 if_sameencodingandsequential.And(); | 1903 if_sameencodingandsequential.And(); |
1864 STATIC_ASSERT(kSeqStringTag == 0); | 1904 STATIC_ASSERT(kSeqStringTag == 0); |
1865 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1905 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
1866 AddUncasted<HBitwise>( | 1906 AddUncasted<HBitwise>( |
1867 Token::BIT_AND, ored_instance_types, | 1907 Token::BIT_AND, ored_instance_types, |
1868 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), | 1908 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |
1869 graph()->GetConstant0(), Token::EQ); | 1909 graph()->GetConstant0(), Token::EQ); |
1870 if_sameencodingandsequential.Then(); | 1910 if_sameencodingandsequential.Then(); |
1871 { | 1911 { |
1872 // Check if the result is a one-byte string. | 1912 HConstant* string_map = |
| 1913 Add<HConstant>(isolate()->factory()->string_map()); |
| 1914 HConstant* ascii_string_map = |
| 1915 Add<HConstant>(isolate()->factory()->ascii_string_map()); |
| 1916 |
| 1917 // Determine map and size depending on whether result is one-byte string. |
1873 IfBuilder if_onebyte(this); | 1918 IfBuilder if_onebyte(this); |
1874 STATIC_ASSERT(kOneByteStringTag != 0); | 1919 STATIC_ASSERT(kOneByteStringTag != 0); |
1875 if_onebyte.If<HCompareNumericAndBranch>( | 1920 if_onebyte.If<HCompareNumericAndBranch>( |
1876 AddUncasted<HBitwise>( | 1921 AddUncasted<HBitwise>( |
1877 Token::BIT_AND, ored_instance_types, | 1922 Token::BIT_AND, ored_instance_types, |
1878 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1923 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
1879 graph()->GetConstant0(), Token::NE); | 1924 graph()->GetConstant0(), Token::NE); |
1880 if_onebyte.Then(); | 1925 if_onebyte.Then(); |
1881 { | 1926 { |
1882 // Calculate the number of bytes needed for the characters in the | 1927 // Allocate sequential one-byte string object. |
1883 // string while observing object alignment. | 1928 Push(length); |
1884 HValue* size = BuildSeqStringSizeFor( | 1929 Push(ascii_string_map); |
1885 length, String::ONE_BYTE_ENCODING); | |
1886 | |
1887 // Allocate the ASCII string object. | |
1888 Handle<Map> map = isolate()->factory()->ascii_string_map(); | |
1889 HAllocate* string = Add<HAllocate>(size, HType::String(), | |
1890 pretenure_flag, ASCII_STRING_TYPE); | |
1891 string->set_known_initial_map(map); | |
1892 | |
1893 // We can safely skip the write barrier for storing map here. | |
1894 AddStoreMapConstantNoWriteBarrier(string, map); | |
1895 | |
1896 // Length must be stored into the string before we copy characters to | |
1897 // make debug verification code happy. | |
1898 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
1899 length); | |
1900 | |
1901 // Copy bytes from the left string. | |
1902 BuildCopySeqStringChars( | |
1903 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1904 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1905 left_length); | |
1906 | |
1907 // Copy bytes from the right string. | |
1908 BuildCopySeqStringChars( | |
1909 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
1910 string, left_length, String::ONE_BYTE_ENCODING, | |
1911 right_length); | |
1912 | |
1913 // Count the native string addition. | |
1914 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
1915 | |
1916 // Return the string. | |
1917 Push(string); | |
1918 } | 1930 } |
1919 if_onebyte.Else(); | 1931 if_onebyte.Else(); |
1920 { | 1932 { |
1921 // Calculate the number of bytes needed for the characters in the | 1933 // Allocate sequential two-byte string object. |
1922 // string while observing object alignment. | 1934 HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1()); |
1923 HValue* size = BuildSeqStringSizeFor( | 1935 size->ClearFlag(HValue::kCanOverflow); |
1924 length, String::TWO_BYTE_ENCODING); | 1936 size->SetFlag(HValue::kUint32); |
| 1937 Push(size); |
| 1938 Push(string_map); |
| 1939 } |
| 1940 if_onebyte.End(); |
| 1941 HValue* map = Pop(); |
1925 | 1942 |
1926 // Allocate the two-byte string object. | 1943 // Calculate the number of bytes needed for the characters in the |
1927 Handle<Map> map = isolate()->factory()->string_map(); | 1944 // string while observing object alignment. |
1928 HAllocate* string = Add<HAllocate>(size, HType::String(), | 1945 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); |
1929 pretenure_flag, STRING_TYPE); | 1946 HValue* size = Pop(); |
1930 string->set_known_initial_map(map); | 1947 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( |
| 1948 SeqString::kHeaderSize + kObjectAlignmentMask))); |
| 1949 size->ClearFlag(HValue::kCanOverflow); |
| 1950 size = AddUncasted<HBitwise>( |
| 1951 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( |
| 1952 ~kObjectAlignmentMask))); |
1931 | 1953 |
1932 // We can safely skip the write barrier for storing map here. | 1954 // Allocate the string object. HAllocate does not care whether we pass |
1933 AddStoreMapConstantNoWriteBarrier(string, map); | 1955 // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here. |
| 1956 HAllocate* result = BuildAllocate( |
| 1957 size, HType::String(), STRING_TYPE, allocation_mode); |
1934 | 1958 |
1935 // Length must be stored into the string before we copy characters to | 1959 // We can safely skip the write barrier for storing map here. |
1936 // make debug verification code happy. | 1960 AddStoreMapNoWriteBarrier(result, map); |
1937 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
1938 length); | |
1939 | 1961 |
1940 // Copy bytes from the left string. | 1962 // Initialize the string fields. |
| 1963 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(), |
| 1964 Add<HConstant>(String::kEmptyHashField)); |
| 1965 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length); |
| 1966 |
| 1967 // Copy characters to the result string. |
| 1968 IfBuilder if_twobyte(this); |
| 1969 if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map); |
| 1970 if_twobyte.Then(); |
| 1971 { |
| 1972 // Copy characters from the left string. |
1941 BuildCopySeqStringChars( | 1973 BuildCopySeqStringChars( |
1942 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1974 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1943 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1975 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1944 left_length); | 1976 left_length); |
1945 | 1977 |
1946 // Copy bytes from the right string. | 1978 // Copy characters from the right string. |
1947 BuildCopySeqStringChars( | 1979 BuildCopySeqStringChars( |
1948 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 1980 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
1949 string, left_length, String::TWO_BYTE_ENCODING, | 1981 result, left_length, String::TWO_BYTE_ENCODING, |
1950 right_length); | 1982 right_length); |
| 1983 } |
| 1984 if_twobyte.Else(); |
| 1985 { |
| 1986 // Copy characters from the left string. |
| 1987 BuildCopySeqStringChars( |
| 1988 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1989 result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1990 left_length); |
1951 | 1991 |
1952 // Return the string. | 1992 // Copy characters from the right string. |
1953 Push(string); | 1993 BuildCopySeqStringChars( |
| 1994 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |
| 1995 result, left_length, String::ONE_BYTE_ENCODING, |
| 1996 right_length); |
1954 } | 1997 } |
1955 if_onebyte.End(); | 1998 if_twobyte.End(); |
1956 | |
1957 // Initialize the (common) string fields. | |
1958 HValue* string = Pop(); | |
1959 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | |
1960 Add<HConstant>(String::kEmptyHashField)); | |
1961 | 1999 |
1962 // Count the native string addition. | 2000 // Count the native string addition. |
1963 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2001 AddIncrementCounter(isolate()->counters()->string_add_native()); |
1964 | 2002 |
1965 Push(string); | 2003 // Return the sequential string. |
| 2004 Push(result); |
1966 } | 2005 } |
1967 if_sameencodingandsequential.Else(); | 2006 if_sameencodingandsequential.Else(); |
1968 { | 2007 { |
1969 // Fallback to the runtime to add the two strings. | 2008 // Fallback to the runtime to add the two strings. |
1970 Add<HPushArgument>(left); | 2009 Add<HPushArgument>(left); |
1971 Add<HPushArgument>(right); | 2010 Add<HPushArgument>(right); |
1972 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | 2011 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), |
1973 Runtime::FunctionForId(Runtime::kStringAdd), | 2012 Runtime::FunctionForId(Runtime::kStringAdd), |
1974 2)); | 2013 2)); |
1975 } | 2014 } |
1976 if_sameencodingandsequential.End(); | 2015 if_sameencodingandsequential.End(); |
1977 } | 2016 } |
1978 if_createcons.End(); | 2017 if_createcons.End(); |
1979 | 2018 |
1980 return Pop(); | 2019 return Pop(); |
1981 } | 2020 } |
1982 | 2021 |
1983 | 2022 |
1984 HValue* HGraphBuilder::BuildStringAdd(HValue* left, | 2023 HValue* HGraphBuilder::BuildStringAdd( |
1985 HValue* right, | 2024 HValue* left, |
1986 PretenureFlag pretenure_flag) { | 2025 HValue* right, |
1987 // Determine the string lengths. | 2026 HAllocationMode allocation_mode) { |
1988 HValue* left_length = Add<HLoadNamedField>( | 2027 NoObservableSideEffectsScope no_effects(this); |
1989 left, HObjectAccess::ForStringLength()); | 2028 |
1990 HValue* right_length = Add<HLoadNamedField>( | 2029 // Determine string lengths. |
1991 right, HObjectAccess::ForStringLength()); | 2030 HValue* left_length = AddLoadStringLength(left); |
| 2031 HValue* right_length = AddLoadStringLength(right); |
1992 | 2032 |
1993 // Check if left string is empty. | 2033 // Check if left string is empty. |
1994 IfBuilder if_leftisempty(this); | 2034 IfBuilder if_leftempty(this); |
1995 if_leftisempty.If<HCompareNumericAndBranch>( | 2035 if_leftempty.If<HCompareNumericAndBranch>( |
1996 left_length, graph()->GetConstant0(), Token::EQ); | 2036 left_length, graph()->GetConstant0(), Token::EQ); |
1997 if_leftisempty.Then(); | 2037 if_leftempty.Then(); |
1998 { | 2038 { |
1999 // Count the native string addition. | 2039 // Count the native string addition. |
2000 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2040 AddIncrementCounter(isolate()->counters()->string_add_native()); |
2001 | 2041 |
2002 // Just return the right string. | 2042 // Just return the right string. |
2003 Push(right); | 2043 Push(right); |
2004 } | 2044 } |
2005 if_leftisempty.Else(); | 2045 if_leftempty.Else(); |
2006 { | 2046 { |
2007 // Check if right string is empty. | 2047 // Check if right string is empty. |
2008 IfBuilder if_rightisempty(this); | 2048 IfBuilder if_rightempty(this); |
2009 if_rightisempty.If<HCompareNumericAndBranch>( | 2049 if_rightempty.If<HCompareNumericAndBranch>( |
2010 right_length, graph()->GetConstant0(), Token::EQ); | 2050 right_length, graph()->GetConstant0(), Token::EQ); |
2011 if_rightisempty.Then(); | 2051 if_rightempty.Then(); |
2012 { | 2052 { |
2013 // Count the native string addition. | 2053 // Count the native string addition. |
2014 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2054 AddIncrementCounter(isolate()->counters()->string_add_native()); |
2015 | 2055 |
2016 // Just return the left string. | 2056 // Just return the left string. |
2017 Push(left); | 2057 Push(left); |
2018 } | 2058 } |
2019 if_rightisempty.Else(); | 2059 if_rightempty.Else(); |
2020 { | 2060 { |
2021 // Concatenate the two non-empty strings. | 2061 // Add the two non-empty strings. |
2022 Push(BuildUncheckedStringAdd(left, right, pretenure_flag)); | 2062 Push(BuildUncheckedStringAdd(left, right, allocation_mode)); |
2023 } | 2063 } |
2024 if_rightisempty.End(); | 2064 if_rightempty.End(); |
2025 } | 2065 } |
2026 if_leftisempty.End(); | 2066 if_leftempty.End(); |
2027 | 2067 |
2028 return Pop(); | 2068 return Pop(); |
2029 } | 2069 } |
2030 | 2070 |
2031 | 2071 |
2032 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2072 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
2033 HValue* checked_object, | 2073 HValue* checked_object, |
2034 HValue* key, | 2074 HValue* key, |
2035 HValue* val, | 2075 HValue* val, |
2036 bool is_js_array, | 2076 bool is_js_array, |
(...skipping 4056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6093 return New<HLoadNamedField>(object, access); | 6133 return New<HLoadNamedField>(object, access); |
6094 } | 6134 } |
6095 | 6135 |
6096 | 6136 |
6097 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object, | 6137 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object, |
6098 HObjectAccess access) { | 6138 HObjectAccess access) { |
6099 return AddInstruction(BuildLoadNamedField(object, access)); | 6139 return AddInstruction(BuildLoadNamedField(object, access)); |
6100 } | 6140 } |
6101 | 6141 |
6102 | 6142 |
6103 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, | 6143 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) { |
6104 HValue* checked_string) { | 6144 if (string->IsConstant()) { |
6105 if (FLAG_fold_constants && object->IsConstant()) { | 6145 HConstant* c_string = HConstant::cast(string); |
6106 HConstant* constant = HConstant::cast(object); | 6146 if (c_string->HasStringValue()) { |
6107 if (constant->HasStringValue()) { | 6147 return Add<HConstant>(c_string->StringValue()->map()->instance_type()); |
6108 return New<HConstant>(constant->StringValue()->length()); | |
6109 } | 6148 } |
6110 } | 6149 } |
6111 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); | 6150 return AddLoadNamedField( |
| 6151 AddLoadNamedField(string, HObjectAccess::ForMap()), |
| 6152 HObjectAccess::ForMapInstanceType()); |
6112 } | 6153 } |
6113 | 6154 |
6114 | 6155 |
| 6156 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) { |
| 6157 if (string->IsConstant()) { |
| 6158 HConstant* c_string = HConstant::cast(string); |
| 6159 if (c_string->HasStringValue()) { |
| 6160 return Add<HConstant>(c_string->StringValue()->length()); |
| 6161 } |
| 6162 } |
| 6163 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); |
| 6164 } |
| 6165 |
| 6166 |
6115 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6167 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
6116 HValue* object, | 6168 HValue* object, |
6117 Handle<String> name, | 6169 Handle<String> name, |
6118 Property* expr) { | 6170 Property* expr) { |
6119 if (expr->IsUninitialized()) { | 6171 if (expr->IsUninitialized()) { |
6120 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 6172 Add<HDeoptimize>("Insufficient type feedback for generic named load", |
6121 Deoptimizer::SOFT); | 6173 Deoptimizer::SOFT); |
6122 } | 6174 } |
6123 return New<HLoadNamedGeneric>(object, name); | 6175 return New<HLoadNamedGeneric>(object, name); |
6124 } | 6176 } |
(...skipping 2424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8549 HConstant* c_index = HConstant::cast(index); | 8601 HConstant* c_index = HConstant::cast(index); |
8550 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 8602 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
8551 int32_t i = c_index->NumberValueAsInteger32(); | 8603 int32_t i = c_index->NumberValueAsInteger32(); |
8552 Handle<String> s = c_string->StringValue(); | 8604 Handle<String> s = c_string->StringValue(); |
8553 if (i < 0 || i >= s->length()) { | 8605 if (i < 0 || i >= s->length()) { |
8554 return New<HConstant>(OS::nan_value()); | 8606 return New<HConstant>(OS::nan_value()); |
8555 } | 8607 } |
8556 return New<HConstant>(s->Get(i)); | 8608 return New<HConstant>(s->Get(i)); |
8557 } | 8609 } |
8558 } | 8610 } |
8559 BuildCheckHeapObject(string); | 8611 string = BuildCheckString(string); |
8560 HValue* checkstring = | 8612 index = Add<HBoundsCheck>(index, AddLoadStringLength(string)); |
8561 Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); | 8613 return New<HStringCharCodeAt>(string, index); |
8562 HInstruction* length = BuildLoadStringLength(string, checkstring); | |
8563 AddInstruction(length); | |
8564 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | |
8565 return New<HStringCharCodeAt>(string, checked_index); | |
8566 } | 8614 } |
8567 | 8615 |
8568 | 8616 |
8569 // Checks if the given shift amounts have following forms: | 8617 // Checks if the given shift amounts have following forms: |
8570 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). | 8618 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). |
8571 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8619 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
8572 HValue* const32_minus_sa) { | 8620 HValue* const32_minus_sa) { |
8573 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { | 8621 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { |
8574 const HConstant* c1 = HConstant::cast(sa); | 8622 const HConstant* c1 = HConstant::cast(sa); |
8575 const HConstant* c2 = HConstant::cast(const32_minus_sa); | 8623 const HConstant* c2 = HConstant::cast(const32_minus_sa); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8686 | 8734 |
8687 | 8735 |
8688 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8736 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
8689 BinaryOperation* expr, | 8737 BinaryOperation* expr, |
8690 HValue* left, | 8738 HValue* left, |
8691 HValue* right) { | 8739 HValue* right) { |
8692 Handle<Type> left_type = expr->left()->bounds().lower; | 8740 Handle<Type> left_type = expr->left()->bounds().lower; |
8693 Handle<Type> right_type = expr->right()->bounds().lower; | 8741 Handle<Type> right_type = expr->right()->bounds().lower; |
8694 Handle<Type> result_type = expr->bounds().lower; | 8742 Handle<Type> result_type = expr->bounds().lower; |
8695 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 8743 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 8744 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 8745 |
| 8746 HAllocationMode allocation_mode = |
| 8747 FLAG_allocation_site_pretenuring |
| 8748 ? (allocation_site.is_null() |
| 8749 ? HAllocationMode(NOT_TENURED) |
| 8750 : HAllocationMode(allocation_site)) |
| 8751 : HAllocationMode(isolate()->heap()->GetPretenureMode()); |
8696 | 8752 |
8697 HValue* result = HGraphBuilder::BuildBinaryOperation( | 8753 HValue* result = HGraphBuilder::BuildBinaryOperation( |
8698 expr->op(), left, right, left_type, right_type, | 8754 expr->op(), left, right, left_type, right_type, result_type, |
8699 result_type, fixed_right_arg); | 8755 fixed_right_arg, allocation_mode); |
8700 // Add a simulate after instructions with observable side effects, and | 8756 // Add a simulate after instructions with observable side effects, and |
8701 // after phis, which are the result of BuildBinaryOperation when we | 8757 // after phis, which are the result of BuildBinaryOperation when we |
8702 // inlined some complex subgraph. | 8758 // inlined some complex subgraph. |
8703 if (result->HasObservableSideEffects() || result->IsPhi()) { | 8759 if (result->HasObservableSideEffects() || result->IsPhi()) { |
8704 Push(result); | 8760 Push(result); |
8705 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 8761 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
8706 Drop(1); | 8762 Drop(1); |
8707 } | 8763 } |
8708 return result; | 8764 return result; |
8709 } | 8765 } |
8710 | 8766 |
8711 | 8767 |
8712 HValue* HGraphBuilder::BuildBinaryOperation( | 8768 HValue* HGraphBuilder::BuildBinaryOperation( |
8713 Token::Value op, | 8769 Token::Value op, |
8714 HValue* left, | 8770 HValue* left, |
8715 HValue* right, | 8771 HValue* right, |
8716 Handle<Type> left_type, | 8772 Handle<Type> left_type, |
8717 Handle<Type> right_type, | 8773 Handle<Type> right_type, |
8718 Handle<Type> result_type, | 8774 Handle<Type> result_type, |
8719 Maybe<int> fixed_right_arg) { | 8775 Maybe<int> fixed_right_arg, |
| 8776 HAllocationMode allocation_mode) { |
8720 | 8777 |
8721 Representation left_rep = Representation::FromType(left_type); | 8778 Representation left_rep = Representation::FromType(left_type); |
8722 Representation right_rep = Representation::FromType(right_type); | 8779 Representation right_rep = Representation::FromType(right_type); |
8723 | 8780 |
8724 bool maybe_string_add = op == Token::ADD && | 8781 bool maybe_string_add = op == Token::ADD && |
8725 (left_type->Maybe(Type::String()) || | 8782 (left_type->Maybe(Type::String()) || |
8726 right_type->Maybe(Type::String())); | 8783 right_type->Maybe(Type::String())); |
8727 | 8784 |
8728 if (left_type->Is(Type::None())) { | 8785 if (left_type->Is(Type::None())) { |
8729 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8786 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8775 ASSERT(left_type->Is(Type::String())); | 8832 ASSERT(left_type->Is(Type::String())); |
8776 right = BuildNumberToString(right, right_type); | 8833 right = BuildNumberToString(right, right_type); |
8777 } else if (!right_type->Is(Type::String())) { | 8834 } else if (!right_type->Is(Type::String())) { |
8778 ASSERT(left_type->Is(Type::String())); | 8835 ASSERT(left_type->Is(Type::String())); |
8779 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 8836 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
8780 Add<HPushArgument>(left); | 8837 Add<HPushArgument>(left); |
8781 Add<HPushArgument>(right); | 8838 Add<HPushArgument>(right); |
8782 return AddUncasted<HInvokeFunction>(function, 2); | 8839 return AddUncasted<HInvokeFunction>(function, 2); |
8783 } | 8840 } |
8784 | 8841 |
8785 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); | 8842 // Inline the string addition into the stub when creating allocation |
| 8843 // mementos to gather allocation site feedback. |
| 8844 if (graph()->info()->IsStub() && |
| 8845 allocation_mode.CreateAllocationMementos()) { |
| 8846 return BuildStringAdd(left, right, allocation_mode); |
| 8847 } |
| 8848 |
| 8849 // Register the dependent code with the allocation site. |
| 8850 if (!allocation_mode.feedback_site().is_null()) { |
| 8851 ASSERT(!graph()->info()->IsStub()); |
| 8852 allocation_mode.feedback_site()->AddDependentCompilationInfo( |
| 8853 AllocationSite::TENURING, top_info()); |
| 8854 } |
| 8855 |
| 8856 // Inline string addition if we know that we'll create a cons string. |
| 8857 if (left->IsConstant()) { |
| 8858 HConstant* c_left = HConstant::cast(left); |
| 8859 if (c_left->HasStringValue()) { |
| 8860 int c_left_length = c_left->StringValue()->length(); |
| 8861 if (c_left_length == 0) { |
| 8862 return right; |
| 8863 } else if (c_left_length + 1 >= ConsString::kMinLength) { |
| 8864 return BuildStringAdd(left, right, allocation_mode); |
| 8865 } |
| 8866 } |
| 8867 } |
| 8868 if (right->IsConstant()) { |
| 8869 HConstant* c_right = HConstant::cast(right); |
| 8870 if (c_right->HasStringValue()) { |
| 8871 int c_right_length = c_right->StringValue()->length(); |
| 8872 if (c_right_length == 0) { |
| 8873 return left; |
| 8874 } else if (c_right_length + 1 >= ConsString::kMinLength) { |
| 8875 return BuildStringAdd(left, right, allocation_mode); |
| 8876 } |
| 8877 } |
| 8878 } |
| 8879 |
| 8880 // Fallback to using the string add stub. |
| 8881 return AddUncasted<HStringAdd>( |
| 8882 left, right, allocation_mode.GetPretenureMode(), |
| 8883 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
8786 } | 8884 } |
8787 | 8885 |
8788 if (graph()->info()->IsStub()) { | 8886 if (graph()->info()->IsStub()) { |
8789 left = EnforceNumberType(left, left_type); | 8887 left = EnforceNumberType(left, left_type); |
8790 right = EnforceNumberType(right, right_type); | 8888 right = EnforceNumberType(right, right_type); |
8791 } | 8889 } |
8792 | 8890 |
8793 Representation result_rep = Representation::FromType(result_type); | 8891 Representation result_rep = Representation::FromType(result_type); |
8794 | 8892 |
8795 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 8893 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
(...skipping 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10004 } | 10102 } |
10005 | 10103 |
10006 | 10104 |
10007 // Fast support for StringAdd. | 10105 // Fast support for StringAdd. |
10008 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 10106 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
10009 ASSERT_EQ(2, call->arguments()->length()); | 10107 ASSERT_EQ(2, call->arguments()->length()); |
10010 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10108 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10011 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10109 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
10012 HValue* right = Pop(); | 10110 HValue* right = Pop(); |
10013 HValue* left = Pop(); | 10111 HValue* left = Pop(); |
10014 HInstruction* result = | 10112 HInstruction* result = NewUncasted<HStringAdd>(left, right); |
10015 NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); | |
10016 return ast_context()->ReturnInstruction(result, call->id()); | 10113 return ast_context()->ReturnInstruction(result, call->id()); |
10017 } | 10114 } |
10018 | 10115 |
10019 | 10116 |
10020 // Fast support for SubString. | 10117 // Fast support for SubString. |
10021 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 10118 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
10022 ASSERT_EQ(3, call->arguments()->length()); | 10119 ASSERT_EQ(3, call->arguments()->length()); |
10023 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10120 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
10024 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 10121 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
10025 Drop(3); | 10122 Drop(3); |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10794 if (ShouldProduceTraceOutput()) { | 10891 if (ShouldProduceTraceOutput()) { |
10795 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10892 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10796 } | 10893 } |
10797 | 10894 |
10798 #ifdef DEBUG | 10895 #ifdef DEBUG |
10799 graph_->Verify(false); // No full verify. | 10896 graph_->Verify(false); // No full verify. |
10800 #endif | 10897 #endif |
10801 } | 10898 } |
10802 | 10899 |
10803 } } // namespace v8::internal | 10900 } } // namespace v8::internal |
OLD | NEW |