Bug 1344686 - Make RegExpShared's read barrier unmark gray if necessary r=sfink a=gchang
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 07 Mar 2017 17:24:22 +0000
changeset 395311 fed3d83c96b9811637c8803e7cabb9742a701315
parent 395310 0d85c641d586e78d553aa6c768d133e10feab32d
child 395312 3d9b17867a0e678181e1ea5005d90dac00cfca6b
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, gchang
bugs1344686
milestone54.0a2
Bug 1344686 - Make RegExpShared's read barrier unmark gray if necessary r=sfink a=gchang
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -115,30 +115,32 @@ VectorMatchPairs::allocOrExpandArray(siz
     pairs_ = &vec_[0];
     pairCount_ = pairCount;
     return true;
 }
 
 /* RegExpObject */
 
 static inline void
-MaybeTraceRegExpShared(JSContext* cx, RegExpShared* shared)
+RegExpSharedReadBarrier(JSContext* cx, RegExpShared* shared)
 {
     Zone* zone = cx->zone();
     if (zone->needsIncrementalBarrier())
         shared->trace(zone->barrierTracer());
+    if (shared->isMarkedGray())
+        shared->unmarkGray();
 }
 
 /* static */ bool
 RegExpObject::getShared(JSContext* cx, Handle<RegExpObject*> regexp, RegExpGuard* g)
 {
     if (RegExpShared* shared = regexp->maybeShared()) {
         // Fetching a RegExpShared from an object requires a read
         // barrier, as the shared pointer might be weak.
-        MaybeTraceRegExpShared(cx, shared);
+        RegExpSharedReadBarrier(cx, shared);
 
         g->init(*shared);
         return true;
     }
 
     return createShared(cx, regexp, g);
 }
 
@@ -956,20 +958,40 @@ RegExpShared::~RegExpShared()
 
 void
 RegExpShared::trace(JSTracer* trc)
 {
     if (trc->isMarkingTracer())
         marked_ = true;
 
     TraceNullableEdge(trc, &source, "RegExpShared source");
+    for (auto& comp : compilationArray)
+        TraceNullableEdge(trc, &comp.jitCode, "RegExpShared code");
+}
 
-    for (size_t i = 0; i < ArrayLength(compilationArray); i++) {
-        RegExpCompilation& compilation = compilationArray[i];
-        TraceNullableEdge(trc, &compilation.jitCode, "RegExpShared code");
+bool
+RegExpShared::isMarkedGray() const
+{
+    if (source && source->isMarked(gc::GRAY))
+        return true;
+    for (const auto& comp : compilationArray) {
+        if (comp.jitCode && comp.jitCode->isMarked(gc::GRAY))
+            return true;
+    }
+    return false;
+}
+
+void
+RegExpShared::unmarkGray()
+{
+    if (source)
+        JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr(source));
+    for (const auto& comp : compilationArray) {
+        if (comp.jitCode)
+            JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr(comp.jitCode.get()));
     }
 }
 
 bool
 RegExpShared::compile(JSContext* cx, HandleLinearString input,
                       CompilationMode mode, ForceByteCodeEnum force)
 {
     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
@@ -1338,33 +1360,33 @@ RegExpCompartment::sweep(JSRuntime* rt)
 bool
 RegExpCompartment::get(JSContext* cx, JSAtom* source, RegExpFlag flags, RegExpGuard* g)
 {
     Key key(source, flags);
     Set::AddPtr p = set_.lookupForAdd(key);
     if (p) {
         // Trigger a read barrier on existing RegExpShared instances fetched
         // from the table (which only holds weak references).
-        MaybeTraceRegExpShared(cx, *p);
+        RegExpSharedReadBarrier(cx, *p);
 
         g->init(**p);
         return true;
     }
 
     ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(source, flags));
     if (!shared)
         return false;
 
     if (!set_.add(p, shared)) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     // Trace RegExpShared instances created during an incremental GC.
-    MaybeTraceRegExpShared(cx, shared);
+    RegExpSharedReadBarrier(cx, shared);
 
     g->init(*shared.forget());
     return true;
 }
 
 bool
 RegExpCompartment::get(JSContext* cx, HandleAtom atom, JSString* opt, RegExpGuard* g)
 {
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -205,16 +205,19 @@ class RegExpShared
 
     void trace(JSTracer* trc);
     bool needsSweep(JSRuntime* rt);
     void discardJitCode();
 
     bool marked() const { return marked_; }
     void clearMarked() { marked_ = false; }
 
+    bool isMarkedGray() const;
+    void unmarkGray();
+
     static size_t offsetOfSource() {
         return offsetof(RegExpShared, source);
     }
 
     static size_t offsetOfFlags() {
         return offsetof(RegExpShared, flags);
     }