| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "hydrogen-minus-zero.h" | 51 #include "hydrogen-minus-zero.h" |
| 52 #include "hydrogen-osr.h" | 52 #include "hydrogen-osr.h" |
| 53 #include "hydrogen-range-analysis.h" | 53 #include "hydrogen-range-analysis.h" |
| 54 #include "hydrogen-redundant-phi.h" | 54 #include "hydrogen-redundant-phi.h" |
| 55 #include "hydrogen-removable-simulates.h" | 55 #include "hydrogen-removable-simulates.h" |
| 56 #include "hydrogen-representation-changes.h" | 56 #include "hydrogen-representation-changes.h" |
| 57 #include "hydrogen-sce.h" | 57 #include "hydrogen-sce.h" |
| 58 #include "hydrogen-uint32-analysis.h" | 58 #include "hydrogen-uint32-analysis.h" |
| 59 #include "lithium-allocator.h" | 59 #include "lithium-allocator.h" |
| 60 #include "parser.h" | 60 #include "parser.h" |
| 61 #include "runtime.h" |
| 61 #include "scopeinfo.h" | 62 #include "scopeinfo.h" |
| 62 #include "scopes.h" | 63 #include "scopes.h" |
| 63 #include "stub-cache.h" | 64 #include "stub-cache.h" |
| 64 #include "typing.h" | 65 #include "typing.h" |
| 65 | 66 |
| 66 #if V8_TARGET_ARCH_IA32 | 67 #if V8_TARGET_ARCH_IA32 |
| 67 #include "ia32/lithium-codegen-ia32.h" | 68 #include "ia32/lithium-codegen-ia32.h" |
| 68 #elif V8_TARGET_ARCH_X64 | 69 #elif V8_TARGET_ARCH_X64 |
| 69 #include "x64/lithium-codegen-x64.h" | 70 #include "x64/lithium-codegen-x64.h" |
| 70 #elif V8_TARGET_ARCH_A64 | 71 #elif V8_TARGET_ARCH_A64 |
| (...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 set_current_block(NULL); | 1191 set_current_block(NULL); |
| 1191 } | 1192 } |
| 1192 } | 1193 } |
| 1193 | 1194 |
| 1194 | 1195 |
| 1195 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1196 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
| 1196 if (FLAG_native_code_counters && counter->Enabled()) { | 1197 if (FLAG_native_code_counters && counter->Enabled()) { |
| 1197 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1198 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
| 1198 HValue* old_value = Add<HLoadNamedField>(reference, | 1199 HValue* old_value = Add<HLoadNamedField>(reference, |
| 1199 HObjectAccess::ForCounter()); | 1200 HObjectAccess::ForCounter()); |
| 1200 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1201 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); |
| 1201 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1202 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
| 1202 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1203 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 1203 new_value); | 1204 new_value); |
| 1204 } | 1205 } |
| 1205 } | 1206 } |
| 1206 | 1207 |
| 1207 | 1208 |
| 1208 void HGraphBuilder::AddSimulate(BailoutId id, | 1209 void HGraphBuilder::AddSimulate(BailoutId id, |
| 1209 RemovableSimulate removable) { | 1210 RemovableSimulate removable) { |
| 1210 ASSERT(current_block() != NULL); | 1211 ASSERT(current_block() != NULL); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 ASSERT(continuation->predecessors()->length() == 0); | 1269 ASSERT(continuation->predecessors()->length() == 0); |
| 1269 } | 1270 } |
| 1270 } | 1271 } |
| 1271 | 1272 |
| 1272 | 1273 |
| 1273 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { | 1274 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { |
| 1274 return Add<HCheckMaps>(obj, map, top_info()); | 1275 return Add<HCheckMaps>(obj, map, top_info()); |
| 1275 } | 1276 } |
| 1276 | 1277 |
| 1277 | 1278 |
| 1278 HValue* HGraphBuilder::BuildCheckString( | 1279 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
| 1279 HValue* object, const char* failure_reason) { | 1280 if (!string->type().IsString()) { |
| 1280 if (!object->type().IsString()) { | 1281 ASSERT(!string->IsConstant() || |
| 1281 ASSERT(!object->IsConstant() || | 1282 !HConstant::cast(string)->HasStringValue()); |
| 1282 !HConstant::cast(object)->HasStringValue()); | 1283 BuildCheckHeapObject(string); |
| 1283 IfBuilder if_isstring(this); | 1284 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); |
| 1284 if_isstring.If<HIsStringAndBranch>(object); | |
| 1285 if_isstring.Then(); | |
| 1286 if_isstring.ElseDeopt(failure_reason); | |
| 1287 } | 1285 } |
| 1288 return object; | 1286 return string; |
| 1289 } | 1287 } |
| 1290 | 1288 |
| 1291 | 1289 |
| 1292 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { | 1290 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { |
| 1293 if (object->type().IsJSObject()) return object; | 1291 if (object->type().IsJSObject()) return object; |
| 1294 return Add<HWrapReceiver>(object, function); | 1292 return Add<HWrapReceiver>(object, function); |
| 1295 } | 1293 } |
| 1296 | 1294 |
| 1297 | 1295 |
| 1298 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1296 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 HValue* elements = AddLoadElements(receiver); | 1535 HValue* elements = AddLoadElements(receiver); |
| 1538 | 1536 |
| 1539 HValue* hash = BuildElementIndexHash(key); | 1537 HValue* hash = BuildElementIndexHash(key); |
| 1540 | 1538 |
| 1541 HValue* capacity = Add<HLoadKeyed>( | 1539 HValue* capacity = Add<HLoadKeyed>( |
| 1542 elements, | 1540 elements, |
| 1543 Add<HConstant>(NameDictionary::kCapacityIndex), | 1541 Add<HConstant>(NameDictionary::kCapacityIndex), |
| 1544 static_cast<HValue*>(NULL), | 1542 static_cast<HValue*>(NULL), |
| 1545 FAST_SMI_ELEMENTS); | 1543 FAST_SMI_ELEMENTS); |
| 1546 | 1544 |
| 1547 HValue* mask = Add<HSub>(capacity, graph()->GetConstant1()); | 1545 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
| 1548 mask->ChangeRepresentation(Representation::Integer32()); | 1546 mask->ChangeRepresentation(Representation::Integer32()); |
| 1549 mask->ClearFlag(HValue::kCanOverflow); | 1547 mask->ClearFlag(HValue::kCanOverflow); |
| 1550 | 1548 |
| 1551 return BuildUncheckedDictionaryElementLoadHelper(elements, key, | 1549 return BuildUncheckedDictionaryElementLoadHelper(elements, key, |
| 1552 hash, mask, 0); | 1550 hash, mask, 0); |
| 1553 } | 1551 } |
| 1554 | 1552 |
| 1555 | 1553 |
| 1556 HValue* HGraphBuilder::BuildNumberToString(HValue* object, | 1554 HValue* HGraphBuilder::BuildNumberToString(HValue* object, |
| 1557 Handle<Type> type) { | 1555 Handle<Type> type) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1569 graph()->CreateBasicBlock()); | 1567 graph()->CreateBasicBlock()); |
| 1570 | 1568 |
| 1571 // Load the number string cache. | 1569 // Load the number string cache. |
| 1572 HValue* number_string_cache = | 1570 HValue* number_string_cache = |
| 1573 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); | 1571 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); |
| 1574 | 1572 |
| 1575 // Make the hash mask from the length of the number string cache. It | 1573 // Make the hash mask from the length of the number string cache. It |
| 1576 // contains two elements (number and string) for each cache entry. | 1574 // contains two elements (number and string) for each cache entry. |
| 1577 HValue* mask = AddLoadFixedArrayLength(number_string_cache); | 1575 HValue* mask = AddLoadFixedArrayLength(number_string_cache); |
| 1578 mask->set_type(HType::Smi()); | 1576 mask->set_type(HType::Smi()); |
| 1579 mask = Add<HSar>(mask, graph()->GetConstant1()); | 1577 mask = AddUncasted<HSar>(mask, graph()->GetConstant1()); |
| 1580 mask = Add<HSub>(mask, graph()->GetConstant1()); | 1578 mask = AddUncasted<HSub>(mask, graph()->GetConstant1()); |
| 1581 | 1579 |
| 1582 // Check whether object is a smi. | 1580 // Check whether object is a smi. |
| 1583 IfBuilder if_objectissmi(this); | 1581 IfBuilder if_objectissmi(this); |
| 1584 if_objectissmi.If<HIsSmiAndBranch>(object); | 1582 if_objectissmi.If<HIsSmiAndBranch>(object); |
| 1585 if_objectissmi.Then(); | 1583 if_objectissmi.Then(); |
| 1586 { | 1584 { |
| 1587 // Compute hash for smi similar to smi_get_hash(). | 1585 // Compute hash for smi similar to smi_get_hash(). |
| 1588 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask); | 1586 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask); |
| 1589 | 1587 |
| 1590 // Load the key. | 1588 // Load the key. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 HValue* dst, | 1712 HValue* dst, |
| 1715 HValue* dst_offset, | 1713 HValue* dst_offset, |
| 1716 String::Encoding dst_encoding, | 1714 String::Encoding dst_encoding, |
| 1717 HValue* length) { | 1715 HValue* length) { |
| 1718 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 1716 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
| 1719 src_encoding == String::ONE_BYTE_ENCODING); | 1717 src_encoding == String::ONE_BYTE_ENCODING); |
| 1720 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1718 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
| 1721 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1719 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1722 { | 1720 { |
| 1723 HValue* src_index = AddUncasted<HAdd>(src_offset, index); | 1721 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
| 1724 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); | 1722 HValue* value = |
| 1723 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); |
| 1725 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); | 1724 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
| 1726 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 1725 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
| 1727 } | 1726 } |
| 1728 loop.EndBody(); | 1727 loop.EndBody(); |
| 1729 } | 1728 } |
| 1730 | 1729 |
| 1731 | 1730 |
| 1732 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1731 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, |
| 1733 HValue* right, | 1732 HValue* right, |
| 1734 PretenureFlag pretenure_flag) { | 1733 PretenureFlag pretenure_flag) { |
| 1735 // Determine the string lengths. | 1734 // Determine the string lengths. |
| 1736 HValue* left_length = Add<HLoadNamedField>( | 1735 HValue* left_length = Add<HLoadNamedField>( |
| 1737 left, HObjectAccess::ForStringLength()); | 1736 left, HObjectAccess::ForStringLength()); |
| 1738 HValue* right_length = Add<HLoadNamedField>( | 1737 HValue* right_length = Add<HLoadNamedField>( |
| 1739 right, HObjectAccess::ForStringLength()); | 1738 right, HObjectAccess::ForStringLength()); |
| 1740 | 1739 |
| 1741 // Check if we concatenated the strings here, or if we have to resort to the | 1740 // Compute the combined string length. If the result is larger than the max |
| 1742 // runtime function. | 1741 // supported string length, we bailout to the runtime. This is done implicitly |
| 1743 HIfContinuation handled(graph()->CreateBasicBlock(), | 1742 // when converting the result back to a smi in case the max string length |
| 1744 graph()->CreateBasicBlock()); | 1743 // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do |
| 1745 | 1744 HValue* length = AddUncasted<HAdd>(left_length, right_length); |
| 1746 // Check if both parameters do not exceed half the max string length, because | 1745 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 1747 // exceptionally long strings should be handled in the runtime. Unfortunately | 1746 if (String::kMaxLength != Smi::kMaxValue) { |
| 1748 // we cannot actually check whether the combined length of both strings | 1747 IfBuilder if_nooverflow(this); |
| 1749 // exceeds String::kMaxLength (because of unclear results from the | 1748 if_nooverflow.If<HCompareNumericAndBranch>( |
| 1750 // representation inference phase), so we use a pessimistic approach here | 1749 length, Add<HConstant>(String::kMaxLength), Token::LTE); |
| 1751 // instead, checking that the length of either substring does not exceed half | 1750 if_nooverflow.Then(); |
| 1752 // of String::kMaxLength. | 1751 if_nooverflow.ElseDeopt("String length exceeds limit"); |
| 1753 HConstant* max_length = Add<HConstant>(String::kMaxLength / 2); | 1752 } |
| 1754 IfBuilder if_nooverflow(this); | 1753 |
| 1755 if_nooverflow.If<HCompareNumericAndBranch>( | 1754 // Determine the string instance types. |
| 1756 left_length, max_length, Token::LTE); | 1755 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( |
| 1757 if_nooverflow.AndIf<HCompareNumericAndBranch>( | 1756 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), |
| 1758 right_length, max_length, Token::LTE); | 1757 HObjectAccess::ForMapInstanceType()); |
| 1759 if_nooverflow.Then(); | 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. |
| 1767 IfBuilder if_createcons(this); |
| 1768 if_createcons.If<HCompareNumericAndBranch>( |
| 1769 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
| 1770 if_createcons.Then(); |
| 1760 { | 1771 { |
| 1761 // Determine the string instance types. | 1772 // Allocate the cons string object. HAllocate does not care whether we |
| 1762 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | 1773 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use |
| 1763 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | 1774 // CONS_STRING_TYPE here. Below we decide whether the cons string is |
| 1764 HObjectAccess::ForMapInstanceType()); | 1775 // one-byte or two-byte and set the appropriate map. |
| 1765 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | 1776 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), |
| 1766 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | 1777 HType::String(), pretenure_flag, |
| 1767 HObjectAccess::ForMapInstanceType()); | 1778 CONS_STRING_TYPE); |
| 1768 | 1779 |
| 1769 // Compute difference of instance types. | 1780 // Compute the intersection of instance types. |
| 1770 HValue* xored_instance_types = AddUncasted<HBitwise>( | 1781 HValue* anded_instance_types = AddUncasted<HBitwise>( |
| 1771 Token::BIT_XOR, left_instance_type, right_instance_type); | 1782 Token::BIT_AND, left_instance_type, right_instance_type); |
| 1772 | 1783 |
| 1773 // Compute the length of the resulting string. | 1784 // We create a one-byte cons string if |
| 1774 HValue* length = AddUncasted<HAdd>(left_length, right_length); | 1785 // 1. both strings are one-byte, or |
| 1775 | 1786 // 2. at least one of the strings is two-byte, but happens to contain only |
| 1776 // Check if we should create a cons string. | 1787 // one-byte characters. |
| 1777 IfBuilder if_createcons(this); | 1788 // To do this, we check |
| 1778 if_createcons.If<HCompareNumericAndBranch>( | 1789 // 1. if both strings are one-byte, or if the one-byte data hint is set in |
| 1779 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 1790 // both strings, or |
| 1780 if_createcons.Then(); | 1791 // 2. if one of the strings has the one-byte data hint set and the other |
| 1781 { | 1792 // string is one-byte. |
| 1782 // Allocate the cons string object. HAllocate does not care whether we | 1793 IfBuilder if_onebyte(this); |
| 1783 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 1794 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1784 // CONS_STRING_TYPE here. Below we decide whether the cons string is | 1795 STATIC_ASSERT(kOneByteDataHintMask != 0); |
| 1785 // one-byte or two-byte and set the appropriate map. | 1796 if_onebyte.If<HCompareNumericAndBranch>( |
| 1786 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | 1797 AddUncasted<HBitwise>( |
| 1787 HType::String(), pretenure_flag, | 1798 Token::BIT_AND, anded_instance_types, |
| 1788 CONS_STRING_TYPE); | 1799 Add<HConstant>(static_cast<int32_t>( |
| 1789 | 1800 kStringEncodingMask | kOneByteDataHintMask))), |
| 1790 // Compute the intersection of instance types. | 1801 graph()->GetConstant0(), Token::NE); |
| 1791 HValue* anded_instance_types = AddUncasted<HBitwise>( | 1802 if_onebyte.Or(); |
| 1792 Token::BIT_AND, left_instance_type, right_instance_type); | 1803 STATIC_ASSERT(kOneByteStringTag != 0 && |
| 1793 | 1804 kOneByteDataHintTag != 0 && |
| 1794 // We create a one-byte cons string if | 1805 kOneByteDataHintTag != kOneByteStringTag); |
| 1795 // 1. both strings are one-byte, or | 1806 if_onebyte.If<HCompareNumericAndBranch>( |
| 1796 // 2. at least one of the strings is two-byte, but happens to contain only | 1807 AddUncasted<HBitwise>( |
| 1797 // one-byte characters. | 1808 Token::BIT_AND, xored_instance_types, |
| 1798 // To do this, we check | 1809 Add<HConstant>(static_cast<int32_t>( |
| 1799 // 1. if both strings are one-byte, or if the one-byte data hint is set in | 1810 kOneByteStringTag | kOneByteDataHintTag))), |
| 1800 // both strings, or | 1811 Add<HConstant>(static_cast<int32_t>( |
| 1801 // 2. if one of the strings has the one-byte data hint set and the other | 1812 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); |
| 1802 // string is one-byte. | 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 } |
| 1841 if_createcons.Else(); |
| 1842 { |
| 1843 // Compute union of instance types. |
| 1844 HValue* ored_instance_types = AddUncasted<HBitwise>( |
| 1845 Token::BIT_OR, left_instance_type, right_instance_type); |
| 1846 |
| 1847 // Check if both strings have the same encoding and both are |
| 1848 // sequential. |
| 1849 IfBuilder if_sameencodingandsequential(this); |
| 1850 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1851 AddUncasted<HBitwise>( |
| 1852 Token::BIT_AND, xored_instance_types, |
| 1853 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1854 graph()->GetConstant0(), Token::EQ); |
| 1855 if_sameencodingandsequential.And(); |
| 1856 STATIC_ASSERT(kSeqStringTag == 0); |
| 1857 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1858 AddUncasted<HBitwise>( |
| 1859 Token::BIT_AND, ored_instance_types, |
| 1860 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |
| 1861 graph()->GetConstant0(), Token::EQ); |
| 1862 if_sameencodingandsequential.Then(); |
| 1863 { |
| 1864 // Check if the result is a one-byte string. |
| 1803 IfBuilder if_onebyte(this); | 1865 IfBuilder if_onebyte(this); |
| 1804 STATIC_ASSERT(kOneByteStringTag != 0); | 1866 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1805 STATIC_ASSERT(kOneByteDataHintMask != 0); | |
| 1806 if_onebyte.If<HCompareNumericAndBranch>( | 1867 if_onebyte.If<HCompareNumericAndBranch>( |
| 1807 AddUncasted<HBitwise>( | 1868 AddUncasted<HBitwise>( |
| 1808 Token::BIT_AND, anded_instance_types, | 1869 Token::BIT_AND, ored_instance_types, |
| 1809 Add<HConstant>(static_cast<int32_t>( | 1870 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1810 kStringEncodingMask | kOneByteDataHintMask))), | |
| 1811 graph()->GetConstant0(), Token::NE); | 1871 graph()->GetConstant0(), Token::NE); |
| 1812 if_onebyte.Or(); | |
| 1813 STATIC_ASSERT(kOneByteStringTag != 0 && | |
| 1814 kOneByteDataHintTag != 0 && | |
| 1815 kOneByteDataHintTag != kOneByteStringTag); | |
| 1816 if_onebyte.If<HCompareNumericAndBranch>( | |
| 1817 AddUncasted<HBitwise>( | |
| 1818 Token::BIT_AND, xored_instance_types, | |
| 1819 Add<HConstant>(static_cast<int32_t>( | |
| 1820 kOneByteStringTag | kOneByteDataHintTag))), | |
| 1821 Add<HConstant>(static_cast<int32_t>( | |
| 1822 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | |
| 1823 if_onebyte.Then(); | 1872 if_onebyte.Then(); |
| 1824 { | 1873 { |
| 1825 // We can safely skip the write barrier for storing the map here. | 1874 // Calculate the number of bytes needed for the characters in the |
| 1826 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | 1875 // string while observing object alignment. |
| 1876 HValue* size = BuildSeqStringSizeFor( |
| 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. |
| 1827 AddStoreMapConstantNoWriteBarrier(string, map); | 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); |
| 1828 } | 1910 } |
| 1829 if_onebyte.Else(); | 1911 if_onebyte.Else(); |
| 1830 { | 1912 { |
| 1831 // We can safely skip the write barrier for storing the map here. | 1913 // Calculate the number of bytes needed for the characters in the |
| 1832 Handle<Map> map = isolate()->factory()->cons_string_map(); | 1914 // string while observing object alignment. |
| 1915 HValue* size = BuildSeqStringSizeFor( |
| 1916 length, String::TWO_BYTE_ENCODING); |
| 1917 |
| 1918 // Allocate the two-byte string object. |
| 1919 Handle<Map> map = isolate()->factory()->string_map(); |
| 1920 HAllocate* string = Add<HAllocate>(size, HType::String(), |
| 1921 pretenure_flag, STRING_TYPE); |
| 1922 string->set_known_initial_map(map); |
| 1923 |
| 1924 // We can safely skip the write barrier for storing map here. |
| 1833 AddStoreMapConstantNoWriteBarrier(string, map); | 1925 AddStoreMapConstantNoWriteBarrier(string, map); |
| 1926 |
| 1927 // Length must be stored into the string before we copy characters to |
| 1928 // make debug verification code happy. |
| 1929 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), |
| 1930 length); |
| 1931 |
| 1932 // Copy bytes from the left string. |
| 1933 BuildCopySeqStringChars( |
| 1934 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1935 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1936 left_length); |
| 1937 |
| 1938 // Copy bytes from the right string. |
| 1939 BuildCopySeqStringChars( |
| 1940 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, |
| 1941 string, left_length, String::TWO_BYTE_ENCODING, |
| 1942 right_length); |
| 1943 |
| 1944 // Return the string. |
| 1945 Push(string); |
| 1834 } | 1946 } |
| 1835 if_onebyte.End(); | 1947 if_onebyte.End(); |
| 1836 | 1948 |
| 1837 // Initialize the cons string fields. | 1949 // Initialize the (common) string fields. |
| 1950 HValue* string = Pop(); |
| 1838 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | 1951 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), |
| 1839 Add<HConstant>(String::kEmptyHashField)); | 1952 Add<HConstant>(String::kEmptyHashField)); |
| 1840 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length); | 1953 |
| 1841 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | 1954 // Count the native string addition. |
| 1842 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | 1955 AddIncrementCounter(isolate()->counters()->string_add_native()); |
| 1843 right); | 1956 |
| 1844 | |
| 1845 // Cons string is result. | |
| 1846 Push(string); | 1957 Push(string); |
| 1847 } | 1958 } |
| 1848 if_createcons.Else(); | 1959 if_sameencodingandsequential.Else(); |
| 1849 { | 1960 { |
| 1850 // Compute union of instance types. | 1961 // Fallback to the runtime to add the two strings. |
| 1851 HValue* ored_instance_types = AddUncasted<HBitwise>( | 1962 Add<HPushArgument>(left); |
| 1852 Token::BIT_OR, left_instance_type, right_instance_type); | 1963 Add<HPushArgument>(right); |
| 1853 | 1964 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 1854 // Check if both strings have the same encoding and both are | 1965 Runtime::FunctionForId(Runtime::kStringAdd), |
| 1855 // sequential. | 1966 2)); |
| 1856 IfBuilder if_sameencodingandsequential(this); | 1967 } |
| 1857 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1968 if_sameencodingandsequential.End(); |
| 1858 AddUncasted<HBitwise>( | |
| 1859 Token::BIT_AND, xored_instance_types, | |
| 1860 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | |
| 1861 graph()->GetConstant0(), Token::EQ); | |
| 1862 if_sameencodingandsequential.And(); | |
| 1863 STATIC_ASSERT(kSeqStringTag == 0); | |
| 1864 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | |
| 1865 AddUncasted<HBitwise>( | |
| 1866 Token::BIT_AND, ored_instance_types, | |
| 1867 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), | |
| 1868 graph()->GetConstant0(), Token::EQ); | |
| 1869 if_sameencodingandsequential.Then(); | |
| 1870 { | |
| 1871 // Check if the result is a one-byte string. | |
| 1872 IfBuilder if_onebyte(this); | |
| 1873 STATIC_ASSERT(kOneByteStringTag != 0); | |
| 1874 if_onebyte.If<HCompareNumericAndBranch>( | |
| 1875 AddUncasted<HBitwise>( | |
| 1876 Token::BIT_AND, ored_instance_types, | |
| 1877 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | |
| 1878 graph()->GetConstant0(), Token::NE); | |
| 1879 if_onebyte.Then(); | |
| 1880 { | |
| 1881 // Calculate the number of bytes needed for the characters in the | |
| 1882 // string while observing object alignment. | |
| 1883 HValue* size = BuildSeqStringSizeFor( | |
| 1884 length, String::ONE_BYTE_ENCODING); | |
| 1885 | |
| 1886 // Allocate the ASCII string object. | |
| 1887 Handle<Map> map = isolate()->factory()->ascii_string_map(); | |
| 1888 HAllocate* string = Add<HAllocate>(size, HType::String(), | |
| 1889 pretenure_flag, ASCII_STRING_TYPE); | |
| 1890 string->set_known_initial_map(map); | |
| 1891 | |
| 1892 // We can safely skip the write barrier for storing map here. | |
| 1893 AddStoreMapConstantNoWriteBarrier(string, map); | |
| 1894 | |
| 1895 // Length must be stored into the string before we copy characters to | |
| 1896 // make debug verification code happy. | |
| 1897 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
| 1898 length); | |
| 1899 | |
| 1900 // Copy bytes from the left string. | |
| 1901 BuildCopySeqStringChars( | |
| 1902 left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
| 1903 string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
| 1904 left_length); | |
| 1905 | |
| 1906 // Copy bytes from the right string. | |
| 1907 BuildCopySeqStringChars( | |
| 1908 right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, | |
| 1909 string, left_length, String::ONE_BYTE_ENCODING, | |
| 1910 right_length); | |
| 1911 | |
| 1912 // Return the string. | |
| 1913 Push(string); | |
| 1914 } | |
| 1915 if_onebyte.Else(); | |
| 1916 { | |
| 1917 // Calculate the number of bytes needed for the characters in the | |
| 1918 // string while observing object alignment. | |
| 1919 HValue* size = BuildSeqStringSizeFor( | |
| 1920 length, String::TWO_BYTE_ENCODING); | |
| 1921 | |
| 1922 // Allocate the two-byte string object. | |
| 1923 Handle<Map> map = isolate()->factory()->string_map(); | |
| 1924 HAllocate* string = Add<HAllocate>(size, HType::String(), | |
| 1925 pretenure_flag, STRING_TYPE); | |
| 1926 string->set_known_initial_map(map); | |
| 1927 | |
| 1928 // We can safely skip the write barrier for storing map here. | |
| 1929 AddStoreMapConstantNoWriteBarrier(string, map); | |
| 1930 | |
| 1931 // Length must be stored into the string before we copy characters to | |
| 1932 // make debug verification code happy. | |
| 1933 Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), | |
| 1934 length); | |
| 1935 | |
| 1936 // Copy bytes from the left string. | |
| 1937 BuildCopySeqStringChars( | |
| 1938 left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | |
| 1939 string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | |
| 1940 left_length); | |
| 1941 | |
| 1942 // Copy bytes from the right string. | |
| 1943 BuildCopySeqStringChars( | |
| 1944 right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, | |
| 1945 string, left_length, String::TWO_BYTE_ENCODING, | |
| 1946 right_length); | |
| 1947 | |
| 1948 // Return the string. | |
| 1949 Push(string); | |
| 1950 } | |
| 1951 if_onebyte.End(); | |
| 1952 | |
| 1953 // Initialize the (common) string fields. | |
| 1954 HValue* string = Pop(); | |
| 1955 Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(), | |
| 1956 Add<HConstant>(String::kEmptyHashField)); | |
| 1957 Push(string); | |
| 1958 } | |
| 1959 if_sameencodingandsequential.JoinContinuation(&handled); | |
| 1960 } | |
| 1961 if_createcons.JoinContinuation(&handled); | |
| 1962 } | 1969 } |
| 1963 if_nooverflow.JoinContinuation(&handled); | 1970 if_createcons.End(); |
| 1964 | |
| 1965 // Check if the strings were concatenated successfully, otherwise fallback to | |
| 1966 // add the strings in the runtime. | |
| 1967 IfBuilder if_handled(this, &handled); | |
| 1968 if_handled.Then(); | |
| 1969 { | |
| 1970 // Count the native string addition. | |
| 1971 AddIncrementCounter(isolate()->counters()->string_add_native()); | |
| 1972 } | |
| 1973 if_handled.Else(); | |
| 1974 { | |
| 1975 // Fallback to the runtime to add the two strings. | |
| 1976 Add<HPushArgument>(left); | |
| 1977 Add<HPushArgument>(right); | |
| 1978 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | |
| 1979 Runtime::FunctionForId(Runtime::kStringAdd), | |
| 1980 2)); | |
| 1981 } | |
| 1982 if_handled.End(); | |
| 1983 | 1971 |
| 1984 return Pop(); | 1972 return Pop(); |
| 1985 } | 1973 } |
| 1986 | 1974 |
| 1987 | 1975 |
| 1988 HValue* HGraphBuilder::BuildStringAdd(HValue* left, | 1976 HValue* HGraphBuilder::BuildStringAdd(HValue* left, |
| 1989 HValue* right, | 1977 HValue* right, |
| 1990 PretenureFlag pretenure_flag) { | 1978 PretenureFlag pretenure_flag) { |
| 1991 // Determine the string lengths. | 1979 // Determine the string lengths. |
| 1992 HValue* left_length = Add<HLoadNamedField>( | 1980 HValue* left_length = Add<HLoadNamedField>( |
| (...skipping 3122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5115 AllocationSiteUsageContext usage_context(isolate(), site, false); | 5103 AllocationSiteUsageContext usage_context(isolate(), site, false); |
| 5116 usage_context.EnterNewScope(); | 5104 usage_context.EnterNewScope(); |
| 5117 literal = BuildFastLiteral(boilerplate_object, &usage_context); | 5105 literal = BuildFastLiteral(boilerplate_object, &usage_context); |
| 5118 usage_context.ExitScope(site, boilerplate_object); | 5106 usage_context.ExitScope(site, boilerplate_object); |
| 5119 } else { | 5107 } else { |
| 5120 NoObservableSideEffectsScope no_effects(this); | 5108 NoObservableSideEffectsScope no_effects(this); |
| 5121 // Boilerplate already exists and constant elements are never accessed, | 5109 // Boilerplate already exists and constant elements are never accessed, |
| 5122 // pass an empty fixed array to the runtime function instead. | 5110 // pass an empty fixed array to the runtime function instead. |
| 5123 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 5111 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 5124 int literal_index = expr->literal_index(); | 5112 int literal_index = expr->literal_index(); |
| 5113 int flags = expr->depth() == 1 |
| 5114 ? ArrayLiteral::kShallowElements |
| 5115 : ArrayLiteral::kNoFlags; |
| 5116 flags |= ArrayLiteral::kDisableMementos; |
| 5125 | 5117 |
| 5126 Add<HPushArgument>(Add<HConstant>(literals)); | 5118 Add<HPushArgument>(Add<HConstant>(literals)); |
| 5127 Add<HPushArgument>(Add<HConstant>(literal_index)); | 5119 Add<HPushArgument>(Add<HConstant>(literal_index)); |
| 5128 Add<HPushArgument>(Add<HConstant>(constants)); | 5120 Add<HPushArgument>(Add<HConstant>(constants)); |
| 5121 Add<HPushArgument>(Add<HConstant>(flags)); |
| 5129 | 5122 |
| 5130 // TODO(mvstanton): Consider a flag to turn off creation of any | 5123 // TODO(mvstanton): Consider a flag to turn off creation of any |
| 5131 // AllocationMementos for this call: we are in crankshaft and should have | 5124 // AllocationMementos for this call: we are in crankshaft and should have |
| 5132 // learned enough about transition behavior to stop emitting mementos. | 5125 // learned enough about transition behavior to stop emitting mementos. |
| 5133 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; | 5126 Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral; |
| 5134 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5127 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5135 Runtime::FunctionForId(function_id), | 5128 Runtime::FunctionForId(function_id), |
| 5136 3); | 5129 4); |
| 5137 | 5130 |
| 5138 // De-opt if elements kind changed from boilerplate_elements_kind. | 5131 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 5139 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); | 5132 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); |
| 5140 literal = Add<HCheckMaps>(literal, map, top_info()); | 5133 literal = Add<HCheckMaps>(literal, map, top_info()); |
| 5141 } | 5134 } |
| 5142 | 5135 |
| 5143 // The array is expected in the bailout environment during computation | 5136 // The array is expected in the bailout environment during computation |
| 5144 // of the property values and is the value of the entire expression. | 5137 // of the property values and is the value of the entire expression. |
| 5145 Push(literal); | 5138 Push(literal); |
| 5146 // The literal index is on the stack, too. | 5139 // The literal index is on the stack, too. |
| (...skipping 2354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7501 } | 7494 } |
| 7502 } | 7495 } |
| 7503 | 7496 |
| 7504 if (result == NULL) { | 7497 if (result == NULL) { |
| 7505 result = NewUncasted<HPower>(left, right); | 7498 result = NewUncasted<HPower>(left, right); |
| 7506 } | 7499 } |
| 7507 ast_context()->ReturnInstruction(result, expr->id()); | 7500 ast_context()->ReturnInstruction(result, expr->id()); |
| 7508 return true; | 7501 return true; |
| 7509 } | 7502 } |
| 7510 break; | 7503 break; |
| 7511 case kMathRandom: | |
| 7512 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | |
| 7513 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7514 Drop(1); // Receiver. | |
| 7515 HGlobalObject* global_object = Add<HGlobalObject>(); | |
| 7516 HRandom* result = New<HRandom>(global_object); | |
| 7517 ast_context()->ReturnInstruction(result, expr->id()); | |
| 7518 return true; | |
| 7519 } | |
| 7520 break; | |
| 7521 case kMathMax: | 7504 case kMathMax: |
| 7522 case kMathMin: | 7505 case kMathMin: |
| 7523 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7506 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 7524 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7507 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7525 HValue* right = Pop(); | 7508 HValue* right = Pop(); |
| 7526 HValue* left = Pop(); | 7509 HValue* left = Pop(); |
| 7527 Drop(1); // Receiver. | 7510 Drop(1); // Receiver. |
| 7528 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin | 7511 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
| 7529 : HMathMinMax::kMathMax; | 7512 : HMathMinMax::kMathMax; |
| 7530 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); | 7513 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8090 &HOptimizedGraphBuilder::Generate##Name, | 8073 &HOptimizedGraphBuilder::Generate##Name, |
| 8091 | 8074 |
| 8092 const HOptimizedGraphBuilder::InlineFunctionGenerator | 8075 const HOptimizedGraphBuilder::InlineFunctionGenerator |
| 8093 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 8076 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { |
| 8094 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 8077 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 8095 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 8078 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 8096 }; | 8079 }; |
| 8097 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 8080 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 8098 | 8081 |
| 8099 | 8082 |
| 8083 template <class ViewClass> |
| 8084 void HGraphBuilder::BuildArrayBufferViewInitialization( |
| 8085 HValue* obj, |
| 8086 HValue* buffer, |
| 8087 HValue* byte_offset, |
| 8088 HValue* byte_length) { |
| 8089 |
| 8090 for (int offset = ViewClass::kSize; |
| 8091 offset < ViewClass::kSizeWithInternalFields; |
| 8092 offset += kPointerSize) { |
| 8093 Add<HStoreNamedField>(obj, |
| 8094 HObjectAccess::ForJSObjectOffset(offset), |
| 8095 Add<HConstant>(static_cast<int32_t>(0))); |
| 8096 } |
| 8097 |
| 8098 Add<HStoreNamedField>( |
| 8099 obj, |
| 8100 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); |
| 8101 Add<HStoreNamedField>( |
| 8102 obj, |
| 8103 HObjectAccess::ForJSArrayBufferViewByteOffset(), |
| 8104 byte_offset); |
| 8105 Add<HStoreNamedField>( |
| 8106 obj, |
| 8107 HObjectAccess::ForJSArrayBufferViewByteLength(), |
| 8108 byte_length); |
| 8109 |
| 8110 HObjectAccess weak_first_view_access = |
| 8111 HObjectAccess::ForJSArrayBufferWeakFirstView(); |
| 8112 Add<HStoreNamedField>(obj, |
| 8113 HObjectAccess::ForJSArrayBufferViewWeakNext(), |
| 8114 Add<HLoadNamedField>(buffer, weak_first_view_access)); |
| 8115 Add<HStoreNamedField>(buffer, weak_first_view_access, obj); |
| 8116 } |
| 8117 |
| 8118 |
| 8100 void HOptimizedGraphBuilder::VisitDataViewInitialize( | 8119 void HOptimizedGraphBuilder::VisitDataViewInitialize( |
| 8101 CallRuntime* expr) { | 8120 CallRuntime* expr) { |
| 8102 ZoneList<Expression*>* arguments = expr->arguments(); | 8121 ZoneList<Expression*>* arguments = expr->arguments(); |
| 8103 | 8122 |
| 8104 NoObservableSideEffectsScope scope(this); | 8123 NoObservableSideEffectsScope scope(this); |
| 8105 ASSERT(arguments->length()== 4); | 8124 ASSERT(arguments->length()== 4); |
| 8106 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 8125 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
| 8107 HValue* obj = Pop(); | 8126 HValue* obj = Pop(); |
| 8108 | 8127 |
| 8109 CHECK_ALIVE(VisitForValue(arguments->at(1))); | 8128 CHECK_ALIVE(VisitForValue(arguments->at(1))); |
| 8110 HValue* buffer = Pop(); | 8129 HValue* buffer = Pop(); |
| 8111 | 8130 |
| 8112 CHECK_ALIVE(VisitForValue(arguments->at(2))); | 8131 CHECK_ALIVE(VisitForValue(arguments->at(2))); |
| 8113 HValue* byte_offset = Pop(); | 8132 HValue* byte_offset = Pop(); |
| 8114 | 8133 |
| 8115 CHECK_ALIVE(VisitForValue(arguments->at(3))); | 8134 CHECK_ALIVE(VisitForValue(arguments->at(3))); |
| 8116 HValue* byte_length = Pop(); | 8135 HValue* byte_length = Pop(); |
| 8117 | 8136 |
| 8118 for (int offset = JSDataView::kSize; | 8137 BuildArrayBufferViewInitialization<JSDataView>( |
| 8119 offset < JSDataView::kSizeWithInternalFields; | 8138 obj, buffer, byte_offset, byte_length); |
| 8120 offset += kPointerSize) { | |
| 8121 Add<HStoreNamedField>(obj, | |
| 8122 HObjectAccess::ForJSObjectOffset(offset), | |
| 8123 Add<HConstant>(static_cast<int32_t>(0))); | |
| 8124 } | |
| 8125 | |
| 8126 Add<HStoreNamedField>(obj, | |
| 8127 HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer); | |
| 8128 Add<HStoreNamedField>(obj, | |
| 8129 HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset), | |
| 8130 byte_offset); | |
| 8131 Add<HStoreNamedField>(obj, | |
| 8132 HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset), | |
| 8133 byte_length); | |
| 8134 | |
| 8135 Add<HStoreNamedField>(obj, | |
| 8136 HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset), | |
| 8137 Add<HLoadNamedField>(buffer, | |
| 8138 HObjectAccess::ForJSObjectOffset( | |
| 8139 JSArrayBuffer::kWeakFirstViewOffset))); | |
| 8140 Add<HStoreNamedField>(buffer, | |
| 8141 HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset), | |
| 8142 obj); | |
| 8143 } | 8139 } |
| 8144 | 8140 |
| 8145 | 8141 |
| 8142 void HOptimizedGraphBuilder::VisitTypedArrayInitialize( |
| 8143 CallRuntime* expr) { |
| 8144 ZoneList<Expression*>* arguments = expr->arguments(); |
| 8145 |
| 8146 NoObservableSideEffectsScope scope(this); |
| 8147 static const int kObjectArg = 0; |
| 8148 static const int kArrayIdArg = 1; |
| 8149 static const int kBufferArg = 2; |
| 8150 static const int kByteOffsetArg = 3; |
| 8151 static const int kByteLengthArg = 4; |
| 8152 static const int kArgsLength = 5; |
| 8153 ASSERT(arguments->length() == kArgsLength); |
| 8154 |
| 8155 |
| 8156 CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg))); |
| 8157 HValue* obj = Pop(); |
| 8158 |
| 8159 ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral); |
| 8160 Handle<Object> value = |
| 8161 static_cast<Literal*>(arguments->at(kArrayIdArg))->value(); |
| 8162 ASSERT(value->IsSmi()); |
| 8163 int array_id = Smi::cast(*value)->value(); |
| 8164 |
| 8165 CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg))); |
| 8166 HValue* buffer = Pop(); |
| 8167 |
| 8168 HValue* byte_offset; |
| 8169 bool is_zero_byte_offset; |
| 8170 |
| 8171 if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral |
| 8172 && Smi::FromInt(0) == |
| 8173 *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) { |
| 8174 byte_offset = Add<HConstant>(static_cast<int32_t>(0)); |
| 8175 is_zero_byte_offset = true; |
| 8176 } else { |
| 8177 CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg))); |
| 8178 byte_offset = Pop(); |
| 8179 is_zero_byte_offset = false; |
| 8180 } |
| 8181 |
| 8182 CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg))); |
| 8183 HValue* byte_length = Pop(); |
| 8184 |
| 8185 IfBuilder byte_offset_smi(this); |
| 8186 |
| 8187 if (!is_zero_byte_offset) { |
| 8188 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); |
| 8189 byte_offset_smi.Then(); |
| 8190 } |
| 8191 |
| 8192 { // byte_offset is Smi. |
| 8193 BuildArrayBufferViewInitialization<JSTypedArray>( |
| 8194 obj, buffer, byte_offset, byte_length); |
| 8195 |
| 8196 ExternalArrayType array_type = kExternalByteArray; // Bogus initialization. |
| 8197 size_t element_size = 1; // Bogus initialization. |
| 8198 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); |
| 8199 |
| 8200 HInstruction* length = AddUncasted<HDiv>(byte_length, |
| 8201 Add<HConstant>(static_cast<int32_t>(element_size))); |
| 8202 |
| 8203 Add<HStoreNamedField>(obj, |
| 8204 HObjectAccess::ForJSTypedArrayLength(), |
| 8205 length); |
| 8206 |
| 8207 HValue* elements = |
| 8208 Add<HAllocate>( |
| 8209 Add<HConstant>(ExternalArray::kAlignedSize), |
| 8210 HType::JSArray(), |
| 8211 NOT_TENURED, |
| 8212 static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type)); |
| 8213 |
| 8214 Handle<Map> external_array_map( |
| 8215 isolate()->heap()->MapForExternalArrayType(array_type)); |
| 8216 Add<HStoreNamedField>(elements, |
| 8217 HObjectAccess::ForMap(), |
| 8218 Add<HConstant>(external_array_map)); |
| 8219 |
| 8220 HValue* backing_store = Add<HLoadNamedField>( |
| 8221 buffer, HObjectAccess::ForJSArrayBufferBackingStore()); |
| 8222 |
| 8223 HValue* typed_array_start; |
| 8224 if (is_zero_byte_offset) { |
| 8225 typed_array_start = backing_store; |
| 8226 } else { |
| 8227 HInstruction* external_pointer = |
| 8228 AddUncasted<HAdd>(backing_store, byte_offset); |
| 8229 // Arguments are checked prior to call to TypedArrayInitialize, |
| 8230 // including byte_offset. |
| 8231 external_pointer->ClearFlag(HValue::kCanOverflow); |
| 8232 typed_array_start = external_pointer; |
| 8233 } |
| 8234 |
| 8235 Add<HStoreNamedField>(elements, |
| 8236 HObjectAccess::ForExternalArrayExternalPointer(), |
| 8237 typed_array_start); |
| 8238 Add<HStoreNamedField>(elements, |
| 8239 HObjectAccess::ForFixedArrayLength(), |
| 8240 length); |
| 8241 Add<HStoreNamedField>( |
| 8242 obj, HObjectAccess::ForElementsPointer(), elements); |
| 8243 } |
| 8244 |
| 8245 if (!is_zero_byte_offset) { |
| 8246 byte_offset_smi.Else(); |
| 8247 { // byte_offset is not Smi. |
| 8248 Push(Add<HPushArgument>(obj)); |
| 8249 VisitArgument(arguments->at(kArrayIdArg)); |
| 8250 Push(Add<HPushArgument>(buffer)); |
| 8251 Push(Add<HPushArgument>(byte_offset)); |
| 8252 Push(Add<HPushArgument>(byte_length)); |
| 8253 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); |
| 8254 Drop(kArgsLength); |
| 8255 } |
| 8256 } |
| 8257 byte_offset_smi.End(); |
| 8258 } |
| 8259 |
| 8260 |
| 8146 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 8261 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 8147 ASSERT(!HasStackOverflow()); | 8262 ASSERT(!HasStackOverflow()); |
| 8148 ASSERT(current_block() != NULL); | 8263 ASSERT(current_block() != NULL); |
| 8149 ASSERT(current_block()->HasPredecessor()); | 8264 ASSERT(current_block()->HasPredecessor()); |
| 8150 if (expr->is_jsruntime()) { | 8265 if (expr->is_jsruntime()) { |
| 8151 return Bailout(kCallToAJavaScriptRuntimeFunction); | 8266 return Bailout(kCallToAJavaScriptRuntimeFunction); |
| 8152 } | 8267 } |
| 8153 | 8268 |
| 8154 const Runtime::Function* function = expr->function(); | 8269 const Runtime::Function* function = expr->function(); |
| 8155 ASSERT(function != NULL); | 8270 ASSERT(function != NULL); |
| 8156 | 8271 |
| 8157 if (function->function_id == Runtime::kDataViewInitialize) { | 8272 if (function->function_id == Runtime::kDataViewInitialize) { |
| 8158 return VisitDataViewInitialize(expr); | 8273 return VisitDataViewInitialize(expr); |
| 8159 } | 8274 } |
| 8160 | 8275 |
| 8276 if (function->function_id == Runtime::kTypedArrayInitialize) { |
| 8277 return VisitTypedArrayInitialize(expr); |
| 8278 } |
| 8279 |
| 8280 if (function->function_id == Runtime::kMaxSmi) { |
| 8281 ASSERT(expr->arguments()->length() == 0); |
| 8282 HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue)); |
| 8283 return ast_context()->ReturnInstruction(max_smi, expr->id()); |
| 8284 } |
| 8285 |
| 8161 if (function->intrinsic_type == Runtime::INLINE) { | 8286 if (function->intrinsic_type == Runtime::INLINE) { |
| 8162 ASSERT(expr->name()->length() > 0); | 8287 ASSERT(expr->name()->length() > 0); |
| 8163 ASSERT(expr->name()->Get(0) == '_'); | 8288 ASSERT(expr->name()->Get(0) == '_'); |
| 8164 // Call to an inline function. | 8289 // Call to an inline function. |
| 8165 int lookup_index = static_cast<int>(function->function_id) - | 8290 int lookup_index = static_cast<int>(function->function_id) - |
| 8166 static_cast<int>(Runtime::kFirstInlineFunction); | 8291 static_cast<int>(Runtime::kFirstInlineFunction); |
| 8167 ASSERT(lookup_index >= 0); | 8292 ASSERT(lookup_index >= 0); |
| 8168 ASSERT(static_cast<size_t>(lookup_index) < | 8293 ASSERT(static_cast<size_t>(lookup_index) < |
| 8169 ARRAY_SIZE(kInlineFunctionGenerators)); | 8294 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 8170 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 8295 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8634 } | 8759 } |
| 8635 | 8760 |
| 8636 | 8761 |
| 8637 HValue* HGraphBuilder::BuildBinaryOperation( | 8762 HValue* HGraphBuilder::BuildBinaryOperation( |
| 8638 Token::Value op, | 8763 Token::Value op, |
| 8639 HValue* left, | 8764 HValue* left, |
| 8640 HValue* right, | 8765 HValue* right, |
| 8641 Handle<Type> left_type, | 8766 Handle<Type> left_type, |
| 8642 Handle<Type> right_type, | 8767 Handle<Type> right_type, |
| 8643 Handle<Type> result_type, | 8768 Handle<Type> result_type, |
| 8644 Maybe<int> fixed_right_arg, | 8769 Maybe<int> fixed_right_arg) { |
| 8645 bool binop_stub) { | |
| 8646 | 8770 |
| 8647 Representation left_rep = Representation::FromType(left_type); | 8771 Representation left_rep = Representation::FromType(left_type); |
| 8648 Representation right_rep = Representation::FromType(right_type); | 8772 Representation right_rep = Representation::FromType(right_type); |
| 8649 | 8773 |
| 8650 bool maybe_string_add = op == Token::ADD && | 8774 bool maybe_string_add = op == Token::ADD && |
| 8651 (left_type->Maybe(Type::String()) || | 8775 (left_type->Maybe(Type::String()) || |
| 8652 right_type->Maybe(Type::String())); | 8776 right_type->Maybe(Type::String())); |
| 8653 | 8777 |
| 8654 if (left_type->Is(Type::None())) { | 8778 if (left_type->Is(Type::None())) { |
| 8655 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8779 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| (...skipping 13 matching lines...) Expand all Loading... |
| 8669 } else { | 8793 } else { |
| 8670 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 8794 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 8671 right_rep = Representation::FromType(right_type); | 8795 right_rep = Representation::FromType(right_type); |
| 8672 } | 8796 } |
| 8673 | 8797 |
| 8674 // Special case for string addition here. | 8798 // Special case for string addition here. |
| 8675 if (op == Token::ADD && | 8799 if (op == Token::ADD && |
| 8676 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 8800 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
| 8677 // Validate type feedback for left argument. | 8801 // Validate type feedback for left argument. |
| 8678 if (left_type->Is(Type::String())) { | 8802 if (left_type->Is(Type::String())) { |
| 8679 left = BuildCheckString( | 8803 left = BuildCheckString(left); |
| 8680 left, "Expected string for LHS of binary operation"); | |
| 8681 } | 8804 } |
| 8682 | 8805 |
| 8683 // Validate type feedback for right argument. | 8806 // Validate type feedback for right argument. |
| 8684 if (right_type->Is(Type::String())) { | 8807 if (right_type->Is(Type::String())) { |
| 8685 right = BuildCheckString( | 8808 right = BuildCheckString(right); |
| 8686 right, "Expected string for RHS of binary operation"); | |
| 8687 } | 8809 } |
| 8688 | 8810 |
| 8689 // Convert left argument as necessary. | 8811 // Convert left argument as necessary. |
| 8690 if (left_type->Is(Type::Number())) { | 8812 if (left_type->Is(Type::Number())) { |
| 8691 ASSERT(right_type->Is(Type::String())); | 8813 ASSERT(right_type->Is(Type::String())); |
| 8692 left = BuildNumberToString(left, left_type); | 8814 left = BuildNumberToString(left, left_type); |
| 8693 } else if (!left_type->Is(Type::String())) { | 8815 } else if (!left_type->Is(Type::String())) { |
| 8694 ASSERT(right_type->Is(Type::String())); | 8816 ASSERT(right_type->Is(Type::String())); |
| 8695 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); | 8817 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); |
| 8696 Add<HPushArgument>(left); | 8818 Add<HPushArgument>(left); |
| 8697 Add<HPushArgument>(right); | 8819 Add<HPushArgument>(right); |
| 8698 return AddUncasted<HInvokeFunction>(function, 2); | 8820 return AddUncasted<HInvokeFunction>(function, 2); |
| 8699 } | 8821 } |
| 8700 | 8822 |
| 8701 // Convert right argument as necessary. | 8823 // Convert right argument as necessary. |
| 8702 if (right_type->Is(Type::Number())) { | 8824 if (right_type->Is(Type::Number())) { |
| 8703 ASSERT(left_type->Is(Type::String())); | 8825 ASSERT(left_type->Is(Type::String())); |
| 8704 right = BuildNumberToString(right, right_type); | 8826 right = BuildNumberToString(right, right_type); |
| 8705 } else if (!right_type->Is(Type::String())) { | 8827 } else if (!right_type->Is(Type::String())) { |
| 8706 ASSERT(left_type->Is(Type::String())); | 8828 ASSERT(left_type->Is(Type::String())); |
| 8707 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 8829 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
| 8708 Add<HPushArgument>(left); | 8830 Add<HPushArgument>(left); |
| 8709 Add<HPushArgument>(right); | 8831 Add<HPushArgument>(right); |
| 8710 return AddUncasted<HInvokeFunction>(function, 2); | 8832 return AddUncasted<HInvokeFunction>(function, 2); |
| 8711 } | 8833 } |
| 8712 | 8834 |
| 8713 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); | 8835 return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE); |
| 8714 } | 8836 } |
| 8715 | 8837 |
| 8716 if (binop_stub) { | 8838 if (graph()->info()->IsStub()) { |
| 8717 left = EnforceNumberType(left, left_type); | 8839 left = EnforceNumberType(left, left_type); |
| 8718 right = EnforceNumberType(right, right_type); | 8840 right = EnforceNumberType(right, right_type); |
| 8719 } | 8841 } |
| 8720 | 8842 |
| 8721 Representation result_rep = Representation::FromType(result_type); | 8843 Representation result_rep = Representation::FromType(result_type); |
| 8722 | 8844 |
| 8723 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 8845 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
| 8724 (right_rep.IsTagged() && !right_rep.IsSmi()); | 8846 (right_rep.IsTagged() && !right_rep.IsSmi()); |
| 8725 | 8847 |
| 8726 HInstruction* instr = NULL; | 8848 HInstruction* instr = NULL; |
| 8727 // Only the stub is allowed to call into the runtime, since otherwise we would | 8849 // Only the stub is allowed to call into the runtime, since otherwise we would |
| 8728 // inline several instructions (including the two pushes) for every tagged | 8850 // inline several instructions (including the two pushes) for every tagged |
| 8729 // operation in optimized code, which is more expensive, than a stub call. | 8851 // operation in optimized code, which is more expensive, than a stub call. |
| 8730 if (binop_stub && is_non_primitive) { | 8852 if (graph()->info()->IsStub() && is_non_primitive) { |
| 8731 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); | 8853 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
| 8732 Add<HPushArgument>(left); | 8854 Add<HPushArgument>(left); |
| 8733 Add<HPushArgument>(right); | 8855 Add<HPushArgument>(right); |
| 8734 instr = AddUncasted<HInvokeFunction>(function, 2); | 8856 instr = AddUncasted<HInvokeFunction>(function, 2); |
| 8735 } else { | 8857 } else { |
| 8736 switch (op) { | 8858 switch (op) { |
| 8737 case Token::ADD: | 8859 case Token::ADD: |
| 8738 instr = AddUncasted<HAdd>(left, right); | 8860 instr = AddUncasted<HAdd>(left, right); |
| 8739 break; | 8861 break; |
| 8740 case Token::SUB: | 8862 case Token::SUB: |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8795 default: | 8917 default: |
| 8796 UNREACHABLE(); | 8918 UNREACHABLE(); |
| 8797 } | 8919 } |
| 8798 } | 8920 } |
| 8799 | 8921 |
| 8800 if (instr->IsBinaryOperation()) { | 8922 if (instr->IsBinaryOperation()) { |
| 8801 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 8923 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 8802 binop->set_observed_input_representation(1, left_rep); | 8924 binop->set_observed_input_representation(1, left_rep); |
| 8803 binop->set_observed_input_representation(2, right_rep); | 8925 binop->set_observed_input_representation(2, right_rep); |
| 8804 binop->initialize_output_representation(result_rep); | 8926 binop->initialize_output_representation(result_rep); |
| 8805 if (binop_stub) { | 8927 if (graph()->info()->IsStub()) { |
| 8806 // Stub should not call into stub. | 8928 // Stub should not call into stub. |
| 8807 instr->SetFlag(HValue::kCannotBeTagged); | 8929 instr->SetFlag(HValue::kCannotBeTagged); |
| 8808 // And should truncate on HForceRepresentation already. | 8930 // And should truncate on HForceRepresentation already. |
| 8809 if (left->IsForceRepresentation()) { | 8931 if (left->IsForceRepresentation()) { |
| 8810 left->CopyFlag(HValue::kTruncatingToSmi, instr); | 8932 left->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 8811 left->CopyFlag(HValue::kTruncatingToInt32, instr); | 8933 left->CopyFlag(HValue::kTruncatingToInt32, instr); |
| 8812 } | 8934 } |
| 8813 if (right->IsForceRepresentation()) { | 8935 if (right->IsForceRepresentation()) { |
| 8814 right->CopyFlag(HValue::kTruncatingToSmi, instr); | 8936 right->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 8815 right->CopyFlag(HValue::kTruncatingToInt32, instr); | 8937 right->CopyFlag(HValue::kTruncatingToInt32, instr); |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9213 return New<HConstant>( | 9335 return New<HConstant>( |
| 9214 function_state()->compilation_info()->closure()); | 9336 function_state()->compilation_info()->closure()); |
| 9215 } else { | 9337 } else { |
| 9216 return New<HThisFunction>(); | 9338 return New<HThisFunction>(); |
| 9217 } | 9339 } |
| 9218 } | 9340 } |
| 9219 | 9341 |
| 9220 | 9342 |
| 9221 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 9343 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 9222 Handle<JSObject> boilerplate_object, | 9344 Handle<JSObject> boilerplate_object, |
| 9223 AllocationSiteContext* site_context) { | 9345 AllocationSiteUsageContext* site_context) { |
| 9224 NoObservableSideEffectsScope no_effects(this); | 9346 NoObservableSideEffectsScope no_effects(this); |
| 9225 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 9347 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| 9226 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 9348 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| 9227 | 9349 |
| 9228 HType type = instance_type == JS_ARRAY_TYPE | 9350 HType type = instance_type == JS_ARRAY_TYPE |
| 9229 ? HType::JSArray() : HType::JSObject(); | 9351 ? HType::JSArray() : HType::JSObject(); |
| 9230 HValue* object_size_constant = Add<HConstant>( | 9352 HValue* object_size_constant = Add<HConstant>( |
| 9231 boilerplate_object->map()->instance_size()); | 9353 boilerplate_object->map()->instance_size()); |
| 9232 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 9354 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 9233 isolate()->heap()->GetPretenureMode(), instance_type); | 9355 isolate()->heap()->GetPretenureMode(), instance_type); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9306 object_elements = Add<HConstant>(elements_field); | 9428 object_elements = Add<HConstant>(elements_field); |
| 9307 } | 9429 } |
| 9308 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 9430 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 9309 object_elements); | 9431 object_elements); |
| 9310 } | 9432 } |
| 9311 | 9433 |
| 9312 | 9434 |
| 9313 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 9435 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 9314 Handle<JSObject> boilerplate_object, | 9436 Handle<JSObject> boilerplate_object, |
| 9315 HInstruction* object, | 9437 HInstruction* object, |
| 9316 AllocationSiteContext* site_context) { | 9438 AllocationSiteUsageContext* site_context) { |
| 9317 Handle<DescriptorArray> descriptors( | 9439 Handle<DescriptorArray> descriptors( |
| 9318 boilerplate_object->map()->instance_descriptors()); | 9440 boilerplate_object->map()->instance_descriptors()); |
| 9319 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 9441 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| 9320 | 9442 |
| 9321 int copied_fields = 0; | 9443 int copied_fields = 0; |
| 9322 for (int i = 0; i < limit; i++) { | 9444 for (int i = 0; i < limit; i++) { |
| 9323 PropertyDetails details = descriptors->GetDetails(i); | 9445 PropertyDetails details = descriptors->GetDetails(i); |
| 9324 if (details.type() != FIELD) continue; | 9446 if (details.type() != FIELD) continue; |
| 9325 copied_fields++; | 9447 copied_fields++; |
| 9326 int index = descriptors->GetFieldIndex(i); | 9448 int index = descriptors->GetFieldIndex(i); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9378 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 9500 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 9379 Add<HStoreNamedField>(object, access, value_instruction); | 9501 Add<HStoreNamedField>(object, access, value_instruction); |
| 9380 } | 9502 } |
| 9381 } | 9503 } |
| 9382 | 9504 |
| 9383 | 9505 |
| 9384 void HOptimizedGraphBuilder::BuildEmitElements( | 9506 void HOptimizedGraphBuilder::BuildEmitElements( |
| 9385 Handle<JSObject> boilerplate_object, | 9507 Handle<JSObject> boilerplate_object, |
| 9386 Handle<FixedArrayBase> elements, | 9508 Handle<FixedArrayBase> elements, |
| 9387 HValue* object_elements, | 9509 HValue* object_elements, |
| 9388 AllocationSiteContext* site_context) { | 9510 AllocationSiteUsageContext* site_context) { |
| 9389 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 9511 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 9390 int elements_length = elements->length(); | 9512 int elements_length = elements->length(); |
| 9391 HValue* object_elements_length = Add<HConstant>(elements_length); | 9513 HValue* object_elements_length = Add<HConstant>(elements_length); |
| 9392 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 9514 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
| 9393 | 9515 |
| 9394 // Copy elements backing store content. | 9516 // Copy elements backing store content. |
| 9395 if (elements->IsFixedDoubleArray()) { | 9517 if (elements->IsFixedDoubleArray()) { |
| 9396 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 9518 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| 9397 } else if (elements->IsFixedArray()) { | 9519 } else if (elements->IsFixedArray()) { |
| 9398 BuildEmitFixedArray(elements, kind, object_elements, | 9520 BuildEmitFixedArray(elements, kind, object_elements, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 9419 value_instruction, kind); | 9541 value_instruction, kind); |
| 9420 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 9542 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 9421 } | 9543 } |
| 9422 } | 9544 } |
| 9423 | 9545 |
| 9424 | 9546 |
| 9425 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 9547 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 9426 Handle<FixedArrayBase> elements, | 9548 Handle<FixedArrayBase> elements, |
| 9427 ElementsKind kind, | 9549 ElementsKind kind, |
| 9428 HValue* object_elements, | 9550 HValue* object_elements, |
| 9429 AllocationSiteContext* site_context) { | 9551 AllocationSiteUsageContext* site_context) { |
| 9430 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 9552 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 9431 int elements_length = elements->length(); | 9553 int elements_length = elements->length(); |
| 9432 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 9554 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 9433 for (int i = 0; i < elements_length; i++) { | 9555 for (int i = 0; i < elements_length; i++) { |
| 9434 Handle<Object> value(fast_elements->get(i), isolate()); | 9556 Handle<Object> value(fast_elements->get(i), isolate()); |
| 9435 HValue* key_constant = Add<HConstant>(i); | 9557 HValue* key_constant = Add<HConstant>(i); |
| 9436 if (value->IsJSObject()) { | 9558 if (value->IsJSObject()) { |
| 9437 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 9559 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 9438 Handle<AllocationSite> current_site = site_context->EnterNewScope(); | 9560 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 9439 HInstruction* result = | 9561 HInstruction* result = |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9885 return ast_context()->ReturnControl(result, call->id()); | 10007 return ast_context()->ReturnControl(result, call->id()); |
| 9886 } | 10008 } |
| 9887 | 10009 |
| 9888 | 10010 |
| 9889 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 10011 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { |
| 9890 // %_Log is ignored in optimized code. | 10012 // %_Log is ignored in optimized code. |
| 9891 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 10013 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 9892 } | 10014 } |
| 9893 | 10015 |
| 9894 | 10016 |
| 9895 // Fast support for Math.random(). | |
| 9896 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | |
| 9897 HGlobalObject* global_object = Add<HGlobalObject>(); | |
| 9898 HRandom* result = New<HRandom>(global_object); | |
| 9899 return ast_context()->ReturnInstruction(result, call->id()); | |
| 9900 } | |
| 9901 | |
| 9902 | |
| 9903 // Fast support for StringAdd. | 10017 // Fast support for StringAdd. |
| 9904 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 10018 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9905 ASSERT_EQ(2, call->arguments()->length()); | 10019 ASSERT_EQ(2, call->arguments()->length()); |
| 9906 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10020 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9907 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10021 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9908 HValue* right = Pop(); | 10022 HValue* right = Pop(); |
| 9909 HValue* left = Pop(); | 10023 HValue* left = Pop(); |
| 9910 HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); | 10024 HInstruction* result = |
| 10025 NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); |
| 9911 return ast_context()->ReturnInstruction(result, call->id()); | 10026 return ast_context()->ReturnInstruction(result, call->id()); |
| 9912 } | 10027 } |
| 9913 | 10028 |
| 9914 | 10029 |
| 9915 // Fast support for SubString. | 10030 // Fast support for SubString. |
| 9916 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 10031 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9917 ASSERT_EQ(3, call->arguments()->length()); | 10032 ASSERT_EQ(3, call->arguments()->length()); |
| 9918 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10033 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9919 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 10034 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
| 9920 Drop(3); | 10035 Drop(3); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10029 result->set_transcendental_type(TranscendentalCache::LOG); | 10144 result->set_transcendental_type(TranscendentalCache::LOG); |
| 10030 Drop(1); | 10145 Drop(1); |
| 10031 return ast_context()->ReturnInstruction(result, call->id()); | 10146 return ast_context()->ReturnInstruction(result, call->id()); |
| 10032 } | 10147 } |
| 10033 | 10148 |
| 10034 | 10149 |
| 10035 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 10150 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 10036 ASSERT(call->arguments()->length() == 1); | 10151 ASSERT(call->arguments()->length() == 1); |
| 10037 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10152 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10038 HValue* value = Pop(); | 10153 HValue* value = Pop(); |
| 10039 HInstruction* result = New<HUnaryMathOperation>(value, kMathSqrt); | 10154 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
| 10040 return ast_context()->ReturnInstruction(result, call->id()); | 10155 return ast_context()->ReturnInstruction(result, call->id()); |
| 10041 } | 10156 } |
| 10042 | 10157 |
| 10043 | 10158 |
| 10044 // Check whether two RegExps are equivalent | 10159 // Check whether two RegExps are equivalent |
| 10045 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 10160 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 10046 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); | 10161 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); |
| 10047 } | 10162 } |
| 10048 | 10163 |
| 10049 | 10164 |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10689 if (ShouldProduceTraceOutput()) { | 10804 if (ShouldProduceTraceOutput()) { |
| 10690 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10805 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10691 } | 10806 } |
| 10692 | 10807 |
| 10693 #ifdef DEBUG | 10808 #ifdef DEBUG |
| 10694 graph_->Verify(false); // No full verify. | 10809 graph_->Verify(false); // No full verify. |
| 10695 #endif | 10810 #endif |
| 10696 } | 10811 } |
| 10697 | 10812 |
| 10698 } } // namespace v8::internal | 10813 } } // namespace v8::internal |
| OLD | NEW |