| 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 1715 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1726 | 1726 | 
| 1727 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1727 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 
| 1728                                                HValue* right, | 1728                                                HValue* right, | 
| 1729                                                PretenureFlag pretenure_flag) { | 1729                                                PretenureFlag pretenure_flag) { | 
| 1730   // Determine the string lengths. | 1730   // Determine the string lengths. | 
| 1731   HValue* left_length = Add<HLoadNamedField>( | 1731   HValue* left_length = Add<HLoadNamedField>( | 
| 1732       left, HObjectAccess::ForStringLength()); | 1732       left, HObjectAccess::ForStringLength()); | 
| 1733   HValue* right_length = Add<HLoadNamedField>( | 1733   HValue* right_length = Add<HLoadNamedField>( | 
| 1734       right, HObjectAccess::ForStringLength()); | 1734       right, HObjectAccess::ForStringLength()); | 
| 1735 | 1735 | 
| 1736   // Check if we concatenated the strings here, or if we have to resort to the | 1736   // Compute the combined string length. If the result is larger than the max | 
| 1737   // runtime function. | 1737   // supported string length, we bailout to the runtime. This is done implicitly | 
| 1738   HIfContinuation handled(graph()->CreateBasicBlock(), | 1738   // when converting the result back to a smi in case the max string length | 
| 1739                           graph()->CreateBasicBlock()); | 1739   // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do | 
| 1740 | 1740   HValue* length = AddUncasted<HAdd>(left_length, right_length); | 
| 1741   // Check if both parameters do not exceed half the max string length, because | 1741   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 
| 1742   // exceptionally long strings should be handled in the runtime. Unfortunately | 1742   if (String::kMaxLength != Smi::kMaxValue) { | 
| 1743   // we cannot actually check whether the combined length of both strings | 1743     IfBuilder if_nooverflow(this); | 
| 1744   // exceeds String::kMaxLength (because of unclear results from the | 1744     if_nooverflow.If<HCompareNumericAndBranch>( | 
| 1745   // representation inference phase), so we use a pessimistic approach here | 1745         length, Add<HConstant>(String::kMaxLength), Token::LTE); | 
| 1746   // instead, checking that the length of either substring does not exceed half | 1746     if_nooverflow.Then(); | 
| 1747   // of String::kMaxLength. | 1747     if_nooverflow.ElseDeopt("String length exceeds limit"); | 
| 1748   HConstant* max_length = Add<HConstant>(String::kMaxLength / 2); | 1748   } | 
| 1749   IfBuilder if_nooverflow(this); | 1749 | 
| 1750   if_nooverflow.If<HCompareNumericAndBranch>( | 1750   // Determine the string instance types. | 
| 1751       left_length, max_length, Token::LTE); | 1751   HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | 
| 1752   if_nooverflow.AndIf<HCompareNumericAndBranch>( | 1752       Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | 
| 1753       right_length, max_length, Token::LTE); | 1753       HObjectAccess::ForMapInstanceType()); | 
| 1754   if_nooverflow.Then(); | 1754   HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | 
|  | 1755       Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | 
|  | 1756       HObjectAccess::ForMapInstanceType()); | 
|  | 1757 | 
|  | 1758   // Compute difference of instance types. | 
|  | 1759   HValue* xored_instance_types = AddUncasted<HBitwise>( | 
|  | 1760       Token::BIT_XOR, left_instance_type, right_instance_type); | 
|  | 1761 | 
|  | 1762   // Check if we should create a cons string. | 
|  | 1763   IfBuilder if_createcons(this); | 
|  | 1764   if_createcons.If<HCompareNumericAndBranch>( | 
|  | 1765       length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 
|  | 1766   if_createcons.Then(); | 
| 1755   { | 1767   { | 
| 1756     // Determine the string instance types. | 1768     // Allocate the cons string object. HAllocate does not care whether we | 
| 1757     HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | 1769     // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 
| 1758         Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | 1770     // CONS_STRING_TYPE here. Below we decide whether the cons string is | 
| 1759         HObjectAccess::ForMapInstanceType()); | 1771     // one-byte or two-byte and set the appropriate map. | 
| 1760     HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | 1772     HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | 
| 1761         Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | 1773                                        HType::String(), pretenure_flag, | 
| 1762         HObjectAccess::ForMapInstanceType()); | 1774                                        CONS_STRING_TYPE); | 
| 1763 | 1775 | 
| 1764     // Compute difference of instance types. | 1776     // Compute the intersection of instance types. | 
| 1765     HValue* xored_instance_types = AddUncasted<HBitwise>( | 1777     HValue* anded_instance_types = AddUncasted<HBitwise>( | 
| 1766         Token::BIT_XOR, left_instance_type, right_instance_type); | 1778         Token::BIT_AND, left_instance_type, right_instance_type); | 
| 1767 | 1779 | 
| 1768     // Compute the length of the resulting string. | 1780     // We create a one-byte cons string if | 
| 1769     HValue* length = AddUncasted<HAdd>(left_length, right_length); | 1781     // 1. both strings are one-byte, or | 
| 1770 | 1782     // 2. at least one of the strings is two-byte, but happens to contain only | 
| 1771     // Check if we should create a cons string. | 1783     //    one-byte characters. | 
| 1772     IfBuilder if_createcons(this); | 1784     // To do this, we check | 
| 1773     if_createcons.If<HCompareNumericAndBranch>( | 1785     // 1. if both strings are one-byte, or if the one-byte data hint is set in | 
| 1774         length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 1786     //    both strings, or | 
| 1775     if_createcons.Then(); | 1787     // 2. if one of the strings has the one-byte data hint set and the other | 
| 1776     { | 1788     //    string is one-byte. | 
| 1777       // Allocate the cons string object. HAllocate does not care whether we | 1789     IfBuilder if_onebyte(this); | 
| 1778       // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 1790     STATIC_ASSERT(kOneByteStringTag != 0); | 
| 1779       // CONS_STRING_TYPE here. Below we decide whether the cons string is | 1791     STATIC_ASSERT(kOneByteDataHintMask != 0); | 
| 1780       // one-byte or two-byte and set the appropriate map. | 1792     if_onebyte.If<HCompareNumericAndBranch>( | 
| 1781       HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | 1793         AddUncasted<HBitwise>( | 
| 1782                                          HType::String(), pretenure_flag, | 1794             Token::BIT_AND, anded_instance_types, | 
| 1783                                          CONS_STRING_TYPE); | 1795             Add<HConstant>(static_cast<int32_t>( | 
| 1784 | 1796                     kStringEncodingMask | kOneByteDataHintMask))), | 
| 1785       // Compute the intersection of instance types. | 1797         graph()->GetConstant0(), Token::NE); | 
| 1786       HValue* anded_instance_types = AddUncasted<HBitwise>( | 1798     if_onebyte.Or(); | 
| 1787           Token::BIT_AND, left_instance_type, right_instance_type); | 1799     STATIC_ASSERT(kOneByteStringTag != 0 && | 
| 1788 | 1800                   kOneByteDataHintTag != 0 && | 
| 1789       // We create a one-byte cons string if | 1801                   kOneByteDataHintTag != kOneByteStringTag); | 
| 1790       // 1. both strings are one-byte, or | 1802     if_onebyte.If<HCompareNumericAndBranch>( | 
| 1791       // 2. at least one of the strings is two-byte, but happens to contain only | 1803         AddUncasted<HBitwise>( | 
| 1792       //    one-byte characters. | 1804             Token::BIT_AND, xored_instance_types, | 
| 1793       // To do this, we check | 1805             Add<HConstant>(static_cast<int32_t>( | 
| 1794       // 1. if both strings are one-byte, or if the one-byte data hint is set in | 1806                     kOneByteStringTag | kOneByteDataHintTag))), | 
| 1795       //    both strings, or | 1807         Add<HConstant>(static_cast<int32_t>( | 
| 1796       // 2. if one of the strings has the one-byte data hint set and the other | 1808                 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | 
| 1797       //    string is one-byte. | 1809     if_onebyte.Then(); | 
|  | 1810     { | 
|  | 1811       // We can safely skip the write barrier for storing the map here. | 
|  | 1812       Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | 
|  | 1813       AddStoreMapConstantNoWriteBarrier(string, map); | 
|  | 1814     } | 
|  | 1815     if_onebyte.Else(); | 
|  | 1816     { | 
|  | 1817       // We can safely skip the write barrier for storing the map here. | 
|  | 1818       Handle<Map> map = isolate()->factory()->cons_string_map(); | 
|  | 1819       AddStoreMapConstantNoWriteBarrier(string, map); | 
|  | 1820     } | 
|  | 1821     if_onebyte.End(); | 
|  | 1822 | 
|  | 1823     // Initialize the cons string fields. | 
|  | 1824     Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | 
|  | 1825                           Add<HConstant>(String::kEmptyHashField)); | 
|  | 1826     Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); | 
|  | 1827     Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | 
|  | 1828     Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | 
|  | 1829                           right); | 
|  | 1830 | 
|  | 1831     // Count the native string addition. | 
|  | 1832     AddIncrementCounter(isolate()->counters()->string_add_native()); | 
|  | 1833 | 
|  | 1834     // Cons string is result. | 
|  | 1835     Push(string); | 
|  | 1836   } | 
|  | 1837   if_createcons.Else(); | 
|  | 1838   { | 
|  | 1839     // Compute union of instance types. | 
|  | 1840     HValue* ored_instance_types = AddUncasted<HBitwise>( | 
|  | 1841         Token::BIT_OR, left_instance_type, right_instance_type); | 
|  | 1842 | 
|  | 1843     // Check if both strings have the same encoding and both are | 
|  | 1844     // sequential. | 
|  | 1845     IfBuilder if_sameencodingandsequential(this); | 
|  | 1846     if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 
|  | 1847         AddUncasted<HBitwise>( | 
|  | 1848             Token::BIT_AND, xored_instance_types, | 
|  | 1849             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 
|  | 1850         graph()->GetConstant0(), Token::EQ); | 
|  | 1851     if_sameencodingandsequential.And(); | 
|  | 1852     STATIC_ASSERT(kSeqStringTag == 0); | 
|  | 1853     if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 
|  | 1854         AddUncasted<HBitwise>( | 
|  | 1855             Token::BIT_AND, ored_instance_types, | 
|  | 1856             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), | 
|  | 1857         graph()->GetConstant0(), Token::EQ); | 
|  | 1858     if_sameencodingandsequential.Then(); | 
|  | 1859     { | 
|  | 1860       // Check if the result is a one-byte string. | 
| 1798       IfBuilder if_onebyte(this); | 1861       IfBuilder if_onebyte(this); | 
| 1799       STATIC_ASSERT(kOneByteStringTag != 0); | 1862       STATIC_ASSERT(kOneByteStringTag != 0); | 
| 1800       STATIC_ASSERT(kOneByteDataHintMask != 0); |  | 
| 1801       if_onebyte.If<HCompareNumericAndBranch>( | 1863       if_onebyte.If<HCompareNumericAndBranch>( | 
| 1802           AddUncasted<HBitwise>( | 1864           AddUncasted<HBitwise>( | 
| 1803               Token::BIT_AND, anded_instance_types, | 1865               Token::BIT_AND, ored_instance_types, | 
| 1804               Add<HConstant>(static_cast<int32_t>( | 1866               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 
| 1805                       kStringEncodingMask | kOneByteDataHintMask))), |  | 
| 1806           graph()->GetConstant0(), Token::NE); | 1867           graph()->GetConstant0(), Token::NE); | 
| 1807       if_onebyte.Or(); |  | 
| 1808       STATIC_ASSERT(kOneByteStringTag != 0 && |  | 
| 1809                     kOneByteDataHintTag != 0 && |  | 
| 1810                     kOneByteDataHintTag != kOneByteStringTag); |  | 
| 1811       if_onebyte.If<HCompareNumericAndBranch>( |  | 
| 1812           AddUncasted<HBitwise>( |  | 
| 1813               Token::BIT_AND, xored_instance_types, |  | 
| 1814               Add<HConstant>(static_cast<int32_t>( |  | 
| 1815                       kOneByteStringTag | kOneByteDataHintTag))), |  | 
| 1816           Add<HConstant>(static_cast<int32_t>( |  | 
| 1817                   kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); |  | 
| 1818       if_onebyte.Then(); | 1868       if_onebyte.Then(); | 
| 1819       { | 1869       { | 
| 1820         // We can safely skip the write barrier for storing the map here. | 1870         // Calculate the number of bytes needed for the characters in the | 
| 1821         Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | 1871         // string while observing object alignment. | 
|  | 1872         HValue* size = BuildSeqStringSizeFor( | 
|  | 1873             length, String::ONE_BYTE_ENCODING); | 
|  | 1874 | 
|  | 1875         // Allocate the ASCII string object. | 
|  | 1876         Handle<Map> map = isolate()->factory()->ascii_string_map(); | 
|  | 1877         HAllocate* string = Add<HAllocate>(size, HType::String(), | 
|  | 1878                                            pretenure_flag, ASCII_STRING_TYPE); | 
|  | 1879         string->set_known_initial_map(map); | 
|  | 1880 | 
|  | 1881         // We can safely skip the write barrier for storing map here. | 
| 1822         AddStoreMapConstantNoWriteBarrier(string, map); | 1882         AddStoreMapConstantNoWriteBarrier(string, map); | 
|  | 1883 | 
|  | 1884         // Length must be stored into the string before we copy characters to | 
|  | 1885         // make debug verification code happy. | 
|  | 1886         Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | 
|  | 1887                               length); | 
|  | 1888 | 
|  | 1889         // Copy bytes from the left string. | 
|  | 1890         BuildCopySeqStringChars( | 
|  | 1891             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | 
|  | 1892             string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | 
|  | 1893             left_length); | 
|  | 1894 | 
|  | 1895         // Copy bytes from the right string. | 
|  | 1896         BuildCopySeqStringChars( | 
|  | 1897             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | 
|  | 1898             string, left_length, String::ONE_BYTE_ENCODING, | 
|  | 1899             right_length); | 
|  | 1900 | 
|  | 1901         // Count the native string addition. | 
|  | 1902         AddIncrementCounter(isolate()->counters()->string_add_native()); | 
|  | 1903 | 
|  | 1904         // Return the string. | 
|  | 1905         Push(string); | 
| 1823       } | 1906       } | 
| 1824       if_onebyte.Else(); | 1907       if_onebyte.Else(); | 
| 1825       { | 1908       { | 
| 1826         // We can safely skip the write barrier for storing the map here. | 1909         // Calculate the number of bytes needed for the characters in the | 
| 1827         Handle<Map> map = isolate()->factory()->cons_string_map(); | 1910         // string while observing object alignment. | 
|  | 1911         HValue* size = BuildSeqStringSizeFor( | 
|  | 1912             length, String::TWO_BYTE_ENCODING); | 
|  | 1913 | 
|  | 1914         // Allocate the two-byte string object. | 
|  | 1915         Handle<Map> map = isolate()->factory()->string_map(); | 
|  | 1916         HAllocate* string = Add<HAllocate>(size, HType::String(), | 
|  | 1917                                            pretenure_flag, STRING_TYPE); | 
|  | 1918         string->set_known_initial_map(map); | 
|  | 1919 | 
|  | 1920         // We can safely skip the write barrier for storing map here. | 
| 1828         AddStoreMapConstantNoWriteBarrier(string, map); | 1921         AddStoreMapConstantNoWriteBarrier(string, map); | 
|  | 1922 | 
|  | 1923         // Length must be stored into the string before we copy characters to | 
|  | 1924         // make debug verification code happy. | 
|  | 1925         Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | 
|  | 1926                               length); | 
|  | 1927 | 
|  | 1928         // Copy bytes from the left string. | 
|  | 1929         BuildCopySeqStringChars( | 
|  | 1930             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 
|  | 1931             string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 
|  | 1932             left_length); | 
|  | 1933 | 
|  | 1934         // Copy bytes from the right string. | 
|  | 1935         BuildCopySeqStringChars( | 
|  | 1936             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | 
|  | 1937             string, left_length, String::TWO_BYTE_ENCODING, | 
|  | 1938             right_length); | 
|  | 1939 | 
|  | 1940         // Return the string. | 
|  | 1941         Push(string); | 
| 1829       } | 1942       } | 
| 1830       if_onebyte.End(); | 1943       if_onebyte.End(); | 
| 1831 | 1944 | 
| 1832       // Initialize the cons string fields. | 1945       // Initialize the (common) string fields. | 
|  | 1946       HValue* string = Pop(); | 
| 1833       Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | 1947       Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | 
| 1834                             Add<HConstant>(String::kEmptyHashField)); | 1948                             Add<HConstant>(String::kEmptyHashField)); | 
| 1835       Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); | 1949 | 
| 1836       Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | 1950       // Count the native string addition. | 
| 1837       Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | 1951       AddIncrementCounter(isolate()->counters()->string_add_native()); | 
| 1838                             right); | 1952 | 
| 1839 |  | 
| 1840       // Cons string is result. |  | 
| 1841       Push(string); | 1953       Push(string); | 
| 1842     } | 1954     } | 
| 1843     if_createcons.Else(); | 1955     if_sameencodingandsequential.Else(); | 
| 1844     { | 1956     { | 
| 1845       // Compute union of instance types. | 1957       // Fallback to the runtime to add the two strings. | 
| 1846       HValue* ored_instance_types = AddUncasted<HBitwise>( | 1958       Add<HPushArgument>(left); | 
| 1847           Token::BIT_OR, left_instance_type, right_instance_type); | 1959       Add<HPushArgument>(right); | 
| 1848 | 1960       Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | 
| 1849       // Check if both strings have the same encoding and both are | 1961                              Runtime::FunctionForId(Runtime::kStringAdd), | 
| 1850       // sequential. | 1962                              2)); | 
| 1851       IfBuilder if_sameencodingandsequential(this); | 1963     } | 
| 1852       if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1964     if_sameencodingandsequential.End(); | 
| 1853           AddUncasted<HBitwise>( |  | 
| 1854               Token::BIT_AND, xored_instance_types, |  | 
| 1855               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |  | 
| 1856           graph()->GetConstant0(), Token::EQ); |  | 
| 1857       if_sameencodingandsequential.And(); |  | 
| 1858       STATIC_ASSERT(kSeqStringTag == 0); |  | 
| 1859       if_sameencodingandsequential.If<HCompareNumericAndBranch>( |  | 
| 1860           AddUncasted<HBitwise>( |  | 
| 1861               Token::BIT_AND, ored_instance_types, |  | 
| 1862               Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |  | 
| 1863           graph()->GetConstant0(), Token::EQ); |  | 
| 1864       if_sameencodingandsequential.Then(); |  | 
| 1865       { |  | 
| 1866         // Check if the result is a one-byte string. |  | 
| 1867         IfBuilder if_onebyte(this); |  | 
| 1868         STATIC_ASSERT(kOneByteStringTag != 0); |  | 
| 1869         if_onebyte.If<HCompareNumericAndBranch>( |  | 
| 1870             AddUncasted<HBitwise>( |  | 
| 1871                 Token::BIT_AND, ored_instance_types, |  | 
| 1872                 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |  | 
| 1873             graph()->GetConstant0(), Token::NE); |  | 
| 1874         if_onebyte.Then(); |  | 
| 1875         { |  | 
| 1876           // Calculate the number of bytes needed for the characters in the |  | 
| 1877           // string while observing object alignment. |  | 
| 1878           HValue* size = BuildSeqStringSizeFor( |  | 
| 1879               length, String::ONE_BYTE_ENCODING); |  | 
| 1880 |  | 
| 1881           // Allocate the ASCII string object. |  | 
| 1882           Handle<Map> map = isolate()->factory()->ascii_string_map(); |  | 
| 1883           HAllocate* string = Add<HAllocate>(size, HType::String(), |  | 
| 1884                                              pretenure_flag, ASCII_STRING_TYPE); |  | 
| 1885           string->set_known_initial_map(map); |  | 
| 1886 |  | 
| 1887           // We can safely skip the write barrier for storing map here. |  | 
| 1888           AddStoreMapConstantNoWriteBarrier(string, map); |  | 
| 1889 |  | 
| 1890           // Length must be stored into the string before we copy characters to |  | 
| 1891           // make debug verification code happy. |  | 
| 1892           Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), |  | 
| 1893                                 length); |  | 
| 1894 |  | 
| 1895           // Copy bytes from the left string. |  | 
| 1896           BuildCopySeqStringChars( |  | 
| 1897               left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |  | 
| 1898               string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |  | 
| 1899               left_length); |  | 
| 1900 |  | 
| 1901           // Copy bytes from the right string. |  | 
| 1902           BuildCopySeqStringChars( |  | 
| 1903               right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, |  | 
| 1904               string, left_length, String::ONE_BYTE_ENCODING, |  | 
| 1905               right_length); |  | 
| 1906 |  | 
| 1907           // Return the string. |  | 
| 1908           Push(string); |  | 
| 1909         } |  | 
| 1910         if_onebyte.Else(); |  | 
| 1911         { |  | 
| 1912           // Calculate the number of bytes needed for the characters in the |  | 
| 1913           // string while observing object alignment. |  | 
| 1914           HValue* size = BuildSeqStringSizeFor( |  | 
| 1915               length, String::TWO_BYTE_ENCODING); |  | 
| 1916 |  | 
| 1917           // Allocate the two-byte string object. |  | 
| 1918           Handle<Map> map = isolate()->factory()->string_map(); |  | 
| 1919           HAllocate* string = Add<HAllocate>(size, HType::String(), |  | 
| 1920                                              pretenure_flag, STRING_TYPE); |  | 
| 1921           string->set_known_initial_map(map); |  | 
| 1922 |  | 
| 1923           // We can safely skip the write barrier for storing map here. |  | 
| 1924           AddStoreMapConstantNoWriteBarrier(string, map); |  | 
| 1925 |  | 
| 1926           // Length must be stored into the string before we copy characters to |  | 
| 1927           // make debug verification code happy. |  | 
| 1928           Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), |  | 
| 1929                                 length); |  | 
| 1930 |  | 
| 1931           // Copy bytes from the left string. |  | 
| 1932           BuildCopySeqStringChars( |  | 
| 1933               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |  | 
| 1934               string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |  | 
| 1935               left_length); |  | 
| 1936 |  | 
| 1937           // Copy bytes from the right string. |  | 
| 1938           BuildCopySeqStringChars( |  | 
| 1939               right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |  | 
| 1940               string, left_length, String::TWO_BYTE_ENCODING, |  | 
| 1941               right_length); |  | 
| 1942 |  | 
| 1943           // Return the string. |  | 
| 1944           Push(string); |  | 
| 1945         } |  | 
| 1946         if_onebyte.End(); |  | 
| 1947 |  | 
| 1948         // Initialize the (common) string fields. |  | 
| 1949         HValue* string = Pop(); |  | 
| 1950         Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), |  | 
| 1951                               Add<HConstant>(String::kEmptyHashField)); |  | 
| 1952         Push(string); |  | 
| 1953       } |  | 
| 1954       if_sameencodingandsequential.JoinContinuation(&handled); |  | 
| 1955     } |  | 
| 1956     if_createcons.JoinContinuation(&handled); |  | 
| 1957   } | 1965   } | 
| 1958   if_nooverflow.JoinContinuation(&handled); | 1966   if_createcons.End(); | 
| 1959 |  | 
| 1960   // Check if the strings were concatenated successfully, otherwise fallback to |  | 
| 1961   // add the strings in the runtime. |  | 
| 1962   IfBuilder if_handled(this, &handled); |  | 
| 1963   if_handled.Then(); |  | 
| 1964   { |  | 
| 1965     // Count the native string addition. |  | 
| 1966     AddIncrementCounter(isolate()->counters()->string_add_native()); |  | 
| 1967   } |  | 
| 1968   if_handled.Else(); |  | 
| 1969   { |  | 
| 1970     // Fallback to the runtime to add the two strings. |  | 
| 1971     Add<HPushArgument>(left); |  | 
| 1972     Add<HPushArgument>(right); |  | 
| 1973     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), |  | 
| 1974                            Runtime::FunctionForId(Runtime::kStringAdd), |  | 
| 1975                            2)); |  | 
| 1976   } |  | 
| 1977   if_handled.End(); |  | 
| 1978 | 1967 | 
| 1979   return Pop(); | 1968   return Pop(); | 
| 1980 } | 1969 } | 
| 1981 | 1970 | 
| 1982 | 1971 | 
| 1983 HValue* HGraphBuilder::BuildStringAdd(HValue* left, | 1972 HValue* HGraphBuilder::BuildStringAdd(HValue* left, | 
| 1984                                       HValue* right, | 1973                                       HValue* right, | 
| 1985                                       PretenureFlag pretenure_flag) { | 1974                                       PretenureFlag pretenure_flag) { | 
| 1986   // Determine the string lengths. | 1975   // Determine the string lengths. | 
| 1987   HValue* left_length = Add<HLoadNamedField>( | 1976   HValue* left_length = Add<HLoadNamedField>( | 
| (...skipping 8677 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 10665   if (ShouldProduceTraceOutput()) { | 10654   if (ShouldProduceTraceOutput()) { | 
| 10666     isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10655     isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 
| 10667   } | 10656   } | 
| 10668 | 10657 | 
| 10669 #ifdef DEBUG | 10658 #ifdef DEBUG | 
| 10670   graph_->Verify(false);  // No full verify. | 10659   graph_->Verify(false);  // No full verify. | 
| 10671 #endif | 10660 #endif | 
| 10672 } | 10661 } | 
| 10673 | 10662 | 
| 10674 } }  // namespace v8::internal | 10663 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|