Bug 1528159 - Add finishgc() calls before each startgc() call r=sfink
authorPaul Bone <pbone@mozilla.com>
Fri, 01 Mar 2019 17:55:13 +0000
changeset 520023 dab1f2af9040b67c0458bc83b1a6ddd149735a3a
parent 520022 7dc59aadcb9d3e6b9698f0a6e1b0813f2502baa9
child 520024 179ed9bc4e22f4f733ce97e6465a211bdc1d6bee
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1528159
milestone67.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 1528159 - Add finishgc() calls before each startgc() call r=sfink Avoid assertion failures with this test by adding finishgc() calls. Add finisgc() shell builtin functions. Differential Revision: https://phabricator.services.mozilla.com/D21644
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/gc/weak-marking-01.js
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1217,16 +1217,34 @@ static bool StartGC(JSContext* cx, unsig
 
   JSGCInvocationKind gckind = shrinking ? GC_SHRINK : GC_NORMAL;
   rt->gc.startDebugGC(gckind, budget);
 
   args.rval().setUndefined();
   return true;
 }
 
+static bool FinishGC(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+
+  if (args.length() > 0) {
+    RootedObject callee(cx, &args.callee());
+    ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
+    return false;
+  }
+
+  JSRuntime* rt = cx->runtime();
+  if (rt->gc.isIncrementalGCInProgress()) {
+    rt->gc.finishGC(JS::GCReason::DEBUG_GC);
+  }
+
+  args.rval().setUndefined();
+  return true;
+}
+
 static bool GCSlice(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   if (args.length() > 1) {
     RootedObject callee(cx, &args.callee());
     ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
     return false;
   }
@@ -5867,16 +5885,20 @@ gc::ZealModeHelpText),
 #endif
 
     JS_FN_HELP("startgc", StartGC, 1, 0,
 "startgc([n [, 'shrinking']])",
 "  Start an incremental GC and run a slice that processes about n objects.\n"
 "  If 'shrinking' is passesd as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
 
+    JS_FN_HELP("finishgc", FinishGC, 0, 0,
+"finishgc()",
+"   Finish an in-progress incremental GC, if none is running then do nothing."),
+
     JS_FN_HELP("gcslice", GCSlice, 1, 0,
 "gcslice([n])",
 "  Start or continue an an incremental GC, running a slice that processes about n objects."),
 
     JS_FN_HELP("abortgc", AbortGC, 1, 0,
 "abortgc()",
 "  Abort the current incremental GC."),
 
--- a/js/src/jit-test/tests/gc/weak-marking-01.js
+++ b/js/src/jit-test/tests/gc/weak-marking-01.js
@@ -8,16 +8,17 @@ gczeal(0);
 // All reachable keys should be found, and the rest should be swept.
 function basicSweeping() {
   var wm1 = new WeakMap();
   wm1.set({'name': 'obj1'}, {'name': 'val1'});
   var hold = {'name': 'obj2'};
   wm1.set(hold, {'name': 'val2'});
   wm1.set({'name': 'obj3'}, {'name': 'val3'});
 
+  finishgc();
   startgc(100000, 'shrinking');
   gcslice();
 
   assertEq(wm1.get(hold).name, 'val2');
   assertEq(nondeterministicGetWeakMapKeys(wm1).length, 1);
 }
 
 basicSweeping();
@@ -31,16 +32,17 @@ function weakGraph() {
   var obj4 = {'name': 'obj4'};
   var clear = {'name': ''}; // Make the interpreter forget about the last obj created
 
   wm1.set(obj2, obj3);
   wm1.set(obj3, obj1);
   wm1.set(obj4, obj1); // This edge will be cleared
   obj1 = obj3 = obj4 = undefined;
 
+  finishgc();
   startgc(100000, 'shrinking');
   gcslice();
 
   assertEq(obj2.name, "obj2");
   assertEq(wm1.get(obj2).name, "obj3");
   assertEq(wm1.get(wm1.get(obj2)).name, "obj1");
   print(nondeterministicGetWeakMapKeys(wm1).map(o => o.name).join(","));
   assertEq(nondeterministicGetWeakMapKeys(wm1).length, 2);
@@ -59,16 +61,17 @@ function deadWeakMap() {
 
   wm1.set(obj2, obj3);
   wm1.set(obj3, obj1);
   wm1.set(obj4, obj1); // This edge will be cleared
   var initialCount = finalizeCount();
   obj1 = obj3 = obj4 = undefined;
   wm1 = undefined;
 
+  finishgc();
   startgc(100000, 'shrinking');
   gcslice();
 
   assertEq(obj2.name, "obj2");
   assertEq(finalizeCount(), initialCount + 1);
 }
 
 deadWeakMap();
@@ -86,16 +89,17 @@ function deadKeys() {
   var obj3 = makeFinalizeObserver();
   var clear = {}; // Make the interpreter forget about the last obj created
 
   wm1.set(obj1, obj1);
   wm1.set(obj3, obj2);
   obj1 = obj3 = undefined;
   var initialCount = finalizeCount();
 
+  finishgc();
   startgc(100000, 'shrinking');
   gcslice();
 
   assertEq(finalizeCount(), initialCount + 2);
   assertEq(nondeterministicGetWeakMapKeys(wm1).length, 0);
 }
 
 deadKeys();
@@ -119,16 +123,17 @@ function weakKeysRealloc() {
     wm3.set(Object.create(null), wm2);
   }
   wm3.set(Object.create(null), makeFinalizeObserver());
   wm2 = undefined;
   wm3 = undefined;
   obj2 = undefined;
 
   var initialCount = finalizeCount();
+  finishgc();
   startgc(100000, 'shrinking');
   gcslice();
   assertEq(finalizeCount(), initialCount + 1);
 }
 
 weakKeysRealloc();
 
 // The weakKeys table is populated during regular marking. When a key is later
@@ -137,16 +142,17 @@ weakKeysRealloc();
 // traversals will include non-keys, etc.
 function deletedKeys() {
   var wm = new WeakMap;
   var g = newGlobal();
 
   for (var i = 0; i < 1000; i++)
     wm.set(g.Object.create(null), i);
 
+  finishgc();
   startgc(100, 'shrinking');
   for (var key of nondeterministicGetWeakMapKeys(wm)) {
     if (wm.get(key) % 2)
       wm.delete(key);
   }
 
   gc();
 }
@@ -166,16 +172,17 @@ function incrementalAdds() {
   wm2.set(obj2, wm3);
   for (var i = 0; i < 10000; i++) {
     wm3.set(Object.create(null), wm2);
   }
   wm3.set(Object.create(null), makeFinalizeObserver());
   obj2 = undefined;
 
   var obj3 = [];
+  finishgc();
   startgc(100, 'shrinking');
   var M = 10;
   var N = 800;
   for (var j = 0; j < M; j++) {
     for (var i = 0; i < N; i++)
       wm3.set(Object.create(null), makeFinalizeObserver()); // Should be swept
     for (var i = 0; i < N; i++) {
       obj3.push({'name': 'obj3'});