From 8b9fb46499c04eb41a6806f7d1b729b03113c386 Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Sun, 11 Nov 2001 21:25:13 +0000 Subject: [PATCH] Avoid ClaimScope (lock-free to -full transition) in JS_GetClass and js_FinalizeObject called from the GC (109183, r=shaver, sr=jband). --- js/src/jsapi.c | 26 ++------------------------ js/src/jsobj.c | 11 +++++++++-- js/src/jsobj.h | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/js/src/jsapi.c b/js/src/jsapi.c index 7e5d911cbdbd..092013df3bcf 100644 --- a/js/src/jsapi.c +++ b/js/src/jsapi.c @@ -1862,7 +1862,8 @@ bad: JS_PUBLIC_API(JSClass *) JS_GetClass(JSContext *cx, JSObject *obj) { - return OBJ_GET_CLASS(cx, obj); + return (JSClass *) + JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS)); } #else JS_PUBLIC_API(JSClass *) @@ -1892,29 +1893,6 @@ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv) return JS_FALSE; } -/* - * If thread-safe, define an OBJ_GET_SLOT wrapper that bypasses, for a native - * object, the lock-free "fast path" test of (OBJ_SCOPE(obj)->ownercx == cx), - * to avoid needlessly switching from lock-free to lock-full scope when doing - * GC on a different context from the last one to own the scope. The caller in - * this case is probably a JSClass.mark function, e.g., fun_mark. - * - * The GC runs only when all threads except the one on which the GC is active - * are suspended at GC-safe points, so there is no hazard in directly accessing - * obj->slots[slot] from the GC's thread, once rt->gcRunning has been set. See - * jsgc.c for details. - */ -#ifdef JS_THREADSAFE -# define GC_AWARE_GET_SLOT(cx, obj, slot) \ - (OBJ_IS_NATIVE(obj) && \ - ((cx)->runtime->gcRunning && (cx)->runtime->gcThread == (cx)->thread) \ - ? (obj)->slots[slot] \ - : OBJ_GET_SLOT(cx, obj, slot)) -#else -# define GC_AWARE_GET_SLOT(cx, obj, slot) \ - OBJ_GET_SLOT(cx, obj, slot) -#endif - JS_PUBLIC_API(void *) JS_GetPrivate(JSContext *cx, JSObject *obj) { diff --git a/js/src/jsobj.c b/js/src/jsobj.c index 8e7b977dda66..1c9511f10059 100644 --- a/js/src/jsobj.c +++ b/js/src/jsobj.c @@ -1778,8 +1778,15 @@ js_FinalizeObject(JSContext *cx, JSObject *obj) JS_ClearWatchPointsForObject(cx, obj); #endif - /* Finalize obj first, in case it needs map and slots. */ - OBJ_GET_CLASS(cx, obj)->finalize(cx, obj); + /* + * Finalize obj first, in case it needs map and slots. Optimized to use + * LOCKED_OBJ_GET_CLASS instead of OBJ_GET_CLASS, so we avoid "promoting" + * obj's scope from lock-free to lock-full (see jslock.c:ClaimScope) when + * we're called from the GC. Only the GC should call js_FinalizeObject, + * and no other threads run JS (and possibly racing to update obj->slots) + * while the GC is running. + */ + LOCKED_OBJ_GET_CLASS(obj)->finalize(cx, obj); /* Drop map and free slots. */ js_DropObjectMap(cx, map, obj); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index b9b020090f3f..721627a9972b 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -168,10 +168,30 @@ struct JSObject { ? (void) LOCKED_OBJ_SET_SLOT(obj, slot, value) \ : js_SetSlotThreadSafe(cx, obj, slot, value)) +/* + * If thread-safe, define an OBJ_GET_SLOT wrapper that bypasses, for a native + * object, the lock-free "fast path" test of (OBJ_SCOPE(obj)->ownercx == cx), + * to avoid needlessly switching from lock-free to lock-full scope when doing + * GC on a different context from the last one to own the scope. The caller + * in this case is probably a JSClass.mark function, e.g., fun_mark, or maybe + * a finalizer. + * + * The GC runs only when all threads except the one on which the GC is active + * are suspended at GC-safe points, so there is no hazard in directly accessing + * obj->slots[slot] from the GC's thread, once rt->gcRunning has been set. See + * jsgc.c for details. + */ +#define GC_AWARE_GET_SLOT(cx, obj, slot) \ + (OBJ_IS_NATIVE(obj) && \ + ((cx)->runtime->gcRunning && (cx)->runtime->gcThread == (cx)->thread) \ + ? (obj)->slots[slot] \ + : OBJ_GET_SLOT(cx, obj, slot)) + #else /* !JS_THREADSAFE */ #define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot) #define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_SET_SLOT(obj,slot,value) +#define GC_AWARE_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot) #endif /* !JS_THREADSAFE */