Bug 898021 - Mark values written to integer typed arrays as truncated, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 26 Jul 2013 11:29:48 -0600
changeset 152470 01bf6add1d1fbb7349dce9f2b481ab245ba25cd6
parent 152469 d2967ea984a7aa53c54e79ab638cbfd72f6cb1e2
child 152471 b8791c396e52684d09a4df2fa144c8c22f396d3c
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs898021
milestone25.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 898021 - Mark values written to integer typed arrays as truncated, r=jandem.
js/src/ion/MIR.h
js/src/ion/RangeAnalysis.cpp
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -5228,16 +5228,17 @@ class MStoreTypedArrayElement
         return AliasSet::Store(AliasSet::TypedArrayElement);
     }
     bool racy() const {
         return racy_;
     }
     void setRacy() {
         racy_ = true;
     }
+    bool isOperandTruncated(size_t index) const;
 };
 
 class MStoreTypedArrayElementHole
   : public MAryInstruction<4>,
     public StoreTypedArrayHolePolicy
 {
     int arrayType_;
 
@@ -5290,16 +5291,17 @@ class MStoreTypedArrayElementHole
         return getOperand(2);
     }
     MDefinition *value() const {
         return getOperand(3);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Store(AliasSet::TypedArrayElement);
     }
+    bool isOperandTruncated(size_t index) const;
 };
 
 // Store a value infallibly to a statically known typed array.
 class MStoreTypedArrayElementStatic :
     public MBinaryInstruction
   , public StoreTypedArrayElementStaticPolicy
 {
     MStoreTypedArrayElementStatic(TypedArrayObject *typedArray, MDefinition *ptr, MDefinition *v)
@@ -5317,24 +5319,30 @@ class MStoreTypedArrayElementStatic :
         return new MStoreTypedArrayElementStatic(typedArray, ptr, v);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     ArrayBufferView::ViewType viewType() const { return JS_GetArrayBufferViewType(typedArray_); }
+    bool isFloatArray() const {
+        return (viewType() == TypedArrayObject::TYPE_FLOAT32 ||
+                viewType() == TypedArrayObject::TYPE_FLOAT64);
+    }
+
     void *base() const;
     size_t length() const;
 
     MDefinition *ptr() const { return getOperand(0); }
     MDefinition *value() const { return getOperand(1); }
     AliasSet getAliasSet() const {
         return AliasSet::Store(AliasSet::TypedArrayElement);
     }
+    bool isOperandTruncated(size_t index) const;
 };
 
 // Compute an "effective address", i.e., a compound computation of the form:
 //   base + index * scale + displacement
 class MEffectiveAddress : public MBinaryInstruction
 {
     MEffectiveAddress(MDefinition *base, MDefinition *index, Scale scale, int32_t displacement)
       : MBinaryInstruction(base, index), scale_(scale), displacement_(displacement)
--- a/js/src/ion/RangeAnalysis.cpp
+++ b/js/src/ion/RangeAnalysis.cpp
@@ -1819,16 +1819,34 @@ MMul::isOperandTruncated(size_t index) c
 bool
 MToDouble::isOperandTruncated(size_t index) const
 {
     // The return type is used to flag that we are replacing this Double by a
     // Truncate of its operand if needed.
     return type() == MIRType_Int32;
 }
 
+bool
+MStoreTypedArrayElement::isOperandTruncated(size_t index) const
+{
+    return index == 2 && !isFloatArray();
+}
+
+bool
+MStoreTypedArrayElementHole::isOperandTruncated(size_t index) const
+{
+    return index == 3 && !isFloatArray();
+}
+
+bool
+MStoreTypedArrayElementStatic::isOperandTruncated(size_t index) const
+{
+    return index == 1 && !isFloatArray();
+}
+
 // Ensure that all observables uses can work with a truncated
 // version of the |candidate|'s result.
 static bool
 AllUsesTruncate(MInstruction *candidate)
 {
     for (MUseIterator use(candidate->usesBegin()); use != candidate->usesEnd(); use++) {
         if (!use->consumer()->isDefinition()) {
             // We can only skip testing resume points, if all original uses are still present.