Bug 1213747 - IonMonkey: MIPS64: Import MoveEmitter-mips64. r=nbp f=rankov
authorHeiher <r@hev.cc>
Fri, 30 Oct 2015 19:50:29 +0800
changeset 270397 a2aee5eb3c7bb16a2459b4bfda40ced9d511f0fe
parent 270396 cf640d7a8d0261b8182ba2ec19da97ebbf69d2e3
child 270398 7cafc955419dfbbff7abb489f1109066a57f76db
push id29612
push userkwierso@gmail.com
push dateFri, 30 Oct 2015 23:36:00 +0000
treeherdermozilla-central@1596ab6985cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1213747, 100644
milestone45.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 1213747 - IonMonkey: MIPS64: Import MoveEmitter-mips64. r=nbp f=rankov --- js/src/jit/mips-shared/MoveEmitter-mips-shared.h | 2 +- js/src/jit/mips64/MoveEmitter-mips64.cpp | 155 +++++++++++++++++++++++ js/src/jit/mips64/MoveEmitter-mips64.h | 34 +++++ js/src/moz.build | 1 + 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 js/src/jit/mips64/MoveEmitter-mips64.cpp create mode 100644 js/src/jit/mips64/MoveEmitter-mips64.h
js/src/jit/mips-shared/MoveEmitter-mips-shared.h
js/src/jit/mips64/MoveEmitter-mips64.cpp
js/src/jit/mips64/MoveEmitter-mips64.h
js/src/moz.build
--- a/js/src/jit/mips-shared/MoveEmitter-mips-shared.h
+++ b/js/src/jit/mips-shared/MoveEmitter-mips-shared.h
@@ -32,17 +32,17 @@ class MoveEmitterMIPSShared
     // assigned InvalidReg. If no corresponding spill space has been assigned,
     // then these registers do not need to be spilled.
     Register spilledReg_;
     FloatRegister spilledFloatReg_;
 
     void assertDone();
     Register tempReg();
     FloatRegister tempFloatReg();
