| Index: src/hydrogen-instructions.cc
|
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
|
| index 927e1866760ce31b26c452827c70bc1b01261b09..1dadb70afb509f5c14a5d549fd14184bd304bc2f 100644
|
| --- a/src/hydrogen-instructions.cc
|
| +++ b/src/hydrogen-instructions.cc
|
| @@ -1239,6 +1239,16 @@ HValue* HMul::Canonicalize() {
|
| }
|
|
|
|
|
| +bool HMul::MulMinusOne() {
|
| + if (left()->EqualsInteger32Constant(-1) ||
|
| + right()->EqualsInteger32Constant(-1)) {
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| HValue* HMod::Canonicalize() {
|
| return this;
|
| }
|
| @@ -1624,10 +1634,13 @@ Range* HMul::InferRange(Zone* zone) {
|
| Range* a = left()->range();
|
| Range* b = right()->range();
|
| Range* res = a->Copy(zone);
|
| - if (!res->MulAndCheckOverflow(r, b)) {
|
| - // Clearing the kCanOverflow flag when kAllUsesAreTruncatingToInt32
|
| - // would be wrong, because truncated integer multiplication is too
|
| - // precise and therefore not the same as converting to Double and back.
|
| + if (!res->MulAndCheckOverflow(r, b) ||
|
| + (((r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
|
| + (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) &&
|
| + MulMinusOne())) {
|
| + // Truncated int multiplication is too precise and therefore not the
|
| + // same as converting to Double and back.
|
| + // Handle truncated integer multiplication by -1 special.
|
| ClearFlag(kCanOverflow);
|
| }
|
| res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
|
| @@ -1649,7 +1662,10 @@ Range* HDiv::InferRange(Zone* zone) {
|
| result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
|
| (a->CanBeMinusZero() ||
|
| (a->CanBeZero() && b->CanBeNegative())));
|
| - if (!a->Includes(kMinInt) || !b->Includes(-1)) {
|
| + if (!a->Includes(kMinInt) ||
|
| + !b->Includes(-1) ||
|
| + CheckFlag(kAllUsesTruncatingToInt32)) {
|
| + // It is safe to clear kCanOverflow when kAllUsesTruncatingToInt32.
|
| ClearFlag(HValue::kCanOverflow);
|
| }
|
|
|
| @@ -2327,18 +2343,27 @@ void HSimulate::ReplayEnvironment(HEnvironment* env) {
|
| }
|
|
|
|
|
| +static void ReplayEnvironmentNested(const ZoneList<HValue*>* values,
|
| + HCapturedObject* other) {
|
| + for (int i = 0; i < values->length(); ++i) {
|
| + HValue* value = values->at(i);
|
| + if (value->IsCapturedObject()) {
|
| + if (HCapturedObject::cast(value)->capture_id() == other->capture_id()) {
|
| + values->at(i) = other;
|
| + } else {
|
| + ReplayEnvironmentNested(HCapturedObject::cast(value)->values(), other);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| // Replay captured objects by replacing all captured objects with the
|
| // same capture id in the current and all outer environments.
|
| void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
|
| ASSERT(env != NULL);
|
| while (env != NULL) {
|
| - for (int i = 0; i < env->length(); ++i) {
|
| - HValue* value = env->values()->at(i);
|
| - if (value->IsCapturedObject() &&
|
| - HCapturedObject::cast(value)->capture_id() == this->capture_id()) {
|
| - env->SetValueAt(i, this);
|
| - }
|
| - }
|
| + ReplayEnvironmentNested(env->values(), this);
|
| env = env->outer();
|
| }
|
| }
|
| @@ -2598,6 +2623,12 @@ void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
|
| ASSERT(CheckFlag(kFlexibleRepresentation));
|
| Representation new_rep = RepresentationFromInputs();
|
| UpdateRepresentation(new_rep, h_infer, "inputs");
|
| +
|
| + if (representation().IsSmi() && HasNonSmiUse()) {
|
| + UpdateRepresentation(
|
| + Representation::Integer32(), h_infer, "use requirements");
|
| + }
|
| +
|
| if (observed_output_representation_.IsNone()) {
|
| new_rep = RepresentationFromUses();
|
| UpdateRepresentation(new_rep, h_infer, "uses");
|
| @@ -2605,11 +2636,6 @@ void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
|
| new_rep = RepresentationFromOutput();
|
| UpdateRepresentation(new_rep, h_infer, "output");
|
| }
|
| -
|
| - if (representation().IsSmi() && HasNonSmiUse()) {
|
| - UpdateRepresentation(
|
| - Representation::Integer32(), h_infer, "use requirements");
|
| - }
|
| }
|
|
|
|
|
| @@ -2636,7 +2662,7 @@ bool HBinaryOperation::IgnoreObservedOutputRepresentation(
|
| return ((current_rep.IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) ||
|
| (current_rep.IsSmi() && CheckUsesForFlag(kTruncatingToSmi))) &&
|
| // Mul in Integer32 mode would be too precise.
|
| - !this->IsMul();
|
| + (!this->IsMul() || HMul::cast(this)->MulMinusOne());
|
| }
|
|
|
|
|
|
|