Chromium Code Reviews| Index: src/hydrogen-instructions.cc |
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc |
| index b8fb1757a5fa0edb9b9fec3f6acdb1c261d85724..4404a5a22c10ea67ff807e484839078d7b5b21f3 100644 |
| --- a/src/hydrogen-instructions.cc |
| +++ b/src/hydrogen-instructions.cc |
| @@ -254,34 +254,56 @@ HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { |
| } |
| -static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { |
| - if (result > kMaxInt) { |
| - *overflow = true; |
| - return kMaxInt; |
| - } |
| - if (result < kMinInt) { |
| - *overflow = true; |
| - return kMinInt; |
| +static int32_t ConvertAndSetOverflow(Representation r, |
| + int64_t result, |
| + bool* overflow) { |
| + if (r.IsSmi()) { |
| + if (result > Smi::kMaxValue) { |
| + *overflow = true; |
| + return Smi::kMaxValue; |
| + } |
| + if (result < Smi::kMinValue) { |
| + *overflow = true; |
| + return Smi::kMinValue; |
| + } |
| + } else { |
| + if (result > kMaxInt) { |
| + *overflow = true; |
| + return kMaxInt; |
| + } |
| + if (result < kMinInt) { |
| + *overflow = true; |
| + return kMinInt; |
| + } |
| } |
| return static_cast<int32_t>(result); |
| } |
| -static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) { |
| +static int32_t AddWithoutOverflow(Representation r, |
| + int32_t a, |
| + int32_t b, |
| + bool* overflow) { |
| int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b); |
| - return ConvertAndSetOverflow(result, overflow); |
| + return ConvertAndSetOverflow(r, result, overflow); |
| } |
| -static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) { |
| +static int32_t SubWithoutOverflow(Representation r, |
| + int32_t a, |
| + int32_t b, |
| + bool* overflow) { |
| int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b); |
| - return ConvertAndSetOverflow(result, overflow); |
| + return ConvertAndSetOverflow(r, result, overflow); |
| } |
| -static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) { |
| +static int32_t MulWithoutOverflow(Representation r, |
| + int32_t a, |
| + int32_t b, |
| + bool* overflow) { |
| int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b); |
| - return ConvertAndSetOverflow(result, overflow); |
| + return ConvertAndSetOverflow(r, result, overflow); |
| } |
| @@ -301,8 +323,9 @@ int32_t Range::Mask() const { |
| void Range::AddConstant(int32_t value) { |
| if (value == 0) return; |
| bool may_overflow = false; // Overflow is ignored here. |
| - lower_ = AddWithoutOverflow(lower_, value, &may_overflow); |
| - upper_ = AddWithoutOverflow(upper_, value, &may_overflow); |
| + Representation r = Representation::Integer32(); |
| + lower_ = AddWithoutOverflow(r, lower_, value, &may_overflow); |
| + upper_ = AddWithoutOverflow(r, upper_, value, &may_overflow); |
| #ifdef DEBUG |
| Verify(); |
| #endif |
| @@ -361,10 +384,10 @@ void Range::Shl(int32_t value) { |
| } |
| -bool Range::AddAndCheckOverflow(Range* other) { |
| +bool Range::AddAndCheckOverflow(const Representation& r, Range* other) { |
| bool may_overflow = false; |
| - lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow); |
| - upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow); |
| + lower_ = AddWithoutOverflow(r, lower_, other->lower(), &may_overflow); |
| + upper_ = AddWithoutOverflow(r, upper_, other->upper(), &may_overflow); |
| KeepOrder(); |
| #ifdef DEBUG |
| Verify(); |
| @@ -373,10 +396,10 @@ bool Range::AddAndCheckOverflow(Range* other) { |
| } |
| -bool Range::SubAndCheckOverflow(Range* other) { |
| +bool Range::SubAndCheckOverflow(const Representation& r, Range* other) { |
| bool may_overflow = false; |
| - lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow); |
| - upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow); |
| + lower_ = SubWithoutOverflow(r, lower_, other->upper(), &may_overflow); |
| + upper_ = SubWithoutOverflow(r, upper_, other->lower(), &may_overflow); |
| KeepOrder(); |
| #ifdef DEBUG |
| Verify(); |
| @@ -401,12 +424,12 @@ void Range::Verify() const { |
| #endif |
| -bool Range::MulAndCheckOverflow(Range* other) { |
| +bool Range::MulAndCheckOverflow(const Representation& r, Range* other) { |
| bool may_overflow = false; |
| - int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow); |
| - int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow); |
| - int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow); |
| - int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow); |
| + int v1 = MulWithoutOverflow(r, lower_, other->lower(), &may_overflow); |
| + int v2 = MulWithoutOverflow(r, lower_, other->upper(), &may_overflow); |
| + int v3 = MulWithoutOverflow(r, upper_, other->lower(), &may_overflow); |
| + int v4 = MulWithoutOverflow(r, upper_, other->upper(), &may_overflow); |
| lower_ = Min(Min(v1, v2), Min(v3, v4)); |
| upper_ = Max(Max(v1, v2), Max(v3, v4)); |
| #ifdef DEBUG |
| @@ -1371,7 +1394,7 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) { |
| HValue* HBitwise::Canonicalize() { |
| - if (!representation().IsInteger32()) return this; |
| + if (!representation().IsSmiOrInteger32()) return this; |
| // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x. |
| int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0; |
| if (left()->EqualsInteger32Constant(nop_constant) && |
| @@ -1480,10 +1503,10 @@ void HChange::PrintDataTo(StringStream* stream) { |
| HValue* HUnaryMathOperation::Canonicalize() { |
| if (op() == kMathFloor) { |
| - // If the input is integer32 then we replace the floor instruction |
| + // If the input is smi or integer32 then we replace the floor instruction |
| // with its input. This happens before the representation changes are |
| // introduced. |
| - if (value()->representation().IsInteger32()) return value(); |
| + if (value()->representation().IsSmiOrInteger32()) return value(); |
| #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \ |
| defined(V8_TARGET_ARCH_X64) |
| @@ -1661,7 +1684,7 @@ void HInstanceOf::PrintDataTo(StringStream* stream) { |
| Range* HValue::InferRange(Zone* zone) { |
| Range* result; |
| - if (type().IsSmi()) { |
| + if (representation().IsSmi() || type().IsSmi()) { |
| result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue); |
| result->set_can_be_minus_zero(false); |
| } else { |
| @@ -1685,7 +1708,7 @@ Range* HChange::InferRange(Zone* zone) { |
| Range* result = (input_range != NULL) |
| ? input_range->Copy(zone) |
| : HValue::InferRange(zone); |
| - if (to().IsInteger32()) result->set_can_be_minus_zero(false); |
| + if (to().IsSmiOrInteger32()) result->set_can_be_minus_zero(false); |
| return result; |
| } |
| @@ -1701,9 +1724,12 @@ Range* HConstant::InferRange(Zone* zone) { |
| Range* HPhi::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| if (block()->IsLoopHeader()) { |
| - Range* range = new(zone) Range(kMinInt, kMaxInt); |
| + Range* range = r.IsSmi() |
| + ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) |
| + : new(zone) Range(kMinInt, kMaxInt); |
| return range; |
| } else { |
| Range* range = OperandAt(0)->range()->Copy(zone); |
| @@ -1719,11 +1745,12 @@ Range* HPhi::InferRange(Zone* zone) { |
| Range* HAdd::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| Range* res = a->Copy(zone); |
| - if (!res->AddAndCheckOverflow(b)) { |
| + if (!res->AddAndCheckOverflow(r, b)) { |
| ClearFlag(kCanOverflow); |
| } |
| bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero(); |
| @@ -1736,11 +1763,12 @@ Range* HAdd::InferRange(Zone* zone) { |
| Range* HSub::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| Range* res = a->Copy(zone); |
| - if (!res->SubAndCheckOverflow(b)) { |
| + if (!res->SubAndCheckOverflow(r, b)) { |
| ClearFlag(kCanOverflow); |
| } |
| res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero()); |
| @@ -1752,11 +1780,12 @@ Range* HSub::InferRange(Zone* zone) { |
| Range* HMul::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| Range* res = a->Copy(zone); |
| - if (!res->MulAndCheckOverflow(b)) { |
| + if (!res->MulAndCheckOverflow(r, b)) { |
| ClearFlag(kCanOverflow); |
| } |
| bool m0 = (a->CanBeZero() && b->CanBeNegative()) || |
| @@ -1770,7 +1799,8 @@ Range* HMul::InferRange(Zone* zone) { |
| Range* HDiv::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| Range* result = new(zone) Range(); |
| @@ -1782,7 +1812,9 @@ Range* HDiv::InferRange(Zone* zone) { |
| result->set_can_be_minus_zero(true); |
| } |
| - if (!a->Includes(kMinInt) || !b->Includes(-1)) { |
| + if (!b->Includes(-1) || |
| + (r.IsSmi() && !a->Includes(Smi::kMinValue)) || |
| + (r.IsInteger32() && !a->Includes(kMinInt))) { |
| ClearFlag(HValue::kCanOverflow); |
| } |
| @@ -1797,7 +1829,8 @@ Range* HDiv::InferRange(Zone* zone) { |
| Range* HMod::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + Representation r = representation(); |
| + if (r.IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| @@ -1815,7 +1848,9 @@ Range* HMod::InferRange(Zone* zone) { |
| result->set_can_be_minus_zero(true); |
| } |
| - if (!a->Includes(kMinInt) || !b->Includes(-1)) { |
| + if (!b->Includes(-1) || |
| + (r.IsSmi() && !a->Includes(Smi::kMinValue)) || |
|
Sven Panne
2013/06/04 09:53:56
* Re-order back to a, then b test.
* Introduce 'mi
Sven Panne
2013/06/04 10:01:07
Thinking about it: We have to avoid an idiv of 0x8
Toon Verwaest
2013/06/04 15:06:40
You are right. I actually (temporarily) backed out
|
| + (r.IsInteger32() && !a->Includes(kMinInt))) { |
| ClearFlag(HValue::kCanOverflow); |
| } |
| @@ -1884,7 +1919,7 @@ bool HPhi::IsRelationTrueInternal(NumericRelation relation, |
| Range* HMathMinMax::InferRange(Zone* zone) { |
| - if (representation().IsInteger32()) { |
| + if (representation().IsSmiOrInteger32()) { |
| Range* a = left()->range(); |
| Range* b = right()->range(); |
| Range* res = a->Copy(zone); |
| @@ -2174,7 +2209,7 @@ void HConstant::Initialize(Representation r) { |
| } |
| set_representation(r); |
| SetFlag(kUseGVN); |
| - if (representation().IsInteger32()) { |
| + if (representation().IsSmiOrInteger32()) { |
| ClearGVNFlag(kDependsOnOsrEntries); |
| } |
| } |
| @@ -2269,8 +2304,7 @@ Representation HBinaryOperation::RepresentationFromInputs() { |
| // the currently assumed output representation. |
| Representation rep = representation(); |
| for (int i = 1; i <= 2; ++i) { |
| - Representation input_rep = observed_input_representation(i); |
| - if (input_rep.is_more_general_than(rep)) rep = input_rep; |
| + rep = rep.generalize(observed_input_representation(i)); |
| } |
| // If any of the actual input representation is more general than what we |
| // have so far but not Tagged, use that representation instead. |
| @@ -2456,8 +2490,8 @@ void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) { |
| Representation observed_left = observed_input_representation(0); |
| Representation observed_right = observed_input_representation(1); |
| - Representation rep = Representation::Smi(); |
| - if (observed_left.IsInteger32() && observed_right.IsInteger32()) { |
| + Representation rep = observed_left.generalize(observed_right); |
| + if (rep.IsNone() || rep.IsSmiOrInteger32()) { |
| if (!left_rep.IsTagged()) rep = rep.generalize(left_rep); |
| if (!right_rep.IsTagged()) rep = rep.generalize(right_rep); |
| } else { |
| @@ -3053,14 +3087,14 @@ HType HFunctionLiteral::CalculateInferredType() { |
| HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero( |
| BitVector* visited) { |
| visited->Add(id()); |
| - if (representation().IsInteger32() && |
| - !value()->representation().IsInteger32()) { |
| + if (representation().IsSmiOrInteger32() && |
| + !value()->representation().Equals(representation())) { |
| if (value()->range() == NULL || value()->range()->CanBeMinusZero()) { |
| SetFlag(kBailoutOnMinusZero); |
| } |
| } |
| - if (RequiredInputRepresentation(0).IsInteger32() && |
| - representation().IsInteger32()) { |
| + if (RequiredInputRepresentation(0).IsSmiOrInteger32() && |
| + representation().Equals(RequiredInputRepresentation(0))) { |
| return value(); |
| } |
| return NULL; |
| @@ -3070,12 +3104,12 @@ HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero( |
| HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) { |
| visited->Add(id()); |
| - if (from().IsInteger32()) return NULL; |
| + if (from().IsSmiOrInteger32()) return NULL; |
| if (CanTruncateToInt32()) return NULL; |
| if (value()->range() == NULL || value()->range()->CanBeMinusZero()) { |
| SetFlag(kBailoutOnMinusZero); |
| } |
| - ASSERT(!from().IsInteger32() || !to().IsInteger32()); |
| + ASSERT(!from().IsSmiOrInteger32() || !to().IsSmiOrInteger32()); |
| return NULL; |
| } |
| @@ -3162,7 +3196,7 @@ bool HStoreKeyed::NeedsCanonicalization() { |
| } |
| if (value()->IsChange()) { |
| - if (HChange::cast(value())->from().IsInteger32()) { |
| + if (HChange::cast(value())->from().IsSmiOrInteger32()) { |
| return false; |
| } |
| if (HChange::cast(value())->value()->type().IsSmi()) { |
| @@ -3538,7 +3572,7 @@ void HPhi::SimplifyConstantInputs() { |
| HValue* use = it.value(); |
| if (use->IsBinaryOperation()) { |
| HBinaryOperation::cast(use)->set_observed_input_representation( |
| - it.index(), Representation::Integer32()); |
| + it.index(), Representation::Smi()); |
| } |
| } |
| } |