[Bug 423874] Allocating functions together with JSObject. r=brendan a1.9=blocking1.9

This commit is contained in:
igor@mir2.org 2008-04-02 00:46:12 -07:00
Родитель d545086c33
Коммит 5e262850d9
25 изменённых файлов: 240 добавлений и 269 удалений

Просмотреть файл

@ -937,7 +937,6 @@ CountHeap(JSContext *cx, uintN argc, jsval *vp)
{ "object", JSTRACE_OBJECT },
{ "double", JSTRACE_DOUBLE },
{ "string", JSTRACE_STRING },
{ "function", JSTRACE_FUNCTION },
#if JS_HAS_XML_SUPPORT
{ "namespace", JSTRACE_NAMESPACE },
{ "qname", JSTRACE_QNAME },

Просмотреть файл

@ -369,7 +369,7 @@ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
break;
case 'f':
fun = va_arg(ap, JSFunction *);
*sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
*sp = fun ? OBJECT_TO_JSVAL(FUN_OBJECT(fun)) : JSVAL_NULL;
break;
case 'v':
*sp = va_arg(ap, jsval);
@ -2014,10 +2014,6 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
name = "double";
break;
case JSTRACE_FUNCTION:
name = "function";
break;
#if JS_HAS_XML_SUPPORT
case JSTRACE_NAMESPACE:
name = "namespace";
@ -2053,7 +2049,20 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
{
JSObject *obj = (JSObject *)thing;
JSClass *clasp = STOBJ_GET_CLASS(obj);
if (clasp->flags & JSCLASS_HAS_PRIVATE) {
if (clasp == &js_FunctionClass) {
JSFunction *fun = (JSFunction *)
JS_GetPrivate(trc->context, obj);
if (!fun) {
JS_snprintf(buf, bufsize, "<newborn>");
} else if (FUN_OBJECT(fun) != obj) {
JS_snprintf(buf, bufsize, "%p", fun);
} else {
if (fun->atom && ATOM_IS_STRING(fun->atom))
js_PutEscapedString(buf, bufsize,
ATOM_TO_STRING(fun->atom), 0);
}
} else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
void *privateThing = JSVAL_IS_VOID(privateValue)
? NULL
@ -2074,15 +2083,6 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
JS_snprintf(buf, bufsize, "%g", *(jsdouble *)thing);
break;
case JSTRACE_FUNCTION:
{
JSFunction *fun = (JSFunction *)thing;
if (fun->atom && ATOM_IS_STRING(fun->atom))
js_PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0);
break;
}
#if JS_HAS_XML_SUPPORT
case JSTRACE_NAMESPACE:
{
@ -2698,7 +2698,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
}
/* Create a prototype object for this class. */
proto = js_NewObject(cx, clasp, parent_proto, obj);
proto = js_NewObject(cx, clasp, parent_proto, obj, 0);
if (!proto)
return NULL;
@ -2749,7 +2749,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
* different object, as is done for operator new -- and as at least
* XML support requires.
*/
ctor = fun->object;
ctor = FUN_OBJECT(fun);
if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
cval = OBJECT_TO_JSVAL(ctor);
if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
@ -2966,7 +2966,7 @@ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
return js_NewObject(cx, clasp, proto, parent);
return js_NewObject(cx, clasp, proto, parent, 0);
}
JS_PUBLIC_API(JSObject *)
@ -2976,7 +2976,7 @@ JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, 0);
}
JS_PUBLIC_API(JSBool)
@ -3120,7 +3120,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
nobj = js_NewObject(cx, clasp, proto, obj);
nobj = js_NewObject(cx, clasp, proto, obj, 0);
if (!nobj)
return NULL;
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
@ -3999,7 +3999,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
JSIdArray *ida;
CHECK_REQUEST(cx);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
if (!iterobj)
return NULL;
@ -4218,13 +4218,13 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
/* Indicate we cannot clone this object. */
return funobj;
}
return js_CloneFunctionObject(cx, funobj, parent);
return js_CloneFunctionObject(cx, GET_FUNCTION_PRIVATE(cx, funobj), parent);
}
JS_PUBLIC_API(JSObject *)
JS_GetFunctionObject(JSFunction *fun)
{
return fun->object;
return FUN_OBJECT(fun);
}
JS_PUBLIC_API(const char *)
@ -4419,7 +4419,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
* As jsapi.h notes, fs must point to storage that lives as long
* as fun->object lives.
*/
if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
if (!JS_SetReservedSlot(cx, FUN_OBJECT(fun), 0, PRIVATE_TO_JSVAL(fs)))
return JS_FALSE;
}
@ -4635,10 +4635,10 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
JSObject *obj;
if (!script)
return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
if (obj) {
JS_SetPrivate(cx, obj, script);
script->object = obj;
@ -4743,7 +4743,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
goto out2;
/* From this point the control must flow through the label out. */
JS_PUSH_TEMP_ROOT_FUNCTION(cx, fun, &tvr);
JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
for (i = 0; i < nargs; i++) {
argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
if (!argAtom) {
@ -4765,7 +4765,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
if (obj &&
funAtom &&
!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
OBJECT_TO_JSVAL(fun->object),
OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
NULL, NULL, JSPROP_ENUMERATE, NULL)) {
fun = NULL;
}
@ -4782,7 +4782,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
#endif
out:
cx->weakRoots.newborn[JSTRACE_FUNCTION] = fun;
cx->weakRoots.newborn[JSTRACE_OBJECT] = FUN_OBJECT(fun);
JS_POP_TEMP_ROOT(cx, &tvr);
out2:
@ -4974,7 +4974,7 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
JSBool ok;
CHECK_REQUEST(cx);
ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(FUN_OBJECT(fun)), argc, argv,
rval);
LAST_FRAME_CHECKS(cx, ok);
return ok;

Просмотреть файл

@ -2879,7 +2879,7 @@ Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* If called without new, replace obj with a new Array object. */
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -2929,7 +2929,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
JSTempValueRooter tvr;
JSObject *obj;
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
if (!obj)
return NULL;
@ -2946,7 +2946,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
JSObject *
js_NewSlowArrayObject(JSContext *cx)
{
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
if (obj)
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
return obj;

Просмотреть файл

@ -619,9 +619,6 @@ JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(void *));
#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)

Просмотреть файл

@ -2150,7 +2150,7 @@ js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
JSObject *obj;
jsdouble *date;
obj = js_NewObject(cx, &js_DateClass, NULL, NULL);
obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
if (!obj)
return NULL;

Просмотреть файл

@ -697,7 +697,7 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
atom);
if (!wrapper)
return NULL;
return (JSPropertyOp) wrapper->object;
return (JSPropertyOp) FUN_OBJECT(wrapper);
}
JS_PUBLIC_API(JSBool)
@ -995,7 +995,7 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
JSRuntime *rt = cx->runtime;
if (rt->findObjectPrincipals) {
if (fp->fun->object != fp->callee)
if (FUN_OBJECT(fp->fun) != fp->callee)
return rt->findObjectPrincipals(cx, fp->callee);
/* FALL THROUGH */
}
@ -1554,8 +1554,7 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
size_t nbytes;
nbytes = sizeof *fun;
if (fun->object)
nbytes += JS_GetObjectTotalSize(cx, fun->object);
nbytes += JS_GetObjectTotalSize(cx, FUN_OBJECT(fun));
if (FUN_INTERPRETED(fun))
nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
if (fun->atom)
@ -1668,7 +1667,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
{
JSObject *obj;
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (obj && system)
STOBJ_SET_SYSTEM(obj);
return obj;

Просмотреть файл

@ -2053,7 +2053,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
* name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
* in jsinterp.c.
*/
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
fun = (JSFunction *) pn->pn_funpob->object;
if (fun->atom)
*answer = JS_TRUE;
break;
@ -3937,7 +3937,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
#endif
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
fun = (JSFunction *) pn->pn_funpob->object;
if (fun->u.i.script) {
/*
* This second pass is needed to emit JSOP_NOP with a source note

Просмотреть файл

@ -750,7 +750,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
.classPrototypeAtom),
rval))
return JS_FALSE;
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -1044,7 +1044,6 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
for (i = 0; exceptions[i].name != 0; i++) {
JSAtom *atom;
JSFunction *fun;
JSObject *funobj;
JSString *nameString;
int protoIndex = exceptions[i].protoIndex;
@ -1053,7 +1052,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
(protoIndex != JSEXN_NONE)
? protos[protoIndex]
: obj_proto,
obj);
obj, 0);
if (!protos[i])
break;
@ -1069,11 +1068,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
/* Make this constructor make objects of class Exception. */
fun->u.n.clasp = &js_ErrorClass;
/* Extract the constructor object. */
funobj = fun->object;
/* Make the prototype and constructor links. */
if (!js_SetClassPrototype(cx, funobj, protos[i],
if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i],
JSPROP_READONLY | JSPROP_PERMANENT)) {
break;
}
@ -1092,7 +1088,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
}
/* Finally, stash the constructor for later uses. */
if (!js_SetClassObject(cx, obj, exceptions[i].key, funobj))
if (!js_SetClassObject(cx, obj, exceptions[i].key, FUN_OBJECT(fun)))
break;
}
@ -1223,7 +1219,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
goto out;
tv[0] = OBJECT_TO_JSVAL(errProto);
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL);
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);
if (!errObject) {
ok = JS_FALSE;
goto out;

Просмотреть файл

@ -254,7 +254,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
return argsobj;
/* Link the new object to fp so it can get actual argument values. */
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -602,7 +602,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
}
/* Create the call object and link it to its stack frame. */
callobj = js_NewObject(cx, &js_CallClass, NULL, parent);
callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
if (!callobj || !JS_SetPrivate(cx, callobj, fp)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -1076,7 +1076,6 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
return JS_TRUE;
fun = GET_FUNCTION_PRIVATE(cx, obj);
JS_ASSERT(fun->object);
/*
* No need to reflect fun.prototype in 'fun.prototype = ... '.
@ -1112,8 +1111,8 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
* Make the prototype object to have the same parent as the function
* object itself.
*/
proto = js_NewObject(cx, &js_ObjectClass, NULL,
OBJ_GET_PARENT(cx, obj));
proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj),
0);
if (!proto)
return JS_FALSE;
@ -1198,15 +1197,15 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
if (!fun)
return JS_FALSE;
STOBJ_SET_PARENT(fun->object, NULL);
STOBJ_SET_PROTO(fun->object, NULL);
STOBJ_SET_PARENT(FUN_OBJECT(fun), NULL);
STOBJ_SET_PROTO(FUN_OBJECT(fun), NULL);
#ifdef __GNUC__
nvars = nargs = 0; /* quell GCC uninitialized warning */
#endif
}
/* From here on, control flow must flow through label out. */
JS_PUSH_TEMP_ROOT_OBJECT(cx, fun->object, &tvr);
JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
ok = JS_TRUE;
if (!JS_XDRUint32(xdr, &nullAtom))
@ -1226,7 +1225,8 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
}
/* do arguments and local vars */
if (fun->object && (n = nargs + nvars) != 0) {
n = nargs + nvars;
if (n != 0) {
void *mark;
uintN i;
uintN bitmapLength;
@ -1326,7 +1326,7 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
goto bad;
if (xdr->mode == JSXDR_DECODE) {
*objp = fun->object;
*objp = FUN_OBJECT(fun);
#ifdef CHECK_SCRIPT_OWNER
fun->u.i.script->owner = NULL;
#endif
@ -1378,6 +1378,12 @@ fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
}
static void
TraceLocalNames(JSTracer *trc, JSFunction *fun);
static void
DestroyLocalNames(JSContext *cx, JSFunction *fun);
static void
fun_trace(JSTracer *trc, JSObject *obj)
{
@ -1385,8 +1391,42 @@ fun_trace(JSTracer *trc, JSObject *obj)
/* A newborn function object may have a not yet initialized private slot. */
fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
if (fun)
JS_CALL_TRACER(trc, fun, JSTRACE_FUNCTION, "private");
if (!fun)
return;
if (FUN_OBJECT(fun) != obj) {
/* obj is cloned function object, trace the original. */
JS_CALL_TRACER(trc, FUN_OBJECT(fun), JSTRACE_OBJECT, "private");
return;
}
if (fun->atom)
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_TraceScript(trc, fun->u.i.script);
TraceLocalNames(trc, fun);
}
}
static void
fun_finalize(JSContext *cx, JSObject *obj)
{
JSFunction *fun;
/* Ignore newborn and cloned function objects. */
fun = (JSFunction *) JS_GetPrivate(cx, obj);
if (!fun || FUN_OBJECT(fun) != obj)
return;
/*
* Null-check of u.i.script is required since the parser sets interpreted
* very early.
*/
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_DestroyScript(cx, fun->u.i.script);
DestroyLocalNames(cx, fun);
}
}
static uint32
@ -1418,7 +1458,7 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
JS_PropertyStub, JS_PropertyStub,
fun_getProperty, JS_PropertyStub,
fun_enumerate, (JSResolveOp)fun_resolve,
fun_convert, JS_FinalizeStub,
fun_convert, fun_finalize,
NULL, NULL,
NULL, NULL,
fun_xdrObject, fun_hasInstance,
@ -1721,20 +1761,19 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fp = cx->fp;
if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
} else {
/*
* The constructor is called before the private slot is initialized so
* we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
*/
if (JS_GetPrivate(cx, obj))
return JS_TRUE;
}
/*
* The constructor is called before the private slot is initialized so we
* must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
*/
fun = (JSFunction *) JS_GetPrivate(cx, obj);
if (fun)
return JS_TRUE;
/*
* NB: (new Function) is not lexically closed by its caller, it's just an
* anonymous function in the top-level scope that its constructor inhabits.
@ -1988,30 +2027,19 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom)
{
JSFunction *fun;
JSTempValueRooter tvr;
/* If funobj is null, allocate an object for it. */
if (funobj) {
JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
OBJ_SET_PARENT(cx, funobj, parent);
} else {
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
if (!funobj)
return NULL;
}
/* Protect fun from any potential GC callback. */
JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(funobj), &tvr);
/*
* Allocate fun after allocating funobj so allocations in js_NewObject
* and hooks called from it do not wipe out fun from newborn[GCX_FUNCTION].
*/
fun = (JSFunction *) js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSFunction));
if (!fun)
goto out;
JS_ASSERT(funobj->fslots[JSSLOT_PRIVATE] == JSVAL_VOID);
fun = (JSFunction *) funobj;
/* Initialize all function members. */
fun->object = NULL;
fun->nargs = nargs;
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
if (flags & JSFUN_INTERPRETED) {
@ -2031,75 +2059,26 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
}
fun->atom = atom;
/* Link fun to funobj and vice versa. */
if (!js_LinkFunctionObject(cx, fun, funobj)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
fun = NULL;
}
out:
JS_POP_TEMP_ROOT(cx, &tvr);
/* Set private to self to indicate non-cloned fully initialized function. */
FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
return fun;
}
static void
TraceLocalNames(JSTracer *trc, JSFunction *fun);
void
js_TraceFunction(JSTracer *trc, JSFunction *fun)
{
if (fun->object)
JS_CALL_OBJECT_TRACER(trc, fun->object, "object");
if (fun->atom)
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_TraceScript(trc, fun->u.i.script);
TraceLocalNames(trc, fun);
}
}
static void
DestroyLocalNames(JSContext *cx, JSFunction *fun);
void
js_FinalizeFunction(JSContext *cx, JSFunction *fun)
{
/*
* Null-check of i.script is required since the parser sets interpreted
* very early.
*/
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_DestroyScript(cx, fun->u.i.script);
DestroyLocalNames(cx, fun);
}
}
JSObject *
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
{
JSObject *newfunobj;
JSFunction *fun;
JSObject *clone;
JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
if (!newfunobj)
/*
* The cloned function object does not need the extra fields beyond
* JSObject as it points to fun via the private slot.
*/
clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,
sizeof(JSObject));
if (!clone)
return NULL;
fun = GET_FUNCTION_PRIVATE(cx, funobj);
if (!js_LinkFunctionObject(cx, fun, newfunobj)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
}
return newfunobj;
}
JSBool
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *funobj)
{
if (!fun->object)
fun->object = funobj;
return JS_SetPrivate(cx, funobj, fun);
clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
return clone;
}
JSFunction *
@ -2114,7 +2093,7 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
return NULL;
gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
OBJECT_TO_JSVAL(fun->object),
OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
gsop, gsop,
attrs & ~JSFUN_FLAGS_MASK, NULL)) {
return NULL;
@ -2153,7 +2132,6 @@ JSObject *
js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
{
JSFunction *fun;
JSObject *funobj;
JSStackFrame *caller;
JSPrincipals *principals;
@ -2163,8 +2141,7 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
fun = js_ValueToFunction(cx, vp, flags);
if (!fun)
return NULL;
funobj = fun->object;
*vp = OBJECT_TO_JSVAL(funobj);
*vp = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
caller = JS_GetScriptedCaller(cx, cx->fp);
if (caller) {
@ -2174,13 +2151,13 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
principals = NULL;
}
if (!js_CheckPrincipalsAccess(cx, funobj, principals,
if (!js_CheckPrincipalsAccess(cx, FUN_OBJECT(fun), principals,
fun->atom
? fun->atom
: cx->runtime->atomState.anonymousAtom)) {
return NULL;
}
return funobj;
return FUN_OBJECT(fun);
}
JSObject *

Просмотреть файл

@ -44,6 +44,7 @@
*/
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsobj.h"
JS_BEGIN_EXTERN_C
@ -63,7 +64,7 @@ typedef union JSLocalNames {
} JSLocalNames;
struct JSFunction {
JSObject *object; /* back-pointer to GC'ed object header */
JSObject object; /* GC'ed object header */
uint16 nargs; /* maximum number of specified arguments,
reflected as f.length/f.arity */
uint16 flags; /* bound method and other flags, see jsapi.h */
@ -90,6 +91,7 @@ struct JSFunction {
#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
#define FUN_OBJECT(fun) (&(fun)->object)
#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
#define FUN_SLOW_NATIVE(fun) (!((fun)->flags & JSFUN_SCRIPT_OR_FAST_NATIVE))
#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
@ -107,19 +109,20 @@ extern JS_FRIEND_DATA(JSClass) js_CallClass;
/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
#define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
/*
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
*/
#define VALUE_IS_FUNCTION(cx, v) \
(!JSVAL_IS_PRIMITIVE(v) && \
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
(!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
/*
* Macro to access the private slot of the function object after the slot is
* initialized.
*/
#define GET_FUNCTION_PRIVATE(cx, funobj) \
(JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass), \
(JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
(JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
extern JSObject *
@ -142,7 +145,7 @@ extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent);
extern JSBool
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);

Просмотреть файл

@ -2250,10 +2250,6 @@ JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
JS_CALL_STRING_TRACER(trc, JSSTRDEP_BASE(str), "base");
break;
case JSTRACE_FUNCTION:
js_TraceFunction(trc, (JSFunction *)thing);
break;
#if JS_HAS_XML_SUPPORT
case JSTRACE_NAMESPACE:
js_TraceXMLNamespace(trc, (JSXMLNamespace *)thing);
@ -2728,7 +2724,6 @@ TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr)
"newborn object",
"newborn double",
"newborn string",
"newborn function",
"newborn namespace",
"newborn qname",
"newborn xml"
@ -3327,9 +3322,6 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
case GCX_DOUBLE:
/* Do nothing. */
break;
case GCX_FUNCTION:
js_FinalizeFunction(cx, (JSFunction *) thing);
break;
#if JS_HAS_XML_SUPPORT
case GCX_NAMESPACE:
js_FinalizeXMLNamespace(cx,

Просмотреть файл

@ -52,15 +52,14 @@ JS_BEGIN_EXTERN_C
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
#define JSTRACE_FUNCTION 3
#define JSTRACE_NAMESPACE 4
#define JSTRACE_QNAME 5
#define JSTRACE_XML 6
#define JSTRACE_NAMESPACE 3
#define JSTRACE_QNAME 4
#define JSTRACE_XML 5
/*
* One past the maximum trace kind.
*/
#define JSTRACE_LIMIT 7
#define JSTRACE_LIMIT 6
/*
* We use the trace kinds as the types for all GC things except external
@ -69,7 +68,6 @@ JS_STATIC_ASSERT(JSTRACE_STRING == 2);
#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
#define GCX_STRING JSTRACE_STRING /* JSString */
#define GCX_FUNCTION JSTRACE_FUNCTION /* JSFunction */
#define GCX_NAMESPACE JSTRACE_NAMESPACE /* JSXMLNamespace */
#define GCX_QNAME JSTRACE_QNAME /* JSXMLQName */
#define GCX_XML JSTRACE_XML /* JSXML */
@ -235,14 +233,14 @@ js_IsAboutToBeFinalized(JSContext *cx, void *thing);
#if JS_HAS_XML_SUPPORT
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_XML)
#else
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_FUNCTION)
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
#endif
/*
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_FUNCTION is the last non-xml
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
* trace kind when JS_HAS_XML_SUPPORT is false.
*/
JS_STATIC_ASSERT(JSTRACE_FUNCTION + 1 == JSTRACE_NAMESPACE);
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_NAMESPACE);
/*
* Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as

Просмотреть файл

@ -931,7 +931,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
vp[0] = ID_TO_VALUE(id);
}
#endif
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL);
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL, 0);
if (!obj) {
ok = JS_FALSE;
goto out;
@ -1600,7 +1600,9 @@ js_ImportProperty(JSContext *cx, JSObject *obj, jsid id)
goto out;
if (VALUE_IS_FUNCTION(cx, value)) {
funobj = JSVAL_TO_OBJECT(value);
closure = js_CloneFunctionObject(cx, funobj, obj);
closure = js_CloneFunctionObject(cx,
GET_FUNCTION_PRIVATE(cx, funobj),
obj);
if (!closure) {
ok = JS_FALSE;
goto out;
@ -1839,7 +1841,7 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
clasp = fun2->u.n.clasp;
}
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (!obj)
return JS_FALSE;
@ -2546,10 +2548,7 @@ js_Interpret(JSContext *cx)
JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)
#define LOAD_FUNCTION(PCOFF) \
JS_BEGIN_MACRO \
LOAD_OBJECT(PCOFF); \
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_FunctionClass); \
JS_END_MACRO
JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
/*
* Prepare to call a user-supplied branch handler, and abort the script
@ -5586,8 +5585,9 @@ interrupt:
* have seen the right parent already and created a sufficiently
* well-scoped function object.
*/
obj = FUN_OBJECT(fun);
if (OBJ_GET_PARENT(cx, obj) != obj2) {
obj = js_CloneFunctionObject(cx, obj, obj2);
obj = js_CloneFunctionObject(cx, fun, obj2);
if (!obj)
goto error;
}
@ -5605,7 +5605,6 @@ interrupt:
* and setters do not need a slot, their value is stored elsewhere
* in the property itself, not in obj slots.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
flags = JSFUN_GSFLAG2ATTR(fun->flags);
if (flags) {
attrs |= flags | JSPROP_SHARED;
@ -5670,7 +5669,7 @@ interrupt:
if (!parent)
goto error;
obj = js_CloneFunctionObject(cx, obj, parent);
obj = js_CloneFunctionObject(cx, fun, parent);
if (!obj)
goto error;
@ -5685,8 +5684,9 @@ interrupt:
parent = js_GetScopeChain(cx, fp);
if (!parent)
goto error;
obj = FUN_OBJECT(fun);
if (OBJ_GET_PARENT(cx, obj) != parent) {
obj = js_CloneFunctionObject(cx, obj, parent);
obj = js_CloneFunctionObject(cx, fun, parent);
if (!obj)
goto error;
}
@ -5694,11 +5694,11 @@ interrupt:
END_CASE(JSOP_ANONFUNOBJ)
BEGIN_CASE(JSOP_NAMEDFUNOBJ)
/* ECMA ed. 3 FunctionExpression: function Identifier [etc.]. */
LOAD_FUNCTION(0);
rval = OBJECT_TO_JSVAL(obj);
/*
* ECMA ed. 3 FunctionExpression: function Identifier [etc.].
*
* 1. Create a new object as if by the expression new Object().
* 2. Add Result(1) to the front of the scope chain.
*
@ -5709,7 +5709,7 @@ interrupt:
obj2 = js_GetScopeChain(cx, fp);
if (!obj2)
goto error;
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2);
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2, 0);
if (!parent)
goto error;
@ -5719,16 +5719,10 @@ interrupt:
* that was parsed by the compiler into a Function object, and
* saved in the script's atom map].
*
* Protect parent from GC after js_CloneFunctionObject calls into
* js_NewObject, which displaces the newborn object root in cx by
* allocating the clone, then runs a last-ditch GC while trying
* to allocate the clone's slots vector. Another, multi-threaded
* path: js_CloneFunctionObject => js_NewObject => OBJ_GET_CLASS
* which may suspend the current request in ClaimScope, with the
* newborn displaced as in the first scenario.
* Protect parent from the GC.
*/
fp->scopeChain = parent;
obj = js_CloneFunctionObject(cx, JSVAL_TO_OBJECT(rval), parent);
obj = js_CloneFunctionObject(cx, fun, parent);
if (!obj)
goto error;
@ -5745,7 +5739,6 @@ interrupt:
* name is [fun->atom, the identifier parsed by the compiler],
* value is Result(3), and attributes are { DontDelete, ReadOnly }.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
attrs = JSFUN_GSFLAG2ATTR(fun->flags);
if (attrs) {
attrs |= JSPROP_SHARED;
@ -5912,7 +5905,7 @@ interrupt:
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
obj = (i == JSProto_Array)
? js_NewArrayObject(cx, 0, NULL)
: js_NewObject(cx, &js_ObjectClass, NULL, NULL);
: js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
if (!obj)
goto error;
PUSH_OPND(OBJECT_TO_JSVAL(obj));

Просмотреть файл

@ -400,7 +400,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
* we use the parent slot to keep track of the iterable, we must
* fix it up after.
*/
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL, 0);
if (!iterobj)
goto bad;
@ -725,7 +725,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
jsval *newsp;
/* After the following return, failing control flow must goto bad. */
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
if (!obj)
return NULL;

Просмотреть файл

@ -1759,7 +1759,7 @@ Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
if (cx->fp->flags & JSFRAME_CONSTRUCTING)
return JS_TRUE;
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
}
@ -1900,7 +1900,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
obj = js_NewObject(cx, &js_WithClass, proto, parent);
obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
if (!obj)
return NULL;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
@ -1919,7 +1919,7 @@ js_NewBlockObject(JSContext *cx)
* scopes. Make sure obj has its own scope too, since clearing proto does
* not affect OBJ_SCOPE(obj).
*/
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL);
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL, 0);
if (!obj)
return NULL;
JS_LOCK_OBJ(cx, obj);
@ -1937,7 +1937,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
{
JSObject *clone;
clone = js_NewObject(cx, &js_BlockClass, proto, parent);
clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
if (!clone)
return NULL;
STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
@ -2423,7 +2423,8 @@ js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN objectSize)
{
jsid id;
@ -2440,12 +2441,12 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
}
}
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
}
JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent)
JSObject *parent, uintN objectSize)
{
JSObject *obj;
JSObjectOps *ops;
@ -2459,24 +2460,25 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
jsdtrace_object_create_start(cx->fp, clasp);
#endif
/* Always call the class's getObjectOps hook if it has one. */
ops = clasp->getObjectOps
? clasp->getObjectOps(cx, clasp)
: &js_ObjectOps;
/* Currently only functions can have non-standard allocation size. */
if (clasp == &js_FunctionClass) {
if (objectSize == 0)
objectSize = sizeof(JSFunction);
else
JS_ASSERT(objectSize == sizeof(JSObject));
} else {
JS_ASSERT(objectSize == 0);
objectSize = sizeof(JSObject);
}
/*
* Allocate a zeroed object from the GC heap. Do this *after* any other
* GC-thing allocations under js_GetClassPrototype or clasp->getObjectOps,
* to avoid displacing the newborn root for obj.
* Allocate an object from the GC heap and initialize all its fields before
* doing any operation that can potentially trigger GC.
*/
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
if (!obj)
goto earlybad;
/*
* Initialize all JSObject fields before doing any operation that can
* potentially trigger GC.
*/
obj->map = NULL;
obj->dslots = NULL;
@ -2496,6 +2498,11 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
for (i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
obj->fslots[i] = JSVAL_VOID;
#ifdef DEBUG
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
objectSize - sizeof(JSObject));
#endif
/*
* Root obj to prevent it from being collected out from under this call to
* js_NewObject. There's a possibilty of GC under the objectHook call-out
@ -2503,11 +2510,16 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
*/
JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
/* Always call the class's getObjectOps hook if it has one. */
ops = clasp->getObjectOps
? clasp->getObjectOps(cx, clasp)
: &js_ObjectOps;
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
if (!parent && proto)
if (proto && !parent)
STOBJ_SET_PARENT(obj, OBJ_GET_PARENT(cx, proto));
/*
@ -2771,7 +2783,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
proto = JSVAL_TO_OBJECT(rval);
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (!obj)
goto out;
@ -4656,7 +4668,7 @@ js_PrimitiveToObject(JSContext *cx, jsval *vp)
JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
JS_ASSERT(*vp != JSVAL_VOID);
clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
obj = js_NewObject(cx, clasp, NULL, NULL);
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);

Просмотреть файл

@ -425,14 +425,18 @@ extern JSBool
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN objectSize);
/*
* See jsapi.h, JS_NewObjectWithGivenProto.
*
* objectSize is either the explicit size for the allocated object or 0
* indicating to use the default size based on object's class.
*/
extern JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent);
JSObject *parent, uintN objectSize);
/*
* Fast access to immutable standard objects (constructors and prototypes).

Просмотреть файл

@ -1700,7 +1700,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
GET_OBJECT_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
#define LOAD_FUNCTION(PCOFF) \
GET_FUNCTION_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
GET_FUNCTION_FROM_BYTECODE(jp->script, pc, PCOFF, fun)
#define LOAD_REGEXP(PCOFF) \
GET_REGEXP_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
@ -2016,11 +2016,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
break;
case SRC_FUNCDEF:
JS_GET_SCRIPT_OBJECT(jp->script, js_GetSrcNoteOffset(sn, 0),
obj);
JS_GET_SCRIPT_FUNCTION(jp->script,
js_GetSrcNoteOffset(sn, 0),
fun);
do_function:
js_puts(jp, "\n");
fun = GET_FUNCTION_PRIVATE(cx, obj);
jp2 = JS_NEW_PRINTER(cx, "nested_function", fun,
jp->indent, jp->pretty);
if (!jp2)
@ -3767,8 +3767,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
SprintStack ss2;
LOAD_FUNCTION(0);
fun = GET_FUNCTION_PRIVATE(cx, obj);
LOCAL_ASSERT(FUN_INTERPRETED(fun));
inner = fun->u.i.script;
/*
@ -3884,7 +3882,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
* parenthesization without confusing getter/setter code
* that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
if (!(fun->flags & JSFUN_EXPR_CLOSURE))
indent |= JS_IN_GROUP_CONTEXT;
str = JS_DecompileFunction(cx, fun, indent);

Просмотреть файл

@ -332,10 +332,10 @@ js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
JS_GET_SCRIPT_OBJECT((script), index_, obj); \
JS_END_MACRO
#define GET_FUNCTION_FROM_BYTECODE(script, pc, pcoff, obj) \
#define GET_FUNCTION_FROM_BYTECODE(script, pc, pcoff, fun) \
JS_BEGIN_MACRO \
GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj); \
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_FunctionClass); \
uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
JS_GET_SCRIPT_FUNCTION((script), index_, fun); \
JS_END_MACRO
#define GET_REGEXP_FROM_BYTECODE(script, pc, pcoff, obj) \

Просмотреть файл

@ -1063,12 +1063,12 @@ NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
JSFunction *fun;
JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
parent = (tc->flags & TCF_IN_FUNCTION) ? tc->fun->object : cx->fp->varobj;
parent = (tc->flags & TCF_IN_FUNCTION) ? FUN_OBJECT(tc->fun) : cx->fp->varobj;
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
parent, atom);
if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
STOBJ_SET_PARENT(fun->object, NULL);
STOBJ_SET_PROTO(fun->object, NULL);
STOBJ_SET_PARENT(FUN_OBJECT(fun), NULL);
STOBJ_SET_PROTO(FUN_OBJECT(fun), NULL);
}
return fun;
}
@ -1191,7 +1191,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
* Create wrapping box for fun->object early to protect against a
* last-ditch GC.
*/
funpob = js_NewParsedObjectBox(cx, tc->parseContext, fun->object);
funpob = js_NewParsedObjectBox(cx, tc->parseContext, FUN_OBJECT(fun));
if (!funpob)
return NULL;
@ -4293,7 +4293,7 @@ GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
lambda->pn_op = JSOP_ANONFUNOBJ;
lambda->pn_pos.begin = body->pn_pos.begin;
lambda->pn_funpob = js_NewParsedObjectBox(cx, tc->parseContext,
fun->object);
FUN_OBJECT(fun));
if (!lambda->pn_funpob)
return NULL;
lambda->pn_body = body;

