Bug 1119584 - Return number of allocations until next zeal GC, r=terrence
authorSteve Fink <sfink@mozilla.com>
Thu, 08 Jan 2015 22:41:31 -0800
changeset 248690 20ed57d8a4e7ecc2d3a10d28533b03675b749f74
parent 248689 575af71f0b2414484878c0ab118c6365affc0837
child 248691 493811e4694e6ca903a9e6a3a8cae3045e878a33
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1119584
milestone37.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 1119584 - Return number of allocations until next zeal GC, r=terrence
js/src/builtin/TestingFunctions.cpp
js/src/gc/GCRuntime.h
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsgc.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -472,35 +472,41 @@ GCZeal(JSContext *cx, unsigned argc, Val
     return true;
 }
 
 static bool
 ScheduleGC(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    if (args.length() != 1) {
+    if (args.length() > 1) {
         RootedObject callee(cx, &args.callee());
-        ReportUsageError(cx, callee, "Wrong number of arguments");
+        ReportUsageError(cx, callee, "Too many arguments");
         return false;
     }
 
-    if (args[0].isInt32()) {
+    if (args.length() == 0) {
+        /* Fetch next zeal trigger only. */
+    } else if (args[0].isInt32()) {
         /* Schedule a GC to happen after |arg| allocations. */
         JS_ScheduleGC(cx, args[0].toInt32());
     } else if (args[0].isObject()) {
         /* Ensure that |zone| is collected during the next GC. */
         Zone *zone = UncheckedUnwrap(&args[0].toObject())->zone();
         PrepareZoneForGC(zone);
     } else if (args[0].isString()) {
         /* This allows us to schedule atomsCompartment for GC. */
         PrepareZoneForGC(args[0].toString()->zone());
     }
 
-    args.rval().setUndefined();
+    uint8_t zeal;
+    uint32_t freq;
+    uint32_t next;
+    JS_GetGCZeal(cx, &zeal, &freq, &next);
+    args.rval().setInt32(next);
     return true;
 }
 
 static bool
 SelectForGC(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
@@ -2276,19 +2282,20 @@ static const JSFunctionSpecWithHelp Test
 "  Preserve JIT code during garbage collections."),
 
 #ifdef JS_GC_ZEAL
     JS_FN_HELP("gczeal", GCZeal, 2, 0,
 "gczeal(level, [N])",
 gc::ZealModeHelpText),
 
     JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
-"schedulegc(num | obj)",
+"schedulegc([num | obj])",
 "  If num is given, schedule a GC after num allocations.\n"
-"  If obj is given, schedule a GC of obj's compartment."),
+"  If obj is given, schedule a GC of obj's compartment.\n"
+"  Returns the number of allocations before the next trigger."),
 
     JS_FN_HELP("selectforgc", SelectForGC, 0, 0,
 "selectforgc(obj1, obj2, ...)",
 "  Schedule the given objects to be marked in the next GC slice."),
 
     JS_FN_HELP("verifyprebarriers", VerifyPreBarriers, 0, 0,
 "verifyprebarriers()",
 "  Start or end a run of the pre-write barrier verifier."),
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -339,17 +339,17 @@ class GCRuntime
 
     void notifyDidPaint();
     void shrinkBuffers();
     void onOutOfMallocMemory();
     void onOutOfMallocMemory(const AutoLockGC &lock);
 
 #ifdef JS_GC_ZEAL
     const void *addressOfZealMode() { return &zealMode; }
-    void getZeal(uint8_t *zeal, uint32_t *frequency);
+    void getZeal(uint8_t *zeal, uint32_t *frequency, uint32_t *nextScheduled);
     void setZeal(uint8_t zeal, uint32_t frequency);
     bool parseAndSetZeal(const char *str);
     void setNextScheduled(uint32_t count);
     void verifyPreBarriers();
     void verifyPostBarriers();
     void maybeVerifyPreBarriers(bool always);
     void maybeVerifyPostBarriers(bool always);
     bool selectForMarking(JSObject *object);
@@ -844,20 +844,20 @@ class GCRuntime
      * or a compartmental GC, based on debugCompartmentGC.
      *
      * At this point, if zeal_ is one of the types that trigger periodic
      * collection, then nextScheduled is reset to the value of zealFrequency.
      * Otherwise, no additional GCs take place.
      *
      * You can control these values in several ways:
      *   - Set the JS_GC_ZEAL environment variable
