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 1574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1585 | 1585 |
1586 cow_checker.Else(); | 1586 cow_checker.Else(); |
1587 | 1587 |
1588 environment()->Push(elements); | 1588 environment()->Push(elements); |
1589 | 1589 |
1590 cow_checker.End(); | 1590 cow_checker.End(); |
1591 | 1591 |
1592 return environment()->Pop(); | 1592 return environment()->Pop(); |
1593 } | 1593 } |
1594 | 1594 |
1595 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { | |
1596 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); | |
1597 HValue* seed = Add<HConstant>(seed_value); | |
1598 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); | |
1599 | |
1600 // hash = ~hash + (hash << 15); | |
1601 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); | |
1602 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, | |
1603 graph()->GetConstantMinus1()); | |
1604 hash = AddUncasted<HAdd>(shifted_hash, not_hash); | |
1605 | |
1606 // hash = hash ^ (hash >> 12); | |
1607 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12)); | |
1608 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | |
1609 | |
1610 // hash = hash + (hash << 2); | |
1611 shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2)); | |
1612 hash = AddUncasted<HAdd>(hash, shifted_hash); | |
1613 | |
1614 // hash = hash ^ (hash >> 4); | |
1615 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4)); | |
1616 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | |
1617 | |
1618 // hash = hash * 2057; | |
1619 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); | |
1620 hash->ClearFlag(HValue::kCanOverflow); | |
1621 | |
1622 // hash = hash ^ (hash >> 16); | |
1623 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); | |
1624 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | |
1625 } | |
1626 | |
1627 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, | |
1628 HValue* elements, | |
1629 HValue* key, | |
1630 HValue* hash) { | |
1631 HValue* capacity = | |
1632 Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex), | |
1633 nullptr, nullptr, FAST_ELEMENTS); | |
1634 | |
1635 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); | |
1636 mask->ChangeRepresentation(Representation::Integer32()); | |
1637 mask->ClearFlag(HValue::kCanOverflow); | |
1638 | |
1639 HValue* entry = hash; | |
1640 HValue* count = graph()->GetConstant1(); | |
1641 Push(entry); | |
1642 Push(count); | |
1643 | |
1644 HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(), | |
1645 graph()->CreateBasicBlock()); | |
1646 HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(), | |
1647 graph()->CreateBasicBlock()); | |
1648 LoopBuilder probe_loop(this); | |
1649 probe_loop.BeginBody(2); // Drop entry, count from last environment to | |
1650 // appease live range building without simulates. | |
1651 | |
1652 count = Pop(); | |
1653 entry = Pop(); | |
1654 entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask); | |
1655 int entry_size = SeededNumberDictionary::kEntrySize; | |
1656 HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size)); | |
1657 base_index->ClearFlag(HValue::kCanOverflow); | |
1658 int start_offset = SeededNumberDictionary::kElementsStartIndex; | |
1659 HValue* key_index = | |
1660 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset)); | |
1661 key_index->ClearFlag(HValue::kCanOverflow); | |
1662 | |
1663 HValue* candidate_key = | |
1664 Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS); | |
1665 IfBuilder if_undefined(this); | |
1666 if_undefined.If<HCompareObjectEqAndBranch>(candidate_key, | |
1667 graph()->GetConstantUndefined()); | |
1668 if_undefined.Then(); | |
1669 { | |
1670 // element == undefined means "not found". Call the runtime. | |
1671 // TODO(jkummerow): walk the prototype chain instead. | |
1672 Add<HPushArguments>(receiver, key); | |
1673 Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty), | |
1674 2)); | |
1675 } | |
1676 if_undefined.Else(); | |
1677 { | |
1678 IfBuilder if_match(this); | |
1679 if_match.If<HCompareObjectEqAndBranch>(candidate_key, key); | |
1680 if_match.Then(); | |
1681 if_match.Else(); | |
1682 | |
1683 // Update non-internalized string in the dictionary with internalized key? | |
1684 IfBuilder if_update_with_internalized(this); | |
1685 HValue* smi_check = | |
1686 if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key); | |
1687 if_update_with_internalized.And(); | |
1688 HValue* map = AddLoadMap(candidate_key, smi_check); | |
1689 HValue* instance_type = | |
1690 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); | |
1691 HValue* not_internalized_bit = AddUncasted<HBitwise>( | |
1692 Token::BIT_AND, instance_type, | |
1693 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); | |
1694 if_update_with_internalized.If<HCompareNumericAndBranch>( | |
1695 not_internalized_bit, graph()->GetConstant0(), Token::NE); | |
1696 if_update_with_internalized.And(); | |
1697 if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>( | |
1698 candidate_key, graph()->GetConstantHole()); | |
1699 if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key, | |
1700 key, Token::EQ); | |
1701 if_update_with_internalized.Then(); | |
1702 // Replace a key that is a non-internalized string by the equivalent | |
1703 // internalized string for faster further lookups. | |
1704 Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS); | |
1705 if_update_with_internalized.Else(); | |
1706 | |
1707 if_update_with_internalized.JoinContinuation(&found_key_match_continuation); | |
1708 if_match.JoinContinuation(&found_key_match_continuation); | |
1709 | |
1710 IfBuilder found_key_match(this, &found_key_match_continuation); | |
1711 found_key_match.Then(); | |
1712 // Key at current probe matches. Relevant bits in the |details| field must | |
1713 // be zero, otherwise the dictionary element requires special handling. | |
1714 HValue* details_index = | |
1715 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2)); | |
1716 details_index->ClearFlag(HValue::kCanOverflow); | |
1717 HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr, | |
1718 FAST_ELEMENTS); | |
1719 int details_mask = PropertyDetails::KindField::kMask; | |
1720 details = AddUncasted<HBitwise>(Token::BIT_AND, details, | |
1721 Add<HConstant>(details_mask)); | |
1722 IfBuilder details_compare(this); | |
1723 details_compare.If<HCompareNumericAndBranch>(details, New<HConstant>(kData), | |
1724 Token::EQ); | |
1725 details_compare.Then(); | |
1726 HValue* result_index = | |
1727 AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1)); | |
1728 result_index->ClearFlag(HValue::kCanOverflow); | |
1729 Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr, | |
1730 FAST_ELEMENTS)); | |
1731 details_compare.Else(); | |
1732 Add<HPushArguments>(receiver, key); | |
1733 Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty), | |
1734 2)); | |
1735 details_compare.End(); | |
1736 | |
1737 found_key_match.Else(); | |
1738 found_key_match.JoinContinuation(&return_or_loop_continuation); | |
1739 } | |
1740 if_undefined.JoinContinuation(&return_or_loop_continuation); | |
1741 | |
1742 IfBuilder return_or_loop(this, &return_or_loop_continuation); | |
1743 return_or_loop.Then(); | |
1744 probe_loop.Break(); | |
1745 | |
1746 return_or_loop.Else(); | |
1747 entry = AddUncasted<HAdd>(entry, count); | |
1748 entry->ClearFlag(HValue::kCanOverflow); | |
1749 count = AddUncasted<HAdd>(count, graph()->GetConstant1()); | |
1750 count->ClearFlag(HValue::kCanOverflow); | |
1751 Push(entry); | |
1752 Push(count); | |
1753 | |
1754 probe_loop.EndBody(); | |
1755 | |
1756 return_or_loop.End(); | |
1757 | |
1758 return Pop(); | |
1759 } | |
1760 | |
1761 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value, | 1595 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value, |
1762 HValue* done) { | 1596 HValue* done) { |
1763 NoObservableSideEffectsScope scope(this); | 1597 NoObservableSideEffectsScope scope(this); |
1764 | 1598 |
1765 // Allocate the JSIteratorResult object. | 1599 // Allocate the JSIteratorResult object. |
1766 HValue* result = | 1600 HValue* result = |
1767 Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(), | 1601 Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(), |
1768 NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0()); | 1602 NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0()); |
1769 | 1603 |
1770 // Initialize the JSIteratorResult object. | 1604 // Initialize the JSIteratorResult object. |
(...skipping 1191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2962 } | 2796 } |
2963 } | 2797 } |
2964 | 2798 |
2965 | 2799 |
2966 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 2800 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
2967 return Add<HLoadNamedField>( | 2801 return Add<HLoadNamedField>( |
2968 context(), nullptr, | 2802 context(), nullptr, |
2969 HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX)); | 2803 HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX)); |
2970 } | 2804 } |
2971 | 2805 |
2972 | |
2973 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { | |
2974 // Get the global object, then the native context | |
2975 HInstruction* context = Add<HLoadNamedField>( | |
2976 closure, nullptr, HObjectAccess::ForFunctionContextPointer()); | |
2977 return Add<HLoadNamedField>( | |
2978 context, nullptr, | |
2979 HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX)); | |
2980 } | |
2981 | |
2982 | |
2983 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) { | |
2984 HValue* script_context = context(); | |
2985 if (depth != NULL) { | |
2986 HValue* zero = graph()->GetConstant0(); | |
2987 | |
2988 Push(script_context); | |
2989 Push(depth); | |
2990 | |
2991 LoopBuilder loop(this); | |
2992 loop.BeginBody(2); // Drop script_context and depth from last environment | |
2993 // to appease live range building without simulates. | |
2994 depth = Pop(); | |
2995 script_context = Pop(); | |
2996 | |
2997 script_context = Add<HLoadNamedField>( | |
2998 script_context, nullptr, | |
2999 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | |
3000 depth = AddUncasted<HSub>(depth, graph()->GetConstant1()); | |
3001 depth->ClearFlag(HValue::kCanOverflow); | |
3002 | |
3003 IfBuilder if_break(this); | |
3004 if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ); | |
3005 if_break.Then(); | |
3006 { | |
3007 Push(script_context); // The result. | |
3008 loop.Break(); | |
3009 } | |
3010 if_break.Else(); | |
3011 { | |
3012 Push(script_context); | |
3013 Push(depth); | |
3014 } | |
3015 loop.EndBody(); | |
3016 if_break.End(); | |
3017 | |
3018 script_context = Pop(); | |
3019 } else if (depth_value > 0) { | |
3020 // Unroll the above loop. | |
3021 for (int i = 0; i < depth_value; i++) { | |
3022 script_context = Add<HLoadNamedField>( | |
3023 script_context, nullptr, | |
3024 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | |
3025 } | |
3026 } | |
3027 return script_context; | |
3028 } | |
3029 | |
3030 | |
3031 HInstruction* HGraphBuilder::BuildGetArrayFunction() { | |
3032 HInstruction* native_context = BuildGetNativeContext(); | |
3033 HInstruction* index = | |
3034 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | |
3035 return Add<HLoadKeyed>(native_context, index, nullptr, nullptr, | |
3036 FAST_ELEMENTS); | |
3037 } | |
3038 | |
3039 | |
3040 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object, | 2806 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object, |
3041 HValue* checked_object, | 2807 HValue* checked_object, |
3042 FieldIndex index) { | 2808 FieldIndex index) { |
3043 NoObservableSideEffectsScope scope(this); | 2809 NoObservableSideEffectsScope scope(this); |
3044 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( | 2810 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( |
3045 index.offset(), Representation::Tagged()); | 2811 index.offset(), Representation::Tagged()); |
3046 HInstruction* buffer = Add<HLoadNamedField>( | 2812 HInstruction* buffer = Add<HLoadNamedField>( |
3047 object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer()); | 2813 object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer()); |
3048 HInstruction* field = Add<HLoadNamedField>(object, checked_object, access); | 2814 HInstruction* field = Add<HLoadNamedField>(object, checked_object, access); |
3049 | 2815 |
3050 HInstruction* flags = Add<HLoadNamedField>( | 2816 HInstruction* flags = Add<HLoadNamedField>( |
3051 buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField()); | 2817 buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField()); |
3052 HValue* was_neutered_mask = | 2818 HValue* was_neutered_mask = |
3053 Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift); | 2819 Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift); |
3054 HValue* was_neutered_test = | 2820 HValue* was_neutered_test = |
3055 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); | 2821 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); |
3056 | 2822 |
3057 IfBuilder if_was_neutered(this); | 2823 IfBuilder if_was_neutered(this); |
3058 if_was_neutered.If<HCompareNumericAndBranch>( | 2824 if_was_neutered.If<HCompareNumericAndBranch>( |
3059 was_neutered_test, graph()->GetConstant0(), Token::NE); | 2825 was_neutered_test, graph()->GetConstant0(), Token::NE); |
3060 if_was_neutered.Then(); | 2826 if_was_neutered.Then(); |
3061 Push(graph()->GetConstant0()); | 2827 Push(graph()->GetConstant0()); |
3062 if_was_neutered.Else(); | 2828 if_was_neutered.Else(); |
3063 Push(field); | 2829 Push(field); |
3064 if_was_neutered.End(); | 2830 if_was_neutered.End(); |
3065 | 2831 |
3066 return Pop(); | 2832 return Pop(); |
3067 } | 2833 } |
3068 | 2834 |
3069 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { | |
3070 HValue* native_context = BuildGetNativeContext(); | |
3071 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); | |
3072 return Add<HLoadNamedField>(native_context, nullptr, function_access); | |
3073 } | |
3074 | |
3075 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 2835 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
3076 bool track_positions) | 2836 bool track_positions) |
3077 : HGraphBuilder(info, CallInterfaceDescriptor(), track_positions), | 2837 : HGraphBuilder(info, CallInterfaceDescriptor(), track_positions), |
3078 function_state_(NULL), | 2838 function_state_(NULL), |
3079 initial_function_state_(this, info, NORMAL_RETURN, -1, | 2839 initial_function_state_(this, info, NORMAL_RETURN, -1, |
3080 TailCallMode::kAllow), | 2840 TailCallMode::kAllow), |
3081 ast_context_(NULL), | 2841 ast_context_(NULL), |
3082 break_scope_(NULL), | 2842 break_scope_(NULL), |
3083 inlined_count_(0), | 2843 inlined_count_(0), |
3084 globals_(10, info->zone()), | 2844 globals_(10, info->zone()), |
(...skipping 9676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12761 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12521 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12762 } | 12522 } |
12763 | 12523 |
12764 #ifdef DEBUG | 12524 #ifdef DEBUG |
12765 graph_->Verify(false); // No full verify. | 12525 graph_->Verify(false); // No full verify. |
12766 #endif | 12526 #endif |
12767 } | 12527 } |
12768 | 12528 |
12769 } // namespace internal | 12529 } // namespace internal |
12770 } // namespace v8 | 12530 } // namespace v8 |
OLD | NEW |