Bug 1116591 - Make every MIR opcode's typePolicy() member function consult op::thisTypePolicy(), never the global thisTypePolicy() method. r=nbp
authorJeff Walden <jwalden@mit.edu>
Wed, 31 Dec 2014 13:51:15 -0600
changeset 247979 d9557e125ac38a0701f75037514466c54e5849ba
parent 247978 d3a71d1c2180c0ebf2e0991c992eb93b43dac16e
child 247980 1298539468f2d22f36603d78e8e8f94e9c821d61
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1116591
milestone37.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 1116591 - Make every MIR opcode's typePolicy() member function consult op::thisTypePolicy(), never the global thisTypePolicy() method. r=nbp
js/src/jit/MIR.h
js/src/jit/TypePolicy.cpp
js/src/jit/TypePolicy.h
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -974,17 +974,19 @@ class MAryInstruction : public MInstruct
     explicit MAryInstruction(const MAryInstruction<Arity> &other)
       : MInstruction(other)
     {
         for (int i = 0; i < (int) Arity; i++) // N.B. use |int| to avoid warnings when Arity == 0
             operands_[i].init(other.operands_[i].producer(), this);
     }
 };
 
-class MNullaryInstruction : public MAryInstruction<0>
+class MNullaryInstruction
+  : public MAryInstruction<0>,
+    public NoTypePolicy::Data
 { };
 
 class MUnaryInstruction : public MAryInstruction<1>
 {
   protected:
     explicit MUnaryInstruction(MDefinition *ins)
     {
         initOperand(0, ins);
@@ -1310,17 +1312,19 @@ class MConstant : public MNullaryInstruc
     void truncate();
 
     bool canProduceFloat32() const;
 
     ALLOW_CLONE(MConstant)
 };
 
 // Generic constructor of SIMD valuesX4.
-class MSimdValueX4 : public MQuaternaryInstruction
+class MSimdValueX4
+  : public MQuaternaryInstruction,
+    public NoTypePolicy::Data
 {
   protected:
     MSimdValueX4(MIRType type, MDefinition *x, MDefinition *y, MDefinition *z, MDefinition *w)
       : MQuaternaryInstruction(x, y, z, w)
     {
         MOZ_ASSERT(IsSimdType(type));
         MOZ_ASSERT(SimdTypeToLength(type) == 4);
         mozilla::DebugOnly<MIRType> scalarType = SimdTypeToScalarType(type);
@@ -1355,17 +1359,19 @@ class MSimdValueX4 : public MQuaternaryI
     }
 
     MDefinition *foldsTo(TempAllocator &alloc);
 
     ALLOW_CLONE(MSimdValueX4)
 };
 
 // Generic constructor of SIMD valuesX4.
-class MSimdSplatX4 : public MUnaryInstruction
+class MSimdSplatX4
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   protected:
     MSimdSplatX4(MIRType type, MDefinition *v)
       : MUnaryInstruction(v)
     {
         MOZ_ASSERT(IsSimdType(type));
         mozilla::DebugOnly<MIRType> scalarType = SimdTypeToScalarType(type);
         MOZ_ASSERT(scalarType == v->type());
@@ -1395,17 +1401,18 @@ class MSimdSplatX4 : public MUnaryInstru
     }
 
     MDefinition *foldsTo(TempAllocator &alloc);
 
     ALLOW_CLONE(MSimdSplatX4)
 };
 
 // A constant SIMD value.
-class MSimdConstant : public MNullaryInstruction
+class MSimdConstant
+  : public MNullaryInstruction
 {
     SimdConstant value_;
 
   protected:
     MSimdConstant(const SimdConstant &v, MIRType type) : value_(v) {
         MOZ_ASSERT(IsSimdType(type));
         setResultType(type);
         setMovable();
@@ -1430,17 +1437,19 @@ class MSimdConstant : public MNullaryIns
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     ALLOW_CLONE(MSimdConstant)
 };
 
 // Converts all lanes of a given vector into the type of another vector
-class MSimdConvert : public MUnaryInstruction
+class MSimdConvert
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MSimdConvert(MDefinition *obj, MIRType fromType, MIRType toType)
       : MUnaryInstruction(obj)
     {
         MOZ_ASSERT(IsSimdType(obj->type()) && fromType == obj->type());
         MOZ_ASSERT(IsSimdType(toType));
         setResultType(toType);
     }
@@ -1458,17 +1467,19 @@ class MSimdConvert : public MUnaryInstru
     }
     bool congruentTo(const MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     ALLOW_CLONE(MSimdConvert)
 };
 
 // Casts bits of a vector input to another SIMD type (doesn't generate code).
-class MSimdReinterpretCast : public MUnaryInstruction
+class MSimdReinterpretCast
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MSimdReinterpretCast(MDefinition *obj, MIRType fromType, MIRType toType)
       : MUnaryInstruction(obj)
     {
         MOZ_ASSERT(IsSimdType(obj->type()) && fromType == obj->type());
         MOZ_ASSERT(IsSimdType(toType));
         setResultType(toType);
     }
@@ -1486,17 +1497,19 @@ class MSimdReinterpretCast : public MUna
     }
     bool congruentTo(const MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     ALLOW_CLONE(MSimdReinterpretCast)
 };
 
 // Extracts a lane element from a given vector type, given by its lane symbol.
-class MSimdExtractElement : public MUnaryInstruction
+class MSimdExtractElement
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   protected:
     SimdLane lane_;
 
     MSimdExtractElement(MDefinition *obj, MIRType type, SimdLane lane)
       : MUnaryInstruction(obj), lane_(lane)
     {
         MOZ_ASSERT(IsSimdType(obj->type()));
@@ -1528,17 +1541,19 @@ class MSimdExtractElement : public MUnar
         if (other->lane_ != lane_)
             return false;
         return congruentIfOperandsEqual(other);
     }
     ALLOW_CLONE(MSimdExtractElement)
 };
 
 // Replaces the datum in the given lane by a scalar value of the same type.
-class MSimdInsertElement : public MBinaryInstruction
+class MSimdInsertElement
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     SimdLane lane_;
 
     MSimdInsertElement(MDefinition *vec, MDefinition *val, MIRType type, SimdLane lane)
       : MBinaryInstruction(vec, val), lane_(lane)
     {
         MOZ_ASSERT(IsSimdType(type) && vec->type() == type);
@@ -1578,17 +1593,19 @@ class MSimdInsertElement : public MBinar
     bool congruentTo(const MDefinition *ins) const {
         return binaryCongruentTo(ins) && lane_ == ins->toSimdInsertElement()->lane();
     }
 
     ALLOW_CLONE(MSimdInsertElement)
 };
 
 // Extracts the sign bits from a given vector, returning an MIRType_Int32.
-class MSimdSignMask : public MUnaryInstruction
+class MSimdSignMask
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   protected:
     explicit MSimdSignMask(MDefinition *obj)
       : MUnaryInstruction(obj)
     {
         MOZ_ASSERT(IsSimdType(obj->type()));
         setResultType(MIRType_Int32);
         setMovable();
@@ -1646,17 +1663,20 @@ class MSimdShuffleBase
     bool lanesMatch(uint32_t x, uint32_t y, uint32_t z, uint32_t w) const {
         return ((x << 0) | (y << 3) | (z << 6) | (w << 9)) == laneMask_;
     }
 };
 
 // Applies a shuffle operation to the input, putting the input lanes as
 // indicated in the output register's lanes. This implements the SIMD.js
 // "shuffle" function, that takes one vector and one mask.
-class MSimdSwizzle : public MUnaryInstruction, public MSimdShuffleBase
+class MSimdSwizzle
+  : public MUnaryInstruction,
+    public MSimdShuffleBase,
+    public NoTypePolicy::Data
 {
   protected:
     MSimdSwizzle(MDefinition *obj, MIRType type,
                  uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
       : MUnaryInstruction(obj), MSimdShuffleBase(laneX, laneY, laneZ, laneW, type)
     {
         MOZ_ASSERT(laneX < 4 && laneY < 4 && laneZ < 4 && laneW < 4);
         MOZ_ASSERT(IsSimdType(obj->type()));
@@ -1689,17 +1709,20 @@ class MSimdSwizzle : public MUnaryInstru
     MDefinition *foldsTo(TempAllocator &alloc);
 
     ALLOW_CLONE(MSimdSwizzle)
 };
 
 // Applies a shuffle operation to the inputs, selecting the 2 first lanes of the
 // output from lanes of the first input, and the 2 last lanes of the output from
 // lanes of the second input.
-class MSimdShuffle : public MBinaryInstruction, public MSimdShuffleBase
+class MSimdShuffle
+  : public MBinaryInstruction,
+    public MSimdShuffleBase,
+    public NoTypePolicy::Data
 {
     MSimdShuffle(MDefinition *lhs, MDefinition *rhs, MIRType type,
                  uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
       : MBinaryInstruction(lhs, rhs), MSimdShuffleBase(laneX, laneY, laneZ, laneW, lhs->type())
     {
         MOZ_ASSERT(laneX < 8 && laneY < 8 && laneZ < 8 && laneW < 8);
         MOZ_ASSERT(IsSimdType(lhs->type()));
         MOZ_ASSERT(IsSimdType(rhs->type()));
@@ -1745,17 +1768,19 @@ class MSimdShuffle : public MBinaryInstr
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     ALLOW_CLONE(MSimdShuffle)
 };
 
-class MSimdUnaryArith : public MUnaryInstruction
+class MSimdUnaryArith
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   public:
     enum Operation {
         abs,
         neg,
         not_,
         reciprocal,
         reciprocalSqrt,
@@ -1794,17 +1819,19 @@ class MSimdUnaryArith : public MUnaryIns
     }
 
     ALLOW_CLONE(MSimdUnaryArith);
 };
 
 // Compares each value of a SIMD vector to each corresponding lane's value of
 // another SIMD vector, and returns a int32x4 vector containing the results of
 // the comparison: all bits are set to 1 if the comparison is true, 0 otherwise.
-class MSimdBinaryComp : public MBinaryInstruction
+class MSimdBinaryComp
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   public:
     enum Operation {
         greaterThan,
         greaterThanOrEqual,
         lessThan,
         lessThanOrEqual,
         equal,
@@ -1873,17 +1900,19 @@ class MSimdBinaryComp : public MBinaryIn
         if (!binaryCongruentTo(ins))
             return false;
         return operation_ == ins->toSimdBinaryComp()->operation();
     }
 
     ALLOW_CLONE(MSimdBinaryComp)
 };
 
-class MSimdBinaryArith : public MBinaryInstruction
+class MSimdBinaryArith
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   public:
     enum Operation {
         Add,
         Sub,
         Mul,
         Div,
         Min,
@@ -1940,17 +1969,19 @@ class MSimdBinaryArith : public MBinaryI
         if (!binaryCongruentTo(ins))
             return false;
         return operation_ == ins->toSimdBinaryArith()->operation();
     }
 
     ALLOW_CLONE(MSimdBinaryArith)
 };
 
-class MSimdBinaryBitwise : public MBinaryInstruction
+class MSimdBinaryBitwise
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   public:
     enum Operation {
         and_,
         or_,
         xor_
     };
 
@@ -1986,17 +2017,19 @@ class MSimdBinaryBitwise : public MBinar
         if (!binaryCongruentTo(ins))
             return false;
         return operation_ == ins->toSimdBinaryBitwise()->operation();
     }
 
     ALLOW_CLONE(MSimdBinaryBitwise)
 };
 
