| 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 |