Просмотреть файл

@ -237,7 +237,6 @@ typedef union JSTempValueUnion {
jsval value;
JSObject *object;
JSString *string;
JSFunction *function;
JSXML *xml;
JSXMLQName *qname;
JSTempValueTrace trace;

Просмотреть файл

@ -3868,7 +3868,7 @@ regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
return JS_FALSE;
}
if (xdr->mode == JSXDR_DECODE) {
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
STOBJ_SET_PARENT(obj, NULL);
@ -4236,7 +4236,7 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Otherwise, replace obj with a new RegExp object. */
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
@ -4296,7 +4296,7 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
if (!re)
return NULL;
JS_PUSH_TEMP_ROOT_STRING(cx, str, &tvr);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, re)) {
js_DestroyRegExp(cx, re);
obj = NULL;
@ -4314,7 +4314,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
JSRegExp *re;
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent, 0);
if (!clone)
return NULL;
re = (JSRegExp *) JS_GetPrivate(cx, obj);

Просмотреть файл

@ -1692,7 +1692,6 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
uintN
js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
{
JSObject *obj;
JSFunction *fun;
uintN lineno;
ptrdiff_t offset, target;
@ -1710,9 +1709,7 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
if (js_CodeSpec[*pc].format & JOF_INDEXBASE)
pc += js_CodeSpec[*pc].length;
if (*pc == JSOP_DEFFUN) {
GET_FUNCTION_FROM_BYTECODE(script, pc, 0, obj);
fun = GET_FUNCTION_PRIVATE(cx, obj);
JS_ASSERT(FUN_INTERPRETED(fun));
GET_FUNCTION_FROM_BYTECODE(script, pc, 0, fun);
return fun->u.i.script->lineno;
}

Просмотреть файл

@ -140,6 +140,17 @@ struct JSScript {
(obj) = objects_->vector[(index)]; \
JS_END_MACRO
#define JS_GET_SCRIPT_FUNCTION(script, index, fun) \
JS_BEGIN_MACRO \
JSObject *funobj_; \
\
JS_GET_SCRIPT_OBJECT(script, index, funobj_); \
JS_ASSERT(HAS_FUNCTION_CLASS(funobj_)); \
JS_ASSERT(funobj_ == (JSObject *) STOBJ_GET_PRIVATE(funobj_)); \
(fun) = (JSFunction *) funobj_; \
JS_ASSERT(FUN_INTERPRETED(fun)); \
JS_END_MACRO
#define JS_GET_SCRIPT_REGEXP(script, index, obj) \
JS_BEGIN_MACRO \
JSObjectArray *regexps_ = JS_SCRIPT_REGEXPS(script); \

Просмотреть файл

@ -331,7 +331,7 @@ js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns)
JS_ASSERT(JS_GetPrivate(cx, obj) == ns);
return obj;
}
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, ns)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -607,7 +607,7 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
JS_ASSERT(JS_GetPrivate(cx, obj) == qn);
return obj;
}
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -632,7 +632,7 @@ js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
return NULL;
}
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -748,7 +748,7 @@ Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Create and return a new QName object exactly as if constructed. */
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -856,7 +856,7 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
*/
obj = js_NewObject(cx,
JS_ValueToFunction(cx, argv[-2])->u.n.clasp,
NULL, NULL);
NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -7584,7 +7584,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
{
JSObject *obj;
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, xml)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -7713,7 +7713,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
if (!fun)
return NULL;
if (!js_SetClassPrototype(cx, fun->object, proto,
if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
JSPROP_READONLY | JSPROP_PERMANENT)) {
return NULL;
}
@ -7997,7 +7997,8 @@ js_GetAnyName(JSContext *cx, jsval *vp)
break;
}
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL, NULL);
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
ok = JS_FALSE;
@ -8311,7 +8312,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
return JS_FALSE;
}
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL);
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL, 0);
if (!filterobj)
return JS_FALSE;

Просмотреть файл

@ -533,13 +533,9 @@ nsXPConnect::Collect()
return gCollected;
}
// JSTRACE_FUNCTION can hold on to a lot of objects, adding it to the cycle
// collector reduces the number of edges to those objects.
// JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to
// the cycle collector avoids stack overflow.
#define ADD_TO_CC(_kind) \
((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_FUNCTION || \
(_kind) == JSTRACE_XML)
#define ADD_TO_CC(_kind) ((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_XML)
#ifdef DEBUG_CC
struct NoteJSRootTracer : public JSTracer