Bug 411025: temp rooting implemenation cleanup, r,a=brendan

This commit is contained in:
igor@mir2.org 2008-01-19 16:46:37 -08:00
parent 4475a39348
commit 70aa979d4f
4 changed files with 70 additions and 109 deletions

View File

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

View File

@ -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_<KIND>(cx, NULL, &tvr). Then &tvr.u.<kind> 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.<gcthing> 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. */

View File

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

View File

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