-class MSimdShift : public MBinaryInstruction
+class MSimdShift
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   public:
     enum Operation {
         lsh,
         rsh,
         ursh
     };
 
@@ -2029,17 +2062,19 @@ class MSimdShift : public MBinaryInstruc
         if (!binaryCongruentTo(ins))
             return false;
         return operation_ == ins->toSimdShift()->operation();
     }
 
     ALLOW_CLONE(MSimdShift)
 };
 
-class MSimdSelect : public MTernaryInstruction
+class MSimdSelect
+  : public MTernaryInstruction,
+    public NoTypePolicy::Data
 {
     bool isElementWise_;
 
     MSimdSelect(MDefinition *mask, MDefinition *lhs, MDefinition *rhs, MIRType type,
                 bool isElementWise)
       : MTernaryInstruction(mask, lhs, rhs), isElementWise_(isElementWise)
     {
         MOZ_ASSERT(IsSimdType(type));
@@ -2367,17 +2402,19 @@ class MAryControlInstruction : public MC
         return successors_[i];
     }
     void replaceSuccessor(size_t i, MBasicBlock *succ) MOZ_FINAL MOZ_OVERRIDE {
         successors_[i] = succ;
     }
 };
 
 // Jump to the start of another basic block.
-class MGoto : public MAryControlInstruction<0, 1>
+class MGoto
+  : public MAryControlInstruction<0, 1>,
+    public NoTypePolicy::Data
 {
     explicit MGoto(MBasicBlock *target) {
         setSuccessor(0, target);
     }
 
   public:
     INSTRUCTION_HEADER(Goto)
     static MGoto *New(TempAllocator &alloc, MBasicBlock *target);
@@ -2461,17 +2498,18 @@ class MTest
     }
 #endif
 };
 
 // Equivalent to MTest(true, successor, fake), except without the foldsTo
 // method. This allows IonBuilder to insert fake CFG edges to magically protect
 // control flow for try-catch blocks.
 class MGotoWithFake
-  : public MAryControlInstruction<0, 2>
+  : public MAryControlInstruction<0, 2>,
+    public NoTypePolicy::Data
 {
     MGotoWithFake(MBasicBlock *successor, MBasicBlock *fake)
     {
         setSuccessor(0, successor);
         setSuccessor(1, fake);
     }
 
   public:
@@ -2574,17 +2612,19 @@ class AlwaysTenured
 
 typedef AlwaysTenured<JSObject*> AlwaysTenuredObject;
 typedef AlwaysTenured<NativeObject*> AlwaysTenuredNativeObject;
 typedef AlwaysTenured<JSFunction*> AlwaysTenuredFunction;
 typedef AlwaysTenured<JSScript*> AlwaysTenuredScript;
 typedef AlwaysTenured<PropertyName*> AlwaysTenuredPropertyName;
 typedef AlwaysTenured<Shape*> AlwaysTenuredShape;
 
-class MNewArray : public MUnaryInstruction
+class MNewArray
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     // Number of space to allocate for the array.
     uint32_t count_;
 
     // Heap where the array should be allocated.
     gc::InitialHeap initialHeap_;
     // Allocate space at initialization or not
@@ -2729,17 +2769,19 @@ class MNewArrayDynamicLength
         return initialHeap_;
     }
 
     virtual AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
-class MNewObject : public MUnaryInstruction
+class MNewObject
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     gc::InitialHeap initialHeap_;
     bool templateObjectIsClassPrototype_;
 
     MNewObject(types::CompilerConstraintList *constraints, MConstant *templateConst,
                gc::InitialHeap initialHeap, bool templateObjectIsClassPrototype)
       : MUnaryInstruction(templateConst),
         initialHeap_(initialHeap),
@@ -2790,17 +2832,19 @@ class MNewObject : public MUnaryInstruct
     bool canRecoverOnBailout() const {
         // The template object can safely be used in the recover instruction
         // because it can never be mutated by any other function execution.
         return true;
     }
 };
 
 // Could be allocating either a new array or a new object.
-class MNewPar : public MUnaryInstruction
+class MNewPar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     AlwaysTenuredNativeObject templateObject_;
 
     MNewPar(MDefinition *cx, NativeObject *templateObject)
       : MUnaryInstruction(cx),
         templateObject_(templateObject)
     {
         setResultType(MIRType_Object);
@@ -3499,31 +3543,35 @@ class MBail : public MNullaryInstruction
         return AliasSet::None();
     }
 
     BailoutKind bailoutKind() const {
         return bailoutKind_;
     }
 };
 
-class MUnreachable : public MAryControlInstruction<0, 0>
+class MUnreachable
+  : public MAryControlInstruction<0, 0>,
+    public NoTypePolicy::Data
 {
   public:
     INSTRUCTION_HEADER(Unreachable)
 
     static MUnreachable *New(TempAllocator &alloc) {
         return new(alloc) MUnreachable();
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
-class MAssertFloat32 : public MUnaryInstruction
+class MAssertFloat32
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   protected:
     bool mustBeFloat32_;
 
     MAssertFloat32(MDefinition *value, bool mustBeFloat32)
       : MUnaryInstruction(value), mustBeFloat32_(mustBeFloat32)
     {
     }
@@ -3821,17 +3869,19 @@ class MCompare
         if (!binaryCongruentTo(ins))
             return false;
         return compareType() == ins->toCompare()->compareType() &&
                jsop() == ins->toCompare()->jsop();
     }
 };
 
 // Takes a typed value and returns an untyped value.
