зеркало из https://github.com/mozilla/pjs.git
Bug 366975: Allow to allocate new GC things from JSGC_END callback. r=brendan
This commit is contained in:
Родитель
e835c91ea5
Коммит
7138d86b57
|
@ -1773,12 +1773,7 @@ JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
|
|||
JS_PUBLIC_API(void)
|
||||
JS_ClearNewbornRoots(JSContext *cx)
|
||||
{
|
||||
uintN i;
|
||||
|
||||
for (i = 0; i < GCX_NTYPES; i++)
|
||||
cx->newborn[i] = NULL;
|
||||
cx->lastAtom = NULL;
|
||||
cx->lastInternalResult = JSVAL_NULL;
|
||||
JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -2561,7 +2556,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
|
|||
return NULL;
|
||||
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
|
||||
0, 0)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return nobj;
|
||||
|
@ -3409,7 +3404,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
|
|||
return iterobj;
|
||||
|
||||
bad:
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -3870,7 +3865,7 @@ JS_CompileUCScript(JSContext *cx, JSObject *obj,
|
|||
#define LAST_FRAME_CHECKS(cx,result) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!(cx)->fp) { \
|
||||
(cx)->lastInternalResult = JSVAL_NULL; \
|
||||
(cx)->weakRoots.lastInternalResult = JSVAL_NULL; \
|
||||
LAST_FRAME_EXCEPTION_CHECK(cx, result); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
|
|
@ -1995,7 +1995,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
|
|||
if (!obj)
|
||||
return NULL;
|
||||
if (!InitArrayObject(cx, obj, length, vector)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return obj;
|
||||
|
|
|
@ -529,7 +529,7 @@ js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags)
|
|||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
cx->lastAtom = atom;
|
||||
cx->weakRoots.lastAtom = atom;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
|
@ -620,7 +620,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
|
|||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
cx->lastAtom = atom;
|
||||
cx->weakRoots.lastAtom = atom;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
|
@ -691,7 +691,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED | ATOM_HIDDEN);
|
||||
cx->lastAtom = atom;
|
||||
cx->weakRoots.lastAtom = atom;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
|
|
|
@ -646,8 +646,8 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
|||
|
||||
/*
|
||||
* Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push
|
||||
* it on the caller's scope, or store it in cx->lastInternalResult if we
|
||||
* are leaving the outermost scope. We don't need to allocate a new lrc
|
||||
* it on the caller's scope, or store it in lastInternalResult if we are
|
||||
* leaving the outermost scope. We don't need to allocate a new lrc
|
||||
* because we can overwrite the old mark's slot with rval.
|
||||
*/
|
||||
lrc = lrs->topChunk;
|
||||
|
@ -655,7 +655,7 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
|||
lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]);
|
||||
if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) {
|
||||
if (mark == 0) {
|
||||
cx->lastInternalResult = rval;
|
||||
cx->weakRoots.lastInternalResult = rval;
|
||||
} else {
|
||||
/*
|
||||
* Increment m to avoid the "else if (m == 0)" case below. If
|
||||
|
|
|
@ -524,6 +524,7 @@ typedef union JSTempValueUnion {
|
|||
void *gcthing;
|
||||
JSTempValueMarker marker;
|
||||
JSScopeProperty *sprop;
|
||||
JSWeakRoots *weakRoots;
|
||||
jsval *array;
|
||||
} JSTempValueUnion;
|
||||
|
||||
|
@ -540,6 +541,7 @@ JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(JSObject *));
|
|||
* If count is -1, then u.value contains the single value or GC-thing to root.
|
||||
* If count is -2, then u.marker holds a mark hook called to mark the values.
|
||||
* If count is -3, then u.sprop points to the property tree node to mark.
|
||||
* If count is -4, then u.weakRoots points to saved weak roots.
|
||||
* If count >= 0, then u.array points to a stack-allocated vector of jsvals.
|
||||
*
|
||||
* To root a single GC-thing pointer, which need not be tagged and stored as a
|
||||
|
@ -569,9 +571,10 @@ struct JSTempValueRooter {
|
|||
JSTempValueUnion u;
|
||||
};
|
||||
|
||||
#define JSTVU_SINGLE (-1)
|
||||
#define JSTVU_MARKER (-2)
|
||||
#define JSTVU_SPROP (-3)
|
||||
#define JSTVU_SINGLE (-1)
|
||||
#define JSTVU_MARKER (-2)
|
||||
#define JSTVU_SPROP (-3)
|
||||
#define JSTVU_WEAK_ROOTS (-4)
|
||||
|
||||
#define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \
|
||||
JS_BEGIN_MACRO \
|
||||
|
@ -645,6 +648,13 @@ struct JSTempValueRooter {
|
|||
JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_PUSH_TEMP_ROOT_WEAK_COPY(cx,weakRoots_,tvr) \
|
||||
JS_BEGIN_MACRO \
|
||||
(tvr)->count = JSTVU_WEAK_ROOTS; \
|
||||
(tvr)->u.weakRoots = (weakRoots_); \
|
||||
JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \
|
||||
JS_END_MACRO
|
||||
|
||||
struct JSContext {
|
||||
/* JSRuntime contextList linkage. */
|
||||
JSCList links;
|
||||
|
@ -668,14 +678,8 @@ struct JSContext {
|
|||
/* Top-level object and pointer to top stack frame's scope chain. */
|
||||
JSObject *globalObject;
|
||||
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
JSGCThing *newborn[GCX_NTYPES];
|
||||
|
||||
/* Atom root for the last-looked-up atom on this context. */
|
||||
JSAtom *lastAtom;
|
||||
|
||||
/* Root for the result of the most recent js_InternalInvoke call. */
|
||||
jsval lastInternalResult;
|
||||
/* Storage to root recently allocated GC things and script result. */
|
||||
JSWeakRoots weakRoots;
|
||||
|
||||
/* Regular expression class statics (XXX not shared globally). */
|
||||
JSRegExpStatics regExpStatics;
|
||||
|
|
|
@ -256,7 +256,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
|
|||
/* Link the new object to fp so it can get actual argument values. */
|
||||
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
|
||||
if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -605,7 +605,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
|
|||
/* Create the call object and link it to its stack frame. */
|
||||
callobj = js_NewObject(cx, &js_CallClass, NULL, parent);
|
||||
if (!callobj || !JS_SetPrivate(cx, callobj, fp)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
fp->callobj = callobj;
|
||||
|
@ -1129,7 +1129,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
* root until then to protect pval in case it is figuratively
|
||||
* up in the air, with no strong refs protecting it.
|
||||
*/
|
||||
cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(pval);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(pval);
|
||||
parentProto = JSVAL_TO_OBJECT(pval);
|
||||
}
|
||||
}
|
||||
|
@ -1160,7 +1160,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
*/
|
||||
if (!js_SetClassPrototype(cx, obj, proto,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return JS_FALSE;
|
||||
}
|
||||
*objp = obj;
|
||||
|
@ -2101,7 +2101,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
|||
return proto;
|
||||
|
||||
bad:
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2144,7 +2144,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
|
||||
/*
|
||||
* Allocate fun after allocating funobj so slot allocation in js_NewObject
|
||||
* does not wipe out fun from cx->newborn[GCX_PRIVATE].
|
||||
* does not wipe out fun from newborn[GCX_PRIVATE].
|
||||
*/
|
||||
fun = (JSFunction *) js_NewGCThing(cx, GCX_PRIVATE, sizeof(JSFunction));
|
||||
if (!fun)
|
||||
|
@ -2162,7 +2162,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
|
||||
/* Link fun to funobj and vice versa. */
|
||||
if (!js_LinkFunctionObject(cx, fun, funobj)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
fun = NULL;
|
||||
}
|
||||
|
||||
|
@ -2183,7 +2183,7 @@ js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
|||
return NULL;
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, funobj);
|
||||
if (!js_LinkFunctionObject(cx, fun, newfunobj)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return newfunobj;
|
||||
|
|
|
@ -1453,12 +1453,13 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
|||
/*
|
||||
* Refill the local free list by taking several things from the
|
||||
* global free list unless we are still at rt->gcMaxMallocBytes
|
||||
* barrier. The latter happens when GC is canceled due to
|
||||
* !gcCallback(cx, JSGC_BEGIN) or no gcPoke.
|
||||
* barrier or the free list is already populated. The former
|
||||
* happens when GC is canceled due to !gcCallback(cx, JSGC_BEGIN)
|
||||
* or no gcPoke. The latter is caused via allocating new things
|
||||
* in gcCallback(cx, JSGC_END).
|
||||
*/
|
||||
if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
|
||||
if (rt->gcMallocBytes >= rt->gcMaxMallocBytes || flbase[flindex])
|
||||
break;
|
||||
JS_ASSERT(!flbase[flindex]);
|
||||
tmpthing = arenaList->freeList;
|
||||
if (tmpthing) {
|
||||
maxFreeThings = MAX_THREAD_LOCAL_THINGS;
|
||||
|
@ -1502,9 +1503,8 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
|||
* arena. Prefer to order free things by ascending address in the
|
||||
* (unscientific) hope of better cache locality.
|
||||
*/
|
||||
if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
|
||||
if (rt->gcMallocBytes >= rt->gcMaxMallocBytes || flbase[flindex])
|
||||
break;
|
||||
JS_ASSERT(!flbase[flindex]);
|
||||
METER(nfree = 0);
|
||||
lastptr = &flbase[flindex];
|
||||
maxFreeThings = MAX_THREAD_LOCAL_THINGS;
|
||||
|
@ -1547,8 +1547,8 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
|||
lrs = cx->localRootStack;
|
||||
if (lrs) {
|
||||
/*
|
||||
* If we're in a local root scope, don't set cx->newborn[type] at all,
|
||||
* to avoid entraining garbage from it for an unbounded amount of time
|
||||
* If we're in a local root scope, don't set newborn[type] at all, to
|
||||
* avoid entraining garbage from it for an unbounded amount of time
|
||||
* on this context. A caller will leave the local root scope and pop
|
||||
* this reference, allowing thing to be GC'd if it has no other refs.
|
||||
* See JS_EnterLocalRootScope and related APIs.
|
||||
|
@ -1568,7 +1568,7 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
|||
* No local root scope, so we're stuck with the old, fragile model of
|
||||
* depending on a pigeon-hole newborn per type per context.
|
||||
*/
|
||||
cx->newborn[flags & GCF_TYPEMASK] = thing;
|
||||
cx->weakRoots.newborn[flags & GCF_TYPEMASK] = thing;
|
||||
}
|
||||
|
||||
/* We can't fail now, so update flags. */
|
||||
|
@ -1576,7 +1576,7 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
|
|||
|
||||
/*
|
||||
* Clear thing before unlocking in case a GC run is about to scan it,
|
||||
* finding it via cx->newborn[].
|
||||
* finding it via newborn[].
|
||||
*/
|
||||
thing->next = NULL;
|
||||
thing->flagp = NULL;
|
||||
|
@ -2659,10 +2659,24 @@ js_MarkStackFrame(JSContext *cx, JSStackFrame *fp)
|
|||
GC_MARK(cx, fp->xmlNamespace, "xmlNamespace");
|
||||
}
|
||||
|
||||
static void
|
||||
MarkWeakRoots(JSContext *cx, JSWeakRoots *wr)
|
||||
{
|
||||
uintN i;
|
||||
void *thing;
|
||||
|
||||
for (i = 0; i < GCX_NTYPES; i++)
|
||||
GC_MARK(cx, wr->newborn[i], gc_typenames[i]);
|
||||
if (wr->lastAtom)
|
||||
GC_MARK_ATOM(cx, wr->lastAtom);
|
||||
if (JSVAL_IS_GCTHING(wr->lastInternalResult)) {
|
||||
thing = JSVAL_TO_GCTHING(wr->lastInternalResult);
|
||||
if (thing)
|
||||
GC_MARK(cx, thing, "lastInternalResult");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return false when the branch callback wants to stop exeution ASAP and true
|
||||
* otherwise.
|
||||
*
|
||||
* When gckind is GC_LAST_DITCH, it indicates a call from js_NewGCThing with
|
||||
* rt->gcLock already held and when the lock should be kept on return.
|
||||
*/
|
||||
|
@ -2697,13 +2711,10 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
|
|||
#endif
|
||||
|
||||
if (gckind == GC_LAST_DITCH) {
|
||||
/* The last ditch GC preserves all atoms and cx->newborn. */
|
||||
/* The last ditch GC preserves all atoms and weak roots. */
|
||||
keepAtoms = JS_TRUE;
|
||||
} else {
|
||||
for (i = 0; i < GCX_NTYPES; i++)
|
||||
cx->newborn[i] = NULL;
|
||||
cx->lastInternalResult = JSVAL_NULL;
|
||||
cx->lastAtom = NULL;
|
||||
JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
|
||||
rt->gcPoke = JS_TRUE;
|
||||
|
||||
/* Keep atoms when a suspended compile is running on another context. */
|
||||
|
@ -2928,15 +2939,7 @@ restart:
|
|||
|
||||
/* Mark other roots-by-definition in acx. */
|
||||
GC_MARK(cx, acx->globalObject, "global object");
|
||||
for (i = 0; i < GCX_NTYPES; i++)
|
||||
GC_MARK(cx, acx->newborn[i], gc_typenames[i]);
|
||||
if (acx->lastAtom)
|
||||
GC_MARK_ATOM(cx, acx->lastAtom);
|
||||
if (JSVAL_IS_GCTHING(acx->lastInternalResult)) {
|
||||
thing = JSVAL_TO_GCTHING(acx->lastInternalResult);
|
||||
if (thing)
|
||||
GC_MARK(cx, thing, "lastInternalResult");
|
||||
}
|
||||
MarkWeakRoots(cx, &acx->weakRoots);
|
||||
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception");
|
||||
#if JS_HAS_LVALUE_RETURN
|
||||
|
@ -2967,6 +2970,9 @@ restart:
|
|||
case JSTVU_SPROP:
|
||||
MARK_SCOPE_PROPERTY(cx, tvr->u.sprop);
|
||||
break;
|
||||
case JSTVU_WEAK_ROOTS:
|
||||
MarkWeakRoots(cx, tvr->u.weakRoots);
|
||||
break;
|
||||
default:
|
||||
JS_ASSERT(tvr->count >= 0);
|
||||
GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array");
|
||||
|
@ -3191,20 +3197,36 @@ restart:
|
|||
JS_UNLOCK_GC(rt);
|
||||
#endif
|
||||
|
||||
/* Execute JSGC_END callback outside the lock. */
|
||||
if (rt->gcCallback) {
|
||||
/* Execute JSGC_END callback outside the lock. */
|
||||
if (gckind == GC_LAST_DITCH)
|
||||
JSWeakRoots savedWeakRoots;
|
||||
JSTempValueRooter tvr;
|
||||
|
||||
if (gckind == GC_LAST_DITCH) {
|
||||
/*
|
||||
* We allow JSGC_END implementation to force a full GC or allocate
|
||||
* new GC things. Thus we must protect the weak roots from GC or
|
||||
* overwrites.
|
||||
*/
|
||||
savedWeakRoots = cx->weakRoots;
|
||||
JS_PUSH_TEMP_ROOT_WEAK_COPY(cx, &savedWeakRoots, &tvr);
|
||||
JS_KEEP_ATOMS(rt);
|
||||
JS_UNLOCK_GC(rt);
|
||||
}
|
||||
|
||||
(void) rt->gcCallback(cx, JSGC_END);
|
||||
|
||||
/*
|
||||
* On shutdown iterate until JSGC_END callback stops creating garbage.
|
||||
*/
|
||||
if (gckind == GC_LAST_CONTEXT && rt->gcPoke)
|
||||
goto restart_after_callback;
|
||||
|
||||
if (gckind == GC_LAST_DITCH)
|
||||
if (gckind == GC_LAST_DITCH) {
|
||||
JS_LOCK_GC(rt);
|
||||
JS_UNKEEP_ATOMS(rt);
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
} else if (gckind == GC_LAST_CONTEXT && rt->gcPoke) {
|
||||
/*
|
||||
* On shutdown iterate until JSGC_END callback stops creating
|
||||
* garbage.
|
||||
*/
|
||||
goto restart_after_callback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsdhash.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -340,6 +341,20 @@ struct JSGCArenaList {
|
|||
#endif
|
||||
};
|
||||
|
||||
typedef struct JSWeakRoots {
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
JSGCThing *newborn[GCX_NTYPES];
|
||||
|
||||
/* Atom root for the last-looked-up atom on this context. */
|
||||
JSAtom *lastAtom;
|
||||
|
||||
/* Root for the result of the most recent js_InternalInvoke call. */
|
||||
jsval lastInternalResult;
|
||||
} JSWeakRoots;
|
||||
|
||||
JS_STATIC_ASSERT(JSVAL_NULL == 0);
|
||||
#define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
|
||||
|
||||
#ifdef DEBUG_notme
|
||||
#define TOO_MUCH_GC 1
|
||||
#endif
|
||||
|
|
|
@ -1445,7 +1445,7 @@ js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
|
|||
|
||||
/*
|
||||
* Store *rval in the a scoped local root if a scope is open, else in
|
||||
* the cx->lastInternalResult pigeon-hole GC root, solely so users of
|
||||
* the lastInternalResult pigeon-hole GC root, solely so users of
|
||||
* js_InternalInvoke and its direct and indirect (js_ValueToString for
|
||||
* example) callers do not need to manage roots for local, temporary
|
||||
* references to such results.
|
||||
|
@ -1456,7 +1456,7 @@ js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
|
|||
if (js_PushLocalRoot(cx, cx->localRootStack, *rval) < 0)
|
||||
ok = JS_FALSE;
|
||||
} else {
|
||||
cx->lastInternalResult = *rval;
|
||||
cx->weakRoots.lastInternalResult = *rval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1919,7 +1919,7 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
|
|||
/* Now we have an object with a constructor method; call it. */
|
||||
vp[1] = OBJECT_TO_JSVAL(obj);
|
||||
if (!js_Invoke(cx, argc, JSINVOKE_CONSTRUCT)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -5028,7 +5028,7 @@ interrupt:
|
|||
/* Restore fp->scopeChain now that obj is defined in parent. */
|
||||
fp->scopeChain = obj2;
|
||||
if (!ok) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -5110,7 +5110,7 @@ interrupt:
|
|||
/* Restore fp->scopeChain now that obj is defined in fp->varobj. */
|
||||
fp->scopeChain = obj2;
|
||||
if (!ok) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -5247,7 +5247,7 @@ interrupt:
|
|||
JS_ASSERT(sp - fp->spbase >= 1);
|
||||
lval = FETCH_OPND(-1);
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(lval));
|
||||
cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
|
||||
END_CASE(JSOP_ENDINIT)
|
||||
|
||||
BEGIN_CASE(JSOP_INITPROP)
|
||||
|
|
|
@ -809,7 +809,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
|
|||
return obj;
|
||||
|
||||
bad:
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -693,7 +693,7 @@ js_NumberToObject(JSContext *cx, jsdouble d)
|
|||
if (!obj)
|
||||
return NULL;
|
||||
if (!js_NewNumberValue(cx, d, &v)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v);
|
||||
|
|
|
@ -2507,7 +2507,7 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
|
|||
|
||||
out:
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
cx->newborn[GCX_OBJECT] = (JSGCThing *) obj;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = (JSGCThing *) obj;
|
||||
return obj;
|
||||
|
||||
bad:
|
||||
|
@ -2734,7 +2734,7 @@ out:
|
|||
return obj;
|
||||
|
||||
bad:
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
obj = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4443,7 +4443,7 @@ js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
|
|||
* instance that delegates to this object, or just query the
|
||||
* prototype for its class.
|
||||
*/
|
||||
cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v);
|
||||
}
|
||||
}
|
||||
*protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL;
|
||||
|
|
|
@ -3345,15 +3345,15 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
|
|||
JS_PropertyStub, JS_PropertyStub, \
|
||||
JSPROP_ENUMERATE, NULL); \
|
||||
if (!ok) { \
|
||||
cx->newborn[GCX_OBJECT] = NULL; \
|
||||
cx->newborn[GCX_STRING] = NULL; \
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL; \
|
||||
cx->weakRoots.newborn[GCX_STRING] = NULL; \
|
||||
goto out; \
|
||||
} \
|
||||
}
|
||||
|
||||
matchstr = js_NewStringCopyN(cx, cp, matchlen, 0);
|
||||
if (!matchstr) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -3390,8 +3390,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
|
|||
res->moreLength * sizeof(JSSubString));
|
||||
}
|
||||
if (!morepar) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->newborn[GCX_STRING] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_STRING] = NULL;
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -3414,8 +3414,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
|
|||
parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index,
|
||||
parsub->length, 0);
|
||||
if (!parstr) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->newborn[GCX_STRING] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_STRING] = NULL;
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -3424,8 +3424,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
|
|||
JSPROP_ENUMERATE, NULL);
|
||||
}
|
||||
if (!ok) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->newborn[GCX_STRING] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_STRING] = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -4166,7 +4166,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
|
|||
return NULL;
|
||||
re = JS_GetPrivate(cx, obj);
|
||||
if (!JS_SetPrivate(cx, clone, re) || !js_SetLastIndex(cx, clone, 0)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
HOLD_REGEXP(cx, re);
|
||||
|
|
|
@ -337,7 +337,7 @@ js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns)
|
|||
}
|
||||
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, ns)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
ns->object = obj;
|
||||
|
@ -606,7 +606,7 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
|
|||
}
|
||||
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
qn->object = obj;
|
||||
|
@ -631,7 +631,7 @@ js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
|
|||
|
||||
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -5455,8 +5455,8 @@ xml_getMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
* value of roots[FUNCTION] since getMethod callers have a bad habit
|
||||
* of passing a pointer to unrooted local value as vp.
|
||||
*/
|
||||
cx->newborn[GCX_OBJECT] = (JSGCThing *)obj;
|
||||
cx->lastInternalResult = roots[FUN_ROOT];
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = (JSGCThing *)obj;
|
||||
cx->weakRoots.lastInternalResult = roots[FUN_ROOT];
|
||||
}
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
return obj;
|
||||
|
@ -7650,7 +7650,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
|
|||
|
||||
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, xml)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
METER(xml_stats.xmlobj);
|
||||
|
@ -8079,7 +8079,7 @@ js_GetAnyName(JSContext *cx, jsval *vp)
|
|||
|
||||
obj = js_NewObject(cx, &js_AnyNameClass, NULL, NULL);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче