Bug 1544631 - Fix functions: branchTestBigInt, negPtr, generateVMWrapper on MIPS. r=jandem
authorqiaopengcheng <qiaopengcheng-hf@loongson.cn>
Wed, 17 Apr 2019 11:56:02 +0000
changeset 470059 00719f1766c13085d3d7685444fa64d41eb8555b
parent 470051 74dc09642c222e18634f4f13e7b0bd6b7f91cbc2
child 470060 448a0265509b6f1f75863f820a03a88efa72d7fb
push id112843
push useraiakab@mozilla.com
push dateFri, 19 Apr 2019 09:50:22 +0000
treeherdermozilla-inbound@c06f27cbfe40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1544631
milestone68.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 1544631 - Fix functions: branchTestBigInt, negPtr, generateVMWrapper on MIPS. r=jandem Fix functions: branchTestBigInt, negPtr, generateVMWrapper on MIPS. Differential Revision: https://phabricator.services.mozilla.com/D27658
js/src/jit/mips32/MacroAssembler-mips32-inl.h
js/src/jit/mips32/Trampoline-mips32.cpp
js/src/jit/mips64/MacroAssembler-mips64-inl.h
js/src/jit/mips64/Trampoline-mips64.cpp
--- a/js/src/jit/mips32/MacroAssembler-mips32-inl.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32-inl.h
@@ -296,16 +296,18 @@ void MacroAssembler::mul64(const Registe
 
 void MacroAssembler::neg64(Register64 reg) {
   as_subu(ScratchRegister, zero, reg.low);
   as_sltu(ScratchRegister, reg.low, ScratchRegister);
   as_subu(reg.high, zero, reg.high);
   as_subu(reg.high, reg.high, ScratchRegister);
 }
 
+void MacroAssembler::negPtr(Register reg) { as_subu(reg, zero, reg); }
+
 void MacroAssembler::mulBy3(Register src, Register dest) {
   MOZ_ASSERT(src != ScratchRegister);
   as_addu(ScratchRegister, src, src);
   as_addu(dest, ScratchRegister, src);
 }
 
 void MacroAssembler::inc64(AbsoluteAddress dest) {
   ma_li(ScratchRegister, Imm32((int32_t)dest.addr));
@@ -809,16 +811,28 @@ void MacroAssembler::branchTestStringTru
   ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
 }
 
 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
                                       Label* label) {
   branchTestSymbol(cond, value.typeReg(), label);
 }
 
+void MacroAssembler::branchTestBigInt(Condition cond, Register tag,
+                                      Label* label) {
+  branchTestBigIntImpl(cond, tag, label);
+}
+
+void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
+                                      Label* label) {
+  SecondScratchRegisterScope scratch2(*this);
+  splitTag(value, scratch2);
+  branchTestBigInt(cond, scratch2, label);
+}
+
 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
                                       Label* label) {
   branchTestBigInt(cond, value.typeReg(), label);
 }
 
 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value,
                                             Label* label) {
   Register bi = value.payloadReg();
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -16,16 +16,17 @@
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "vm/Realm.h"
 
 #include "jit/MacroAssembler-inl.h"
 #include "jit/SharedICHelpers-inl.h"
+#include "jit/VMFunctionList-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 static_assert(sizeof(uintptr_t) == sizeof(uint32_t), "Not 64-bit clean.");
 
 struct EnterJITRegs {
   double f30;
@@ -667,21 +668,22 @@ JitRuntime::BailoutTable JitRuntime::gen
 void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
                                         Label* bailoutTail) {
   bailoutHandlerOffset_ = startTrampolineCode(masm);
 
   GenerateBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID, bailoutTail);
 }
 
 bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