-class MBox : public MUnaryInstruction
+class MBox
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MBox(TempAllocator &alloc, MDefinition *ins)
       : MUnaryInstruction(ins)
     {
         setResultType(MIRType_Value);
         if (ins->resultTypeSet()) {
             setResultTypeSet(ins->resultTypeSet());
         } else if (ins->type() != MIRType_Value) {
@@ -4025,17 +4075,18 @@ class MGuardString
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 class MAssertRange
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     // This is the range checked by the assertion. Don't confuse this with the
     // range_ member or the range() accessor. Since MAssertRange doesn't return
     // a value, it doesn't use those.
     const Range *assertedRange_;
 
     MAssertRange(MDefinition *ins, const Range *assertedRange)
       : MUnaryInstruction(ins), assertedRange_(assertedRange)
@@ -4061,17 +4112,18 @@ class MAssertRange
     }
 
     void printOpcode(FILE *fp) const;
 };
 
 // Caller-side allocation of |this| for |new|:
 // Given a templateobject, construct |this| for JSOP_NEW
 class MCreateThisWithTemplate
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     gc::InitialHeap initialHeap_;
 
     MCreateThisWithTemplate(types::CompilerConstraintList *constraints, MConstant *templateConst,
                             gc::InitialHeap initialHeap)
       : MUnaryInstruction(templateConst),
         initialHeap_(initialHeap)
     {
@@ -4472,17 +4524,18 @@ class MToFloat32
         return true;
     }
 
     ALLOW_CLONE(MToFloat32)
 };
 
 // Converts a uint32 to a double (coming from asm.js).
 class MAsmJSUnsignedToDouble
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MAsmJSUnsignedToDouble(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
@@ -4498,17 +4551,18 @@ class MAsmJSUnsignedToDouble
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Converts a uint32 to a float32 (coming from asm.js).
 class MAsmJSUnsignedToFloat32
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MAsmJSUnsignedToFloat32(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Float32);
         setMovable();
     }
 
@@ -6017,17 +6071,18 @@ class MConcat
     bool canRecoverOnBailout() const {
         return true;
     }
 
     ALLOW_CLONE(MConcat)
 };
 
 class MConcatPar
-  : public MTernaryInstruction
+  : public MTernaryInstruction,
+    public NoTypePolicy::Data
 {
     MConcatPar(MDefinition *cx, MDefinition *left, MDefinition *right)
       : MTernaryInstruction(cx, left, right)
     {
         // Type analysis has already run, before replacing with the parallel
         // variant.
         MOZ_ASSERT(left->type() == MIRType_String && right->type() == MIRType_String);
 
@@ -6229,17 +6284,20 @@ class MLoadArrowThis
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         // An arrow function's lexical |this| value is immutable.
         return AliasSet::None();
     }
 };
 
-class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
+class MPhi MOZ_FINAL
+  : public MDefinition,
+    public InlineListNode<MPhi>,
+    public NoTypePolicy::Data
 {
     js::Vector<MUse, 2, JitAllocPolicy> inputs_;
 
     TruncateKind truncateKind_;
     bool hasBackedgeType_;
     bool triedToSpecialize_;
     bool isIterator_;
     bool canProduceFloat32_;
@@ -6412,17 +6470,19 @@ class MPhi MOZ_FINAL : public MDefinitio
 
     TruncateKind operandTruncateKind(size_t index) const;
     bool needTruncation(TruncateKind kind);
     void truncate();
 };
 
 // The goal of a Beta node is to split a def at a conditionally taken
 // branch, so that uses dominated by it have a different name.
-class MBeta : public MUnaryInstruction
+class MBeta
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     // This is the range induced by a comparison and branch in a preceding
     // block. Note that this does not reflect any range constraints from
     // the input value itself, so this value may differ from the range()
     // range after it is computed.
     const Range *comparison_;
 
@@ -6446,17 +6506,19 @@ class MBeta : public MUnaryInstruction
         return AliasSet::None();
     }
 
     void computeRange(TempAllocator &alloc);
 };
 
 // MIR representation of a Value on the OSR BaselineFrame.
 // The Value is indexed off of OsrFrameReg.
-class MOsrValue : public MUnaryInstruction
+class MOsrValue
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     ptrdiff_t frameOffset_;
 
     MOsrValue(MOsrEntry *entry, ptrdiff_t frameOffset)
       : MUnaryInstruction(entry),
         frameOffset_(frameOffset)
     {
@@ -6479,17 +6541,19 @@ class MOsrValue : public MUnaryInstructi
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // MIR representation of a JSObject scope chain pointer on the OSR BaselineFrame.
 // The pointer is indexed off of OsrFrameReg.
-class MOsrScopeChain : public MUnaryInstruction
+class MOsrScopeChain
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     explicit MOsrScopeChain(MOsrEntry *entry)
       : MUnaryInstruction(entry)
     {
         setResultType(MIRType_Object);
     }
 
@@ -6501,17 +6565,19 @@ class MOsrScopeChain : public MUnaryInst
 
     MOsrEntry *entry() {
         return getOperand(0)->toOsrEntry();
     }
 };
 
 // MIR representation of a JSObject ArgumentsObject pointer on the OSR BaselineFrame.
 // The pointer is indexed off of OsrFrameReg.
