Bug 1116591 - Make all TypePolicy subclasses final to prevent the mistake of inheriting from one (rather than inheriting from its nested Data class). r=nbp
authorJeff Walden <jwalden@mit.edu>
Wed, 31 Dec 2014 13:51:15 -0600
changeset 247978 d3a71d1c2180c0ebf2e0991c992eb93b43dac16e
parent 247977 92c8c395677fad5a2579b4fba0c625fdd4ae237c
child 247979 d9557e125ac38a0701f75037514466c54e5849ba
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 all TypePolicy subclasses final to prevent the mistake of inheriting from one (rather than inheriting from its nested Data class). r=nbp
js/src/jit/IonAnalysis.cpp
js/src/jit/MIR.h
js/src/jit/TypePolicy.cpp
js/src/jit/TypePolicy.h
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1064,17 +1064,17 @@ TypeAnalyzer::adjustPhiInputs(MPhi *phi)
         if (in->type() == MIRType_Value)
             continue;
 
         if (in->isUnbox() && phi->typeIncludes(in->toUnbox()->input())) {
             // The input is being explicitly unboxed, so sneak past and grab
             // the original box.
             phi->replaceOperand(i, in->toUnbox()->input());
         } else {
-            MDefinition *box = BoxInputsPolicy::alwaysBoxAt(alloc(), in->block()->lastIns(), in);
+            MDefinition *box = AlwaysBoxAt(alloc(), in->block()->lastIns(), in);
             phi->replaceOperand(i, box);
         }
     }
 }
 
 bool
 TypeAnalyzer::adjustInputs(MDefinition *def)
 {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3977,17 +3977,19 @@ class MUnbox MOZ_FINAL : public MUnaryIn
         // Should only be called if we're already Infallible or TypeBarrier
         MOZ_ASSERT(mode() != Fallible);
         mode_ = Infallible;
     }
 
     ALLOW_CLONE(MUnbox)
 };
 
-class MGuardObject : public MUnaryInstruction, public SingleObjectPolicy::Data
+class MGuardObject
+  : public MUnaryInstruction,
+    public SingleObjectPolicy::Data
 {
     explicit MGuardObject(MDefinition *ins)
       : MUnaryInstruction(ins)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_Object);
     }
@@ -11392,17 +11394,19 @@ class MTypeBarrier
     }
 
     ALLOW_CLONE(MTypeBarrier)
 };
 
 // Like MTypeBarrier, guard that the value is in the given type set. This is
 // used before property writes to ensure the value being written is represented
 // in the property types for the object.
-class MMonitorTypes : public MUnaryInstruction, public BoxInputsPolicy::Data
+class MMonitorTypes
+  : public MUnaryInstruction,
+    public BoxInputsPolicy::Data
 {
     const types::TemporaryTypeSet *typeSet_;
     BarrierKind barrierKind_;
 
     MMonitorTypes(MDefinition *def, const types::TemporaryTypeSet *types, BarrierKind kind)
       : MUnaryInstruction(def),
         typeSet_(types),
         barrierKind_(kind)
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -22,56 +22,56 @@ EnsureOperandNotFloat32(TempAllocator &a
     if (in->type() == MIRType_Float32) {
         MToDouble *replace = MToDouble::New(alloc, in);
         def->block()->insertBefore(def, replace);
         def->replaceOperand(op, replace);
     }
 }
 
 MDefinition *
-BoxInputsPolicy::boxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand)
-{
-    if (operand->isUnbox())
-        return operand->toUnbox()->input();
-    return alwaysBoxAt(alloc, at, operand);
-}
-
-MDefinition *
-BoxInputsPolicy::alwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand)
+js::jit::AlwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand)
 {
     MDefinition *boxedOperand = operand;
     // Replace Float32 by double
     if (operand->type() == MIRType_Float32) {
         MInstruction *replace = MToDouble::New(alloc, operand);
         at->block()->insertBefore(at, replace);
         boxedOperand = replace;
     }
     MBox *box = MBox::New(alloc, boxedOperand);
     at->block()->insertBefore(at, box);
     return box;
 }
 