-                                   const VMFunction& f) {
-  MOZ_ASSERT(functionWrappers_);
+                                   const VMFunctionData& f, void* nativeFun,
+                                   uint32_t* wrapperOffset) {
+  *wrapperOffset = startTrampolineCode(masm);
 
-  uint32_t wrapperOffset = startTrampolineCode(masm);
-
+  // Avoid conflicts with argument registers while discarding the result after
+  // the function call.
   AllocatableGeneralRegisterSet regs(Register::Codes::WrapperMask);
 
   static_assert(
       (Register::Codes::VolatileMask & ~Register::Codes::WrapperMask) == 0,
       "Wrapper register set should be a superset of Volatile register set.");
 
   // The context is the first argument; a0 is the first argument register.
   Register cxreg = a0;
@@ -762,34 +764,34 @@ bool JitRuntime::generateVMWrapper(JSCon
   masm.passABIArg(cxreg);
 
   size_t argDisp = 0;
   size_t doubleArgDisp = 0;
 
   // Copy any arguments.
   for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
     switch (f.argProperties(explicitArg)) {
-      case VMFunction::WordByValue:
+      case VMFunctionData::WordByValue:
         masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
         argDisp += sizeof(uint32_t);
         break;
-      case VMFunction::DoubleByValue:
+      case VMFunctionData::DoubleByValue:
         // Values should be passed by reference, not by value, so we
         // assert that the argument is a double-precision float.
         MOZ_ASSERT(f.argPassedInFloatReg(explicitArg));
         masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::DOUBLE);
         argDisp += sizeof(double);
         break;
-      case VMFunction::WordByRef:
+      case VMFunctionData::WordByRef:
         masm.passABIArg(
             MoveOperand(argsBase, argDisp, MoveOperand::EFFECTIVE_ADDRESS),
             MoveOp::GENERAL);
         argDisp += sizeof(uint32_t);
         break;
-      case VMFunction::DoubleByRef:
+      case VMFunctionData::DoubleByRef:
         // Copy double sized argument to aligned place.
         masm.ma_ldc1WordAligned(ScratchDoubleReg, argsBase, argDisp);
         masm.as_sdc1(ScratchDoubleReg, doubleArgs, doubleArgDisp);
         masm.passABIArg(MoveOperand(doubleArgs, doubleArgDisp,
                                     MoveOperand::EFFECTIVE_ADDRESS),
                         MoveOp::GENERAL);
         doubleArgDisp += sizeof(double);
         argDisp += sizeof(double);
@@ -802,17 +804,17 @@ bool JitRuntime::generateVMWrapper(JSCon
 
   // Copy the implicit outparam, if any.
   if (f.outParam != Type_Void) {
     masm.passABIArg(
         MoveOperand(doubleArgs, outParamOffset, MoveOperand::EFFECTIVE_ADDRESS),
         MoveOp::GENERAL);
   }
 
-  masm.callWithABI(f.wrapped, MoveOp::GENERAL,
+  masm.callWithABI(nativeFun, MoveOp::GENERAL,
                    CheckUnsafeCallWithABI::DontCheckHasExitFrame);
 
   if (!generateTLExitVM(masm, f)) {
     return false;
   }
 
   // Test for failure.
   switch (f.failType()) {
@@ -873,17 +875,17 @@ bool JitRuntime::generateVMWrapper(JSCon
   masm.restoreStackPointer();
   masm.setFramePushed(framePushedBeforeAlignStack);
 
   masm.leaveExitFrame();
   masm.retn(Imm32(sizeof(ExitFrameLayout) +
                   f.explicitStackSlots() * sizeof(uintptr_t) +
                   f.extraValuesToPop * sizeof(Value)));
 
-  return functionWrappers_->putNew(&f, wrapperOffset);
+  return true;
 }
 
 uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,
                                         MIRType type) {
   uint32_t offset = startTrampolineCode(masm);
 
   MOZ_ASSERT(PreBarrierReg == a1);
   Register temp1 = a0;
@@ -928,38 +930,35 @@ uint32_t JitRuntime::generatePreBarrier(
   masm.pop(temp3);
   masm.pop(temp2);
   masm.pop(temp1);
   masm.abiret();
 
   return offset;
 }
 
-typedef bool (*HandleDebugTrapFn)(JSContext*, BaselineFrame*, uint8_t*, bool*);
-static const VMFunction HandleDebugTrapInfo =
-    FunctionInfo<HandleDebugTrapFn>(HandleDebugTrap, "HandleDebugTrap");
-
 JitCode* JitRuntime::generateDebugTrapHandler(JSContext* cx) {
   StackMacroAssembler masm(cx);
 
   Register scratch1 = t0;
   Register scratch2 = t1;
 
   // Load BaselineFrame pointer in scratch1.
   masm.movePtr(s5, scratch1);
   masm.subPtr(Imm32(BaselineFrame::Size()), scratch1);
 
   // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
   // the stub frame has a nullptr ICStub pointer, since this pointer is
   // marked during GC.
   masm.movePtr(ImmPtr(nullptr), ICStubReg);
   EmitBaselineEnterStubFrame(masm, scratch2);
 
-  TrampolinePtr code =
-      cx->runtime()->jitRuntime()->getVMWrapper(HandleDebugTrapInfo);
+  using Fn = bool (*)(JSContext*, BaselineFrame*, uint8_t*, bool*);
+  VMFunctionId id = VMFunctionToId<Fn, jit::HandleDebugTrap>::id;
+  TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
 
   masm.subPtr(Imm32(2 * sizeof(uintptr_t)), StackPointer);
   masm.storePtr(ra, Address(StackPointer, sizeof(uintptr_t)));
   masm.storePtr(scratch1, Address(StackPointer, 0));
 
   EmitBaselineCallVM(code, masm);
 
   EmitBaselineLeaveStubFrame(masm);
--- a/js/src/jit/mips64/MacroAssembler-mips64-inl.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h
@@ -50,16 +50,23 @@ void MacroAssembler::move16To64SignExten
   move16SignExtend(dest.reg, dest.reg);
 }
 
 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) {
   ma_sll(dest.reg, src, Imm32(0));
 }
 
 // ===============================================================
+// Load instructions
+
+void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) {
+  loadPtr(src, dest);
+}
+
+// ===============================================================
 // Logical instructions
 
 void MacroAssembler::andPtr(Register src, Register dest) { ma_and(dest, src); }
 
 void MacroAssembler::andPtr(Imm32 imm, Register dest) { ma_and(dest, imm); }
 
 void MacroAssembler::and64(Imm64 imm, Register64 dest) {
   ma_li(ScratchRegister, ImmWord(imm.value));
@@ -255,16 +262,18 @@ void MacroAssembler::inc64(AbsoluteAddre
   ma_li(ScratchRegister, ImmWord(uintptr_t(dest.addr)));
   as_ld(SecondScratchReg, ScratchRegister, 0);
   as_daddiu(SecondScratchReg, SecondScratchReg, 1);
   as_sd(SecondScratchReg, ScratchRegister, 0);
 }
 
 void MacroAssembler::neg64(Register64 reg) { as_dsubu(reg.reg, zero, reg.reg); }
 
+void MacroAssembler::negPtr(Register reg) { as_dsubu(reg, zero, reg); }
+
 // ===============================================================
 // Shift functions
 
 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) {
   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
   ma_dsll(dest, dest, imm);
 }
 
@@ -541,16 +550,30 @@ void MacroAssembler::branchTestStringTru
 
 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
                                       Label* label) {
   SecondScratchRegisterScope scratch2(*this);
   splitTag(value, scratch2);
   branchTestSymbol(cond, scratch2, label);
 }
 
+void MacroAssembler::branchTestBigInt(Condition cond, Register tag,
+                                      Label* label) {
+  MOZ_ASSERT(cond == Equal || cond == NotEqual);
+  ma_b(tag, ImmTag(JSVAL_TAG_BIGINT), label, cond);
+}
+
+void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
+                                      Label* label) {
+  SecondScratchRegisterScope scratch2(*this);
+  computeEffectiveAddress(address, scratch2);
+  splitTag(scratch2, scratch2);
+  branchTestBigInt(cond, scratch2, label);
+}
+
 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
                                       Label* label) {
   SecondScratchRegisterScope scratch2(*this);
   splitTag(value, scratch2);
   branchTestBigInt(cond, scratch2, label);
 }
 
 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value,
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -16,16 +16,17 @@
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "vm/Realm.h"
 
 #include "jit/MacroAssembler-inl.h"
 #include "jit/SharedICHelpers-inl.h"
