Bug 927031 - Use MPostWriteBarrier to postbarrier SetElementIC r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 17 Oct 2013 20:58:21 +0100
changeset 164977 db52454329c6b0f3daabe2169ce9b0f612d9d8b8
parent 164976 d0097bc342f9dbab3772904120d4fde8c5cca894
child 164978 a6c52aabcdece06451ad7bbe26c0e75681de1681
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs927031
milestone27.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 927031 - Use MPostWriteBarrier to postbarrier SetElementIC r=jandem
js/src/jit/IonBuilder.cpp
js/src/jit/IonCaches.cpp
js/src/jit/IonMacroAssembler.cpp
js/src/jit/IonMacroAssembler.h
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7204,16 +7204,19 @@ IonBuilder::setElemTryCache(bool *emitte
     }
 
     // We can avoid worrying about holes in the IC if we know a priori we are safe
     // from them. If TI can guard that there are no indexed properties on the prototype
     // chain, we know that we anen't missing any setters by overwriting the hole with
     // another value.
     bool guardHoles = ElementAccessHasExtraIndexedProperty(constraints(), object);
 
+    if (NeedsPostBarrier(info(), value))
+        current->add(MPostWriteBarrier::New(object, value));
+
     // Emit SetElementCache.
     MInstruction *ins = MSetElementCache::New(object, index, value, script()->strict, guardHoles);
     current->add(ins);
     current->push(value);
 
     if (!resumeAfter(ins))
         return false;
 
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3474,17 +3474,17 @@ GenerateSetDenseElement(JSContext *cx, M
                         Register temp)
 {
     JS_ASSERT(obj->isNative());
     JS_ASSERT(idval.isInt32());
 
     Label failures;
     Label outOfBounds; // index represents a known hole, or an illegal append
 
-    Label markElem, postBarrier; // used if TI protects us from worrying about holes.
+    Label markElem, storeElement; // used if TI protects us from worrying about holes.
 
     // Guard object is a dense array.
     Shape *shape = obj->lastProperty();
     if (!shape)
         return false;
     masm.branchTestObjShape(Assembler::NotEqual, object, shape, &failures);
 
     // Ensure the index is an int32 value.
@@ -3529,35 +3529,30 @@ GenerateSetDenseElement(JSContext *cx, M
                 Label bumpedLength;
                 Address length(elements, ObjectElements::offsetOfLength());
                 masm.branch32(Assembler::AboveOrEqual, length, index, &bumpedLength);
                 masm.storeKey(newLength, length);
                 masm.bind(&bumpedLength);
 
                 // Restore the index.
                 masm.bumpKey(&newLength, -1);
-                masm.jump(&postBarrier);
+                masm.jump(&storeElement);
             }
             // else
             masm.bind(&markElem);
         }
 
         if (cx->zone()->needsBarrier())
             masm.callPreBarrier(target, MIRType_Value);
 
-        // Call post barrier if necessary, and recalculate elements pointer if it got clobbered.
-        if (!guardHoles)
-            masm.bind(&postBarrier);
-        Register postBarrierScratch = elements;
-        if (masm.maybeCallPostBarrier(object, value, postBarrierScratch))
-            masm.loadPtr(Address(object, JSObject::offsetOfElements()), elements);
-
         // Store the value.
         if (guardHoles)
             masm.branchTestMagic(Assembler::Equal, target, &failures);
+        else
+            masm.bind(&storeElement);
         masm.storeConstantOrRegister(value, target);
     }
     attacher.jumpRejoin(masm);
 
     // All failures flow to here.
     masm.bind(&outOfBounds);
     masm.bind(&failures);
     attacher.jumpNextStub(masm);
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -336,63 +336,16 @@ MacroAssembler::PopRegsInMaskIgnore(Regi
             if (!ignore.has(*iter))
                 loadPtr(Address(StackPointer, diffG), *iter);
         }
         freeStack(reservedG);
     }
     JS_ASSERT(diffG == 0);
 }
 
-bool MacroAssembler::maybeCallPostBarrier(Register object, ConstantOrRegister value,
-                                          Register maybeScratch) {
-    bool usedMaybeScratch = false;
-
-#ifdef JSGC_GENERATIONAL
-    JSRuntime *runtime = GetIonContext()->runtime;
-    if (value.constant()) {
-        JS_ASSERT_IF(value.value().isGCThing(),
-                     !gc::IsInsideNursery(runtime, value.value().toGCThing()));
-        return false;
-    }
-
-    TypedOrValueRegister valReg = value.reg();
-    if (valReg.hasTyped() && valReg.type() != MIRType_Object)
-        return false;
-
-    Label done;
-    Label tenured;
-    branchPtr(Assembler::Below, object, ImmWord(runtime->gcNurseryStart_), &tenured);
-    branchPtr(Assembler::Below, object, ImmWord(runtime->gcNurseryEnd_), &done);
-
-    bind(&tenured);
-    if (valReg.hasValue()) {
-        branchTestObject(Assembler::NotEqual, valReg.valueReg(), &done);
-        extractObject(valReg, maybeScratch);
-        usedMaybeScratch = true;
-    }
-    Register valObj = valReg.hasValue() ? maybeScratch : valReg.typedReg().gpr();
-    branchPtr(Assembler::Below, valObj, ImmWord(runtime->gcNurseryStart_), &done);
-    branchPtr(Assembler::AboveOrEqual, valObj, ImmWord(runtime->gcNurseryEnd_), &done);
-
-    GeneralRegisterSet saveRegs = GeneralRegisterSet::Volatile();
-    PushRegsInMask(saveRegs);
-    Register callScratch = saveRegs.getAny();
-    setupUnalignedABICall(2, callScratch);
-    movePtr(ImmPtr(runtime), callScratch);
-    passABIArg(callScratch);
-    passABIArg(object);
-    callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
-    PopRegsInMask(saveRegs);
-
-    bind(&done);
-#endif
-
-    return usedMaybeScratch;
-}
-
 void
 MacroAssembler::branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2,
                                  Label *label)
 {
 #ifdef JSGC_GENERATIONAL
     if (ptr2.value && gc::IsInsideNursery(GetIonContext()->cx->runtime(), (void *)ptr2.value))
         embedsNurseryPointers_ = true;
 #endif
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -674,24 +674,16 @@ class MacroAssembler : public MacroAssem
 
         callPreBarrier(address, type);
         jump(&done);
 
         align(8);
         bind(&done);
     }
 
-    /*
-     * Call the post barrier if necessary when writing value to a slot or
-     * element of object.
-     *
-     * Returns whether the maybeScratch register was used.
-     */
-    bool maybeCallPostBarrier(Register object, ConstantOrRegister value, Register maybeScratch);
-
     void branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2,
                           Label *label);
     void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register &reg);
 
     void canonicalizeDouble(FloatRegister reg) {
         Label notNaN;
         branchDouble(DoubleOrdered, reg, reg, &notNaN);
         loadConstantDouble(JS::GenericNaN(), reg);