Bug 945453 - Postbarrier JIT-code writes to arguments objects r=terrence r=djvj
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 11 Dec 2013 14:03:24 +0000
changeset 175920 7201bf07232e7b43aa5242166b4ba40daa69def2
parent 175919 9e38b4476027828f4291d17b17c7ca5be9f894cd
child 175921 c8d4a4361516211d2e725502d4a73d1ed6ac6356
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, djvj
bugs945453
milestone29.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 945453 - Postbarrier JIT-code writes to arguments objects r=terrence r=djvj
js/src/gc/StoreBuffer.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/IonBuilder.cpp
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef JSGC_GENERATIONAL
 
 #include "gc/StoreBuffer.h"
 
 #include "mozilla/Assertions.h"
 
+#include "vm/ArgumentsObject.h"
 #include "vm/ForkJoin.h"
 
 #include "jsgcinlines.h"
 
 using namespace js;
 using namespace js::gc;
 using mozilla::ReentrancyGuard;
 
@@ -59,17 +60,21 @@ StoreBuffer::SlotEdge::isNullEdge() cons
 }
 
 void
 StoreBuffer::WholeCellEdges::mark(JSTracer *trc)
 {
     JS_ASSERT(tenured->isTenured());
     JSGCTraceKind kind = GetGCThingTraceKind(tenured);
     if (kind <= JSTRACE_OBJECT) {
-        MarkChildren(trc, static_cast<JSObject *>(tenured));
+        JSObject *object = static_cast<JSObject *>(tenured);
+        if (object->is<ArgumentsObject>())
+            ArgumentsObject::trace(trc, object);
+        else
+            MarkChildren(trc, object);
         return;
     }
 #ifdef JS_ION
     JS_ASSERT(kind == JSTRACE_IONCODE);
     static_cast<jit::IonCode *>(tenured)->trace(trc);
 #else
     MOZ_ASSUME_UNREACHABLE("Only objects can be in the wholeCellBuffer if IonMonkey is disabled.");
 #endif
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2338,16 +2338,36 @@ BaselineCompiler::emitFormalArgAccess(ui
     // Load/store the argument.
     Address argAddr(reg, ArgumentsData::offsetOfArgs() + arg * sizeof(Value));
     if (get) {
         masm.loadValue(argAddr, R0);
         frame.push(R0);
     } else {
         masm.patchableCallPreBarrier(argAddr, MIRType_Value);
         storeValue(frame.peek(-1), argAddr, R0);
+
+#ifdef JSGC_GENERATIONAL
+        // Fully sync the stack if post-barrier is needed.
+        frame.syncStack(0);
+
+        // Reload the arguments object
+        Register reg = R2.scratchReg();
+        masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg);
+
+        Nursery &nursery = cx->runtime()->gcNursery;
+        Label skipBarrier;
+        Label isTenured;
+        masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.start()), &isTenured);
+        masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.heapEnd()), &skipBarrier);
+
+        masm.bind(&isTenured);
+        masm.call(&postBarrierSlot_);
+
+        masm.bind(&skipBarrier);
+#endif
     }
 
     masm.bind(&done);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_GETARG()
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -9106,17 +9106,20 @@ IonBuilder::jsop_setarg(uint32_t arg)
     // captured by the GETARG and by the resume point, only by
     // MGetFrameArgument.
     JS_ASSERT(analysis_.hasSetArg());
     MDefinition *val = current->peek(-1);
 
     // If an arguments object is in use, and it aliases formals, then all SETARGs
     // must go through the arguments object.
     if (info().argsObjAliasesFormals()) {
-        current->add(MSetArgumentsObjectArg::New(alloc(), current->argumentsObject(), GET_SLOTNO(pc), val));
+        if (NeedsPostBarrier(info(), val))
+            current->add(MPostWriteBarrier::New(alloc(), current->argumentsObject(), val));
+        current->add(MSetArgumentsObjectArg::New(alloc(), current->argumentsObject(),
+                                                 GET_SLOTNO(pc), val));
         return true;
     }
 
     // Otherwise, if a magic arguments is in use, and it aliases formals, and there exist
     // arguments[...] GETELEM expressions in the script, then SetFrameArgument must be used.
     // If no arguments[...] GETELEM expressions are in the script, and an argsobj is not
     // required, then it means that any aliased argument set can never be observed, and
     // the frame does not actually need to be updated with the new arg value.