Bug 861785 - Odinmonkey ARM: use the hard-float ABI for inter-asm.js function calls irrespective of the system ABI. r=luke
authorDouglas Crosher <dtc-moz@scieneer.com>
Fri, 06 Dec 2013 23:00:31 +1100
changeset 175165 9e1a644eb6f37daca96cdff84d1046bfe2d322ed
parent 175164 a8b06549f680c3bec8c15a629e437c6e20848238
child 175166 8dc4d9276c7a278aa6c537de680ed2ef40ce1d0e
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs861785
milestone28.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 861785 - Odinmonkey ARM: use the hard-float ABI for inter-asm.js function calls irrespective of the system ABI. r=luke
js/src/jit/AsmJS.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/arm/Assembler-arm.cpp
js/src/jit/arm/Assembler-arm.h
js/src/jit/arm/CodeGenerator-arm.h
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -5593,22 +5593,17 @@ GenerateEntry(ModuleCompiler &m, const A
     for (ABIArgTypeIter iter(func.sig().args()); !iter.done(); iter++) {
         unsigned argOffset = iter.index() * sizeof(uint64_t);
         Address src(argv, argOffset);
         switch (iter->kind()) {
           case ABIArg::GPR:
             masm.load32(src, iter->gpr());
             break;
           case ABIArg::FPU:
-#if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
-            masm.ma_dataTransferN(IsLoad, 64, true, argv, Imm32(argOffset),
-                                  Register::FromCode(iter->fpu().code()*2));
-#else
             masm.loadDouble(src, iter->fpu());
-#endif
             break;
           case ABIArg::Stack:
             if (iter.mirType() == MIRType_Int32) {
                 masm.load32(src, scratch);
                 masm.storePtr(scratch, Address(StackPointer, iter->offsetFromArgBase()));
             } else {
                 JS_ASSERT(iter.mirType() == MIRType_Double);
                 masm.loadDouble(src, ScratchFloatReg);
@@ -5630,19 +5625,16 @@ GenerateEntry(ModuleCompiler &m, const A
     // Store the return value in argv[0]
     switch (func.sig().retType().which()) {
       case RetType::Void:
         break;
       case RetType::Signed:
         masm.storeValue(JSVAL_TYPE_INT32, ReturnReg, Address(argv, 0));
         break;
       case RetType::Double:
-#if defined(JS_CPU_ARM) and !defined(JS_CPU_ARM_HARDFP)
-        masm.ma_vxfer(r0, r1, d0);
-#endif
         masm.canonicalizeDouble(ReturnFloatReg);
         masm.storeDouble(ReturnFloatReg, Address(argv, 0));
         break;
     }
 
     // Restore clobbered non-volatile registers of the caller.
     masm.PopRegsInMask(NonVolatileRegs);
 
@@ -5765,21 +5757,16 @@ FillArgumentArray(ModuleCompiler &m, con
 
     for (ABIArgTypeIter i(argTypes); !i.done(); i++) {
         Address dstAddr = Address(StackPointer, offsetToArgs + i.index() * sizeof(Value));
         switch (i->kind()) {
           case ABIArg::GPR:
             masm.storeValue(JSVAL_TYPE_INT32, i->gpr(), dstAddr);
             break;
           case ABIArg::FPU: {
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-              FloatRegister fr = i->fpu();
-              int srcId = fr.code() * 2;
-              masm.ma_vxfer(Register::FromCode(srcId), Register::FromCode(srcId+1), fr);
-#endif
               masm.canonicalizeDouble(i->fpu());
               masm.storeDouble(i->fpu(), dstAddr);
               break;
           }
           case ABIArg::Stack:
             if (i.mirType() == MIRType_Int32) {
                 Address src(StackPointer, offsetToCallerStackArgs + i->offsetFromArgBase());
 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
@@ -5930,21 +5917,17 @@ GenerateFFIInterpreterExit(ModuleCompile
       case RetType::Signed:
         masm.call(AsmJSImm_InvokeFromAsmJS_ToInt32);
         masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
         masm.unboxInt32(argv, ReturnReg);
         break;
       case RetType::Double:
         masm.call(AsmJSImm_InvokeFromAsmJS_ToNumber);
         masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-        masm.loadValue(argv, softfpReturnOperand);
-#else
         masm.loadDouble(argv, ReturnFloatReg);
-#endif
         break;
     }
 
     masm.freeStack(reserveSize + sizeof(int32_t));
     masm.ret();
 #endif
 }
 
@@ -6000,21 +5983,17 @@ GenerateOOLConvert(ModuleCompiler &m, Re
       case RetType::Signed:
           masm.call(AsmJSImm_CoerceInPlace_ToInt32);
           masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
           masm.unboxInt32(Address(StackPointer, offsetToArgv), ReturnReg);
           break;
       case RetType::Double:
           masm.call(AsmJSImm_CoerceInPlace_ToNumber);
           masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-          masm.loadValue(Address(StackPointer, offsetToArgv), softfpReturnOperand);
-#else
           masm.loadDouble(Address(StackPointer, offsetToArgv), ReturnFloatReg);
-#endif
           break;
       default:
           MOZ_ASSUME_UNREACHABLE("Unsupported convert type");
     }
 
     masm.freeStack(stackDec);
 }
 
@@ -6143,19 +6122,16 @@ GenerateFFIIonExit(ModuleCompiler &m, co
       case RetType::Void:
         break;
       case RetType::Signed:
         masm.convertValueToInt32(JSReturnOperand, ReturnFloatReg, ReturnReg, &oolConvert,
                                  /* -0 check */ false);
         break;
       case RetType::Double:
         masm.convertValueToDouble(JSReturnOperand, ReturnFloatReg, &oolConvert);
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-        masm.boxDouble(ReturnFloatReg, softfpReturnOperand);
-#endif
         break;
     }
 
     masm.bind(&done);
     masm.PopRegsInMask(restoreSet);
     masm.ret();
 
     // oolConvert
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -7680,22 +7680,24 @@ CodeGenerator::visitHaveSameClass(LHaveS
 }
 
 bool
 CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
 {
     MAsmJSCall *mir = ins->mir();
 
 #if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-    for (unsigned i = 0, e = ins->numOperands(); i < e; i++) {
-        LAllocation *a = ins->getOperand(i);
-        if (a->isFloatReg()) {
-            FloatRegister fr = ToFloatRegister(a);
-            int srcId = fr.code() * 2;
-            masm.ma_vxfer(fr, Register::FromCode(srcId), Register::FromCode(srcId+1));
+    if (mir->callee().which() == MAsmJSCall::Callee::Builtin) {
+        for (unsigned i = 0, e = ins->numOperands(); i < e; i++) {
+            LAllocation *a = ins->getOperand(i);
+            if (a->isFloatReg()) {
+                FloatRegister fr = ToFloatRegister(a);
+                int srcId = fr.code() * 2;
+                masm.ma_vxfer(fr, Register::FromCode(srcId), Register::FromCode(srcId+1));
+            }
         }
     }
 #endif
    if (mir->spIncrement())
         masm.freeStack(mir->spIncrement());
 
    JS_ASSERT((AlignmentAtPrologue +  masm.framePushed()) % StackAlignment == 0);
 
@@ -7725,37 +7727,23 @@ CodeGenerator::visitAsmJSCall(LAsmJSCall
 
     postAsmJSCall(ins);
     return true;
 }
 
 bool
 CodeGenerator::visitAsmJSParameter(LAsmJSParameter *lir)
 {
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-    // softfp transfers some double values in gprs.
-    // undo this.
-    LAllocation *a = lir->getDef(0)->output();
-    if (a->isFloatReg()) {
-        FloatRegister fr = ToFloatRegister(a);
-        int srcId = fr.code() * 2;
-        masm.ma_vxfer(Register::FromCode(srcId), Register::FromCode(srcId+1), fr);
-    }
-#endif
     return true;
 }
 
 bool
 CodeGenerator::visitAsmJSReturn(LAsmJSReturn *lir)
 {
     // Don't emit a jump to the return label if this is the last block.
-#if defined(JS_CPU_ARM) && !defined(JS_CPU_ARM_HARDFP)
-    if (lir->getOperand(0)->isFloatReg())
-        masm.ma_vxfer(d0, r0, r1);
-#endif
     if (current->mir() != *gen->graph().poBegin())
         masm.jump(&returnLabel_);
     return true;
 }
 
 bool
 CodeGenerator::visitAsmJSVoidReturn(LAsmJSVoidReturn *lir)
 {
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -17,31 +17,28 @@
 #include "jit/arm/MacroAssembler-arm.h"
 #include "jit/JitCompartment.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::CountLeadingZeroes32;
 
+// Note this is used for inter-AsmJS calls and may pass arguments and results
+// in floating point registers even if the system ABI does not.
 ABIArgGenerator::ABIArgGenerator() :
-#if defined(JS_CPU_ARM_HARDFP)
     intRegIndex_(0),
     floatRegIndex_(0),
-#else
-    argRegIndex_(0),
-#endif
     stackOffset_(0),
     current_()
 {}
 
 ABIArg
 ABIArgGenerator::next(MIRType type)
 {
-#if defined(JS_CPU_ARM_HARDFP)
     switch (type) {
       case MIRType_Int32:
       case MIRType_Pointer:
         if (intRegIndex_ == NumIntArgRegs) {
             current_ = ABIArg(stackOffset_);
             stackOffset_ += sizeof(uint32_t);
             break;
         }
@@ -57,50 +54,18 @@ ABIArgGenerator::next(MIRType type)
             break;
         }
         current_ = ABIArg(FloatRegister::FromCode(floatRegIndex_));
         floatRegIndex_++;
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unexpected argument type");
     }
+
     return current_;
-#else
-    switch (type) {
-      case MIRType_Int32:
-      case MIRType_Pointer:
-        if (argRegIndex_ == NumIntArgRegs) {
-            current_ = ABIArg(stackOffset_);
-            stackOffset_ += sizeof(uint32_t);
-            break;
-        }
-        current_ = ABIArg(Register::FromCode(argRegIndex_));
-        argRegIndex_++;
-        break;
-      case MIRType_Double: {
-        unsigned alignedArgRegIndex_ = (argRegIndex_ + 1) & ~1;
-        if (alignedArgRegIndex_ + 1 > NumIntArgRegs) {
-            static const int align = sizeof(double) - 1;
-            stackOffset_ = (stackOffset_ + align) & ~align;
-            current_ = ABIArg(stackOffset_);
-            stackOffset_ += sizeof(uint64_t);
-            argRegIndex_ = NumIntArgRegs;
-            break;
-        }
-        argRegIndex_ = alignedArgRegIndex_;
-        current_ = ABIArg(FloatRegister::FromCode(argRegIndex_ >> 1));
-
-        argRegIndex_+=2;
-      }
-        break;
-      default:
-        MOZ_ASSUME_UNREACHABLE("Unexpected argument type");
-    }
-    return current_;
-#endif
 }
 const Register ABIArgGenerator::NonArgReturnVolatileReg0 = r4;
 const Register ABIArgGenerator::NonArgReturnVolatileReg1 = r5;
 
 // Encode a standard register when it is being used as src1, the dest, and
 // an extra register. These should never be called with an InvalidReg.
 uint32_t
 js::jit::RT(Register r)
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -63,22 +63,18 @@ static MOZ_CONSTEXPR_VAR Register IntArg
 static MOZ_CONSTEXPR_VAR Register IntArgReg3 = r3;
 static MOZ_CONSTEXPR_VAR Register GlobalReg = r10;
 static MOZ_CONSTEXPR_VAR Register HeapReg = r11;
 static MOZ_CONSTEXPR_VAR Register CallTempNonArgRegs[] = { r5, r6, r7, r8 };
 static const uint32_t NumCallTempNonArgRegs =
     mozilla::ArrayLength(CallTempNonArgRegs);
 class ABIArgGenerator
 {
-#if defined(JS_CPU_ARM_HARDFP)
     unsigned intRegIndex_;
     unsigned floatRegIndex_;
-#else
-    unsigned argRegIndex_;
-#endif
     uint32_t stackOffset_;
     ABIArg current_;
 
   public:
     ABIArgGenerator();
     ABIArg next(MIRType argType);
     ABIArg &current() { return current_; }
     uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -172,21 +172,22 @@ class CodeGeneratorARM : public CodeGene
     bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
 
     bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
 
     bool generateInvalidateEpilogue();
   protected:
     void postAsmJSCall(LAsmJSCall *lir) {
 #if  !defined(JS_CPU_ARM_HARDFP)
-        if (lir->mir()->type() == MIRType_Double) {
-            masm.ma_vxfer(r0, r1, d0);
+        if (lir->mir()->callee().which() == MAsmJSCall::Callee::Builtin) {
+            if (lir->mir()->type() == MIRType_Double)
+                masm.ma_vxfer(r0, r1, d0);
         }
 #endif
-}
+    }
 
     bool visitEffectiveAddress(LEffectiveAddress *ins);
     bool visitUDiv(LUDiv *ins);
     bool visitUMod(LUMod *ins);
     bool visitSoftUDivOrMod(LSoftUDivOrMod *ins);
 };
 
 typedef CodeGeneratorARM CodeGeneratorSpecific;