+static MDefinition *
+BoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand)
+{
+    if (operand->isUnbox())
+        return operand->toUnbox()->input();
+    return AlwaysBoxAt(alloc, at, operand);
+}
+
 bool
-BoxInputsPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
+BoxInputsPolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
         MDefinition *in = ins->getOperand(i);
         if (in->type() == MIRType_Value)
             continue;
-        ins->replaceOperand(i, boxAt(alloc, ins, in));
+        ins->replaceOperand(i, BoxAt(alloc, ins, in));
     }
     return true;
 }
 
 bool
 ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MIRType specialization = ins->typePolicySpecialization();
     if (specialization == MIRType_None)
-        return BoxInputsPolicy::adjustInputs(alloc, ins);
+        return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
 
     MOZ_ASSERT(ins->type() == MIRType_Double || ins->type() == MIRType_Int32 || ins->type() == MIRType_Float32);
 
     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
         MDefinition *in = ins->getOperand(i);
         if (in->type() == ins->type())
             continue;
 
@@ -109,17 +109,17 @@ ComparePolicy::adjustInputs(TempAllocato
             def->replaceOperand(i, replace);
         }
     }
 
     // Box inputs to get value
     if (compare->compareType() == MCompare::Compare_Unknown ||
         compare->compareType() == MCompare::Compare_Value)
     {
-        return BoxInputsPolicy::adjustInputs(alloc, def);
+        return BoxInputsPolicy::staticAdjustInputs(alloc, def);
     }
 
     // Compare_Boolean specialization is done for "Anything === Bool"
     // If the LHS is boolean, we set the specialization to Compare_Int32.
     // This matches other comparisons of the form bool === bool and
     // generated code of Compare_Int32 is more efficient.
     if (compare->compareType() == MCompare::Compare_Boolean &&
         def->getOperand(0)->type() == MIRType_Boolean)
@@ -250,24 +250,24 @@ TypeBarrierPolicy::adjustInputs(TempAllo
     if (inputType == outputType)
         return true;
 
     // Output is a value, currently box the input.
     if (outputType == MIRType_Value) {
         // XXX: Possible optimization: decrease resultTypeSet to only include
         // the inputType. This will remove the need for boxing.
         MOZ_ASSERT(inputType != MIRType_Value);
-        ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
+        ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
         return true;
     }
 
     // Box input if needed.
     if (inputType != MIRType_Value) {
         MOZ_ASSERT(ins->alwaysBails());
-        ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
+        ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
     }
 
     // We can't unbox a value to null/undefined/lazyargs. So keep output
     // also a value.
     // Note: Using setResultType shouldn't be done in TypePolicies,
     //       Here it is fine, since the type barrier has no uses.
     if (IsNullOrUndefined(outputType) || outputType == MIRType_MagicOptimizedArguments) {
         MOZ_ASSERT(!ins->hasDefUses());
@@ -314,28 +314,28 @@ TestPolicy::adjustInputs(TempAllocator &
       {
         MStringLength *length = MStringLength::New(alloc, op);
         ins->block()->insertBefore(ins, length);
         ins->replaceOperand(0, length);
         break;
       }
 
       default:
-        ins->replaceOperand(0, boxAt(alloc, ins, op));
+        ins->replaceOperand(0, BoxAt(alloc, ins, op));
         break;
     }
     return true;
 }
 
 bool
 BitwisePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MIRType specialization = ins->typePolicySpecialization();
     if (specialization == MIRType_None)
-        return BoxInputsPolicy::adjustInputs(alloc, ins);
+        return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
 
     MOZ_ASSERT(ins->type() == specialization);
     MOZ_ASSERT(specialization == MIRType_Int32 || specialization == MIRType_Double);
 
     // This policy works for both unary and binary bitwise operations.
     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
         MDefinition *in = ins->getOperand(i);
         if (in->type() == MIRType_Int32)
@@ -523,17 +523,17 @@ template bool NoFloatPolicyAfter<2>::adj
 template <unsigned Op>
 bool
 BoxPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MDefinition *in = ins->getOperand(Op);
     if (in->type() == MIRType_Value)
         return true;
 
-    ins->replaceOperand(Op, boxAt(alloc, ins, in));
+    ins->replaceOperand(Op, BoxAt(alloc, ins, in));
     return true;
 }
 
 template bool BoxPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
 template bool BoxPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
 template bool BoxPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
 
 template <unsigned Op, MIRType Type>
