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

This commit is contained in:
jband%netscape.com 2001-02-02 08:44:24 +00:00
Родитель b71790af51
Коммит 39d156eef0
5 изменённых файлов: 37 добавлений и 9 удалений

Просмотреть файл

@ -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)
{

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -251,7 +251,8 @@ typedef JSBool
typedef enum JSGCStatus {
JSGC_BEGIN,
JSGC_END
JSGC_END,
JSGC_MARK_END
} JSGCStatus;
typedef JSBool