-class MOsrArgumentsObject : public MUnaryInstruction
+class MOsrArgumentsObject
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     explicit MOsrArgumentsObject(MOsrEntry *entry)
       : MUnaryInstruction(entry)
     {
         setResultType(MIRType_Object);
     }
 
@@ -6523,17 +6589,19 @@ class MOsrArgumentsObject : public MUnar
 
     MOsrEntry *entry() {
         return getOperand(0)->toOsrEntry();
     }
 };
 
 // MIR representation of the return value on the OSR BaselineFrame.
 // The Value is indexed off of OsrFrameReg.
-class MOsrReturnValue : public MUnaryInstruction
+class MOsrReturnValue
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     explicit MOsrReturnValue(MOsrEntry *entry)
       : MUnaryInstruction(entry)
     {
         setResultType(MIRType_Value);
     }
 
@@ -6544,29 +6612,32 @@ class MOsrReturnValue : public MUnaryIns
     }
 
     MOsrEntry *entry() {
         return getOperand(0)->toOsrEntry();
     }
 };
 
 // Check the current frame for over-recursion past the global stack limit.
-class MCheckOverRecursed : public MNullaryInstruction
+class MCheckOverRecursed
+  : public MNullaryInstruction
 {
   public:
     INSTRUCTION_HEADER(CheckOverRecursed)
 
     static MCheckOverRecursed *New(TempAllocator &alloc) {
         return new(alloc) MCheckOverRecursed();
     }
 };
 
 // Check the current frame for over-recursion past the global stack limit.
 // Uses the per-thread recursion limit.
-class MCheckOverRecursedPar : public MUnaryInstruction
+class MCheckOverRecursedPar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MCheckOverRecursedPar(MDefinition *cx)
       : MUnaryInstruction(cx)
     {
         setResultType(MIRType_None);
         setGuard();
         setMovable();
     }
@@ -6579,17 +6650,19 @@ class MCheckOverRecursedPar : public MUn
     }
 
     MDefinition *forkJoinContext() const {
         return getOperand(0);
     }
 };
 
 // Check for an interrupt (or rendezvous) in parallel mode.
-class MInterruptCheckPar : public MUnaryInstruction
+class MInterruptCheckPar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MInterruptCheckPar(MDefinition *cx)
       : MUnaryInstruction(cx)
     {
         setResultType(MIRType_None);
         setGuard();
     }
 
@@ -6624,17 +6697,18 @@ class MInterruptCheck : public MNullaryI
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Check whether we need to fire the interrupt handler at loop headers and
 // function prologues in asm.js. Generated only if we can't use implicit
 // interrupt checks with signal handlers.
-class MAsmJSInterruptCheck : public MNullaryInstruction
+class MAsmJSInterruptCheck
+  : public MNullaryInstruction
 {
     Label *interruptExit_;
     CallSiteDesc funcDesc_;
 
     MAsmJSInterruptCheck(Label *interruptExit, const CallSiteDesc &funcDesc)
       : interruptExit_(interruptExit), funcDesc_(funcDesc)
     {}
 
@@ -6699,17 +6773,19 @@ class MThrowUninitializedLexical : publi
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // If not defined, set a global variable to |undefined|.
-class MDefVar : public MUnaryInstruction
+class MDefVar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     AlwaysTenuredPropertyName name_; // Target name to be defined.
     unsigned attrs_; // Attributes to be set.
 
   private:
     MDefVar(PropertyName *name, unsigned attrs, MDefinition *scopeChain)
       : MUnaryInstruction(scopeChain),
         name_(name),
@@ -6735,17 +6811,19 @@ class MDefVar : public MUnaryInstruction
     MDefinition *scopeChain() const {
         return getOperand(0);
     }
     bool possiblyCalls() const {
         return true;
     }
 };
 
-class MDefFun : public MUnaryInstruction
+class MDefFun
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     AlwaysTenuredFunction fun_;
 
   private:
     MDefFun(JSFunction *fun, MDefinition *scopeChain)
       : MUnaryInstruction(scopeChain),
         fun_(fun)
     {}
@@ -7256,17 +7334,18 @@ class MConstantElements : public MNullar
         return AliasSet::None();
     }
 
     ALLOW_CLONE(MConstantElements)
 };
 
 // Passes through an object's elements, after ensuring it is entirely doubles.
 class MConvertElementsToDoubles
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MConvertElementsToDoubles(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_Elements);
     }
@@ -7370,17 +7449,18 @@ class MMaybeCopyElementsForWrite
         return false;
     }
 #endif
 
 };
 
 // Load the initialized length from an elements header.
 class MInitializedLength
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MInitializedLength(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
@@ -7404,17 +7484,18 @@ class MInitializedLength
     void computeRange(TempAllocator &alloc);
 
     ALLOW_CLONE(MInitializedLength)
 };
 
 // Store to the initialized length in an elements header. Note the input is an
 // *index*, one less than the desired length.
 class MSetInitializedLength
-  : public MAryInstruction<2>
+  : public MAryInstruction<2>,
+    public NoTypePolicy::Data
 {
     MSetInitializedLength(MDefinition *elements, MDefinition *index) {
         initOperand(0, elements);
         initOperand(1, index);
     }
 
   public:
     INSTRUCTION_HEADER(SetInitializedLength)
@@ -7433,17 +7514,18 @@ class MSetInitializedLength
         return AliasSet::Store(AliasSet::ObjectFields);
     }
 
     ALLOW_CLONE(MSetInitializedLength)
 };
 
 // Load the array length from an elements header.
 class MArrayLength
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MArrayLength(MDefinition *elements)
       : MUnaryInstruction(elements)
     {
         setResultType(MIRType_Int32);
         setMovable();
     }
 
