Bug 366975: Allow to allocate new GC things from JSGC_END callback. r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2007-01-18 23:36:41 +00:00
Родитель e835c91ea5
Коммит 7138d86b57
14 изменённых файлов: 135 добавлений и 99 удалений

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

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