From 70aa979d4f6d1b953cb1d2de1bf79b6fa3c4f307 Mon Sep 17 00:00:00 2001 From: "igor@mir2.org" Date: Sat, 19 Jan 2008 16:46:37 -0800 Subject: [PATCH] Bug 411025: temp rooting implemenation cleanup, r,a=brendan --- js/src/jsapi.c | 12 +++- js/src/jscntxt.h | 159 ++++++++++++++++------------------------------- js/src/jsprvtd.h | 4 +- js/src/jsxml.c | 4 +- 4 files changed, 70 insertions(+), 109 deletions(-) diff --git a/js/src/jsapi.c b/js/src/jsapi.c index 3f249bdf093..a3f367602e1 100644 --- a/js/src/jsapi.c +++ b/js/src/jsapi.c @@ -4653,6 +4653,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, const char *filename, uintN lineno) { JSFunction *fun; + JSTempValueRooter tvr; JSAtom *funAtom, *argAtom; uintN i; @@ -4663,12 +4664,15 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, funAtom = js_Atomize(cx, name, strlen(name), 0); if (!funAtom) { fun = NULL; - goto out; + goto out2; } } fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom); if (!fun) - goto out; + goto out2; + + /* From this point the control must flow through the label out. */ + JS_PUSH_TEMP_ROOT_FUNCTION(cx, fun, &tvr); for (i = 0; i < nargs; i++) { argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); if (!argAtom) { @@ -4707,6 +4711,10 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, #endif out: + cx->weakRoots.newborn[JSTRACE_FUNCTION] = fun; + JS_POP_TEMP_ROOT(cx, &tvr); + + out2: LAST_FRAME_CHECKS(cx, fun); return fun; } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 6f794cfb6ef..bea884226ea 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -514,141 +514,92 @@ typedef struct JSLocalRootStack { * a C function across several layers of other functions, use the * js_LeaveLocalRootScopeWithResult internal API (see further below) instead. * - * JSTempValueRooter.count defines the type of the rooted value referenced by - * JSTempValueRooter.u union of type JSTempValueUnion according to the - * following table: + * The macros also provide a simple way to get a single rooted pointer via + * JS_PUSH_TEMP_ROOT_(cx, NULL, &tvr). Then &tvr.u. gives the + * necessary pointer. * - * count description - * JSTVU_SINGLE u.value contains the single value or GC-thing to root. - * JSTVU_TRACE u.trace holds a trace hook called to trace the values. - * JSTVU_SPROP u.sprop points to the property tree node to mark. - * JSTVU_WEAK_ROOTS u.weakRoots points to saved weak roots. - * JSTVU_PARSE_CONTEXT u.parseContext roots things generated during parsing. - * JSTVU_SCRIPT u.script roots a pointer to JSScript. - * >= 0 u.array points to a stack-allocated vector of jsvals. + * JSTempValueRooter.count defines the type of the rooted value referenced by + * JSTempValueRooter.u union of type JSTempValueUnion. When count is positive + * or zero, u.array points to a vector of jsvals. Otherwise it must be one of + * the following constants: */ -#define JSTVU_SINGLE (-1) -#define JSTVU_TRACE (-2) -#define JSTVU_SPROP (-3) -#define JSTVU_WEAK_ROOTS (-4) -#define JSTVU_PARSE_CONTEXT (-5) -#define JSTVU_SCRIPT (-6) +#define JSTVU_SINGLE (-1) /* u.value or u. is single jsval + or GC-thing */ +#define JSTVU_TRACE (-2) /* u.trace is a hook to trace a custom + * structure */ +#define JSTVU_SPROP (-3) /* u.sprop roots property tree node */ +#define JSTVU_WEAK_ROOTS (-4) /* u.weakRoots points to saved weak roots */ +#define JSTVU_PARSE_CONTEXT (-5) /* u.parseContext roots JSParseContext* */ +#define JSTVU_SCRIPT (-6) /* u.script roots JSScript* */ /* - * To root a single GC-thing pointer, which need not be tagged and stored as a - * jsval, use JS_PUSH_TEMP_ROOT_GCTHING. The macro reinterprets an arbitrary - * GC-thing as jsval. It works because a GC-thing is aligned on a 0 mod 8 - * boundary, and object has the 0 jsval tag. So any GC-thing may be tagged as - * if it were an object and untagged, if it's then used only as an opaque - * pointer until discriminated by other means than tag bits (this is how the - * GC mark function uses its |thing| parameter -- it consults GC-thing flags - * stored separately from the thing to decide the type of thing). - * - * JS_PUSH_TEMP_ROOT_OBJECT and JS_PUSH_TEMP_ROOT_STRING are type-safe - * alternatives to JS_PUSH_TEMP_ROOT_GCTHING for JSObject and JSString. They - * also provide a simple way to get a single pointer to rooted JSObject or - * JSString via JS_PUSH_TEMP_ROOT_(OBJECT|STRTING)(cx, NULL, &tvr). Then - * &tvr.u.object or tvr.u.string gives the necessary pointer, which puns - * tvr.u.value safely because JSObject * and JSString * are GC-things and, as - * such, their tag bits are all zeroes. + * Here single JSTVU_SINGLE covers both jsval and pointers to any GC-thing via + * reinterpreting the thing as JSVAL_OBJECT. It works because the GC-thing is + * aligned on a 0 mod 8 boundary, and object has the 0 jsval tag. So any + * GC-thing may be tagged as if it were an object and untagged, if it's then + * used only as an opaque pointer until discriminated by other means than tag + * bits. This is how, for example, js_GetGCThingTraceKind uses its |thing| + * parameter -- it consults GC-thing flags stored separately from the thing to + * decide the kind of thing. * * The following checks that this type-punning is possible. */ JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval)); -JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(JSObject *)); +JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(void *)); -#define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \ +#define JS_PUSH_TEMP_ROOT_COMMON(cx,x,tvr,cnt,kind) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters != (tvr)); \ + (tvr)->count = (cnt); \ + (tvr)->u.kind = (x); \ (tvr)->down = (cx)->tempValueRooters; \ (cx)->tempValueRooters = (tvr); \ JS_END_MACRO -#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.value = val; \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT((int)(cnt) >= 0); \ - (tvr)->count = (ptrdiff_t)(cnt); \ - (tvr)->u.array = (arr); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_TRACE; \ - (tvr)->u.trace = (trace_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.object = (obj); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.string = (str); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_GCTHING(cx,thing,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT(JSVAL_IS_OBJECT((jsval)thing)); \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.gcthing = (thing); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - #define JS_POP_TEMP_ROOT(cx,tvr) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters == (tvr)); \ (cx)->tempValueRooters = (tvr)->down; \ JS_END_MACRO -#define JS_TEMP_ROOT_EVAL(cx,cnt,val,expr) \ +#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ JS_BEGIN_MACRO \ - JSTempValueRooter tvr; \ - JS_PUSH_TEMP_ROOT(cx, cnt, val, &tvr); \ - (expr); \ - JS_POP_TEMP_ROOT(cx, &tvr); \ + JS_ASSERT((int)(cnt) >= 0); \ + JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \ JS_END_MACRO +#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, val, tvr, JSTVU_SINGLE, value) + +#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object) + +#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, str, tvr, JSTVU_SINGLE, string) + +#define JS_PUSH_TEMP_ROOT_FUNCTION(cx,fun,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, fun, tvr, JSTVU_SINGLE, function) + +#define JS_PUSH_TEMP_ROOT_QNAME(cx,qn,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, qn, tvr, JSTVU_SINGLE, qname) + +#define JS_PUSH_TEMP_ROOT_XML(cx,xml_,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, xml_, tvr, JSTVU_SINGLE, xml) + +#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, trace_, tvr, JSTVU_TRACE, trace) + #define JS_PUSH_TEMP_ROOT_SPROP(cx,sprop_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SPROP; \ - (tvr)->u.sprop = (sprop_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, sprop_, tvr, JSTVU_SPROP, sprop) #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 + JS_PUSH_TEMP_ROOT_COMMON(cx, weakRoots_, tvr, JSTVU_WEAK_ROOTS, weakRoots) #define JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx,pc,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_PARSE_CONTEXT; \ - (tvr)->u.parseContext = (pc); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, pc, tvr, JSTVU_PARSE_CONTEXT, parseContext) #define JS_PUSH_TEMP_ROOT_SCRIPT(cx,script_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SCRIPT; \ - (tvr)->u.script = (script_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, script_, tvr, JSTVU_SCRIPT, script) struct JSContext { /* JSRuntime contextList linkage. */ diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 82c0407ec88..80fb29f3312 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -234,7 +234,9 @@ typedef union JSTempValueUnion { jsval value; JSObject *object; JSString *string; - void *gcthing; + JSFunction *function; + JSXML *xml; + JSXMLQName *qname; JSTempValueTrace trace; JSScopeProperty *sprop; JSWeakRoots *weakRoots; diff --git a/js/src/jsxml.c b/js/src/jsxml.c index 972daaf7cff..264cf4a9c77 100644 --- a/js/src/jsxml.c +++ b/js/src/jsxml.c @@ -3121,7 +3121,7 @@ ToAttributeName(JSContext *cx, jsval v) if (!qn) return NULL; - JS_PUSH_TEMP_ROOT_GCTHING(cx, qn, &tvr); + JS_PUSH_TEMP_ROOT_QNAME(cx, qn, &tvr); obj = js_GetAttributeNameObject(cx, qn); JS_POP_TEMP_ROOT(cx, &tvr); if (!obj) @@ -7559,7 +7559,7 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class) xml = js_NewXML(cx, xml_class); if (!xml) return NULL; - JS_PUSH_TEMP_ROOT_GCTHING(cx, xml, &tvr); + JS_PUSH_TEMP_ROOT_XML(cx, xml, &tvr); obj = js_GetXMLObject(cx, xml); JS_POP_TEMP_ROOT(cx, &tvr); return obj;