Bug 1343007 - Insert explicit casts to enforce signed wasm div/mod operation. r=bbouvier, r=nbp
authorLars T Hansen <lhansen@mozilla.com>
Mon, 20 Mar 2017 12:47:38 +0100
changeset 348664 620f5ed5c91ec42874c6b725d8caddb713bbe022
parent 348663 21223d98c2eabfb28b4ce4d13d0d86ff6a61b838
child 348665 22e3e7b047903ae1c9b47d9aeb3206e417ef66c0
push id31533
push userkwierso@gmail.com
push dateTue, 21 Mar 2017 23:08:53 +0000
treeherdermozilla-central@8744e9f8eb99 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier, nbp
bugs1343007
milestone55.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 1343007 - Insert explicit casts to enforce signed wasm div/mod operation. r=bbouvier, r=nbp
js/src/jit/MIR.h
js/src/wasm/WasmIonCompile.cpp
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -6996,17 +6996,17 @@ class MMul : public MBinaryArithInstruct
 };
 
 class MDiv : public MBinaryArithInstruction
 {
     bool canBeNegativeZero_;
     bool canBeNegativeOverflow_;
     bool canBeDivideByZero_;
     bool canBeNegativeDividend_;
-    bool unsigned_;
+    bool unsigned_;             // If false, signedness will be derived from operands
     bool trapOnError_;
     wasm::TrapOffset trapOffset_;
 
     MDiv(MDefinition* left, MDefinition* right, MIRType type)
       : MBinaryArithInstruction(left, right),
         canBeNegativeZero_(true),
         canBeNegativeOverflow_(true),
         canBeDivideByZero_(true),
@@ -7134,17 +7134,17 @@ class MDiv : public MBinaryArithInstruct
         return unsigned_ == other->isUnsigned();
     }
 
     ALLOW_CLONE(MDiv)
 };
 
 class MMod : public MBinaryArithInstruction
 {
-    bool unsigned_;
+    bool unsigned_;             // If false, signedness will be derived from operands
     bool canBeNegativeDividend_;
     bool canBePowerOfTwoDivisor_;
     bool canBeDivideByZero_;
     bool trapOnError_;
     wasm::TrapOffset trapOffset_;
 
     MMod(MDefinition* left, MDefinition* right, MIRType type)
       : MBinaryArithInstruction(left, right),
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -617,27 +617,51 @@ class FunctionCompiler
         return ins;
     }
 
     MDefinition* div(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd)
     {
         if (inDeadCode())
             return nullptr;
         bool trapOnError = !env().isAsmJS();
+        if (!unsignd && type == MIRType::Int32) {
+            // Enforce the signedness of the operation by coercing the operands
+            // to signed.  Otherwise, operands that "look" unsigned to Ion but
+            // are not unsigned to Baldr (eg, unsigned right shifts) may lead to
+            // the operation being executed unsigned.  Applies to mod() as well.
+            //
+            // Do this for Int32 only since Int64 is not subject to the same
+            // issues.
+            auto* lhs2 = MTruncateToInt32::New(alloc(), lhs);
+            curBlock_->add(lhs2);
+            lhs = lhs2;
+            auto* rhs2 = MTruncateToInt32::New(alloc(), rhs);
+            curBlock_->add(rhs2);
+            rhs = rhs2;
+        }
         auto* ins = MDiv::New(alloc(), lhs, rhs, type, unsignd, trapOnError, trapOffset(),
                               mustPreserveNaN(type));
         curBlock_->add(ins);
         return ins;
     }
 
     MDefinition* mod(MDefinition* lhs, MDefinition* rhs, MIRType type, bool unsignd)
     {
         if (inDeadCode())
             return nullptr;
         bool trapOnError = !env().isAsmJS();
+        if (!unsignd && type == MIRType::Int32) {
+            // See block comment in div().
+            auto* lhs2 = MTruncateToInt32::New(alloc(), lhs);
+            curBlock_->add(lhs2);
+            lhs = lhs2;
+            auto* rhs2 = MTruncateToInt32::New(alloc(), rhs);
+            curBlock_->add(rhs2);
+            rhs = rhs2;
+        }
         auto* ins = MMod::New(alloc(), lhs, rhs, type, unsignd, trapOnError, trapOffset());
         curBlock_->add(ins);
         return ins;
     }
 
     MDefinition* bitnot(MDefinition* op)
     {
         if (inDeadCode())