Bug 1135042: Share more code between StoreTypedArray* classes; r=bhackett
authorBenjamin Bouvier <benj@benj.me>
Tue, 03 Mar 2015 13:56:49 +0100
changeset 231855 caea9f8b038e81c7a896654f17a9f7489ba179d3
parent 231854 3f54fe544025d1a49bbf51ca1f40761a2cbe3e5f
child 231856 bc9e6089b8e18c415753510a7ee2a6bf0944d039
push id28362
push userryanvm@gmail.com
push dateWed, 04 Mar 2015 21:35:51 +0000
treeherdermozilla-central@56492f7244a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1135042
milestone39.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 1135042: Share more code between StoreTypedArray* classes; r=bhackett
js/src/jit/Lowering.cpp
js/src/jit/MIR.h
js/src/jit/RangeAnalysis.cpp
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2979,29 +2979,29 @@ void
 LIRGenerator::visitStoreTypedArrayElement(MStoreTypedArrayElement *ins)
 {
     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
     MOZ_ASSERT(ins->index()->type() == MIRType_Int32);
 
     if (ins->isSimdWrite()) {
         MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32x4, ins->value()->type() == MIRType_Float32x4);
         MOZ_ASSERT_IF(ins->writeType() == Scalar::Int32x4, ins->value()->type() == MIRType_Int32x4);
-    } else if (ins->isFloatArray()) {
-        MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float32, ins->value()->type() == MIRType_Float32);
-        MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float64, ins->value()->type() == MIRType_Double);
+    } else if (ins->isFloatWrite()) {
+        MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32, ins->value()->type() == MIRType_Float32);
+        MOZ_ASSERT_IF(ins->writeType() == Scalar::Float64, ins->value()->type() == MIRType_Double);
     } else {
         MOZ_ASSERT(ins->value()->type() == MIRType_Int32);
     }
 
     LUse elements = useRegister(ins->elements());
     LAllocation index = useRegisterOrConstant(ins->index());
     LAllocation value;
 
     // For byte arrays, the value has to be in a byte register on x86.
-    if (ins->isByteArray() && !ins->isSimdWrite())
+    if (ins->isByteWrite())
         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
     else
         value = useRegisterOrNonDoubleConstant(ins->value());
 
     // Optimization opportunity for atomics: on some platforms there
     // is a store instruction that incorporates the necessary
     // barriers, and we could use that instead of separate barrier and
     // store instructions.  See bug #1077027.
@@ -3018,30 +3018,30 @@ LIRGenerator::visitStoreTypedArrayElemen
 
 void
 LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole *ins)
 {
     MOZ_ASSERT(ins->elements()->type() == MIRType_Elements);
     MOZ_ASSERT(ins->index()->type() == MIRType_Int32);
     MOZ_ASSERT(ins->length()->type() == MIRType_Int32);
 
-    if (ins->isFloatArray()) {
+    if (ins->isFloatWrite()) {
         MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float32, ins->value()->type() == MIRType_Float32);
         MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float64, ins->value()->type() == MIRType_Double);
     } else {
         MOZ_ASSERT(ins->value()->type() == MIRType_Int32);
     }
 
     LUse elements = useRegister(ins->elements());
     LAllocation length = useAnyOrConstant(ins->length());
     LAllocation index = useRegisterOrConstant(ins->index());
     LAllocation value;
 
     // For byte arrays, the value has to be in a byte register on x86.
-    if (ins->isByteArray())
+    if (ins->isByteWrite())
         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
     else
         value = useRegisterOrNonDoubleConstant(ins->value());
     add(new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value), ins);
 }
 
 void
 LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot *ins)
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9058,34 +9058,74 @@ class MLoadTypedArrayElementStatic
     }
 
     void computeRange(TempAllocator &alloc) MOZ_OVERRIDE;
     bool needTruncation(TruncateKind kind) MOZ_OVERRIDE;
     bool canProduceFloat32() const MOZ_OVERRIDE { return accessType() == Scalar::Float32; }
     void collectRangeInfoPreTrunc() MOZ_OVERRIDE;
 };
 
