| 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 19 matching lines...) Expand all Loading... |
| 30 #include <algorithm> | 30 #include <algorithm> |
| 31 | 31 |
| 32 #include "v8.h" | 32 #include "v8.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
| 35 #include "hashmap.h" | 35 #include "hashmap.h" |
| 36 #include "hydrogen-environment-liveness.h" | 36 #include "hydrogen-environment-liveness.h" |
| 37 #include "hydrogen-escape-analysis.h" | 37 #include "hydrogen-escape-analysis.h" |
| 38 #include "hydrogen-infer-representation.h" | 38 #include "hydrogen-infer-representation.h" |
| 39 #include "hydrogen-gvn.h" | 39 #include "hydrogen-gvn.h" |
| 40 #include "hydrogen-uint32-analysis.h" |
| 40 #include "lithium-allocator.h" | 41 #include "lithium-allocator.h" |
| 41 #include "parser.h" | 42 #include "parser.h" |
| 42 #include "scopeinfo.h" | 43 #include "scopeinfo.h" |
| 43 #include "scopes.h" | 44 #include "scopes.h" |
| 44 #include "stub-cache.h" | 45 #include "stub-cache.h" |
| 45 #include "typing.h" | 46 #include "typing.h" |
| 46 | 47 |
| 47 #if V8_TARGET_ARCH_IA32 | 48 #if V8_TARGET_ARCH_IA32 |
| 48 #include "ia32/lithium-codegen-ia32.h" | 49 #include "ia32/lithium-codegen-ia32.h" |
| 49 #elif V8_TARGET_ARCH_X64 | 50 #elif V8_TARGET_ARCH_X64 |
| (...skipping 3021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3071 HValue* use_value = it.value(); | 3072 HValue* use_value = it.value(); |
| 3072 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { | 3073 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { |
| 3073 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | 3074 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
| 3074 break; | 3075 break; |
| 3075 } | 3076 } |
| 3076 } | 3077 } |
| 3077 } | 3078 } |
| 3078 } | 3079 } |
| 3079 | 3080 |
| 3080 | 3081 |
| 3081 // Discover instructions that can be marked with kUint32 flag allowing | |
| 3082 // them to produce full range uint32 values. | |
| 3083 class Uint32Analysis BASE_EMBEDDED { | |
| 3084 public: | |
| 3085 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { } | |
| 3086 | |
| 3087 void Analyze(HInstruction* current); | |
| 3088 | |
| 3089 void UnmarkUnsafePhis(); | |
| 3090 | |
| 3091 private: | |
| 3092 bool IsSafeUint32Use(HValue* val, HValue* use); | |
| 3093 bool Uint32UsesAreSafe(HValue* uint32val); | |
| 3094 bool CheckPhiOperands(HPhi* phi); | |
| 3095 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); | |
| 3096 | |
| 3097 Zone* zone_; | |
| 3098 ZoneList<HPhi*> phis_; | |
| 3099 }; | |
| 3100 | |
| 3101 | |
| 3102 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { | |
| 3103 // Operations that operatate on bits are safe. | |
| 3104 if (use->IsBitwise() || | |
| 3105 use->IsShl() || | |
| 3106 use->IsSar() || | |
| 3107 use->IsShr() || | |
| 3108 use->IsBitNot()) { | |
| 3109 return true; | |
| 3110 } else if (use->IsChange() || use->IsSimulate()) { | |
| 3111 // Conversions and deoptimization have special support for unt32. | |
| 3112 return true; | |
| 3113 } else if (use->IsStoreKeyed()) { | |
| 3114 HStoreKeyed* store = HStoreKeyed::cast(use); | |
| 3115 if (store->is_external()) { | |
| 3116 // Storing a value into an external integer array is a bit level | |
| 3117 // operation. | |
| 3118 if (store->value() == val) { | |
| 3119 // Clamping or a conversion to double should have beed inserted. | |
| 3120 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); | |
| 3121 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); | |
| 3122 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); | |
| 3123 return true; | |
| 3124 } | |
| 3125 } | |
| 3126 } | |
| 3127 | |
| 3128 return false; | |
| 3129 } | |
| 3130 | |
| 3131 | |
| 3132 // Iterate over all uses and verify that they are uint32 safe: either don't | |
| 3133 // distinguish between int32 and uint32 due to their bitwise nature or | |
| 3134 // have special support for uint32 values. | |
| 3135 // Encountered phis are optimisitically treated as safe uint32 uses, | |
| 3136 // marked with kUint32 flag and collected in the phis_ list. A separate | |
| 3137 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from | |
| 3138 // phis that are not actually uint32-safe (it requries fix point iteration). | |
| 3139 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { | |
| 3140 bool collect_phi_uses = false; | |
| 3141 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
| 3142 HValue* use = it.value(); | |
| 3143 | |
| 3144 if (use->IsPhi()) { | |
| 3145 if (!use->CheckFlag(HInstruction::kUint32)) { | |
| 3146 // There is a phi use of this value from a phis that is not yet | |
| 3147 // collected in phis_ array. Separate pass is required. | |
| 3148 collect_phi_uses = true; | |
| 3149 } | |
| 3150 | |
| 3151 // Optimistically treat phis as uint32 safe. | |
| 3152 continue; | |
| 3153 } | |
| 3154 | |
| 3155 if (!IsSafeUint32Use(uint32val, use)) { | |
| 3156 return false; | |
| 3157 } | |
| 3158 } | |
| 3159 | |
| 3160 if (collect_phi_uses) { | |
| 3161 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
| 3162 HValue* use = it.value(); | |
| 3163 | |
| 3164 // There is a phi use of this value from a phis that is not yet | |
| 3165 // collected in phis_ array. Separate pass is required. | |
| 3166 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) { | |
| 3167 use->SetFlag(HInstruction::kUint32); | |
| 3168 phis_.Add(HPhi::cast(use), zone_); | |
| 3169 } | |
| 3170 } | |
| 3171 } | |
| 3172 | |
| 3173 return true; | |
| 3174 } | |
| 3175 | |
| 3176 | |
| 3177 // Analyze instruction and mark it with kUint32 if all its uses are uint32 | |
| 3178 // safe. | |
| 3179 void Uint32Analysis::Analyze(HInstruction* current) { | |
| 3180 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32); | |
| 3181 } | |
| 3182 | |
| 3183 | |
| 3184 // Check if all operands to the given phi are marked with kUint32 flag. | |
| 3185 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { | |
| 3186 if (!phi->CheckFlag(HInstruction::kUint32)) { | |
| 3187 // This phi is not uint32 safe. No need to check operands. | |
| 3188 return false; | |
| 3189 } | |
| 3190 | |
| 3191 for (int j = 0; j < phi->OperandCount(); j++) { | |
| 3192 HValue* operand = phi->OperandAt(j); | |
| 3193 if (!operand->CheckFlag(HInstruction::kUint32)) { | |
| 3194 // Lazyly mark constants that fit into uint32 range with kUint32 flag. | |
| 3195 if (operand->IsInteger32Constant() && | |
| 3196 operand->GetInteger32Constant() >= 0) { | |
| 3197 operand->SetFlag(HInstruction::kUint32); | |
| 3198 continue; | |
| 3199 } | |
| 3200 | |
| 3201 // This phi is not safe, some operands are not uint32 values. | |
| 3202 return false; | |
| 3203 } | |
| 3204 } | |
| 3205 | |
| 3206 return true; | |
| 3207 } | |
| 3208 | |
| 3209 | |
| 3210 // Remove kUint32 flag from the phi itself and its operands. If any operand | |
| 3211 // was a phi marked with kUint32 place it into a worklist for | |
| 3212 // transitive clearing of kUint32 flag. | |
| 3213 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) { | |
| 3214 phi->ClearFlag(HInstruction::kUint32); | |
| 3215 for (int j = 0; j < phi->OperandCount(); j++) { | |
| 3216 HValue* operand = phi->OperandAt(j); | |
| 3217 if (operand->CheckFlag(HInstruction::kUint32)) { | |
| 3218 operand->ClearFlag(HInstruction::kUint32); | |
| 3219 if (operand->IsPhi()) { | |
| 3220 worklist->Add(HPhi::cast(operand), zone_); | |
| 3221 } | |
| 3222 } | |
| 3223 } | |
| 3224 } | |
| 3225 | |
| 3226 | |
| 3227 void Uint32Analysis::UnmarkUnsafePhis() { | |
| 3228 // No phis were collected. Nothing to do. | |
| 3229 if (phis_.length() == 0) return; | |
| 3230 | |
| 3231 // Worklist used to transitively clear kUint32 from phis that | |
| 3232 // are used as arguments to other phis. | |
| 3233 ZoneList<HPhi*> worklist(phis_.length(), zone_); | |
| 3234 | |
| 3235 // Phi can be used as a uint32 value if and only if | |
| 3236 // all its operands are uint32 values and all its | |
| 3237 // uses are uint32 safe. | |
| 3238 | |
| 3239 // Iterate over collected phis and unmark those that | |
| 3240 // are unsafe. When unmarking phi unmark its operands | |
| 3241 // and add it to the worklist if it is a phi as well. | |
| 3242 // Phis that are still marked as safe are shifted down | |
| 3243 // so that all safe phis form a prefix of the phis_ array. | |
| 3244 int phi_count = 0; | |
| 3245 for (int i = 0; i < phis_.length(); i++) { | |
| 3246 HPhi* phi = phis_[i]; | |
| 3247 | |
| 3248 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { | |
| 3249 phis_[phi_count++] = phi; | |
| 3250 } else { | |
| 3251 UnmarkPhi(phi, &worklist); | |
| 3252 } | |
| 3253 } | |
| 3254 | |
| 3255 // Now phis array contains only those phis that have safe | |
| 3256 // non-phi uses. Start transitively clearing kUint32 flag | |
| 3257 // from phi operands of discovered non-safe phies until | |
| 3258 // only safe phies are left. | |
| 3259 while (!worklist.is_empty()) { | |
| 3260 while (!worklist.is_empty()) { | |
| 3261 HPhi* phi = worklist.RemoveLast(); | |
| 3262 UnmarkPhi(phi, &worklist); | |
| 3263 } | |
| 3264 | |
| 3265 // Check if any operands to safe phies were unmarked | |
| 3266 // turning a safe phi into unsafe. The same value | |
| 3267 // can flow into several phis. | |
| 3268 int new_phi_count = 0; | |
| 3269 for (int i = 0; i < phi_count; i++) { | |
| 3270 HPhi* phi = phis_[i]; | |
| 3271 | |
| 3272 if (CheckPhiOperands(phi)) { | |
| 3273 phis_[new_phi_count++] = phi; | |
| 3274 } else { | |
| 3275 UnmarkPhi(phi, &worklist); | |
| 3276 } | |
| 3277 } | |
| 3278 phi_count = new_phi_count; | |
| 3279 } | |
| 3280 } | |
| 3281 | |
| 3282 | |
| 3283 void HGraph::ComputeSafeUint32Operations() { | |
| 3284 HPhase phase("H_Compute safe UInt32 operations", this); | |
| 3285 if (uint32_instructions_ == NULL) return; | |
| 3286 | |
| 3287 Uint32Analysis analysis(zone()); | |
| 3288 for (int i = 0; i < uint32_instructions_->length(); ++i) { | |
| 3289 HInstruction* current = uint32_instructions_->at(i); | |
| 3290 if (current->IsLinked() && current->representation().IsInteger32()) { | |
| 3291 analysis.Analyze(current); | |
| 3292 } | |
| 3293 } | |
| 3294 | |
| 3295 // Some phis might have been optimistically marked with kUint32 flag. | |
| 3296 // Remove this flag from those phis that are unsafe and propagate | |
| 3297 // this information transitively potentially clearing kUint32 flag | |
| 3298 // from some non-phi operations that are used as operands to unsafe phis. | |
| 3299 analysis.UnmarkUnsafePhis(); | |
| 3300 } | |
| 3301 | |
| 3302 | |
| 3303 void HGraph::ComputeMinusZeroChecks() { | 3082 void HGraph::ComputeMinusZeroChecks() { |
| 3304 HPhase phase("H_Compute minus zero checks", this); | 3083 HPhase phase("H_Compute minus zero checks", this); |
| 3305 BitVector visited(GetMaximumValueID(), zone()); | 3084 BitVector visited(GetMaximumValueID(), zone()); |
| 3306 for (int i = 0; i < blocks_.length(); ++i) { | 3085 for (int i = 0; i < blocks_.length(); ++i) { |
| 3307 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) { | 3086 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) { |
| 3308 HInstruction* current = it.Current(); | 3087 HInstruction* current = it.Current(); |
| 3309 if (current->IsChange()) { | 3088 if (current->IsChange()) { |
| 3310 HChange* change = HChange::cast(current); | 3089 HChange* change = HChange::cast(current); |
| 3311 // Propagate flags for negative zero checks upwards from conversions | 3090 // Propagate flags for negative zero checks upwards from conversions |
| 3312 // int32-to-tagged and int32-to-double. | 3091 // int32-to-tagged and int32-to-double. |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3804 MergeRemovableSimulates(); | 3583 MergeRemovableSimulates(); |
| 3805 | 3584 |
| 3806 MarkDeoptimizeOnUndefined(); | 3585 MarkDeoptimizeOnUndefined(); |
| 3807 InsertRepresentationChanges(); | 3586 InsertRepresentationChanges(); |
| 3808 | 3587 |
| 3809 InitializeInferredTypes(); | 3588 InitializeInferredTypes(); |
| 3810 | 3589 |
| 3811 // Must be performed before canonicalization to ensure that Canonicalize | 3590 // Must be performed before canonicalization to ensure that Canonicalize |
| 3812 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 3591 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 3813 // zero. | 3592 // zero. |
| 3814 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); | 3593 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
| 3815 | 3594 |
| 3816 if (FLAG_use_canonicalizing) Canonicalize(); | 3595 if (FLAG_use_canonicalizing) Canonicalize(); |
| 3817 | 3596 |
| 3818 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); | 3597 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
| 3819 | 3598 |
| 3820 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3599 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 3821 | 3600 |
| 3822 if (FLAG_use_range) { | 3601 if (FLAG_use_range) { |
| 3823 HRangeAnalysis range_analysis(this); | 3602 HRangeAnalysis range_analysis(this); |
| 3824 range_analysis.Analyze(); | 3603 range_analysis.Analyze(); |
| (...skipping 7416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11241 if (ShouldProduceTraceOutput()) { | 11020 if (ShouldProduceTraceOutput()) { |
| 11242 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11021 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11243 } | 11022 } |
| 11244 | 11023 |
| 11245 #ifdef DEBUG | 11024 #ifdef DEBUG |
| 11246 graph_->Verify(false); // No full verify. | 11025 graph_->Verify(false); // No full verify. |
| 11247 #endif | 11026 #endif |
| 11248 } | 11027 } |
| 11249 | 11028 |
| 11250 } } // namespace v8::internal | 11029 } } // namespace v8::internal |
| OLD | NEW |