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 |