@@ -7467,17 +7549,18 @@ class MArrayLength
     void computeRange(TempAllocator &alloc);
 
     ALLOW_CLONE(MArrayLength)
 };
 
 // Store to the length in an elements header. Note the input is an *index*, one
 // less than the desired length.
 class MSetArrayLength
-  : public MAryInstruction<2>
+  : public MAryInstruction<2>,
+    public NoTypePolicy::Data
 {
     MSetArrayLength(MDefinition *elements, MDefinition *index) {
         initOperand(0, elements);
         initOperand(1, index);
     }
 
   public:
     INSTRUCTION_HEADER(SetArrayLength)
@@ -7603,17 +7686,18 @@ class MTypedObjectElements
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Inlined version of the js::SetTypedObjectOffset() intrinsic.
 class MSetTypedObjectOffset
-  : public MBinaryInstruction
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
   private:
     MSetTypedObjectOffset(MDefinition *object, MDefinition *offset)
       : MBinaryInstruction(object, offset)
     {
         MOZ_ASSERT(object->type() == MIRType_Object);
         MOZ_ASSERT(offset->type() == MIRType_Int32);
         setResultType(MIRType_None);
@@ -7706,17 +7790,18 @@ class MNot
         return true;
     }
 };
 
 // Bailout if index + minimum < 0 or index + maximum >= length. The length used
 // in a bounds check must not be negative, or the wrong result may be computed
 // (unsigned comparisons may be used).
 class MBoundsCheck
-  : public MBinaryInstruction
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
     // Range over which to perform the bounds check, may be modified by GVN.
     int32_t minimum_;
     int32_t maximum_;
 
     MBoundsCheck(MDefinition *index, MDefinition *length)
       : MBinaryInstruction(index, length), minimum_(0), maximum_(0)
     {
@@ -7767,17 +7852,18 @@ class MBoundsCheck
     }
     void computeRange(TempAllocator &alloc);
 
     ALLOW_CLONE(MBoundsCheck)
 };
 
 // Bailout if index < minimum.
 class MBoundsCheckLower
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     int32_t minimum_;
     bool fallible_;
 
     explicit MBoundsCheckLower(MDefinition *index)
       : MUnaryInstruction(index), minimum_(0), fallible_(true)
     {
         setGuard();
@@ -8901,17 +8987,19 @@ class MStoreTypedArrayElementStatic :
     bool canConsumeFloat32(MUse *use) const {
         return use == getUseFor(1) && viewType() == Scalar::Float32;
     }
     void collectRangeInfoPreTrunc();
 };
 
 // Compute an "effective address", i.e., a compound computation of the form:
 //   base + index * scale + displacement
-class MEffectiveAddress : public MBinaryInstruction
+class MEffectiveAddress
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
     MEffectiveAddress(MDefinition *base, MDefinition *index, Scale scale, int32_t displacement)
       : MBinaryInstruction(base, index), scale_(scale), displacement_(displacement)
     {
         MOZ_ASSERT(base->type() == MIRType_Int32);
         MOZ_ASSERT(index->type() == MIRType_Int32);
         setMovable();
         setResultType(MIRType_Int32);
@@ -9941,17 +10029,18 @@ class MForkJoinContext
     bool possiblyCalls() const {
         return true;
     }
 };
 
 // Calls the ForkJoinGetSlice stub, used for inlining the eponymous intrinsic.
 // Only applicable in ParallelExecution.
 class MForkJoinGetSlice
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MForkJoinGetSlice(MDefinition *cx)
       : MUnaryInstruction(cx)
     {
         setResultType(MIRType_Int32);
     }
 
   public:
@@ -10888,17 +10977,18 @@ class MIteratorMore
     }
 
     MDefinition *iterator() const {
         return getOperand(0);
     }
 };
 
 class MIsNoIter
-  : public MUnaryInstruction
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     explicit MIsNoIter(MDefinition *def)
       : MUnaryInstruction(def)
     {
         setResultType(MIRType_Boolean);
         setMovable();
     }
 
@@ -11551,17 +11641,19 @@ class MNewRunOnceCallObject : public MNe
 
     static MNewRunOnceCallObject *
     New(TempAllocator &alloc, CallObject *templateObj)
     {
         return new(alloc) MNewRunOnceCallObject(templateObj);
     }
 };
 
-class MNewCallObjectPar : public MUnaryInstruction
+class MNewCallObjectPar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     AlwaysTenured<CallObject*> templateObj_;
 
     MNewCallObjectPar(MDefinition *cx, CallObject *templateObj)
         : MUnaryInstruction(cx),
           templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
@@ -11670,17 +11762,19 @@ class MEnclosingScope : public MLoadFixe
         // ScopeObject reserved slots are immutable.
         return AliasSet::None();
     }
 };
 
 // Creates a dense array of the given length.
 //
 // Note: the template object should be an *empty* dense array!
