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 379182 7b852b9750055433ba5bd46473602ba42422a045
parent 379181 d2cecf0997150e0d18e459d058db82b5253dc9f8
child 379183 1fe52840b0eaa4b2ca02f66446351640a2848704
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, gchang
bugs1344686
milestone53.0
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();
 }
 
 bool
 RegExpObject::getShared(JSContext* cx, RegExpGuard* g)
 {
     if (RegExpShared* shared = 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, 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 = TraceLoggerForMainThread(cx->runtime());
@@ -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);
     }