Don't go through GetPcScript to monitor AddValue edge cases (bug 776022, r=dvander).
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 27 Jul 2012 13:12:30 -0700
changeset 102396 ee40f69169e92bab907a3981943363f63ae2620f
parent 102395 1274d6819bae7c97d22a872ac8092d8c51c80b01
child 102397 ba811ef4de1ccccf32bb0724459a027cee7cd101
push id1150
push userdanderson@mozilla.com
push dateFri, 27 Jul 2012 20:13:50 +0000
reviewersdvander
bugs776022
milestone17.0a1
Don't go through GetPcScript to monitor AddValue edge cases (bug 776022, r=dvander).
js/src/ion/CodeGenerator.cpp
js/src/ion/VMFunctions.h
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1562,26 +1562,28 @@ CodeGenerator::visitMathFunctionD(LMathF
 
     masm.callWithABI(funptr, MacroAssembler::DOUBLE);
     return true;
 }
 
 bool
 CodeGenerator::visitBinaryV(LBinaryV *lir)
 {
-    typedef bool (*pf)(JSContext *, HandleValue, HandleValue, Value *);
+    typedef bool (*pf)(JSContext *, HandleScript, jsbytecode *, HandleValue, HandleValue, Value *);
     static const VMFunction AddInfo = FunctionInfo<pf>(js::AddValues);
     static const VMFunction SubInfo = FunctionInfo<pf>(js::SubValues);
     static const VMFunction MulInfo = FunctionInfo<pf>(js::MulValues);
     static const VMFunction DivInfo = FunctionInfo<pf>(js::DivValues);
     static const VMFunction ModInfo = FunctionInfo<pf>(js::ModValues);
     static const VMFunction UrshInfo = FunctionInfo<pf>(js::UrshValues);
 
     pushArg(ToValue(lir, LBinaryV::RhsInput));
     pushArg(ToValue(lir, LBinaryV::LhsInput));
+    pushArg(ImmWord(lir->mirRaw()->toInstruction()->resumePoint()->pc()));
+    pushArg(ImmGCPtr(current->mir()->info().script()));
 
     switch (lir->jsop()) {
       case JSOP_ADD:
         return callVM(AddInfo, lir);
 
       case JSOP_SUB:
         return callVM(SubInfo, lir);
 
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -174,16 +174,17 @@ template <class> struct TypeToDataType {
 template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; };
 template <> struct TypeToDataType<JSObject *> { static const DataType result = Type_Object; };
 template <> struct TypeToDataType<JSString *> { static const DataType result = Type_Object; };
 template <> struct TypeToDataType<JSFixedString *> { static const DataType result = Type_Object; };
 template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
+template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; };
 
 // Convert argument types to properties of the argument known by the jit.
 template <class T> struct TypeToArgProperties {
     static const uint32 result =
         (sizeof(T) <= sizeof(void *) ? VMFunction::Word : VMFunction::Double);
 };
 template <> struct TypeToArgProperties<const Value &> {
@@ -196,16 +197,19 @@ template <> struct TypeToArgProperties<H
     static const uint32 result = TypeToArgProperties<JSString *>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandlePropertyName> {
     static const uint32 result = TypeToArgProperties<PropertyName *>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandleFunction> {
     static const uint32 result = TypeToArgProperties<JSFunction *>::result | VMFunction::ByRef;
 };
+template <> struct TypeToArgProperties<HandleScript> {
+    static const uint32 result = TypeToArgProperties<JSScript *>::result | VMFunction::ByRef;
+};
 template <> struct TypeToArgProperties<HandleValue> {
     static const uint32 result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandleShape> {
     static const uint32 result = TypeToArgProperties<Shape *>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandleTypeObject> {
     static const uint32 result = TypeToArgProperties<types::TypeObject *>::result | VMFunction::ByRef;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2095,71 +2095,71 @@ BEGIN_CASE(JSOP_RSH)
 END_CASE(JSOP_RSH)
 
 #undef SIGNED_SHIFT_OP
 
 BEGIN_CASE(JSOP_URSH)
 {
     Value lval = regs.sp[-2];
     Value rval = regs.sp[-1];
-    if (!UrshOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!UrshOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_URSH)
 
 BEGIN_CASE(JSOP_ADD)
 {
     Value lval = regs.sp[-2];
     Value rval = regs.sp[-1];
-    if (!AddOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!AddOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_ADD)
 
 BEGIN_CASE(JSOP_SUB)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
     lval = regs.sp[-2];
     rval = regs.sp[-1];
-    if (!SubOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!SubOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_SUB)
 
 BEGIN_CASE(JSOP_MUL)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
     lval = regs.sp[-2];
     rval = regs.sp[-1];
-    if (!MulOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!MulOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_MUL)
 
 BEGIN_CASE(JSOP_DIV)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
     lval = regs.sp[-2];
     rval = regs.sp[-1];
-    if (!DivOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!DivOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_DIV)
 
 BEGIN_CASE(JSOP_MOD)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
     lval = regs.sp[-2];
     rval = regs.sp[-1];
-    if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
+    if (!ModOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_MOD)
 
 BEGIN_CASE(JSOP_NOT)
 {
     Value *_;
@@ -4118,42 +4118,48 @@ js::SetObjectElement(JSContext *cx, Hand
     RootedId id(cx);
     Value indexval = index;
     if (!FetchElementId(cx, obj, indexval, id.address(), &indexval))
         return false;
     return SetObjectElementOperation(cx, obj, id, value, strict);
 }
 
 bool
-js::AddValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::AddValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return AddOperation(cx, lhs, rhs, res);
+    return AddOperation(cx, script, pc, lhs, rhs, res);
 }
 
 bool
-js::SubValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::SubValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return SubOperation(cx, lhs, rhs, res);
+    return SubOperation(cx, script, pc, lhs, rhs, res);
 }
 
 bool
-js::MulValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::MulValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return MulOperation(cx, lhs, rhs, res);
+    return MulOperation(cx, script, pc, lhs, rhs, res);
 }
 
 bool
-js::DivValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::DivValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return DivOperation(cx, lhs, rhs, res);
+    return DivOperation(cx, script, pc, lhs, rhs, res);
 }
 
 bool
-js::ModValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::ModValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return ModOperation(cx, lhs, rhs, res);
+    return ModOperation(cx, script, pc, lhs, rhs, res);
 }
 
 bool
-js::UrshValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+js::UrshValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+              Value *res)
 {
-    return UrshOperation(cx, lhs, rhs, res);
+    return UrshOperation(cx, script, pc, lhs, rhs, res);
 }
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -348,32 +348,38 @@ GetElementMonitored(JSContext *cx, const
 bool
 CallElement(JSContext *cx, const Value &lref, const Value &rref, Value *res);
 
 bool
 SetObjectElement(JSContext *cx, HandleObject obj, const Value &index, const Value &value,
                  JSBool strict);
 
 bool
-AddValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+AddValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 bool
-SubValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+SubValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 bool
-MulValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+MulValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 bool
-DivValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+DivValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 bool
-ModValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+ModValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 bool
-UrshValues(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res);
+UrshValues(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+          Value *res);
 
 template <bool strict>
 bool
 SetProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value);
 
 template <bool strict>
 bool
 DeleteProperty(JSContext *ctx, const Value &val, HandlePropertyName name, JSBool *bv);
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -472,33 +472,34 @@ DefVarOrConstOperation(JSContext *cx, Ha
 inline void
 InterpreterFrames::enableInterruptsIfRunning(JSScript *script)
 {
     if (script == regs->fp()->script())
         enabler.enable();
 }
 
 static JS_ALWAYS_INLINE bool
-AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
+AddOperation(JSContext *cx, HandleScript script, jsbytecode *pc, const Value &lhs, const Value &rhs,
+             Value *res)
 {
     if (lhs.isInt32() && rhs.isInt32()) {
         int32_t l = lhs.toInt32(), r = rhs.toInt32();
         int32_t sum = l + r;
         if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
             res->setDouble(double(l) + double(r));
-            types::TypeScript::MonitorOverflow(cx);
+            types::TypeScript::MonitorOverflow(cx, script, pc);
         } else {
             res->setInt32(sum);
         }
     } else
 #if JS_HAS_XML_SUPPORT
     if (IsXML(lhs) && IsXML(rhs)) {
         if (!js_ConcatenateXML(cx, &lhs.toObject(), &rhs.toObject(), res))
             return false;
-        types::TypeScript::MonitorUnknown(cx);
+        types::TypeScript::MonitorUnknown(cx, script, pc);
     } else
 #endif
     {
         RootedValue lval_(cx, lhs);
         RootedValue rval_(cx, rhs);
         Value &lval = lval_.get();
         Value &rval = rval_.get();
 
@@ -528,86 +529,90 @@ AddOperation(JSContext *cx, const Value 
                 rstr = ToString(cx, rval);
                 if (!rstr)
                     return false;
             }
             JSString *str = js_ConcatStrings(cx, lstr, rstr);
             if (!str)
                 return false;
             if (lIsObject || rIsObject)
-                types::TypeScript::MonitorString(cx);
+                types::TypeScript::MonitorString(cx, script, pc);
             res->setString(str);
         } else {
             double l, r;
             if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))
                 return false;
             l += r;
             if (!res->setNumber(l) &&
                 (lIsObject || rIsObject || (!lval.isDouble() && !rval.isDouble()))) {
-                types::TypeScript::MonitorOverflow(cx);
+                types::TypeScript::MonitorOverflow(cx, script, pc);
             }
         }
     }
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-SubOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+SubOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+             Value *res)
 {
     double d1, d2;
     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
         return false;
     double d = d1 - d2;
     if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
-        types::TypeScript::MonitorOverflow(cx);
+        types::TypeScript::MonitorOverflow(cx, script, pc);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-MulOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+MulOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+             Value *res)
 {
     double d1, d2;
     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
         return false;
     double d = d1 * d2;
     if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
-        types::TypeScript::MonitorOverflow(cx);
+        types::TypeScript::MonitorOverflow(cx, script, pc);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-DivOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+DivOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+             Value *res)
 {
     double d1, d2;
     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
         return false;
     res->setNumber(NumberDiv(d1, d2));
 
     if (d2 == 0 || (res->isDouble() && !(lhs.isDouble() || rhs.isDouble())))
-        types::TypeScript::MonitorOverflow(cx);
+        types::TypeScript::MonitorOverflow(cx, script, pc);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-ModOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
+ModOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
+             Value *res)
 {
     int32_t l, r;
     if (lhs.isInt32() && rhs.isInt32() &&
         (l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) {
         int32_t mod = l % r;
         res->setInt32(mod);
         return true;
     }
 
     double d1, d2;
     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
         return false;
 
     res->setNumber(NumberMod(d1, d2));
-    types::TypeScript::MonitorOverflow(cx);
+    types::TypeScript::MonitorOverflow(cx, script, pc);
     return true;
 }
 
 static inline bool
 FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp, Value *vp)
 {
     int32_t i_;
     if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
@@ -899,25 +904,26 @@ BitRsh(JSContext *cx, const Value &lhs, 
     int32_t left, right;
     if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right))
         return false;
     *out = left >> (right & 31);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-UrshOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *out)
+UrshOperation(JSContext *cx, HandleScript script, jsbytecode *pc, const Value &lhs, const Value &rhs,
+              Value *out)
 {
     uint32_t left;
     int32_t  right;
     if (!ToUint32(cx, lhs, &left) || !ToInt32(cx, rhs, &right))
         return false;
     left >>= right & 31;
     if (!out->setNumber(uint32_t(left)))
-        types::TypeScript::MonitorOverflow(cx);
+        types::TypeScript::MonitorOverflow(cx, script, pc);
     return true;
 }
 
 #undef RELATIONAL_OP
 
 }  /* namespace js */
 
 #endif /* jsinterpinlines_h__ */