[INFER] Only convert known ints when fixing doubles before branching, bug 652590.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 26 Apr 2011 23:28:39 -0700
changeset 74982 89d2095c7a87bb5dd924aa1ac92543e9ca5ce509
parent 74981 b40247ae7dd53bd1c828ceafff037afdfbf15fb8
child 74983 09cce9915b80ef98fab169e0a2d2ac2351af5b2f
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs652590
milestone6.0a1
[INFER] Only convert known ints when fixing doubles before branching, bug 652590.
js/src/jit-test/tests/jaeger/bug652590.js
js/src/methodjit/Compiler.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug652590.js
@@ -0,0 +1,5 @@
+function f() {
+    var x = undefined ? 1 : 4294967295;
+    print(false || x);
+}
+f();
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -2231,16 +2231,26 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_BINDGNAME)
 
           BEGIN_CASE(JSOP_SETARG)
           {
             updateVarType();
             jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
             frame.storeArg(GET_SLOTNO(PC), pop);
+
+            /*
+             * Types of variables inferred as doubles need to be maintained as
+             * doubles. We might forget the type of the variable by the next
+             * call to fixDoubleTypes.
+             */
+            uint32 slot = analyze::ArgSlot(GET_SLOTNO(PC));
+            if (a->varTypes[slot].type == JSVAL_TYPE_DOUBLE && fixDoubleSlot(slot))
+                frame.ensureDouble(frame.getArg(GET_SLOTNO(PC)));
+
             if (pop) {
                 frame.pop();
                 PC += JSOP_SETARG_LENGTH + JSOP_POP_LENGTH;
                 break;
             }
           }
           END_CASE(JSOP_SETARG)
 
@@ -2252,16 +2262,21 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_GETLOCAL)
 
           BEGIN_CASE(JSOP_SETLOCAL)
           {
             updateVarType();
             jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
             frame.storeLocal(GET_SLOTNO(PC), pop, true);
+
+            uint32 slot = analyze::LocalSlot(script, GET_SLOTNO(PC));
+            if (a->varTypes[slot].type == JSVAL_TYPE_DOUBLE && fixDoubleSlot(slot))
+                frame.ensureDouble(frame.getLocal(GET_SLOTNO(PC)));
+
             if (pop) {
                 frame.pop();
                 PC += JSOP_SETLOCAL_LENGTH + JSOP_POP_LENGTH;
                 break;
             }
           }
           END_CASE(JSOP_SETLOCAL)
 
@@ -7080,59 +7095,44 @@ mjit::Compiler::fixDoubleSlot(uint32 slo
 
 void
 mjit::Compiler::fixDoubleTypes(jsbytecode *target)
 {
     if (!cx->typeInferenceEnabled())
         return;
 
     /*
-     * Temporarily fix up the variable types to reflect state at the branch
-     * target. As described in prepareInferenceTypes, the target state consists
-     * of the current state plus any phi nodes introduced at the target.
+     * Fill fixedDoubleEntries with all variables that are known to be an int
+     * here and a double at the branch target. Per prepareInferenceTypes, the
+     * target state consists of the current state plus any phi nodes or other
+     * new values introduced at the target.
      */
-    Vector<SlotType, 8, CompilerAllocPolicy> restoreTypes(CompilerAllocPolicy(cx, *this));
     const analyze::SlotValue *newv = analysis->newValues(target);
     if (newv) {
         while (newv->slot) {
             if (newv->value.kind() != analyze::SSAValue::PHI ||
                 newv->value.phiOffset() != uint32(target - script->code)) {
                 newv++;
                 continue;
             }
             if (newv->slot < analyze::TotalSlots(script)) {
                 VarType &vt = a->varTypes[newv->slot];
-                restoreTypes.append(SlotType(newv->slot, vt));
-                vt.types = analysis->getValueTypes(newv->value);
-                vt.type = vt.types->getKnownTypeTag(cx);
+                if (vt.type == JSVAL_TYPE_INT32) {
+                    types::TypeSet *targetTypes = analysis->getValueTypes(newv->value);
+                    if (targetTypes->getKnownTypeTag(cx) == JSVAL_TYPE_DOUBLE &&
+                        fixDoubleSlot(newv->slot)) {
+                        fixedDoubleEntries.append(newv->slot);
+                        FrameEntry *fe = frame.getOrTrack(newv->slot);
+                        frame.ensureDouble(fe);
+                    }
+                }
             }
             newv++;
         }
     }
-
-    for (uint32 slot = analyze::ArgSlot(0); slot < analyze::TotalSlots(script); slot++) {
-        if (!fixDoubleSlot(slot))
-            continue;
-        if (a->varTypes[slot].type == JSVAL_TYPE_DOUBLE) {
-            FrameEntry *fe = frame.getOrTrack(slot);
-            if (!fe->isType(JSVAL_TYPE_DOUBLE)) {
-                /*
-                 * Remember any slots we converted to double, so we can convert
-                 * them back into ints at the start of the next iteration.
-                 */
-                fixedDoubleEntries.append(frame.indexOfFe(fe));
-                frame.ensureDouble(fe);
-            }
-        }
-    }
-
-    for (unsigned i = 0; i < restoreTypes.length(); i++) {
-        const SlotType &rt = restoreTypes[i];
-        a->varTypes[rt.slot] = rt.vt;
-    }
 }
 
 void
 mjit::Compiler::restoreAnalysisTypes()
 {
     if (!cx->typeInferenceEnabled())
         return;