Bug 1237445 - Use GCHashSet for RegExpShared sweeping, r=terrence
authorSteve Fink <sfink@mozilla.com>
Tue, 12 Jan 2016 12:55:35 -0800
changeset 281962 c1153dc8ccd12858e6f0e2b3762e2331b9feee01
parent 281961 d0b106a76c7f44f96aea815e7dfb74902d49b386
child 281963 d8f94c8056847a041d918102131eab86f15cd4ed
push id17275
push usercbook@mozilla.com
push dateThu, 28 Jan 2016 11:37:27 +0000
treeherderfx-team@e2d11e2d506c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1237445
milestone47.0a1
Bug 1237445 - Use GCHashSet for RegExpShared sweeping, r=terrence
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -782,48 +782,53 @@ RegExpCompartment::init(JSContext* cx)
         if (cx)
             ReportOutOfMemory(cx);
         return false;
     }
 
     return true;
 }
 
+bool
+RegExpShared::needsSweep(JSRuntime* rt)
+{
+    // Sometimes RegExpShared instances are marked without the compartment
+    // being subsequently cleared. This can happen if a GC is restarted while
+    // in progress (i.e. performing a full GC in the middle of an incremental
+    // GC) or if a RegExpShared referenced via the stack is traced but is not
+    // in a zone being collected.
+    //
+    // Because of this we only treat the marked_ bit as a hint, and destroy the
+    // RegExpShared if it was accidentally marked earlier but wasn't marked by
+    // the current trace.
+    bool keep = marked() && IsMarked(&source);
+    for (size_t i = 0; i < ArrayLength(compilationArray); i++) {
+        RegExpShared::RegExpCompilation& compilation = compilationArray[i];
+        if (compilation.jitCode && gc::IsAboutToBeFinalized(&compilation.jitCode))
+            keep = false;
+    }
+
+    MOZ_ASSERT(rt->isHeapMajorCollecting());
+    if (keep || rt->gc.isHeapCompacting()) {
+        clearMarked();
+        return false;
+    }
+
+    return true;
+}
+
 void
 RegExpCompartment::sweep(JSRuntime* rt)
 {
     if (!set_.initialized())
         return;
 
     for (Set::Enum e(set_); !e.empty(); e.popFront()) {
         RegExpShared* shared = e.front();
-
-        // Sometimes RegExpShared instances are marked without the
-        // compartment being subsequently cleared. This can happen if a GC is
-        // restarted while in progress (i.e. performing a full GC in the
-        // middle of an incremental GC) or if a RegExpShared referenced via the
-        // stack is traced but is not in a zone being collected.
-        //
-        // Because of this we only treat the marked_ bit as a hint, and destroy
-        // the RegExpShared if it was accidentally marked earlier but wasn't
-        // marked by the current trace.
-        bool keep = shared->marked() &&
-                    IsMarked(&shared->source);
-        for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) {
-            RegExpShared::RegExpCompilation& compilation = shared->compilationArray[i];
-            if (compilation.jitCode &&
-                IsAboutToBeFinalized(&compilation.jitCode))
-            {
-                keep = false;
-            }
-        }
-        MOZ_ASSERT(rt->isHeapMajorCollecting());
-        if (keep || rt->gc.isHeapCompacting()) {
-            shared->clearMarked();
-        } else {
+        if (shared->needsSweep(rt)) {
             js_delete(shared);
             e.removeFront();
         }
     }
 
     if (matchResultTemplateObject_ &&
         IsAboutToBeFinalized(&matchResultTemplateObject_))
     {
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -196,16 +196,17 @@ class RegExpShared
     bool isCompiled() const {
         return isCompiled(Normal, true, true) || isCompiled(Normal, true, false)
             || isCompiled(Normal, false, true) || isCompiled(Normal, false, false)
             || isCompiled(MatchOnly, true, true) || isCompiled(MatchOnly, true, false)
             || isCompiled(MatchOnly, false, true) || isCompiled(MatchOnly, false, false);
     }
 
     void trace(JSTracer* trc);
+    bool needsSweep(JSRuntime* rt);
 
     bool marked() const { return marked_; }
     void clearMarked() { marked_ = false; }
 
     static size_t offsetOfSource() {
         return offsetof(RegExpShared, source);
     }