From 39d156eef0b342ce6d42e75254958962d7953b65 Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Fri, 2 Feb 2001 08:44:24 +0000 Subject: [PATCH] part of the fix to bug 66950. Add support for cheaply tracking the lifetime of arbitrary JSObject by extending the GC callback mechanism to notify after marking is done but before sweeping, and by providing an api function that can be called at that point to determine if any given gcthing is about to be finalized. r=rogerl sr=brendan --- js/src/jsapi.c | 7 +++++++ js/src/jsapi.h | 3 +++ js/src/jsgc.c | 30 ++++++++++++++++++++++-------- js/src/jsgc.h | 3 +++ js/src/jspubtd.h | 3 ++- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/js/src/jsapi.c b/js/src/jsapi.c index 563d18178b34..169448a62e5f 100644 --- a/js/src/jsapi.c +++ b/js/src/jsapi.c @@ -1631,6 +1631,13 @@ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb) return oldcb; } +JS_PUBLIC_API(JSBool) +JS_IsAboutToBeFinalized(JSContext *cx, void *thing) +{ + JS_ASSERT(thing); + return js_IsAboutToBeFinalized(cx, thing); +} + JS_PUBLIC_API(intN) JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d970064ed508..24e1a7033e67 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -562,6 +562,9 @@ JS_SetGCCallback(JSContext *cx, JSGCCallback cb); extern JS_PUBLIC_API(JSGCCallback) JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb); +extern JS_PUBLIC_API(JSBool) +JS_IsAboutToBeFinalized(JSContext *cx, void *thing); + /* * Add an external string finalizer, one created by JS_NewExternalString (see * below) using a type-code returned from this function, and that understands diff --git a/js/src/jsgc.c b/js/src/jsgc.c index 18d8342bd24c..0a5616e6207a 100644 --- a/js/src/jsgc.c +++ b/js/src/jsgc.c @@ -214,6 +214,12 @@ gc_find_flags(void *thing) return flagp; } +JSBool js_IsAboutToBeFinalized(JSContext *cx, void *thing) +{ + uint8 flags = *gc_find_flags(thing); + return !(flags & (GCF_MARK | GCF_LOCKMASK | GCF_FINAL)); +} + typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing); static GCFinalizeOp gc_finalizers[GCX_NTYPES]; @@ -331,7 +337,7 @@ js_FinishGC(JSRuntime *rt) JS_FinishArenaPool(&rt->gcArenaPool); JS_ArenaFinish(); -#if DEBUG +#ifdef DEBUG { uint32 leakedroots = 0; /* Warn (but don't assert) debug builds of any remaining roots. */ @@ -966,12 +972,17 @@ js_GC(JSContext *cx, uintN gcflags) /* Avoid deadlock. */ JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt)); #endif - if (!(gcflags & GC_LAST_CONTEXT)) { - if (rt->gcDisabled) - return; + + /* Don't run gc if it is disabled (unless this is the last context). */ + if (rt->gcDisabled && !(gcflags & GC_LAST_CONTEXT)) + return; - /* Let the API user decide to defer a GC if it wants to. */ - if (rt->gcCallback && !rt->gcCallback(cx, JSGC_BEGIN)) + /* + * Let the API user decide to defer a GC if it wants to (unless this + * is the last context). Call the callback regardless. + */ + if (rt->gcCallback) { + if (!rt->gcCallback(cx, JSGC_BEGIN) && !(gcflags & GC_LAST_CONTEXT)) return; } @@ -1169,6 +1180,9 @@ restart: } } + if (rt->gcCallback) + (void) rt->gcCallback(cx, JSGC_MARK_END); + /* * Sweep phase. * Finalize as we sweep, outside of rt->gcLock, but with rt->gcRunning set @@ -1275,6 +1289,6 @@ out: JS_UNLOCK_GC(rt); #endif - if (!(gcflags & GC_LAST_CONTEXT) && rt->gcCallback) - (void) rt->gcCallback(cx, JSGC_END); + if (rt->gcCallback) + (void) rt->gcCallback(cx, JSGC_END); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 75fc7b6e2115..589308e33448 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -94,6 +94,9 @@ js_LockGCThing(JSContext *cx, void *thing); extern JSBool js_UnlockGCThing(JSContext *cx, void *thing); +extern JSBool +js_IsAboutToBeFinalized(JSContext *cx, void *thing); + extern void js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg); diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index e35c70c83c48..f0c4db312e2b 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -251,7 +251,8 @@ typedef JSBool typedef enum JSGCStatus { JSGC_BEGIN, - JSGC_END + JSGC_END, + JSGC_MARK_END } JSGCStatus; typedef JSBool