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/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1523 string_index_if.If<HCompareNumericAndBranch>(not_index_test, | 1523 string_index_if.If<HCompareNumericAndBranch>(not_index_test, |
1524 graph()->GetConstant0(), | 1524 graph()->GetConstant0(), |
1525 Token::EQ); | 1525 Token::EQ); |
1526 string_index_if.Then(); | 1526 string_index_if.Then(); |
1527 { | 1527 { |
1528 // String with index in hash: extract string and merge to index path. | 1528 // String with index in hash: extract string and merge to index path. |
1529 Push(BuildDecodeField<String::ArrayIndexValueBits>(hash)); | 1529 Push(BuildDecodeField<String::ArrayIndexValueBits>(hash)); |
1530 } | 1530 } |
1531 string_index_if.Else(); | 1531 string_index_if.Else(); |
1532 { | 1532 { |
1533 // Key is a non-index String, check for uniqueness/internalization. If | 1533 // Key is a non-index String, check for uniqueness/internalization. |
1534 // it's not, deopt. | 1534 // If it's not internalized yet, internalize it now. |
1535 HValue* not_internalized_bit = AddUncasted<HBitwise>( | 1535 HValue* not_internalized_bit = AddUncasted<HBitwise>( |
1536 Token::BIT_AND, | 1536 Token::BIT_AND, |
1537 instance_type, | 1537 instance_type, |
1538 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); | 1538 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); |
1539 | 1539 |
1540 IfBuilder internalized(this); | 1540 IfBuilder internalized(this); |
1541 internalized.If<HCompareNumericAndBranch>(not_internalized_bit, | 1541 internalized.If<HCompareNumericAndBranch>(not_internalized_bit, |
1542 graph()->GetConstant0(), | 1542 graph()->GetConstant0(), |
1543 Token::EQ); | 1543 Token::EQ); |
1544 internalized.Then(); | 1544 internalized.Then(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1624 HValue* shifted_hash = AddUncasted<HShr>( | 1624 HValue* shifted_hash = AddUncasted<HShr>( |
1625 string_hash, Add<HConstant>(String::kHashShift)); | 1625 string_hash, Add<HConstant>(String::kHashShift)); |
1626 HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map, | 1626 HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map, |
1627 shifted_hash); | 1627 shifted_hash); |
1628 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | 1628 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); |
1629 return AddUncasted<HBitwise>(Token::BIT_AND, xor_result, | 1629 return AddUncasted<HBitwise>(Token::BIT_AND, xor_result, |
1630 Add<HConstant>(mask)); | 1630 Add<HConstant>(mask)); |
1631 } | 1631 } |
1632 | 1632 |
1633 | 1633 |
1634 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper( | |
1635 HValue* elements, | |
1636 HValue* key, | |
1637 HValue* hash, | |
1638 HValue* mask, | |
1639 int current_probe) { | |
1640 if (current_probe == kNumberDictionaryProbes) { | |
1641 return NULL; | |
1642 } | |
1643 | |
1644 int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe); | |
1645 HValue* raw_index = (current_probe == 0) | |
1646 ? hash | |
1647 : AddUncasted<HAdd>(hash, Add<HConstant>(offset)); | |
1648 raw_index = AddUncasted<HBitwise>(Token::BIT_AND, raw_index, mask); | |
1649 int32_t entry_size = SeededNumberDictionary::kEntrySize; | |
1650 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size)); | |
1651 raw_index->ClearFlag(HValue::kCanOverflow); | |
1652 | |
1653 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; | |
1654 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset)); | |
1655 key_index->ClearFlag(HValue::kCanOverflow); | |
1656 | |
1657 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index, | |
1658 static_cast<HValue*>(NULL), | |
1659 FAST_ELEMENTS); | |
1660 | |
1661 IfBuilder key_compare(this); | |
1662 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key); | |
1663 key_compare.Then(); | |
1664 { | |
1665 // Key at the current probe doesn't match, try at the next probe. | |
1666 HValue* result = BuildUncheckedDictionaryElementLoadHelper( | |
1667 elements, key, hash, mask, current_probe + 1); | |
1668 if (result == NULL) { | |
1669 key_compare.Deopt("probes exhausted in keyed load dictionary lookup"); | |
1670 result = graph()->GetConstantUndefined(); | |
1671 } else { | |
1672 Push(result); | |
1673 } | |
1674 } | |
1675 key_compare.Else(); | |
1676 { | |
1677 // Key at current probe matches. Details must be zero, otherwise the | |
1678 // dictionary element requires special handling. | |
1679 HValue* details_index = AddUncasted<HAdd>( | |
1680 raw_index, Add<HConstant>(base_offset + 2)); | |
1681 details_index->ClearFlag(HValue::kCanOverflow); | |
1682 | |
1683 HValue* details = Add<HLoadKeyed>(elements, details_index, | |
1684 static_cast<HValue*>(NULL), | |
1685 FAST_ELEMENTS); | |
1686 IfBuilder details_compare(this); | |
1687 details_compare.If<HCompareNumericAndBranch>(details, | |
1688 graph()->GetConstant0(), | |
1689 Token::NE); | |
1690 details_compare.ThenDeopt("keyed load dictionary element not fast case"); | |
1691 | |
1692 details_compare.Else(); | |
1693 { | |
1694 // Key matches and details are zero --> fast case. Load and return the | |
1695 // value. | |
1696 HValue* result_index = AddUncasted<HAdd>( | |
1697 raw_index, Add<HConstant>(base_offset + 1)); | |
1698 result_index->ClearFlag(HValue::kCanOverflow); | |
1699 | |
1700 Push(Add<HLoadKeyed>(elements, result_index, | |
1701 static_cast<HValue*>(NULL), | |
1702 FAST_ELEMENTS)); | |
1703 } | |
1704 details_compare.End(); | |
1705 } | |
1706 key_compare.End(); | |
1707 | |
1708 return Pop(); | |
1709 } | |
1710 | |
1711 | |
1712 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { | 1634 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { |
1713 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); | 1635 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); |
1714 HValue* seed = Add<HConstant>(seed_value); | 1636 HValue* seed = Add<HConstant>(seed_value); |
1715 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); | 1637 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); |
1716 | 1638 |
1717 // hash = ~hash + (hash << 15); | 1639 // hash = ~hash + (hash << 15); |
1718 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); | 1640 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); |
1719 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, | 1641 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, |
1720 graph()->GetConstantMinus1()); | 1642 graph()->GetConstantMinus1()); |
1721 hash = AddUncasted<HAdd>(shifted_hash, not_hash); | 1643 hash = AddUncasted<HAdd>(shifted_hash, not_hash); |
(...skipping 27 matching lines...) Expand all Loading... | |
1749 HValue* capacity = Add<HLoadKeyed>( | 1671 HValue* capacity = Add<HLoadKeyed>( |
1750 elements, | 1672 elements, |
1751 Add<HConstant>(NameDictionary::kCapacityIndex), | 1673 Add<HConstant>(NameDictionary::kCapacityIndex), |
1752 static_cast<HValue*>(NULL), | 1674 static_cast<HValue*>(NULL), |
1753 FAST_ELEMENTS); | 1675 FAST_ELEMENTS); |
1754 | 1676 |
1755 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); | 1677 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
1756 mask->ChangeRepresentation(Representation::Integer32()); | 1678 mask->ChangeRepresentation(Representation::Integer32()); |
1757 mask->ClearFlag(HValue::kCanOverflow); | 1679 mask->ClearFlag(HValue::kCanOverflow); |
1758 | 1680 |
1759 return BuildUncheckedDictionaryElementLoadHelper(elements, key, | 1681 HValue* entry = hash; |
1760 hash, mask, 0); | 1682 HValue* count = graph()->GetConstant1(); |
1683 Push(entry); | |
1684 Push(count); | |
1685 | |
1686 HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(), | |
1687 graph()->CreateBasicBlock()); | |
1688 HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(), | |
1689 graph()->CreateBasicBlock()); | |
1690 LoopBuilder probe_loop(this); | |
1691 probe_loop.BeginBody(2); // Drop entry, count from last environment to | |
danno
2014/07/07 08:10:26
This makes me gag, but I guess there is no other w
Jakob Kummerow
2014/07/07 11:40:43
I don't like it either, but don't see a way around
| |
1692 // appease live range building without simulates. | |
1693 | |
1694 count = Pop(); | |
1695 entry = Pop(); | |
1696 entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask); | |
1697 int entry_size = SeededNumberDictionary::kEntrySize; | |
1698 HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size)); | |
1699 base_index->ClearFlag(HValue::kCanOverflow); | |
1700 int start_offset = SeededNumberDictionary::kElementsStartIndex; | |
1701 HValue* key_index = | |
1702 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset)); | |
1703 key_index->ClearFlag(HValue::kCanOverflow); | |
1704 | |
1705 HValue* candidate_key = Add<HLoadKeyed>( | |
1706 elements, key_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1707 IfBuilder if_undefined(this); | |
1708 if_undefined.If<HCompareObjectEqAndBranch>(candidate_key, | |
1709 graph()->GetConstantUndefined()); | |
1710 if_undefined.Then(); | |
1711 { | |
1712 // element == undefined means "not found". Call the runtime. | |
1713 // TODO(jkummerow): walk the prototype chain instead. | |
1714 Add<HPushArguments>(receiver, key); | |
1715 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | |
1716 Runtime::FunctionForId(Runtime::kKeyedGetProperty), | |
1717 2)); | |
1718 } | |
1719 if_undefined.Else(); | |
1720 { | |
1721 IfBuilder if_match(this); | |
1722 if_match.If<HCompareObjectEqAndBranch>(candidate_key, key); | |
1723 if_match.Then(); | |
1724 if_match.Else(); | |
1725 | |
1726 // Update non-internalized string in the dictionary with internalized key? | |
1727 IfBuilder if_update_with_internalized(this); | |
1728 HValue* smi_check = | |
1729 if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key); | |
1730 if_update_with_internalized.And(); | |
1731 HValue* map = AddLoadMap(candidate_key, smi_check); | |
1732 HValue* instance_type = Add<HLoadNamedField>( | |
1733 map, static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType()); | |
1734 HValue* not_internalized_bit = AddUncasted<HBitwise>( | |
1735 Token::BIT_AND, instance_type, | |
1736 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); | |
1737 if_update_with_internalized.If<HCompareNumericAndBranch>( | |
1738 not_internalized_bit, graph()->GetConstant0(), Token::NE); | |
1739 if_update_with_internalized.And(); | |
1740 if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>( | |
1741 candidate_key, graph()->GetConstantHole()); | |
1742 if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key, | |
1743 key, Token::EQ); | |
1744 if_update_with_internalized.Then(); | |
1745 // Replace a key that is a non-internalized string by the equivalent | |
1746 // internalized string for faster further lookups. | |
1747 Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS); | |
1748 if_update_with_internalized.Else(); | |
1749 | |
1750 if_update_with_internalized.JoinContinuation(&found_key_match_continuation); | |
1751 if_match.JoinContinuation(&found_key_match_continuation); | |
1752 | |
1753 IfBuilder found_key_match(this, &found_key_match_continuation); | |
1754 found_key_match.Then(); | |
1755 // Key at current probe matches. Relevant bits in the |details| field must | |
1756 // be zero, otherwise the dictionary element requires special handling. | |
1757 HValue* details_index = | |
1758 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2)); | |
1759 details_index->ClearFlag(HValue::kCanOverflow); | |
1760 HValue* details = Add<HLoadKeyed>( | |
1761 elements, details_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1762 int details_mask = PropertyDetails::TypeField::kMask | | |
1763 PropertyDetails::DeletedField::kMask; | |
1764 details = AddUncasted<HBitwise>(Token::BIT_AND, details, | |
1765 Add<HConstant>(details_mask)); | |
1766 IfBuilder details_compare(this); | |
1767 details_compare.If<HCompareNumericAndBranch>( | |
1768 details, graph()->GetConstant0(), Token::EQ); | |
1769 details_compare.Then(); | |
1770 HValue* result_index = | |
1771 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1)); | |
1772 result_index->ClearFlag(HValue::kCanOverflow); | |
1773 Push(Add<HLoadKeyed>(elements, result_index, static_cast<HValue*>(NULL), | |
1774 FAST_ELEMENTS)); | |
1775 details_compare.Else(); | |
1776 Add<HPushArguments>(receiver, key); | |
1777 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | |
1778 Runtime::FunctionForId(Runtime::kKeyedGetProperty), | |
1779 2)); | |
1780 details_compare.End(); | |
1781 | |
1782 found_key_match.Else(); | |
1783 found_key_match.JoinContinuation(&return_or_loop_continuation); | |
1784 } | |
1785 if_undefined.JoinContinuation(&return_or_loop_continuation); | |
1786 | |
1787 IfBuilder return_or_loop(this, &return_or_loop_continuation); | |
1788 return_or_loop.Then(); | |
1789 probe_loop.Break(); | |
1790 | |
1791 return_or_loop.Else(); | |
1792 entry = AddUncasted<HAdd>(entry, count); | |
1793 entry->ClearFlag(HValue::kCanOverflow); | |
1794 count = AddUncasted<HAdd>(count, graph()->GetConstant1()); | |
1795 count->ClearFlag(HValue::kCanOverflow); | |
1796 Push(entry); | |
1797 Push(count); | |
1798 | |
1799 probe_loop.EndBody(); | |
1800 | |
1801 return_or_loop.End(); | |
1802 | |
1803 return Pop(); | |
1761 } | 1804 } |
1762 | 1805 |
1763 | 1806 |
1764 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length, | 1807 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length, |
1765 HValue* index, | 1808 HValue* index, |
1766 HValue* input) { | 1809 HValue* input) { |
1767 NoObservableSideEffectsScope scope(this); | 1810 NoObservableSideEffectsScope scope(this); |
1768 HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray); | 1811 HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray); |
1769 Add<HBoundsCheck>(length, max_length); | 1812 Add<HBoundsCheck>(length, max_length); |
1770 | 1813 |
(...skipping 10628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12399 if (ShouldProduceTraceOutput()) { | 12442 if (ShouldProduceTraceOutput()) { |
12400 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12443 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12401 } | 12444 } |
12402 | 12445 |
12403 #ifdef DEBUG | 12446 #ifdef DEBUG |
12404 graph_->Verify(false); // No full verify. | 12447 graph_->Verify(false); // No full verify. |
12405 #endif | 12448 #endif |
12406 } | 12449 } |
12407 | 12450 |
12408 } } // namespace v8::internal | 12451 } } // namespace v8::internal |
OLD | NEW |