Bug 895950 - Support calling VM functions with double out parameters. (r=nbp)
authorShu-yu Guo <shu@rfrn.org>
Fri, 02 Aug 2013 08:24:57 -0700
changeset 153426 699c21af878da8539a77b1b7b232e156c9d08bea
parent 153425 4e12ba2df6a6cf16721c337217e2470dbe2d0745
child 153427 aba98905fc13482fa3c649f9ea54138185b9b517
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs895950
milestone25.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 895950 - Support calling VM functions with double out parameters. (r=nbp)
js/src/ion/IonMacroAssembler.h
js/src/ion/VMFunctions.h
js/src/ion/arm/MacroAssembler-arm.h
js/src/ion/arm/Trampoline-arm.cpp
js/src/ion/shared/CodeGenerator-shared.h
js/src/ion/shared/MacroAssembler-x86-shared.h
js/src/ion/x64/Trampoline-x64.cpp
js/src/ion/x86/Trampoline-x86.cpp
--- a/js/src/ion/IonMacroAssembler.h
+++ b/js/src/ion/IonMacroAssembler.h
@@ -288,16 +288,21 @@ class MacroAssembler : public MacroAssem
             storeTypedOrValue(src.reg(), dest);
     }
 
     void storeCallResult(Register reg) {
         if (reg != ReturnReg)
             mov(ReturnReg, reg);
     }
 
+    void storeCallFloatResult(const FloatRegister &reg) {
+        if (reg != ReturnFloatReg)
+            moveDouble(ReturnFloatReg, reg);
+    }
+
     void storeCallResultValue(AnyRegister dest) {
 #if defined(JS_NUNBOX32)
         unboxValue(ValueOperand(JSReturnReg_Type, JSReturnReg_Data), dest);
 #elif defined(JS_PUNBOX64)
         unboxValue(ValueOperand(JSReturnReg), dest);
 #else
 #error "Bad architecture"
 #endif
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -19,16 +19,17 @@ class DeclEnvObject;
 class ForkJoinSlice;
 
 namespace ion {
 
 enum DataType {
     Type_Void,
     Type_Bool,
     Type_Int32,
+    Type_Double,
     Type_Pointer,
     Type_Object,
     Type_Value,
     Type_Handle,
     Type_ParallelResult
 };
 
 struct PopValues
@@ -359,16 +360,17 @@ template <> struct TypeToRootType<Handle
 };
 
 template <class> struct OutParamToDataType { static const DataType result = Type_Void; };
 template <> struct OutParamToDataType<Value *> { static const DataType result = Type_Value; };
 template <> struct OutParamToDataType<int *> { static const DataType result = Type_Int32; };
 template <> struct OutParamToDataType<uint32_t *> { static const DataType result = Type_Int32; };
 template <> struct OutParamToDataType<uint8_t **> { static const DataType result = Type_Pointer; };
 template <> struct OutParamToDataType<bool *> { static const DataType result = Type_Bool; };
+template <> struct OutParamToDataType<double *> { static const DataType result = Type_Double; };
 template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
 template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; };
 template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; };
 
 template <class> struct OutParamToRootType {
     static const VMFunction::RootType result = VMFunction::RootNone;
 };
 template <> struct OutParamToRootType<MutableHandleValue> {
--- a/js/src/ion/arm/MacroAssembler-arm.h
+++ b/js/src/ion/arm/MacroAssembler-arm.h
@@ -1193,16 +1193,19 @@ class MacroAssemblerARMCompat : public M
         ma_vstr(src, Operand(addr));
     }
     void storeDouble(FloatRegister src, BaseIndex addr) {
         // Harder cases not handled yet.
         JS_ASSERT(addr.offset == 0);
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
         ma_vstr(src, addr.base, addr.index, scale);
     }
+    void moveDouble(FloatRegister src, FloatRegister dest) {
+        ma_vstr(src, Operand(dest));
+    }
 
     void storeFloat(FloatRegister src, Address addr) {
         ma_vstr(VFPRegister(src).singleOverlay(), Operand(addr));
     }
     void storeFloat(FloatRegister src, BaseIndex addr) {
         // Harder cases not handled yet.
         JS_ASSERT(addr.offset == 0);
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
--- a/js/src/ion/arm/Trampoline-arm.cpp
+++ b/js/src/ion/arm/Trampoline-arm.cpp
@@ -641,16 +641,23 @@ IonRuntime::generateVMWrapper(JSContext 
       case Type_Pointer:
       case Type_Bool:
         outReg = r4;
         regs.take(outReg);
         masm.reserveStack(sizeof(int32_t));
         masm.ma_mov(sp, outReg);
         break;
 
+      case Type_Double:
+        outReg = r4;
+        regs.take(outReg);
+        masm.reserveStack(sizeof(double));
+        masm.ma_mov(sp, outReg);
+        break;
+
       default:
         JS_ASSERT(f.outParam == Type_Void);
         break;
     }
 
     masm.setupUnalignedABICall(f.argc(), regs.getAny());
     masm.passABIArg(cxreg);
 
@@ -720,16 +727,21 @@ IonRuntime::generateVMWrapper(JSContext 
         masm.freeStack(sizeof(int32_t));
         break;
 
       case Type_Bool:
         masm.load8ZeroExtend(Address(sp, 0), ReturnReg);
         masm.freeStack(sizeof(int32_t));
         break;
 
+      case Type_Double:
+        masm.loadDouble(Address(sp, 0), ReturnFloatReg);
+        masm.freeStack(sizeof(double));
+        break;
+
       default:
         JS_ASSERT(f.outParam == Type_Void);
         break;
     }
     masm.leaveExitFrame();
     masm.retn(Imm32(sizeof(IonExitFrameLayout) +
                     f.explicitStackSlots() * sizeof(void *) +
                     f.extraValuesToPop * sizeof(Value)));
--- a/js/src/ion/shared/CodeGenerator-shared.h
+++ b/js/src/ion/shared/CodeGenerator-shared.h
@@ -307,16 +307,20 @@ class CodeGeneratorShared : public LInst
         pushedArgs_++;
 #endif
     }
 
     void storeResultTo(const Register &reg) {
         masm.storeCallResult(reg);
     }
 
