зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
d14aee7e18
Коммит
5a16cfe95c
|
@ -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 */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче