diff -up mozilla/js/src/jsapi.c.411025 mozilla/js/src/jsapi.c --- mozilla/js/src/jsapi.c.411025 2008-03-22 03:59:06.000000000 -0400 +++ mozilla/js/src/jsapi.c 2008-04-09 09:57:53.000000000 -0400 @@ -3893,6 +3893,7 @@ JS_CompileUCFunctionForPrincipals(JSCont JSTokenStream *ts; JSFunction *fun; JSAtom *funAtom, *argAtom; + JSTempValueRooter tvr; uintN i; CHECK_REQUEST(cx); @@ -3900,7 +3901,7 @@ JS_CompileUCFunctionForPrincipals(JSCont ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); if (!ts) { fun = NULL; - goto out; + goto out2; } if (!name) { funAtom = NULL; @@ -3908,12 +3909,15 @@ JS_CompileUCFunctionForPrincipals(JSCont funAtom = js_Atomize(cx, name, strlen(name), 0); if (!funAtom) { fun = NULL; - goto out; + goto out2; } } fun = js_NewFunction(cx, NULL, NULL, nargs, 0, 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); if (nargs) { for (i = 0; i < nargs; i++) { argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); @@ -3940,10 +3944,15 @@ JS_CompileUCFunctionForPrincipals(JSCont if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom), OBJECT_TO_JSVAL(fun->object), NULL, NULL, JSPROP_ENUMERATE, NULL)) { - return NULL; + fun = NULL; } } -out: + + out: + cx->weakRoots.newborn[GCX_PRIVATE] = (JSGCThing *) fun; + JS_POP_TEMP_ROOT(cx, &tvr); + + out2: if (ts) js_CloseTokenStream(cx, ts); JS_ARENA_RELEASE(&cx->tempPool, mark); diff -up mozilla/js/src/jscntxt.h.411025 mozilla/js/src/jscntxt.h --- mozilla/js/src/jscntxt.h.411025 2008-03-22 03:59:06.000000000 -0400 +++ mozilla/js/src/jscntxt.h 2008-04-09 09:55:34.000000000 -0400 @@ -387,130 +387,88 @@ 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: - * - * count description - * JSTVU_SINGLE u.value contains the single value or GC-thing to root. - * JSTVU_MARKER u.marker holds a hook that GC calls to mark 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_SCRIPT u.script roots a pointer to JSScript. - * >= 0 u.array points to a stack-allocated vector of jsvals. - */ -#define JSTVU_SINGLE (-1) -#define JSTVU_MARKER (-2) -#define JSTVU_SPROP (-3) -#define JSTVU_WEAK_ROOTS (-4) -#define JSTVU_SCRIPT (-5) - -/* - * 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). + * 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. * - * 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. + * 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) /* u.value or u. is single jsval + or GC-thing */ +#define JSTVU_MARKER (-2) /* u.marker is a hook to mark 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_SCRIPT (-5) /* u.script roots JSScript* */ + +/* + * 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(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) \ +#define JS_POP_TEMP_ROOT(cx,tvr) \ JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.value = val; \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ + JS_ASSERT((cx)->tempValueRooters == (tvr)); \ + (cx)->tempValueRooters = (tvr)->down; \ JS_END_MACRO #define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ JS_BEGIN_MACRO \ JS_ASSERT((ptrdiff_t)(cnt) >= 0); \ - (tvr)->count = (ptrdiff_t)(cnt); \ - (tvr)->u.array = (arr); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ + JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \ JS_END_MACRO -#define JS_PUSH_TEMP_ROOT_MARKER(cx,marker_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_MARKER; \ - (tvr)->u.marker = (marker_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - 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_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.object = (obj); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object) #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 + JS_PUSH_TEMP_ROOT_COMMON(cx, str, tvr, JSTVU_SINGLE, string) -#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_PUSH_TEMP_ROOT_FUNCTION(cx,fun,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, fun, tvr, JSTVU_SINGLE, function) -#define JS_POP_TEMP_ROOT(cx,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT((cx)->tempValueRooters == (tvr)); \ - (cx)->tempValueRooters = (tvr)->down; \ - JS_END_MACRO +#define JS_PUSH_TEMP_ROOT_QNAME(cx,qn,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, qn, tvr, JSTVU_SINGLE, qname) -#define JS_TEMP_ROOT_EVAL(cx,cnt,val,expr) \ - JS_BEGIN_MACRO \ - JSTempValueRooter tvr; \ - JS_PUSH_TEMP_ROOT(cx, cnt, val, &tvr); \ - (expr); \ - JS_POP_TEMP_ROOT(cx, &tvr); \ - JS_END_MACRO +#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_MARKER(cx,marker_,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, marker_, tvr, JSTVU_MARKER, marker) #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_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 { JSCList links; diff -up mozilla/js/src/jsprvtd.h.411025 mozilla/js/src/jsprvtd.h --- mozilla/js/src/jsprvtd.h.411025 2008-03-22 03:59:07.000000000 -0400 +++ mozilla/js/src/jsprvtd.h 2008-04-09 09:55:34.000000000 -0400 @@ -212,7 +212,9 @@ typedef union JSTempValueUnion { jsval value; JSObject *object; JSString *string; - void *gcthing; + JSFunction *function; + JSXML *xml; + JSXMLQName *qname; JSTempValueMarker marker; JSScopeProperty *sprop; JSWeakRoots *weakRoots; diff -up mozilla/js/src/jsutil.h.411025 mozilla/js/src/jsutil.h --- mozilla/js/src/jsutil.h.411025 2004-11-17 02:39:42.000000000 -0500 +++ mozilla/js/src/jsutil.h 2008-04-09 09:55:34.000000000 -0400 @@ -64,6 +64,14 @@ JS_Assert(const char *s, const char *fil #endif /* defined(DEBUG) */ /* + * Compile-time assert. "condition" must be a constant expression. + * The macro can be used only in places where an "extern" declaration is + * allowed. + */ +#define JS_STATIC_ASSERT(condition) \ + extern void js_static_assert(int arg[(condition) ? 1 : -1]) + +/* ** Abort the process in a non-graceful manner. This will cause a core file, ** call to the debugger or other moral equivalent as well as causing the ** entire process to stop. diff -up mozilla/js/src/jsxml.c.411025 mozilla/js/src/jsxml.c --- mozilla/js/src/jsxml.c.411025 2007-04-18 22:22:35.000000000 -0400 +++ mozilla/js/src/jsxml.c 2008-04-09 09:55:34.000000000 -0400 @@ -3086,7 +3086,7 @@ ToAttributeName(JSContext *cx, jsval v) * and blindly untag. Since qn is a GC-thing pointer, we can treat it as * an object pointer. */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(qn), &tvr); + JS_PUSH_TEMP_ROOT_QNAME(cx, qn, &tvr); obj = js_GetAttributeNameObject(cx, qn); JS_POP_TEMP_ROOT(cx, &tvr); if (!obj) @@ -7549,7 +7549,7 @@ js_NewXMLObject(JSContext *cx, JSXMLClas xml = js_NewXML(cx, xml_class); if (!xml) return NULL; - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(xml), &tvr); + JS_PUSH_TEMP_ROOT_XML(cx, xml, &tvr); obj = js_GetXMLObject(cx, xml); JS_POP_TEMP_ROOT(cx, &tvr); return obj;