Bug 1213749 - IonMonkey: MIPS64: Import SharedIC-mips64. r=nbp f=rankov
authorHeiher <r@hev.cc>
Sun, 25 Oct 2015 06:01:59 +0800
changeset 304562 16c2a146a49396e19b433dc958cca731065e45e7
parent 304561 682060676362c22c3a3141f0b73a1566869e8745
child 304563 ebd106bca18d38a40fbafb5ad5ec132b421854dc
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1213749, 100644
milestone44.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 1213749 - IonMonkey: MIPS64: Import SharedIC-mips64. r=nbp f=rankov --- js/src/jit/mips64/SharedIC-mips64.cpp | 191 +++++++++++++++ js/src/jit/mips64/SharedICHelpers-mips64.h | 350 +++++++++++++++++++++++++++ js/src/jit/mips64/SharedICRegisters-mips64.h | 47 ++++ js/src/moz.build | 1 + 4 files changed, 589 insertions(+) create mode 100644 js/src/jit/mips64/SharedIC-mips64.cpp create mode 100644 js/src/jit/mips64/SharedICHelpers-mips64.h create mode 100644 js/src/jit/mips64/SharedICRegisters-mips64.h
js/src/jit/mips64/SharedIC-mips64.cpp
js/src/jit/mips64/SharedICHelpers-mips64.h
js/src/jit/mips64/SharedICRegisters-mips64.h
js/src/moz.build
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips64/SharedIC-mips64.cpp
@@ -0,0 +1,191 @@
+/* -*- 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 "jsiter.h"
+
+#include "jit/BaselineCompiler.h"
+#include "jit/BaselineIC.h"
+#include "jit/BaselineJIT.h"
+#include "jit/Linker.h"
+#include "jit/SharedICHelpers.h"
+
+#include "jsboolinlines.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // Add R0 and R1. Don't need to explicitly unbox, just use R2's valueReg.
+    Register scratchReg = R2.valueReg();
+
+    Label goodMul, divTest1, divTest2;
+    switch(op_) {
+      case JSOP_ADD:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        masm.ma_addTestOverflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
+        masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
+        break;
+      case JSOP_SUB:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        masm.ma_subTestOverflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
+        masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
+        break;
+      case JSOP_MUL: {
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        masm.ma_mul_branch_overflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
+
+        masm.ma_b(scratchReg, Imm32(0), &goodMul, Assembler::NotEqual, ShortJump);
+
+        // Result is -0 if operands have different signs.
+        masm.as_xor(t8, ExtractTemp0, ExtractTemp1);
+        masm.ma_b(t8, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+
+        masm.bind(&goodMul);
+        masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
+        break;
+      }
+      case JSOP_DIV:
+      case JSOP_MOD: {
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        // Check for INT_MIN / -1, it results in a double.
+        masm.ma_b(ExtractTemp0, Imm32(INT_MIN), &divTest1, Assembler::NotEqual, ShortJump);
+        masm.ma_b(ExtractTemp1, Imm32(-1), &failure, Assembler::Equal, ShortJump);
+        masm.bind(&divTest1);
+
+        // Check for division by zero
+        masm.ma_b(ExtractTemp1, Imm32(0), &failure, Assembler::Equal, ShortJump);
+
+        // Check for 0 / X with X < 0 (results in -0).
+        masm.ma_b(ExtractTemp0, Imm32(0), &divTest2, Assembler::NotEqual, ShortJump);
+        masm.ma_b(ExtractTemp1, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+        masm.bind(&divTest2);
+
+        masm.as_div(ExtractTemp0, ExtractTemp1);
+
+        if (op_ == JSOP_DIV) {
+            // Result is a double if the remainder != 0.
+            masm.as_mfhi(scratchReg);
+            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::NotEqual, ShortJump);
+            masm.as_mflo(scratchReg);
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        } else {
+            Label done;
+            // If X % Y == 0 and X < 0, the result is -0.
+            masm.as_mfhi(scratchReg);
+            masm.ma_b(scratchReg, Imm32(0), &done, Assembler::NotEqual, ShortJump);
+            masm.ma_b(ExtractTemp0, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+            masm.bind(&done);
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        }
+        break;
+      }
+      case JSOP_BITOR:
+        masm.as_or(R0.valueReg() , R0.valueReg(), R1.valueReg());
+        break;
+      case JSOP_BITXOR:
+        masm.as_xor(scratchReg, R0.valueReg(), R1.valueReg());
+        masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        break;
+      case JSOP_BITAND:
+        masm.as_and(R0.valueReg() , R0.valueReg(), R1.valueReg());
+        break;
+      case JSOP_LSH:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        // MIPS will only use 5 lowest bits in R1 as shift offset.
+        masm.ma_sll(scratchReg, ExtractTemp0, ExtractTemp1);
+        masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        break;
+      case JSOP_RSH:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        masm.ma_sra(scratchReg, ExtractTemp0, ExtractTemp1);
+        masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        break;
+      case JSOP_URSH:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ExtractTemp1);
+        masm.ma_srl(scratchReg, ExtractTemp0, ExtractTemp1);
+        if (allowDouble_) {
+            Label toUint;
+            masm.ma_b(scratchReg, Imm32(0), &toUint, Assembler::LessThan, ShortJump);
+
+            // Move result and box for return.
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            masm.convertUInt32ToDouble(scratchReg, FloatReg1);
+            masm.boxDouble(FloatReg1, R0);
+        } else {
+            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+            // Move result for return.
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        }
+        break;
+      default:
+        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
+    }
+
+    EmitReturnFromIC(masm);
+
+    // Failure case - jump to next stub
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.not32(R0.valueReg());
+        masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
+        break;
+      case JSOP_NEG:
+        masm.unboxInt32(R0, ExtractTemp0);
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, ExtractTemp0, Imm32(INT32_MAX), &failure);
+
+        masm.neg32(ExtractTemp0);
+        masm.tagValue(JSVAL_TYPE_INT32, ExtractTemp0, R0);
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+        return false;
+    }
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
+
+} // namespace jit
+} // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips64/SharedICHelpers-mips64.h
@@ -0,0 +1,350 @@
+/* -*- 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_SharedICHelpers_mips64_h
+#define jit_mips64_SharedICHelpers_mips64_h
+
+#include "jit/BaselineFrame.h"
+#include "jit/BaselineIC.h"
+#include "jit/MacroAssembler.h"
+#include "jit/SharedICRegisters.h"
+
+namespace js {
+namespace jit {
+
+// Distance from sp to the top Value inside an IC stub (no return address on
+// the stack on MIPS).
+static const size_t ICStackValueOffset = 0;
+
+inline void
+EmitRestoreTailCallReg(MacroAssembler& masm)
+{
+    // No-op on MIPS because ra register is always holding the return address.
+}
+
+inline void
+EmitRepushTailCallReg(MacroAssembler& masm)
+{
+    // No-op on MIPS because ra register is always holding the return address.
+}
+
+inline void
+EmitCallIC(CodeOffsetLabel* patchOffset, MacroAssembler& masm)
+{
+    // Move ICEntry offset into ICStubReg.
+    CodeOffsetLabel offset = masm.movWithPatch(ImmWord(-1), ICStubReg);
+    *patchOffset = offset;
+
+    // Load stub pointer into ICStubReg.
+    masm.loadPtr(Address(ICStubReg, ICEntry::offsetOfFirstStub()), ICStubReg);
+
+    // Load stubcode pointer from BaselineStubEntry.
+    // R2 won't be active when we call ICs, so we can use it as scratch.
+    masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
+
+    // Call the stubcode via a direct jump-and-link
+    masm.call(R2.scratchReg());
+}
+
+inline void
+EmitEnterTypeMonitorIC(MacroAssembler& masm,
+                       size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
+{
+    // This is expected to be called from within an IC, when ICStubReg
+    // is properly initialized to point to the stub.
+    masm.loadPtr(Address(ICStubReg, (uint32_t) monitorStubOffset), ICStubReg);
+
+    // Load stubcode pointer from BaselineStubEntry.
+    // R2 won't be active when we call ICs, so we can use it.
+    masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
+
+    // Jump to the stubcode.
+    masm.branch(R2.scratchReg());
+}
+
+inline void
+EmitReturnFromIC(MacroAssembler& masm)
+{
+    masm.branch(ra);
+}
+
+inline void
+EmitChangeICReturnAddress(MacroAssembler& masm, Register reg)
+{
+    masm.movePtr(reg, ra);
+}
+
+inline void
+EmitBaselineTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t argSize)
+{
+    // We assume during this that R0 and R1 have been pushed, and that R2 is
+    // unused.
+    MOZ_ASSERT(R2 == ValueOperand(a6));
+
+    // Compute frame size.
+    masm.movePtr(BaselineFrameReg, a6);
+    masm.addPtr(Imm32(BaselineFrame::FramePointerOffset), a6);
+    masm.subPtr(BaselineStackReg, a6);
+
+    // Store frame size without VMFunction arguments for GC marking.
+    masm.ma_dsubu(a7, a6, Imm32(argSize));
+    masm.store32(a7, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
+
+    // Push frame descriptor and perform the tail call.
+    // ICTailCallReg (ra) already contains the return address (as we
+    // keep it there through the stub calls), but the VMWrapper code being
+    // called expects the return address to also be pushed on the stack.
+    MOZ_ASSERT(ICTailCallReg == ra);
+    masm.makeFrameDescriptor(a6, JitFrame_BaselineJS);
+    masm.subPtr(Imm32(sizeof(CommonFrameLayout)), StackPointer);
+    masm.storePtr(a6, Address(StackPointer, CommonFrameLayout::offsetOfDescriptor()));
+    masm.storePtr(ra, Address(StackPointer, CommonFrameLayout::offsetOfReturnAddress()));
+
+    masm.branch(target);
+}
+
+inline void
+EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
+{
+    MOZ_CRASH("Not implemented yet.");
+}
+
+inline void
+EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
+{
+    // Compute stub frame size. We have to add two pointers: the stub reg and
+    // previous frame pointer pushed by EmitEnterStubFrame.
+    masm.movePtr(BaselineFrameReg, reg);
+    masm.addPtr(Imm32(sizeof(intptr_t) * 2), reg);
+    masm.subPtr(BaselineStackReg, reg);
+
+    masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
+}
+
+inline void
+EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
+{
+    EmitBaselineCreateStubFrameDescriptor(masm, a6);
+    masm.push(a6);
+    masm.call(target);
+}
+
+inline void
+EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
+{
+    MOZ_CRASH("Not implemented yet.");
+}
+
+struct BaselineStubFrame {
+    uintptr_t savedFrame;
+    uintptr_t savedStub;
+    uintptr_t returnAddress;
+    uintptr_t descriptor;
+};
+
+static const uint32_t STUB_FRAME_SIZE = sizeof(BaselineStubFrame);
+static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = offsetof(BaselineStubFrame, savedStub);
+
+inline void
+EmitBaselineEnterStubFrame(MacroAssembler& masm, Register scratch)
+{
+    MOZ_ASSERT(scratch != ICTailCallReg);
+
+    // Compute frame size.
+    masm.movePtr(BaselineFrameReg, scratch);
+    masm.addPtr(Imm32(BaselineFrame::FramePointerOffset), scratch);
+    masm.subPtr(BaselineStackReg, scratch);
+
+    masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
+
+    // Note: when making changes here, don't forget to update
+    // BaselineStubFrame if needed.
+
+    // Push frame descriptor and return address.
+    masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
+    masm.subPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
+    masm.storePtr(scratch, Address(StackPointer, offsetof(BaselineStubFrame, descriptor)));
+    masm.storePtr(ICTailCallReg, Address(StackPointer,
+                                               offsetof(BaselineStubFrame, returnAddress)));
+
+    // Save old frame pointer, stack pointer and stub reg.
+    masm.storePtr(ICStubReg, Address(StackPointer,
+                                           offsetof(BaselineStubFrame, savedStub)));
+    masm.storePtr(BaselineFrameReg, Address(StackPointer,
+                                            offsetof(BaselineStubFrame, savedFrame)));
+    masm.movePtr(BaselineStackReg, BaselineFrameReg);
+}
+
+inline void
+EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
+{
+    MOZ_CRASH("Not implemented yet.");
+}
+
+inline void
+EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
+{
+    // Ion frames do not save and restore the frame pointer. If we called
+    // into Ion, we have to restore the stack pointer from the frame descriptor.
+    // If we performed a VM call, the descriptor has been popped already so
+    // in that case we use the frame pointer.
+    if (calledIntoIon) {
+        masm.pop(ScratchRegister);
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), ScratchRegister);
+        masm.addPtr(ScratchRegister, BaselineStackReg);
+    } else {
+        masm.movePtr(BaselineFrameReg, BaselineStackReg);
+    }
+
+    masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, savedFrame)),
+                 BaselineFrameReg);
+    masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, savedStub)),
+                 ICStubReg);
+
+    // Load the return address.
+    masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, returnAddress)),
+                 ICTailCallReg);
+
+    // Discard the frame descriptor.
+    masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, descriptor)), ScratchRegister);
+    masm.addPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
+}
+
+inline void
+EmitIonLeaveStubFrame(MacroAssembler& masm)
+{
+    MOZ_CRASH("Not implemented yet.");
+}
+
+inline void
+EmitStowICValues(MacroAssembler& masm, int values)
+{
+    MOZ_ASSERT(values >= 0 && values <= 2);
+    switch(values) {
+      case 1:
+        // Stow R0
+        masm.pushValue(R0);
+        break;
+      case 2:
+        // Stow R0 and R1
+        masm.pushValue(R0);
+        masm.pushValue(R1);
+        break;
+    }
+}
+
+inline void
+EmitUnstowICValues(MacroAssembler& masm, int values, bool discard = false)
+{
+    MOZ_ASSERT(values >= 0 && values <= 2);
+    switch(values) {
+      case 1:
+        // Unstow R0.
+        if (discard)
+            masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
+        else
+            masm.popValue(R0);
+        break;
+      case 2:
+        // Unstow R0 and R1.
+        if (discard) {
+            masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
+        } else {
+            masm.popValue(R1);
+            masm.popValue(R0);
+        }
+        break;
+    }
+}
+
+inline void
+EmitCallTypeUpdateIC(MacroAssembler& masm, JitCode* code, uint32_t objectOffset)
+{
+    // R0 contains the value that needs to be typechecked.
+    // The object we're updating is a boxed Value on the stack, at offset
+    // objectOffset from $sp, excluding the return address.
+
+    // Save the current ICStubReg to stack, as well as the TailCallReg,
+    // since on mips, the $ra is live.
+    masm.subPtr(Imm32(2 * sizeof(intptr_t)), StackPointer);
+    masm.storePtr(ICStubReg, Address(StackPointer, sizeof(intptr_t)));
+    masm.storePtr(ICTailCallReg, Address(StackPointer, 0));
+
+    // This is expected to be called from within an IC, when ICStubReg
+    // is properly initialized to point to the stub.
+    masm.loadPtr(Address(ICStubReg, ICUpdatedStub::offsetOfFirstUpdateStub()),
+                 ICStubReg);
+
+    // Load stubcode pointer from ICStubReg into ICTailCallReg.
+    masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
+
+    // Call the stubcode.
+    masm.call(R2.scratchReg());
+
+    // Restore the old stub reg and tailcall reg.
+    masm.loadPtr(Address(StackPointer, 0), ICTailCallReg);
+    masm.loadPtr(Address(StackPointer, sizeof(intptr_t)), ICStubReg);
+    masm.addPtr(Imm32(2 * sizeof(intptr_t)), StackPointer);
+
+    // The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
+    // value in R0 type-checked properly or not.
+    Label success;
+    masm.ma_b(R1.scratchReg(), Imm32(1), &success, Assembler::Equal, ShortJump);
+
+    // If the IC failed, then call the update fallback function.
+    EmitBaselineEnterStubFrame(masm, R1.scratchReg());
+
+    masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
+
+    masm.pushValue(R0);
+    masm.pushValue(R1);
+    masm.push(ICStubReg);
+
+    // Load previous frame pointer, push BaselineFrame*.
+    masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
+    masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
+
+    EmitBaselineCallVM(code, masm);
+    EmitBaselineLeaveStubFrame(masm);
+
+    // Success at end.
+    masm.bind(&success);
+}
+
+template <typename AddrType>
+inline void
+EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
+{
+    // On MIPS, $ra is clobbered by patchableCallPreBarrier. Save it first.
+    masm.push(ra);
+    masm.patchableCallPreBarrier(addr, type);
+    masm.pop(ra);
+}
+
+inline void
+EmitStubGuardFailure(MacroAssembler& masm)
+{
+    // NOTE: This routine assumes that the stub guard code left the stack in
+    // the same state it was in when it was entered.
+
+    // BaselineStubEntry points to the current stub.
+
+    // Load next stub into ICStubReg
+    masm.loadPtr(Address(ICStubReg, ICStub::offsetOfNext()), ICStubReg);
+
+    // Load stubcode pointer from BaselineStubEntry into scratch register.
+    masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
+
+    // Return address is already loaded, just jump to the next stubcode.
+    MOZ_ASSERT(ICTailCallReg == ra);
+    masm.branch(R2.scratchReg());
+}
+
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_mips64_SharedICHelpers_mips64_h */
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips64/SharedICRegisters-mips64.h
@@ -0,0 +1,47 @@
+/* -*- 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_SharedICRegisters_mips64_h
+#define jit_mips64_SharedICRegisters_mips64_h
+
+#include "jit/MacroAssembler.h"
+
+namespace js {
+namespace jit {
+
+static MOZ_CONSTEXPR_VAR Register BaselineFrameReg = s5;
+static MOZ_CONSTEXPR_VAR Register BaselineStackReg = sp;
+
+// ValueOperands R0, R1, and R2.
+// R0 == JSReturnReg, and R2 uses registers not preserved across calls. R1 value
+// should be preserved across calls.
+static MOZ_CONSTEXPR_VAR ValueOperand R0(v1);
+static MOZ_CONSTEXPR_VAR ValueOperand R1(s4);
+static MOZ_CONSTEXPR_VAR ValueOperand R2(a6);
+
+// ICTailCallReg and ICStubReg
+// These use registers that are not preserved across calls.
+static MOZ_CONSTEXPR_VAR Register ICTailCallReg = ra;
+static MOZ_CONSTEXPR_VAR Register ICStubReg = a5;
+
+static MOZ_CONSTEXPR_VAR Register ExtractTemp0 = s6;
+static MOZ_CONSTEXPR_VAR Register ExtractTemp1 = s7;
+
+// Register used internally by MacroAssemblerMIPS.
+static MOZ_CONSTEXPR_VAR Register BaselineSecondScratchReg = SecondScratchReg;
+
+// Note that ICTailCallReg is actually just the link register.
+// In MIPS code emission, we do not clobber ICTailCallReg since we keep
+// the return address for calls there.
+
+// FloatReg0 must be equal to ReturnFloatReg.
+static MOZ_CONSTEXPR_VAR FloatRegister FloatReg0 = f0;
+static MOZ_CONSTEXPR_VAR FloatRegister FloatReg1 = f2;
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_mips64_SharedICRegisters_mips64_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -510,16 +510,17 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONF
     elif CONFIG['JS_CODEGEN_MIPS64']:
         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/Lowering-mips64.cpp',
+            'jit/mips64/SharedIC-mips64.cpp',
         ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'jit/ExecutableAllocatorWin.cpp',
     ]
     # _CRT_RAND_S must be #defined before #including stdlib.h to get rand_s()
     DEFINES['_CRT_RAND_S'] = True