@@ -589,17 +589,17 @@ ToDoublePolicy::staticAdjustInputs(TempA
       case MIRType_String:
       case MIRType_Symbol:
         // Objects might be effectful. Symbols give TypeError.
         break;
       default:
         break;
     }
 
-    in = boxAt(alloc, ins, in);
+    in = BoxAt(alloc, ins, in);
     ins->replaceOperand(0, in);
     return true;
 }
 
 bool
 ToInt32Policy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MOZ_ASSERT(ins->isToInt32() || ins->isTruncateToInt32());
@@ -637,29 +637,29 @@ ToInt32Policy::staticAdjustInputs(TempAl
       case MIRType_String:
       case MIRType_Symbol:
         // Objects might be effectful. Symbols give TypeError.
         break;
       default:
         break;
     }
 
-    in = boxAt(alloc, ins, in);
+    in = BoxAt(alloc, ins, in);
     ins->replaceOperand(0, in);
     return true;
 }
 
 bool
 ToStringPolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MOZ_ASSERT(ins->isToString());
 
     MIRType type = ins->getOperand(0)->type();
     if (type == MIRType_Object || type == MIRType_Symbol) {
-        ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
+        ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
         return true;
     }
 
     // TODO remove the following line once 966957 has landed
     EnsureOperandNotFloat32(alloc, ins, 0);
 
     return true;
 }
@@ -707,24 +707,24 @@ CallPolicy::adjustInputs(TempAllocator &
 
     return true;
 }
 
 bool
 CallSetElementPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     // The first operand should be an object.