+// Base class for MIR ops that write to typed arrays.
+class StoreTypedArrayBase
+{
+    Scalar::Type writeType_;
+
+  protected:
+    explicit StoreTypedArrayBase(Scalar::Type writeType)
+      : writeType_(writeType)
+    {
+        MOZ_ASSERT(isIntegerWrite() || isFloatWrite() || isSimdWrite());
+    }
+
+  public:
+    void setWriteType(Scalar::Type type) {
+        writeType_ = type;
+    }
+    Scalar::Type writeType() const {
+        return writeType_;
+    }
+    bool isByteWrite() const {
+        return writeType_ == Scalar::Int8 ||
+               writeType_ == Scalar::Uint8 ||
+               writeType_ == Scalar::Uint8Clamped;
+    }
+    bool isIntegerWrite() const {
+        return isByteWrite () ||
+               writeType_ == Scalar::Int16 ||
+               writeType_ == Scalar::Uint16 ||
+               writeType_ == Scalar::Int32 ||
+               writeType_ == Scalar::Uint32;
+    }
+    bool isFloatWrite() const {
+        return writeType_ == Scalar::Float32 ||
+               writeType_ == Scalar::Float64;
+    }
+    bool isSimdWrite() const {
+        return Scalar::isSimdType(writeType());
+    }
+};
+
 class MStoreTypedArrayElement
   : public MTernaryInstruction,
+    public StoreTypedArrayBase,
     public StoreTypedArrayPolicy::Data
 {
     Scalar::Type arrayType_;
-    Scalar::Type writeType_;
     bool requiresBarrier_;
     int32_t offsetAdjustment_;
 
     // See note in MStoreElementCommon.
     bool racy_;
 
     MStoreTypedArrayElement(MDefinition *elements, MDefinition *index, MDefinition *value,
                             Scalar::Type arrayType, MemoryBarrierRequirement requiresBarrier,
                             int32_t offsetAdjustment)
       : MTernaryInstruction(elements, index, value),
+        StoreTypedArrayBase(arrayType),
         arrayType_(arrayType),
-        writeType_(arrayType),
         requiresBarrier_(requiresBarrier == DoesRequireMemoryBarrier),
         offsetAdjustment_(offsetAdjustment),
         racy_(false)
     {
         if (requiresBarrier_)
             setGuard();         // Not removable or movable
         else
             setMovable();
@@ -9101,37 +9141,19 @@ class MStoreTypedArrayElement
                                         MDefinition *value, Scalar::Type arrayType,
                                         MemoryBarrierRequirement requiresBarrier = DoesNotRequireMemoryBarrier,
                                         int32_t offsetAdjustment = 0)
     {
         return new(alloc) MStoreTypedArrayElement(elements, index, value, arrayType,
                                                   requiresBarrier, offsetAdjustment);
     }
 
-    void setWriteType(Scalar::Type type) {
-        writeType_ = type;
-    }
-    Scalar::Type writeType() const {
-        return writeType_;
-    }
     Scalar::Type arrayType() const {
         return arrayType_;
     }
-    bool isSimdWrite() const {
-        return Scalar::isSimdType(writeType());
-    }
-    bool isByteArray() const {
-        return arrayType_ == Scalar::Int8 ||
-               arrayType_ == Scalar::Uint8 ||
-               arrayType_ == Scalar::Uint8Clamped;
-    }
-    bool isFloatArray() const {
-        return arrayType_ == Scalar::Float32 ||
-               arrayType_ == Scalar::Float64;
-    }
     MDefinition *elements() const {
         return getOperand(0);
     }
     MDefinition *index() const {
         return getOperand(1);
     }
     MDefinition *value() const {
         return getOperand(2);
@@ -9157,23 +9179,23 @@ class MStoreTypedArrayElement
         return use == getUseFor(2) && arrayType_ == Scalar::Float32;
     }
 
     ALLOW_CLONE(MStoreTypedArrayElement)
 };
 
 class MStoreTypedArrayElementHole
   : public MAryInstruction<4>,
