[INFER] Fix JSOP_NEG convert-to-double bug, bug 619433.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 07 Mar 2011 23:46:04 -0800
changeset 74731 511f51584aad04478fbf1febe7b8fbbc17d7304f
parent 74730 559b9da69fcb6f18265d928b0b067e31a7c4c31c
child 74732 c5cd2693106e6445f6ec42f4dc7130a09dd2f6bb
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs619433
milestone2.0b12pre
[INFER] Fix JSOP_NEG convert-to-double bug, bug 619433.
js/src/jit-test/tests/jaeger/bug619433-2.js
js/src/jsinfer.cpp
js/src/methodjit/FastArithmetic.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug619433-2.js
@@ -0,0 +1,10 @@
+
+function foo(x) {
+  var y = 2.5;
+  y = -x;
+  var z = [1,2,y];
+  return x + 5;
+}
+for (var i = 0; i < 20; i++)
+  foo(i);
+assertEq(foo(20), 25);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2032,16 +2032,19 @@ TypeCompartment::monitorBytecode(JSConte
         cx->compartment->types.addPendingRecompile(cx, script);
 }
 
 void
 TypeCompartment::finish(JSContext *cx, JSCompartment *compartment)
 {
     JS_ASSERT(this == &compartment->types);
 
+    if (pendingArray)
+        cx->free(pendingArray);
+
     if (!InferSpewActive(ISpewResult) || JS_CLIST_IS_EMPTY(&compartment->scripts))
         return;
 
     for (JSScript *script = (JSScript *)compartment->scripts.next;
          &script->links != &compartment->scripts;
          script = (JSScript *)script->links.next) {
         if (script->types)
             script->types->finish(cx, script);
@@ -4113,16 +4116,17 @@ JSScript::condenseTypes(JSContext *cx)
 
         unsigned num = 2 + nfixed + (fun ? fun->nargs : 0) + bindings.countUpvars();
 
         if (isCachedEval ||
             (u.object && IsAboutToBeFinalized(cx, u.object)) ||
             (fun && IsAboutToBeFinalized(cx, fun))) {
             for (unsigned i = 0; i < num; i++)
                 varTypes[i].destroy(cx);
+            cx->free(varTypes);
             varTypes = NULL;
         } else {
             for (unsigned i = 0; i < num; i++)
                 js::types::CondenseSweepTypeSet(cx, &compartment->types, pcondensed, &varTypes[i]);
         }
     }
 }
 
--- a/js/src/methodjit/FastArithmetic.cpp
+++ b/js/src/methodjit/FastArithmetic.cpp
@@ -771,25 +771,34 @@ mjit::Compiler::jsop_neg()
         INLINE_STUBCALL(stubs::Neg);
         frame.pop();
         frame.pushSynced(type);
         return;
     }
 
     JS_ASSERT(!fe->isConstant());
 
-    if (type == JSVAL_TYPE_DOUBLE)
-        frame.ensureDouble(fe);
+    /* Handle negation of a known double, or of a known integer which has previously overflowed. */
+    if (fe->isType(JSVAL_TYPE_DOUBLE) ||
+        (fe->isType(JSVAL_TYPE_INT32) && type == JSVAL_TYPE_DOUBLE)) {
+        FPRegisterID fpreg;
+        if (fe->isType(JSVAL_TYPE_DOUBLE)) {
+            fpreg = frame.tempFPRegForData(fe);
+        } else {
+            fpreg = frame.allocFPReg();
+            frame.convertInt32ToDouble(masm, fe, fpreg);
+        }
 
-    if (fe->isType(JSVAL_TYPE_DOUBLE)) {
-        FPRegisterID fpreg = frame.tempFPRegForData(fe);
         FPRegisterID res = frame.allocFPReg();
         masm.moveDouble(fpreg, res);
         masm.negateDouble(res);
 
+        if (!fe->isType(JSVAL_TYPE_DOUBLE))
+            frame.freeReg(fpreg);
+
         frame.pop();
         frame.pushDouble(res);
 
         if (recompiling) {
             OOL_STUBCALL(stubs::Neg);
             stubcc.rejoin(Changes(1));
         }