diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 0fe4a0ed20..82fdfa70a2 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -555,6 +555,8 @@ class HValue: public ZoneObject { representation_ = r; } + virtual bool IsConvertibleToInteger() const { return true; } + HType type() const { return type_; } void set_type(HType type) { ASSERT(HasNoUses()); @@ -1923,7 +1925,8 @@ class HPhi: public HValue { : inputs_(2), merged_index_(merged_index), phi_id_(-1), - is_live_(false) { + is_live_(false), + is_convertible_to_integer_(true) { for (int i = 0; i < Representation::kNumRepresentations; i++) { non_phi_uses_[i] = 0; indirect_uses_[i] = 0; @@ -2001,6 +2004,14 @@ class HPhi: public HValue { } virtual Opcode opcode() const { return HValue::kPhi; } + virtual bool IsConvertibleToInteger() const { + return is_convertible_to_integer_; + } + + void set_is_convertible_to_integer(bool b) { + is_convertible_to_integer_ = b; + } + protected: virtual void DeleteFromGraph(); virtual void InternalSetOperandAt(int index, HValue* value) { @@ -2015,6 +2026,7 @@ class HPhi: public HValue { int indirect_uses_[Representation::kNumRepresentations]; int phi_id_; bool is_live_; + bool is_convertible_to_integer_; }; @@ -2045,6 +2057,14 @@ class HConstant: public HTemplateInstruction<0> { return Representation::None(); } + virtual bool IsConvertibleToInteger() const { + if (handle_->IsSmi()) return true; + if (handle_->IsHeapNumber() && + (HeapNumber::cast(*handle_)->value() == + static_cast(NumberToInt32(*handle_)))) return true; + return false; + } + virtual bool EmitAtUses() { return !representation().IsDouble(); } virtual void PrintDataTo(StringStream* stream); virtual HType CalculateInferredType(); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 4de8305a24..3b57f9fafa 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1574,14 +1574,12 @@ Representation HInferRepresentation::TryChange(HValue* value) { } if (non_tagged_count >= tagged_count) { - // More untagged than tagged. - if (double_count > 0) { - // There is at least one usage that is a double => guess that the - // correct representation is double. - return Representation::Double(); - } else if (int32_count > 0) { - return Representation::Integer32(); + if (int32_count > 0) { + if (!value->IsPhi() || value->IsConvertibleToInteger()) { + return Representation::Integer32(); + } } + if (double_count > 0) return Representation::Double(); } return Representation::None(); } @@ -1594,11 +1592,12 @@ void HInferRepresentation::Analyze() { // bit-vector of length . const ZoneList* phi_list = graph_->phi_list(); int phi_count = phi_list->length(); - ScopedVector connected_phis(phi_count); + ZoneList connected_phis(phi_count); for (int i = 0; i < phi_count; ++i) { phi_list->at(i)->InitRealUses(i); - connected_phis[i] = new(zone()) BitVector(phi_count); - connected_phis[i]->Add(i); + BitVector* connected_set = new(zone()) BitVector(phi_count); + connected_set->Add(i); + connected_phis.Add(connected_set); } // (2) Do a fixed point iteration to find the set of connected phis. A @@ -1635,6 +1634,25 @@ void HInferRepresentation::Analyze() { } } + // (4) Compute phis that definitely can't be converted to integer + // without deoptimization and mark them to avoid unnecessary deoptimization. + change = true; + while (change) { + change = false; + for (int i = 0; i < phi_count; ++i) { + HPhi* phi = phi_list->at(i); + for (int j = 0; j < phi->OperandCount(); ++j) { + if (phi->IsConvertibleToInteger() && + !phi->OperandAt(j)->IsConvertibleToInteger()) { + phi->set_is_convertible_to_integer(false); + change = true; + break; + } + } + } + } + + for (int i = 0; i < graph_->blocks()->length(); ++i) { HBasicBlock* block = graph_->blocks()->at(i); const ZoneList* phis = block->phis();