diff --git a/js/src/jsapi.c b/js/src/jsapi.c index 24b9f510f355..07033300da0f 100644 --- a/js/src/jsapi.c +++ b/js/src/jsapi.c @@ -1877,10 +1877,8 @@ JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg) #ifdef JS_THREADSAFE JS_ASSERT(cx->runtime->gcThread == trc->context->thread); #endif - if (thing) { - JS_SET_TRACING_NAME(trc, name ? name : "unknown"); - js_CallGCThingTracer(trc, thing); - } + JS_SET_TRACING_NAME(trc, name ? name : "unknown"); + js_CallValueTracerIfGCThing(trc, (jsval)thing); } extern JS_PUBLIC_API(JSBool) diff --git a/js/src/jscntxt.c b/js/src/jscntxt.c index 198c127e0df3..2dec7d901c56 100644 --- a/js/src/jscntxt.c +++ b/js/src/jscntxt.c @@ -816,15 +816,7 @@ js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs) v = lrc->roots[m]; JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL); JS_SET_TRACING_INDEX(trc, "local_root", n); - - /* - * When v is tagged as an object, it can be in fact an arbitrary - * GC thing so we have to use js_CallGCThingTracer on it. - */ - if (JSVAL_IS_OBJECT(v)) - js_CallGCThingTracer(trc, JSVAL_TO_GCTHING(v)); - else - JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); + js_CallValueTracerIfGCThing(trc, v); if (m == 0) lrc = lrc->down; } diff --git a/js/src/jsgc.c b/js/src/jsgc.c index 099b889d3fee..97b097b0e672 100644 --- a/js/src/jsgc.c +++ b/js/src/jsgc.c @@ -2467,6 +2467,7 @@ JS_CallTracer(JSTracer *trc, void *thing, uint32 kind) uint8 *flagp; jsval v; + JS_ASSERT(thing); JS_ASSERT(JS_IS_VALID_TRACE_KIND(kind)); JS_ASSERT(trc->debugPrinter || trc->debugPrintArg); @@ -2572,17 +2573,24 @@ JS_CallTracer(JSTracer *trc, void *thing, uint32 kind) } void -js_CallGCThingTracer(JSTracer *trc, void *thing) +js_CallValueTracerIfGCThing(JSTracer *trc, jsval v) { - uint32 traceKind; + void *thing; + uint32 kind; - JS_ASSERT(thing != NULL); - - traceKind = GCTypeToTraceKindMap[*js_GetGCThingFlags(thing) & GCF_TYPEMASK]; - JS_CallTracer(trc, thing, traceKind); + if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) { + thing = JSVAL_TO_TRACEABLE(v); + kind = JSVAL_TRACE_KIND(v); + } else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) { + /* v can be an arbitrary GC thing reinterpreted as an object. */ + thing = JSVAL_TO_OBJECT(v); + kind = GCTypeToTraceKindMap[*js_GetGCThingFlags(thing) & GCF_TYPEMASK]; + } else { + return; + } + JS_CallTracer(trc, thing, kind); } - JS_STATIC_DLL_CALLBACK(JSDHashOperator) gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg) @@ -2623,7 +2631,7 @@ gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, JS_ASSERT(root_points_to_gcArenaList); #endif JS_SET_TRACING_NAME(trc, rhe->name ? rhe->name : "root"); - js_CallGCThingTracer(trc, JSVAL_TO_GCTHING(v)); + js_CallValueTracerIfGCThing(trc, v); } return JS_DHASH_NEXT; @@ -2763,12 +2771,15 @@ TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr) for (i = 0; i < GCX_NTYPES; i++) { thing = wr->newborn[i]; - if (thing) - JS_CALL_TRACER(trc, thing, GCTypeToTraceKindMap[i], gc_typenames[i]); + if (thing) { + JS_CALL_TRACER(trc, thing, GCTypeToTraceKindMap[i], + gc_typenames[i]); + } } if (wr->lastAtom) JS_CALL_TRACER(trc, wr->lastAtom, JSTRACE_ATOM, "lastAtom"); - JS_CALL_VALUE_TRACER(trc, wr->lastInternalResult, "lastInternalResult"); + JS_SET_TRACING_NAME(trc, "lastInternalResult"); + js_CallValueTracerIfGCThing(trc, wr->lastInternalResult); } JS_FRIEND_API(void) @@ -2777,7 +2788,6 @@ js_TraceContext(JSTracer *trc, JSContext *acx) JSStackFrame *chain, *fp; JSStackHeader *sh; JSTempValueRooter *tvr; - jsval v; /* * Iterate frame chain and dormant chains. Temporarily tack current @@ -2830,21 +2840,8 @@ js_TraceContext(JSTracer *trc, JSContext *acx) for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) { switch (tvr->count) { case JSTVU_SINGLE: - v = tvr->u.value; - if (JSVAL_IS_GCTHING(v) && v != JSVAL_NULL) { - /* - * When v is tagged as an object, it can be in fact an - * arbitrary GC thing so we have to use js_CallGCThingTracer - * on it. - */ - JS_SET_TRACING_NAME(trc, "tvr->u.value"); - if (JSVAL_IS_OBJECT(v)) { - js_CallGCThingTracer(trc, JSVAL_TO_GCTHING(v)); - } else { - JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), - JSVAL_TRACE_KIND(v)); - } - } + JS_SET_TRACING_NAME(trc, "tvr->u.value"); + js_CallValueTracerIfGCThing(trc, tvr->u.value); break; case JSTVU_TRACE: tvr->u.trace(trc, tvr); diff --git a/js/src/jsgc.h b/js/src/jsgc.h index a20daf2226b1..b6727d4ca4fb 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -232,8 +232,13 @@ JS_STATIC_ASSERT(JSTRACE_STRING == 2); # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_ATOM) #endif +/* + * Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as + * JSVAL_OBJECT and js_GetGCThingFlags has to be used to find the real type + * behind v. + */ extern void -js_CallGCThingTracer(JSTracer *trc, void *thing); +js_CallValueTracerIfGCThing(JSTracer *trc, jsval v); extern void js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp); diff --git a/js/src/jsxml.c b/js/src/jsxml.c index 94358ed60ed0..54fb7a150157 100644 --- a/js/src/jsxml.c +++ b/js/src/jsxml.c @@ -212,7 +212,8 @@ namespace_trace(JSTracer *trc, JSObject *obj) JSXMLNamespace *ns; ns = (JSXMLNamespace *) JS_GetPrivate(trc->context, obj); - JS_CALL_TRACER(trc, ns, JSTRACE_NAMESPACE, "private"); + if (ns) + JS_CALL_TRACER(trc, ns, JSTRACE_NAMESPACE, "private"); } static JSBool @@ -407,7 +408,8 @@ qname_trace(JSTracer *trc, JSObject *obj) JSXMLQName *qn; qn = (JSXMLQName *) JS_GetPrivate(trc->context, obj); - JS_CALL_TRACER(trc, qn, JSTRACE_QNAME, "private"); + if (qn) + JS_CALL_TRACER(trc, qn, JSTRACE_QNAME, "private"); } static JSBool @@ -1045,13 +1047,10 @@ XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) size_t index = 0; #endif - while (cursor) { + for (; cursor; cursor = cursor->next) { root = cursor->root; - if (root) { - JS_SET_TRACING_INDEX(trc, "cursor_root", index++); - js_CallGCThingTracer(trc, root); - } - cursor = cursor->next; + JS_SET_TRACING_INDEX(trc, "cursor_root", index++); + js_CallValueTracerIfGCThing(trc, (jsval)root); } }