+    void storeFloatResultTo(const FloatRegister &reg) {
+        masm.storeCallFloatResult(reg);
+    }
+
     template <typename T>
     void storeResultValueTo(const T &t) {
         masm.storeCallResultValue(t);
     }
 
     bool callVM(const VMFunction &f, LInstruction *ins, const Register *dynStack = NULL);
 
     template <class ArgSeq, class StoreOutputTo>
@@ -528,16 +532,36 @@ class StoreRegisterTo
     }
     inline RegisterSet clobbered() const {
         RegisterSet set = RegisterSet();
         set.add(out_);
         return set;
     }
 };
 
+class StoreFloatRegisterTo
+{
+  private:
+    FloatRegister out_;
+
+  public:
+    StoreFloatRegisterTo(const FloatRegister &out)
+      : out_(out)
+    { }
+
+    inline void generate(CodeGeneratorShared *codegen) const {
+        codegen->storeFloatResultTo(out_);
+    }
+    inline RegisterSet clobbered() const {
+        RegisterSet set = RegisterSet();
+        set.add(out_);
+        return set;
+    }
+};
+
 template <typename Output>
 class StoreValueTo_
 {
   private:
     Output out_;
 
   public:
     StoreValueTo_(const Output &out)
--- a/js/src/ion/shared/MacroAssembler-x86-shared.h
+++ b/js/src/ion/shared/MacroAssembler-x86-shared.h
@@ -278,16 +278,19 @@ class MacroAssemblerX86Shared : public A
         movsd(src, Operand(dest));
     }
     void storeDouble(FloatRegister src, const BaseIndex &dest) {
         movsd(src, Operand(dest));
     }
     void storeDouble(FloatRegister src, const Operand &dest) {
         movsd(src, dest);
     }
+    void moveDouble(FloatRegister src, FloatRegister dest) {
+        movsd(src, dest);
+    }
     void zeroDouble(FloatRegister reg) {
         xorpd(reg, reg);
     }
     void negateDouble(FloatRegister reg) {
         // From MacroAssemblerX86Shared::maybeInlineDouble
         pcmpeqw(ScratchFloatReg, ScratchFloatReg);
         psllq(Imm32(63), ScratchFloatReg);
 
--- a/js/src/ion/x64/Trampoline-x64.cpp
+++ b/js/src/ion/x64/Trampoline-x64.cpp
@@ -526,16 +526,22 @@ IonRuntime::generateVMWrapper(JSContext 
 
       case Type_Int32:
       case Type_Bool:
         outReg = regs.takeAny();
         masm.reserveStack(sizeof(int32_t));
         masm.movq(esp, outReg);
         break;
 
+      case Type_Double:
+        outReg = regs.takeAny();
+        masm.reserveStack(sizeof(double));
+        masm.movq(esp, outReg);
+        break;
+
       case Type_Pointer:
         outReg = regs.takeAny();
         masm.reserveStack(sizeof(uintptr_t));
         masm.movq(esp, outReg);
         break;
 
       default:
         JS_ASSERT(f.outParam == Type_Void);
@@ -609,16 +615,21 @@ IonRuntime::generateVMWrapper(JSContext 
         masm.freeStack(sizeof(int32_t));
         break;
 
       case Type_Bool:
         masm.load8ZeroExtend(Address(esp, 0), ReturnReg);
         masm.freeStack(sizeof(int32_t));
         break;
 
+      case Type_Double:
+        masm.loadDouble(Address(esp, 0), ReturnFloatReg);
+        masm.freeStack(sizeof(double));
+        break;
+
       case Type_Pointer:
         masm.loadPtr(Address(esp, 0), ReturnReg);
         masm.freeStack(sizeof(uintptr_t));
         break;
 
       default:
         JS_ASSERT(f.outParam == Type_Void);
         break;
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -551,16 +551,22 @@ IonRuntime::generateVMWrapper(JSContext 
       case Type_Int32:
       case Type_Pointer:
       case Type_Bool:
         outReg = regs.takeAny();
         masm.reserveStack(sizeof(int32_t));
         masm.movl(esp, outReg);
         break;
 
+      case Type_Double:
+        outReg = regs.takeAny();
+        masm.reserveStack(sizeof(double));
+        masm.movl(esp, outReg);
+        break;
+
       default:
         JS_ASSERT(f.outParam == Type_Void);
         break;
     }
 
     masm.setupUnalignedABICall(f.argc(), regs.getAny());
     masm.passABIArg(cxreg);
 
@@ -633,16 +639,20 @@ IonRuntime::generateVMWrapper(JSContext 
         masm.Pop(ReturnReg);
         break;
 
       case Type_Bool:
         masm.Pop(ReturnReg);
         masm.movzxbl(ReturnReg, ReturnReg);
         break;
 
+      case Type_Double:
+        masm.Pop(ReturnFloatReg);
+        break;
+
       default:
         JS_ASSERT(f.outParam == Type_Void);
         break;
     }
     masm.leaveExitFrame();
     masm.retn(Imm32(sizeof(IonExitFrameLayout) +
                     f.explicitStackSlots() * sizeof(void *) +
                     f.extraValuesToPop * sizeof(Value)));