зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
b71790af51
Коммит
39d156eef0
|
@ -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;
|
||||
|
||||
/* Let the API user decide to defer a GC if it wants to. */
|
||||
if (rt->gcCallback && !rt->gcCallback(cx, JSGC_BEGIN))
|
||||
/* 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 (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
|
||||
|
|
Загрузка…
Ссылка в новой задаче