Backed out changeset b4300d783a34 (Bug 1239075) for 12.5% Octane-crypto regression. r=awfy
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Fri, 04 Mar 2016 13:17:37 +0000
changeset 286786 77192f60c4a5992651c9a9c2550adf6dd3ece42f
parent 286785 36a77fdd0533553090e6ff53809d1b31dd23bdac
child 286787 cb95e5ff55faf8d7ee19b80ab63d2d2946ae43fd
push id72909
push usernpierron@mozilla.com
push dateFri, 04 Mar 2016 13:18:16 +0000
treeherdermozilla-inbound@77192f60c4a5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersawfy
bugs1239075
milestone47.0a1
backs outb4300d783a34181af73612711f21ae98e54f4d69
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset b4300d783a34 (Bug 1239075) for 12.5% Octane-crypto regression. r=awfy
js/src/jit-test/tests/ion/bug1239075.js
js/src/jit/RangeAnalysis.cpp
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug1239075.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-function g0() { with({}){}; }
-function f0(y, x) {
-    var a = y >>> 0;
-    a = a - 1 + 1;
-    g0(); // Capture the truncate result after the call.
-    var b = x / 2; // bailout.
-    return ~(a + b);
-}
-assertEq(f0(-1, 0), 0);
-assertEq(f0(-1, 1), 0);
-
-
-function g1() { with({}){}; }
-function f1(y, x) {
-    var a = y >>> 0;
-    a = a - 1 + 1;
-    g1(); // Capture the truncate result after the call.
-    var b = Math.pow(x / 2, x); // bailout.
-    return ~(a + b);
-}
-assertEq(f1(-1, 0), -1);
-assertEq(f1(-1, 1), 0);
-
-function f2(x) {
-    return ~(((~0 | 0) >>> 0 || 0) + Math.pow(Math.cos(x >>> 0), Math.atan2(0, x)))
-}
-assertEq(f2(0), -1);
-assertEq(f2(-9999), 0);
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2865,34 +2865,39 @@ CloneForDeadBranches(TempAllocator& allo
 }
 
 // Examine all the users of |candidate| and determine the most aggressive
 // truncate kind that satisfies all of them.
 static MDefinition::TruncateKind
 ComputeRequestedTruncateKind(MDefinition* candidate, bool* shouldClone)
 {
     bool isCapturedResult = false;
+    bool isObservableResult = false;
     bool isRecoverableResult = true;
+    bool hasUseRemoved = candidate->isUseRemoved();
 
     MDefinition::TruncateKind kind = MDefinition::Truncate;
     for (MUseIterator use(candidate->usesBegin()); use != candidate->usesEnd(); use++) {
         if (use->consumer()->isResumePoint()) {
             // Truncation is a destructive optimization, as such, we need to pay
             // attention to removed branches and prevent optimization
             // destructive optimizations if we have no alternative. (see
             // UseRemoved flag)
             isCapturedResult = true;
+            isObservableResult = isObservableResult ||
+                use->consumer()->toResumePoint()->isObservableOperand(*use);
             isRecoverableResult = isRecoverableResult &&
                 use->consumer()->toResumePoint()->isRecoverableOperand(*use);
             continue;
         }
 
         MDefinition* consumer = use->consumer()->toDefinition();
         if (consumer->isRecoveredOnBailout()) {
             isCapturedResult = true;
+            hasUseRemoved = hasUseRemoved || consumer->isUseRemoved();
             continue;
         }
 
         MDefinition::TruncateKind consumerKind = consumer->operandTruncateKind(consumer->indexOf(*use));
         kind = Min(kind, consumerKind);
         if (kind == MDefinition::NoTruncate)
             break;
     }
@@ -2907,26 +2912,34 @@ ComputeRequestedTruncateKind(MDefinition
     bool needsConversion = !candidate->range() || !candidate->range()->isInt32();
 
     // If the candidate instruction appears as operand of a resume point or a
     // recover instruction, and we have to truncate its result, then we might
     // have to either recover the result during the bailout, or avoid the
     // truncation.
     if (isCapturedResult && needsConversion) {
 
-        // If the result can be recovered from all the resume points (not needed
-        // for iterating over the inlined frames), and this instruction can be
-        // recovered on bailout, then we can clone it and use the cloned
-        // instruction to encode the recover instruction.  Otherwise, we should
-        // keep the original result and bailout if the value is not in the int32
-        // range.
-        if (isRecoverableResult && candidate->canRecoverOnBailout())
+        // These optimizations are pointless if there are no removed uses or any
+        // resume point observing the result.  Not having any means that we know
+        // everything about where this results flows into.
+        if ((hasUseRemoved || (isObservableResult && isRecoverableResult)) &&
+            candidate->canRecoverOnBailout())
+        {
+            // The cloned instruction is expected to be used as a recover
+            // instruction.
             *shouldClone = true;
-        else
+
+        } else if (hasUseRemoved || isObservableResult) {
+            // 1. If uses are removed and we cannot recover the result, then we
+            // need to keep the expected result for dead branches.
+            //
+            // 2. If the result is observable and not recoverable, then the
+            // result might be read while the frame is on the stack.
             kind = Min(kind, MDefinition::TruncateAfterBailouts);
+        }
     }
 
     return kind;
 }
 
 static MDefinition::TruncateKind
 ComputeTruncateKind(MDefinition* candidate, bool* shouldClone)
 {