-     *   - Call zeal() or schedulegc() from inside shell-executed JS code
+     *   - Call gczeal() or schedulegc() from inside shell-executed JS code
      *     (see the help for details)
      *
-     * If gzZeal_ == 1 then we perform GCs in select places (during MaybeGC and
+     * If gcZeal_ == 1 then we perform GCs in select places (during MaybeGC and
      * whenever a GC poke happens). This option is mainly useful to embedders.
      *
      * We use zeal_ == 4 to enable write barrier verification. See the comment
      * in jsgc.cpp for more information about this.
      *
      * zeal_ values from 8 to 10 periodically run different types of
      * incremental GC.
      *
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -420,17 +420,18 @@ class TestJSPrincipals : public JSPrinci
 class AutoLeaveZeal
 {
     JSContext *cx_;
     uint8_t zeal_;
     uint32_t frequency_;
 
   public:
     explicit AutoLeaveZeal(JSContext *cx) : cx_(cx) {
-        JS_GetGCZeal(cx_, &zeal_, &frequency_);
+        uint32_t dummy;
+        JS_GetGCZeal(cx_, &zeal_, &frequency_, &dummy);
         JS_SetGCZeal(cx_, 0, 0);
         JS::PrepareForFullGC(JS_GetRuntime(cx_));
         JS::GCForReason(JS_GetRuntime(cx_), GC_SHRINK, JS::gcreason::DEBUG_GC);
     }
     ~AutoLeaveZeal() {
         JS_SetGCZeal(cx_, zeal_, frequency_);
     }
 };
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5742,19 +5742,19 @@ JS_AbortIfWrongThread(JSRuntime *rt)
     if (!CurrentThreadCanAccessRuntime(rt))
         MOZ_CRASH();
     if (!js::TlsPerThreadData.get()->associatedWith(rt))
         MOZ_CRASH();
 }
 
 #ifdef JS_GC_ZEAL
 JS_PUBLIC_API(void)
-JS_GetGCZeal(JSContext *cx, uint8_t *zeal, uint32_t *frequency)
-{
-    cx->runtime()->gc.getZeal(zeal, frequency);
+JS_GetGCZeal(JSContext *cx, uint8_t *zeal, uint32_t *frequency, uint32_t *nextScheduled)
+{
+    cx->runtime()->gc.getZeal(zeal, frequency, nextScheduled);
 }
 
 JS_PUBLIC_API(void)
 JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
 {
     cx->runtime()->gc.setZeal(zeal, frequency);
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5060,17 +5060,17 @@ extern JS_PUBLIC_API(JSObject *)
 JS_NewObjectForConstructor(JSContext *cx, const JSClass *clasp, const JS::CallArgs& args);
 
 /************************************************************************/
 
 #ifdef JS_GC_ZEAL
 #define JS_DEFAULT_ZEAL_FREQ 100
 
 extern JS_PUBLIC_API(void)
-JS_GetGCZeal(JSContext *cx, uint8_t *zeal, uint32_t *frequency);
+JS_GetGCZeal(JSContext *cx, uint8_t *zeal, uint32_t *frequency, uint32_t *nextScheduled);
 
 extern JS_PUBLIC_API(void)
 JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency);
 
 extern JS_PUBLIC_API(void)
 JS_ScheduleGC(JSContext *cx, uint32_t count);
 #endif
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1152,20 +1152,21 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
     helperState(rt)
 {
     setGCMode(JSGC_MODE_GLOBAL);
 }
 
 #ifdef JS_GC_ZEAL
 
 void
-GCRuntime::getZeal(uint8_t *zeal, uint32_t *frequency)
+GCRuntime::getZeal(uint8_t *zeal, uint32_t *frequency, uint32_t *scheduled)
 {
     *zeal = zealMode;
     *frequency = zealFrequency;
+    *scheduled = nextScheduled;
 }
 
 const char *gc::ZealModeHelpText =
     "  Specifies how zealous the garbage collector should be. Values for level:\n"
     "    0: Normal amount of collection\n"
     "    1: Collect when roots are added or removed\n"
     "    2: Collect when every N allocations (default: 100)\n"
     "    3: Collect when the window paints (browser only)\n"