-class MNewDenseArrayPar : public MBinaryInstruction
+class MNewDenseArrayPar
+  : public MBinaryInstruction,
+    public NoTypePolicy::Data
 {
     AlwaysTenured<ArrayObject*> templateObject_;
 
     MNewDenseArrayPar(MDefinition *cx, MDefinition *length, ArrayObject *templateObject)
       : MBinaryInstruction(cx, length),
         templateObject_(templateObject)
     {
         MOZ_ASSERT(length->type() == MIRType_Int32);
@@ -12199,17 +12293,19 @@ class MDebugger : public MNullaryInstruc
   public:
     INSTRUCTION_HEADER(Debugger);
 
     static MDebugger *New(TempAllocator &alloc) {
         return new(alloc) MDebugger();
     }
 };
 
-class MAsmJSNeg : public MUnaryInstruction
+class MAsmJSNeg
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MAsmJSNeg(MDefinition *op, MIRType type)
       : MUnaryInstruction(op)
     {
         setResultType(type);
         setMovable();
     }
 
@@ -12230,17 +12326,20 @@ class MAsmJSHeapAccess
       : viewType_(vt), needsBoundsCheck_(needsBoundsCheck)
     {}
 
     Scalar::Type viewType() const { return viewType_; }
     bool needsBoundsCheck() const { return needsBoundsCheck_; }
     void removeBoundsCheck() { needsBoundsCheck_ = false; }
 };
 
-class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
+class MAsmJSLoadHeap
+  : public MUnaryInstruction,
+    public MAsmJSHeapAccess,
+    public NoTypePolicy::Data
 {
     MemoryBarrierBits barrierBefore_;
     MemoryBarrierBits barrierAfter_;
 
     MAsmJSLoadHeap(Scalar::Type vt, MDefinition *ptr, bool needsBoundsCheck,
                    MemoryBarrierBits before, MemoryBarrierBits after)
       : MUnaryInstruction(ptr),
         MAsmJSHeapAccess(vt, needsBoundsCheck),
@@ -12296,17 +12395,20 @@ class MAsmJSLoadHeap : public MUnaryInst
 
     bool congruentTo(const MDefinition *ins) const;
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::AsmJSHeap);
     }
     bool mightAlias(const MDefinition *def) const;
 };
 
-class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
+class MAsmJSStoreHeap
+  : public MBinaryInstruction,
+    public MAsmJSHeapAccess,
+    public NoTypePolicy::Data
 {
     MemoryBarrierBits barrierBefore_;
     MemoryBarrierBits barrierAfter_;
 
     MAsmJSStoreHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *v, bool needsBoundsCheck,
                     MemoryBarrierBits before, MemoryBarrierBits after)
       : MBinaryInstruction(ptr, v),
         MAsmJSHeapAccess(vt, needsBoundsCheck),
@@ -12334,17 +12436,20 @@ class MAsmJSStoreHeap : public MBinaryIn
     MemoryBarrierBits barrierBefore() const { return barrierBefore_; }
     MemoryBarrierBits barrierAfter() const { return barrierAfter_; }
 
     AliasSet getAliasSet() const {
         return AliasSet::Store(AliasSet::AsmJSHeap);
     }
 };
 
-class MAsmJSCompareExchangeHeap : public MTernaryInstruction, public MAsmJSHeapAccess
+class MAsmJSCompareExchangeHeap
+  : public MTernaryInstruction,
+    public MAsmJSHeapAccess,
+    public NoTypePolicy::Data
 {
     MAsmJSCompareExchangeHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *oldv, MDefinition *newv,
                               bool needsBoundsCheck)
         : MTernaryInstruction(ptr, oldv, newv),
           MAsmJSHeapAccess(vt, needsBoundsCheck)
     {
         setGuard();             // Not removable
         setResultType(MIRType_Int32);
@@ -12364,17 +12469,20 @@ class MAsmJSCompareExchangeHeap : public
     MDefinition *oldValue() const { return getOperand(1); }
     MDefinition *newValue() const { return getOperand(2); }
 
     AliasSet getAliasSet() const {
         return AliasSet::Store(AliasSet::AsmJSHeap);
     }
 };
 
-class MAsmJSAtomicBinopHeap : public MBinaryInstruction, public MAsmJSHeapAccess
+class MAsmJSAtomicBinopHeap
+  : public MBinaryInstruction,
+    public MAsmJSHeapAccess,
+    public NoTypePolicy::Data
 {
     AtomicOp op_;
 
     MAsmJSAtomicBinopHeap(AtomicOp op, Scalar::Type vt, MDefinition *ptr, MDefinition *v,
                           bool needsBoundsCheck)
         : MBinaryInstruction(ptr, v),
           MAsmJSHeapAccess(vt, needsBoundsCheck),
           op_(op)
@@ -12431,17 +12539,19 @@ class MAsmJSLoadGlobalVar : public MNull
 
     AliasSet getAliasSet() const {
         return isConstant_ ? AliasSet::None() : AliasSet::Load(AliasSet::AsmJSGlobalVar);
     }
 
     bool mightAlias(const MDefinition *def) const;
 };
 
-class MAsmJSStoreGlobalVar : public MUnaryInstruction
+class MAsmJSStoreGlobalVar
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MAsmJSStoreGlobalVar(unsigned globalDataOffset, MDefinition *v)
       : MUnaryInstruction(v), globalDataOffset_(globalDataOffset)
     {}
 
     unsigned globalDataOffset_;
 
   public:
@@ -12454,17 +12564,19 @@ class MAsmJSStoreGlobalVar : public MUna
     unsigned globalDataOffset() const { return globalDataOffset_; }
     MDefinition *value() const { return getOperand(0); }
 
     AliasSet getAliasSet() const {
         return AliasSet::Store(AliasSet::AsmJSGlobalVar);
     }
 };
 
