Bug 1237445 - Use GCHashSet for RegExpShared sweeping, r=terrence
authorSteve Fink <sfink@mozilla.com>
Tue, 12 Jan 2016 12:55:35 -0800
changeset 281954 c1153dc8ccd12858e6f0e2b3762e2331b9feee01
parent 281953 d0b106a76c7f44f96aea815e7dfb74902d49b386
child 281955 d8f94c8056847a041d918102131eab86f15cd4ed
push id29950
push usercbook@mozilla.com
push dateThu, 28 Jan 2016 11:14:03 +0000
treeherdermozilla-central@2b73b0a4d52b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1237445
milestone47.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 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);
     }