Bug 836774 - Prevent objects/strings from flowing to an MToDouble, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 01 Feb 2013 06:44:17 -0700
changeset 130458 6123591fafb8ed4c3245ed4c792105e97c0aa813
parent 130457 71021f2374545b00ab23786060e3f7633427bd6b
child 130459 8ee65e7da665d8a0802479d242e9a1750a1e23ee
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs836774
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 836774 - Prevent objects/strings from flowing to an MToDouble, r=jandem.
js/src/ion/Lowering.cpp
js/src/ion/MIR.h
js/src/ion/TypePolicy.cpp
js/src/ion/TypePolicy.h
js/src/jit-test/tests/ion/bug836774.js
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1229,17 +1229,17 @@ LIRGenerator::visitToDouble(MToDouble *c
       }
 
       case MIRType_Double:
         return redefine(convert, opd);
 
       default:
         // Objects might be effectful.
         // Strings are complicated - we don't handle them yet.
-        JS_ASSERT(!"unexpected type");
+        JS_NOT_REACHED("unexpected type");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitToInt32(MToInt32 *convert)
 {
     MDefinition *opd = convert->input();
@@ -1276,17 +1276,17 @@ LIRGenerator::visitToInt32(MToInt32 *con
         IonSpew(IonSpew_Abort, "Object to Int32 not supported yet.");
         return false;
 
       case MIRType_Undefined:
         IonSpew(IonSpew_Abort, "Undefined coerces to NaN, not int32_t.");
         return false;
 
       default:
-        JS_ASSERT(!"unexpected type");
+        JS_NOT_REACHED("unexpected type");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitTruncateToInt32(MTruncateToInt32 *truncate)
 {
     MDefinition *opd = truncate->input();
@@ -1309,45 +1309,45 @@ LIRGenerator::visitTruncateToInt32(MTrun
         return redefine(truncate, opd);
 
       case MIRType_Double:
         return define(new LTruncateDToInt32(useRegister(opd), tempFloat()), truncate);
 
       default:
         // Objects might be effectful.
         // Strings are complicated - we don't handle them yet.
-        JS_ASSERT(!"unexpected type");
+        JS_NOT_REACHED("unexpected type");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitToString(MToString *ins)
 {
     MDefinition *opd = ins->input();
 
     switch (opd->type()) {
       case MIRType_Double:
       case MIRType_Null:
       case MIRType_Undefined:
       case MIRType_Boolean:
-        JS_ASSERT(!"NYI: Lower MToString");
+        JS_NOT_REACHED("NYI: Lower MToString");
         return false;
 
       case MIRType_Int32: {
         LIntToString *lir = new LIntToString(useRegister(opd));
 
         if (!define(lir, ins))
             return false;
         return assignSafepoint(lir, ins);
       }
 
       default:
         // Objects might be effectful. (see ToPrimitive)
-        JS_ASSERT(!"unexpected type");
+        JS_NOT_REACHED("unexpected type");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitRegExp(MRegExp *ins)
 {
     LRegExp *lir = new LRegExp();
@@ -1420,17 +1420,17 @@ bool
 LIRGenerator::visitLoadSlot(MLoadSlot *ins)
 {
     switch (ins->type()) {
       case MIRType_Value:
         return defineBox(new LLoadSlotV(useRegister(ins->slots())), ins);
 
       case MIRType_Undefined:
       case MIRType_Null:
-        JS_ASSERT(!"typed load must have a payload");
+        JS_NOT_REACHED("typed load must have a payload");
         return false;
 
       default:
         return define(new LLoadSlotT(useRegister(ins->slots())), ins);
     }
 }
 
 bool
@@ -1572,17 +1572,17 @@ LIRGenerator::visitNot(MNot *ins)
 
         LNotV *lir = new LNotV(tempFloat(), temp0, temp1);
         if (!useBox(lir, LNotV::Input, op))
             return false;
         return define(lir, ins);
       }
 
       default:
-        JS_ASSERT(!"Unexpected MIRType.");
+        JS_NOT_REACHED("Unexpected MIRType.");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitBoundsCheck(MBoundsCheck *ins)
 {
     LInstruction *check;
@@ -1633,17 +1633,17 @@ LIRGenerator::visitLoadElement(MLoadElem
         LLoadElementV *lir = new LLoadElementV(useRegister(ins->elements()),
                                                useRegisterOrConstant(ins->index()));
         if (ins->fallible() && !assignSnapshot(lir))
             return false;
         return defineBox(lir, ins);
       }
       case MIRType_Undefined:
       case MIRType_Null:
-        JS_ASSERT(!"typed load must have a payload");
+        JS_NOT_REACHED("typed load must have a payload");
         return false;
 
       default:
       {
         LLoadElementT *lir = new LLoadElementT(useRegister(ins->elements()),
                                                useRegisterOrConstant(ins->index()));
         if (ins->fallible() && !assignSnapshot(lir))
             return false;
@@ -1734,17 +1734,17 @@ LIRGenerator::visitArrayPopShift(MArrayP
     switch (ins->type()) {
       case MIRType_Value:
       {
         LArrayPopShiftV *lir = new LArrayPopShiftV(object, temp(), temp());
         return defineBox(lir, ins) && assignSafepoint(lir, ins);
       }
       case MIRType_Undefined:
       case MIRType_Null:
-        JS_ASSERT(!"typed load must have a payload");
+        JS_NOT_REACHED("typed load must have a payload");
         return false;
 
       default:
       {
         LArrayPopShiftT *lir = new LArrayPopShiftT(object, temp(), temp());
         return define(lir, ins) && assignSafepoint(lir, ins);
       }
     }
@@ -1830,17 +1830,17 @@ LIRGenerator::visitClampToUint8(MClampTo
       {
         LClampVToUint8 *lir = new LClampVToUint8(tempFloat());
         if (!useBox(lir, LClampVToUint8::Input, in))
             return false;
         return assignSnapshot(lir) && define(lir, ins);
       }
 
       default:
-        JS_ASSERT(!"unexpected type");
+        JS_NOT_REACHED("unexpected type");
         return false;
     }
 }
 
 bool
 LIRGenerator::visitLoadTypedArrayElementHole(MLoadTypedArrayElementHole *ins)
 {
     JS_ASSERT(ins->object()->type() == MIRType_Object);
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1917,32 +1917,37 @@ class MPassArg : public MUnaryInstructio
         return AliasSet::None();
     }
     void printOpcode(FILE *fp);
 };
 
 // Converts a primitive (either typed or untyped) to a double. If the input is
 // not primitive at runtime, a bailout occurs.
 class MToDouble
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public ToDoublePolicy
 {
     MToDouble(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(ToDouble)
     static MToDouble *New(MDefinition *def)
     {
         return new MToDouble(def);
     }
 
+    TypePolicy *typePolicy() {
+        return this;
+    }
+
     MDefinition *foldsTo(bool useValueNumbers);
     MDefinition *input() const {
         return getOperand(0);
     }
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
--- a/js/src/ion/TypePolicy.cpp
+++ b/js/src/ion/TypePolicy.cpp
@@ -346,16 +346,28 @@ BoxPolicy<Op>::staticAdjustInputs(MInstr
     ins->replaceOperand(Op, boxAt(ins, in));
     return true;
 }
 
 template bool BoxPolicy<0>::staticAdjustInputs(MInstruction *ins);
 template bool BoxPolicy<1>::staticAdjustInputs(MInstruction *ins);
 template bool BoxPolicy<2>::staticAdjustInputs(MInstruction *ins);
 
+bool
+ToDoublePolicy::staticAdjustInputs(MInstruction *ins)
+{
+    MDefinition *in = ins->getOperand(0);
+    if (in->type() != MIRType_Object && in->type() != MIRType_String)
+        return true;
+
+    in = boxAt(ins, in);
+    ins->replaceOperand(0, in);
+    return true;
+}
+
 template <unsigned Op>
 bool
 ObjectPolicy<Op>::staticAdjustInputs(MInstruction *ins)
 {
     MDefinition *in = ins->getOperand(Op);
     if (in->type() == MIRType_Object || in->type() == MIRType_Slots ||
         in->type() == MIRType_Elements)
     {
--- a/js/src/ion/TypePolicy.h
+++ b/js/src/ion/TypePolicy.h
@@ -133,16 +133,26 @@ class DoublePolicy : public BoxInputsPol
 {
   public:
     static bool staticAdjustInputs(MInstruction *def);
     bool adjustInputs(MInstruction *def) {
         return staticAdjustInputs(def);
     }
 };
 
+// Box objects or strings as an input to a ToDouble instruction.
+class ToDoublePolicy : public BoxInputsPolicy
+{
+  public:
+    static bool staticAdjustInputs(MInstruction *def);
+    bool adjustInputs(MInstruction *def) {
+        return staticAdjustInputs(def);
+    }
+};
+
 template <unsigned Op>
 class ObjectPolicy : public BoxInputsPolicy
 {
   public:
     static bool staticAdjustInputs(MInstruction *ins);
     bool adjustInputs(MInstruction *ins) {
         return staticAdjustInputs(ins);
     }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug836774.js
@@ -0,0 +1,3 @@
+
+x = ''.charCodeAt(NaN);
+evaluate("for each (var e in [{}, {}, {}, {}, x]) {}");