-    Address cycleSlot(uint32_t slot, uint32_t subslot) const;
+    Address cycleSlot(uint32_t slot, uint32_t subslot = 0) const;
     int32_t getAdjustedOffset(const MoveOperand& operand);
     Address getAdjustedAddress(const MoveOperand& operand);
 
     void emitMove(const MoveOperand& from, const MoveOperand& to);
     void emitInt32Move(const MoveOperand& from, const MoveOperand& to);
     void emitFloat32Move(const MoveOperand& from, const MoveOperand& to);
     virtual void emitDoubleMove(const MoveOperand& from, const MoveOperand& to) = 0;
     virtual void breakCycle(const MoveOperand& from, const MoveOperand& to,
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips64/MoveEmitter-mips64.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/mips64/MoveEmitter-mips64.h"
+
+#include "jit/MacroAssembler-inl.h"
+
+using namespace js;
+using namespace js::jit;
+
+void
+MoveEmitterMIPS64::breakCycle(const MoveOperand& from, const MoveOperand& to,
+                              MoveOp::Type type, uint32_t slotId)
+{
+    // There is some pattern:
+    //   (A -> B)
+    //   (B -> A)
+    //
+    // This case handles (A -> B), which we reach first. We save B, then allow
+    // the original move to continue.
+    switch (type) {
+      case MoveOp::FLOAT32:
+        if (to.isMemory()) {
+            FloatRegister temp = ScratchFloat32Reg;
+            masm.loadFloat32(getAdjustedAddress(to), temp);
+            masm.storeFloat32(temp, cycleSlot(slotId));
+        } else {
+            masm.storeFloat32(to.floatReg(), cycleSlot(slotId));
+        }
+        break;
+      case MoveOp::DOUBLE:
+        if (to.isMemory()) {
+            FloatRegister temp = ScratchDoubleReg;
+            masm.loadDouble(getAdjustedAddress(to), temp);
+            masm.storeDouble(temp, cycleSlot(slotId));
+        } else {
+            masm.storeDouble(to.floatReg(), cycleSlot(slotId));
+        }
+        break;
+      case MoveOp::INT32:
+        if (to.isMemory()) {
+            Register temp = tempReg();
+            masm.load32(getAdjustedAddress(to), temp);
+            masm.store32(temp, cycleSlot(0));
+        } else {
+            // Second scratch register should not be moved by MoveEmitter.
+            MOZ_ASSERT(to.reg() != spilledReg_);
+            masm.store32(to.reg(), cycleSlot(0));
+        }
+        break;
+      case MoveOp::GENERAL:
+        if (to.isMemory()) {
+            Register temp = tempReg();
+            masm.loadPtr(getAdjustedAddress(to), temp);
+            masm.storePtr(temp, cycleSlot(0));
+        } else {
+            // Second scratch register should not be moved by MoveEmitter.
+            MOZ_ASSERT(to.reg() != spilledReg_);
+            masm.storePtr(to.reg(), cycleSlot(0));
+        }
+        break;
+      default:
+        MOZ_CRASH("Unexpected move type");
+    }
+}
+
+void
+MoveEmitterMIPS64::completeCycle(const MoveOperand& from, const MoveOperand& to,
+                                 MoveOp::Type type, uint32_t slotId)
+{
+    // There is some pattern:
+    //   (A -> B)
+    //   (B -> A)
+    //
+    // This case handles (B -> A), which we reach last. We emit a move from the
+    // saved value of B, to A.
+    switch (type) {
+      case MoveOp::FLOAT32:
+        if (to.isMemory()) {
+            FloatRegister temp = ScratchFloat32Reg;
+            masm.loadFloat32(cycleSlot(slotId), temp);
+            masm.storeFloat32(temp, getAdjustedAddress(to));
+        } else {
+            masm.loadFloat32(cycleSlot(slotId), to.floatReg());
+        }
+        break;
+      case MoveOp::DOUBLE:
+        if (to.isMemory()) {
+            FloatRegister temp = ScratchDoubleReg;
+            masm.loadDouble(cycleSlot(slotId), temp);
+            masm.storeDouble(temp, getAdjustedAddress(to));
+        } else {
+            masm.loadDouble(cycleSlot(slotId), to.floatReg());
+        }
+        break;
+      case MoveOp::INT32:
+        MOZ_ASSERT(slotId == 0);
+        if (to.isMemory()) {
+            Register temp = tempReg();
+            masm.load32(cycleSlot(0), temp);
+            masm.store32(temp, getAdjustedAddress(to));
+        } else {
+            // Second scratch register should not be moved by MoveEmitter.
+            MOZ_ASSERT(to.reg() != spilledReg_);
+            masm.load32(cycleSlot(0), to.reg());
+        }
+        break;
+      case MoveOp::GENERAL:
+        MOZ_ASSERT(slotId == 0);
+        if (to.isMemory()) {
+            Register temp = tempReg();
+            masm.loadPtr(cycleSlot(0), temp);
+            masm.storePtr(temp, getAdjustedAddress(to));
+        } else {
+            // Second scratch register should not be moved by MoveEmitter.
+            MOZ_ASSERT(to.reg() != spilledReg_);
+            masm.loadPtr(cycleSlot(0), to.reg());
+        }
+        break;
+      default:
+        MOZ_CRASH("Unexpected move type");
+    }
+}
+
+void
+MoveEmitterMIPS64::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
+{
+    // Ensure that we can use ScratchDoubleReg in memory move.
+    MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchDoubleReg);
+    MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchDoubleReg);
+
+    if (from.isFloatReg()) {
+        if (to.isFloatReg()) {
+            masm.moveDouble(from.floatReg(), to.floatReg());
+        } else if (to.isGeneralReg()) {
+            masm.moveFromDouble(from.floatReg(), to.reg());
+        } else {
+            MOZ_ASSERT(to.isMemory());
+            masm.storeDouble(from.floatReg(), getAdjustedAddress(to));
+        }
+    } else if (to.isFloatReg()) {
+        if (from.isMemory())
+          masm.loadDouble(getAdjustedAddress(from), to.floatReg());
+        else
+          masm.moveToDouble(from.reg(), to.floatReg());
+    } else {
+        MOZ_ASSERT(from.isMemory());
+        MOZ_ASSERT(to.isMemory());
+        masm.loadDouble(getAdjustedAddress(from), ScratchDoubleReg);
+        masm.storeDouble(ScratchDoubleReg, getAdjustedAddress(to));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips64/MoveEmitter-mips64.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_mips64_MoveEmitter_mips64_h
+#define jit_mips64_MoveEmitter_mips64_h
+
+#include "jit/mips-shared/MoveEmitter-mips-shared.h"
+
+namespace js {
+namespace jit {
+
+class MoveEmitterMIPS64 : public MoveEmitterMIPSShared
+{
+    void emitDoubleMove(const MoveOperand& from, const MoveOperand& to);
+    void breakCycle(const MoveOperand& from, const MoveOperand& to,
+                    MoveOp::Type type, uint32_t slot);
+    void completeCycle(const MoveOperand& from, const MoveOperand& to,
+                       MoveOp::Type type, uint32_t slot);
+
+  public:
+    MoveEmitterMIPS64(MacroAssembler& masm)
+      : MoveEmitterMIPSShared(masm)
+    { }
+};
+
+typedef MoveEmitterMIPS64 MoveEmitter;
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_mips64_MoveEmitter_mips64_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -512,16 +512,17 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONF
         UNIFIED_SOURCES += [
             'jit/mips64/Architecture-mips64.cpp',
             'jit/mips64/Assembler-mips64.cpp',
             'jit/mips64/Bailouts-mips64.cpp',
             'jit/mips64/BaselineCompiler-mips64.cpp',
             'jit/mips64/BaselineIC-mips64.cpp',
             'jit/mips64/CodeGenerator-mips64.cpp',
             'jit/mips64/Lowering-mips64.cpp',
+            'jit/mips64/MoveEmitter-mips64.cpp',
             'jit/mips64/SharedIC-mips64.cpp',
             'jit/mips64/Trampoline-mips64.cpp',
         ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'jit/ExecutableAllocatorWin.cpp',
     ]