-    SingleObjectPolicy::adjustInputs(alloc, ins);
+    SingleObjectPolicy::staticAdjustInputs(alloc, ins);
 
     // Box the index and value operands.
     for (size_t i = 1, e = ins->numOperands(); i < e; i++) {
         MDefinition *in = ins->getOperand(i);
         if (in->type() == MIRType_Value)
             continue;
-        ins->replaceOperand(i, boxAt(alloc, ins, in));
+        ins->replaceOperand(i, BoxAt(alloc, ins, in));
     }
     return true;
 }
 
 bool
 InstanceOfPolicy::adjustInputs(TempAllocator &alloc, MInstruction *def)
 {
     // Box first operand if it isn't object
@@ -756,17 +756,17 @@ StoreTypedArrayPolicy::adjustValueInput(
       case MIRType_Undefined:
         value->setImplicitlyUsedUnchecked();
         value = MConstant::New(alloc, DoubleNaNValue());
         ins->block()->insertBefore(ins, value->toInstruction());
         break;
       case MIRType_Object:
       case MIRType_String:
       case MIRType_Symbol:
-        value = boxAt(alloc, ins, value);
+        value = BoxAt(alloc, ins, value);
         break;
       default:
         MOZ_CRASH("Unexpected type");
     }
 
     if (value != curValue) {
         ins->replaceOperand(valueOperand, value);
         curValue = value;
@@ -831,26 +831,26 @@ StoreTypedArrayPolicy::adjustInputs(Temp
 bool
 StoreTypedArrayHolePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MStoreTypedArrayElementHole *store = ins->toStoreTypedArrayElementHole();
     MOZ_ASSERT(store->elements()->type() == MIRType_Elements);
     MOZ_ASSERT(store->index()->type() == MIRType_Int32);
     MOZ_ASSERT(store->length()->type() == MIRType_Int32);
 
-    return adjustValueInput(alloc, ins, store->arrayType(), store->value(), 3);
+    return StoreTypedArrayPolicy::adjustValueInput(alloc, ins, store->arrayType(), store->value(), 3);
 }
 
 bool
 StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     MStoreTypedArrayElementStatic *store = ins->toStoreTypedArrayElementStatic();
 
     return ConvertToInt32Policy<0>::staticAdjustInputs(alloc, ins) &&
-        adjustValueInput(alloc, ins, store->viewType(), store->value(), 1);
+        StoreTypedArrayPolicy::adjustValueInput(alloc, ins, store->viewType(), store->value(), 1);
 }
 
 bool
 StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
 {
     SingleObjectPolicy::staticAdjustInputs(alloc, ins);
 
     // Change the value input to a ToObjectOrNull instruction if it might be
@@ -889,17 +889,17 @@ ClampPolicy::adjustInputs(TempAllocator 
     MDefinition *in = ins->toClampToUint8()->input();
 
     switch (in->type()) {
       case MIRType_Int32:
       case MIRType_Double:
       case MIRType_Value:
         break;
       default:
-          ins->replaceOperand(0, boxAt(alloc, ins, in));
+          ins->replaceOperand(0, BoxAt(alloc, ins, in));
         break;
     }
 
     return true;
 }
 
 bool
 FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
@@ -910,29 +910,29 @@ FilterTypeSetPolicy::adjustInputs(TempAl
 
     // Input and output type are already in accordance.
     if (inputType == outputType)
         return true;
 
     // Output is a value, box the input.
     if (outputType == MIRType_Value) {
         MOZ_ASSERT(inputType != MIRType_Value);
-        ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
+        ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
         return true;
     }
 
     // The outputType should be a subset of the inputType else we are in code
     // that has never executed yet. Bail to see the new type (if that hasn't
     // happened yet).
     if (inputType != MIRType_Value) {
         MBail *bail = MBail::New(alloc);
         ins->block()->insertBefore(ins, bail);
         bail->setDependency(ins->dependency());
         ins->setDependency(bail);
-        ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
+        ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
     }
 
     // We can't unbox a value to null/undefined/lazyargs. So keep output
     // also a value.
     // Note: Using setResultType shouldn't be done in TypePolicies,
     //       Here it is fine, since the type barrier has no uses.
     if (IsNullOrUndefined(outputType) || outputType == MIRType_MagicOptimizedArguments) {
         MOZ_ASSERT(!ins->hasDefUses());
@@ -1046,22 +1046,24 @@ namespace jit {
 }
 }
 
 namespace {
 
 // Default function visited by the C++ lookup rules, if the MIR Instruction does
 // not inherit from a TypePolicy::Data type.
 static TypePolicy *
-thisTypePolicy() {
+thisTypePolicy()
+{
     return nullptr;
 }
 
 static MIRType
-thisTypeSpecialization() {
+thisTypeSpecialization()
+{
     MOZ_CRASH("TypeSpecialization lacks definition of thisTypeSpecialization.");
 }
 
 }
 
 TypePolicy *
 MGetElementCache::thisTypePolicy()
 {
--- a/js/src/jit/TypePolicy.h
+++ b/js/src/jit/TypePolicy.h
@@ -11,16 +11,19 @@
 #include "jit/JitAllocPolicy.h"
 
 namespace js {
 namespace jit {
 
 class MInstruction;
 class MDefinition;
 
+extern MDefinition *
+AlwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand);
+
 // A type policy directs the type analysis phases, which insert conversion,
 // boxing, unboxing, and type changes as necessary.
 class TypePolicy
 {
   public:
     // Analyze the inputs of the instruction and perform one of the following
     // actions for each input:
     //  * Nothing; the input already type-checks.
@@ -57,154 +60,153 @@ struct TypeSpecializationData
 #define INHERIT_DATA_(DATA_TYPE)                        \
     struct Data : public DATA_TYPE                      \
     {                                                   \
         static TypePolicy *thisTypePolicy();            \
     }
 
 #define SPECIALIZATION_DATA_ INHERIT_DATA_(TypeSpecializationData)
 
-class BoxInputsPolicy : public TypePolicy
-{
-  protected:
-    static MDefinition *boxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand);
-
-  public:
-    EMPTY_DATA_;
-    static MDefinition *alwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand);
-    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def);
-};
-
-class ArithPolicy : public BoxInputsPolicy
+class BoxInputsPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     SPECIALIZATION_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
+        return staticAdjustInputs(alloc, def);
+    }
 };
 
-class BitwisePolicy : public BoxInputsPolicy
+class ArithPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     SPECIALIZATION_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
-class ComparePolicy : public BoxInputsPolicy
+class BitwisePolicy MOZ_FINAL : public TypePolicy
+{
+  public:
+    SPECIALIZATION_DATA_;
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
+};
+
+class ComparePolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
 // Policy for MTest instructions.
-class TestPolicy : public BoxInputsPolicy
+class TestPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class TypeBarrierPolicy : public BoxInputsPolicy
+class TypeBarrierPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class CallPolicy : public BoxInputsPolicy
+class CallPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
 // Policy for MPow. First operand Double; second Double or Int32.
-class PowPolicy : public BoxInputsPolicy
+class PowPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     SPECIALIZATION_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
 // Expect a string for operand Op. If the input is a Value, it is unboxed.
 template <unsigned Op>
-class StringPolicy : public BoxInputsPolicy
+class StringPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect a string for operand Op. Else a ToString instruction is inserted.
 template <unsigned Op>
-class ConvertToStringPolicy : public TypePolicy
+class ConvertToStringPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect an Int for operand Op. If the input is a Value, it is unboxed.
 template <unsigned Op>
-class IntPolicy : public BoxInputsPolicy
+class IntPolicy MOZ_FINAL : private TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect an Int for operand Op. Else a ToInt32 instruction is inserted.
 template <unsigned Op>
-class ConvertToInt32Policy : public BoxInputsPolicy
+class ConvertToInt32Policy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect a double for operand Op. If the input is a Value, it is unboxed.
 template <unsigned Op>
-class DoublePolicy : public BoxInputsPolicy
+class DoublePolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect a float32 for operand Op. If the input is a Value, it is unboxed.
 template <unsigned Op>
-class Float32Policy : public BoxInputsPolicy
+class Float32Policy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Expect a float32 OR a double for operand Op, but will prioritize Float32
 // if the result type is set as such. If the input is a Value, it is unboxed.
 template <unsigned Op>
-class FloatingPointPolicy : public TypePolicy
+class FloatingPointPolicy MOZ_FINAL : public TypePolicy
 {
 
   public:
     struct PolicyTypeData
     {
         MIRType policyType_;
 
         void setPolicyType(MIRType type) {
@@ -214,218 +216,224 @@ class FloatingPointPolicy : public TypeP
       protected:
         MIRType &thisTypeSpecialization() {
             return policyType_;
         }
     };
 
     INHERIT_DATA_(PolicyTypeData);
 
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
 template <unsigned Op>
-class NoFloatPolicy : public TypePolicy
+class NoFloatPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Policy for guarding variadic instructions such as object / array state
 // instructions.
 template <unsigned FirstOp>
-class NoFloatPolicyAfter : public TypePolicy
+class NoFloatPolicyAfter MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
 // Box objects or strings as an input to a ToDouble instruction.
-class ToDoublePolicy : public BoxInputsPolicy
+class ToDoublePolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Box objects, strings and undefined as input to a ToInt32 instruction.
-class ToInt32Policy : public BoxInputsPolicy
+class ToInt32Policy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 // Box objects as input to a ToString instruction.
-class ToStringPolicy : public BoxInputsPolicy
+class ToStringPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, def);
     }
 };
 
 template <unsigned Op>
-class ObjectPolicy : public BoxInputsPolicy
+class ObjectPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
 // Single-object input. If the input is a Value, it is unboxed. If it is
 // a primitive, we use ValueToNonNullObject.
 typedef ObjectPolicy<0> SingleObjectPolicy;
 
 template <unsigned Op>
-class BoxPolicy : public BoxInputsPolicy
+class BoxPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
 // Boxes everything except inputs of type Type.
 template <unsigned Op, MIRType Type>
-class BoxExceptPolicy : public TypePolicy
+class BoxExceptPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
     bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
 // Combine multiple policies.
 template <class Lhs, class Rhs>
-class MixPolicy : public TypePolicy
+class MixPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) {
         return Lhs::staticAdjustInputs(alloc, ins) && Rhs::staticAdjustInputs(alloc, ins);
     }
-    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
 // Combine three policies.
 template <class Policy1, class Policy2, class Policy3>
-class Mix3Policy : public TypePolicy
+class Mix3Policy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) {
         return Policy1::staticAdjustInputs(alloc, ins) &&
                Policy2::staticAdjustInputs(alloc, ins) &&
                Policy3::staticAdjustInputs(alloc, ins);
     }
