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

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: REBASE Created 6 years, 11 months 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1675 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698