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 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 } | 687 } |
688 | 688 |
689 | 689 |
690 HGraph::HGraph(CompilationInfo* info) | 690 HGraph::HGraph(CompilationInfo* info) |
691 : isolate_(info->isolate()), | 691 : isolate_(info->isolate()), |
692 next_block_id_(0), | 692 next_block_id_(0), |
693 entry_block_(NULL), | 693 entry_block_(NULL), |
694 blocks_(8, info->zone()), | 694 blocks_(8, info->zone()), |
695 values_(16, info->zone()), | 695 values_(16, info->zone()), |
696 phi_list_(NULL), | 696 phi_list_(NULL), |
| 697 uint32_instructions_(NULL), |
697 info_(info), | 698 info_(info), |
698 zone_(info->zone()), | 699 zone_(info->zone()), |
699 is_recursive_(false) { | 700 is_recursive_(false) { |
700 start_environment_ = | 701 start_environment_ = |
701 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 702 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
702 start_environment_->set_ast_id(BailoutId::FunctionEntry()); | 703 start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
703 entry_block_ = CreateBasicBlock(); | 704 entry_block_ = CreateBasicBlock(); |
704 entry_block_->SetInitialEnvironment(start_environment_); | 705 entry_block_->SetInitialEnvironment(start_environment_); |
705 } | 706 } |
706 | 707 |
(...skipping 2009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { | 2717 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { |
2717 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | 2718 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
2718 break; | 2719 break; |
2719 } | 2720 } |
2720 } | 2721 } |
2721 } | 2722 } |
2722 } | 2723 } |
2723 } | 2724 } |
2724 | 2725 |
2725 | 2726 |
| 2727 // Discover instructions that can be marked with kUint32 flag allowing |
| 2728 // them to produce full range uint32 values. |
| 2729 class Uint32Analysis BASE_EMBEDDED { |
| 2730 public: |
| 2731 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { } |
| 2732 |
| 2733 void Analyze(HInstruction* current); |
| 2734 |
| 2735 void UnmarkUnsafePhis(); |
| 2736 |
| 2737 private: |
| 2738 bool IsSafeUint32Use(HValue* val, HValue* use); |
| 2739 bool Uint32UsesAreSafe(HValue* uint32val); |
| 2740 bool CheckPhiOperands(HPhi* phi); |
| 2741 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); |
| 2742 |
| 2743 Zone* zone_; |
| 2744 ZoneList<HPhi*> phis_; |
| 2745 }; |
| 2746 |
| 2747 |
| 2748 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { |
| 2749 // Operations that operatate on bits are safe. |
| 2750 if (use->IsBitwise() || |
| 2751 use->IsShl() || |
| 2752 use->IsSar() || |
| 2753 use->IsShr() || |
| 2754 use->IsBitNot()) { |
| 2755 return true; |
| 2756 } else if (use->IsChange() || use->IsSimulate()) { |
| 2757 // Conversions and deoptimization have special support for unt32. |
| 2758 return true; |
| 2759 } else if (use->IsStoreKeyedSpecializedArrayElement()) { |
| 2760 // Storing a value into an external integer array is a bit level operation. |
| 2761 HStoreKeyedSpecializedArrayElement* store = |
| 2762 HStoreKeyedSpecializedArrayElement::cast(use); |
| 2763 |
| 2764 if (store->value() == val) { |
| 2765 // Clamping or a conversion to double should have beed inserted. |
| 2766 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); |
| 2767 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); |
| 2768 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); |
| 2769 return true; |
| 2770 } |
| 2771 } |
| 2772 |
| 2773 return false; |
| 2774 } |
| 2775 |
| 2776 |
| 2777 // Iterate over all uses and verify that they are uint32 safe: either don't |
| 2778 // distinguish between int32 and uint32 due to their bitwise nature or |
| 2779 // have special support for uint32 values. |
| 2780 // Encountered phis are optimisitically treated as safe uint32 uses, |
| 2781 // marked with kUint32 flag and collected in the phis_ list. A separate |
| 2782 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from |
| 2783 // phis that are not actually uint32-safe (it requries fix point iteration). |
| 2784 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { |
| 2785 bool collect_phi_uses = false; |
| 2786 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { |
| 2787 HValue* use = it.value(); |
| 2788 |
| 2789 if (use->IsPhi()) { |
| 2790 if (!use->CheckFlag(HInstruction::kUint32)) { |
| 2791 // There is a phi use of this value from a phis that is not yet |
| 2792 // collected in phis_ array. Separate pass is required. |
| 2793 collect_phi_uses = true; |
| 2794 } |
| 2795 |
| 2796 // Optimistically treat phis as uint32 safe. |
| 2797 continue; |
| 2798 } |
| 2799 |
| 2800 if (!IsSafeUint32Use(uint32val, use)) { |
| 2801 return false; |
| 2802 } |
| 2803 } |
| 2804 |
| 2805 if (collect_phi_uses) { |
| 2806 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { |
| 2807 HValue* use = it.value(); |
| 2808 |
| 2809 // There is a phi use of this value from a phis that is not yet |
| 2810 // collected in phis_ array. Separate pass is required. |
| 2811 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) { |
| 2812 use->SetFlag(HInstruction::kUint32); |
| 2813 phis_.Add(HPhi::cast(use), zone_); |
| 2814 } |
| 2815 } |
| 2816 } |
| 2817 |
| 2818 return true; |
| 2819 } |
| 2820 |
| 2821 |
| 2822 // Analyze instruction and mark it with kUint32 if all its uses are uint32 |
| 2823 // safe. |
| 2824 void Uint32Analysis::Analyze(HInstruction* current) { |
| 2825 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32); |
| 2826 } |
| 2827 |
| 2828 |
| 2829 // Check if all operands to the given phi are marked with kUint32 flag. |
| 2830 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { |
| 2831 if (!phi->CheckFlag(HInstruction::kUint32)) { |
| 2832 // This phi is not uint32 safe. No need to check operands. |
| 2833 return false; |
| 2834 } |
| 2835 |
| 2836 for (int j = 0; j < phi->OperandCount(); j++) { |
| 2837 HValue* operand = phi->OperandAt(j); |
| 2838 if (!operand->CheckFlag(HInstruction::kUint32)) { |
| 2839 // Lazyly mark constants that fit into uint32 range with kUint32 flag. |
| 2840 if (operand->IsConstant() && |
| 2841 HConstant::cast(operand)->IsUint32()) { |
| 2842 operand->SetFlag(HInstruction::kUint32); |
| 2843 continue; |
| 2844 } |
| 2845 |
| 2846 // This phi is not safe, some operands are not uint32 values. |
| 2847 return false; |
| 2848 } |
| 2849 } |
| 2850 |
| 2851 return true; |
| 2852 } |
| 2853 |
| 2854 |
| 2855 // Remove kUint32 flag from the phi itself and its operands. If any operand |
| 2856 // was a phi marked with kUint32 place it into a worklist for |
| 2857 // transitive clearing of kUint32 flag. |
| 2858 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) { |
| 2859 phi->ClearFlag(HInstruction::kUint32); |
| 2860 for (int j = 0; j < phi->OperandCount(); j++) { |
| 2861 HValue* operand = phi->OperandAt(j); |
| 2862 if (operand->CheckFlag(HInstruction::kUint32)) { |
| 2863 operand->ClearFlag(HInstruction::kUint32); |
| 2864 if (operand->IsPhi()) { |
| 2865 worklist->Add(HPhi::cast(operand), zone_); |
| 2866 } |
| 2867 } |
| 2868 } |
| 2869 } |
| 2870 |
| 2871 |
| 2872 void Uint32Analysis::UnmarkUnsafePhis() { |
| 2873 // No phis were collected. Nothing to do. |
| 2874 if (phis_.length() == 0) return; |
| 2875 |
| 2876 // Worklist used to transitively clear kUint32 from phis that |
| 2877 // are used as arguments to other phis. |
| 2878 ZoneList<HPhi*> worklist(phis_.length(), zone_); |
| 2879 |
| 2880 // Phi can be used as a uint32 value if and only if |
| 2881 // all its operands are uint32 values and all its |
| 2882 // uses are uint32 safe. |
| 2883 |
| 2884 // Iterate over collected phis and unmark those that |
| 2885 // are unsafe. When unmarking phi unmark its operands |
| 2886 // and add it to the worklist if it is a phi as well. |
| 2887 // Phis that are still marked as safe are shifted down |
| 2888 // so that all safe phis form a prefix of the phis_ array. |
| 2889 int phi_count = 0; |
| 2890 for (int i = 0; i < phis_.length(); i++) { |
| 2891 HPhi* phi = phis_[i]; |
| 2892 |
| 2893 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { |
| 2894 phis_[phi_count++] = phi; |
| 2895 } else { |
| 2896 UnmarkPhi(phi, &worklist); |
| 2897 } |
| 2898 } |
| 2899 |
| 2900 // Now phis array contains only those phis that have safe |
| 2901 // non-phi uses. Start transitively clearing kUint32 flag |
| 2902 // from phi operands of discovered non-safe phies until |
| 2903 // only safe phies are left. |
| 2904 while (!worklist.is_empty()) { |
| 2905 while (!worklist.is_empty()) { |
| 2906 HPhi* phi = worklist.RemoveLast(); |
| 2907 UnmarkPhi(phi, &worklist); |
| 2908 } |
| 2909 |
| 2910 // Check if any operands to safe phies were unmarked |
| 2911 // turning a safe phi into unsafe. The same value |
| 2912 // can flow into several phis. |
| 2913 int new_phi_count = 0; |
| 2914 for (int i = 0; i < phi_count; i++) { |
| 2915 HPhi* phi = phis_[i]; |
| 2916 |
| 2917 if (CheckPhiOperands(phi)) { |
| 2918 phis_[new_phi_count++] = phi; |
| 2919 } else { |
| 2920 UnmarkPhi(phi, &worklist); |
| 2921 } |
| 2922 } |
| 2923 phi_count = new_phi_count; |
| 2924 } |
| 2925 } |
| 2926 |
| 2927 |
| 2928 void HGraph::ComputeSafeUint32Operations() { |
| 2929 if (!FLAG_opt_safe_uint32_operations || uint32_instructions_ == NULL) { |
| 2930 return; |
| 2931 } |
| 2932 |
| 2933 Uint32Analysis analysis(zone()); |
| 2934 for (int i = 0; i < uint32_instructions_->length(); ++i) { |
| 2935 HInstruction* current = uint32_instructions_->at(i); |
| 2936 if (current->IsLinked()) analysis.Analyze(current); |
| 2937 } |
| 2938 |
| 2939 // Some phis might have been optimistically marked with kUint32 flag. |
| 2940 // Remove this flag from those phis that are unsafe and propagate |
| 2941 // this information transitively potentially clearing kUint32 flag |
| 2942 // from some non-phi operations that are used as operands to unsafe phis. |
| 2943 analysis.UnmarkUnsafePhis(); |
| 2944 } |
| 2945 |
| 2946 |
2726 void HGraph::ComputeMinusZeroChecks() { | 2947 void HGraph::ComputeMinusZeroChecks() { |
2727 BitVector visited(GetMaximumValueID(), zone()); | 2948 BitVector visited(GetMaximumValueID(), zone()); |
2728 for (int i = 0; i < blocks_.length(); ++i) { | 2949 for (int i = 0; i < blocks_.length(); ++i) { |
2729 for (HInstruction* current = blocks_[i]->first(); | 2950 for (HInstruction* current = blocks_[i]->first(); |
2730 current != NULL; | 2951 current != NULL; |
2731 current = current->next()) { | 2952 current = current->next()) { |
2732 if (current->IsChange()) { | 2953 if (current->IsChange()) { |
2733 HChange* change = HChange::cast(current); | 2954 HChange* change = HChange::cast(current); |
2734 // Propagate flags for negative zero checks upwards from conversions | 2955 // Propagate flags for negative zero checks upwards from conversions |
2735 // int32-to-tagged and int32-to-double. | 2956 // int32-to-tagged and int32-to-double. |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3124 } | 3345 } |
3125 } | 3346 } |
3126 | 3347 |
3127 HInferRepresentation rep(this); | 3348 HInferRepresentation rep(this); |
3128 rep.Analyze(); | 3349 rep.Analyze(); |
3129 | 3350 |
3130 MarkDeoptimizeOnUndefined(); | 3351 MarkDeoptimizeOnUndefined(); |
3131 InsertRepresentationChanges(); | 3352 InsertRepresentationChanges(); |
3132 | 3353 |
3133 InitializeInferredTypes(); | 3354 InitializeInferredTypes(); |
| 3355 |
| 3356 // Must be performed before canonicalization to ensure that Canonicalize |
| 3357 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 3358 // zero. |
| 3359 ComputeSafeUint32Operations(); |
| 3360 |
3134 Canonicalize(); | 3361 Canonicalize(); |
3135 | 3362 |
3136 // Perform common subexpression elimination and loop-invariant code motion. | 3363 // Perform common subexpression elimination and loop-invariant code motion. |
3137 if (FLAG_use_gvn) { | 3364 if (FLAG_use_gvn) { |
3138 HPhase phase("H_Global value numbering", this); | 3365 HPhase phase("H_Global value numbering", this); |
3139 HGlobalValueNumberer gvn(this, info()); | 3366 HGlobalValueNumberer gvn(this, info()); |
3140 bool removed_side_effects = gvn.Analyze(); | 3367 bool removed_side_effects = gvn.Analyze(); |
3141 // Trigger a second analysis pass to further eliminate duplicate values that | 3368 // Trigger a second analysis pass to further eliminate duplicate values that |
3142 // could only be discovered by removing side-effect-generating instructions | 3369 // could only be discovered by removing side-effect-generating instructions |
3143 // during the first pass. | 3370 // during the first pass. |
(...skipping 2673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5817 case FAST_HOLEY_DOUBLE_ELEMENTS: | 6044 case FAST_HOLEY_DOUBLE_ELEMENTS: |
5818 case DICTIONARY_ELEMENTS: | 6045 case DICTIONARY_ELEMENTS: |
5819 case NON_STRICT_ARGUMENTS_ELEMENTS: | 6046 case NON_STRICT_ARGUMENTS_ELEMENTS: |
5820 UNREACHABLE(); | 6047 UNREACHABLE(); |
5821 break; | 6048 break; |
5822 } | 6049 } |
5823 return new(zone()) HStoreKeyedSpecializedArrayElement( | 6050 return new(zone()) HStoreKeyedSpecializedArrayElement( |
5824 external_elements, checked_key, val, elements_kind); | 6051 external_elements, checked_key, val, elements_kind); |
5825 } else { | 6052 } else { |
5826 ASSERT(val == NULL); | 6053 ASSERT(val == NULL); |
5827 return new(zone()) HLoadKeyedSpecializedArrayElement( | 6054 HLoadKeyedSpecializedArrayElement* load = |
5828 external_elements, checked_key, dependency, elements_kind); | 6055 new(zone()) HLoadKeyedSpecializedArrayElement( |
| 6056 external_elements, checked_key, dependency, elements_kind); |
| 6057 if (FLAG_opt_safe_uint32_operations && |
| 6058 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 6059 graph()->RecordUint32Instruction(load); |
| 6060 } |
| 6061 return load; |
5829 } | 6062 } |
5830 } | 6063 } |
5831 | 6064 |
5832 | 6065 |
5833 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, | 6066 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, |
5834 HValue* checked_key, | 6067 HValue* checked_key, |
5835 HValue* val, | 6068 HValue* val, |
5836 HValue* load_dependency, | 6069 HValue* load_dependency, |
5837 ElementsKind elements_kind, | 6070 ElementsKind elements_kind, |
5838 bool is_store) { | 6071 bool is_store) { |
(...skipping 2164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8003 case Token::BIT_XOR: | 8236 case Token::BIT_XOR: |
8004 case Token::BIT_AND: | 8237 case Token::BIT_AND: |
8005 case Token::BIT_OR: | 8238 case Token::BIT_OR: |
8006 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); | 8239 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
8007 break; | 8240 break; |
8008 case Token::SAR: | 8241 case Token::SAR: |
8009 instr = HSar::NewHSar(zone(), context, left, right); | 8242 instr = HSar::NewHSar(zone(), context, left, right); |
8010 break; | 8243 break; |
8011 case Token::SHR: | 8244 case Token::SHR: |
8012 instr = HShr::NewHShr(zone(), context, left, right); | 8245 instr = HShr::NewHShr(zone(), context, left, right); |
| 8246 if (FLAG_opt_safe_uint32_operations && instr->IsShr()) { |
| 8247 graph()->RecordUint32Instruction(instr); |
| 8248 } |
8013 break; | 8249 break; |
8014 case Token::SHL: | 8250 case Token::SHL: |
8015 instr = HShl::NewHShl(zone(), context, left, right); | 8251 instr = HShl::NewHShl(zone(), context, left, right); |
8016 break; | 8252 break; |
8017 default: | 8253 default: |
8018 UNREACHABLE(); | 8254 UNREACHABLE(); |
8019 } | 8255 } |
8020 | 8256 |
8021 // If we hit an uninitialized binary op stub we will get type info | 8257 // If we hit an uninitialized binary op stub we will get type info |
8022 // for a smi operation. If one of the operands is a constant string | 8258 // for a smi operation. If one of the operands is a constant string |
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9673 } | 9909 } |
9674 } | 9910 } |
9675 | 9911 |
9676 #ifdef DEBUG | 9912 #ifdef DEBUG |
9677 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9913 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9678 if (allocator_ != NULL) allocator_->Verify(); | 9914 if (allocator_ != NULL) allocator_->Verify(); |
9679 #endif | 9915 #endif |
9680 } | 9916 } |
9681 | 9917 |
9682 } } // namespace v8::internal | 9918 } } // namespace v8::internal |
OLD | NEW |