mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 718600 - remove JSRuntime::(rtLock, state). r=luke
This commit is contained in:
parent
4a57071627
commit
2942303dc8
@ -216,7 +216,7 @@ JS_GetEmptyStringValue(JSContext *cx)
|
||||
JS_PUBLIC_API(JSString *)
|
||||
JS_GetEmptyString(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt->state == JSRTS_UP);
|
||||
JS_ASSERT(rt->hasContexts());
|
||||
return rt->emptyString;
|
||||
}
|
||||
|
||||
@ -680,7 +680,6 @@ static JSBool js_NewRuntimeWasCalled = JS_FALSE;
|
||||
|
||||
JSRuntime::JSRuntime()
|
||||
: atomsCompartment(NULL),
|
||||
state(),
|
||||
cxCallback(NULL),
|
||||
compartmentCallback(NULL),
|
||||
activityCallback(NULL),
|
||||
@ -739,11 +738,6 @@ JSRuntime::JSRuntime()
|
||||
requestCount(0),
|
||||
gcThread(NULL),
|
||||
gcHelperThread(thisFromCtor()),
|
||||
rtLock(NULL),
|
||||
# ifdef DEBUG
|
||||
rtLockOwner(0),
|
||||
# endif
|
||||
stateChange(NULL),
|
||||
#endif
|
||||
debuggerMutations(0),
|
||||
securityCallbacks(NULL),
|
||||
@ -811,12 +805,6 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
/* this is asymmetric with JS_ShutDown: */
|
||||
if (!js_SetupLocks(8, 16))
|
||||
return false;
|
||||
rtLock = JS_NEW_LOCK();
|
||||
if (!rtLock)
|
||||
return false;
|
||||
stateChange = JS_NEW_CONDVAR(gcLock);
|
||||
if (!stateChange)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
debugMode = false;
|
||||
@ -859,10 +847,6 @@ JSRuntime::~JSRuntime()
|
||||
JS_DESTROY_CONDVAR(gcDone);
|
||||
if (requestDone)
|
||||
JS_DESTROY_CONDVAR(requestDone);
|
||||
if (rtLock)
|
||||
JS_DESTROY_LOCK(rtLock);
|
||||
if (stateChange)
|
||||
JS_DESTROY_CONDVAR(stateChange);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1137,18 +1121,6 @@ JS_IsInRequest(JSContext *cx)
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_Lock(JSRuntime *rt)
|
||||
{
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_Unlock(JSRuntime *rt)
|
||||
{
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSContextCallback)
|
||||
JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
|
||||
{
|
||||
@ -1927,8 +1899,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
|
||||
*resolved = JS_FALSE;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_ASSERT(rt->state != JSRTS_DOWN);
|
||||
if (rt->state == JSRTS_LANDING || !JSID_IS_ATOM(id))
|
||||
if (!rt->hasContexts() || !JSID_IS_ATOM(id))
|
||||
return JS_TRUE;
|
||||
|
||||
idstr = JSID_TO_STRING(id);
|
||||
|
@ -2449,12 +2449,6 @@ class JSAutoCheckRequest {
|
||||
JS_BEGIN_EXTERN_C
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_Lock(JSRuntime *rt);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_Unlock(JSRuntime *rt);
|
||||
|
||||
extern JS_PUBLIC_API(JSContextCallback)
|
||||
JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback);
|
||||
|
||||
|
@ -455,30 +455,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
* Here the GC lock is still held after js_InitContextThreadAndLockGC took it and
|
||||
* the GC is not running on another thread.
|
||||
*/
|
||||
bool first;
|
||||
for (;;) {
|
||||
if (rt->state == JSRTS_UP) {
|
||||
JS_ASSERT(!JS_CLIST_IS_EMPTY(&rt->contextList));
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
if (rt->state == JSRTS_DOWN) {
|
||||
JS_ASSERT(JS_CLIST_IS_EMPTY(&rt->contextList));
|
||||
first = true;
|
||||
rt->state = JSRTS_LAUNCHING;
|
||||
break;
|
||||
}
|
||||
JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT);
|
||||
|
||||
/*
|
||||
* During the above wait after we are notified about the state change
|
||||
* but before we wake up, another thread could enter the GC from
|
||||
* js_DestroyContext, bug 478336. So we must wait here to ensure that
|
||||
* when we exit the loop with the first flag set to true, that GC is
|
||||
* finished.
|
||||
*/
|
||||
js_WaitForGC(rt);
|
||||
}
|
||||
bool first = JS_CLIST_IS_EMPTY(&rt->contextList);
|
||||
JS_APPEND_LINK(&cx->link, &rt->contextList);
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
@ -507,10 +484,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
js_DestroyContext(cx, JSDCM_NEW_FAILED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
rt->state = JSRTS_UP;
|
||||
JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
|
||||
}
|
||||
|
||||
JSContextCallback cxCallback = rt->cxCallback;
|
||||
@ -529,7 +502,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
JSContextCallback cxCallback;
|
||||
JSBool last;
|
||||
|
||||
JS_ASSERT(!cx->enumerators);
|
||||
|
||||
@ -565,7 +537,6 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
}
|
||||
|
||||
JS_LOCK_GC(rt);
|
||||
JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* Typically we are called outside a request, so ensure that the GC is not
|
||||
@ -575,9 +546,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
js_WaitForGC(rt);
|
||||
#endif
|
||||
JS_REMOVE_LINK(&cx->link);
|
||||
last = (rt->contextList.next == &rt->contextList);
|
||||
if (last)
|
||||
rt->state = JSRTS_LANDING;
|
||||
bool last = !rt->hasContexts();
|
||||
if (last || mode == JSDCM_FORCE_GC || mode == JSDCM_MAYBE_GC
|
||||
#ifdef JS_THREADSAFE
|
||||
|| cx->outstandingRequests != 0
|
||||
@ -595,12 +564,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
/*
|
||||
* If this thread is not in a request already, begin one now so
|
||||
* that we wait for any racing GC started on a not-last context to
|
||||
* finish, before we plow ahead and unpin atoms. Note that even
|
||||
* though we begin a request here if necessary, we end all
|
||||
* thread's requests before forcing a final GC. This lets any
|
||||
* not-last context destruction racing in another thread try to
|
||||
* force or maybe run the GC, but by that point, rt->state will
|
||||
* not be JSRTS_UP, and that GC attempt will return early.
|
||||
* finish, before we plow ahead and unpin atoms.
|
||||
*/
|
||||
if (cx->thread()->data.requestDepth == 0)
|
||||
JS_BeginRequest(cx);
|
||||
@ -626,24 +590,16 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* Destroying a context implicitly calls JS_EndRequest(). Also, we must
|
||||
* end our request here in case we are "last" -- in that event, another
|
||||
* js_DestroyContext that was not last might be waiting in the GC for our
|
||||
* request to end. We'll let it run below, just before we do the truly
|
||||
* final GC and then free atom state.
|
||||
*/
|
||||
/* Destroying a context implicitly calls JS_EndRequest(). */
|
||||
while (cx->outstandingRequests != 0)
|
||||
JS_EndRequest(cx);
|
||||
#endif
|
||||
|
||||
if (last) {
|
||||
js_GC(cx, NULL, GC_LAST_CONTEXT, gcstats::LASTCONTEXT);
|
||||
js_GC(cx, NULL, GC_NORMAL, gcstats::LASTCONTEXT);
|
||||
|
||||
/* Take the runtime down, now that it has no contexts or atoms. */
|
||||
JS_LOCK_GC(rt);
|
||||
rt->state = JSRTS_DOWN;
|
||||
JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
|
||||
} else {
|
||||
if (mode == JSDCM_FORCE_GC)
|
||||
js_GC(cx, NULL, GC_NORMAL, gcstats::DESTROYCONTEXT);
|
||||
|
@ -325,13 +325,6 @@ typedef enum JSDestroyContextMode {
|
||||
JSDCM_NEW_FAILED
|
||||
} JSDestroyContextMode;
|
||||
|
||||
typedef enum JSRuntimeState {
|
||||
JSRTS_DOWN,
|
||||
JSRTS_LAUNCHING,
|
||||
JSRTS_UP,
|
||||
JSRTS_LANDING
|
||||
} JSRuntimeState;
|
||||
|
||||
typedef struct JSPropertyTreeEntry {
|
||||
JSDHashEntryHdr hdr;
|
||||
js::Shape *child;
|
||||
@ -351,9 +344,6 @@ struct JSRuntime
|
||||
/* List of compartments (protected by the GC lock). */
|
||||
js::CompartmentVector compartments;
|
||||
|
||||
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
|
||||
JSRuntimeState state;
|
||||
|
||||
/* See comment for JS_AbortIfWrongThread in jsapi.h. */
|
||||
#ifdef JS_THREADSAFE
|
||||
public:
|
||||
@ -532,6 +522,10 @@ struct JSRuntime
|
||||
/* List of active contexts sharing this runtime; protected by gcLock. */
|
||||
JSCList contextList;
|
||||
|
||||
bool hasContexts() const {
|
||||
return !JS_CLIST_IS_EMPTY(&contextList);
|
||||
}
|
||||
|
||||
/* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
|
||||
JSDebugHooks globalDebugHooks;
|
||||
|
||||
@ -563,15 +557,6 @@ struct JSRuntime
|
||||
|
||||
js::GCHelperThread gcHelperThread;
|
||||
|
||||
/* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
|
||||
PRLock *rtLock;
|
||||
#ifdef DEBUG
|
||||
void * rtLockOwner;
|
||||
#endif
|
||||
|
||||
/* Used to synchronize down/up state change; protected by gcLock. */
|
||||
PRCondVar *stateChange;
|
||||
|
||||
/*
|
||||
* Mapping from NSPR thread identifiers to JSThreads.
|
||||
*
|
||||
|
@ -60,7 +60,7 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
|
||||
JS_FRIEND_API(JSString *)
|
||||
JS_GetAnonymousString(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt->state == JSRTS_UP);
|
||||
JS_ASSERT(rt->hasContexts());
|
||||
return rt->atomState.anonymousAtom;
|
||||
}
|
||||
|
||||
|
@ -2103,7 +2103,7 @@ MarkRuntime(JSTracer *trc)
|
||||
{
|
||||
JSRuntime *rt = trc->runtime;
|
||||
|
||||
if (rt->state != JSRTS_LANDING)
|
||||
if (rt->hasContexts())
|
||||
MarkConservativeStackRoots(trc);
|
||||
|
||||
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront())
|
||||
@ -2659,7 +2659,7 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
|
||||
JSCompartment *compartment = *read++;
|
||||
|
||||
if (!compartment->hold &&
|
||||
(compartment->arenas.arenaListsAreEmpty() || gckind == GC_LAST_CONTEXT))
|
||||
(compartment->arenas.arenaListsAreEmpty() || !rt->hasContexts()))
|
||||
{
|
||||
compartment->arenas.checkEmptyFreeLists();
|
||||
if (callback)
|
||||
@ -3050,7 +3050,6 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
JS_ASSERT_IF(comp, gckind != GC_LAST_CONTEXT);
|
||||
JS_ASSERT_IF(comp, comp != rt->atomsCompartment);
|
||||
JS_ASSERT_IF(comp, rt->gcMode == JSGC_MODE_COMPARTMENT);
|
||||
|
||||
@ -3077,10 +3076,8 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
||||
* is either the current thread or waits for the GC to complete on this
|
||||
* thread.
|
||||
*/
|
||||
if (rt->inOOMReport) {
|
||||
JS_ASSERT(gckind != GC_LAST_CONTEXT);
|
||||
if (rt->inOOMReport)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We should not be depending on cx->compartment in the GC, so set it to
|
||||
@ -3102,10 +3099,8 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
||||
*/
|
||||
JS_ASSERT(!cx->gcBackgroundFree);
|
||||
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
|
||||
if (rt->gcHelperThread.prepareForBackgroundSweep())
|
||||
cx->gcBackgroundFree = &rt->gcHelperThread;
|
||||
}
|
||||
if (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep())
|
||||
cx->gcBackgroundFree = &rt->gcHelperThread;
|
||||
#endif
|
||||
|
||||
MarkAndSweep(cx, gckind);
|
||||
@ -3135,15 +3130,6 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Re
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
/*
|
||||
* Don't collect garbage if the runtime isn't up, and cx is not the last
|
||||
* context in the runtime. The last context must force a GC, and nothing
|
||||
* should suppress that final collection or there may be shutdown leaks,
|
||||
* or runtime bloat until the next context is created.
|
||||
*/
|
||||
if (rt->state != JSRTS_UP && gckind != GC_LAST_CONTEXT)
|
||||
return;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
struct AutoVerifyBarriers {
|
||||
JSContext *cx;
|
||||
@ -3167,7 +3153,7 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Re
|
||||
* on another thread.
|
||||
*/
|
||||
if (JSGCCallback callback = rt->gcCallback) {
|
||||
if (!callback(cx, JSGC_BEGIN) && gckind != GC_LAST_CONTEXT)
|
||||
if (!callback(cx, JSGC_BEGIN) && rt->hasContexts())
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3186,7 +3172,7 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Re
|
||||
* On shutdown, iterate until finalizers or the JSGC_END callback
|
||||
* stop creating garbage.
|
||||
*/
|
||||
} while (gckind == GC_LAST_CONTEXT && rt->gcPoke);
|
||||
} while (!rt->hasContexts() && rt->gcPoke);
|
||||
|
||||
rt->gcNextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN;
|
||||
|
||||
|
@ -1408,14 +1408,8 @@ typedef enum JSGCInvocationKind {
|
||||
/* Normal invocation. */
|
||||
GC_NORMAL = 0,
|
||||
|
||||
/*
|
||||
* Called from js_DestroyContext for last JSContext in a JSRuntime, when
|
||||
* it is imperative that rt->gcPoke gets cleared early in js_GC.
|
||||
*/
|
||||
GC_LAST_CONTEXT = 1,
|
||||
|
||||
/* Minimize GC triggers and release empty GC chunks right away. */
|
||||
GC_SHRINK = 2
|
||||
GC_SHRINK = 1
|
||||
} JSGCInvocationKind;
|
||||
|
||||
/* Pass NULL for |comp| to get a full GC. */
|
||||
|
@ -740,30 +740,4 @@ js_Unlock(JSContext *cx, JSThinLock *tl)
|
||||
ThinUnlock(tl, CX_THINLOCK_ID(cx));
|
||||
}
|
||||
|
||||
void
|
||||
js_LockRuntime(JSRuntime *rt)
|
||||
{
|
||||
PR_Lock(rt->rtLock);
|
||||
#ifdef DEBUG
|
||||
rt->rtLockOwner = js_CurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js_UnlockRuntime(JSRuntime *rt)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
rt->rtLockOwner = NULL;
|
||||
#endif
|
||||
PR_Unlock(rt->rtLock);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool
|
||||
js_IsRuntimeLocked(JSRuntime *rt)
|
||||
{
|
||||
return js_CurrentThreadId() == rt->rtLockOwner;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
@ -113,30 +113,13 @@ typedef PRLock JSLock;
|
||||
#define JS_LOCK(cx, tl) js_Lock(cx, tl)
|
||||
#define JS_UNLOCK(cx, tl) js_Unlock(cx, tl)
|
||||
|
||||
#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt)
|
||||
#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt)
|
||||
|
||||
extern void js_Lock(JSContext *cx, JSThinLock *tl);
|
||||
extern void js_Unlock(JSContext *cx, JSThinLock *tl);
|
||||
extern void js_LockRuntime(JSRuntime *rt);
|
||||
extern void js_UnlockRuntime(JSRuntime *rt);
|
||||
extern int js_SetupLocks(int,int);
|
||||
extern void js_CleanupLocks();
|
||||
extern void js_InitLock(JSThinLock *);
|
||||
extern void js_FinishLock(JSThinLock *);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt)
|
||||
|
||||
extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
|
||||
|
||||
#else
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) 0
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
#define JS_ATOMIC_INCREMENT(p) (++*(p))
|
||||
@ -158,11 +141,6 @@ extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
|
||||
#define JS_NOTIFY_CONDVAR(cv) ((void)0)
|
||||
#define JS_NOTIFY_ALL_CONDVAR(cv) ((void)0)
|
||||
|
||||
#define JS_LOCK_RUNTIME(rt) ((void)0)
|
||||
#define JS_UNLOCK_RUNTIME(rt) ((void)0)
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) 1
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
#define JS_LOCK_GC(rt) JS_ACQUIRE_LOCK((rt)->gcLock)
|
||||
|
Loading…
Reference in New Issue
Block a user