Bug 1337427 - Implement GCVector::sweep, r=jonco
authorSteve Fink <sfink@mozilla.com>
Tue, 07 Feb 2017 16:12:25 -0800
changeset 373819 9bccecac02bbf9a84645acb9755bace9236dd20c
parent 373818 71bbaf9a0d0ff6b014ecbc43a32eca2ad68906cc
child 373820 237552f782e7c1d474b46b9aa2b540326860e41d
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1337427
milestone54.0a1
Bug 1337427 - Implement GCVector::sweep, r=jonco MozReview-Commit-ID: 6q2OlAHHMsy
js/public/GCVector.h
js/src/jsapi-tests/testGCWeakCache.cpp
--- a/js/public/GCVector.h
+++ b/js/public/GCVector.h
@@ -124,16 +124,30 @@ class GCVector
     }
 
     static void trace(GCVector* vec, JSTracer* trc) { vec->trace(trc); }
 
     void trace(JSTracer* trc) {
         for (auto& elem : vector)
             GCPolicy<T>::trace(trc, &elem, "vector element");
     }
+
+    void sweep() {
+        uint32_t src, dst = 0;
+        for (src = 0; src < length(); src++) {
+            if (!GCPolicy<T>::needsSweep(&vector[src])) {
+                if (dst != src)
+                    vector[dst] = vector[src].unbarrieredGet();
+                dst++;
+            }
+        }
+
+        if (dst != length())
+            vector.shrinkTo(dst);
+    }
 };
 
 } // namespace JS
 
 namespace js {
 
 template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
 class WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
--- a/js/src/jsapi-tests/testGCWeakCache.cpp
+++ b/js/src/jsapi-tests/testGCWeakCache.cpp
@@ -87,8 +87,46 @@ BEGIN_TEST(testWeakCacheMap)
     JS_GC(cx);
     CHECK(cache.has(tenured1));
     CHECK(cache.has(nursery1));
     CHECK(cache.count() == 2);
 
     return true;
 }
 END_TEST(testWeakCacheMap)
+
+// Exercise WeakCache<GCVector>.
+BEGIN_TEST(testWeakCacheGCVector)
+{
+    // Create two objects tenured and two in the nursery. If zeal is on,
+    // this may fail and we'll get more tenured objects. That's fine:
+    // the test will continue to work, it will just not test as much.
+    JS::RootedObject tenured1(cx, JS_NewPlainObject(cx));
+    JS::RootedObject tenured2(cx, JS_NewPlainObject(cx));
+    JS_GC(cx);
+    JS::RootedObject nursery1(cx, JS_NewPlainObject(cx));
+    JS::RootedObject nursery2(cx, JS_NewPlainObject(cx));
+
+    using ObjectVector = js::GCVector<JS::Heap<JSObject*>>;
+    using Cache = JS::WeakCache<ObjectVector>;
+    auto cache = Cache(JS::GetObjectZone(tenured1), ObjectVector(cx));
+
+    CHECK(cache.append(tenured1));
+    CHECK(cache.append(tenured2));
+    CHECK(cache.append(nursery1));
+    CHECK(cache.append(nursery2));
+
+    JS_GC(cx);
+    CHECK(cache.get().length() == 4);
+    CHECK(cache.get()[0] == tenured1);
+    CHECK(cache.get()[1] == tenured2);
+    CHECK(cache.get()[2] == nursery1);
+    CHECK(cache.get()[3] == nursery2);
+
+    tenured2 = nursery2 = nullptr;
+    JS_GC(cx);
+    CHECK(cache.get().length() == 2);
+    CHECK(cache.get()[0] == tenured1);
+    CHECK(cache.get()[1] == nursery1);
+
+    return true;
+}
+END_TEST(testWeakCacheGCVector)