Bug 1420104 - rabaldr, fix operand order when loading from value stack. r?bbouvier draft
authorLars T Hansen <lhansen@mozilla.com>
Thu, 23 Nov 2017 10:35:11 +0100
changeset 704215 e7c636d2cd1472968bbdc7c4653545533f0b1808
parent 704214 0cfeb6736dc481ca278c35fac815ba79208cce87
child 704216 767ea41d5d71b3ff2dbb5eb3248fa9394441e405
push id91107
push userbmo:lhansen@mozilla.com
push dateTue, 28 Nov 2017 10:55:44 +0000
reviewersbbouvier
bugs1420104
milestone59.0a1
Bug 1420104 - rabaldr, fix operand order when loading from value stack. r?bbouvier Change the layer in BaseCompiler that operates on Stk& values so that it always takes source first and destination last. Generally rename operands so that they are called 'src' and 'dest', to further reduce confusion. MozReview-Commit-ID: 4sldPz1mYtw
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1862,199 +1862,199 @@ class BaseCompiler final : public BaseCo
 
     Vector<Stk, 8, SystemAllocPolicy> stk_;
 
     Stk& push() {
         stk_.infallibleEmplaceBack(Stk());
         return stk_.back();
     }
 
-    void loadConstI32(RegI32 r, Stk& src) {
-        moveImm32(src.i32val(), r);
-    }
-
-    void loadMemI32(RegI32 r, Stk& src) {
-        fr.loadStackI32(r, src.offs());
-    }
-
-    void loadLocalI32(RegI32 r, Stk& src) {
-        fr.loadLocalI32(r, localFromSlot(src.slot(), MIRType::Int32));
-    }
-
-    void loadRegisterI32(RegI32 r, Stk& src) {
-        moveI32(src.i32reg(), r);
-    }
-
-    void loadConstI64(RegI64 r, Stk &src) {
-        moveImm64(src.i64val(), r);
-    }
-
-    void loadMemI64(RegI64 r, Stk& src) {
-        fr.loadStackI64(r, src.offs());
-    }
-
-    void loadLocalI64(RegI64 r, Stk& src) {
-        fr.loadLocalI64(r, localFromSlot(src.slot(), MIRType::Int64));
-    }
-
-    void loadRegisterI64(RegI64 r, Stk& src) {
-        moveI64(src.i64reg(), r);
-    }
-
-    void loadConstF64(RegF64 r, Stk &src) {
+    void loadConstI32(Stk& src, RegI32 dest) {
+        moveImm32(src.i32val(), dest);
+    }
+
+    void loadMemI32(Stk& src, RegI32 dest) {
+        fr.loadStackI32(dest, src.offs());
+    }
+
+    void loadLocalI32(Stk& src, RegI32 dest) {
+        fr.loadLocalI32(dest, localFromSlot(src.slot(), MIRType::Int32));
+    }
+
+    void loadRegisterI32(Stk& src, RegI32 dest) {
+        moveI32(src.i32reg(), dest);
+    }
+
+    void loadConstI64(Stk &src, RegI64 dest) {
+        moveImm64(src.i64val(), dest);
+    }
+
+    void loadMemI64(Stk& src, RegI64 dest) {
+        fr.loadStackI64(dest, src.offs());
+    }
+
+    void loadLocalI64(Stk& src, RegI64 dest) {
+        fr.loadLocalI64(dest, localFromSlot(src.slot(), MIRType::Int64));
+    }
+
+    void loadRegisterI64(Stk& src, RegI64 dest) {
+        moveI64(src.i64reg(), dest);
+    }
+
+    void loadConstF64(Stk &src, RegF64 dest) {
         double d;
         src.f64val(&d);
-        masm.loadConstantDouble(d, r);
-    }
-
-    void loadMemF64(RegF64 r, Stk& src) {
-        fr.loadStackF64(r, src.offs());
-    }
-
-    void loadLocalF64(RegF64 r, Stk& src) {
-        fr.loadLocalF64(r, localFromSlot(src.slot(), MIRType::Double));
-    }
-
-    void loadRegisterF64(RegF64 r, Stk& src) {
-        moveF64(src.f64reg(), r);
-    }
-
-    void loadConstF32(RegF32 r, Stk &src) {
+        masm.loadConstantDouble(d, dest);
+    }
+
+    void loadMemF64(Stk& src, RegF64 dest) {
+        fr.loadStackF64(dest, src.offs());
+    }
+
+    void loadLocalF64(Stk& src, RegF64 dest) {
+        fr.loadLocalF64(dest, localFromSlot(src.slot(), MIRType::Double));
+    }
+
+    void loadRegisterF64(Stk& src, RegF64 dest) {
+        moveF64(src.f64reg(), dest);
+    }
+
+    void loadConstF32(Stk &src, RegF32 dest) {
         float f;
         src.f32val(&f);
-        masm.loadConstantFloat32(f, r);
-    }
-
-    void loadMemF32(RegF32 r, Stk& src) {
-        fr.loadStackF32(r, src.offs());
-    }
-
-    void loadLocalF32(RegF32 r, Stk& src) {
-        fr.loadLocalF32(r, localFromSlot(src.slot(), MIRType::Float32));
-    }
-
-    void loadRegisterF32(RegF32 r, Stk& src) {
-        moveF32(src.f32reg(), r);
-    }
-
-    void loadI32(RegI32 r, Stk& src) {
+        masm.loadConstantFloat32(f, dest);
+    }
+
+    void loadMemF32(Stk& src, RegF32 dest) {
+        fr.loadStackF32(dest, src.offs());
+    }
+
+    void loadLocalF32(Stk& src, RegF32 dest) {
+        fr.loadLocalF32(dest, localFromSlot(src.slot(), MIRType::Float32));
+    }
+
+    void loadRegisterF32(Stk& src, RegF32 dest) {
+        moveF32(src.f32reg(), dest);
+    }
+
+    void loadI32(Stk& src, RegI32 dest) {
         switch (src.kind()) {
           case Stk::ConstI32:
-            loadConstI32(r, src);
+            loadConstI32(src, dest);
             break;
           case Stk::MemI32:
-            loadMemI32(r, src);
+            loadMemI32(src, dest);
             break;
           case Stk::LocalI32:
-            loadLocalI32(r, src);
+            loadLocalI32(src, dest);
             break;
           case Stk::RegisterI32:
-            loadRegisterI32(r, src);
+            loadRegisterI32(src, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: Expected I32 on stack");
         }
     }
 
-    void loadI64(RegI64 r, Stk& src) {
+    void loadI64(Stk& src, RegI64 dest) {
         switch (src.kind()) {
           case Stk::ConstI64:
-            loadConstI64(r, src);
+            loadConstI64(src, dest);
             break;
           case Stk::MemI64:
-            loadMemI64(r, src);
+            loadMemI64(src, dest);
             break;
           case Stk::LocalI64:
-            loadLocalI64(r, src);
+            loadLocalI64(src, dest);
             break;
           case Stk::RegisterI64:
-            loadRegisterI64(r, src);
+            loadRegisterI64(src, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: Expected I64 on stack");
         }
     }
 
 #if !defined(JS_PUNBOX64)
-    void loadI64Low(RegI32 r, Stk& src) {
+    void loadI64Low(Stk& src, RegI32 dest) {
         switch (src.kind()) {
           case Stk::ConstI64:
-            moveImm32(int32_t(src.i64val()), r);
+            moveImm32(int32_t(src.i64val()), dest);
             break;
           case Stk::MemI64:
-            fr.loadStackI64Low(r, src.offs());
+            fr.loadStackI64Low(dest, src.offs());
             break;
           case Stk::LocalI64:
-            fr.loadLocalI64Low(r, localFromSlot(src.slot(), MIRType::Int64));
+            fr.loadLocalI64Low(dest, localFromSlot(src.slot(), MIRType::Int64));
             break;
           case Stk::RegisterI64:
-            moveI32(RegI32(src.i64reg().low), r);
+            moveI32(RegI32(src.i64reg().low), dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: Expected I64 on stack");
         }
     }
 
-    void loadI64High(RegI32 r, Stk& src) {
+    void loadI64High(Stk& src, RegI32 dest) {
         switch (src.kind()) {
           case Stk::ConstI64:
-            moveImm32(int32_t(src.i64val() >> 32), r);
+            moveImm32(int32_t(src.i64val() >> 32), dest);
             break;
           case Stk::MemI64:
-            fr.loadStackI64High(r, src.offs());
+            fr.loadStackI64High(dest, src.offs());
             break;
           case Stk::LocalI64:
-            fr.loadLocalI64High(r, localFromSlot(src.slot(), MIRType::Int64));
+            fr.loadLocalI64High(dest, localFromSlot(src.slot(), MIRType::Int64));
             break;
           case Stk::RegisterI64:
-            moveI32(RegI32(src.i64reg().high), r);
+            moveI32(RegI32(src.i64reg().high), dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: Expected I64 on stack");
         }
     }
 #endif
 
-    void loadF64(RegF64 r, Stk& src) {
+    void loadF64(Stk& src, RegF64 dest) {
         switch (src.kind()) {
           case Stk::ConstF64:
-            loadConstF64(r, src);
+            loadConstF64(src, dest);
             break;
           case Stk::MemF64:
-            loadMemF64(r, src);
+            loadMemF64(src, dest);
             break;
           case Stk::LocalF64:
-            loadLocalF64(r, src);
+            loadLocalF64(src, dest);
             break;
           case Stk::RegisterF64:
-            loadRegisterF64(r, src);
+            loadRegisterF64(src, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected F64 on stack");
         }
     }
 
-    void loadF32(RegF32 r, Stk& src) {
+    void loadF32(Stk& src, RegF32 dest) {
         switch (src.kind()) {
           case Stk::ConstF32:
-            loadConstF32(r, src);
+            loadConstF32(src, dest);
             break;
           case Stk::MemF32:
-            loadMemF32(r, src);
+            loadMemF32(src, dest);
             break;
           case Stk::LocalF32:
-            loadLocalF32(r, src);
+            loadLocalF32(src, dest);
             break;
           case Stk::RegisterF32:
-            loadRegisterF32(r, src);
+            loadRegisterF32(src, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected F32 on stack");
         }
     }
 
     // Flush all local and register value stack elements to memory.
@@ -2091,31 +2091,31 @@ class BaseCompiler final : public BaseCo
             }
         }
 
         for (size_t i = start; i < lim; i++) {
             Stk& v = stk_[i];
             switch (v.kind()) {
               case Stk::LocalI32: {
                 ScratchI32 scratch(*this);
-                loadLocalI32(scratch, v);
+                loadLocalI32(v, scratch);
                 uint32_t offs = fr.pushPtr(scratch);
                 v.setOffs(Stk::MemI32, offs);
                 break;
               }
               case Stk::RegisterI32: {
                 uint32_t offs = fr.pushPtr(v.i32reg());
                 freeI32(v.i32reg());
                 v.setOffs(Stk::MemI32, offs);
                 break;
               }
               case Stk::LocalI64: {
                 ScratchI32 scratch(*this);
 #ifdef JS_PUNBOX64
-                loadI64(fromI32(scratch), v);
+                loadI64(v, fromI32(scratch));
                 uint32_t offs = fr.pushPtr(scratch);
 #else
                 fr.loadLocalI64High(scratch, localFromSlot(v.slot(), MIRType::Int64));
                 fr.pushPtr(scratch);
                 fr.loadLocalI64Low(scratch, localFromSlot(v.slot(), MIRType::Int64));
                 uint32_t offs = fr.pushPtr(scratch);
 #endif
                 v.setOffs(Stk::MemI64, offs);
@@ -2130,30 +2130,30 @@ class BaseCompiler final : public BaseCo
                 uint32_t offs = fr.pushPtr(v.i64reg().low);
                 freeI64(v.i64reg());
 #endif
                 v.setOffs(Stk::MemI64, offs);
                 break;
               }
               case Stk::LocalF64: {
                 ScratchF64 scratch(*this);
-                loadF64(scratch, v);
+                loadF64(v, scratch);
                 uint32_t offs = fr.pushDouble(scratch);
                 v.setOffs(Stk::MemF64, offs);
                 break;
               }
               case Stk::RegisterF64: {
                 uint32_t offs = fr.pushDouble(v.f64reg());
                 freeF64(v.f64reg());
                 v.setOffs(Stk::MemF64, offs);
                 break;
               }
               case Stk::LocalF32: {
                 ScratchF32 scratch(*this);
-                loadF32(scratch, v);
+                loadF32(v, scratch);
                 uint32_t offs = fr.pushFloat(scratch);
                 v.setOffs(Stk::MemF32, offs);
                 break;
               }
               case Stk::RegisterF32: {
                 uint32_t offs = fr.pushFloat(v.f32reg());
                 freeF32(v.f32reg());
                 v.setOffs(Stk::MemF32, offs);
@@ -2257,32 +2257,33 @@ class BaseCompiler final : public BaseCo
         x.setSlot(Stk::LocalF64, slot);
     }
 
     void pushLocalF32(uint32_t slot) {
         Stk& x = push();
         x.setSlot(Stk::LocalF32, slot);
     }
 
-    // PRIVATE.  Call only from other popI32() variants.
-    // v must be the stack top.
-
-    void popI32(Stk& v, RegI32 r) {
+    // Call only from other popI32() variants.
+    // v must be the stack top.  May pop the CPU stack.
+
+    void popI32(Stk& v, RegI32 dest) {
+        MOZ_ASSERT(&v == &stk_.back());
         switch (v.kind()) {
           case Stk::ConstI32:
-            loadConstI32(r, v);
+            loadConstI32(v, dest);
             break;
           case Stk::LocalI32:
-            loadLocalI32(r, v);
+            loadLocalI32(v, dest);
             break;
           case Stk::MemI32:
-            fr.popPtr(r);
+            fr.popPtr(dest);
             break;
           case Stk::RegisterI32:
-            loadRegisterI32(r, v);
+            loadRegisterI32(v, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected int on stack");
         }
     }
 
     MOZ_MUST_USE RegI32 popI32() {
@@ -2305,37 +2306,38 @@ class BaseCompiler final : public BaseCo
             if (v.kind() == Stk::RegisterI32)
                 freeI32(v.i32reg());
         }
 
         stk_.popBack();
         return specific;
     }
 
-    // PRIVATE.  Call only from other popI64() variants.
-    // v must be the stack top.
-
-    void popI64(Stk& v, RegI64 r) {
+    // Call only from other popI64() variants.
+    // v must be the stack top.  May pop the CPU stack.
+
+    void popI64(Stk& v, RegI64 dest) {
+        MOZ_ASSERT(&v == &stk_.back());
         switch (v.kind()) {
           case Stk::ConstI64:
-            loadConstI64(r, v);
+            loadConstI64(v, dest);
             break;
           case Stk::LocalI64:
-            loadLocalI64(r, v);
+            loadLocalI64(v, dest);
             break;
           case Stk::MemI64:
 #ifdef JS_PUNBOX64
-            fr.popPtr(r.reg);
+            fr.popPtr(dest.reg);
 #else
-            fr.popPtr(r.low);
-            fr.popPtr(r.high);
+            fr.popPtr(dest.low);
+            fr.popPtr(dest.high);
 #endif
             break;
           case Stk::RegisterI64:
-            loadRegisterI64(r, v);
+            loadRegisterI64(v, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected long on stack");
         }
     }
 
     MOZ_MUST_USE RegI64 popI64() {
@@ -2363,32 +2365,33 @@ class BaseCompiler final : public BaseCo
             if (v.kind() == Stk::RegisterI64)
                 freeI64(v.i64reg());
         }
 
         stk_.popBack();
         return specific;
     }
 
-    // PRIVATE.  Call only from other popF64() variants.
-    // v must be the stack top.
-
-    void popF64(Stk& v, RegF64 r) {
+    // Call only from other popF64() variants.
+    // v must be the stack top.  May pop the CPU stack.
+
+    void popF64(Stk& v, RegF64 dest) {
+        MOZ_ASSERT(&v == &stk_.back());
         switch (v.kind()) {
           case Stk::ConstF64:
-            loadConstF64(r, v);
+            loadConstF64(v, dest);
             break;
           case Stk::LocalF64:
-            loadLocalF64(r, v);
+            loadLocalF64(v, dest);
             break;
           case Stk::MemF64:
-            fr.popDouble(r);
+            fr.popDouble(dest);
             break;
           case Stk::RegisterF64:
-            loadRegisterF64(r, v);
+            loadRegisterF64(v, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected double on stack");
         }
     }
 
     MOZ_MUST_USE RegF64 popF64() {
@@ -2411,32 +2414,33 @@ class BaseCompiler final : public BaseCo
             if (v.kind() == Stk::RegisterF64)
                 freeF64(v.f64reg());
         }
 
         stk_.popBack();
         return specific;
     }
 
-    // PRIVATE.  Call only from other popF32() variants.
-    // v must be the stack top.
-
-    void popF32(Stk& v, RegF32 r) {
+    // Call only from other popF32() variants.
+    // v must be the stack top.  May pop the CPU stack.
+
+    void popF32(Stk& v, RegF32 dest) {
+        MOZ_ASSERT(&v == &stk_.back());
         switch (v.kind()) {
           case Stk::ConstF32:
-            loadConstF32(r, v);
+            loadConstF32(v, dest);
             break;
           case Stk::LocalF32:
-            loadLocalF32(r, v);
+            loadLocalF32(v, dest);
             break;
           case Stk::MemF32:
-            fr.popFloat(r);
+            fr.popFloat(dest);
             break;
           case Stk::RegisterF32:
-            loadRegisterF32(r, v);
+            loadRegisterF32(v, dest);
             break;
           case Stk::None:
           default:
             MOZ_CRASH("Compiler bug: expected float on stack");
         }
     }
 
     MOZ_MUST_USE RegF32 popF32() {
@@ -3072,93 +3076,93 @@ class BaseCompiler final : public BaseCo
     // args based on the info we read.
 
     void passArg(FunctionCall& call, ValType type, Stk& arg) {
         switch (type) {
           case ValType::I32: {
             ABIArg argLoc = call.abi.next(MIRType::Int32);
             if (argLoc.kind() == ABIArg::Stack) {
                 ScratchI32 scratch(*this);
-                loadI32(scratch, arg);
+                loadI32(arg, scratch);
                 masm.store32(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
             } else {
-                loadI32(RegI32(argLoc.gpr()), arg);
+                loadI32(arg, RegI32(argLoc.gpr()));
             }
             break;
           }
           case ValType::I64: {
             ABIArg argLoc = call.abi.next(MIRType::Int64);
             if (argLoc.kind() == ABIArg::Stack) {
                 ScratchI32 scratch(*this);
 #if defined(JS_CODEGEN_X64)
-                loadI64(fromI32(scratch), arg);
+                loadI64(arg, fromI32(scratch));
                 masm.movq(scratch, Operand(masm.getStackPointer(), argLoc.offsetFromArgBase()));
 #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
-                loadI64Low(scratch, arg);
+                loadI64Low(arg, scratch);
                 masm.store32(scratch, LowWord(Address(masm.getStackPointer(), argLoc.offsetFromArgBase())));
-                loadI64High(scratch, arg);
+                loadI64High(arg, scratch);
                 masm.store32(scratch, HighWord(Address(masm.getStackPointer(), argLoc.offsetFromArgBase())));
 #else
                 MOZ_CRASH("BaseCompiler platform hook: passArg I64");
 #endif
             } else {
-                loadI64(RegI64(argLoc.gpr64()), arg);
+                loadI64(arg, RegI64(argLoc.gpr64()));
             }
             break;
           }
           case ValType::F64: {
             ABIArg argLoc = call.abi.next(MIRType::Double);
             switch (argLoc.kind()) {
               case ABIArg::Stack: {
                 ScratchF64 scratch(*this);
-                loadF64(scratch, arg);
+                loadF64(arg, scratch);
                 masm.storeDouble(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
                 break;
               }
 #if defined(JS_CODEGEN_REGISTER_PAIR)
               case ABIArg::GPR_PAIR: {
 # ifdef JS_CODEGEN_ARM
                 ScratchF64 scratch(*this);
-                loadF64(scratch, arg);
+                loadF64(arg, scratch);
                 masm.ma_vxfer(scratch, argLoc.evenGpr(), argLoc.oddGpr());
                 break;
 # else
                 MOZ_CRASH("BaseCompiler platform hook: passArg F64 pair");
 # endif
               }
 #endif
               case ABIArg::FPU: {
-                loadF64(RegF64(argLoc.fpu()), arg);
+                loadF64(arg, RegF64(argLoc.fpu()));
                 break;
               }
               case ABIArg::GPR: {
                 MOZ_CRASH("Unexpected parameter passing discipline");
               }
               case ABIArg::Uninitialized:
                 MOZ_CRASH("Uninitialized ABIArg kind");
             }
             break;
           }
           case ValType::F32: {
             ABIArg argLoc = call.abi.next(MIRType::Float32);
             switch (argLoc.kind()) {
               case ABIArg::Stack: {
                 ScratchF32 scratch(*this);
-                loadF32(scratch, arg);
+                loadF32(arg, scratch);
                 masm.storeFloat32(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
                 break;
               }
               case ABIArg::GPR: {
                 ScratchF32 scratch(*this);
-                loadF32(scratch, arg);
+                loadF32(arg, scratch);
                 masm.moveFloat32ToGPR(scratch, argLoc.gpr());
                 break;
               }
               case ABIArg::FPU: {
-                loadF32(RegF32(argLoc.fpu()), arg);
+                loadF32(arg, RegF32(argLoc.fpu()));
                 break;
               }
 #if defined(JS_CODEGEN_REGISTER_PAIR)
               case ABIArg::GPR_PAIR: {
                 MOZ_CRASH("Unexpected parameter passing discipline");
               }
 #endif
               case ABIArg::Uninitialized:
@@ -3187,17 +3191,17 @@ class BaseCompiler final : public BaseCo
     void callIndirect(uint32_t sigIndex, Stk& indexVal, const FunctionCall& call)
     {
         const SigWithId& sig = env_.sigs[sigIndex];
         MOZ_ASSERT(sig.id.kind() != SigIdDesc::Kind::None);
 
         MOZ_ASSERT(env_.tables.length() == 1);
         const TableDesc& table = env_.tables[0];
 
-        loadI32(RegI32(WasmTableCallIndexReg), indexVal);
+        loadI32(indexVal, RegI32(WasmTableCallIndexReg));
 
         CallSiteDesc desc(call.lineOrBytecode, CallSiteDesc::Dynamic);
         CalleeDesc callee = CalleeDesc::wasmTable(table, sig.id);
         masm.wasmCallIndirect(desc, callee, NeedsBoundsCheck(true));
     }
 
     // Precondition: sync()
 
@@ -3247,17 +3251,17 @@ class BaseCompiler final : public BaseCo
     }
 
     void addInterruptCheck()
     {
         // Always use signals for interrupts with Asm.JS/Wasm
         MOZ_RELEASE_ASSERT(HaveSignalHandlers());
     }
 
-    void jumpTable(LabelVector& labels, Label* theTable) {
+    void jumpTable(const LabelVector& labels, Label* theTable) {
         // Flush constant pools to ensure that the table is never interrupted by
         // constant pool entries.
         masm.flush();
 
         masm.bind(theTable);
 
 #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
         for (uint32_t i = 0; i < labels.length(); i++) {