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

Side by Side Diff: src/hydrogen.cc

Issue 369893004: Hydrogenized KeyedLoadGeneric stub: exhaustively search dictionary properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698