[INFER] Don't incorrectly mark compilation failure on loop bodies with large modsets, bug 656096.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 10 May 2011 13:34:23 -0700
changeset 75027 71e561e48de407b07b2c41ed29460939bcea88be
parent 75026 5aadf6bc110b9b4d5a7690f24ed8e543354ee917
child 75028 fd1abc43d698ff67eae944a26a4c2d3098d3f6a0
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs656096
milestone6.0a1
[INFER] Don't incorrectly mark compilation failure on loop bodies with large modsets, bug 656096.
js/src/jit-test/tests/jaeger/bug656096.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/LoopState.cpp
js/src/methodjit/LoopState.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug656096.js
@@ -0,0 +1,37 @@
+function aes(a) {
+    d = a.slice()
+    for (; a < 28; a++)
+    d[0] = d[0] ^ undefined
+}
+var sjcl = {};
+sjcl.bitArray = {
+    concat: function (a, b) {
+        return d ? a : [];
+    },
+    clamp: function (a, b) {
+        return a
+    }
+};
+function G(a, b, c, d, e, f) {
+    var g = [],
+        h = sjcl.bitArray,
+        f = [];
+    f = h.concat(f, c)
+    if (c) g = []
+    else c = h.concat([], [])
+    h.concat(g, d)
+    h.clamp(f, <x></x> )
+}
+function decrypt(a, b, c, d, e) {
+    G(a, 1, c, d, e, b)
+    var g = [],
+        h = sjcl.bitArray,
+        f = [];
+    h.concat(f, c)
+    if (c) g = []
+    else c = h.concat([], [])
+    h.concat(g, d)
+    h.concat([], c).concat.slice
+}
+aes(sjcl.bitArray.clamp([]));
+decrypt(1, 2, 3);
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -627,16 +627,18 @@ mjit::TryCompile(JSContext *cx, StackFra
          * Treat this the same way as a static overflow and wait for another
          * attempt to compile the script.
          */
         JITScriptStatus status = fp->script()->getJITStatus(fp->isConstructing());
         JS_ASSERT(status != JITScript_Invalid);
         return (status == JITScript_Valid) ? Compile_Okay : Compile_Retry;
     }
 
+    JS_ASSERT_IF(status == Compile_Error, cx->isExceptionPending());
+
     return status;
 }
 
 CompileStatus
 mjit::Compiler::generatePrologue()
 {
     invokeLabel = masm.label();
 
--- a/js/src/methodjit/LoopState.cpp
+++ b/js/src/methodjit/LoopState.cpp
@@ -118,18 +118,17 @@ LoopState::init(jsbytecode *head, Jump e
             unsigned pframe = index;
             while (ssa->getFrame(pframe).parent != CrossScriptSSA::OUTER_FRAME)
                 pframe = ssa->getFrame(pframe).parent;
             uint32 offset = ssa->getFrame(pframe).parentpc - outerScript->code;
             JS_ASSERT(offset < outerScript->length);
             if (offset < lifetime->head || offset > lifetime->backedge)
                 continue;
         }
-        if (!analyzeLoopBody(index))
-            return false;
+        analyzeLoopBody(index);
     }
 
     if (testLHS != UNASSIGNED) {
         JaegerSpew(JSpew_Analysis, "loop test at %u: %s %s %s + %d\n", lifetime->head,
                    frame.entryName(testLHS),
                    testLessEqual ? "<=" : ">=",
                    (testRHS == UNASSIGNED) ? "" : frame.entryName(testRHS),
                    testConstant);
@@ -1540,17 +1539,17 @@ LoopState::definiteArrayAccess(const SSA
     /*
      * The index is determined from a variable's value at loop entry. We don't
      * carry values with ignored overflows around loop back edges, so will know
      * the index is a non-integer before such overflows are ignored.
      */
     return true;
 }
 
-bool
+void
 LoopState::analyzeLoopBody(unsigned frame)
 {
     JSScript *script = ssa->getFrame(frame).script;
     analyze::ScriptAnalysis *analysis = script->analysis(cx);
     JS_ASSERT(analysis && !analysis->failed() && analysis->ranInference());
 
     /*
      * The temporaries need to be positioned after all values in the deepest
@@ -1627,19 +1626,19 @@ LoopState::analyzeLoopBody(unsigned fram
             }
 
             objTypes->addFreeze(cx);
             for (unsigned i = 0; i < objTypes->getObjectCount(); i++) {
                 types::TypeObject *object = objTypes->getObject(i);
                 if (!object)
                     continue;
                 if (!addModifiedProperty(object, JSID_VOID))
-                    return false;
+                    return;
                 if (op == JSOP_SETHOLE && !addGrowArray(object))
-                    return false;
+                    return;
             }
 
             if (constrainedLoop && !definiteArrayAccess(objValue, elemValue))
                 constrainedLoop = false;
             break;
           }
 
           case JSOP_GETELEM: {
@@ -1762,18 +1761,16 @@ LoopState::analyzeLoopBody(unsigned fram
 
           default:
             constrainedLoop = false;
             break;
         }
 
         offset = successorOffset;
     }
-
-    return true;
 }
 
 bool
 LoopState::addGrowArray(types::TypeObject *object)
 {
     static const uint32 MAX_SIZE = 10;
     for (unsigned i = 0; i < growArrays.length(); i++) {
         if (growArrays[i] == object)
--- a/js/src/methodjit/LoopState.h
+++ b/js/src/methodjit/LoopState.h
@@ -336,17 +336,17 @@ class LoopState : public MacroAssemblerT
      * Whether this loop only performs integer and double arithmetic and dense
      * array accesses. Integer overflows in this loop which only flow to bitops
      * can be ignored.
      */
     bool constrainedLoop;
 
     void analyzeLoopTest();
     void analyzeLoopIncrements();
-    bool analyzeLoopBody(unsigned frame);
+    void analyzeLoopBody(unsigned frame);
 
     bool definiteArrayAccess(const analyze::SSAValue &obj, const analyze::SSAValue &index);
     bool getLoopTestAccess(const analyze::SSAValue &v, uint32 *pslot, int32 *pconstant);
 
     bool addGrowArray(types::TypeObject *object);
     bool addModifiedProperty(types::TypeObject *object, jsid id);
 
     bool hasGrowArray(types::TypeObject *object);