зеркало из https://github.com/mozilla/pjs.git
Bug 330692: GC_MARK_DEBUG-only arguments are removed when GC_MARK_DEBUG is not defined. r=brendan
This commit is contained in:
Родитель
26ffa16738
Коммит
4b4cc4665f
|
@ -1828,7 +1828,7 @@ JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
|
|||
JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
|
||||
#endif
|
||||
|
||||
GC_MARK(cx, thing, name, arg);
|
||||
GC_MARK(cx, thing, name);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -3187,9 +3187,9 @@ prop_iter_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
for (i = 0, n = ida->length; i < n; i++) {
|
||||
id = ida->vector[i];
|
||||
if (JSID_IS_ATOM(id))
|
||||
GC_MARK_ATOM(cx, JSID_TO_ATOM(id), arg);
|
||||
GC_MARK_ATOM(cx, JSID_TO_ATOM(id));
|
||||
else if (JSID_IS_OBJECT(id))
|
||||
GC_MARK(cx, JSID_TO_OBJECT(id), "id", arg);
|
||||
GC_MARK(cx, JSID_TO_OBJECT(id), "id");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -676,12 +676,10 @@ js_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs)
|
|||
#ifdef GC_MARK_DEBUG
|
||||
char name[22];
|
||||
JS_snprintf(name, sizeof name, "<local root %u>", n);
|
||||
#else
|
||||
const char *name = NULL;
|
||||
#endif
|
||||
m = n & JSLRS_CHUNK_MASK;
|
||||
JS_ASSERT(JSVAL_IS_GCTHING(lrc->roots[m]));
|
||||
JS_MarkGCThing(cx, JSVAL_TO_GCTHING(lrc->roots[m]), name, NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(lrc->roots[m]), name);
|
||||
if (m == 0)
|
||||
lrc = lrc->down;
|
||||
}
|
||||
|
|
|
@ -524,6 +524,8 @@ struct JSContext {
|
|||
*/
|
||||
JSPackedBool throwing; /* is there a pending exception? */
|
||||
jsval exception; /* most-recently-thrown exception */
|
||||
/* Flag to indicate that we run inside gcCallback(cx, JSGC_MARK_END). */
|
||||
JSPackedBool insideGCMarkCallback;
|
||||
|
||||
/* Per-context options. */
|
||||
uint32 options; /* see jsapi.h for JSOPTION_* */
|
||||
|
@ -548,8 +550,10 @@ struct JSContext {
|
|||
/* Stack of thread-stack-allocated temporary GC roots. */
|
||||
JSTempValueRooter *tempValueRooters;
|
||||
|
||||
/* Flag to indicate that we run inside gcCallback(cx, JSGC_MARK_END). */
|
||||
JSBool insideGCMarkCallback;
|
||||
#ifdef GC_MARK_DEBUG
|
||||
/* Top of the GC mark stack. */
|
||||
void *gcCurrentMarkNode;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1416,11 +1416,11 @@ fun_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
if (fun) {
|
||||
JS_MarkGCThing(cx, fun, js_private_str, arg);
|
||||
GC_MARK(cx, fun, "private");
|
||||
if (fun->atom)
|
||||
GC_MARK_ATOM(cx, fun->atom, arg);
|
||||
GC_MARK_ATOM(cx, fun->atom);
|
||||
if (fun->interpreted && fun->u.i.script)
|
||||
js_MarkScript(cx, fun->u.i.script, arg);
|
||||
js_MarkScript(cx, fun->u.i.script);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
159
js/src/jsgc.c
159
js/src/jsgc.c
|
@ -916,6 +916,15 @@ out:
|
|||
#include <stdio.h>
|
||||
#include "jsprf.h"
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
const char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
|
||||
JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
|
||||
JS_EXPORT_DATA(void *) js_LiveThingToFind;
|
||||
|
||||
|
@ -974,8 +983,9 @@ gc_object_class_name(void* thing)
|
|||
}
|
||||
|
||||
static void
|
||||
gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp)
|
||||
gc_dump_thing(JSContext *cx, JSGCThing *thing, uint8 flags, FILE *fp)
|
||||
{
|
||||
GCMarkNode *prev = (GCMarkNode *)cx->gcCurrentMarkNode;
|
||||
GCMarkNode *next = NULL;
|
||||
char *path = NULL;
|
||||
|
||||
|
@ -1051,6 +1061,26 @@ gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp)
|
|||
free(path);
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkNamedGCThing(JSContext *cx, void *thing, const char *name)
|
||||
{
|
||||
GCMarkNode markNode;
|
||||
|
||||
markNode.thing = thing;
|
||||
markNode.name = name;
|
||||
markNode.next = NULL;
|
||||
markNode.prev = (GCMarkNode *)cx->gcCurrentMarkNode;
|
||||
if (markNode.prev)
|
||||
markNode.prev->next = &markNode;
|
||||
cx->gcCurrentMarkNode = &markNode;
|
||||
|
||||
js_MarkGCThing(cx, thing);
|
||||
|
||||
if (markNode.prev)
|
||||
markNode.prev->next = NULL;
|
||||
cx->gcCurrentMarkNode = markNode.prev;
|
||||
}
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
|
||||
static void
|
||||
|
@ -1058,11 +1088,11 @@ gc_mark_atom_key_thing(void *thing, void *arg)
|
|||
{
|
||||
JSContext *cx = (JSContext *) arg;
|
||||
|
||||
GC_MARK(cx, thing, "atom", NULL);
|
||||
GC_MARK(cx, thing, "atom");
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg)
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom)
|
||||
{
|
||||
jsval key;
|
||||
|
||||
|
@ -1081,38 +1111,24 @@ js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg)
|
|||
JS_snprintf(name, sizeof name, "<%x>", key);
|
||||
}
|
||||
#endif
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(key), name, arg);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(key), name);
|
||||
}
|
||||
if (atom->flags & ATOM_HIDDEN)
|
||||
js_MarkAtom(cx, atom->entry.value, arg);
|
||||
js_MarkAtom(cx, atom->entry.value);
|
||||
}
|
||||
|
||||
/*
|
||||
* These macros help avoid passing the GC_MARK_DEBUG-only |arg| parameter
|
||||
* during recursive calls when GC_MARK_DEBUG is not defined.
|
||||
* Macro to avoid passing the GC_MARK_DEBUG-only cx parameter.
|
||||
*/
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
# define UNMARKED_GC_THING_FLAGS(thing, arg) \
|
||||
UnmarkedGCThingFlags(thing, arg)
|
||||
# define NEXT_UNMARKED_GC_THING(vp, end, thingp, flagpp, arg) \
|
||||
NextUnmarkedGCThing(vp, end, thingp, flagpp, arg)
|
||||
# define MARK_GC_THING_CHILDREN(cx, thing, flagp, shouldCheckRecursion, arg) \
|
||||
MarkGCThingChildren(cx, thing, flagp, shouldCheckRecursion, arg)
|
||||
# define CALL_GC_THING_MARKER(marker, cx, thing, arg) \
|
||||
marker(cx, thing, arg)
|
||||
# define GC_MARK_DEBUG_CX(cx, arg) cx, arg
|
||||
#else
|
||||
# define UNMARKED_GC_THING_FLAGS(thing, arg) \
|
||||
UnmarkedGCThingFlags(thing)
|
||||
# define NEXT_UNMARKED_GC_THING(vp, end, thingp, flagpp, arg) \
|
||||
NextUnmarkedGCThing(vp, end, thingp, flagpp)
|
||||
# define MARK_GC_THING_CHILDREN(cx, thing, flagp, shouldCheckRecursion, arg) \
|
||||
MarkGCThingChildren(cx, thing, flagp, shouldCheckRecursion)
|
||||
# define CALL_GC_THING_MARKER(marker, cx, thing, arg) \
|
||||
marker(cx, thing, NULL)
|
||||
# define GC_MARK_DEBUG_CX(cx, arg) arg
|
||||
#endif
|
||||
|
||||
static uint8 *
|
||||
UNMARKED_GC_THING_FLAGS(void *thing, void *arg)
|
||||
UnmarkedGCThingFlags(GC_MARK_DEBUG_CX(JSContext *cx, void *thing))
|
||||
{
|
||||
uint8 flags, *flagp;
|
||||
|
||||
|
@ -1124,7 +1140,7 @@ UNMARKED_GC_THING_FLAGS(void *thing, void *arg)
|
|||
JS_ASSERT(flags != GCF_FINAL);
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_LiveThingToFind == thing)
|
||||
gc_dump_thing(thing, flags, arg, stderr);
|
||||
gc_dump_thing(cx, thing, flags, stderr);
|
||||
#endif
|
||||
|
||||
if (flags & GCF_MARK)
|
||||
|
@ -1134,8 +1150,8 @@ UNMARKED_GC_THING_FLAGS(void *thing, void *arg)
|
|||
}
|
||||
|
||||
static jsval *
|
||||
NEXT_UNMARKED_GC_THING(jsval *vp, jsval *end, void **thingp, uint8 **flagpp,
|
||||
void *arg)
|
||||
NextUnmarkedGCThing(GC_MARK_DEBUG_CX(JSContext *cx, jsval *vp), jsval *end,
|
||||
void **thingp, uint8 **flagpp)
|
||||
{
|
||||
jsval v;
|
||||
void *thing;
|
||||
|
@ -1145,7 +1161,7 @@ NEXT_UNMARKED_GC_THING(jsval *vp, jsval *end, void **thingp, uint8 **flagpp,
|
|||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v)) {
|
||||
thing = JSVAL_TO_GCTHING(v);
|
||||
flagp = UNMARKED_GC_THING_FLAGS(thing, arg);
|
||||
flagp = UnmarkedGCThingFlags(GC_MARK_DEBUG_CX(cx, thing));
|
||||
if (flagp) {
|
||||
*thingp = thing;
|
||||
*flagpp = flagp;
|
||||
|
@ -1172,8 +1188,8 @@ static void
|
|||
AddThingToUnscannedBag(JSRuntime *rt, void *thing, uint8 *flagp);
|
||||
|
||||
static void
|
||||
MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
||||
JSBool shouldCheckRecursion, void *arg)
|
||||
MarkGCThingChildren(JSContext *cx, void *thing, uint8 *flagp,
|
||||
JSBool shouldCheckRecursion)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSObject *obj;
|
||||
|
@ -1205,7 +1221,7 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
rt->gcStats.maxdepth = rt->gcStats.depth);
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_DumpGCHeap)
|
||||
gc_dump_thing(thing, *flagp, arg, js_DumpGCHeap);
|
||||
gc_dump_thing(cx, thing, *flagp, js_DumpGCHeap);
|
||||
#endif
|
||||
|
||||
#define RECURSION_TOO_DEEP() \
|
||||
|
@ -1224,15 +1240,16 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
|
||||
/* Mark slots if they are small enough to be GC-allocated. */
|
||||
if ((vp[-1] + 1) * sizeof(jsval) <= GC_NBYTES_MAX)
|
||||
GC_MARK(cx, vp - 1, "slots", arg);
|
||||
GC_MARK(cx, vp - 1, "slots");
|
||||
|
||||
/* Set up local variables to loop over unmarked things. */
|
||||
end = vp + ((obj->map->ops->mark)
|
||||
? CALL_GC_THING_MARKER(obj->map->ops->mark, cx, obj, arg)
|
||||
? obj->map->ops->mark(cx, obj, NULL)
|
||||
: JS_MIN(obj->map->freeslot, obj->map->nslots));
|
||||
|
||||
search_for_unmarked_slot:
|
||||
vp = NEXT_UNMARKED_GC_THING(vp, end, &thing, &flagp, arg);
|
||||
vp = NextUnmarkedGCThing(GC_MARK_DEBUG_CX(cx, vp),
|
||||
end, &thing, &flagp);
|
||||
if (!vp)
|
||||
break;
|
||||
v = *vp;
|
||||
|
@ -1293,8 +1310,8 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
#endif
|
||||
|
||||
do {
|
||||
vp = NEXT_UNMARKED_GC_THING(vp+1, end, &next_thing, &next_flagp,
|
||||
arg);
|
||||
vp = NextUnmarkedGCThing(GC_MARK_DEBUG_CX(cx, vp + 1),
|
||||
end, &next_thing, &next_flagp);
|
||||
if (!vp) {
|
||||
/*
|
||||
* thing came from the last unmarked GC-thing slot and we
|
||||
|
@ -1310,16 +1327,16 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
v = *vp;
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
GC_MARK(cx, thing, name, arg);
|
||||
GC_MARK(cx, thing, name);
|
||||
#else
|
||||
*flagp |= GCF_MARK;
|
||||
MARK_GC_THING_CHILDREN(cx, thing, flagp, JS_TRUE, arg);
|
||||
MarkGCThingChildren(cx, thing, flagp, JS_TRUE);
|
||||
#endif
|
||||
thing = next_thing;
|
||||
flagp = next_flagp;
|
||||
if (*flagp & GCF_MARK) {
|
||||
/*
|
||||
* This happens when recursive MarkGCThing marks
|
||||
* This happens when recursive MarkGCThingChildren marks
|
||||
* flags already stored in caller's *next_flagp.
|
||||
*/
|
||||
goto search_for_unmarked_slot;
|
||||
|
@ -1339,7 +1356,7 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
if (!JSSTRING_IS_DEPENDENT(str))
|
||||
break;
|
||||
thing = JSSTRDEP_BASE(str);
|
||||
flagp = UNMARKED_GC_THING_FLAGS(thing, arg);
|
||||
flagp = UnmarkedGCThingFlags(GC_MARK_DEBUG_CX(cx, thing));
|
||||
if (!flagp)
|
||||
break;
|
||||
#ifdef GC_MARK_DEBUG
|
||||
|
@ -1350,7 +1367,7 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
on_tail_recursion:
|
||||
#ifdef GC_MARK_DEBUG
|
||||
/* Do not eliminate C recursion to get full GC graph when debugging. */
|
||||
GC_MARK(cx, thing, name, arg);
|
||||
GC_MARK(cx, thing, name);
|
||||
break;
|
||||
#else
|
||||
/* Eliminate tail recursion for the last unmarked child. */
|
||||
|
@ -1363,20 +1380,19 @@ MARK_GC_THING_CHILDREN(JSContext *cx, void *thing, uint8 *flagp,
|
|||
case GCX_NAMESPACE:
|
||||
if (RECURSION_TOO_DEEP())
|
||||
goto add_to_unscanned_bag;
|
||||
CALL_GC_THING_MARKER(js_MarkXMLNamespace, cx, (JSXMLNamespace *)thing,
|
||||
arg);
|
||||
js_MarkXMLNamespace(cx, (JSXMLNamespace *)thing);
|
||||
break;
|
||||
|
||||
case GCX_QNAME:
|
||||
if (RECURSION_TOO_DEEP())
|
||||
goto add_to_unscanned_bag;
|
||||
CALL_GC_THING_MARKER(js_MarkXMLQName, cx, (JSXMLQName *)thing, arg);
|
||||
js_MarkXMLQName(cx, (JSXMLQName *)thing);
|
||||
break;
|
||||
|
||||
case GCX_XML:
|
||||
if (RECURSION_TOO_DEEP())
|
||||
goto add_to_unscanned_bag;
|
||||
CALL_GC_THING_MARKER(js_MarkXML, cx, (JSXML *)thing, arg);
|
||||
js_MarkXML(cx, (JSXML *)thing);
|
||||
break;
|
||||
#endif
|
||||
add_to_unscanned_bag:
|
||||
|
@ -1601,14 +1617,14 @@ ScanDelayedChildren(JSContext *cx)
|
|||
JS_ASSERT(0);
|
||||
}
|
||||
#endif
|
||||
MARK_GC_THING_CHILDREN(cx, thing, flagp, JS_FALSE, NULL);
|
||||
MarkGCThingChildren(cx, thing, flagp, JS_FALSE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We finished scanning of the arena but we can only pop it from
|
||||
* the stack if the arena is the stack's top.
|
||||
*
|
||||
* When MARK_GC_THING_CHILDREN from the above calls
|
||||
* When MarkGCThingChildren from the above calls
|
||||
* AddThingToUnscannedBag and the latter pushes new arenas to the
|
||||
* stack, we have to skip popping of this arena until it becomes
|
||||
* the top of the stack again.
|
||||
|
@ -1637,12 +1653,12 @@ ScanDelayedChildren(JSContext *cx)
|
|||
}
|
||||
|
||||
void
|
||||
js_MarkGCThing(JSContext *cx, void *thing, void *arg)
|
||||
js_MarkGCThing(JSContext *cx, void *thing)
|
||||
{
|
||||
uint8 *flagp;
|
||||
JSBool fromCallback;
|
||||
|
||||
flagp = UNMARKED_GC_THING_FLAGS(thing, arg);
|
||||
flagp = UnmarkedGCThingFlags(GC_MARK_DEBUG_CX(cx, thing));
|
||||
if (!flagp)
|
||||
return;
|
||||
*flagp |= GCF_MARK;
|
||||
|
@ -1650,7 +1666,7 @@ js_MarkGCThing(JSContext *cx, void *thing, void *arg)
|
|||
fromCallback = cx->insideGCMarkCallback;
|
||||
if (fromCallback)
|
||||
cx->insideGCMarkCallback = JS_FALSE;
|
||||
MARK_GC_THING_CHILDREN(cx, thing, flagp, JS_TRUE, arg);
|
||||
MarkGCThingChildren(cx, thing, flagp, JS_TRUE);
|
||||
if (fromCallback) {
|
||||
/*
|
||||
* Make sure that JSGC_MARK_END callback can assume that all
|
||||
|
@ -1662,6 +1678,9 @@ js_MarkGCThing(JSContext *cx, void *thing, void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
#endif
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
||||
gc_root_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg)
|
||||
{
|
||||
|
@ -1701,7 +1720,7 @@ gc_root_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg)
|
|||
JS_ASSERT(root_points_to_gcArenaList);
|
||||
#endif
|
||||
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(v), rhe->name ? rhe->name : "root", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(v), rhe->name ? rhe->name : "root");
|
||||
}
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
@ -1713,7 +1732,7 @@ gc_lock_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg)
|
|||
void *thing = (void *)lhe->thing;
|
||||
JSContext *cx = (JSContext *)arg;
|
||||
|
||||
GC_MARK(cx, thing, "locked object", NULL);
|
||||
GC_MARK(cx, thing, "locked object");
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -1737,7 +1756,7 @@ js_ForceGC(JSContext *cx, uintN gcflags)
|
|||
for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) { \
|
||||
_v = *_vp; \
|
||||
if (JSVAL_IS_GCTHING(_v)) \
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(_v), name, NULL); \
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(_v), name); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
|
@ -1947,13 +1966,13 @@ restart:
|
|||
for (fp = chain; fp; fp = chain = chain->dormantNext) {
|
||||
do {
|
||||
if (fp->callobj)
|
||||
GC_MARK(cx, fp->callobj, "call object", NULL);
|
||||
GC_MARK(cx, fp->callobj, "call object");
|
||||
if (fp->argsobj)
|
||||
GC_MARK(cx, fp->argsobj, "arguments object", NULL);
|
||||
GC_MARK(cx, fp->argsobj, "arguments object");
|
||||
if (fp->varobj)
|
||||
GC_MARK(cx, fp->varobj, "variables object", NULL);
|
||||
GC_MARK(cx, fp->varobj, "variables object");
|
||||
if (fp->script) {
|
||||
js_MarkScript(cx, fp->script, NULL);
|
||||
js_MarkScript(cx, fp->script);
|
||||
if (fp->spbase) {
|
||||
/*
|
||||
* Don't mark what has not been pushed yet, or what
|
||||
|
@ -1967,7 +1986,7 @@ restart:
|
|||
GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
|
||||
}
|
||||
}
|
||||
GC_MARK(cx, fp->thisp, "this", NULL);
|
||||
GC_MARK(cx, fp->thisp, "this");
|
||||
if (fp->argv) {
|
||||
nslots = fp->argc;
|
||||
if (fp->fun) {
|
||||
|
@ -1979,15 +1998,15 @@ restart:
|
|||
GC_MARK_JSVALS(cx, nslots, fp->argv, "arg");
|
||||
}
|
||||
if (JSVAL_IS_GCTHING(fp->rval))
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval");
|
||||
if (fp->vars)
|
||||
GC_MARK_JSVALS(cx, fp->nvars, fp->vars, "var");
|
||||
GC_MARK(cx, fp->scopeChain, "scope chain", NULL);
|
||||
GC_MARK(cx, fp->scopeChain, "scope chain");
|
||||
if (fp->sharpArray)
|
||||
GC_MARK(cx, fp->sharpArray, "sharp array", NULL);
|
||||
GC_MARK(cx, fp->sharpArray, "sharp array");
|
||||
|
||||
if (fp->xmlNamespace)
|
||||
GC_MARK(cx, fp->xmlNamespace, "xmlNamespace", NULL);
|
||||
GC_MARK(cx, fp->xmlNamespace, "xmlNamespace");
|
||||
} while ((fp = fp->down) != NULL);
|
||||
}
|
||||
|
||||
|
@ -1996,23 +2015,23 @@ restart:
|
|||
acx->fp->dormantNext = NULL;
|
||||
|
||||
/* Mark other roots-by-definition in acx. */
|
||||
GC_MARK(cx, acx->globalObject, "global object", NULL);
|
||||
GC_MARK(cx, acx->globalObject, "global object");
|
||||
for (i = 0; i < GCX_NTYPES; i++)
|
||||
GC_MARK(cx, acx->newborn[i], gc_typenames[i], NULL);
|
||||
GC_MARK(cx, acx->newborn[i], gc_typenames[i]);
|
||||
if (acx->lastAtom)
|
||||
GC_MARK_ATOM(cx, acx->lastAtom, NULL);
|
||||
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", NULL);
|
||||
GC_MARK(cx, thing, "lastInternalResult");
|
||||
}
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception");
|
||||
#endif
|
||||
#if JS_HAS_LVALUE_RETURN
|
||||
if (acx->rval2set && JSVAL_IS_GCTHING(acx->rval2))
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->rval2), "rval2", NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(acx->rval2), "rval2");
|
||||
#endif
|
||||
|
||||
for (sh = acx->stackHeaders; sh; sh = sh->down) {
|
||||
|
@ -2026,8 +2045,8 @@ restart:
|
|||
for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) {
|
||||
if (tvr->count < 0) {
|
||||
if (JSVAL_IS_GCTHING(tvr->u.value)) {
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(tvr->u.value), "tvr->u.value",
|
||||
NULL);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING(tvr->u.value),
|
||||
"tvr->u.value");
|
||||
}
|
||||
} else {
|
||||
GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array");
|
||||
|
|
|
@ -153,49 +153,30 @@ extern JSBool
|
|||
js_IsAboutToBeFinalized(JSContext *cx, void *thing);
|
||||
|
||||
extern void
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg);
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom);
|
||||
|
||||
/* We avoid a large number of unnecessary calls by doing the flag check first */
|
||||
#define GC_MARK_ATOM(cx, atom, arg) \
|
||||
#define GC_MARK_ATOM(cx, atom) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!((atom)->flags & ATOM_MARK)) \
|
||||
js_MarkAtom(cx, atom, arg); \
|
||||
js_MarkAtom(cx, atom); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
* FIXME: We should remove "arg" argument when GC_MARK_DEBUG is not defined.
|
||||
* See bug 330692.
|
||||
*/
|
||||
extern void
|
||||
js_MarkGCThing(JSContext *cx, void *thing, void *arg);
|
||||
js_MarkGCThing(JSContext *cx, void *thing);
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
# define GC_MARK(cx, thing, name) js_MarkNamedGCThing(cx, thing, name)
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
const char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
extern void
|
||||
js_MarkNamedGCThing(JSContext *cx, void *thing, const char *name);
|
||||
|
||||
#define GC_MARK(cx_, thing_, name_, prev_) \
|
||||
JS_BEGIN_MACRO \
|
||||
GCMarkNode node_; \
|
||||
node_.thing = thing_; \
|
||||
node_.name = name_; \
|
||||
node_.next = NULL; \
|
||||
node_.prev = prev_; \
|
||||
if (prev_) ((GCMarkNode *)(prev_))->next = &node_; \
|
||||
js_MarkGCThing(cx_, thing_, &node_); \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
|
||||
#else /* !GC_MARK_DEBUG */
|
||||
# define GC_MARK(cx, thing, name) js_MarkGCThing(cx, thing)
|
||||
|
||||
#define GC_MARK(cx, thing, name, prev) js_MarkGCThing(cx, thing, NULL)
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags to modify how a GC marks and sweeps:
|
||||
|
|
|
@ -4274,9 +4274,9 @@ js_Mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
continue;
|
||||
MARK_SCOPE_PROPERTY(sprop);
|
||||
if (JSID_IS_ATOM(sprop->id))
|
||||
GC_MARK_ATOM(cx, JSID_TO_ATOM(sprop->id), arg);
|
||||
GC_MARK_ATOM(cx, JSID_TO_ATOM(sprop->id));
|
||||
else if (JSID_IS_OBJECT(sprop->id))
|
||||
GC_MARK(cx, JSID_TO_OBJECT(sprop->id), "id", arg);
|
||||
GC_MARK(cx, JSID_TO_OBJECT(sprop->id), "id");
|
||||
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
|
@ -4293,20 +4293,14 @@ js_Mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_getter_str);
|
||||
#endif
|
||||
GC_MARK(cx,
|
||||
JSVAL_TO_GCTHING((jsval) sprop->getter),
|
||||
buf,
|
||||
arg);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING((jsval) sprop->getter), buf);
|
||||
}
|
||||
if (sprop->attrs & JSPROP_SETTER) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
JS_snprintf(buf, sizeof buf, "%s %s",
|
||||
id, js_setter_str);
|
||||
#endif
|
||||
GC_MARK(cx,
|
||||
JSVAL_TO_GCTHING((jsval) sprop->setter),
|
||||
buf,
|
||||
arg);
|
||||
GC_MARK(cx, JSVAL_TO_GCTHING((jsval) sprop->setter), buf);
|
||||
}
|
||||
}
|
||||
#endif /* JS_HAS_GETTER_SETTER */
|
||||
|
@ -4315,7 +4309,7 @@ js_Mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
/* No one runs while the GC is running, so we can use LOCKED_... here. */
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
if (clasp->mark)
|
||||
(void) clasp->mark(cx, obj, arg);
|
||||
(void) clasp->mark(cx, obj, NULL);
|
||||
|
||||
if (scope->object != obj) {
|
||||
/*
|
||||
|
|
|
@ -3757,7 +3757,7 @@ regexp_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
{
|
||||
JSRegExp *re = (JSRegExp *) JS_GetPrivate(cx, obj);
|
||||
if (re)
|
||||
JS_MarkGCThing(cx, re->source, "source", arg);
|
||||
GC_MARK(cx, re->source, "source");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -843,7 +843,7 @@ script_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
|
||||
script = (JSScript *) JS_GetPrivate(cx, obj);
|
||||
if (script)
|
||||
js_MarkScript(cx, script, arg);
|
||||
js_MarkScript(cx, script);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1345,7 +1345,7 @@ js_DestroyScript(JSContext *cx, JSScript *script)
|
|||
}
|
||||
|
||||
void
|
||||
js_MarkScript(JSContext *cx, JSScript *script, void *arg)
|
||||
js_MarkScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSAtomMap *map;
|
||||
uintN i, length;
|
||||
|
@ -1355,7 +1355,7 @@ js_MarkScript(JSContext *cx, JSScript *script, void *arg)
|
|||
length = map->length;
|
||||
vector = map->vector;
|
||||
for (i = 0; i < length; i++)
|
||||
GC_MARK_ATOM(cx, vector[i], arg);
|
||||
GC_MARK_ATOM(cx, vector[i]);
|
||||
|
||||
if (script->filename)
|
||||
js_MarkScriptFilename(script->filename);
|
||||
|
|
|
@ -177,7 +177,7 @@ extern void
|
|||
js_DestroyScript(JSContext *cx, JSScript *script);
|
||||
|
||||
extern void
|
||||
js_MarkScript(JSContext *cx, JSScript *script, void *arg);
|
||||
js_MarkScript(JSContext *cx, JSScript *script);
|
||||
|
||||
extern jssrcnote *
|
||||
js_GetSrcNote(JSScript *script, jsbytecode *pc);
|
||||
|
|
|
@ -193,8 +193,7 @@ namespace_finalize(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static void
|
||||
namespace_mark_vector(JSContext *cx, JSXMLNamespace **vec, uint32 len,
|
||||
void *arg)
|
||||
namespace_mark_vector(JSContext *cx, JSXMLNamespace **vec, uint32 len)
|
||||
{
|
||||
uint32 i;
|
||||
JSXMLNamespace *ns;
|
||||
|
@ -208,10 +207,8 @@ namespace_mark_vector(JSContext *cx, JSXMLNamespace **vec, uint32 len,
|
|||
JS_snprintf(buf, sizeof buf, "%s=%s",
|
||||
ns->prefix ? JS_GetStringBytes(ns->prefix) : "",
|
||||
JS_GetStringBytes(ns->uri));
|
||||
#else
|
||||
const char *buf = NULL;
|
||||
#endif
|
||||
JS_MarkGCThing(cx, ns, buf, arg);
|
||||
GC_MARK(cx, ns, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +219,7 @@ namespace_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
JSXMLNamespace *ns;
|
||||
|
||||
ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj);
|
||||
JS_MarkGCThing(cx, ns, js_private_str, arg);
|
||||
GC_MARK(cx, ns, "private");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -305,11 +302,11 @@ js_NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri,
|
|||
}
|
||||
|
||||
void
|
||||
js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns, void *arg)
|
||||
js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns)
|
||||
{
|
||||
JS_MarkGCThing(cx, ns->object, js_object_str, arg);
|
||||
JS_MarkGCThing(cx, ns->prefix, js_prefix_str, arg);
|
||||
JS_MarkGCThing(cx, ns->uri, js_uri_str, arg);
|
||||
GC_MARK(cx, ns->object, "object");
|
||||
GC_MARK(cx, ns->prefix, "prefix");
|
||||
GC_MARK(cx, ns->uri, "uri");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -415,7 +412,7 @@ qname_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
JSXMLQName *qn;
|
||||
|
||||
qn = (JSXMLQName *) JS_GetPrivate(cx, obj);
|
||||
JS_MarkGCThing(cx, qn, js_private_str, arg);
|
||||
GC_MARK(cx, qn, "private");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -569,12 +566,12 @@ js_NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix,
|
|||
}
|
||||
|
||||
void
|
||||
js_MarkXMLQName(JSContext *cx, JSXMLQName *qn, void *arg)
|
||||
js_MarkXMLQName(JSContext *cx, JSXMLQName *qn)
|
||||
{
|
||||
JS_MarkGCThing(cx, qn->object, js_object_str, arg);
|
||||
JS_MarkGCThing(cx, qn->uri, js_uri_str, arg);
|
||||
JS_MarkGCThing(cx, qn->prefix, js_prefix_str, arg);
|
||||
JS_MarkGCThing(cx, qn->localName, js_localName_str, arg);
|
||||
GC_MARK(cx, qn->object, "object");
|
||||
GC_MARK(cx, qn->uri, "uri");
|
||||
GC_MARK(cx, qn->prefix, "prefix");
|
||||
GC_MARK(cx, qn->localName, "localName");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4904,7 +4901,7 @@ xml_finalize(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static void
|
||||
xml_mark_vector(JSContext *cx, JSXML **vec, uint32 len, void *arg)
|
||||
xml_mark_vector(JSContext *cx, JSXML **vec, uint32 len)
|
||||
{
|
||||
uint32 i;
|
||||
JSXML *elt;
|
||||
|
@ -4933,10 +4930,8 @@ xml_mark_vector(JSContext *cx, JSXML **vec, uint32 len, void *arg)
|
|||
js_DeflateStringToBuffer(cx, JSSTRING_CHARS(str), srclen,
|
||||
buf, &dstlen);
|
||||
}
|
||||
#else
|
||||
const char *buf = NULL;
|
||||
#endif
|
||||
JS_MarkGCThing(cx, elt, buf, arg);
|
||||
GC_MARK(cx, elt, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5164,8 +5159,8 @@ xml_mark(JSContext *cx, JSObject *obj, void *arg)
|
|||
JSXML *xml;
|
||||
|
||||
xml = (JSXML *) JS_GetPrivate(cx, obj);
|
||||
JS_MarkGCThing(cx, xml, js_private_str, arg);
|
||||
return js_Mark(cx, obj, arg);
|
||||
GC_MARK(cx, xml, "private");
|
||||
return js_Mark(cx, obj, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -7238,39 +7233,36 @@ js_NewXML(JSContext *cx, JSXMLClass xml_class)
|
|||
}
|
||||
|
||||
void
|
||||
js_MarkXML(JSContext *cx, JSXML *xml, void *arg)
|
||||
js_MarkXML(JSContext *cx, JSXML *xml)
|
||||
{
|
||||
JS_MarkGCThing(cx, xml->object, js_object_str, arg);
|
||||
JS_MarkGCThing(cx, xml->name, js_name_str, arg);
|
||||
JS_MarkGCThing(cx, xml->parent, js_xml_parent_str, arg);
|
||||
GC_MARK(cx, xml->object, "object");
|
||||
GC_MARK(cx, xml->name, "name");
|
||||
GC_MARK(cx, xml->parent, "xml_parent");
|
||||
|
||||
if (JSXML_HAS_VALUE(xml)) {
|
||||
JS_MarkGCThing(cx, xml->xml_value, "value", arg);
|
||||
GC_MARK(cx, xml->xml_value, "value");
|
||||
return;
|
||||
}
|
||||
|
||||
xml_mark_vector(cx,
|
||||
(JSXML **) xml->xml_kids.vector,
|
||||
xml->xml_kids.length,
|
||||
arg);
|
||||
xml->xml_kids.length);
|
||||
XMLArrayTrim(&xml->xml_kids);
|
||||
|
||||
if (xml->xml_class == JSXML_CLASS_LIST) {
|
||||
if (xml->xml_target)
|
||||
JS_MarkGCThing(cx, xml->xml_target, "target", arg);
|
||||
GC_MARK(cx, xml->xml_target, "target");
|
||||
if (xml->xml_targetprop)
|
||||
JS_MarkGCThing(cx, xml->xml_targetprop, "targetprop", arg);
|
||||
GC_MARK(cx, xml->xml_targetprop, "targetprop");
|
||||
} else {
|
||||
namespace_mark_vector(cx,
|
||||
(JSXMLNamespace **) xml->xml_namespaces.vector,
|
||||
xml->xml_namespaces.length,
|
||||
arg);
|
||||
xml->xml_namespaces.length);
|
||||
XMLArrayTrim(&xml->xml_namespaces);
|
||||
|
||||
xml_mark_vector(cx,
|
||||
(JSXML **) xml->xml_attrs.vector,
|
||||
xml->xml_attrs.length,
|
||||
arg);
|
||||
xml->xml_attrs.length);
|
||||
XMLArrayTrim(&xml->xml_attrs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ js_NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri,
|
|||
JSBool declared);
|
||||
|
||||
extern void
|
||||
js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns, void *arg);
|
||||
js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns);
|
||||
|
||||
extern void
|
||||
js_FinalizeXMLNamespace(JSContext *cx, JSXMLNamespace *ns);
|
||||
|
@ -88,7 +88,7 @@ js_NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix,
|
|||
JSString *localName);
|
||||
|
||||
extern void
|
||||
js_MarkXMLQName(JSContext *cx, JSXMLQName *qn, void *arg);
|
||||
js_MarkXMLQName(JSContext *cx, JSXMLQName *qn);
|
||||
|
||||
extern void
|
||||
js_FinalizeXMLQName(JSContext *cx, JSXMLQName *qn);
|
||||
|
@ -202,7 +202,7 @@ extern JSXML *
|
|||
js_NewXML(JSContext *cx, JSXMLClass xml_class);
|
||||
|
||||
extern void
|
||||
js_MarkXML(JSContext *cx, JSXML *xml, void *arg);
|
||||
js_MarkXML(JSContext *cx, JSXML *xml);
|
||||
|
||||
extern void
|
||||
js_FinalizeXML(JSContext *cx, JSXML *xml);
|
||||
|
|
Загрузка…
Ссылка в новой задаче