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

Side by Side Diff: src/hydrogen.cc

Issue 157503002: A64: Synchronize with r18444. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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-check-elimination.cc » ('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 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 if (object->type().IsJSObject()) return object; 1291 if (object->type().IsJSObject()) return object;
1292 return Add<HWrapReceiver>(object, function); 1292 return Add<HWrapReceiver>(object, function);
1293 } 1293 }
1294 1294
1295 1295
1296 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1296 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1297 HValue* elements, 1297 HValue* elements,
1298 ElementsKind kind, 1298 ElementsKind kind,
1299 HValue* length, 1299 HValue* length,
1300 HValue* key, 1300 HValue* key,
1301 bool is_js_array) { 1301 bool is_js_array,
1302 bool is_store) {
1302 IfBuilder length_checker(this); 1303 IfBuilder length_checker(this);
1303 1304
1304 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; 1305 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1305 length_checker.If<HCompareNumericAndBranch>(key, length, token); 1306 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1306 1307
1307 length_checker.Then(); 1308 length_checker.Then();
1308 1309
1309 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1310 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1310 1311
1311 IfBuilder capacity_checker(this); 1312 IfBuilder capacity_checker(this);
(...skipping 22 matching lines...) Expand all
1334 capacity_checker.End(); 1335 capacity_checker.End();
1335 1336
1336 if (is_js_array) { 1337 if (is_js_array) {
1337 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); 1338 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1338 new_length->ClearFlag(HValue::kCanOverflow); 1339 new_length->ClearFlag(HValue::kCanOverflow);
1339 1340
1340 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), 1341 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1341 new_length); 1342 new_length);
1342 } 1343 }
1343 1344
1345 if (is_store && kind == FAST_SMI_ELEMENTS) {
1346 HValue* checked_elements = environment()->Top();
1347
1348 // Write zero to ensure that the new element is initialized with some smi.
1349 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1350 }
1351
1344 length_checker.Else(); 1352 length_checker.Else();
1345 Add<HBoundsCheck>(key, length); 1353 Add<HBoundsCheck>(key, length);
1346 1354
1347 environment()->Push(elements); 1355 environment()->Push(elements);
1348 length_checker.End(); 1356 length_checker.End();
1349 1357
1350 return environment()->Pop(); 1358 return environment()->Pop();
1351 } 1359 }
1352 1360
1353 1361
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 isolate()->factory()->empty_string(), 1688 isolate()->factory()->empty_string(),
1681 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), 1689 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1682 1)); 1690 1));
1683 } 1691 }
1684 if_found.End(); 1692 if_found.End();
1685 1693
1686 return Pop(); 1694 return Pop();
1687 } 1695 }
1688 1696
1689 1697
1690 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, 1698 HAllocate* HGraphBuilder::BuildAllocate(
1691 String::Encoding encoding) { 1699 HValue* object_size,
1692 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); 1700 HType type,
1693 HValue* size = length; 1701 InstanceType instance_type,
1694 if (encoding == String::TWO_BYTE_ENCODING) { 1702 HAllocationMode allocation_mode) {
1695 size = AddUncasted<HShl>(length, graph()->GetConstant1()); 1703 // Compute the effective allocation size.
1704 HValue* size = object_size;
1705 if (allocation_mode.CreateAllocationMementos()) {
1706 size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
1696 size->ClearFlag(HValue::kCanOverflow); 1707 size->ClearFlag(HValue::kCanOverflow);
1697 size->SetFlag(HValue::kUint32);
1698 } 1708 }
1699 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( 1709
1700 SeqString::kHeaderSize + kObjectAlignmentMask))); 1710 // Perform the actual allocation.
1701 size->ClearFlag(HValue::kCanOverflow); 1711 HAllocate* object = Add<HAllocate>(
1702 size = AddUncasted<HBitwise>( 1712 size, type, allocation_mode.GetPretenureMode(),
1703 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( 1713 instance_type, allocation_mode.feedback_site());
1704 ~kObjectAlignmentMask))); 1714
1705 return size; 1715 // Setup the allocation memento.
1716 if (allocation_mode.CreateAllocationMementos()) {
1717 BuildCreateAllocationMemento(
1718 object, object_size, allocation_mode.current_site());
1719 }
1720
1721 return object;
1706 } 1722 }
1707 1723
1708 1724
1725 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
1726 HValue* right_length) {
1727 // Compute the combined string length. If the result is larger than the max
1728 // supported string length, we bailout to the runtime. This is done implicitly
1729 // when converting the result back to a smi in case the max string length
1730 // equals the max smi value. Otherwise, for platforms with 32-bit smis, we do
1731 HValue* length = AddUncasted<HAdd>(left_length, right_length);
1732 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
1733 if (String::kMaxLength != Smi::kMaxValue) {
1734 IfBuilder if_nooverflow(this);
1735 if_nooverflow.If<HCompareNumericAndBranch>(
1736 length, Add<HConstant>(String::kMaxLength), Token::LTE);
1737 if_nooverflow.Then();
1738 if_nooverflow.ElseDeopt("String length exceeds limit");
1739 }
1740 return length;
1741 }
1742
1743
1744 HValue* HGraphBuilder::BuildCreateConsString(
1745 HValue* length,
1746 HValue* left,
1747 HValue* right,
1748 HAllocationMode allocation_mode) {
1749 // Determine the string instance types.
1750 HInstruction* left_instance_type = AddLoadStringInstanceType(left);
1751 HInstruction* right_instance_type = AddLoadStringInstanceType(right);
1752
1753 // Allocate the cons string object. HAllocate does not care whether we
1754 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
1755 // CONS_STRING_TYPE here. Below we decide whether the cons string is
1756 // one-byte or two-byte and set the appropriate map.
1757 ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
1758 CONS_ASCII_STRING_TYPE));
1759 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
1760 HType::String(), CONS_STRING_TYPE,
1761 allocation_mode);
1762
1763 // Compute intersection and difference of instance types.
1764 HValue* anded_instance_types = AddUncasted<HBitwise>(
1765 Token::BIT_AND, left_instance_type, right_instance_type);
1766 HValue* xored_instance_types = AddUncasted<HBitwise>(
1767 Token::BIT_XOR, left_instance_type, right_instance_type);
1768
1769 // We create a one-byte cons string if
1770 // 1. both strings are one-byte, or
1771 // 2. at least one of the strings is two-byte, but happens to contain only
1772 // one-byte characters.
1773 // To do this, we check
1774 // 1. if both strings are one-byte, or if the one-byte data hint is set in
1775 // both strings, or
1776 // 2. if one of the strings has the one-byte data hint set and the other
1777 // string is one-byte.
1778 IfBuilder if_onebyte(this);
1779 STATIC_ASSERT(kOneByteStringTag != 0);
1780 STATIC_ASSERT(kOneByteDataHintMask != 0);
1781 if_onebyte.If<HCompareNumericAndBranch>(
1782 AddUncasted<HBitwise>(
1783 Token::BIT_AND, anded_instance_types,
1784 Add<HConstant>(static_cast<int32_t>(
1785 kStringEncodingMask | kOneByteDataHintMask))),
1786 graph()->GetConstant0(), Token::NE);
1787 if_onebyte.Or();
1788 STATIC_ASSERT(kOneByteStringTag != 0 &&
1789 kOneByteDataHintTag != 0 &&
1790 kOneByteDataHintTag != kOneByteStringTag);
1791 if_onebyte.If<HCompareNumericAndBranch>(
1792 AddUncasted<HBitwise>(
1793 Token::BIT_AND, xored_instance_types,
1794 Add<HConstant>(static_cast<int32_t>(
1795 kOneByteStringTag | kOneByteDataHintTag))),
1796 Add<HConstant>(static_cast<int32_t>(
1797 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
1798 if_onebyte.Then();
1799 {
1800 // We can safely skip the write barrier for storing the map here.
1801 Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
1802 AddStoreMapConstantNoWriteBarrier(result, map);
1803 }
1804 if_onebyte.Else();
1805 {
1806 // We can safely skip the write barrier for storing the map here.
1807 Handle<Map> map = isolate()->factory()->cons_string_map();
1808 AddStoreMapConstantNoWriteBarrier(result, map);
1809 }
1810 if_onebyte.End();
1811
1812 // Initialize the cons string fields.
1813 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
1814 Add<HConstant>(String::kEmptyHashField));
1815 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
1816 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
1817 Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
1818
1819 // Count the native string addition.
1820 AddIncrementCounter(isolate()->counters()->string_add_native());
1821
1822 return result;
1823 }
1824
1825
1709 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, 1826 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
1710 HValue* src_offset, 1827 HValue* src_offset,
1711 String::Encoding src_encoding, 1828 String::Encoding src_encoding,
1712 HValue* dst, 1829 HValue* dst,
1713 HValue* dst_offset, 1830 HValue* dst_offset,
1714 String::Encoding dst_encoding, 1831 String::Encoding dst_encoding,
1715 HValue* length) { 1832 HValue* length) {
1716 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || 1833 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING ||
1717 src_encoding == String::ONE_BYTE_ENCODING); 1834 src_encoding == String::ONE_BYTE_ENCODING);
1718 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); 1835 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
1719 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); 1836 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
1720 { 1837 {
1721 HValue* src_index = AddUncasted<HAdd>(src_offset, index); 1838 HValue* src_index = AddUncasted<HAdd>(src_offset, index);
1722 HValue* value = 1839 HValue* value =
1723 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); 1840 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
1724 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); 1841 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
1725 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); 1842 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
1726 } 1843 }
1727 loop.EndBody(); 1844 loop.EndBody();
1728 } 1845 }
1729 1846
1730 1847
1731 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, 1848 HValue* HGraphBuilder::BuildUncheckedStringAdd(
1732 HValue* right, 1849 HValue* left,
1733 PretenureFlag pretenure_flag) { 1850 HValue* right,
1851 HAllocationMode allocation_mode) {
1734 // Determine the string lengths. 1852 // Determine the string lengths.
1735 HValue* left_length = Add<HLoadNamedField>( 1853 HValue* left_length = AddLoadStringLength(left);
1736 left, HObjectAccess::ForStringLength()); 1854 HValue* right_length = AddLoadStringLength(right);
1737 HValue* right_length = Add<HLoadNamedField>(
1738 right, HObjectAccess::ForStringLength());
1739 1855
1740 // Compute the combined string length. If the result is larger than the max 1856 // Compute the combined string length.
1741 // supported string length, we bailout to the runtime. This is done implicitly 1857 HValue* length = BuildAddStringLengths(left_length, right_length);
1742 // when converting the result back to a smi in case the max string length 1858
1743 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do 1859 // Do some manual constant folding here.
1744 HValue* length = AddUncasted<HAdd>(left_length, right_length); 1860 if (left_length->IsConstant()) {
1745 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 1861 HConstant* c_left_length = HConstant::cast(left_length);
1746 if (String::kMaxLength != Smi::kMaxValue) { 1862 ASSERT_NE(0, c_left_length->Integer32Value());
1747 IfBuilder if_nooverflow(this); 1863 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
1748 if_nooverflow.If<HCompareNumericAndBranch>( 1864 // The right string contains at least one character.
1749 length, Add<HConstant>(String::kMaxLength), Token::LTE); 1865 return BuildCreateConsString(length, left, right, allocation_mode);
1750 if_nooverflow.Then(); 1866 }
1751 if_nooverflow.ElseDeopt("String length exceeds limit"); 1867 } else if (right_length->IsConstant()) {
1868 HConstant* c_right_length = HConstant::cast(right_length);
1869 ASSERT_NE(0, c_right_length->Integer32Value());
1870 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
1871 // The left string contains at least one character.
1872 return BuildCreateConsString(length, left, right, allocation_mode);
1873 }
1752 } 1874 }
1753 1875
1754 // Determine the string instance types.
1755 HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
1756 Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
1757 HObjectAccess::ForMapInstanceType());
1758 HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
1759 Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
1760 HObjectAccess::ForMapInstanceType());
1761
1762 // Compute difference of instance types.
1763 HValue* xored_instance_types = AddUncasted<HBitwise>(
1764 Token::BIT_XOR, left_instance_type, right_instance_type);
1765
1766 // Check if we should create a cons string. 1876 // Check if we should create a cons string.
1767 IfBuilder if_createcons(this); 1877 IfBuilder if_createcons(this);
1768 if_createcons.If<HCompareNumericAndBranch>( 1878 if_createcons.If<HCompareNumericAndBranch>(
1769 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); 1879 length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
1770 if_createcons.Then(); 1880 if_createcons.Then();
1771 { 1881 {
1772 // Allocate the cons string object. HAllocate does not care whether we 1882 // Create a cons string.
1773 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use 1883 Push(BuildCreateConsString(length, left, right, allocation_mode));
1774 // CONS_STRING_TYPE here. Below we decide whether the cons string is
1775 // one-byte or two-byte and set the appropriate map.
1776 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
1777 HType::String(), pretenure_flag,
1778 CONS_STRING_TYPE);
1779
1780 // Compute the intersection of instance types.
1781 HValue* anded_instance_types = AddUncasted<HBitwise>(
1782 Token::BIT_AND, left_instance_type, right_instance_type);
1783
1784 // We create a one-byte cons string if
1785 // 1. both strings are one-byte, or
1786 // 2. at least one of the strings is two-byte, but happens to contain only
1787 // one-byte characters.
1788 // To do this, we check
1789 // 1. if both strings are one-byte, or if the one-byte data hint is set in
1790 // both strings, or
1791 // 2. if one of the strings has the one-byte data hint set and the other
1792 // string is one-byte.
1793 IfBuilder if_onebyte(this);
1794 STATIC_ASSERT(kOneByteStringTag != 0);
1795 STATIC_ASSERT(kOneByteDataHintMask != 0);
1796 if_onebyte.If<HCompareNumericAndBranch>(
1797 AddUncasted<HBitwise>(
1798 Token::BIT_AND, anded_instance_types,
1799 Add<HConstant>(static_cast<int32_t>(
1800 kStringEncodingMask | kOneByteDataHintMask))),
1801 graph()->GetConstant0(), Token::NE);
1802 if_onebyte.Or();
1803 STATIC_ASSERT(kOneByteStringTag != 0 &&
1804 kOneByteDataHintTag != 0 &&
1805 kOneByteDataHintTag != kOneByteStringTag);
1806 if_onebyte.If<HCompareNumericAndBranch>(
1807 AddUncasted<HBitwise>(
1808 Token::BIT_AND, xored_instance_types,
1809 Add<HConstant>(static_cast<int32_t>(
1810 kOneByteStringTag | kOneByteDataHintTag))),
1811 Add<HConstant>(static_cast<int32_t>(
1812 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
1813 if_onebyte.Then();
1814 {
1815 // We can safely skip the write barrier for storing the map here.
1816 Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
1817 AddStoreMapConstantNoWriteBarrier(string, map);
1818 }
1819 if_onebyte.Else();
1820 {
1821 // We can safely skip the write barrier for storing the map here.
1822 Handle<Map> map = isolate()->factory()->cons_string_map();
1823 AddStoreMapConstantNoWriteBarrier(string, map);
1824 }
1825 if_onebyte.End();
1826
1827 // Initialize the cons string fields.
1828 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1829 Add<HConstant>(String::kEmptyHashField));
1830 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
1831 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
1832 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
1833 right);
1834
1835 // Count the native string addition.
1836 AddIncrementCounter(isolate()->counters()->string_add_native());
1837
1838 // Cons string is result.
1839 Push(string);
1840 } 1884 }
1841 if_createcons.Else(); 1885 if_createcons.Else();
1842 { 1886 {
1843 // Compute union of instance types. 1887 // Determine the string instance types.
1888 HValue* left_instance_type = AddLoadStringInstanceType(left);
1889 HValue* right_instance_type = AddLoadStringInstanceType(right);
1890
1891 // Compute union and difference of instance types.
1844 HValue* ored_instance_types = AddUncasted<HBitwise>( 1892 HValue* ored_instance_types = AddUncasted<HBitwise>(
1845 Token::BIT_OR, left_instance_type, right_instance_type); 1893 Token::BIT_OR, left_instance_type, right_instance_type);
1894 HValue* xored_instance_types = AddUncasted<HBitwise>(
1895 Token::BIT_XOR, left_instance_type, right_instance_type);
1846 1896
1847 // Check if both strings have the same encoding and both are 1897 // Check if both strings have the same encoding and both are
1848 // sequential. 1898 // sequential.
1849 IfBuilder if_sameencodingandsequential(this); 1899 IfBuilder if_sameencodingandsequential(this);
1850 if_sameencodingandsequential.If<HCompareNumericAndBranch>( 1900 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1851 AddUncasted<HBitwise>( 1901 AddUncasted<HBitwise>(
1852 Token::BIT_AND, xored_instance_types, 1902 Token::BIT_AND, xored_instance_types,
1853 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), 1903 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1854 graph()->GetConstant0(), Token::EQ); 1904 graph()->GetConstant0(), Token::EQ);
1855 if_sameencodingandsequential.And(); 1905 if_sameencodingandsequential.And();
1856 STATIC_ASSERT(kSeqStringTag == 0); 1906 STATIC_ASSERT(kSeqStringTag == 0);
1857 if_sameencodingandsequential.If<HCompareNumericAndBranch>( 1907 if_sameencodingandsequential.If<HCompareNumericAndBranch>(
1858 AddUncasted<HBitwise>( 1908 AddUncasted<HBitwise>(
1859 Token::BIT_AND, ored_instance_types, 1909 Token::BIT_AND, ored_instance_types,
1860 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), 1910 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
1861 graph()->GetConstant0(), Token::EQ); 1911 graph()->GetConstant0(), Token::EQ);
1862 if_sameencodingandsequential.Then(); 1912 if_sameencodingandsequential.Then();
1863 { 1913 {
1864 // Check if the result is a one-byte string. 1914 HConstant* string_map =
1915 Add<HConstant>(isolate()->factory()->string_map());
1916 HConstant* ascii_string_map =
1917 Add<HConstant>(isolate()->factory()->ascii_string_map());
1918
1919 // Determine map and size depending on whether result is one-byte string.
1865 IfBuilder if_onebyte(this); 1920 IfBuilder if_onebyte(this);
1866 STATIC_ASSERT(kOneByteStringTag != 0); 1921 STATIC_ASSERT(kOneByteStringTag != 0);
1867 if_onebyte.If<HCompareNumericAndBranch>( 1922 if_onebyte.If<HCompareNumericAndBranch>(
1868 AddUncasted<HBitwise>( 1923 AddUncasted<HBitwise>(
1869 Token::BIT_AND, ored_instance_types, 1924 Token::BIT_AND, ored_instance_types,
1870 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), 1925 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
1871 graph()->GetConstant0(), Token::NE); 1926 graph()->GetConstant0(), Token::NE);
1872 if_onebyte.Then(); 1927 if_onebyte.Then();
1873 { 1928 {
1874 // Calculate the number of bytes needed for the characters in the 1929 // Allocate sequential one-byte string object.
1875 // string while observing object alignment. 1930 Push(length);
1876 HValue* size = BuildSeqStringSizeFor( 1931 Push(ascii_string_map);
1877 length, String::ONE_BYTE_ENCODING);
1878
1879 // Allocate the ASCII string object.
1880 Handle<Map> map = isolate()->factory()->ascii_string_map();
1881 HAllocate* string = Add<HAllocate>(size, HType::String(),
1882 pretenure_flag, ASCII_STRING_TYPE);
1883 string->set_known_initial_map(map);
1884
1885 // We can safely skip the write barrier for storing map here.
1886 AddStoreMapConstantNoWriteBarrier(string, map);
1887
1888 // Length must be stored into the string before we copy characters to
1889 // make debug verification code happy.
1890 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1891 length);
1892
1893 // Copy bytes from the left string.
1894 BuildCopySeqStringChars(
1895 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1896 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1897 left_length);
1898
1899 // Copy bytes from the right string.
1900 BuildCopySeqStringChars(
1901 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1902 string, left_length, String::ONE_BYTE_ENCODING,
1903 right_length);
1904
1905 // Count the native string addition.
1906 AddIncrementCounter(isolate()->counters()->string_add_native());
1907
1908 // Return the string.
1909 Push(string);
1910 } 1932 }
1911 if_onebyte.Else(); 1933 if_onebyte.Else();
1912 { 1934 {
1913 // Calculate the number of bytes needed for the characters in the 1935 // Allocate sequential two-byte string object.
1914 // string while observing object alignment. 1936 HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
1915 HValue* size = BuildSeqStringSizeFor( 1937 size->ClearFlag(HValue::kCanOverflow);
1916 length, String::TWO_BYTE_ENCODING); 1938 size->SetFlag(HValue::kUint32);
1939 Push(size);
1940 Push(string_map);
1941 }
1942 if_onebyte.End();
1943 HValue* map = Pop();
1917 1944
1918 // Allocate the two-byte string object. 1945 // Calculate the number of bytes needed for the characters in the
1919 Handle<Map> map = isolate()->factory()->string_map(); 1946 // string while observing object alignment.
1920 HAllocate* string = Add<HAllocate>(size, HType::String(), 1947 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
1921 pretenure_flag, STRING_TYPE); 1948 HValue* size = Pop();
1922 string->set_known_initial_map(map); 1949 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
1950 SeqString::kHeaderSize + kObjectAlignmentMask)));
1951 size->ClearFlag(HValue::kCanOverflow);
1952 size = AddUncasted<HBitwise>(
1953 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
1954 ~kObjectAlignmentMask)));
1923 1955
1924 // We can safely skip the write barrier for storing map here. 1956 // Allocate the string object. HAllocate does not care whether we pass
1925 AddStoreMapConstantNoWriteBarrier(string, map); 1957 // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here.
1958 HAllocate* result = BuildAllocate(
1959 size, HType::String(), STRING_TYPE, allocation_mode);
1926 1960
1927 // Length must be stored into the string before we copy characters to 1961 // We can safely skip the write barrier for storing map here.
1928 // make debug verification code happy. 1962 AddStoreMapNoWriteBarrier(result, map);
1929 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
1930 length);
1931 1963
1932 // Copy bytes from the left string. 1964 // Initialize the string fields.
1965 Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
1966 Add<HConstant>(String::kEmptyHashField));
1967 Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
1968
1969 // Copy characters to the result string.
1970 IfBuilder if_twobyte(this);
1971 if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
1972 if_twobyte.Then();
1973 {
1974 // Copy characters from the left string.
1933 BuildCopySeqStringChars( 1975 BuildCopySeqStringChars(
1934 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, 1976 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1935 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, 1977 result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1936 left_length); 1978 left_length);
1937 1979
1938 // Copy bytes from the right string. 1980 // Copy characters from the right string.
1939 BuildCopySeqStringChars( 1981 BuildCopySeqStringChars(
1940 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, 1982 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
1941 string, left_length, String::TWO_BYTE_ENCODING, 1983 result, left_length, String::TWO_BYTE_ENCODING,
1942 right_length); 1984 right_length);
1985 }
1986 if_twobyte.Else();
1987 {
1988 // Copy characters from the left string.
1989 BuildCopySeqStringChars(
1990 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1991 result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1992 left_length);
1943 1993
1944 // Return the string. 1994 // Copy characters from the right string.
1945 Push(string); 1995 BuildCopySeqStringChars(
1996 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
1997 result, left_length, String::ONE_BYTE_ENCODING,
1998 right_length);
1946 } 1999 }
1947 if_onebyte.End(); 2000 if_twobyte.End();
1948
1949 // Initialize the (common) string fields.
1950 HValue* string = Pop();
1951 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
1952 Add<HConstant>(String::kEmptyHashField));
1953 2001
1954 // Count the native string addition. 2002 // Count the native string addition.
1955 AddIncrementCounter(isolate()->counters()->string_add_native()); 2003 AddIncrementCounter(isolate()->counters()->string_add_native());
1956 2004
1957 Push(string); 2005 // Return the sequential string.
2006 Push(result);
1958 } 2007 }
1959 if_sameencodingandsequential.Else(); 2008 if_sameencodingandsequential.Else();
1960 { 2009 {
1961 // Fallback to the runtime to add the two strings. 2010 // Fallback to the runtime to add the two strings.
1962 Add<HPushArgument>(left); 2011 Add<HPushArgument>(left);
1963 Add<HPushArgument>(right); 2012 Add<HPushArgument>(right);
1964 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), 2013 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1965 Runtime::FunctionForId(Runtime::kStringAdd), 2014 Runtime::FunctionForId(Runtime::kStringAdd),
1966 2)); 2015 2));
1967 } 2016 }
1968 if_sameencodingandsequential.End(); 2017 if_sameencodingandsequential.End();
1969 } 2018 }
1970 if_createcons.End(); 2019 if_createcons.End();
1971 2020
1972 return Pop(); 2021 return Pop();
1973 } 2022 }
1974 2023
1975 2024
1976 HValue* HGraphBuilder::BuildStringAdd(HValue* left, 2025 HValue* HGraphBuilder::BuildStringAdd(
1977 HValue* right, 2026 HValue* left,
1978 PretenureFlag pretenure_flag) { 2027 HValue* right,
1979 // Determine the string lengths. 2028 HAllocationMode allocation_mode) {
1980 HValue* left_length = Add<HLoadNamedField>( 2029 NoObservableSideEffectsScope no_effects(this);
1981 left, HObjectAccess::ForStringLength()); 2030
1982 HValue* right_length = Add<HLoadNamedField>( 2031 // Determine string lengths.
1983 right, HObjectAccess::ForStringLength()); 2032 HValue* left_length = AddLoadStringLength(left);
2033 HValue* right_length = AddLoadStringLength(right);
1984 2034
1985 // Check if left string is empty. 2035 // Check if left string is empty.
1986 IfBuilder if_leftisempty(this); 2036 IfBuilder if_leftempty(this);
1987 if_leftisempty.If<HCompareNumericAndBranch>( 2037 if_leftempty.If<HCompareNumericAndBranch>(
1988 left_length, graph()->GetConstant0(), Token::EQ); 2038 left_length, graph()->GetConstant0(), Token::EQ);
1989 if_leftisempty.Then(); 2039 if_leftempty.Then();
1990 { 2040 {
1991 // Count the native string addition. 2041 // Count the native string addition.
1992 AddIncrementCounter(isolate()->counters()->string_add_native()); 2042 AddIncrementCounter(isolate()->counters()->string_add_native());
1993 2043
1994 // Just return the right string. 2044 // Just return the right string.
1995 Push(right); 2045 Push(right);
1996 } 2046 }
1997 if_leftisempty.Else(); 2047 if_leftempty.Else();
1998 { 2048 {
1999 // Check if right string is empty. 2049 // Check if right string is empty.
2000 IfBuilder if_rightisempty(this); 2050 IfBuilder if_rightempty(this);
2001 if_rightisempty.If<HCompareNumericAndBranch>( 2051 if_rightempty.If<HCompareNumericAndBranch>(
2002 right_length, graph()->GetConstant0(), Token::EQ); 2052 right_length, graph()->GetConstant0(), Token::EQ);
2003 if_rightisempty.Then(); 2053 if_rightempty.Then();
2004 { 2054 {
2005 // Count the native string addition. 2055 // Count the native string addition.
2006 AddIncrementCounter(isolate()->counters()->string_add_native()); 2056 AddIncrementCounter(isolate()->counters()->string_add_native());
2007 2057
2008 // Just return the left string. 2058 // Just return the left string.
2009 Push(left); 2059 Push(left);
2010 } 2060 }
2011 if_rightisempty.Else(); 2061 if_rightempty.Else();
2012 { 2062 {
2013 // Concatenate the two non-empty strings. 2063 // Add the two non-empty strings.
2014 Push(BuildUncheckedStringAdd(left, right, pretenure_flag)); 2064 Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2015 } 2065 }
2016 if_rightisempty.End(); 2066 if_rightempty.End();
2017 } 2067 }
2018 if_leftisempty.End(); 2068 if_leftempty.End();
2019 2069
2020 return Pop(); 2070 return Pop();
2021 } 2071 }
2022 2072
2023 2073
2024 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 2074 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2025 HValue* checked_object, 2075 HValue* checked_object,
2026 HValue* key, 2076 HValue* key,
2027 HValue* val, 2077 HValue* val,
2028 bool is_js_array, 2078 bool is_js_array,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2097 // deopt, leaving the backing store in an invalid state. 2147 // deopt, leaving the backing store in an invalid state.
2098 if (is_store && IsFastSmiElementsKind(elements_kind) && 2148 if (is_store && IsFastSmiElementsKind(elements_kind) &&
2099 !val->type().IsSmi()) { 2149 !val->type().IsSmi()) {
2100 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); 2150 val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2101 } 2151 }
2102 2152
2103 if (IsGrowStoreMode(store_mode)) { 2153 if (IsGrowStoreMode(store_mode)) {
2104 NoObservableSideEffectsScope no_effects(this); 2154 NoObservableSideEffectsScope no_effects(this);
2105 elements = BuildCheckForCapacityGrow(checked_object, elements, 2155 elements = BuildCheckForCapacityGrow(checked_object, elements,
2106 elements_kind, length, key, 2156 elements_kind, length, key,
2107 is_js_array); 2157 is_js_array, is_store);
2108 checked_key = key; 2158 checked_key = key;
2109 } else { 2159 } else {
2110 checked_key = Add<HBoundsCheck>(key, length); 2160 checked_key = Add<HBoundsCheck>(key, length);
2111 2161
2112 if (is_store && (fast_elements || fast_smi_only_elements)) { 2162 if (is_store && (fast_elements || fast_smi_only_elements)) {
2113 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 2163 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2114 NoObservableSideEffectsScope no_effects(this); 2164 NoObservableSideEffectsScope no_effects(this);
2115 elements = BuildCopyElementsOnWrite(checked_object, elements, 2165 elements = BuildCopyElementsOnWrite(checked_object, elements,
2116 elements_kind, length); 2166 elements_kind, length);
2117 } else { 2167 } else {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2261 HValue* val, 2311 HValue* val,
2262 HValue* dependency, 2312 HValue* dependency,
2263 ElementsKind elements_kind, 2313 ElementsKind elements_kind,
2264 bool is_store, 2314 bool is_store,
2265 LoadKeyedHoleMode load_mode) { 2315 LoadKeyedHoleMode load_mode) {
2266 if (is_store) { 2316 if (is_store) {
2267 ASSERT(val != NULL); 2317 ASSERT(val != NULL);
2268 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 2318 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
2269 val = Add<HClampToUint8>(val); 2319 val = Add<HClampToUint8>(val);
2270 } 2320 }
2271 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind); 2321 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2322 elements_kind == FAST_SMI_ELEMENTS
2323 ? STORE_TO_INITIALIZED_ENTRY
2324 : INITIALIZING_STORE);
2272 } 2325 }
2273 2326
2274 ASSERT(!is_store); 2327 ASSERT(!is_store);
2275 ASSERT(val == NULL); 2328 ASSERT(val == NULL);
2276 HLoadKeyed* load = Add<HLoadKeyed>( 2329 HLoadKeyed* load = Add<HLoadKeyed>(
2277 elements, checked_key, dependency, elements_kind, load_mode); 2330 elements, checked_key, dependency, elements_kind, load_mode);
2278 if (FLAG_opt_safe_uint32_operations && 2331 if (FLAG_opt_safe_uint32_operations &&
2279 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 2332 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
2280 graph()->RecordUint32Instruction(load); 2333 graph()->RecordUint32Instruction(load);
2281 } 2334 }
(...skipping 1849 matching lines...) Expand 10 before | Expand all | Expand 10 after
4131 ASSERT(current_block()->HasPredecessor()); 4184 ASSERT(current_block()->HasPredecessor());
4132 return Bailout(kWithStatement); 4185 return Bailout(kWithStatement);
4133 } 4186 }
4134 4187
4135 4188
4136 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 4189 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4137 ASSERT(!HasStackOverflow()); 4190 ASSERT(!HasStackOverflow());
4138 ASSERT(current_block() != NULL); 4191 ASSERT(current_block() != NULL);
4139 ASSERT(current_block()->HasPredecessor()); 4192 ASSERT(current_block()->HasPredecessor());
4140 4193
4141 // We only optimize switch statements with smi-literal smi comparisons, 4194 // We only optimize switch statements with a bounded number of clauses.
4142 // with a bounded number of clauses.
4143 const int kCaseClauseLimit = 128; 4195 const int kCaseClauseLimit = 128;
4144 ZoneList<CaseClause*>* clauses = stmt->cases(); 4196 ZoneList<CaseClause*>* clauses = stmt->cases();
4145 int clause_count = clauses->length(); 4197 int clause_count = clauses->length();
4198 ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4146 if (clause_count > kCaseClauseLimit) { 4199 if (clause_count > kCaseClauseLimit) {
4147 return Bailout(kSwitchStatementTooManyClauses); 4200 return Bailout(kSwitchStatementTooManyClauses);
4148 } 4201 }
4149 4202
4150 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
4151 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
4152 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
4153 }
4154
4155 CHECK_ALIVE(VisitForValue(stmt->tag())); 4203 CHECK_ALIVE(VisitForValue(stmt->tag()));
4156 Add<HSimulate>(stmt->EntryId()); 4204 Add<HSimulate>(stmt->EntryId());
4157 HValue* tag_value = Pop(); 4205 HValue* tag_value = Top();
4158 HBasicBlock* first_test_block = current_block(); 4206 Handle<Type> tag_type = stmt->tag()->bounds().lower;
4159
4160 HUnaryControlInstruction* string_check = NULL;
4161 HBasicBlock* not_string_block = NULL;
4162
4163 // Test switch's tag value if all clauses are string literals
4164 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
4165 first_test_block = graph()->CreateBasicBlock();
4166 not_string_block = graph()->CreateBasicBlock();
4167 string_check = New<HIsStringAndBranch>(
4168 tag_value, first_test_block, not_string_block);
4169 FinishCurrentBlock(string_check);
4170
4171 set_current_block(first_test_block);
4172 }
4173 4207
4174 // 1. Build all the tests, with dangling true branches 4208 // 1. Build all the tests, with dangling true branches
4175 BailoutId default_id = BailoutId::None(); 4209 BailoutId default_id = BailoutId::None();
4176 for (int i = 0; i < clause_count; ++i) { 4210 for (int i = 0; i < clause_count; ++i) {
4177 CaseClause* clause = clauses->at(i); 4211 CaseClause* clause = clauses->at(i);
4178 if (clause->is_default()) { 4212 if (clause->is_default()) {
4179 default_id = clause->EntryId(); 4213 body_blocks.Add(NULL, zone());
4214 if (default_id.IsNone()) default_id = clause->EntryId();
4180 continue; 4215 continue;
4181 } 4216 }
4182 4217
4183 // Generate a compare and branch. 4218 // Generate a compare and branch.
4184 CHECK_ALIVE(VisitForValue(clause->label())); 4219 CHECK_ALIVE(VisitForValue(clause->label()));
4185 HValue* label_value = Pop(); 4220 HValue* label_value = Pop();
4186 4221
4222 Handle<Type> label_type = clause->label()->bounds().lower;
4223 Handle<Type> combined_type = clause->compare_type();
4224 HControlInstruction* compare = BuildCompareInstruction(
4225 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4226 combined_type, stmt->tag()->position(), clause->label()->position(),
4227 clause->id());
4228
4187 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 4229 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4188 HBasicBlock* body_block = graph()->CreateBasicBlock(); 4230 HBasicBlock* body_block = graph()->CreateBasicBlock();
4189 4231 body_blocks.Add(body_block, zone());
4190 HControlInstruction* compare;
4191
4192 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
4193 if (!clause->compare_type()->Is(Type::Smi())) {
4194 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
4195 }
4196
4197 HCompareNumericAndBranch* compare_ =
4198 New<HCompareNumericAndBranch>(tag_value,
4199 label_value,
4200 Token::EQ_STRICT);
4201 compare_->set_observed_input_representation(
4202 Representation::Smi(), Representation::Smi());
4203 compare = compare_;
4204 } else {
4205 compare = New<HStringCompareAndBranch>(tag_value,
4206 label_value,
4207 Token::EQ_STRICT);
4208 }
4209
4210 compare->SetSuccessorAt(0, body_block); 4232 compare->SetSuccessorAt(0, body_block);
4211 compare->SetSuccessorAt(1, next_test_block); 4233 compare->SetSuccessorAt(1, next_test_block);
4212 FinishCurrentBlock(compare); 4234 FinishCurrentBlock(compare);
4213 4235
4236 set_current_block(body_block);
4237 Drop(1); // tag_value
4238
4214 set_current_block(next_test_block); 4239 set_current_block(next_test_block);
4215 } 4240 }
4216 4241
4217 // Save the current block to use for the default or to join with the 4242 // Save the current block to use for the default or to join with the
4218 // exit. 4243 // exit.
4219 HBasicBlock* last_block = current_block(); 4244 HBasicBlock* last_block = current_block();
4220 4245 Drop(1); // tag_value
4221 if (not_string_block != NULL) {
4222 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
4223 last_block = CreateJoin(last_block, not_string_block, join_id);
4224 }
4225 4246
4226 // 2. Loop over the clauses and the linked list of tests in lockstep, 4247 // 2. Loop over the clauses and the linked list of tests in lockstep,
4227 // translating the clause bodies. 4248 // translating the clause bodies.
4228 HBasicBlock* curr_test_block = first_test_block;
4229 HBasicBlock* fall_through_block = NULL; 4249 HBasicBlock* fall_through_block = NULL;
4230 4250
4231 BreakAndContinueInfo break_info(stmt); 4251 BreakAndContinueInfo break_info(stmt);
4232 { BreakAndContinueScope push(&break_info, this); 4252 { BreakAndContinueScope push(&break_info, this);
4233 for (int i = 0; i < clause_count; ++i) { 4253 for (int i = 0; i < clause_count; ++i) {
4234 CaseClause* clause = clauses->at(i); 4254 CaseClause* clause = clauses->at(i);
4235 4255
4236 // Identify the block where normal (non-fall-through) control flow 4256 // Identify the block where normal (non-fall-through) control flow
4237 // goes to. 4257 // goes to.
4238 HBasicBlock* normal_block = NULL; 4258 HBasicBlock* normal_block = NULL;
4239 if (clause->is_default()) { 4259 if (clause->is_default()) {
4240 if (last_block != NULL) { 4260 if (last_block == NULL) continue;
4241 normal_block = last_block; 4261 normal_block = last_block;
4242 last_block = NULL; // Cleared to indicate we've handled it. 4262 last_block = NULL; // Cleared to indicate we've handled it.
4243 }
4244 } else { 4263 } else {
4245 // If the current test block is deoptimizing due to an unhandled clause 4264 normal_block = body_blocks[i];
4246 // of the switch, the test instruction is in the next block since the
4247 // deopt must end the current block.
4248 if (curr_test_block->IsDeoptimizing()) {
4249 ASSERT(curr_test_block->end()->SecondSuccessor() == NULL);
4250 curr_test_block = curr_test_block->end()->FirstSuccessor();
4251 }
4252 normal_block = curr_test_block->end()->FirstSuccessor();
4253 curr_test_block = curr_test_block->end()->SecondSuccessor();
4254 } 4265 }
4255 4266
4256 // Identify a block to emit the body into. 4267 if (fall_through_block == NULL) {
4257 if (normal_block == NULL) {
4258 if (fall_through_block == NULL) {
4259 // (a) Unreachable.
4260 if (clause->is_default()) {
4261 continue; // Might still be reachable clause bodies.
4262 } else {
4263 break;
4264 }
4265 } else {
4266 // (b) Reachable only as fall through.
4267 set_current_block(fall_through_block);
4268 }
4269 } else if (fall_through_block == NULL) {
4270 // (c) Reachable only normally.
4271 set_current_block(normal_block); 4268 set_current_block(normal_block);
4272 } else { 4269 } else {
4273 // (d) Reachable both ways.
4274 HBasicBlock* join = CreateJoin(fall_through_block, 4270 HBasicBlock* join = CreateJoin(fall_through_block,
4275 normal_block, 4271 normal_block,
4276 clause->EntryId()); 4272 clause->EntryId());
4277 set_current_block(join); 4273 set_current_block(join);
4278 } 4274 }
4279 4275
4280 CHECK_BAILOUT(VisitStatements(clause->statements())); 4276 CHECK_BAILOUT(VisitStatements(clause->statements()));
4281 fall_through_block = current_block(); 4277 fall_through_block = current_block();
4282 } 4278 }
4283 } 4279 }
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
5258 // Already holds a HeapNumber; load the box and write its value field. 5254 // Already holds a HeapNumber; load the box and write its value field.
5259 HInstruction* heap_number = Add<HLoadNamedField>(checked_object, 5255 HInstruction* heap_number = Add<HLoadNamedField>(checked_object,
5260 heap_number_access); 5256 heap_number_access);
5261 heap_number->set_type(HType::HeapNumber()); 5257 heap_number->set_type(HType::HeapNumber());
5262 instr = New<HStoreNamedField>(heap_number, 5258 instr = New<HStoreNamedField>(heap_number,
5263 HObjectAccess::ForHeapNumberValue(), 5259 HObjectAccess::ForHeapNumberValue(),
5264 value); 5260 value);
5265 } 5261 }
5266 } else { 5262 } else {
5267 // This is a normal store. 5263 // This is a normal store.
5268 instr = New<HStoreNamedField>(checked_object->ActualValue(), 5264 instr = New<HStoreNamedField>(
5269 field_access, 5265 checked_object->ActualValue(), field_access, value,
5270 value); 5266 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5271 } 5267 }
5272 5268
5273 if (transition_to_field) { 5269 if (transition_to_field) {
5274 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); 5270 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
5275 HConstant* transition_constant = Add<HConstant>(transition); 5271 HConstant* transition_constant = Add<HConstant>(transition);
5276 instr->SetTransition(transition_constant, top_info()); 5272 instr->SetTransition(transition_constant, top_info());
5277 // TODO(fschneider): Record the new map type of the object in the IR to 5273 // TODO(fschneider): Record the new map type of the object in the IR to
5278 // enable elimination of redundant checks after the transition store. 5274 // enable elimination of redundant checks after the transition store.
5279 instr->SetGVNFlag(kChangesMaps); 5275 instr->SetGVNFlag(kChangesMaps);
5280 } 5276 }
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
6139 return New<HLoadNamedField>(object, access); 6135 return New<HLoadNamedField>(object, access);
6140 } 6136 }
6141 6137
6142 6138
6143 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object, 6139 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
6144 HObjectAccess access) { 6140 HObjectAccess access) {
6145 return AddInstruction(BuildLoadNamedField(object, access)); 6141 return AddInstruction(BuildLoadNamedField(object, access));
6146 } 6142 }
6147 6143
6148 6144
6149 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, 6145 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
6150 HValue* checked_string) { 6146 if (string->IsConstant()) {
6151 if (FLAG_fold_constants && object->IsConstant()) { 6147 HConstant* c_string = HConstant::cast(string);
6152 HConstant* constant = HConstant::cast(object); 6148 if (c_string->HasStringValue()) {
6153 if (constant->HasStringValue()) { 6149 return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6154 return New<HConstant>(constant->StringValue()->length());
6155 } 6150 }
6156 } 6151 }
6157 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); 6152 return AddLoadNamedField(
6153 AddLoadNamedField(string, HObjectAccess::ForMap()),
6154 HObjectAccess::ForMapInstanceType());
6158 } 6155 }
6159 6156
6160 6157
6158 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
6159 if (string->IsConstant()) {
6160 HConstant* c_string = HConstant::cast(string);
6161 if (c_string->HasStringValue()) {
6162 return Add<HConstant>(c_string->StringValue()->length());
6163 }
6164 }
6165 return AddLoadNamedField(string, HObjectAccess::ForStringLength());
6166 }
6167
6168
6161 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 6169 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
6162 HValue* object, 6170 HValue* object,
6163 Handle<String> name, 6171 Handle<String> name,
6164 Property* expr) { 6172 Property* expr) {
6165 if (expr->IsUninitialized()) { 6173 if (expr->IsUninitialized()) {
6166 Add<HDeoptimize>("Insufficient type feedback for generic named load", 6174 Add<HDeoptimize>("Insufficient type feedback for generic named load",
6167 Deoptimizer::SOFT); 6175 Deoptimizer::SOFT);
6168 } 6176 }
6169 return New<HLoadNamedGeneric>(object, name); 6177 return New<HLoadNamedGeneric>(object, name);
6170 } 6178 }
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
6777 if (!expr->ComputeTarget(info.map(), name)) return false; 6785 if (!expr->ComputeTarget(info.map(), name)) return false;
6778 6786
6779 BuildCheckHeapObject(receiver); 6787 BuildCheckHeapObject(receiver);
6780 Add<HCheckMaps>(receiver, types); 6788 Add<HCheckMaps>(receiver, types);
6781 AddCheckPrototypeMaps(expr->holder(), info.map()); 6789 AddCheckPrototypeMaps(expr->holder(), info.map());
6782 if (FLAG_trace_inlining) { 6790 if (FLAG_trace_inlining) {
6783 Handle<JSFunction> caller = current_info()->closure(); 6791 Handle<JSFunction> caller = current_info()->closure();
6784 SmartArrayPointer<char> caller_name = 6792 SmartArrayPointer<char> caller_name =
6785 caller->shared()->DebugName()->ToCString(); 6793 caller->shared()->DebugName()->ToCString();
6786 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6794 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6787 *name->ToCString(), *caller_name); 6795 name->ToCString().get(), caller_name.get());
6788 } 6796 }
6789 6797
6790 if (!TryInlineCall(expr)) { 6798 if (!TryInlineCall(expr)) {
6791 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6799 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6792 HCallConstantFunction* call = 6800 HCallConstantFunction* call =
6793 New<HCallConstantFunction>(expr->target(), argument_count); 6801 New<HCallConstantFunction>(expr->target(), argument_count);
6794 PreProcessCall(call); 6802 PreProcessCall(call);
6795 AddInstruction(call); 6803 AddInstruction(call);
6796 if (!ast_context()->IsEffect()) Push(call); 6804 if (!ast_context()->IsEffect()) Push(call);
6797 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 6805 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
6890 } 6898 }
6891 set_current_block(if_true); 6899 set_current_block(if_true);
6892 6900
6893 expr->ComputeTarget(map, name); 6901 expr->ComputeTarget(map, name);
6894 AddCheckPrototypeMaps(expr->holder(), map); 6902 AddCheckPrototypeMaps(expr->holder(), map);
6895 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 6903 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6896 Handle<JSFunction> caller = current_info()->closure(); 6904 Handle<JSFunction> caller = current_info()->closure();
6897 SmartArrayPointer<char> caller_name = 6905 SmartArrayPointer<char> caller_name =
6898 caller->shared()->DebugName()->ToCString(); 6906 caller->shared()->DebugName()->ToCString();
6899 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6907 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6900 *name->ToCString(), 6908 name->ToCString().get(),
6901 *caller_name); 6909 caller_name.get());
6902 } 6910 }
6903 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 6911 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6904 // Trying to inline will signal that we should bailout from the 6912 // Trying to inline will signal that we should bailout from the
6905 // entire compilation by setting stack overflow on the visitor. 6913 // entire compilation by setting stack overflow on the visitor.
6906 if (HasStackOverflow()) return; 6914 if (HasStackOverflow()) return;
6907 } else { 6915 } else {
6908 HCallConstantFunction* call = 6916 HCallConstantFunction* call =
6909 New<HCallConstantFunction>(expr->target(), argument_count); 6917 New<HCallConstantFunction>(expr->target(), argument_count);
6910 PreProcessCall(call); 6918 PreProcessCall(call);
6911 AddInstruction(call); 6919 AddInstruction(call);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6955 6963
6956 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, 6964 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
6957 Handle<JSFunction> caller, 6965 Handle<JSFunction> caller,
6958 const char* reason) { 6966 const char* reason) {
6959 if (FLAG_trace_inlining) { 6967 if (FLAG_trace_inlining) {
6960 SmartArrayPointer<char> target_name = 6968 SmartArrayPointer<char> target_name =
6961 target->shared()->DebugName()->ToCString(); 6969 target->shared()->DebugName()->ToCString();
6962 SmartArrayPointer<char> caller_name = 6970 SmartArrayPointer<char> caller_name =
6963 caller->shared()->DebugName()->ToCString(); 6971 caller->shared()->DebugName()->ToCString();
6964 if (reason == NULL) { 6972 if (reason == NULL) {
6965 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 6973 PrintF("Inlined %s called from %s.\n", target_name.get(),
6974 caller_name.get());
6966 } else { 6975 } else {
6967 PrintF("Did not inline %s called from %s (%s).\n", 6976 PrintF("Did not inline %s called from %s (%s).\n",
6968 *target_name, *caller_name, reason); 6977 target_name.get(), caller_name.get(), reason);
6969 } 6978 }
6970 } 6979 }
6971 } 6980 }
6972 6981
6973 6982
6974 static const int kNotInlinable = 1000000000; 6983 static const int kNotInlinable = 1000000000;
6975 6984
6976 6985
6977 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { 6986 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
6978 if (!FLAG_use_inlining) return kNotInlinable; 6987 if (!FLAG_use_inlining) return kNotInlinable;
(...skipping 1632 matching lines...) Expand 10 before | Expand all | Expand 10 after
8611 HConstant* c_index = HConstant::cast(index); 8620 HConstant* c_index = HConstant::cast(index);
8612 if (c_string->HasStringValue() && c_index->HasNumberValue()) { 8621 if (c_string->HasStringValue() && c_index->HasNumberValue()) {
8613 int32_t i = c_index->NumberValueAsInteger32(); 8622 int32_t i = c_index->NumberValueAsInteger32();
8614 Handle<String> s = c_string->StringValue(); 8623 Handle<String> s = c_string->StringValue();
8615 if (i < 0 || i >= s->length()) { 8624 if (i < 0 || i >= s->length()) {
8616 return New<HConstant>(OS::nan_value()); 8625 return New<HConstant>(OS::nan_value());
8617 } 8626 }
8618 return New<HConstant>(s->Get(i)); 8627 return New<HConstant>(s->Get(i));
8619 } 8628 }
8620 } 8629 }
8621 BuildCheckHeapObject(string); 8630 string = BuildCheckString(string);
8622 HValue* checkstring = 8631 index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
8623 Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); 8632 return New<HStringCharCodeAt>(string, index);
8624 HInstruction* length = BuildLoadStringLength(string, checkstring);
8625 AddInstruction(length);
8626 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
8627 return New<HStringCharCodeAt>(string, checked_index);
8628 } 8633 }
8629 8634
8630 8635
8631 // Checks if the given shift amounts have following forms: 8636 // Checks if the given shift amounts have following forms:
8632 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). 8637 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
8633 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, 8638 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
8634 HValue* const32_minus_sa) { 8639 HValue* const32_minus_sa) {
8635 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { 8640 if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
8636 const HConstant* c1 = HConstant::cast(sa); 8641 const HConstant* c1 = HConstant::cast(sa);
8637 const HConstant* c2 = HConstant::cast(const32_minus_sa); 8642 const HConstant* c2 = HConstant::cast(const32_minus_sa);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
8748 8753
8749 8754
8750 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( 8755 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
8751 BinaryOperation* expr, 8756 BinaryOperation* expr,
8752 HValue* left, 8757 HValue* left,
8753 HValue* right) { 8758 HValue* right) {
8754 Handle<Type> left_type = expr->left()->bounds().lower; 8759 Handle<Type> left_type = expr->left()->bounds().lower;
8755 Handle<Type> right_type = expr->right()->bounds().lower; 8760 Handle<Type> right_type = expr->right()->bounds().lower;
8756 Handle<Type> result_type = expr->bounds().lower; 8761 Handle<Type> result_type = expr->bounds().lower;
8757 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 8762 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
8763 Handle<AllocationSite> allocation_site = expr->allocation_site();
8764
8765 HAllocationMode allocation_mode =
8766 FLAG_allocation_site_pretenuring
8767 ? (allocation_site.is_null()
8768 ? HAllocationMode(NOT_TENURED)
8769 : HAllocationMode(allocation_site))
8770 : HAllocationMode(isolate()->heap()->GetPretenureMode());
8758 8771
8759 HValue* result = HGraphBuilder::BuildBinaryOperation( 8772 HValue* result = HGraphBuilder::BuildBinaryOperation(
8760 expr->op(), left, right, left_type, right_type, 8773 expr->op(), left, right, left_type, right_type, result_type,
8761 result_type, fixed_right_arg); 8774 fixed_right_arg, allocation_mode);
8762 // Add a simulate after instructions with observable side effects, and 8775 // Add a simulate after instructions with observable side effects, and
8763 // after phis, which are the result of BuildBinaryOperation when we 8776 // after phis, which are the result of BuildBinaryOperation when we
8764 // inlined some complex subgraph. 8777 // inlined some complex subgraph.
8765 if (result->HasObservableSideEffects() || result->IsPhi()) { 8778 if (result->HasObservableSideEffects() || result->IsPhi()) {
8766 Push(result); 8779 Push(result);
8767 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 8780 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8768 Drop(1); 8781 Drop(1);
8769 } 8782 }
8770 return result; 8783 return result;
8771 } 8784 }
8772 8785
8773 8786
8774 HValue* HGraphBuilder::BuildBinaryOperation( 8787 HValue* HGraphBuilder::BuildBinaryOperation(
8775 Token::Value op, 8788 Token::Value op,
8776 HValue* left, 8789 HValue* left,
8777 HValue* right, 8790 HValue* right,
8778 Handle<Type> left_type, 8791 Handle<Type> left_type,
8779 Handle<Type> right_type, 8792 Handle<Type> right_type,
8780 Handle<Type> result_type, 8793 Handle<Type> result_type,
8781 Maybe<int> fixed_right_arg) { 8794 Maybe<int> fixed_right_arg,
8795 HAllocationMode allocation_mode) {
8782 8796
8783 Representation left_rep = Representation::FromType(left_type); 8797 Representation left_rep = Representation::FromType(left_type);
8784 Representation right_rep = Representation::FromType(right_type); 8798 Representation right_rep = Representation::FromType(right_type);
8785 8799
8786 bool maybe_string_add = op == Token::ADD && 8800 bool maybe_string_add = op == Token::ADD &&
8787 (left_type->Maybe(Type::String()) || 8801 (left_type->Maybe(Type::String()) ||
8788 right_type->Maybe(Type::String())); 8802 right_type->Maybe(Type::String()));
8789 8803
8790 if (left_type->Is(Type::None())) { 8804 if (left_type->Is(Type::None())) {
8791 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", 8805 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8837 ASSERT(left_type->Is(Type::String())); 8851 ASSERT(left_type->Is(Type::String()));
8838 right = BuildNumberToString(right, right_type); 8852 right = BuildNumberToString(right, right_type);
8839 } else if (!right_type->Is(Type::String())) { 8853 } else if (!right_type->Is(Type::String())) {
8840 ASSERT(left_type->Is(Type::String())); 8854 ASSERT(left_type->Is(Type::String()));
8841 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); 8855 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
8842 Add<HPushArgument>(left); 8856 Add<HPushArgument>(left);
8843 Add<HPushArgument>(right); 8857 Add<HPushArgument>(right);
8844 return AddUncasted<HInvokeFunction>(function, 2); 8858 return AddUncasted<HInvokeFunction>(function, 2);
8845 } 8859 }
8846 8860
8847 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); 8861 // Inline the string addition into the stub when creating allocation
8862 // mementos to gather allocation site feedback.
8863 if (graph()->info()->IsStub() &&
8864 allocation_mode.CreateAllocationMementos()) {
8865 return BuildStringAdd(left, right, allocation_mode);
8866 }
8867
8868 // Register the dependent code with the allocation site.
8869 if (!allocation_mode.feedback_site().is_null()) {
8870 ASSERT(!graph()->info()->IsStub());
8871 allocation_mode.feedback_site()->AddDependentCompilationInfo(
8872 AllocationSite::TENURING, top_info());
8873 }
8874
8875 // Inline string addition if we know that we'll create a cons string.
8876 if (left->IsConstant()) {
8877 HConstant* c_left = HConstant::cast(left);
8878 if (c_left->HasStringValue()) {
8879 int c_left_length = c_left->StringValue()->length();
8880 if (c_left_length == 0) {
8881 return right;
8882 } else if (c_left_length + 1 >= ConsString::kMinLength) {
8883 return BuildStringAdd(left, right, allocation_mode);
8884 }
8885 }
8886 }
8887 if (right->IsConstant()) {
8888 HConstant* c_right = HConstant::cast(right);
8889 if (c_right->HasStringValue()) {
8890 int c_right_length = c_right->StringValue()->length();
8891 if (c_right_length == 0) {
8892 return left;
8893 } else if (c_right_length + 1 >= ConsString::kMinLength) {
8894 return BuildStringAdd(left, right, allocation_mode);
8895 }
8896 }
8897 }
8898
8899 // Fallback to using the string add stub.
8900 return AddUncasted<HStringAdd>(
8901 left, right, allocation_mode.GetPretenureMode(),
8902 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
8848 } 8903 }
8849 8904
8850 if (graph()->info()->IsStub()) { 8905 if (graph()->info()->IsStub()) {
8851 left = EnforceNumberType(left, left_type); 8906 left = EnforceNumberType(left, left_type);
8852 right = EnforceNumberType(right, right_type); 8907 right = EnforceNumberType(right, right_type);
8853 } 8908 }
8854 8909
8855 Representation result_rep = Representation::FromType(result_type); 8910 Representation result_rep = Representation::FromType(result_type);
8856 8911
8857 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || 8912 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
9163 HValue* value = Pop(); 9218 HValue* value = Pop();
9164 Literal* literal = expr->right()->AsLiteral(); 9219 Literal* literal = expr->right()->AsLiteral();
9165 Handle<String> rhs = Handle<String>::cast(literal->value()); 9220 Handle<String> rhs = Handle<String>::cast(literal->value());
9166 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); 9221 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
9167 return ast_context()->ReturnControl(instr, expr->id()); 9222 return ast_context()->ReturnControl(instr, expr->id());
9168 } 9223 }
9169 9224
9170 Handle<Type> left_type = expr->left()->bounds().lower; 9225 Handle<Type> left_type = expr->left()->bounds().lower;
9171 Handle<Type> right_type = expr->right()->bounds().lower; 9226 Handle<Type> right_type = expr->right()->bounds().lower;
9172 Handle<Type> combined_type = expr->combined_type(); 9227 Handle<Type> combined_type = expr->combined_type();
9173 Representation combined_rep = Representation::FromType(combined_type);
9174 Representation left_rep = Representation::FromType(left_type);
9175 Representation right_rep = Representation::FromType(right_type);
9176 9228
9177 CHECK_ALIVE(VisitForValue(expr->left())); 9229 CHECK_ALIVE(VisitForValue(expr->left()));
9178 CHECK_ALIVE(VisitForValue(expr->right())); 9230 CHECK_ALIVE(VisitForValue(expr->right()));
9179 9231
9180 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 9232 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
9181 9233
9182 HValue* right = Pop(); 9234 HValue* right = Pop();
9183 HValue* left = Pop(); 9235 HValue* left = Pop();
9184 Token::Value op = expr->op(); 9236 Token::Value op = expr->op();
9185 9237
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
9230 } else if (op == Token::IN) { 9282 } else if (op == Token::IN) {
9231 HValue* function = AddLoadJSBuiltin(Builtins::IN); 9283 HValue* function = AddLoadJSBuiltin(Builtins::IN);
9232 Add<HPushArgument>(left); 9284 Add<HPushArgument>(left);
9233 Add<HPushArgument>(right); 9285 Add<HPushArgument>(right);
9234 // TODO(olivf) InvokeFunction produces a check for the parameter count, 9286 // TODO(olivf) InvokeFunction produces a check for the parameter count,
9235 // even though we are certain to pass the correct number of arguments here. 9287 // even though we are certain to pass the correct number of arguments here.
9236 HInstruction* result = New<HInvokeFunction>(function, 2); 9288 HInstruction* result = New<HInvokeFunction>(function, 2);
9237 return ast_context()->ReturnInstruction(result, expr->id()); 9289 return ast_context()->ReturnInstruction(result, expr->id());
9238 } 9290 }
9239 9291
9292 HControlInstruction* compare = BuildCompareInstruction(
9293 op, left, right, left_type, right_type, combined_type,
9294 expr->left()->position(), expr->right()->position(), expr->id());
9295 if (compare == NULL) return; // Bailed out.
9296 return ast_context()->ReturnControl(compare, expr->id());
9297 }
9298
9299
9300 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
9301 Token::Value op,
9302 HValue* left,
9303 HValue* right,
9304 Handle<Type> left_type,
9305 Handle<Type> right_type,
9306 Handle<Type> combined_type,
9307 int left_position,
9308 int right_position,
9309 BailoutId bailout_id) {
9240 // Cases handled below depend on collected type feedback. They should 9310 // Cases handled below depend on collected type feedback. They should
9241 // soft deoptimize when there is no type feedback. 9311 // soft deoptimize when there is no type feedback.
9242 if (combined_type->Is(Type::None())) { 9312 if (combined_type->Is(Type::None())) {
9243 Add<HDeoptimize>("Insufficient type feedback for combined type " 9313 Add<HDeoptimize>("Insufficient type feedback for combined type "
9244 "of binary operation", 9314 "of binary operation",
9245 Deoptimizer::SOFT); 9315 Deoptimizer::SOFT);
9246 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 9316 combined_type = left_type = right_type = handle(Type::Any(), isolate());
9247 } 9317 }
9248 9318
9319 Representation left_rep = Representation::FromType(left_type);
9320 Representation right_rep = Representation::FromType(right_type);
9321 Representation combined_rep = Representation::FromType(combined_type);
9322
9249 if (combined_type->Is(Type::Receiver())) { 9323 if (combined_type->Is(Type::Receiver())) {
9250 switch (op) { 9324 if (Token::IsEqualityOp(op)) {
9251 case Token::EQ: 9325 // Can we get away with map check and not instance type check?
9252 case Token::EQ_STRICT: { 9326 HValue* operand_to_check =
9253 // Can we get away with map check and not instance type check? 9327 left->block()->block_id() < right->block()->block_id() ? left : right;
9254 if (combined_type->IsClass()) { 9328 if (combined_type->IsClass()) {
9255 Handle<Map> map = combined_type->AsClass(); 9329 Handle<Map> map = combined_type->AsClass();
9256 AddCheckMap(left, map); 9330 AddCheckMap(operand_to_check, map);
9257 AddCheckMap(right, map); 9331 HCompareObjectEqAndBranch* result =
9258 HCompareObjectEqAndBranch* result = 9332 New<HCompareObjectEqAndBranch>(left, right);
9259 New<HCompareObjectEqAndBranch>(left, right); 9333 if (FLAG_emit_opt_code_positions) {
9260 if (FLAG_emit_opt_code_positions) { 9334 result->set_operand_position(zone(), 0, left_position);
9261 result->set_operand_position(zone(), 0, expr->left()->position()); 9335 result->set_operand_position(zone(), 1, right_position);
9262 result->set_operand_position(zone(), 1, expr->right()->position());
9263 }
9264 return ast_context()->ReturnControl(result, expr->id());
9265 } else {
9266 BuildCheckHeapObject(left);
9267 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
9268 BuildCheckHeapObject(right);
9269 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
9270 HCompareObjectEqAndBranch* result =
9271 New<HCompareObjectEqAndBranch>(left, right);
9272 return ast_context()->ReturnControl(result, expr->id());
9273 } 9336 }
9337 return result;
9338 } else {
9339 BuildCheckHeapObject(operand_to_check);
9340 Add<HCheckInstanceType>(operand_to_check,
9341 HCheckInstanceType::IS_SPEC_OBJECT);
9342 HCompareObjectEqAndBranch* result =
9343 New<HCompareObjectEqAndBranch>(left, right);
9344 return result;
9274 } 9345 }
9275 default: 9346 } else {
9276 return Bailout(kUnsupportedNonPrimitiveCompare); 9347 Bailout(kUnsupportedNonPrimitiveCompare);
9348 return NULL;
9277 } 9349 }
9278 } else if (combined_type->Is(Type::InternalizedString()) && 9350 } else if (combined_type->Is(Type::InternalizedString()) &&
9279 Token::IsEqualityOp(op)) { 9351 Token::IsEqualityOp(op)) {
9280 BuildCheckHeapObject(left); 9352 BuildCheckHeapObject(left);
9281 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); 9353 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
9282 BuildCheckHeapObject(right); 9354 BuildCheckHeapObject(right);
9283 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); 9355 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
9284 HCompareObjectEqAndBranch* result = 9356 HCompareObjectEqAndBranch* result =
9285 New<HCompareObjectEqAndBranch>(left, right); 9357 New<HCompareObjectEqAndBranch>(left, right);
9286 return ast_context()->ReturnControl(result, expr->id()); 9358 return result;
9287 } else if (combined_type->Is(Type::String())) { 9359 } else if (combined_type->Is(Type::String())) {
9288 BuildCheckHeapObject(left); 9360 BuildCheckHeapObject(left);
9289 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING); 9361 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
9290 BuildCheckHeapObject(right); 9362 BuildCheckHeapObject(right);
9291 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING); 9363 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
9292 HStringCompareAndBranch* result = 9364 HStringCompareAndBranch* result =
9293 New<HStringCompareAndBranch>(left, right, op); 9365 New<HStringCompareAndBranch>(left, right, op);
9294 return ast_context()->ReturnControl(result, expr->id()); 9366 return result;
9295 } else { 9367 } else {
9296 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 9368 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
9297 HCompareGeneric* result = New<HCompareGeneric>(left, right, op); 9369 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
9298 result->set_observed_input_representation(1, left_rep); 9370 result->set_observed_input_representation(1, left_rep);
9299 result->set_observed_input_representation(2, right_rep); 9371 result->set_observed_input_representation(2, right_rep);
9300 return ast_context()->ReturnInstruction(result, expr->id()); 9372 if (result->HasObservableSideEffects()) {
9373 Push(result);
9374 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9375 Drop(1);
9376 }
9377 // TODO(jkummerow): Can we make this more efficient?
9378 HBranch* branch = New<HBranch>(result);
9379 return branch;
9301 } else { 9380 } else {
9302 HCompareNumericAndBranch* result = 9381 HCompareNumericAndBranch* result =
9303 New<HCompareNumericAndBranch>(left, right, op); 9382 New<HCompareNumericAndBranch>(left, right, op);
9304 result->set_observed_input_representation(left_rep, right_rep); 9383 result->set_observed_input_representation(left_rep, right_rep);
9305 if (FLAG_emit_opt_code_positions) { 9384 if (FLAG_emit_opt_code_positions) {
9306 result->SetOperandPositions(zone(), 9385 result->SetOperandPositions(zone(), left_position, right_position);
9307 expr->left()->position(),
9308 expr->right()->position());
9309 } 9386 }
9310 return ast_context()->ReturnControl(result, expr->id()); 9387 return result;
9311 } 9388 }
9312 } 9389 }
9313 } 9390 }
9314 9391
9315 9392
9316 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9393 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9317 Expression* sub_expr, 9394 Expression* sub_expr,
9318 NilValue nil) { 9395 NilValue nil) {
9319 ASSERT(!HasStackOverflow()); 9396 ASSERT(!HasStackOverflow());
9320 ASSERT(current_block() != NULL); 9397 ASSERT(current_block() != NULL);
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
9487 9564
9488 if (value->IsJSObject()) { 9565 if (value->IsJSObject()) {
9489 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 9566 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
9490 Handle<AllocationSite> current_site = site_context->EnterNewScope(); 9567 Handle<AllocationSite> current_site = site_context->EnterNewScope();
9491 HInstruction* result = 9568 HInstruction* result =
9492 BuildFastLiteral(value_object, site_context); 9569 BuildFastLiteral(value_object, site_context);
9493 site_context->ExitScope(current_site, value_object); 9570 site_context->ExitScope(current_site, value_object);
9494 Add<HStoreNamedField>(object, access, result); 9571 Add<HStoreNamedField>(object, access, result);
9495 } else { 9572 } else {
9496 Representation representation = details.representation(); 9573 Representation representation = details.representation();
9497 HInstruction* value_instruction = Add<HConstant>(value); 9574 HInstruction* value_instruction;
9498 9575
9499 if (representation.IsDouble()) { 9576 if (representation.IsDouble()) {
9500 // Allocate a HeapNumber box and store the value into it. 9577 // Allocate a HeapNumber box and store the value into it.
9501 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); 9578 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
9502 // This heap number alloc does not have a corresponding 9579 // This heap number alloc does not have a corresponding
9503 // AllocationSite. That is okay because 9580 // AllocationSite. That is okay because
9504 // 1) it's a child object of another object with a valid allocation site 9581 // 1) it's a child object of another object with a valid allocation site
9505 // 2) we can just use the mode of the parent object for pretenuring 9582 // 2) we can just use the mode of the parent object for pretenuring
9506 HInstruction* double_box = 9583 HInstruction* double_box =
9507 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), 9584 Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
9508 pretenure_flag, HEAP_NUMBER_TYPE); 9585 pretenure_flag, HEAP_NUMBER_TYPE);
9509 AddStoreMapConstant(double_box, 9586 AddStoreMapConstant(double_box,
9510 isolate()->factory()->heap_number_map()); 9587 isolate()->factory()->heap_number_map());
9511 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), 9588 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
9512 value_instruction); 9589 Add<HConstant>(value));
9513 value_instruction = double_box; 9590 value_instruction = double_box;
9591 } else if (representation.IsSmi() && value->IsUninitialized()) {
9592 value_instruction = graph()->GetConstant0();
9593 } else {
9594 value_instruction = Add<HConstant>(value);
9514 } 9595 }
9515 9596
9516 Add<HStoreNamedField>(object, access, value_instruction); 9597 Add<HStoreNamedField>(object, access, value_instruction);
9517 } 9598 }
9518 } 9599 }
9519 9600
9520 int inobject_properties = boilerplate_object->map()->inobject_properties(); 9601 int inobject_properties = boilerplate_object->map()->inobject_properties();
9521 HInstruction* value_instruction = 9602 HInstruction* value_instruction =
9522 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); 9603 Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
9523 for (int i = copied_fields; i < inobject_properties; i++) { 9604 for (int i = copied_fields; i < inobject_properties; i++) {
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
10040 } 10121 }
10041 10122
10042 10123
10043 // Fast support for StringAdd. 10124 // Fast support for StringAdd.
10044 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { 10125 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
10045 ASSERT_EQ(2, call->arguments()->length()); 10126 ASSERT_EQ(2, call->arguments()->length());
10046 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10127 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10047 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10128 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10048 HValue* right = Pop(); 10129 HValue* right = Pop();
10049 HValue* left = Pop(); 10130 HValue* left = Pop();
10050 HInstruction* result = 10131 HInstruction* result = NewUncasted<HStringAdd>(left, right);
10051 NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH);
10052 return ast_context()->ReturnInstruction(result, call->id()); 10132 return ast_context()->ReturnInstruction(result, call->id());
10053 } 10133 }
10054 10134
10055 10135
10056 // Fast support for SubString. 10136 // Fast support for SubString.
10057 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { 10137 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
10058 ASSERT_EQ(3, call->arguments()->length()); 10138 ASSERT_EQ(3, call->arguments()->length());
10059 CHECK_ALIVE(VisitArgumentList(call->arguments())); 10139 CHECK_ALIVE(VisitArgumentList(call->arguments()));
10060 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); 10140 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
10061 Drop(3); 10141 Drop(3);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
10157 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10237 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10158 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10238 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10159 HValue* right = Pop(); 10239 HValue* right = Pop();
10160 HValue* left = Pop(); 10240 HValue* left = Pop();
10161 HInstruction* result = NewUncasted<HPower>(left, right); 10241 HInstruction* result = NewUncasted<HPower>(left, right);
10162 return ast_context()->ReturnInstruction(result, call->id()); 10242 return ast_context()->ReturnInstruction(result, call->id());
10163 } 10243 }
10164 10244
10165 10245
10166 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { 10246 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) {
10167 ASSERT_EQ(1, call->arguments()->length()); 10247 ASSERT(call->arguments()->length() == 1);
10168 CHECK_ALIVE(VisitArgumentList(call->arguments())); 10248 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10169 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); 10249 HValue* value = Pop();
10170 result->set_transcendental_type(TranscendentalCache::LOG); 10250 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
10171 Drop(1);
10172 return ast_context()->ReturnInstruction(result, call->id()); 10251 return ast_context()->ReturnInstruction(result, call->id());
10173 } 10252 }
10174 10253
10175 10254
10176 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 10255 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
10177 ASSERT(call->arguments()->length() == 1); 10256 ASSERT(call->arguments()->length() == 1);
10178 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10257 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10179 HValue* value = Pop(); 10258 HValue* value = Pop();
10180 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); 10259 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
10181 return ast_context()->ReturnInstruction(result, call->id()); 10260 return ast_context()->ReturnInstruction(result, call->id());
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
10511 stream->Add("\n"); 10590 stream->Add("\n");
10512 } 10591 }
10513 PrintF("\n"); 10592 PrintF("\n");
10514 } 10593 }
10515 10594
10516 10595
10517 void HEnvironment::PrintToStd() { 10596 void HEnvironment::PrintToStd() {
10518 HeapStringAllocator string_allocator; 10597 HeapStringAllocator string_allocator;
10519 StringStream trace(&string_allocator); 10598 StringStream trace(&string_allocator);
10520 PrintTo(&trace); 10599 PrintTo(&trace);
10521 PrintF("%s", *trace.ToCString()); 10600 PrintF("%s", trace.ToCString().get());
10522 } 10601 }
10523 10602
10524 10603
10525 void HTracer::TraceCompilation(CompilationInfo* info) { 10604 void HTracer::TraceCompilation(CompilationInfo* info) {
10526 Tag tag(this, "compilation"); 10605 Tag tag(this, "compilation");
10527 if (info->IsOptimizing()) { 10606 if (info->IsOptimizing()) {
10528 Handle<String> name = info->function()->debug_name(); 10607 Handle<String> name = info->function()->debug_name();
10529 PrintStringProperty("name", *name->ToCString()); 10608 PrintStringProperty("name", name->ToCString().get());
10530 PrintStringProperty("method", *name->ToCString()); 10609 PrintStringProperty("method", name->ToCString().get());
10531 } else { 10610 } else {
10532 CodeStub::Major major_key = info->code_stub()->MajorKey(); 10611 CodeStub::Major major_key = info->code_stub()->MajorKey();
10533 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); 10612 PrintStringProperty("name", CodeStub::MajorName(major_key, false));
10534 PrintStringProperty("method", "stub"); 10613 PrintStringProperty("method", "stub");
10535 } 10614 }
10536 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 10615 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
10537 } 10616 }
10538 10617
10539 10618
10540 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 10619 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
10740 } 10819 }
10741 current_pos = current_pos->next(); 10820 current_pos = current_pos->next();
10742 } 10821 }
10743 10822
10744 trace_.Add(" \"\"\n"); 10823 trace_.Add(" \"\"\n");
10745 } 10824 }
10746 } 10825 }
10747 10826
10748 10827
10749 void HTracer::FlushToFile() { 10828 void HTracer::FlushToFile() {
10750 AppendChars(filename_.start(), *trace_.ToCString(), trace_.length(), false); 10829 AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
10830 false);
10751 trace_.Reset(); 10831 trace_.Reset();
10752 } 10832 }
10753 10833
10754 10834
10755 void HStatistics::Initialize(CompilationInfo* info) { 10835 void HStatistics::Initialize(CompilationInfo* info) {
10756 if (info->shared_info().is_null()) return; 10836 if (info->shared_info().is_null()) return;
10757 source_size_ += info->shared_info()->SourceSize(); 10837 source_size_ += info->shared_info()->SourceSize();
10758 } 10838 }
10759 10839
10760 10840
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
10830 if (ShouldProduceTraceOutput()) { 10910 if (ShouldProduceTraceOutput()) {
10831 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10911 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10832 } 10912 }
10833 10913
10834 #ifdef DEBUG 10914 #ifdef DEBUG
10835 graph_->Verify(false); // No full verify. 10915 graph_->Verify(false); // No full verify.
10836 #endif 10916 #endif
10837 } 10917 }
10838 10918
10839 } } // namespace v8::internal 10919 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-check-elimination.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698