Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: src/hydrogen.cc

Issue 106453003: Allocation site support for monomorphic StringAdds in BinaryOps. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Michael's comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« src/arm/code-stubs-arm.cc ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698