Bug 926512 - Pause barrier verification during fork join sections. (r=billm)
authorShu-yu Guo <shu@rfrn.org>
Tue, 15 Oct 2013 01:30:36 -0700
changeset 164606 7664c5abfdbd463ee71c1e1e561d216979f0f255
parent 164605 5db1f111ac1972307ec97a6c4819cf5811bff503
child 164607 0ce5fda9fbe2cbe1f4d213c8942cd82c1087057c
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)
reviewersbillm
bugs926512
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 926512 - Pause barrier verification during fork join sections. (r=billm)
js/src/vm/ForkJoin.cpp
js/src/vm/ForkJoin.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -450,16 +450,53 @@ class AutoSetForkJoinSlice
     ~AutoSetForkJoinSlice() {
         PR_SetThreadPrivate(ForkJoinSlice::ThreadPrivateIndex, nullptr);
     }
 };
 
 } // namespace js
 
 ///////////////////////////////////////////////////////////////////////////
+// ForkJoinActivation
+//
+// Takes care of tidying up GC before we enter a fork join section. Also
+// pauses the barrier verifier, as we cannot enter fork join with the runtime
+// or the zone needing barriers.
+
+ForkJoinActivation::ForkJoinActivation(JSContext *cx)
+  : Activation(cx, ForkJoin),
+    prevIonTop_(cx->mainThread().ionTop),
+    av_(cx->runtime(), false)
+{
+    // Note: we do not allow GC during parallel sections.
+    // Moreover, we do not wish to worry about making
+    // write barriers thread-safe.  Therefore, we guarantee
+    // that there is no incremental GC in progress and force
+    // a minor GC to ensure no cross-generation pointers get
+    // created:
+
+    if (JS::IsIncrementalGCInProgress(cx->runtime())) {
+        JS::PrepareForIncrementalGC(cx->runtime());
+        JS::FinishIncrementalGC(cx->runtime(), JS::gcreason::API);
+    }
+
+    MinorGC(cx->runtime(), JS::gcreason::API);
+
+    cx->runtime()->gcHelperThread.waitBackgroundSweepEnd();
+
+    JS_ASSERT(!cx->runtime()->needsBarrier());
+    JS_ASSERT(!cx->zone()->needsBarrier());
+}
+
+ForkJoinActivation::~ForkJoinActivation()
+{
+    cx_->mainThread().ionTop = prevIonTop_;
+}
+
+///////////////////////////////////////////////////////////////////////////
 // js::ForkJoin() and ParallelDo class
 //
 // These are the top-level objects that manage the parallel execution.
 // They handle parallel compilation (if necessary), triggering
 // parallel execution, and recovering from bailouts.
 
 static const char *ForkJoinModeString(ForkJoinMode mode);
 
--- a/js/src/vm/ForkJoin.h
+++ b/js/src/vm/ForkJoin.h
@@ -4,16 +4,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_ForkJoin_h
 #define vm_ForkJoin_h
 
 #include "jscntxt.h"
 
+#include "gc/GCInternals.h"
+
 #include "jit/Ion.h"
 
 ///////////////////////////////////////////////////////////////////////////
 // Read Me First
 //
 // The ForkJoin abstraction:
 // -------------------------
 //
@@ -194,16 +196,31 @@
 // - No load balancing is performed between worker threads.  That means that
 //   the fork-join system is best suited for problems that can be slice into
 //   uniform bits.
 //
 ///////////////////////////////////////////////////////////////////////////
 
 namespace js {
 
+class ForkJoinActivation : public Activation
+{
+    uint8_t *prevIonTop_;
+
+    // We ensure that incremental GC be finished before we enter into a fork
+    // join section, but the runtime/zone might still be marked as needing
+    // barriers due to being in the middle of verifying barriers. Pause
+    // verification during the fork join section.
+    gc::AutoStopVerifyingBarriers av_;
+
+  public:
+    ForkJoinActivation(JSContext *cx);
+    ~ForkJoinActivation();
+};
+
 class ForkJoinSlice;
 
 bool ForkJoin(JSContext *cx, CallArgs &args);
 
 // Returns the number of slices that a fork-join op will have when
 // executed.
 uint32_t ForkJoinSlices(JSContext *cx);
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1331,42 +1331,16 @@ jit::JitActivation::setActive(JSContext 
         prevIonJSContext_ = cx->mainThread().ionJSContext;
         cx->mainThread().ionJSContext = cx;
     } else {
         cx->mainThread().ionTop = prevIonTop_;
         cx->mainThread().ionJSContext = prevIonJSContext_;
     }
 }
 
-ForkJoinActivation::ForkJoinActivation(JSContext *cx)
-  : Activation(cx, ForkJoin),
-    prevIonTop_(cx->mainThread().ionTop)
-{
-    // Note: we do not allow GC during parallel sections.
-    // Moreover, we do not wish to worry about making
-    // write barriers thread-safe.  Therefore, we guarantee
-    // that there is no incremental GC in progress and force
-    // a minor GC to ensure no cross-generation pointers get
-    // created:
-
-    if (JS::IsIncrementalGCInProgress(cx->runtime())) {
-        JS::PrepareForIncrementalGC(cx->runtime());
-        JS::FinishIncrementalGC(cx->runtime(), JS::gcreason::API);
-    }
-
-    MinorGC(cx->runtime(), JS::gcreason::API);
-
-    cx->runtime()->gcHelperThread.waitBackgroundSweepEnd();
-}
-
-ForkJoinActivation::~ForkJoinActivation()
-{
-    cx_->mainThread().ionTop = prevIonTop_;
-}
-
 InterpreterFrameIterator &
 InterpreterFrameIterator::operator++()
 {
     JS_ASSERT(!done());
     if (fp_ != activation_->entry_) {
         pc_ = fp_->prevpc();
         sp_ = fp_->prevsp();
         fp_ = fp_->prev();
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1395,25 +1395,16 @@ class JitActivationIterator : public Act
     }
 
     // Returns the bottom and top addresses of the current JitActivation.
     void jitStackRange(uintptr_t *&min, uintptr_t *&end);
 };
 
 } // namespace jit
 
-class ForkJoinActivation : public Activation
-{
-    uint8_t *prevIonTop_;
-
-  public:
-    ForkJoinActivation(JSContext *cx);
-    ~ForkJoinActivation();
-};
-
 // Iterates over the frames of a single InterpreterActivation.
 class InterpreterFrameIterator
 {
     InterpreterActivation *activation_;
     StackFrame *fp_;
     jsbytecode *pc_;
     Value *sp_;