+#include "jit/VMFunctionList-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 // All registers to save and restore. This includes the stack pointer, since we
 // use the ability to reference register values on the stack by index.
 static const LiveRegisterSet AllRegs =
     LiveRegisterSet(GeneralRegisterSet(Registers::AllMask),
@@ -644,21 +645,22 @@ JitRuntime::BailoutTable JitRuntime::gen
 void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
                                         Label* bailoutTail) {
   bailoutHandlerOffset_ = startTrampolineCode(masm);
 
   GenerateBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID, bailoutTail);
 }
 
 bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
-                                   const VMFunction& f) {
-  MOZ_ASSERT(functionWrappers_);
+                                   const VMFunctionData& f, void* nativeFun,
+                                   uint32_t* wrapperOffset) {
+  *wrapperOffset = startTrampolineCode(masm);
 
-  uint32_t wrapperOffset = startTrampolineCode(masm);
-
+  // Avoid conflicts with argument registers while discarding the result after
+  // the function call.
   AllocatableGeneralRegisterSet regs(Register::Codes::WrapperMask);
 
   static_assert(
       (Register::Codes::VolatileMask & ~Register::Codes::WrapperMask) == 0,
       "Wrapper register set should be a superset of Volatile register set.");
 
   // The context is the first argument; a0 is the first argument register.
   Register cxreg = a0;
@@ -729,43 +731,43 @@ bool JitRuntime::generateVMWrapper(JSCon
   masm.setupUnalignedABICall(regs.getAny());
   masm.passABIArg(cxreg);
 
   size_t argDisp = 0;
 
   // Copy any arguments.
   for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
     switch (f.argProperties(explicitArg)) {
-      case VMFunction::WordByValue:
+      case VMFunctionData::WordByValue:
         if (f.argPassedInFloatReg(explicitArg)) {
           masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::DOUBLE);
         } else {
           masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
         }
         argDisp += sizeof(void*);
         break;
-      case VMFunction::WordByRef:
+      case VMFunctionData::WordByRef:
         masm.passABIArg(
             MoveOperand(argsBase, argDisp, MoveOperand::EFFECTIVE_ADDRESS),
             MoveOp::GENERAL);
         argDisp += sizeof(void*);
         break;
-      case VMFunction::DoubleByValue:
-      case VMFunction::DoubleByRef:
+      case VMFunctionData::DoubleByValue:
+      case VMFunctionData::DoubleByRef:
         MOZ_CRASH("NYI: MIPS64 callVM should not be used with 128bits values.");
         break;
     }
   }
 
   // Copy the implicit outparam, if any.
   if (InvalidReg != outReg) {
     masm.passABIArg(outReg);
   }
 
