Avoid ClaimScope (lock-free to -full transition) in JS_GetClass and js_FinalizeObject called from the GC (109183, r=shaver, sr=jband).

This commit is contained in:
brendan%mozilla.org 2001-11-11 21:25:13 +00:00
Родитель 88158430a4
Коммит 8b9fb46499
3 изменённых файлов: 31 добавлений и 26 удалений

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

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

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

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

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

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