-class MAsmJSLoadFuncPtr : public MUnaryInstruction
+class MAsmJSLoadFuncPtr
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MAsmJSLoadFuncPtr(unsigned globalDataOffset, MDefinition *index)
       : MUnaryInstruction(index), globalDataOffset_(globalDataOffset)
     {
         setResultType(MIRType_Pointer);
     }
 
     unsigned globalDataOffset_;
@@ -12524,39 +12636,45 @@ class MAsmJSParameter : public MNullaryI
 
     static MAsmJSParameter *New(TempAllocator &alloc, ABIArg abi, MIRType mirType) {
         return new(alloc) MAsmJSParameter(abi, mirType);
     }
 
     ABIArg abi() const { return abi_; }
 };
 
-class MAsmJSReturn : public MAryControlInstruction<1, 0>
+class MAsmJSReturn
+  : public MAryControlInstruction<1, 0>,
+    public NoTypePolicy::Data
 {
     explicit MAsmJSReturn(MDefinition *ins) {
         initOperand(0, ins);
     }
 
   public:
     INSTRUCTION_HEADER(AsmJSReturn);
     static MAsmJSReturn *New(TempAllocator &alloc, MDefinition *ins) {
         return new(alloc) MAsmJSReturn(ins);
     }
 };
 
-class MAsmJSVoidReturn : public MAryControlInstruction<0, 0>
+class MAsmJSVoidReturn
+  : public MAryControlInstruction<0, 0>,
+    public NoTypePolicy::Data
 {
   public:
     INSTRUCTION_HEADER(AsmJSVoidReturn);
     static MAsmJSVoidReturn *New(TempAllocator &alloc) {
         return new(alloc) MAsmJSVoidReturn();
     }
 };
 
-class MAsmJSPassStackArg : public MUnaryInstruction
+class MAsmJSPassStackArg
+  : public MUnaryInstruction,
+    public NoTypePolicy::Data
 {
     MAsmJSPassStackArg(uint32_t spOffset, MDefinition *ins)
       : MUnaryInstruction(ins),
         spOffset_(spOffset)
     {}
 
     uint32_t spOffset_;
 
@@ -12571,17 +12689,19 @@ class MAsmJSPassStackArg : public MUnary
     void incrementOffset(uint32_t inc) {
         spOffset_ += inc;
     }
     MDefinition *arg() const {
         return getOperand(0);
     }
 };
 
-class MAsmJSCall MOZ_FINAL : public MVariadicInstruction
+class MAsmJSCall MOZ_FINAL
+  : public MVariadicInstruction,
+    public NoTypePolicy::Data
 {
   public:
     class Callee {
       public:
         enum Which { Internal, Dynamic, Builtin };
       private:
         Which which_;
         union {
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -1043,23 +1043,21 @@ namespace jit {
     TEMPLATE_TYPE_POLICY_LIST(template<> DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
 #undef DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_
 
 }
 }
 
 namespace {
 
-// Default function visited by the C++ lookup rules, if the MIR Instruction does
-// not inherit from a TypePolicy::Data type.
-static TypePolicy *
-thisTypePolicy()
-{
-    return nullptr;
-}
+// For extra-good measure in case an unqualified use is ever introduced.  (The
+// main use in the macro below is explicitly qualified so as not to consult
+// this scope and find this function.)
+inline TypePolicy *
+thisTypePolicy() MOZ_DELETE;
 
 static MIRType
 thisTypeSpecialization()
 {
     MOZ_CRASH("TypeSpecialization lacks definition of thisTypeSpecialization.");
 }
 
 }
@@ -1068,26 +1066,25 @@ TypePolicy *
 MGetElementCache::thisTypePolicy()
 {
     if (type() == MIRType_Value)
         return PolicyV.thisTypePolicy();
     return PolicyT.thisTypePolicy();
 }
 
 // For each MIR Instruction, this macro define the |typePolicy| method which is
-// using the |thisTypePolicy| function.  We use the C++ lookup rules to select
-// the right |thisTypePolicy| member.  The |thisTypePolicy| function can either
-// be a member of the MIR Instruction, such as done for MGetElementCache, or a
-// member inherited from the TypePolicy::Data structure, or at last the global
-// with the same name if the instruction has no TypePolicy.
+// using the |thisTypePolicy| method.  The |thisTypePolicy| method is either a
+// member of the MIR Instruction, such as with MGetElementCache, a member
+// inherited from the TypePolicy::Data structure, or a member inherited from
+// NoTypePolicy if the MIR instruction has no type policy.
 #define DEFINE_MIR_TYPEPOLICY_MEMBERS_(op)      \
     TypePolicy *                                \
     js::jit::M##op::typePolicy()                \
     {                                           \
-        return thisTypePolicy();                \
+        return M##op::thisTypePolicy();         \
     }                                           \
                                                 \
     MIRType                                     \
     js::jit::M##op::typePolicySpecialization()  \
     {                                           \
         return thisTypeSpecialization();        \
     }
 
--- a/js/src/jit/TypePolicy.h
+++ b/js/src/jit/TypePolicy.h
@@ -60,16 +60,27 @@ struct TypeSpecializationData
 #define INHERIT_DATA_(DATA_TYPE)                        \
     struct Data : public DATA_TYPE                      \
     {                                                   \
         static TypePolicy *thisTypePolicy();            \
     }
 
 #define SPECIALIZATION_DATA_ INHERIT_DATA_(TypeSpecializationData)
 
+class NoTypePolicy
+{
+  public:
+    struct Data
+    {
+        static TypePolicy *thisTypePolicy() {
+            return nullptr;
+        }
+    };
+};
+
 class BoxInputsPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     SPECIALIZATION_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
     virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }