| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
| (...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 | 1640 |
| 1641 cow_checker.Else(); | 1641 cow_checker.Else(); |
| 1642 | 1642 |
| 1643 environment()->Push(elements); | 1643 environment()->Push(elements); |
| 1644 | 1644 |
| 1645 cow_checker.End(); | 1645 cow_checker.End(); |
| 1646 | 1646 |
| 1647 return environment()->Pop(); | 1647 return environment()->Pop(); |
| 1648 } | 1648 } |
| 1649 | 1649 |
| 1650 | |
| 1651 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver, | |
| 1652 int bit_field_mask) { | |
| 1653 // Check that the object isn't a smi. | |
| 1654 Add<HCheckHeapObject>(receiver); | |
| 1655 | |
| 1656 // Get the map of the receiver. | |
| 1657 HValue* map = | |
| 1658 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); | |
| 1659 | |
| 1660 // Check the instance type and if an access check is needed, this can be | |
| 1661 // done with a single load, since both bytes are adjacent in the map. | |
| 1662 HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField()); | |
| 1663 HValue* instance_type_and_bit_field = | |
| 1664 Add<HLoadNamedField>(map, nullptr, access); | |
| 1665 | |
| 1666 HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8)); | |
| 1667 HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND, | |
| 1668 instance_type_and_bit_field, | |
| 1669 mask); | |
| 1670 HValue* sub_result = AddUncasted<HSub>(and_result, | |
| 1671 Add<HConstant>(JS_OBJECT_TYPE)); | |
| 1672 Add<HBoundsCheck>(sub_result, | |
| 1673 Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE)); | |
| 1674 } | |
| 1675 | |
| 1676 | |
| 1677 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key, | |
| 1678 HIfContinuation* join_continuation) { | |
| 1679 // The sometimes unintuitively backward ordering of the ifs below is | |
| 1680 // convoluted, but necessary. All of the paths must guarantee that the | |
| 1681 // if-true of the continuation returns a smi element index and the if-false of | |
| 1682 // the continuation returns either a symbol or a unique string key. All other | |
| 1683 // object types cause a deopt to fall back to the runtime. | |
| 1684 | |
| 1685 IfBuilder key_smi_if(this); | |
| 1686 key_smi_if.If<HIsSmiAndBranch>(key); | |
| 1687 key_smi_if.Then(); | |
| 1688 { | |
| 1689 Push(key); // Nothing to do, just continue to true of continuation. | |
| 1690 } | |
| 1691 key_smi_if.Else(); | |
| 1692 { | |
| 1693 HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap()); | |
| 1694 HValue* instance_type = | |
| 1695 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); | |
| 1696 | |
| 1697 // Non-unique string, check for a string with a hash code that is actually | |
| 1698 // an index. | |
| 1699 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); | |
| 1700 IfBuilder not_string_or_name_if(this); | |
| 1701 not_string_or_name_if.If<HCompareNumericAndBranch>( | |
| 1702 instance_type, | |
| 1703 Add<HConstant>(LAST_UNIQUE_NAME_TYPE), | |
| 1704 Token::GT); | |
| 1705 | |
| 1706 not_string_or_name_if.Then(); | |
| 1707 { | |
| 1708 // Non-smi, non-Name, non-String: Try to convert to smi in case of | |
| 1709 // HeapNumber. | |
| 1710 // TODO(danno): This could call some variant of ToString | |
| 1711 Push(AddUncasted<HForceRepresentation>(key, Representation::Smi())); | |
| 1712 } | |
| 1713 not_string_or_name_if.Else(); | |
| 1714 { | |
| 1715 // String or Name: check explicitly for Name, they can short-circuit | |
| 1716 // directly to unique non-index key path. | |
| 1717 IfBuilder not_symbol_if(this); | |
| 1718 not_symbol_if.If<HCompareNumericAndBranch>( | |
| 1719 instance_type, | |
| 1720 Add<HConstant>(SYMBOL_TYPE), | |
| 1721 Token::NE); | |
| 1722 | |
| 1723 not_symbol_if.Then(); | |
| 1724 { | |
| 1725 // String: check whether the String is a String of an index. If it is, | |
| 1726 // extract the index value from the hash. | |
| 1727 HValue* hash = Add<HLoadNamedField>(key, nullptr, | |
| 1728 HObjectAccess::ForNameHashField()); | |
| 1729 HValue* not_index_mask = Add<HConstant>(static_cast<int>( | |
| 1730 String::kContainsCachedArrayIndexMask)); | |
| 1731 | |
| 1732 HValue* not_index_test = AddUncasted<HBitwise>( | |
| 1733 Token::BIT_AND, hash, not_index_mask); | |
| 1734 | |
| 1735 IfBuilder string_index_if(this); | |
| 1736 string_index_if.If<HCompareNumericAndBranch>(not_index_test, | |
| 1737 graph()->GetConstant0(), | |
| 1738 Token::EQ); | |
| 1739 string_index_if.Then(); | |
| 1740 { | |
| 1741 // String with index in hash: extract string and merge to index path. | |
| 1742 Push(BuildDecodeField<String::ArrayIndexValueBits>(hash)); | |
| 1743 } | |
| 1744 string_index_if.Else(); | |
| 1745 { | |
| 1746 // Key is a non-index String, check for uniqueness/internalization. | |
| 1747 // If it's not internalized yet, internalize it now. | |
| 1748 HValue* not_internalized_bit = AddUncasted<HBitwise>( | |
| 1749 Token::BIT_AND, | |
| 1750 instance_type, | |
| 1751 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); | |
| 1752 | |
| 1753 IfBuilder internalized(this); | |
| 1754 internalized.If<HCompareNumericAndBranch>(not_internalized_bit, | |
| 1755 graph()->GetConstant0(), | |
| 1756 Token::EQ); | |
| 1757 internalized.Then(); | |
| 1758 Push(key); | |
| 1759 | |
| 1760 internalized.Else(); | |
| 1761 Add<HPushArguments>(key); | |
| 1762 HValue* intern_key = Add<HCallRuntime>( | |
| 1763 Runtime::FunctionForId(Runtime::kInternalizeString), 1); | |
| 1764 Push(intern_key); | |
| 1765 | |
| 1766 internalized.End(); | |
| 1767 // Key guaranteed to be a unique string | |
| 1768 } | |
| 1769 string_index_if.JoinContinuation(join_continuation); | |
| 1770 } | |
| 1771 not_symbol_if.Else(); | |
| 1772 { | |
| 1773 Push(key); // Key is symbol | |
| 1774 } | |
| 1775 not_symbol_if.JoinContinuation(join_continuation); | |
| 1776 } | |
| 1777 not_string_or_name_if.JoinContinuation(join_continuation); | |
| 1778 } | |
| 1779 key_smi_if.JoinContinuation(join_continuation); | |
| 1780 } | |
| 1781 | |
| 1782 | |
| 1783 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) { | |
| 1784 // Get the the instance type of the receiver, and make sure that it is | |
| 1785 // not one of the global object types. | |
| 1786 HValue* map = | |
| 1787 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); | |
| 1788 HValue* instance_type = | |
| 1789 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); | |
| 1790 HValue* global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE); | |
| 1791 | |
| 1792 IfBuilder if_global_object(this); | |
| 1793 if_global_object.If<HCompareNumericAndBranch>(instance_type, global_type, | |
| 1794 Token::EQ); | |
| 1795 if_global_object.ThenDeopt(DeoptimizeReason::kReceiverWasAGlobalObject); | |
| 1796 if_global_object.End(); | |
| 1797 } | |
| 1798 | |
| 1799 | |
| 1800 void HGraphBuilder::BuildTestForDictionaryProperties( | |
| 1801 HValue* object, | |
| 1802 HIfContinuation* continuation) { | |
| 1803 HValue* properties = Add<HLoadNamedField>( | |
| 1804 object, nullptr, HObjectAccess::ForPropertiesPointer()); | |
| 1805 HValue* properties_map = | |
| 1806 Add<HLoadNamedField>(properties, nullptr, HObjectAccess::ForMap()); | |
| 1807 HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex); | |
| 1808 IfBuilder builder(this); | |
| 1809 builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map); | |
| 1810 builder.CaptureContinuation(continuation); | |
| 1811 } | |
| 1812 | |
| 1813 | |
| 1814 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object, | |
| 1815 HValue* key) { | |
| 1816 // Load the map of the receiver, compute the keyed lookup cache hash | |
| 1817 // based on 32 bits of the map pointer and the string hash. | |
| 1818 HValue* object_map = | |
| 1819 Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMapAsInteger32()); | |
| 1820 HValue* shifted_map = AddUncasted<HShr>( | |
| 1821 object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift)); | |
| 1822 HValue* string_hash = | |
| 1823 Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForStringHashField()); | |
| 1824 HValue* shifted_hash = AddUncasted<HShr>( | |
| 1825 string_hash, Add<HConstant>(String::kHashShift)); | |
| 1826 HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map, | |
| 1827 shifted_hash); | |
| 1828 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | |
| 1829 return AddUncasted<HBitwise>(Token::BIT_AND, xor_result, | |
| 1830 Add<HConstant>(mask)); | |
| 1831 } | |
| 1832 | |
| 1833 | |
| 1834 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { | 1650 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { |
| 1835 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); | 1651 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); |
| 1836 HValue* seed = Add<HConstant>(seed_value); | 1652 HValue* seed = Add<HConstant>(seed_value); |
| 1837 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); | 1653 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); |
| 1838 | 1654 |
| 1839 // hash = ~hash + (hash << 15); | 1655 // hash = ~hash + (hash << 15); |
| 1840 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); | 1656 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); |
| 1841 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, | 1657 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, |
| 1842 graph()->GetConstantMinus1()); | 1658 graph()->GetConstantMinus1()); |
| 1843 hash = AddUncasted<HAdd>(shifted_hash, not_hash); | 1659 hash = AddUncasted<HAdd>(shifted_hash, not_hash); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1990 Push(entry); | 1806 Push(entry); |
| 1991 Push(count); | 1807 Push(count); |
| 1992 | 1808 |
| 1993 probe_loop.EndBody(); | 1809 probe_loop.EndBody(); |
| 1994 | 1810 |
| 1995 return_or_loop.End(); | 1811 return_or_loop.End(); |
| 1996 | 1812 |
| 1997 return Pop(); | 1813 return Pop(); |
| 1998 } | 1814 } |
| 1999 | 1815 |
| 2000 | |
| 2001 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value, | 1816 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value, |
| 2002 HValue* done) { | 1817 HValue* done) { |
| 2003 NoObservableSideEffectsScope scope(this); | 1818 NoObservableSideEffectsScope scope(this); |
| 2004 | 1819 |
| 2005 // Allocate the JSIteratorResult object. | 1820 // Allocate the JSIteratorResult object. |
| 2006 HValue* result = | 1821 HValue* result = |
| 2007 Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(), | 1822 Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(), |
| 2008 NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0()); | 1823 NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0()); |
| 2009 | 1824 |
| 2010 // Initialize the JSIteratorResult object. | 1825 // Initialize the JSIteratorResult object. |
| (...skipping 11276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13287 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13102 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13288 } | 13103 } |
| 13289 | 13104 |
| 13290 #ifdef DEBUG | 13105 #ifdef DEBUG |
| 13291 graph_->Verify(false); // No full verify. | 13106 graph_->Verify(false); // No full verify. |
| 13292 #endif | 13107 #endif |
| 13293 } | 13108 } |
| 13294 | 13109 |
| 13295 } // namespace internal | 13110 } // namespace internal |
| 13296 } // namespace v8 | 13111 } // namespace v8 |
| OLD | NEW |