Bug 988950 - Split macro assembler implementation by architecture r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 23 Apr 2014 13:48:35 +0100
changeset 180114 13d60930dab2b563e9bdd9564f54775588914bf5
parent 180113 b72e6cc2357400d932efd7cae75c4766984b06f8
child 180115 174895f05c9f2ed25fc4454b344cc88ce207e2cf
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjandem
bugs988950
milestone31.0a1
Bug 988950 - Split macro assembler implementation by architecture r=jandem
js/src/gc/Nursery.h
js/src/jit/IonMacroAssembler.cpp
js/src/jit/IonMacroAssembler.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/mips/MacroAssembler-mips.cpp
js/src/jit/mips/MacroAssembler-mips.h
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -134,16 +134,26 @@ class Nursery
     size_t sizeOfHugeSlots(mozilla::MallocSizeOf mallocSizeOf) const {
         size_t total = 0;
         for (HugeSlotsSet::Range r = hugeSlots.all(); !r.empty(); r.popFront())
             total += mallocSizeOf(r.front());
         total += hugeSlots.sizeOfExcludingThis(mallocSizeOf);
         return total;
     }
 
+    MOZ_ALWAYS_INLINE uintptr_t start() const {
+        JS_ASSERT(runtime_);
+        return ((JS::shadow::Runtime *)runtime_)->gcNurseryStart_;
+    }
+
+    MOZ_ALWAYS_INLINE uintptr_t heapEnd() const {
+        JS_ASSERT(runtime_);
+        return ((JS::shadow::Runtime *)runtime_)->gcNurseryEnd_;
+    }
+
   private:
     /*
      * The start and end pointers are stored under the runtime so that we can
      * inline the isInsideNursery check into embedder code. Use the start()
      * and heapEnd() functions to access these values.
      */
     JSRuntime *runtime_;
 
@@ -185,26 +195,16 @@ class Nursery
     static_assert(sizeof(NurseryChunkLayout) == gc::ChunkSize,
                   "Nursery chunk size must match gc::Chunk size.");
     NurseryChunkLayout &chunk(int index) const {
         JS_ASSERT(index < NumNurseryChunks);
         JS_ASSERT(start());
         return reinterpret_cast<NurseryChunkLayout *>(start())[index];
     }
 
-    MOZ_ALWAYS_INLINE uintptr_t start() const {
-        JS_ASSERT(runtime_);
-        return ((JS::shadow::Runtime *)runtime_)->gcNurseryStart_;
-    }
-
-    MOZ_ALWAYS_INLINE uintptr_t heapEnd() const {
-        JS_ASSERT(runtime_);
-        return ((JS::shadow::Runtime *)runtime_)->gcNurseryEnd_;
-    }
-
     MOZ_ALWAYS_INLINE void setCurrentChunk(int chunkno) {
         JS_ASSERT(chunkno < NumNurseryChunks);
         JS_ASSERT(chunkno < numActiveChunks_);
         currentChunk_ = chunkno;
         position_ = chunk(chunkno).start();
         currentEnd_ = chunk(chunkno).end();
         chunk(chunkno).trailer.runtime = runtime();
     }
@@ -309,19 +309,16 @@ class Nursery
         }
     }
 #else
     void enterZealMode() {}
     void leaveZealMode() {}
 #endif
 
     friend class gc::MinorCollectionTracer;
-    friend class jit::CodeGenerator;
     friend class jit::MacroAssembler;
-    friend class jit::ICStubCompiler;
-    friend class jit::BaselineCompiler;
     friend void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
 };
 
 } /* namespace js */
 
 #endif /* JSGC_GENERATIONAL */
 #endif /* gc_Nursery_h */
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -1781,45 +1781,8 @@ MacroAssembler::spsUnmarkJit(SPSProfiler
     Label spsNotEnabled;
     pop(temp); // -4: Was the profiler enabled.
     branchTest32(Assembler::Equal, temp, temp, &spsNotEnabled);
 
     spsPopFrameSafe(p, temp);
 
     bind(&spsNotEnabled);
 }