-    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
 // Combine four policies.  (Missing variadic templates yet?)
 template <class Policy1, class Policy2, class Policy3, class Policy4>
 class Mix4Policy : public TypePolicy
 {
   public:
     EMPTY_DATA_;
     static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) {
         return Policy1::staticAdjustInputs(alloc, ins) &&
                Policy2::staticAdjustInputs(alloc, ins) &&
                Policy3::staticAdjustInputs(alloc, ins) &&
                Policy4::staticAdjustInputs(alloc, ins);
     }
-    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) {
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE {
         return staticAdjustInputs(alloc, ins);
     }
 };
 
-class CallSetElementPolicy : public SingleObjectPolicy
+class CallSetElementPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
 // First operand will be boxed to a Value (except for an object)
 // Second operand (if specified) will forcefully be unboxed to an object
-class InstanceOfPolicy : public TypePolicy
+class InstanceOfPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
-class StoreTypedArrayPolicy : public BoxInputsPolicy
+class StoreTypedArrayHolePolicy;
+class StoreTypedArrayElementStaticPolicy;
+
+class StoreTypedArrayPolicy : public TypePolicy
 {
-  protected:
-    bool adjustValueInput(TempAllocator &alloc, MInstruction *ins, int arrayType, MDefinition *value, int valueOperand);
+  private:
+    static bool adjustValueInput(TempAllocator &alloc, MInstruction *ins, int arrayType, MDefinition *value, int valueOperand);
+
+    friend class StoreTypedArrayHolePolicy;
+    friend class StoreTypedArrayElementStaticPolicy;
 
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class StoreTypedArrayHolePolicy : public StoreTypedArrayPolicy
+class StoreTypedArrayHolePolicy MOZ_FINAL : public StoreTypedArrayPolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class StoreTypedArrayElementStaticPolicy : public StoreTypedArrayPolicy
+class StoreTypedArrayElementStaticPolicy MOZ_FINAL : public StoreTypedArrayPolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class StoreUnboxedObjectOrNullPolicy : public TypePolicy
+class StoreUnboxedObjectOrNullPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *def);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
 };
 
 // Accepts integers and doubles. Everything else is boxed.
-class ClampPolicy : public BoxInputsPolicy
+class ClampPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
-class FilterTypeSetPolicy : public BoxInputsPolicy
+class FilterTypeSetPolicy MOZ_FINAL : public TypePolicy
 {
   public:
     EMPTY_DATA_;
-    bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
+    virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE;
 };
 
 static inline bool
 CoercesToDouble(MIRType type)
 {
     if (type == MIRType_Undefined || IsFloatingPointType(type))
         return true;
     return false;