[INFER] Handle jsop_binary overflow in inc/dec ops, bug 644970. r=bhackett
authorJan de Mooij <jandemooij@gmail.com>
Mon, 28 Mar 2011 15:44:30 -0700
changeset 74856 60a4769fe844423e41f32e444af620b5522f252f
parent 74855 d1ba6ce55784f30c59914a58a708b4756087050f
child 74857 a3632d306b1396e160098e5cf835f09b9c6bdfd2
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersbhackett
bugs644970
milestone2.0b13pre
[INFER] Handle jsop_binary overflow in inc/dec ops, bug 644970. r=bhackett
js/src/jit-test/tests/basic/bug645293.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug645293.js
@@ -0,0 +1,12 @@
+/* Don't assert. */
+function f() {
+    NaN++;
+    --NaN;
+    Infinity--;
+    ++Infinity;
+    undefined++;
+    --undefined;
+    ++Math;
+    Math--;
+}
+f();
\ No newline at end of file
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1697,93 +1697,121 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_TYPEOF)
 
           BEGIN_CASE(JSOP_VOID)
             frame.pop();
             frame.push(UndefinedValue());
           END_CASE(JSOP_VOID)
 
           BEGIN_CASE(JSOP_INCNAME)
-            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_INCNAME)
 
           BEGIN_CASE(JSOP_INCGNAME)
-            jsop_gnameinc(op, STRICT_VARIANT(stubs::IncGlobalName), fullAtomIndex(PC));
+            if (!jsop_gnameinc(op, STRICT_VARIANT(stubs::IncGlobalName), fullAtomIndex(PC)))
+                return Compile_Retry;
             break;
           END_CASE(JSOP_INCGNAME)
 
           BEGIN_CASE(JSOP_INCPROP)
-            if (!jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_INCPROP)
 
           BEGIN_CASE(JSOP_INCELEM)
             jsop_eleminc(op, STRICT_VARIANT(stubs::IncElem));
           END_CASE(JSOP_INCELEM)
 
           BEGIN_CASE(JSOP_DECNAME)
-            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_DECNAME)
 
           BEGIN_CASE(JSOP_DECGNAME)
-            jsop_gnameinc(op, STRICT_VARIANT(stubs::DecGlobalName), fullAtomIndex(PC));
+            if (!jsop_gnameinc(op, STRICT_VARIANT(stubs::DecGlobalName), fullAtomIndex(PC)))
+                return Compile_Retry;
             break;
           END_CASE(JSOP_DECGNAME)
 
           BEGIN_CASE(JSOP_DECPROP)
-            if (!jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_DECPROP)
 
           BEGIN_CASE(JSOP_DECELEM)
             jsop_eleminc(op, STRICT_VARIANT(stubs::DecElem));
           END_CASE(JSOP_DECELEM)
 
           BEGIN_CASE(JSOP_NAMEINC)
-            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_NAMEINC)
 
           BEGIN_CASE(JSOP_GNAMEINC)
-            jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameInc), fullAtomIndex(PC));
+            if (!jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameInc), fullAtomIndex(PC)))
+                return Compile_Retry;
             break;
           END_CASE(JSOP_GNAMEINC)
 
           BEGIN_CASE(JSOP_PROPINC)
-            if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_PROPINC)
 
           BEGIN_CASE(JSOP_ELEMINC)
             jsop_eleminc(op, STRICT_VARIANT(stubs::ElemInc));
           END_CASE(JSOP_ELEMINC)
 
           BEGIN_CASE(JSOP_NAMEDEC)
-            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_NAMEDEC)
 
           BEGIN_CASE(JSOP_GNAMEDEC)
-            jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameDec), fullAtomIndex(PC));
+            if (!jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameDec), fullAtomIndex(PC)))
+                return Compile_Retry;
             break;
           END_CASE(JSOP_GNAMEDEC)
 
           BEGIN_CASE(JSOP_PROPDEC)
-            if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC)))
-                return Compile_Error;
+          {
+            CompileStatus status = jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC));
+            if (status != Compile_Okay)
+                return status;
             break;
+          }
           END_CASE(JSOP_PROPDEC)
 
           BEGIN_CASE(JSOP_ELEMDEC)
             jsop_eleminc(op, STRICT_VARIANT(stubs::ElemDec));
           END_CASE(JSOP_ELEMDEC)
 
           BEGIN_CASE(JSOP_GETTHISPROP)
             /* Push thisv onto stack. */
@@ -4869,17 +4897,17 @@ mjit::Compiler::jsop_this()
             frame.learnThisIsObject();
             frame.pushThis();
         }
 
         JS_ASSERT(thisFe->isType(JSVAL_TYPE_OBJECT));
     }
 }
 
-void
+bool
 mjit::Compiler::jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
 
 #if defined JS_MONOIC
     jsbytecode *next = &PC[JSOP_GNAMEINC_LENGTH];
     bool pop = (JSOp(*next) == JSOP_POP) && !a->analysis.jumpTarget(next);
     int amt = (op == JSOP_GNAMEINC || op == JSOP_INCGNAME) ? -1 : 1;
@@ -4889,17 +4917,18 @@ mjit::Compiler::jsop_gnameinc(JSOp op, V
 
         jsop_getgname(index, JSVAL_TYPE_UNKNOWN);
         // V
 
         frame.push(Int32Value(amt));
         // V 1
 
         /* Use sub since it calls ValueToNumber instead of string concat. */
-        jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+        if (!jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+            return false;
         // N+1
 
         jsop_bindgname();
         // V+1 OBJ
 
         frame.dup2();
         // V+1 OBJ V+1 OBJ
 
@@ -4924,17 +4953,18 @@ mjit::Compiler::jsop_gnameinc(JSOp op, V
         // N
 
         frame.dup();
         // N N
 
         frame.push(Int32Value(-amt));
         // N N 1
 
-        jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+        if (!jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+            return false;
         // N N+1
 
         jsop_bindgname();
         // N N+1 OBJ
 
         frame.dup2();
         // N N+1 OBJ N+1 OBJ
 
@@ -4956,19 +4986,20 @@ mjit::Compiler::jsop_gnameinc(JSOp op, V
 #else
     prepareStubCall(Uses(0));
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     INLINE_STUBCALL(stub);
     frame.pushSynced(knownPushedType(0));
 #endif
 
     PC += JSOP_GNAMEINC_LENGTH;
+    return true;
 }
 
-bool
+CompileStatus
 mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
 #if defined JS_POLYIC
     jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH];
     bool pop = (JSOp(*next) == JSOP_POP) && !a->analysis.jumpTarget(next);
     int amt = (op == JSOP_NAMEINC || op == JSOP_INCNAME) ? -1 : 1;
 
@@ -4981,21 +5012,22 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
         jsop_name(atom, JSVAL_TYPE_UNKNOWN);
         // OBJ V
 
         frame.push(Int32Value(amt));
         // OBJ V 1
 
         /* Use sub since it calls ValueToNumber instead of string concat. */
         frame.syncAt(-3);
-        jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+        if (!jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+            return Compile_Retry;
         // OBJ N+1
 
         if (!jsop_setprop(atom, false))
-            return false;
+            return Compile_Error;
         // N+1
 
         if (pop)
             frame.pop();
     } else {
         /* The pre-value is observed, making this more tricky. */
 
         jsop_name(atom, JSVAL_TYPE_UNKNOWN);
@@ -5009,41 +5041,42 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
 
         frame.dupAt(-2);
         // N OBJ N
 
         frame.push(Int32Value(-amt));
         // N OBJ N 1
 
         frame.syncAt(-3);
-        jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+        if (!jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+            return Compile_Retry;
         // N OBJ N+1
 
         if (!jsop_setprop(atom, false))
-            return false;
+            return Compile_Error;
         // N N+1
 
         frame.pop();
         // N
     }
 
     if (pop)
         PC += JSOP_POP_LENGTH;
 #else
     prepareStubCall(Uses(0));
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     INLINE_STUBCALL(stub);
     frame.pushSynced(knownPushedType(0));
 #endif
 
     PC += JSOP_NAMEINC_LENGTH;
-    return true;
+    return Compile_Okay;
 }
 
-bool
+CompileStatus
 mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
 #if defined JS_POLYIC
     FrameEntry *objFe = frame.peek(-1);
     if (!objFe->isTypeKnown() || objFe->getKnownType() == JSVAL_TYPE_OBJECT) {
         jsbytecode *next = &PC[JSOP_PROPINC_LENGTH];
         bool pop = (JSOp(*next) == JSOP_POP) && !a->analysis.jumpTarget(next);
@@ -5059,67 +5092,69 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
 
             frame.dup();
             // OBJ OBJ
 
             frame.dup();
             // OBJ * OBJ
 
             if (!jsop_getprop(atom, JSVAL_TYPE_UNKNOWN))
-                return false;
+                return Compile_Error;
             // OBJ * V
 
             frame.push(Int32Value(amt));
             // OBJ * V 1
 
             /* Use sub since it calls ValueToNumber instead of string concat. */
             frame.syncAt(-4);
-            jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+            if (!jsop_binary(JSOP_SUB, stubs::Sub, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+                return Compile_Retry;
             // OBJ * V+1
 
             frame.shimmy(1);
             // OBJ V+1
 
             if (!jsop_setprop(atom, false))
-                return false;
+                return Compile_Error;
             // V+1
 
             if (pop)
                 frame.pop();
         } else {
             /* The pre-value is observed, making this more tricky. */
 
             frame.dup();
             // OBJ OBJ 
 
             if (!jsop_getprop(atom, JSVAL_TYPE_UNKNOWN))
-                return false;
+                return Compile_Error;
             // OBJ V
 
             jsop_pos();
             // OBJ N
 
             frame.dup();
             // OBJ N N
 
             frame.push(Int32Value(-amt));
             // OBJ N N 1
 
             frame.syncAt(-4);
-            jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0));
+            if (!jsop_binary(JSOP_ADD, stubs::Add, JSVAL_TYPE_UNKNOWN, pushedTypeSet(0)))
+                return Compile_Retry;
             // OBJ N N+1
 
             frame.dupAt(-3);
             // OBJ N N+1 OBJ
 
             frame.dupAt(-2);
             // OBJ N N+1 OBJ N+1
 
             if (!jsop_setprop(atom, false))
-                return false;
+                return Compile_Error;
             // OBJ N N+1 N+1
 
             frame.popn(2);
             // OBJ N
 
             frame.shimmy(1);
             // N
         }
@@ -5131,17 +5166,17 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
         prepareStubCall(Uses(1));
         masm.move(ImmPtr(atom), Registers::ArgReg1);
         INLINE_STUBCALL(stub);
         frame.pop();
         pushSyncedEntry(0);
     }
 
     PC += JSOP_PROPINC_LENGTH;
-    return true;
+    return Compile_Okay;
 }
 
 bool
 mjit::Compiler::iter(uintN flags)
 {
     FrameEntry *fe = frame.peek(-1);
 
     /*
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -558,19 +558,19 @@ class Compiler : public BaseCompiler
     void emitUncachedCall(uint32 argc, bool callingNew);
     void checkCallApplySpeculation(uint32 callImmArgc, uint32 speculatedArgc,
                                    FrameEntry *origCallee, FrameEntry *origThis,
                                    MaybeRegisterID origCalleeType, RegisterID origCalleeData,
                                    MaybeRegisterID origThisType, RegisterID origThisData,
                                    Jump *uncachedCallSlowRejoin, CallPatchInfo *uncachedCallPatch);
     bool inlineCallHelper(uint32 argc, bool callingNew);
     void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
-    void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
-    bool jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
-    bool jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
+    bool jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
+    CompileStatus jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
+    CompileStatus jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
     void jsop_eleminc(JSOp op, VoidStub);
     void jsop_getgname(uint32 index, JSValueType type);
     void jsop_getgname_slow(uint32 index);
     void jsop_callgname_epilogue();
     void jsop_setgname(JSAtom *atom, bool usePropertyCache);
     void jsop_setgname_slow(JSAtom *atom, bool usePropertyCache);
     void jsop_bindgname();
     void jsop_setelem_slow();