mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 453432 - Checking for MaybeGC conditions when allocating GC things.
r=igor,mrbkap a191=blocker
This commit is contained in:
parent
9491b0201f
commit
651c16ba12
@ -850,24 +850,8 @@ PrintWinCodebase(nsGlobalWindow *win)
|
||||
}
|
||||
#endif
|
||||
|
||||
// The accumulated operation weight before we call MaybeGC
|
||||
const PRUint32 MAYBE_GC_OPERATION_WEIGHT = 5000 * JS_OPERATION_WEIGHT_BASE;
|
||||
|
||||
static void
|
||||
MaybeGC(JSContext *cx)
|
||||
{
|
||||
size_t bytes = cx->runtime->gcBytes;
|
||||
size_t lastBytes = cx->runtime->gcLastBytes;
|
||||
|
||||
if ((bytes > 8192 && bytes / 16 > lastBytes)
|
||||
#ifdef DEBUG
|
||||
|| cx->runtime->gcZeal > 0
|
||||
#endif
|
||||
) {
|
||||
++sGCCount;
|
||||
JS_GC(cx);
|
||||
}
|
||||
}
|
||||
// The accumulated operation weight for DOM callback.
|
||||
const PRUint32 DOM_CALLBACK_OPERATION_WEIGHT = 5000 * JS_OPERATION_WEIGHT_BASE;
|
||||
|
||||
static already_AddRefed<nsIPrompt>
|
||||
GetPromptFromContext(nsJSContext* ctx)
|
||||
@ -900,17 +884,8 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// XXX Save the operation callback time so we can restore it after the GC,
|
||||
// because GCing can cause JS to run on our context, causing our
|
||||
// ScriptEvaluated to be called, and clearing our operation callback time.
|
||||
// See bug 302333.
|
||||
PRTime callbackTime = ctx->mOperationCallbackTime;
|
||||
|
||||
MaybeGC(cx);
|
||||
|
||||
// Now restore the callback time and count, in case they got reset.
|
||||
ctx->mOperationCallbackTime = callbackTime;
|
||||
|
||||
// Check to see if we are running OOM
|
||||
nsCOMPtr<nsIMemory> mem;
|
||||
NS_GetMemoryManager(getter_AddRefs(mem));
|
||||
@ -932,24 +907,24 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
|
||||
|
||||
if (nsContentUtils::GetBoolPref("dom.prevent_oom_dialog", PR_FALSE))
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
nsCOMPtr<nsIPrompt> prompt = GetPromptFromContext(ctx);
|
||||
|
||||
|
||||
nsXPIDLString title, msg;
|
||||
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
"LowMemoryTitle",
|
||||
title);
|
||||
|
||||
|
||||
rv |= nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
"LowMemoryMessage",
|
||||
msg);
|
||||
|
||||
|
||||
//GetStringFromName can return NS_OK and still give NULL string
|
||||
if (NS_FAILED(rv) || !title || !msg) {
|
||||
NS_ERROR("Failed to get localized strings.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
prompt->Alert(title, msg);
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -1238,7 +1213,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
||||
this);
|
||||
|
||||
::JS_SetOperationCallback(mContext, DOMOperationCallback,
|
||||
MAYBE_GC_OPERATION_WEIGHT);
|
||||
DOM_CALLBACK_OPERATION_WEIGHT);
|
||||
|
||||
static JSLocaleCallbacks localeCallbacks =
|
||||
{
|
||||
@ -1251,7 +1226,6 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
||||
::JS_SetLocaleCallbacks(mContext, &localeCallbacks);
|
||||
}
|
||||
mIsInitialized = PR_FALSE;
|
||||
mNumEvaluations = 0;
|
||||
mTerminations = nsnull;
|
||||
mScriptsEnabled = PR_TRUE;
|
||||
mOperationCallbackTime = LL_ZERO;
|
||||
@ -3294,21 +3268,7 @@ nsJSContext::ScriptEvaluated(PRBool aTerminated)
|
||||
delete start;
|
||||
}
|
||||
|
||||
mNumEvaluations++;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (mContext->runtime->gcZeal >= 2) {
|
||||
MaybeGC(mContext);
|
||||
} else
|
||||
#endif
|
||||
if (mNumEvaluations > 20) {
|
||||
mNumEvaluations = 0;
|
||||
MaybeGC(mContext);
|
||||
}
|
||||
|
||||
if (aTerminated) {
|
||||
mOperationCallbackTime = LL_ZERO;
|
||||
}
|
||||
mOperationCallbackTime = LL_ZERO;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -3392,19 +3352,29 @@ nsJSContext::CC()
|
||||
#endif
|
||||
sPreviousCCTime = PR_Now();
|
||||
sDelayedCCollectCount = 0;
|
||||
sGCCount = 0;
|
||||
sGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
|
||||
sCCSuspectChanges = 0;
|
||||
// nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
|
||||
// we do not explicitly call ::JS_GC() here.
|
||||
sCollectedObjectsCounts = nsCycleCollector_collect();
|
||||
sCCSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
#ifdef DEBUG_smaug
|
||||
printf("Collected %u objects, %u suspected objects, took %lldms\n",
|
||||
sCollectedObjectsCounts, sCCSuspectedCount,
|
||||
(PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
|
||||
printf("Collected %u objects, %u suspected objects\n",
|
||||
sCollectedObjectsCounts, sCCSuspectedCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
GetGCRunsCount()
|
||||
{
|
||||
/*
|
||||
* The result value may overflow if sGCCount is close to the uint32
|
||||
* maximum. It may cause additional invocations of the CC, which may
|
||||
* reduce performance but cannot breach security.
|
||||
*/
|
||||
return JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER) - sGCCount;
|
||||
}
|
||||
|
||||
//static
|
||||
PRBool
|
||||
nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||
@ -3413,7 +3383,7 @@ nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||
|
||||
// Don't check suspected count if CC will be called anyway.
|
||||
if (sCCSuspectChanges <= NS_MIN_SUSPECT_CHANGES ||
|
||||
sGCCount <= NS_MAX_GC_COUNT) {
|
||||
GetGCRunsCount() <= NS_MAX_GC_COUNT) {
|
||||
#ifdef DEBUG_smaug
|
||||
PRTime now = PR_Now();
|
||||
#endif
|
||||
@ -3431,7 +3401,8 @@ nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||
}
|
||||
#ifdef DEBUG_smaug
|
||||
printf("sCCSuspectChanges %u, sGCCount %u\n",
|
||||
sCCSuspectChanges, sGCCount);
|
||||
sCCSuspectChanges,
|
||||
GetGCRunsCount());
|
||||
#endif
|
||||
|
||||
// Increase the probability also if the previous call to cycle collector
|
||||
@ -3444,7 +3415,7 @@ nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||
if (!sGCTimer &&
|
||||
(sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT) &&
|
||||
((sCCSuspectChanges > NS_MIN_SUSPECT_CHANGES &&
|
||||
sGCCount > NS_MAX_GC_COUNT) ||
|
||||
GetGCRunsCount() > NS_MAX_GC_COUNT) ||
|
||||
(sCCSuspectChanges > NS_MAX_SUSPECT_CHANGES))) {
|
||||
if ((PR_Now() - sPreviousCCTime) >=
|
||||
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
|
||||
|
@ -213,19 +213,18 @@ protected:
|
||||
|
||||
// given an nsISupports object (presumably an event target or some other
|
||||
// DOM object), get (or create) the JSObject wrapping it.
|
||||
nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript,
|
||||
nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript,
|
||||
JSObject **aRet);
|
||||
|
||||
private:
|
||||
void Unlink();
|
||||
|
||||
JSContext *mContext;
|
||||
PRUint32 mNumEvaluations;
|
||||
|
||||
protected:
|
||||
struct TerminationFuncHolder;
|
||||
friend struct TerminationFuncHolder;
|
||||
|
||||
|
||||
struct TerminationFuncClosure
|
||||
{
|
||||
TerminationFuncClosure(nsScriptTerminationFunc aFunc,
|
||||
@ -240,7 +239,7 @@ protected:
|
||||
{
|
||||
delete mNext;
|
||||
}
|
||||
|
||||
|
||||
nsScriptTerminationFunc mTerminationFunc;
|
||||
nsCOMPtr<nsISupports> mTerminationFuncArg;
|
||||
TerminationFuncClosure* mNext;
|
||||
@ -273,7 +272,7 @@ protected:
|
||||
nsJSContext* mContext;
|
||||
TerminationFuncClosure* mTerminations;
|
||||
};
|
||||
|
||||
|
||||
TerminationFuncClosure* mTerminations;
|
||||
|
||||
private:
|
||||
@ -319,7 +318,7 @@ public:
|
||||
|
||||
virtual nsresult DropScriptObject(void *object);
|
||||
virtual nsresult HoldScriptObject(void *object);
|
||||
|
||||
|
||||
static void Startup();
|
||||
static void Shutdown();
|
||||
// Setup all the statics etc - safe to call multiple times after Startup()
|
||||
|
@ -186,14 +186,8 @@ my_BranchCallback(JSContext *cx, JSScript *script)
|
||||
return JS_FALSE;
|
||||
}
|
||||
#ifdef JS_THREADSAFE
|
||||
if ((gBranchCount & 0xff) == 1) {
|
||||
#endif
|
||||
if ((gBranchCount & 0x3fff) == 1)
|
||||
JS_MaybeGC(cx);
|
||||
#ifdef JS_THREADSAFE
|
||||
else
|
||||
JS_YieldRequest(cx);
|
||||
}
|
||||
if ((gBranchCount & 0xff) == 1)
|
||||
JS_YieldRequest(cx);
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -471,7 +465,7 @@ extern void js_InitJITStatsClass(JSContext *cx, JSObject *glob);
|
||||
&jitstats_class, NULL, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
case 'o':
|
||||
if (++i == argc)
|
||||
return usage();
|
||||
@ -866,24 +860,49 @@ GCParameter(JSContext *cx, uintN argc, jsval *vp)
|
||||
param = JSGC_MAX_BYTES;
|
||||
} else if (strcmp(paramName, "maxMallocBytes") == 0) {
|
||||
param = JSGC_MAX_MALLOC_BYTES;
|
||||
} else if (strcmp(paramName, "gcStackpoolLifespan") == 0) {
|
||||
param = JSGC_STACKPOOL_LIFESPAN;
|
||||
} else if (strcmp(paramName, "gcBytes") == 0) {
|
||||
param = JSGC_BYTES;
|
||||
} else if (strcmp(paramName, "gcNumber") == 0) {
|
||||
param = JSGC_NUMBER;
|
||||
} else if (strcmp(paramName, "gcTriggerFactor") == 0) {
|
||||
param = JSGC_TRIGGER_FACTOR;
|
||||
} else {
|
||||
JS_ReportError(cx,
|
||||
"the first argument argument must be either maxBytes "
|
||||
"or maxMallocBytes");
|
||||
"the first argument argument must be maxBytes, "
|
||||
"maxMallocBytes, gcStackpoolLifespan, gcBytes, "
|
||||
"gcNumber or gcTriggerFactor");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_ValueToECMAUint32(cx, argc < 2 ? JSVAL_VOID : vp[3], &value))
|
||||
if (argc == 1) {
|
||||
value = JS_GetGCParameter(cx->runtime, param);
|
||||
return JS_NewNumberValue(cx, value, &vp[0]);
|
||||
}
|
||||
|
||||
if (param == JSGC_NUMBER ||
|
||||
param == JSGC_BYTES) {
|
||||
JS_ReportError(cx, "Attempt to change read-only parameter %s",
|
||||
paramName);
|
||||
return JS_FALSE;
|
||||
if (value == 0) {
|
||||
}
|
||||
|
||||
if (!JS_ValueToECMAUint32(cx, vp[3], &value)) {
|
||||
JS_ReportError(cx,
|
||||
"the second argument must be convertable to uint32 with "
|
||||
"non-zero value");
|
||||
"the second argument must be convertable to uint32 "
|
||||
"with non-zero value");
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (param == JSGC_TRIGGER_FACTOR && value < 100) {
|
||||
JS_ReportError(cx,
|
||||
"the gcTriggerFactor value must be >= 100");
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_SetGCParameter(cx->runtime, param, value);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
@ -1451,7 +1470,7 @@ DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSScript *script;
|
||||
JSBool ok;
|
||||
uint32 oldopts;
|
||||
|
||||
|
||||
if (!argc)
|
||||
return JS_TRUE;
|
||||
|
||||
@ -1471,7 +1490,7 @@ DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
obj = JS_NewScriptObject(cx, script);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
|
||||
ok = Disassemble(cx, obj, 1, rval, rval); /* gross, but works! */
|
||||
*rval = JSVAL_VOID;
|
||||
|
@ -2593,6 +2593,31 @@ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
|
||||
case JSGC_STACKPOOL_LIFESPAN:
|
||||
rt->gcEmptyArenaPoolLifespan = value;
|
||||
break;
|
||||
default:
|
||||
JS_ASSERT(key == JSGC_TRIGGER_FACTOR);
|
||||
JS_ASSERT(value >= 100);
|
||||
rt->gcTriggerFactor = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32)
|
||||
JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
|
||||
{
|
||||
switch (key) {
|
||||
case JSGC_MAX_BYTES:
|
||||
return rt->gcMaxBytes;
|
||||
case JSGC_MAX_MALLOC_BYTES:
|
||||
return rt->gcMaxMallocBytes;
|
||||
case JSGC_STACKPOOL_LIFESPAN:
|
||||
return rt->gcEmptyArenaPoolLifespan;
|
||||
case JSGC_TRIGGER_FACTOR:
|
||||
return rt->gcTriggerFactor;
|
||||
case JSGC_BYTES:
|
||||
return rt->gcBytes;
|
||||
default:
|
||||
JS_ASSERT(key == JSGC_NUMBER);
|
||||
return rt->gcNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3807,7 +3832,7 @@ JS_HasUCProperty(JSContext *cx, JSObject *obj,
|
||||
JSProperty *prop;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
ok = LookupUCProperty(cx, obj, name, namelen,
|
||||
ok = LookupUCProperty(cx, obj, name, namelen,
|
||||
JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
|
||||
&obj2, &prop);
|
||||
if (ok) {
|
||||
|
@ -1134,12 +1134,31 @@ typedef enum JSGCParamKey {
|
||||
JSGC_MAX_MALLOC_BYTES = 1,
|
||||
|
||||
/* Hoard stackPools for this long, in ms, default is 30 seconds. */
|
||||
JSGC_STACKPOOL_LIFESPAN = 2
|
||||
JSGC_STACKPOOL_LIFESPAN = 2,
|
||||
|
||||
/*
|
||||
* The factor that defines when the GC is invoked. The factor is a
|
||||
* percent of the memory allocated by the GC after the last run of
|
||||
* the GC. When the current memory allocated by the GC is more than
|
||||
* this percent then the GC is invoked. The factor cannot be less
|
||||
* than 100 since the current memory allocated by the GC cannot be less
|
||||
* than the memory allocated after the last run of the GC.
|
||||
*/
|
||||
JSGC_TRIGGER_FACTOR = 3,
|
||||
|
||||
/* Amount of bytes allocated by the GC. */
|
||||
JSGC_BYTES = 4,
|
||||
|
||||
/* Number of times when GC was invoked. */
|
||||
JSGC_NUMBER = 5
|
||||
} JSGCParamKey;
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
|
||||
|
||||
extern JS_PUBLIC_API(uint32)
|
||||
JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key);
|
||||
|
||||
/*
|
||||
* Add a finalizer for external strings created by JS_NewExternalString (see
|
||||
* below) using a type-code returned from this function, and that understands
|
||||
|
@ -253,6 +253,7 @@ struct JSRuntime {
|
||||
uint32 gcLevel;
|
||||
uint32 gcNumber;
|
||||
JSTracer *gcMarkingTracer;
|
||||
uint32 gcTriggerFactor;
|
||||
|
||||
/*
|
||||
* NB: do not pack another flag here by claiming gcPadding unless the new
|
||||
|
@ -1253,6 +1253,18 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
rt->gcMaxBytes = rt->gcMaxMallocBytes = maxbytes;
|
||||
rt->gcEmptyArenaPoolLifespan = 30000;
|
||||
|
||||
/*
|
||||
* By default the trigger factor gets maximum possible value. This
|
||||
* means that GC will not be triggered by growth of GC memory (gcBytes).
|
||||
*/
|
||||
rt->gcTriggerFactor = (uint32) -1;
|
||||
|
||||
/*
|
||||
* The assigned value prevents GC from running when GC memory is too low
|
||||
* (during JS engine start).
|
||||
*/
|
||||
rt->gcLastBytes = 8192;
|
||||
|
||||
METER(memset(&rt->gcStats, 0, sizeof rt->gcStats));
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -1757,6 +1769,17 @@ EnsureLocalFreeList(JSContext *cx)
|
||||
|
||||
#endif
|
||||
|
||||
static JS_INLINE JSBool
|
||||
IsGCThresholdReached(JSRuntime *rt)
|
||||
{
|
||||
/*
|
||||
* Since the initial value of the gcLastBytes parameter is not equal to
|
||||
* zero (see the js_InitGC function) the return value is false when
|
||||
* the gcBytes value is close to zero at the JS engine start.
|
||||
*/
|
||||
return rt->gcBytes / rt->gcTriggerFactor >= rt->gcLastBytes / 100;
|
||||
}
|
||||
|
||||
void *
|
||||
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
||||
{
|
||||
@ -1823,7 +1846,8 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
doGC = (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke);
|
||||
doGC = (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke) ||
|
||||
IsGCThresholdReached(rt);
|
||||
#ifdef JS_GC_ZEAL
|
||||
doGC = doGC || rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke);
|
||||
#endif
|
||||
@ -2033,9 +2057,10 @@ RefillDoubleFreeList(JSContext *cx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke
|
||||
if ((rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke) ||
|
||||
IsGCThresholdReached(rt)
|
||||
#ifdef JS_GC_ZEAL
|
||||
&& (rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke))
|
||||
|| (rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke))
|
||||
#endif
|
||||
) {
|
||||
goto do_gc;
|
||||
@ -2207,7 +2232,8 @@ js_AddAsGCBytes(JSContext *cx, size_t sz)
|
||||
|
||||
rt = cx->runtime;
|
||||
if (rt->gcBytes >= rt->gcMaxBytes ||
|
||||
sz > (size_t) (rt->gcMaxBytes - rt->gcBytes)
|
||||
sz > (size_t) (rt->gcMaxBytes - rt->gcBytes) ||
|
||||
IsGCThresholdReached(rt)
|
||||
#ifdef JS_GC_ZEAL
|
||||
|| rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke)
|
||||
#endif
|
||||
|
@ -216,7 +216,7 @@ static JSDHashOperator
|
||||
DetachedWrappedNativeProtoMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
uint32 number, void *arg)
|
||||
{
|
||||
XPCWrappedNativeProto* proto =
|
||||
XPCWrappedNativeProto* proto =
|
||||
(XPCWrappedNativeProto*)((JSDHashEntryStub*)hdr)->key;
|
||||
|
||||
proto->Mark();
|
||||
@ -309,7 +309,7 @@ void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
|
||||
// them here.
|
||||
for(XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
|
||||
static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
|
||||
|
||||
|
||||
if(self->GetXPConnect()->ShouldTraceRoots())
|
||||
{
|
||||
// Only trace these if we're not cycle-collecting, the cycle collector
|
||||
@ -527,7 +527,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
case JSGC_MARK_END:
|
||||
{
|
||||
NS_ASSERTION(!self->mDoingFinalization, "bad state");
|
||||
|
||||
|
||||
// mThreadRunningGC indicates that GC is running
|
||||
{ // scoped lock
|
||||
XPCAutoLock lock(self->GetMapLock());
|
||||
@ -550,8 +550,8 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
Enumerate(WrappedJSDyingJSObjectFinder, &data);
|
||||
}
|
||||
|
||||
// Do cleanup in NativeInterfaces. This part just finds
|
||||
// member cloned function objects that are about to be
|
||||
// Do cleanup in NativeInterfaces. This part just finds
|
||||
// member cloned function objects that are about to be
|
||||
// collected. It does not deal with collection of interfaces or
|
||||
// sets at this point.
|
||||
CX_AND_XPCRT_Data data = {cx, self};
|
||||
@ -716,7 +716,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
if(threadLock)
|
||||
{
|
||||
// Do the marking...
|
||||
|
||||
|
||||
{ // scoped lock
|
||||
nsAutoLock lock(threadLock);
|
||||
|
||||
@ -735,7 +735,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
// possibly be valid.
|
||||
if(ccxp->CanGetTearOff())
|
||||
{
|
||||
XPCWrappedNativeTearOff* to =
|
||||
XPCWrappedNativeTearOff* to =
|
||||
ccxp->GetTearOff();
|
||||
if(to)
|
||||
to->Mark();
|
||||
@ -744,7 +744,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do the sweeping...
|
||||
XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs();
|
||||
}
|
||||
@ -850,7 +850,7 @@ static JSDHashOperator
|
||||
DetachedWrappedNativeProtoShutdownMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
uint32 number, void *arg)
|
||||
{
|
||||
XPCWrappedNativeProto* proto =
|
||||
XPCWrappedNativeProto* proto =
|
||||
(XPCWrappedNativeProto*)((JSDHashEntryStub*)hdr)->key;
|
||||
|
||||
proto->SystemIsBeingShutDown((JSContext*)arg);
|
||||
@ -1084,6 +1084,9 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
JS_SetContextCallback(mJSRuntime, ContextCallback);
|
||||
JS_SetGCCallbackRT(mJSRuntime, GCCallback);
|
||||
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
|
||||
|
||||
// GC will be called when gcBytes is 1600% of gcLastBytes.
|
||||
JS_SetGCParameter(mJSRuntime, JSGC_TRIGGER_FACTOR, 1600);
|
||||
}
|
||||
|
||||
if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
|
||||
|
@ -275,22 +275,22 @@ extern const char XPC_XPCONNECT_CONTRACTID[];
|
||||
|
||||
typedef PRMonitor XPCLock;
|
||||
|
||||
static inline void xpc_Wait(XPCLock* lock)
|
||||
static inline void xpc_Wait(XPCLock* lock)
|
||||
{
|
||||
NS_ASSERTION(lock, "xpc_Wait called with null lock!");
|
||||
#ifdef DEBUG
|
||||
PRStatus result =
|
||||
PRStatus result =
|
||||
#endif
|
||||
PR_Wait(lock, PR_INTERVAL_NO_TIMEOUT);
|
||||
NS_ASSERTION(PR_SUCCESS == result, "bad result from PR_Wait!");
|
||||
}
|
||||
|
||||
static inline void xpc_NotifyAll(XPCLock* lock)
|
||||
static inline void xpc_NotifyAll(XPCLock* lock)
|
||||
{
|
||||
NS_ASSERTION(lock, "xpc_NotifyAll called with null lock!");
|
||||
#ifdef DEBUG
|
||||
PRStatus result =
|
||||
#endif
|
||||
PRStatus result =
|
||||
#endif
|
||||
PR_NotifyAll(lock);
|
||||
NS_ASSERTION(PR_SUCCESS == result, "bad result from PR_NotifyAll!");
|
||||
}
|
||||
@ -510,7 +510,7 @@ public:
|
||||
NS_IMETHOD Unroot(void *p);
|
||||
NS_IMETHOD Traverse(void *p,
|
||||
nsCycleCollectionTraversalCallback &cb);
|
||||
|
||||
|
||||
// nsCycleCollectionLanguageRuntime
|
||||
virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
|
||||
virtual nsresult FinishCycleCollection();
|
||||
@ -808,26 +808,26 @@ public:
|
||||
JSContext* GetJSContext() const {return mJSContext;}
|
||||
|
||||
enum LangType {LANG_UNKNOWN, LANG_JS, LANG_NATIVE};
|
||||
|
||||
|
||||
LangType GetCallingLangType() const
|
||||
{
|
||||
return mCallingLangType;
|
||||
}
|
||||
LangType SetCallingLangType(LangType lt)
|
||||
{
|
||||
LangType tmp = mCallingLangType;
|
||||
mCallingLangType = lt;
|
||||
LangType tmp = mCallingLangType;
|
||||
mCallingLangType = lt;
|
||||
return tmp;
|
||||
}
|
||||
JSBool CallerTypeIsJavaScript() const
|
||||
JSBool CallerTypeIsJavaScript() const
|
||||
{
|
||||
return LANG_JS == mCallingLangType;
|
||||
}
|
||||
JSBool CallerTypeIsNative() const
|
||||
JSBool CallerTypeIsNative() const
|
||||
{
|
||||
return LANG_NATIVE == mCallingLangType;
|
||||
}
|
||||
JSBool CallerTypeIsKnown() const
|
||||
JSBool CallerTypeIsKnown() const
|
||||
{
|
||||
return LANG_UNKNOWN != mCallingLangType;
|
||||
}
|
||||
@ -1244,7 +1244,7 @@ public:
|
||||
{return mScriptObjectPrincipal ?
|
||||
mScriptObjectPrincipal->GetPrincipal() : nsnull;}
|
||||
#endif
|
||||
|
||||
|
||||
JSObject*
|
||||
GetPrototypeJSFunction() const {return mPrototypeJSFunction;}
|
||||
|
||||
@ -1977,7 +1977,7 @@ public:
|
||||
|
||||
// Yes, we *do* need to mark the mScriptableInfo in both cases.
|
||||
void Mark() const
|
||||
{mSet->Mark();
|
||||
{mSet->Mark();
|
||||
if(mScriptableInfo) mScriptableInfo->Mark();}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -2499,9 +2499,9 @@ public:
|
||||
JSObject* aJSObj,
|
||||
nsISimpleEnumerator** aEnumerate);
|
||||
|
||||
static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
|
||||
static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
|
||||
JSObject* aJSObj,
|
||||
jsval aName,
|
||||
jsval aName,
|
||||
nsIVariant** aResult);
|
||||
|
||||
virtual ~nsXPCWrappedJSClass();
|
||||
@ -2737,7 +2737,7 @@ public:
|
||||
* @param scope the default scope to put on the new JSObject's __parent__
|
||||
* chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
*/
|
||||
*/
|
||||
static JSBool NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
JSObject* scope, nsresult* pErr);
|
||||
@ -2771,7 +2771,7 @@ public:
|
||||
|
||||
static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
|
||||
void** dest, JSObject* src,
|
||||
const nsID* iid,
|
||||
const nsID* iid,
|
||||
nsresult* pErr);
|
||||
static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
|
||||
void** dest, JSObject* src,
|
||||
@ -2792,7 +2792,7 @@ public:
|
||||
* @param scope the default scope to put on the new JSObjects' __parent__
|
||||
* chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
*/
|
||||
*/
|
||||
static JSBool NativeArray2JS(XPCCallContext& ccx,
|
||||
jsval* d, const void** s,
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
@ -2880,7 +2880,7 @@ public:
|
||||
static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
|
||||
static void ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx);
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
static void ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
|
||||
static void ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
|
||||
nsresult rv = NS_ERROR_XPC_COM_ERROR,
|
||||
const EXCEPINFO * exception = nsnull);
|
||||
#endif
|
||||
@ -3287,7 +3287,7 @@ private:
|
||||
static XPCPerThreadData* gThreads;
|
||||
static PRUintn gTLSIndex;
|
||||
|
||||
// Cached value of cx->thread on the main thread.
|
||||
// Cached value of cx->thread on the main thread.
|
||||
static void *sMainJSThread;
|
||||
|
||||
// Cached per thread data for the main thread. Only safe to access
|
||||
@ -3595,7 +3595,7 @@ private:
|
||||
JSContext *mCX;
|
||||
jsrefcount mDepth;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************/
|
||||
|
||||
@ -3691,7 +3691,7 @@ public:
|
||||
~AutoResolveName()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
jsval old =
|
||||
jsval old =
|
||||
#endif
|
||||
mTLS->SetResolveName(mOld);
|
||||
NS_ASSERTION(old == mCheck, "Bad Nesting!");
|
||||
@ -3717,17 +3717,17 @@ public:
|
||||
}
|
||||
void AutoTrace(JSTracer* trc) {}
|
||||
private:
|
||||
XPCMarkableJSVal(); // not implemented
|
||||
XPCMarkableJSVal(); // not implemented
|
||||
jsval mVal;
|
||||
jsval* mValPtr;
|
||||
};
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
// AutoMarkingPtr is the base class for the various AutoMarking pointer types
|
||||
// below. This system allows us to temporarily protect instances of our garbage
|
||||
// collected types after they are constructed but before they are safely
|
||||
// AutoMarkingPtr is the base class for the various AutoMarking pointer types
|
||||
// below. This system allows us to temporarily protect instances of our garbage
|
||||
// collected types after they are constructed but before they are safely
|
||||
// attached to other rooted objects.
|
||||
// This base class has pure virtual support for marking.
|
||||
// This base class has pure virtual support for marking.
|
||||
|
||||
class AutoMarkingPtr
|
||||
{
|
||||
@ -3736,15 +3736,15 @@ public:
|
||||
: mNext(nsnull), mTLS(ccx.GetThreadData()) {Link();}
|
||||
|
||||
virtual ~AutoMarkingPtr() {Unlink();}
|
||||
|
||||
void Link()
|
||||
|
||||
void Link()
|
||||
{if(!mTLS) return;
|
||||
AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
|
||||
AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
|
||||
mNext = *list; *list = this;}
|
||||
|
||||
void Unlink()
|
||||
void Unlink()
|
||||
{if(!mTLS) return;
|
||||
AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
|
||||
AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
|
||||
while(*cur != this) {
|
||||
NS_ASSERTION(*cur, "This object not in list!");
|
||||
cur = &(*cur)->mNext;
|
||||
@ -3754,7 +3754,7 @@ public:
|
||||
}
|
||||
|
||||
AutoMarkingPtr* GetNext() {return mNext;}
|
||||
|
||||
|
||||
virtual void TraceJS(JSTracer* trc) = 0;
|
||||
virtual void MarkAfterJSFinalize() = 0;
|
||||
|
||||
@ -3803,7 +3803,7 @@ DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative)
|
||||
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeTearOffPtr, XPCWrappedNativeTearOff)
|
||||
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto)
|
||||
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingJSVal, XPCMarkableJSVal)
|
||||
|
||||
|
||||
#define DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(class_, type_) \
|
||||
class class_ : public AutoMarkingPtr \
|
||||
{ \
|
||||
@ -3858,9 +3858,9 @@ protected: \
|
||||
|
||||
DEFINE_AUTO_MARKING_ARRAY_PTR_TYPE(AutoMarkingNativeInterfacePtrArrayPtr,
|
||||
XPCNativeInterface)
|
||||
|
||||
|
||||
// Note: It looked like I would need one of these AutoMarkingPtr types for
|
||||
// XPCNativeScriptableInfo in order to manage marking its
|
||||
// XPCNativeScriptableInfo in order to manage marking its
|
||||
// XPCNativeScriptableShared member during construction. But AFAICT we build
|
||||
// these and bind them to rooted things so immediately that this just is not
|
||||
// needed.
|
||||
@ -3903,8 +3903,8 @@ public:
|
||||
// the case when mJSVal is JSVAL_STRING, since we don't own the data in
|
||||
// that case.
|
||||
|
||||
// We #define and iid so that out module local code can use QI to detect
|
||||
// if a given nsIVariant is in fact an XPCVariant.
|
||||
// We #define and iid so that out module local code can use QI to detect
|
||||
// if a given nsIVariant is in fact an XPCVariant.
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
|
||||
|
||||
static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
|
||||
@ -3922,8 +3922,8 @@ public:
|
||||
* chain
|
||||
* @param pErr [out] relevant error code, if any.
|
||||
* @param pJSVal [out] the resulting jsval.
|
||||
*/
|
||||
static JSBool VariantDataToJS(XPCCallContext& ccx,
|
||||
*/
|
||||
static JSBool VariantDataToJS(XPCCallContext& ccx,
|
||||
nsIVariant* variant,
|
||||
JSObject* scope, nsresult* pErr,
|
||||
jsval* pJSVal);
|
||||
|
Loading…
Reference in New Issue
Block a user