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 141148 699c21af878da8539a77b1b7b232e156c9d08bea
parent 141147 4e12ba2df6a6cf16721c337217e2470dbe2d0745
child 141149 aba98905fc13482fa3c649f9ea54138185b9b517
push idunknown
push userunknown
push dateunknown
reviewersnbp
bugs895950
milestone25.0a1
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)));