| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 PrintChangesTo(stream); | 626 PrintChangesTo(stream); |
| 627 PrintTypeTo(stream); | 627 PrintTypeTo(stream); |
| 628 } | 628 } |
| 629 | 629 |
| 630 | 630 |
| 631 void HInstruction::PrintMnemonicTo(StringStream* stream) { | 631 void HInstruction::PrintMnemonicTo(StringStream* stream) { |
| 632 stream->Add("%s ", Mnemonic()); | 632 stream->Add("%s ", Mnemonic()); |
| 633 } | 633 } |
| 634 | 634 |
| 635 | 635 |
| 636 bool HInstruction::IsDefinedAfterInSameBlock(HValue* other) const { |
| 637 // Is the current instruction defined after other and in |
| 638 // the same block? |
| 639 if (block() != other->block()) { |
| 640 return false; |
| 641 } |
| 642 |
| 643 HInstruction* cur = previous(); |
| 644 while (cur != NULL) { |
| 645 if (cur == other) break; |
| 646 cur = cur->previous(); |
| 647 } |
| 648 |
| 649 return cur == other; |
| 650 } |
| 651 |
| 652 |
| 636 void HInstruction::Unlink() { | 653 void HInstruction::Unlink() { |
| 637 ASSERT(IsLinked()); | 654 ASSERT(IsLinked()); |
| 638 ASSERT(!IsControlInstruction()); // Must never move control instructions. | 655 ASSERT(!IsControlInstruction()); // Must never move control instructions. |
| 639 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these. | 656 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these. |
| 640 ASSERT(previous_ != NULL); | 657 ASSERT(previous_ != NULL); |
| 641 previous_->next_ = next_; | 658 previous_->next_ = next_; |
| 642 if (next_ == NULL) { | 659 if (next_ == NULL) { |
| 643 ASSERT(block()->last() == this); | 660 ASSERT(block()->last() == this); |
| 644 block()->set_last(previous_); | 661 block()->set_last(previous_); |
| 645 } else { | 662 } else { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 #ifdef DEBUG | 718 #ifdef DEBUG |
| 702 void HInstruction::Verify() { | 719 void HInstruction::Verify() { |
| 703 // Verify that input operands are defined before use. | 720 // Verify that input operands are defined before use. |
| 704 HBasicBlock* cur_block = block(); | 721 HBasicBlock* cur_block = block(); |
| 705 for (int i = 0; i < OperandCount(); ++i) { | 722 for (int i = 0; i < OperandCount(); ++i) { |
| 706 HValue* other_operand = OperandAt(i); | 723 HValue* other_operand = OperandAt(i); |
| 707 if (other_operand == NULL) continue; | 724 if (other_operand == NULL) continue; |
| 708 HBasicBlock* other_block = other_operand->block(); | 725 HBasicBlock* other_block = other_operand->block(); |
| 709 if (cur_block == other_block) { | 726 if (cur_block == other_block) { |
| 710 if (!other_operand->IsPhi()) { | 727 if (!other_operand->IsPhi()) { |
| 711 HInstruction* cur = this->previous(); | 728 // We must be defined after other operand in the same block! |
| 712 while (cur != NULL) { | 729 ASSERT(IsDefinedAfterInSameBlock(other_operand)); |
| 713 if (cur == other_operand) break; | |
| 714 cur = cur->previous(); | |
| 715 } | |
| 716 // Must reach other operand in the same block! | |
| 717 ASSERT(cur == other_operand); | |
| 718 } | 730 } |
| 719 } else { | 731 } else { |
| 720 // If the following assert fires, you may have forgotten an | 732 // If the following assert fires, you may have forgotten an |
| 721 // AddInstruction. | 733 // AddInstruction. |
| 722 ASSERT(other_block->Dominates(cur_block)); | 734 ASSERT(other_block->Dominates(cur_block)); |
| 723 } | 735 } |
| 724 } | 736 } |
| 725 | 737 |
| 726 // Verify that instructions that may have side-effects are followed | 738 // Verify that instructions that may have side-effects are followed |
| 727 // by a simulate instruction. | 739 // by a simulate instruction. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 stream->Add(")"); | 832 stream->Add(")"); |
| 821 } | 833 } |
| 822 | 834 |
| 823 | 835 |
| 824 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) { | 836 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) { |
| 825 value()->PrintNameTo(stream); | 837 value()->PrintNameTo(stream); |
| 826 HControlInstruction::PrintDataTo(stream); | 838 HControlInstruction::PrintDataTo(stream); |
| 827 } | 839 } |
| 828 | 840 |
| 829 | 841 |
| 842 void HFastLiteral::PrintDataTo(StringStream* stream) { |
| 843 if (TransitionRequested()) { |
| 844 stream->Add(" (Transition to %s requested)", |
| 845 ElementsKindToString(TransitionTo())); |
| 846 } |
| 847 } |
| 848 |
| 849 |
| 830 void HIsNilAndBranch::PrintDataTo(StringStream* stream) { | 850 void HIsNilAndBranch::PrintDataTo(StringStream* stream) { |
| 831 value()->PrintNameTo(stream); | 851 value()->PrintNameTo(stream); |
| 832 stream->Add(kind() == kStrictEquality ? " === " : " == "); | 852 stream->Add(kind() == kStrictEquality ? " === " : " == "); |
| 833 stream->Add(nil() == kNullValue ? "null" : "undefined"); | 853 stream->Add(nil() == kNullValue ? "null" : "undefined"); |
| 834 HControlInstruction::PrintDataTo(stream); | 854 HControlInstruction::PrintDataTo(stream); |
| 835 } | 855 } |
| 836 | 856 |
| 837 | 857 |
| 838 void HReturn::PrintDataTo(StringStream* stream) { | 858 void HReturn::PrintDataTo(StringStream* stream) { |
| 839 value()->PrintNameTo(stream); | 859 value()->PrintNameTo(stream); |
| (...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 : new(zone) Range(); | 1786 : new(zone) Range(); |
| 1767 result->Shl(c->Integer32Value()); | 1787 result->Shl(c->Integer32Value()); |
| 1768 result->set_can_be_minus_zero(false); | 1788 result->set_can_be_minus_zero(false); |
| 1769 return result; | 1789 return result; |
| 1770 } | 1790 } |
| 1771 } | 1791 } |
| 1772 return HValue::InferRange(zone); | 1792 return HValue::InferRange(zone); |
| 1773 } | 1793 } |
| 1774 | 1794 |
| 1775 | 1795 |
| 1796 HLoadKeyed::HLoadKeyed(HValue* obj, |
| 1797 HValue* key, |
| 1798 HValue* dependency, |
| 1799 ElementsKind elements_kind, |
| 1800 Zone* zone) |
| 1801 : HArrayInstruction(obj, key, zone), bit_field_(0) { |
| 1802 bit_field_ = ElementsKindField::encode(elements_kind); |
| 1803 SetOperandAt(2, dependency); |
| 1804 |
| 1805 if (is_external()) { |
| 1806 SetInitialized(); |
| 1807 |
| 1808 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| 1809 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 1810 set_representation(Representation::Double()); |
| 1811 } else { |
| 1812 set_representation(Representation::Integer32()); |
| 1813 } |
| 1814 |
| 1815 SetGVNFlag(kDependsOnSpecializedArrayElements); |
| 1816 // Native code could change the specialized array. |
| 1817 SetGVNFlag(kDependsOnCalls); |
| 1818 } else { |
| 1819 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
| 1820 IsFastDoubleElementsKind(elements_kind)); |
| 1821 |
| 1822 // We don't yet know what it depends on yet, so set both flags |
| 1823 SetGVNFlag(kDependsOnArrayElements); |
| 1824 SetGVNFlag(kDependsOnDoubleArrayElements); |
| 1825 if (!FLAG_use_place_elements_transitions) { |
| 1826 PerformDeferredInitialization(); |
| 1827 } |
| 1828 } |
| 1829 |
| 1830 SetFlag(kUseGVN); |
| 1831 } |
| 1832 |
| 1833 |
| 1834 void HLoadKeyed::PerformDeferredInitialization(ElementsKind new_elements_kind) { |
| 1835 ASSERT(!is_external()); |
| 1836 ASSERT(!Initialized()); |
| 1837 SetInitialized(); |
| 1838 |
| 1839 if (new_elements_kind != elements_kind()) { |
| 1840 bit_field_ = ElementsKindField::encode(new_elements_kind); |
| 1841 } |
| 1842 |
| 1843 ClearGVNFlag(kDependsOnArrayElements); |
| 1844 ClearGVNFlag(kDependsOnDoubleArrayElements); |
| 1845 |
| 1846 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
| 1847 if (IsFastSmiElementsKind(elements_kind()) && |
| 1848 IsFastPackedElementsKind(elements_kind())) { |
| 1849 set_type(HType::Smi()); |
| 1850 } |
| 1851 |
| 1852 set_representation(Representation::Tagged()); |
| 1853 SetGVNFlag(kDependsOnArrayElements); |
| 1854 } else { |
| 1855 set_representation(Representation::Double()); |
| 1856 SetGVNFlag(kDependsOnDoubleArrayElements); |
| 1857 } |
| 1858 } |
| 1859 |
| 1860 |
| 1776 Range* HLoadKeyed::InferRange(Zone* zone) { | 1861 Range* HLoadKeyed::InferRange(Zone* zone) { |
| 1777 switch (elements_kind()) { | 1862 switch (elements_kind()) { |
| 1778 case EXTERNAL_PIXEL_ELEMENTS: | 1863 case EXTERNAL_PIXEL_ELEMENTS: |
| 1779 return new(zone) Range(0, 255); | 1864 return new(zone) Range(0, 255); |
| 1780 case EXTERNAL_BYTE_ELEMENTS: | 1865 case EXTERNAL_BYTE_ELEMENTS: |
| 1781 return new(zone) Range(-128, 127); | 1866 return new(zone) Range(-128, 127); |
| 1782 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 1867 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 1783 return new(zone) Range(0, 255); | 1868 return new(zone) Range(0, 255); |
| 1784 case EXTERNAL_SHORT_ELEMENTS: | 1869 case EXTERNAL_SHORT_ELEMENTS: |
| 1785 return new(zone) Range(-32768, 32767); | 1870 return new(zone) Range(-32768, 32767); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 | 2160 |
| 2076 if (names_cache->enumerable() == object()) { | 2161 if (names_cache->enumerable() == object()) { |
| 2077 HForInCacheArray* index_cache = | 2162 HForInCacheArray* index_cache = |
| 2078 names_cache->index_cache(); | 2163 names_cache->index_cache(); |
| 2079 HCheckMapValue* map_check = | 2164 HCheckMapValue* map_check = |
| 2080 new(block()->zone()) HCheckMapValue(object(), names_cache->map()); | 2165 new(block()->zone()) HCheckMapValue(object(), names_cache->map()); |
| 2081 HInstruction* index = new(block()->zone()) HLoadKeyed( | 2166 HInstruction* index = new(block()->zone()) HLoadKeyed( |
| 2082 index_cache, | 2167 index_cache, |
| 2083 key_load->key(), | 2168 key_load->key(), |
| 2084 key_load->key(), | 2169 key_load->key(), |
| 2085 key_load->elements_kind()); | 2170 key_load->elements_kind(), |
| 2171 block()->zone()); |
| 2086 map_check->InsertBefore(this); | 2172 map_check->InsertBefore(this); |
| 2087 index->InsertBefore(this); | 2173 index->InsertBefore(this); |
| 2088 HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex( | 2174 HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex( |
| 2089 object(), index); | 2175 object(), index); |
| 2090 load->InsertBefore(this); | 2176 load->InsertBefore(this); |
| 2091 return load; | 2177 return load; |
| 2092 } | 2178 } |
| 2093 } | 2179 } |
| 2094 } | 2180 } |
| 2095 | 2181 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2438 visited->Add(id()); | 2524 visited->Add(id()); |
| 2439 // Propagate to the left argument. If the left argument cannot be -0, then | 2525 // Propagate to the left argument. If the left argument cannot be -0, then |
| 2440 // the result of the sub operation cannot be either. | 2526 // the result of the sub operation cannot be either. |
| 2441 if (range() == NULL || range()->CanBeMinusZero()) { | 2527 if (range() == NULL || range()->CanBeMinusZero()) { |
| 2442 return left(); | 2528 return left(); |
| 2443 } | 2529 } |
| 2444 return NULL; | 2530 return NULL; |
| 2445 } | 2531 } |
| 2446 | 2532 |
| 2447 | 2533 |
| 2534 // Determines whether the given array or object literal boilerplate satisfies |
| 2535 // all limits to be considered for fast deep-copying and computes the total |
| 2536 // size of all objects that are part of the graph. |
| 2537 bool HFastLiteral::IsFastLiteral(Handle<JSObject> boilerplate, |
| 2538 int max_depth, |
| 2539 int* max_properties, |
| 2540 int* total_size) { |
| 2541 ASSERT(max_depth >= 0 && *max_properties >= 0); |
| 2542 if (max_depth == 0) return false; |
| 2543 |
| 2544 Handle<FixedArrayBase> elements(boilerplate->elements()); |
| 2545 if (elements->length() > 0 && |
| 2546 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { |
| 2547 if (boilerplate->HasFastDoubleElements()) { |
| 2548 *total_size += FixedDoubleArray::SizeFor(elements->length()); |
| 2549 } else if (boilerplate->HasFastObjectElements()) { |
| 2550 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 2551 int length = elements->length(); |
| 2552 for (int i = 0; i < length; i++) { |
| 2553 if ((*max_properties)-- == 0) return false; |
| 2554 Handle<Object> value(fast_elements->get(i)); |
| 2555 if (value->IsJSObject()) { |
| 2556 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 2557 if (!IsFastLiteral(value_object, |
| 2558 max_depth - 1, |
| 2559 max_properties, |
| 2560 total_size)) { |
| 2561 return false; |
| 2562 } |
| 2563 } |
| 2564 } |
| 2565 *total_size += FixedArray::SizeFor(length); |
| 2566 } else { |
| 2567 return false; |
| 2568 } |
| 2569 } |
| 2570 |
| 2571 Handle<FixedArray> properties(boilerplate->properties()); |
| 2572 if (properties->length() > 0) { |
| 2573 return false; |
| 2574 } else { |
| 2575 int nof = boilerplate->map()->inobject_properties(); |
| 2576 for (int i = 0; i < nof; i++) { |
| 2577 if ((*max_properties)-- == 0) return false; |
| 2578 Handle<Object> value(boilerplate->InObjectPropertyAt(i)); |
| 2579 if (value->IsJSObject()) { |
| 2580 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 2581 if (!IsFastLiteral(value_object, |
| 2582 max_depth - 1, |
| 2583 max_properties, |
| 2584 total_size)) { |
| 2585 return false; |
| 2586 } |
| 2587 } |
| 2588 } |
| 2589 } |
| 2590 |
| 2591 *total_size += boilerplate->map()->instance_size(); |
| 2592 return true; |
| 2593 } |
| 2594 |
| 2595 |
| 2596 HStoreKeyed::HStoreKeyed(HValue* obj, HValue* key, HValue* val, |
| 2597 ElementsKind elements_kind, |
| 2598 Zone* zone) |
| 2599 : HArrayInstruction(obj, key, zone), |
| 2600 elements_kind_(elements_kind), |
| 2601 index_offset_(0), |
| 2602 is_dehoisted_(false) { |
| 2603 SetOperandAt(2, val); |
| 2604 |
| 2605 if (is_external()) { |
| 2606 SetInitialized(); |
| 2607 |
| 2608 SetGVNFlag(kChangesSpecializedArrayElements); |
| 2609 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating. |
| 2610 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS && |
| 2611 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 2612 SetFlag(kTruncatingToInt32); |
| 2613 } |
| 2614 } else { |
| 2615 // We don't know what we'll have later. |
| 2616 // Initialize for the worst case |
| 2617 SetGVNFlag(kChangesDoubleArrayElements); |
| 2618 SetFlag(kDeoptimizeOnUndefined); |
| 2619 SetGVNFlag(kChangesArrayElements); |
| 2620 |
| 2621 if (!FLAG_use_place_elements_transitions) { |
| 2622 PerformDeferredInitialization(); |
| 2623 } |
| 2624 } |
| 2625 } |
| 2626 |
| 2627 |
| 2628 void HStoreKeyed::PerformDeferredInitialization( |
| 2629 ElementsKind new_elements_kind) { |
| 2630 ASSERT(!is_external()); |
| 2631 ASSERT(!Initialized()); |
| 2632 SetInitialized(); |
| 2633 |
| 2634 if (new_elements_kind != elements_kind_) { |
| 2635 elements_kind_ = new_elements_kind; |
| 2636 } |
| 2637 |
| 2638 // Adjust flags appropriately |
| 2639 if (IsFastDoubleElementsKind(elements_kind())) { |
| 2640 ClearGVNFlag(kChangesArrayElements); |
| 2641 } else { |
| 2642 ClearGVNFlag(kChangesDoubleArrayElements); |
| 2643 ClearFlag(kDeoptimizeOnUndefined); |
| 2644 } |
| 2645 } |
| 2646 |
| 2647 |
| 2448 bool HStoreKeyed::NeedsCanonicalization() { | 2648 bool HStoreKeyed::NeedsCanonicalization() { |
| 2449 // If value is an integer or comes from the result of a keyed load | 2649 // If value is an integer or comes from the result of a keyed load |
| 2450 // then it will be a non-hole value: no need for canonicalization. | 2650 // then it will be a non-hole value: no need for canonicalization. |
| 2451 if (value()->IsLoadKeyed() || | 2651 if (value()->IsLoadKeyed() || |
| 2452 (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) { | 2652 (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) { |
| 2453 return false; | 2653 return false; |
| 2454 } | 2654 } |
| 2455 return true; | 2655 return true; |
| 2456 } | 2656 } |
| 2457 | 2657 |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2732 all_uses_require = use_rep; | 2932 all_uses_require = use_rep; |
| 2733 } | 2933 } |
| 2734 if (all_uses_require_the_same) { | 2934 if (all_uses_require_the_same) { |
| 2735 return all_uses_require; | 2935 return all_uses_require; |
| 2736 } | 2936 } |
| 2737 | 2937 |
| 2738 return Representation::None(); | 2938 return Representation::None(); |
| 2739 } | 2939 } |
| 2740 | 2940 |
| 2741 | 2941 |
| 2942 HTransitionElementsKind::HTransitionElementsKind(HValue* object, |
| 2943 Handle<Map> original_map, |
| 2944 Handle<Map> transitioned_map, |
| 2945 Isolate* isolate, |
| 2946 bool calculatePessimisticHoleyAndFamily) |
| 2947 |
| 2948 : original_map_(original_map), |
| 2949 transitioned_map_(transitioned_map), |
| 2950 pessimistic_holey_(Handle<Map>::null()), |
| 2951 family_(Handle<Map>::null()), |
| 2952 special_case_(false) { |
| 2953 SetOperandAt(0, object); |
| 2954 SetFlag(kUseGVN); |
| 2955 SetGVNFlag(kChangesElementsKind); |
| 2956 if (original_map->has_fast_double_elements()) { |
| 2957 SetGVNFlag(kChangesElementsPointer); |
| 2958 SetGVNFlag(kChangesNewSpacePromotion); |
| 2959 } |
| 2960 if (transitioned_map->has_fast_double_elements()) { |
| 2961 SetGVNFlag(kChangesElementsPointer); |
| 2962 SetGVNFlag(kChangesNewSpacePromotion); |
| 2963 } |
| 2964 set_representation(Representation::Tagged()); |
| 2965 |
| 2966 if (calculatePessimisticHoleyAndFamily) { |
| 2967 Handle<Map> map_to = transitioned_map_; |
| 2968 |
| 2969 // When transition records are created, we have the chance to create map |
| 2970 // transitions we might need later. Transitions are unified during |
| 2971 // optimization, and we may need to transition from a packed fastmap to a |
| 2972 // holey version of same. But we can't create those transitions during |
| 2973 // optimization. Do it now, recognizing that when the handle disappears |
| 2974 // these maps may be collected if they didn't make it into usage in the |
| 2975 // optimized graph. |
| 2976 if (pessimistic_holey_.is_null()) { |
| 2977 if (IsFastPackedElementsKind(map_to->elements_kind())) { |
| 2978 ElementsKind holey_kind = GetHoleyElementsKind(map_to->elements_kind()); |
| 2979 // The transition might already exist |
| 2980 Handle<Map> holey_map_handle(FindClosestElementsTransition(*map_to, |
| 2981 holey_kind)); |
| 2982 ASSERT(!holey_map_handle.is_null()); |
| 2983 if (holey_map_handle->elements_kind() != holey_kind) { |
| 2984 MaybeObject* holey_map = map_to->AddMissingElementsTransitions( |
| 2985 holey_kind); |
| 2986 holey_map->ToHandle<Map>(&pessimistic_holey_, isolate); |
| 2987 } else { |
| 2988 pessimistic_holey_ = holey_map_handle; |
| 2989 } |
| 2990 } else { |
| 2991 pessimistic_holey_ = map_to; |
| 2992 } |
| 2993 } |
| 2994 |
| 2995 if (family_.is_null()) { |
| 2996 // fill in map_family_ |
| 2997 // Walk up to the base map from the map_to(); |
| 2998 Handle<Map> end_map(FindClosestElementsTransition(*map_to, |
| 2999 TERMINAL_FAST_ELEMENTS_KIND)); |
| 3000 ASSERT(!end_map.is_null()); |
| 3001 family_ = end_map; |
| 3002 } |
| 3003 |
| 3004 ASSERT(!pessimistic_holey_.is_null()); |
| 3005 ASSERT(!family_.is_null()); |
| 3006 } |
| 3007 } |
| 3008 |
| 3009 void HArrayInstruction::PrintElementPlacementTo(StringStream* stream) { |
| 3010 stream->Add("SITE: block%d %d: ", block()->block_id(), |
| 3011 id()); |
| 3012 PrintTo(stream); |
| 3013 stream->Add("\n"); |
| 3014 |
| 3015 stream->Add(" HOISTABLE: %s\n", hoistable() ? "true" : "false"); |
| 3016 stream->Add(" ELEMENTS_KIND: %s\n", ElementsKindToString(GetElementsKind())); |
| 3017 |
| 3018 // Print score |
| 3019 // stream->Add(" SCORE: (+%d,%d,-%d)\n", score_[0], score_[1], score_[2]); |
| 3020 |
| 3021 // Find the def point for the instruction |
| 3022 HValue *element = elements(); |
| 3023 ASSERT(element != NULL); |
| 3024 // Now get the item from the elements |
| 3025 ASSERT(element->IsLoadElements()); |
| 3026 HValue *elements_value = HLoadElements::cast(element)->value(); |
| 3027 stream->Add(" OBJECT: "); |
| 3028 elements_value->PrintNameTo(stream); |
| 3029 stream->Add(" "); |
| 3030 elements_value->PrintTo(stream); |
| 3031 stream->Add(" %s\n", elements_value->IsPhi() ? "PHI" : ""); |
| 3032 stream->Add(" TRANSITIONS:\n"); |
| 3033 ElementsKind transitionElementsKind = FAST_SMI_ELEMENTS; |
| 3034 for (int i = 0; i < transitions(); i++) { |
| 3035 HTransitionElementsKind* b = transition(i); |
| 3036 stream->Add(" %s", ElementsKindToString( |
| 3037 b->original_map()->elements_kind())); |
| 3038 stream->Add("(0x%p)-> ", *(b->original_map())); |
| 3039 transitionElementsKind = b->transitioned_map()->elements_kind(); |
| 3040 stream->Add("%s", ElementsKindToString(transitionElementsKind)); |
| 3041 stream->Add("(0x%p)\n", *(b->transitioned_map())); |
| 3042 } |
| 3043 } |
| 3044 |
| 3045 |
| 3046 void HArrayInstruction::AddTransitions(const ZoneList<HTransitionElementsKind*>& |
| 3047 transition_list) { |
| 3048 ASSERT(transition_list.length() > 0); |
| 3049 #ifdef DEBUG |
| 3050 Map* first_to_map = *(transition_list[0]->transitioned_map()); |
| 3051 #endif |
| 3052 |
| 3053 // Doesn't check for duplicates. |
| 3054 // The "to" map values should be the same for the whole group |
| 3055 for (int i = 0; i < transition_list.length(); i++) { |
| 3056 transitions_->Add(transition_list[i], zone_); |
| 3057 ASSERT(first_to_map == |
| 3058 *(transition_list[i]->transitioned_map())); |
| 3059 } |
| 3060 } |
| 3061 |
| 3062 |
| 3063 Handle<Map> HArrayInstruction::map_family() { |
| 3064 Handle<Map> family = Handle<Map>::null(); |
| 3065 if (transitions()) { |
| 3066 family = transition(0)->family(); |
| 3067 } |
| 3068 |
| 3069 #ifdef DEBUG |
| 3070 for (int i = 1; i < transitions(); i++) { |
| 3071 HTransitionElementsKind* tr = transition(i); |
| 3072 ASSERT(*(tr->family()) == *family); |
| 3073 } |
| 3074 #endif |
| 3075 return family; |
| 3076 } |
| 3077 |
| 3078 |
| 2742 // Node-specific verification code is only included in debug mode. | 3079 // Node-specific verification code is only included in debug mode. |
| 2743 #ifdef DEBUG | 3080 #ifdef DEBUG |
| 2744 | 3081 |
| 2745 void HPhi::Verify() { | 3082 void HPhi::Verify() { |
| 2746 ASSERT(OperandCount() == block()->predecessors()->length()); | 3083 ASSERT(OperandCount() == block()->predecessors()->length()); |
| 2747 for (int i = 0; i < OperandCount(); ++i) { | 3084 for (int i = 0; i < OperandCount(); ++i) { |
| 2748 HValue* value = OperandAt(i); | 3085 HValue* value = OperandAt(i); |
| 2749 HBasicBlock* defining_block = value->block(); | 3086 HBasicBlock* defining_block = value->block(); |
| 2750 HBasicBlock* predecessor_block = block()->predecessors()->at(i); | 3087 HBasicBlock* predecessor_block = block()->predecessors()->at(i); |
| 2751 ASSERT(defining_block == predecessor_block || | 3088 ASSERT(defining_block == predecessor_block || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2773 | 3110 |
| 2774 | 3111 |
| 2775 void HCheckFunction::Verify() { | 3112 void HCheckFunction::Verify() { |
| 2776 HInstruction::Verify(); | 3113 HInstruction::Verify(); |
| 2777 ASSERT(HasNoUses()); | 3114 ASSERT(HasNoUses()); |
| 2778 } | 3115 } |
| 2779 | 3116 |
| 2780 #endif | 3117 #endif |
| 2781 | 3118 |
| 2782 } } // namespace v8::internal | 3119 } } // namespace v8::internal |
| OLD | NEW |