-
-#ifdef JSGC_GENERATIONAL
-
-void
-MacroAssembler::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
-{
-    JS_ASSERT(ptr != temp);
-    JS_ASSERT(temp != InvalidReg);
-
-    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
-    addPtr(ptr, temp);
-    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
-}
-
-void
-MacroAssembler::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
-{
-    Label done;
-
-    branchTestObject(Assembler::NotEqual, value, &done);
-
-    Register obj = extractObject(value, temp);
-    // valobj and temp may be the same register, in which case we mustn't trash it
-    // before we use its contents.
-    if (obj == temp) {
-        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
-        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
-    } else {
-        branchPtrInNurseryRange(obj, temp, label);
-    }
-
-    bind(&done);
-}
-
-#endif
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -1347,21 +1347,16 @@ class MacroAssembler : public MacroAssem
                                               IntConversion_ClampToUint8);
     }
     void clampTypedOrValueToUint8(TypedOrValueRegister src, FloatRegister temp, Register output,
                                   Label *fail)
     {
         convertTypedOrValueToInt(src, temp, output, fail, IntConversion_ClampToUint8);
     }
 
-#ifdef JSGC_GENERATIONAL
-    void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
-    void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
-#endif
-
   public:
     class AfterICSaveLive {
         friend class MacroAssembler;
         AfterICSaveLive(uint32_t initialStack)
 #ifdef JS_DEBUG
           : initialStack(initialStack)
 #endif
         {}
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4329,8 +4329,44 @@ MacroAssemblerARMCompat::jumpWithPatch(R
     ARMBuffer::PoolEntry pe;
     BufferOffset bo = as_BranchPool(0xdeadbeef, label, &pe, cond);
     // Fill in a new CodeOffset with both the load and the
     // pool entry that the instruction loads from.
     CodeOffsetJump ret(bo.getOffset(), pe.encode());
     return ret;
 }
 
+#ifdef JSGC_GENERATIONAL
+
+void
+MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
+{
+    JS_ASSERT(ptr != temp);
+    JS_ASSERT(temp != InvalidReg);
+
+    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
+    addPtr(ptr, temp);
+    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+}
+
+void
+MacroAssemblerARMCompat::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
+{
+    Label done;
+
+    branchTestObject(Assembler::NotEqual, value, &done);
+
+    Register obj = extractObject(value, temp);
+    // valobj and temp may be the same register, in which case we mustn't trash it
+    // before we use its contents.
+    if (obj == temp) {
+        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
+        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
+    } else {
+        branchPtrInNurseryRange(obj, temp, label);
+    }
+
+    bind(&done);
+}
+
+#endif
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1554,16 +1554,21 @@ class MacroAssemblerARMCompat : public M
     }
     BufferOffset ma_BoundsCheck(Register bounded) {
         return as_cmp(bounded, Imm8(0));
     }
 
     void moveFloat32(FloatRegister src, FloatRegister dest) {
         as_vmov(VFPRegister(src).singleOverlay(), VFPRegister(dest).singleOverlay());
     }
+
+#ifdef JSGC_GENERATIONAL
+    void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
+    void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
+#endif
 };
 
 typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm_MacroAssembler_arm_h */
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -3240,8 +3240,26 @@ MacroAssemblerMIPSCompat::toggledCall(Ji
         as_nop();
     } else {
         as_nop();
         as_nop();
     }
     MOZ_ASSERT(nextOffset().getOffset() - offset.offset() == ToggledCallSize());
     return offset;
 }