-  masm.callWithABI(f.wrapped, MoveOp::GENERAL,
+  masm.callWithABI(nativeFun, MoveOp::GENERAL,
                    CheckUnsafeCallWithABI::DontCheckHasExitFrame);
 
   if (!generateTLExitVM(masm, f)) {
     return false;
   }
 
   // Test for failure.
   switch (f.failType()) {
@@ -823,17 +825,17 @@ bool JitRuntime::generateVMWrapper(JSCon
       break;
   }
 
   masm.leaveExitFrame();
   masm.retn(Imm32(sizeof(ExitFrameLayout) +
                   f.explicitStackSlots() * sizeof(void*) +
                   f.extraValuesToPop * sizeof(Value)));
 
-  return functionWrappers_->putNew(&f, wrapperOffset);
+  return true;
 }
 
 uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,
                                         MIRType type) {
   uint32_t offset = startTrampolineCode(masm);
 
   MOZ_ASSERT(PreBarrierReg == a1);
   Register temp1 = a0;
@@ -878,38 +880,35 @@ uint32_t JitRuntime::generatePreBarrier(
   masm.pop(temp3);
   masm.pop(temp2);
   masm.pop(temp1);
   masm.abiret();
 
   return offset;
 }
 
-typedef bool (*HandleDebugTrapFn)(JSContext*, BaselineFrame*, uint8_t*, bool*);
-static const VMFunction HandleDebugTrapInfo =
-    FunctionInfo<HandleDebugTrapFn>(HandleDebugTrap, "HandleDebugTrap");
-
 JitCode* JitRuntime::generateDebugTrapHandler(JSContext* cx) {
   StackMacroAssembler masm(cx);
 
   Register scratch1 = t0;
   Register scratch2 = t1;
 
   // Load BaselineFrame pointer in scratch1.
   masm.movePtr(s5, scratch1);
   masm.subPtr(Imm32(BaselineFrame::Size()), scratch1);
 
   // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
   // the stub frame has a nullptr ICStub pointer, since this pointer is
   // marked during GC.
   masm.movePtr(ImmPtr(nullptr), ICStubReg);
   EmitBaselineEnterStubFrame(masm, scratch2);
 
-  TrampolinePtr code =
-      cx->runtime()->jitRuntime()->getVMWrapper(HandleDebugTrapInfo);
+  using Fn = bool (*)(JSContext*, BaselineFrame*, uint8_t*, bool*);
+  VMFunctionId id = VMFunctionToId<Fn, jit::HandleDebugTrap>::id;
+  TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
 
   masm.subPtr(Imm32(2 * sizeof(uintptr_t)), StackPointer);
   masm.storePtr(ra, Address(StackPointer, sizeof(uintptr_t)));
   masm.storePtr(scratch1, Address(StackPointer, 0));
 
   EmitBaselineCallVM(code, masm);
 
   EmitBaselineLeaveStubFrame(masm);