+    public StoreTypedArrayBase,
     public StoreTypedArrayHolePolicy::Data
 {
-    Scalar::Type arrayType_;
-
     MStoreTypedArrayElementHole(MDefinition *elements, MDefinition *length, MDefinition *index,
                                 MDefinition *value, Scalar::Type arrayType)
-      : MAryInstruction<4>(), arrayType_(arrayType)
+      : MAryInstruction<4>(),
+        StoreTypedArrayBase(arrayType)
     {
         initOperand(0, elements);
         initOperand(1, length);
         initOperand(2, index);
         initOperand(3, value);
         setMovable();
         MOZ_ASSERT(elements->type() == MIRType_Elements);
         MOZ_ASSERT(length->type() == MIRType_Int32);
@@ -9187,26 +9209,19 @@ class MStoreTypedArrayElementHole
     static MStoreTypedArrayElementHole *New(TempAllocator &alloc, MDefinition *elements,
                                             MDefinition *length, MDefinition *index,
                                             MDefinition *value, Scalar::Type arrayType)
     {
         return new(alloc) MStoreTypedArrayElementHole(elements, length, index, value, arrayType);
     }
 
     Scalar::Type arrayType() const {
-        return arrayType_;
-    }
-    bool isByteArray() const {
-        return arrayType_ == Scalar::Int8 ||
-               arrayType_ == Scalar::Uint8 ||
-               arrayType_ == Scalar::Uint8Clamped;
-    }
-    bool isFloatArray() const {
-        return arrayType_ == Scalar::Float32 ||
-               arrayType_ == Scalar::Float64;
+        MOZ_ASSERT(!Scalar::isSimdType(writeType()),
+                   "arrayType == writeType iff the write type isn't SIMD");
+        return writeType();
     }
     MDefinition *elements() const {
         return getOperand(0);
     }
     MDefinition *length() const {
         return getOperand(1);
     }
     MDefinition *index() const {
@@ -9216,34 +9231,38 @@ class MStoreTypedArrayElementHole
         return getOperand(3);
     }
     AliasSet getAliasSet() const MOZ_OVERRIDE {
         return AliasSet::Store(AliasSet::TypedArrayElement);
     }
     TruncateKind operandTruncateKind(size_t index) const MOZ_OVERRIDE;
 
     bool canConsumeFloat32(MUse *use) const MOZ_OVERRIDE {
-        return use == getUseFor(3) && arrayType_ == Scalar::Float32;
+        return use == getUseFor(3) && arrayType() == Scalar::Float32;
     }
 
     ALLOW_CLONE(MStoreTypedArrayElementHole)
 };
 
 // Store a value infallibly to a statically known typed array.
 class MStoreTypedArrayElementStatic :
-    public MBinaryInstruction
-  , public StoreTypedArrayElementStaticPolicy::Data
+    public MBinaryInstruction,
+    public StoreTypedArrayBase,
+    public StoreTypedArrayElementStaticPolicy::Data
 {
     MStoreTypedArrayElementStatic(JSObject *someTypedArray, MDefinition *ptr, MDefinition *v,
                                   int32_t offset, bool needsBoundsCheck)
-        : MBinaryInstruction(ptr, v), someTypedArray_(someTypedArray),
+        : MBinaryInstruction(ptr, v),
+          StoreTypedArrayBase(AnyTypedArrayType(someTypedArray)),
+          someTypedArray_(someTypedArray),
           offset_(offset), needsBoundsCheck_(needsBoundsCheck)
     {}
 
     AlwaysTenured<JSObject*> someTypedArray_;
+
     // An offset to be encoded in the store instruction - taking advantage of the
     // addressing modes. This is only non-zero when the access is proven to be
     // within bounds.
     int32_t offset_;
     bool needsBoundsCheck_;
 
   public:
     INSTRUCTION_HEADER(StoreTypedArrayElementStatic)
@@ -9253,21 +9272,17 @@ class MStoreTypedArrayElementStatic :
                                               int32_t offset = 0,
                                               bool needsBoundsCheck = true)
     {
         return new(alloc) MStoreTypedArrayElementStatic(someTypedArray, ptr, v,
                                                         offset, needsBoundsCheck);
     }
 
     Scalar::Type accessType() const {
-        return AnyTypedArrayType(someTypedArray_);
-    }
-    bool isFloatArray() const {
-        return accessType() == Scalar::Float32 ||
-               accessType() == Scalar::Float64;
+        return writeType();
     }
 
     void *base() const;
     size_t length() const;
 
     MDefinition *ptr() const { return getOperand(0); }
     MDefinition *value() const { return getOperand(1); }
     bool needsBoundsCheck() const { return needsBoundsCheck_; }
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2640,31 +2640,31 @@ MToDouble::operandTruncateKind(size_t in
     // MToDouble propagates its truncate kind to its operand.
     return truncateKind();
 }
 
 MDefinition::TruncateKind
 MStoreTypedArrayElement::operandTruncateKind(size_t index) const
 {
     // An integer store truncates the stored value.
-    return index == 2 && !isFloatArray() && !isSimdWrite() ? Truncate : NoTruncate;
+    return index == 2 && isIntegerWrite() ? Truncate : NoTruncate;
 }
 
 MDefinition::TruncateKind
 MStoreTypedArrayElementHole::operandTruncateKind(size_t index) const
 {
     // An integer store truncates the stored value.
-    return index == 3 && !isFloatArray() ? Truncate : NoTruncate;
+    return index == 3 && isIntegerWrite() ? Truncate : NoTruncate;
 }
 
 MDefinition::TruncateKind
 MStoreTypedArrayElementStatic::operandTruncateKind(size_t index) const
 {
     // An integer store truncates the stored value.
-    return index == 1 && !isFloatArray() ? Truncate : NoTruncate;
+    return index == 1 && isIntegerWrite() ? Truncate : NoTruncate;
 }
 
 MDefinition::TruncateKind
 MDiv::operandTruncateKind(size_t index) const
 {
     return Min(truncateKind(), TruncateAfterBailouts);
 }