+
+void
+MacroAssemblerMIPSCompat::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
+{
+    JS_ASSERT(temp != InvalidReg);
+    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+
+    // ptr and temp may be the same register, in which case we mustn't trash it
+    // before we use its contents.
+    if (ptr == temp) {
+        addPtr(ImmWord(-ptrdiff_t(nursery.start())), ptr);
+        branchPtr(Assembler::Below, ptr, Imm32(Nursery::NurserySize), label);
+    } else {
+        movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
+        addPtr(ptr, temp);
+        branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+    }
+}
--- a/js/src/jit/mips/MacroAssembler-mips.h
+++ b/js/src/jit/mips/MacroAssembler-mips.h
@@ -1137,16 +1137,18 @@ public:
         BufferOffset bo = m_buffer.nextOffset();
         ma_liPatchable(bounded, Imm32(0));
         return bo;
     }
 
     void moveFloat32(FloatRegister src, FloatRegister dest) {
         as_movs(dest, src);
     }
+
+    void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
 };
 
 typedef MacroAssemblerMIPSCompat MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips_MacroAssembler_mips_h */
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -377,8 +377,45 @@ MacroAssemblerX64::testNegativeZero(cons
 
 Assembler::Condition
 MacroAssemblerX64::testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch)
 {
     movd(reg, scratch);
     cmpl(scratch, Imm32(1));
     return Overflow;
 }
+
+#ifdef JSGC_GENERATIONAL
+
+void
+MacroAssemblerX64::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
+{
+    JS_ASSERT(ptr != temp);
+    JS_ASSERT(temp != InvalidReg);
+
+    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
+    addPtr(ptr, temp);
+    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+}
+
+void
+MacroAssemblerX64::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
+{
+    Label done;
+
+    branchTestObject(Assembler::NotEqual, value, &done);
+
+    Register obj = extractObject(value, temp);
+    // valobj and temp may be the same register, in which case we mustn't trash it
+    // before we use its contents.
+    if (obj == temp) {
+        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
+        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
+    } else {
+        branchPtrInNurseryRange(obj, temp, label);
+    }
+
+    bind(&done);
+}
+
+#endif
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -1320,16 +1320,20 @@ class MacroAssemblerX64 : public MacroAs
         uint8_t *target = globalData + globalDataOffset;
         ((int32_t *)nextInsn)[-1] = target - nextInsn;
     }
     void memIntToValue(Address Source, Address Dest) {
         load32(Source, ScratchReg);
         storeValue(JSVAL_TYPE_INT32, ScratchReg, Dest);
     }
 
+#ifdef JSGC_GENERATIONAL
+    void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
+    void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
+#endif
 };
 
 typedef MacroAssemblerX64 MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x64_MacroAssembler_x64_h */
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -422,8 +422,45 @@ MacroAssemblerX86::testNegativeZero(cons
 
 Assembler::Condition
 MacroAssemblerX86::testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch)
 {
     movd(reg, scratch);
     cmpl(scratch, Imm32(1));
     return Overflow;
 }
+
+#ifdef JSGC_GENERATIONAL
+
+void
+MacroAssemblerX86::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
+{
+    JS_ASSERT(ptr != temp);
+    JS_ASSERT(temp != InvalidReg);
+
+    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
+    addPtr(ptr, temp);
+    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+}
+
+void
+MacroAssemblerX86::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
+{
+    Label done;
+
+    branchTestObject(Assembler::NotEqual, value, &done);
+
+    Register obj = extractObject(value, temp);
+    // valobj and temp may be the same register, in which case we mustn't trash it
+    // before we use its contents.
+    if (obj == temp) {
+        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
+        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
+        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
+    } else {
+        branchPtrInNurseryRange(obj, temp, label);
+    }
+
+    bind(&done);
+}
+
+#endif
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -1109,16 +1109,21 @@ class MacroAssemblerX86 : public MacroAs
         call(target);
     }
 
     // Save an exit frame to the thread data of the current thread, given a
     // register that holds a PerThreadData *.
     void linkParallelExitFrame(const Register &pt) {
         movl(StackPointer, Operand(pt, offsetof(PerThreadData, ionTop)));
     }
+
+#ifdef JSGC_GENERATIONAL
+    void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
+    void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
+#endif
 };
 
 typedef MacroAssemblerX86 MacroAssemblerSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_MacroAssembler_x86_h */