Avoid integer division in NewGCThing path (503157, r=jwalden).

This commit is contained in:
Andreas Gal 2009-07-14 17:06:09 -07:00
parent 5e2d05e0f0
commit 9f8d42c569
19 changed files with 246 additions and 242 deletions

View File

@ -2650,8 +2650,7 @@ JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
CHECK_REQUEST(cx);
JS_ASSERT((uintN) type < (uintN) (GCX_NTYPES - GCX_EXTERNAL_STRING));
str = (JSString *) js_NewGCThing(cx, (uintN) type + GCX_EXTERNAL_STRING,
sizeof(JSString));
str = js_NewGCString(cx, (uintN) type + GCX_EXTERNAL_STRING);
if (!str)
return NULL;
str->initFlat(chars, length);
@ -2896,7 +2895,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, 0);
return js_NewObject(cx, clasp, proto, parent);
}
JS_PUBLIC_API(JSObject *)
@ -2906,7 +2905,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, 0);
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
}
JS_PUBLIC_API(JSBool)
@ -3064,7 +3063,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, 0);
nobj = js_NewObject(cx, clasp, proto, obj);
if (!nobj)
return NULL;
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
@ -4109,7 +4108,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
JSIdArray *ida;
CHECK_REQUEST(cx);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
if (!iterobj)
return NULL;
@ -4822,12 +4821,12 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
CHECK_REQUEST(cx);
if (!script)
return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
JS_ASSERT(!script->u.object);
JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
if (obj) {
JS_SetPrivate(cx, obj, script);
script->u.object = obj;

View File

@ -3346,7 +3346,7 @@ js_Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* If called without new, replace obj with a new Array object. */
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -3381,7 +3381,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
JS_ASSERT(JS_ON_TRACE(cx));
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
if (!obj)
return NULL;
@ -3442,7 +3442,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector, JSBool holey)
JSTempValueRooter tvr;
JSObject *obj;
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
if (!obj)
return NULL;
@ -3459,7 +3459,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector, JSBool holey)
JSObject *
js_NewSlowArrayObject(JSContext *cx)
{
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
if (obj)
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
return obj;

View File

@ -390,7 +390,7 @@ js_Arguments(JSContext* cx, JSObject* parent, JSObject* cached)
{
if (cached)
return cached;
return js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
return js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
}
JS_DEFINE_CALLINFO_3(extern, OBJECT, js_Arguments, CONTEXT, OBJECT, OBJECT, 0, 0)
@ -404,7 +404,7 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa
JSFunction *fun = (JSFunction*) funobj;
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
JSObject* closure = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
JSObject* closure = js_NewGCObject(cx, GCX_OBJECT);
if (!closure)
return NULL;

View File

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

View File

@ -1729,7 +1729,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
{
JSObject *obj;
obj = js_NewObject(cx, clasp, proto, parent, 0);
obj = js_NewObject(cx, clasp, proto, parent);
if (obj && system)
STOBJ_SET_SYSTEM(obj);
return obj;

View File

@ -709,7 +709,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, 0);
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -1033,7 +1033,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
/* Make the prototype for the current constructor name. */
proto = js_NewObject(cx, &js_ErrorClass,
(i != JSEXN_ERR) ? error_proto : obj_proto,
obj, 0);
obj);
if (!proto)
return NULL;
if (i == JSEXN_ERR) {
@ -1185,7 +1185,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, 0);
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL);
if (!errObject) {
ok = JS_FALSE;
goto out;

View File

@ -259,7 +259,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, 0);
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -386,7 +386,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio
return NULL;
JSObject *wfunobj = js_NewObjectWithGivenProto(cx, &js_FunctionClass,
funobj, scopeChain, 0);
funobj, scopeChain);
if (!wfunobj)
return NULL;
JSAutoTempValueRooter tvr(cx, wfunobj);
@ -880,7 +880,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
JSAtom *lambdaName = (fp->fun->flags & JSFUN_LAMBDA) ? fp->fun->atom : NULL;
if (lambdaName) {
JSObject *env = js_NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,
fp->scopeChain, 0);
fp->scopeChain);
if (!env)
return NULL;
env->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fp);
@ -896,8 +896,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
}
}
callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL,
fp->scopeChain, 0);
callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, fp->scopeChain);
if (!callobj)
return NULL;
@ -1514,8 +1513,7 @@ 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),
0);
proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj));
if (!proto)
return JS_FALSE;
@ -2187,7 +2185,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSTokenType tt;
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -2437,7 +2435,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
OBJ_SET_PARENT(cx, funobj, parent);
} else {
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
if (!funobj)
return NULL;
}
@ -2491,8 +2489,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
* The cloned function object does not need the extra JSFunction members
* beyond JSObject as it points to fun via the private slot.
*/
JSObject *clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,
sizeof(JSObject));
JSObject *clone = js_NewObject(cx, &js_FunctionClass, NULL, parent, sizeof(JSObject));
if (!clone)
return NULL;
clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);

View File

@ -1836,11 +1836,10 @@ IsGCThresholdReached(JSRuntime *rt)
rt->gcBytes >= rt->gcTriggerBytes;
}
void *
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
template <class T> static JS_INLINE T*
NewGCThing(JSContext *cx, uintN flags)
{
JSRuntime *rt;
uintN flindex;
bool doGC;
JSGCThing *thing;
uint8 *flagp;
@ -1863,8 +1862,9 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
JS_ASSERT((flags & GCF_TYPEMASK) != GCX_DOUBLE);
rt = cx->runtime;
nbytes = JS_ROUNDUP(nbytes, sizeof(JSGCThing));
flindex = GC_FREELIST_INDEX(nbytes);
size_t nbytes = sizeof(T);
JS_ASSERT(JS_ROUNDUP(nbytes, sizeof(JSGCThing)) == nbytes);
uintN flindex = GC_FREELIST_INDEX(nbytes);
/* Updates of metering counters here may not be thread-safe. */
METER(astats = &cx->runtime->gcStats.arenaStats[flindex]);
@ -2098,7 +2098,7 @@ testReservedObjects:
if (gcLocked)
JS_UNLOCK_GC(rt);
#endif
return thing;
return (T*)thing;
fail:
#ifdef JS_THREADSAFE
@ -2110,6 +2110,26 @@ fail:
return NULL;
}
extern JSObject* js_NewGCObject(JSContext *cx, uintN flags)
{
return NewGCThing<JSObject>(cx, flags);
}
extern JSString* js_NewGCString(JSContext *cx, uintN flags)
{
return NewGCThing<JSString>(cx, flags);
}
extern JSFunction* js_NewGCFunction(JSContext *cx, uintN flags)
{
return NewGCThing<JSFunction>(cx, flags);
}
extern JSXML* js_NewGCXML(JSContext *cx, uintN flags)
{
return NewGCThing<JSXML>(cx, flags);
}
static JSGCDoubleCell *
RefillDoubleFreeList(JSContext *cx)
{
@ -2303,7 +2323,7 @@ js_ReserveObjects(JSContext *cx, size_t nobjects)
JSObject *&head = JS_TRACE_MONITOR(cx).reservedObjects;
size_t i = head ? JSVAL_TO_INT(head->fslots[1]) : 0;
while (i < nobjects) {
JSObject *obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
JSObject *obj = js_NewGCObject(cx, GCX_OBJECT);
if (!obj)
return JS_FALSE;
memset(obj, 0, sizeof(JSObject));

View File

@ -167,8 +167,17 @@ struct JSGCThing {
* can potentially trigger GC. This will ensure that GC tracing never sees junk
* values stored in the partially initialized thing.
*/
extern void *
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
extern JSObject*
js_NewGCObject(JSContext *cx, uintN flags);
extern JSString*
js_NewGCString(JSContext *cx, uintN flags);
extern JSFunction*
js_NewGCFunction(JSContext *cx, uintN flags);
extern JSXML*
js_NewGCXML(JSContext *cx, uintN flags);
/*
* Allocate a new double jsval and store the result in *vp. vp must be a root.

View File

@ -998,7 +998,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
}
#endif
obj = js_NewObjectWithGivenProto(cx, &js_NoSuchMethodClass,
NULL, NULL, 0);
NULL, NULL);
if (!obj) {
ok = JS_FALSE;
goto out;
@ -1877,7 +1877,7 @@ js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
clasp = fun2->u.n.clasp;
}
}
obj = js_NewObject(cx, clasp, proto, parent, 0);
obj = js_NewObject(cx, clasp, proto, parent);
if (!obj)
return JS_FALSE;
@ -4960,8 +4960,7 @@ js_Interpret(JSContext *cx)
JSVAL_IS_OBJECT(rval)
? JSVAL_TO_OBJECT(rval)
: NULL,
OBJ_GET_PARENT(cx, obj),
0);
OBJ_GET_PARENT(cx, obj));
if (!obj2)
goto error;
vp[1] = OBJECT_TO_JSVAL(obj2);
@ -6372,7 +6371,7 @@ js_Interpret(JSContext *cx)
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
obj = (i == JSProto_Array)
? js_NewArrayObject(cx, 0, NULL)
: js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
: js_NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
goto error;
PUSH_OPND(OBJECT_TO_JSVAL(obj));

View File

@ -388,7 +388,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, 0);
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
if (!iterobj)
goto bad;
@ -705,7 +705,7 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
jsval *slots;
/* After the following return, failing control flow must goto bad. */
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
if (!obj)
return NULL;

View File

@ -2011,29 +2011,6 @@ static JSFunctionSpec object_static_methods[] = {
JS_FS_END
};
JSBool
js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if (argc == 0) {
/* Trigger logic below to construct a blank object. */
obj = NULL;
} else {
/* If argv[0] is null or undefined, obj comes back null. */
if (!js_ValueToObject(cx, argv[0], &obj))
return JS_FALSE;
}
if (!obj) {
JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
if (JS_IsConstructing(cx))
return JS_TRUE;
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
}
*rval = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
static inline bool
InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto,
JSObjectOps* ops)
@ -2085,13 +2062,156 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto,
return false;
}
JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
jsdtrace_object_create_start(cx->fp, clasp);
#endif
/* Assert that the class is a proper class. */
JS_ASSERT_IF(clasp->flags & JSCLASS_IS_EXTENDED,
((JSExtendedClass *)clasp)->equality);
/* Always call the class's getObjectOps hook if it has one. */
JSObjectOps *ops = clasp->getObjectOps
? clasp->getObjectOps(cx, clasp)
: &js_ObjectOps;
/*
* Allocate an object from the GC heap and initialize all its fields before
* doing any operation that can potentially trigger GC. Functions have a
* larger non-standard allocation size.
*/
JSObject* obj;
if (clasp == &js_FunctionClass && !objectSize) {
obj = (JSObject*) js_NewGCFunction(cx, GCX_OBJECT);
#ifdef DEBUG
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
sizeof(JSFunction) - sizeof(JSObject));
#endif
} else {
JS_ASSERT(!objectSize || objectSize == sizeof(JSObject));
obj = js_NewGCObject(cx, GCX_OBJECT);
}
if (!obj)
goto out;
/*
* Set the class slot with the initial value of the system and delegate
* flags set to false.
*/
JS_ASSERT(((jsuword) clasp & 3) == 0);
obj->classword = jsuword(clasp);
JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL((!parent && proto)
? OBJ_GET_PARENT(cx, proto)
: parent);
/* Initialize the remaining fixed slots. */
for (uint32 i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
obj->fslots[i] = JSVAL_VOID;
obj->dslots = NULL;
if (OPS_IS_NATIVE(ops)) {
if (!InitScopeForObject(cx, obj, proto, ops)) {
obj = NULL;
goto out;
}
} else {
JS_ASSERT(ops->objectMap->ops == ops);
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
}
/* Check that the newborn root still holds the object. */
JS_ASSERT_IF(!cx->localRootStack, cx->weakRoots.newborn[GCX_OBJECT] == obj);
/*
* Do not call debug hooks on trace, because we might be in a non-_FAIL
* builtin. See bug 481444.
*/
if (cx->debugHooks->objectHook && !JS_ON_TRACE(cx)) {
JSAutoTempValueRooter tvr(cx, obj);
JS_KEEP_ATOMS(cx->runtime);
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
cx->debugHooks->objectHookData);
JS_UNKEEP_ATOMS(cx->runtime);
cx->weakRoots.newborn[GCX_OBJECT] = obj;
}
out:
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
jsdtrace_object_create(cx, clasp, obj);
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
jsdtrace_object_create_done(cx->fp, clasp);
#endif
return obj;
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize)
{
jsid id;
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
if (!js_GetClassId(cx, clasp, &id))
return NULL;
if (!js_GetClassPrototype(cx, parent, id, &proto))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),
&proto)) {
return NULL;
}
}
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
}
JSBool
js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if (argc == 0) {
/* Trigger logic below to construct a blank object. */
obj = NULL;
} else {
/* If argv[0] is null or undefined, obj comes back null. */
if (!js_ValueToObject(cx, argv[0], &obj))
return JS_FALSE;
}
if (!obj) {
JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
if (JS_IsConstructing(cx))
return JS_TRUE;
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;
}
*rval = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
#ifdef JS_TRACER
static inline JSObject*
NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto, JSObject *parent)
{
JS_ASSERT(JS_ON_TRACE(cx));
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
if (!obj)
return NULL;
@ -2141,7 +2261,7 @@ js_NewInstance(JSContext *cx, JSClass *clasp, JSObject *ctor)
proto = JSVAL_TO_OBJECT(pval);
} else if (pval == JSVAL_HOLE) {
/* No ctor.prototype yet, inline and optimize fun_resolve's prototype code. */
proto = js_NewObject(cx, clasp, NULL, OBJ_GET_PARENT(cx, ctor), 0);
proto = js_NewObject(cx, clasp, NULL, OBJ_GET_PARENT(cx, ctor));
if (!proto)
return NULL;
if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_ENUMERATE | JSPROP_PERMANENT))
@ -2408,7 +2528,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
obj = js_NewObject(cx, &js_WithClass, proto, parent);
if (!obj)
return NULL;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
@ -2424,7 +2544,7 @@ js_NewBlockObject(JSContext *cx)
* scopes and to give the block object its own scope.
*/
JSObject *blockObj = js_NewObjectWithGivenProto(cx, &js_BlockClass,
NULL, NULL, 0);
NULL, NULL);
JS_ASSERT_IF(blockObj, !OBJ_IS_CLONED_BLOCK(blockObj));
return blockObj;
}
@ -2437,7 +2557,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
JS_ASSERT(STOBJ_GET_CLASS(proto) == &js_BlockClass);
JS_ASSERT(!OBJ_IS_CLONED_BLOCK(proto));
clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
clone = js_NewObject(cx, &js_BlockClass, proto, parent);
if (!clone)
return NULL;
STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
@ -2763,7 +2883,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, 0);
proto = js_NewObject(cx, clasp, parent_proto, obj);
if (!proto)
return NULL;
@ -3005,131 +3125,6 @@ js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
return JS_TRUE;
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN objectSize)
{
jsid id;
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
if (!js_GetClassId(cx, clasp, &id))
return NULL;
if (!js_GetClassPrototype(cx, parent, id, &proto))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),
&proto)) {
return NULL;
}
}
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
}
JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, uintN objectSize)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
jsdtrace_object_create_start(cx->fp, clasp);
#endif
/* 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);
}
/* Assert that the class is a proper class. */
JS_ASSERT_IF(clasp->flags & JSCLASS_IS_EXTENDED,
((JSExtendedClass *)clasp)->equality);
/* Always call the class's getObjectOps hook if it has one. */
JSObjectOps *ops = clasp->getObjectOps
? clasp->getObjectOps(cx, clasp)
: &js_ObjectOps;
/*
* Allocate an object from the GC heap and initialize all its fields before
* doing any operation that can potentially trigger GC.
*/
JSObject *obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
if (!obj)
goto out;
/*
* Set the class slot with the initial value of the system and delegate
* flags set to false.
*/
JS_ASSERT(((jsuword) clasp & 3) == 0);
obj->classword = jsuword(clasp);
JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL((!parent && proto)
? OBJ_GET_PARENT(cx, proto)
: parent);
/* Initialize the remaining fixed slots. */
for (uint32 i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
obj->fslots[i] = JSVAL_VOID;
obj->dslots = NULL;
if (OPS_IS_NATIVE(ops)) {
if (!InitScopeForObject(cx, obj, proto, ops)) {
obj = NULL;
goto out;
}
} else {
JS_ASSERT(ops->objectMap->ops == ops);
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
}
#ifdef DEBUG
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
objectSize - sizeof(JSObject));
#endif
/* Check that the newborn root still holds the object. */
JS_ASSERT_IF(!cx->localRootStack, cx->weakRoots.newborn[GCX_OBJECT] == obj);
/*
* Do not call debug hooks on trace, because we might be in a non-_FAIL
* builtin. See bug 481444.
*/
if (cx->debugHooks->objectHook && !JS_ON_TRACE(cx)) {
JSAutoTempValueRooter tvr(cx, obj);
JS_KEEP_ATOMS(cx->runtime);
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
cx->debugHooks->objectHookData);
JS_UNKEEP_ATOMS(cx->runtime);
cx->weakRoots.newborn[GCX_OBJECT] = obj;
}
out:
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
jsdtrace_object_create(cx, clasp, obj);
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
jsdtrace_object_create_done(cx->fp, clasp);
#endif
return obj;
}
JSObject*
js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto, uint32 slot)
{
@ -3137,7 +3132,7 @@ js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto, uint32 slot)
JS_ASSERT(proto->map->ops == &js_ObjectOps);
JS_ASSERT(OBJ_GET_CLASS(cx, proto) == clasp);
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
JSObject* obj = js_NewGCObject(cx, GCX_OBJECT);
if (!obj)
return NULL;
@ -3360,7 +3355,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
proto = JSVAL_TO_OBJECT(rval);
}
obj = js_NewObject(cx, clasp, proto, parent, 0);
obj = js_NewObject(cx, clasp, proto, parent);
if (!obj)
goto out;
@ -5447,7 +5442,7 @@ js_PrimitiveToObject(JSContext *cx, jsval *vp)
JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
JS_ASSERT(!JSVAL_IS_VOID(*vp));
clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
obj = js_NewObject(cx, clasp, NULL, NULL);
if (!obj)
return JS_FALSE;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);

View File

@ -529,18 +529,15 @@ extern JSBool
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN objectSize);
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0);
/*
* 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, uintN objectSize);
JSObject *parent, size_t objectSize = 0);
/*
* Allocate a new native object and initialize all fslots with JSVAL_VOID

View File

@ -609,7 +609,7 @@ js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
if (!InitializeGap(cx, space, &scx.gap))
return JS_FALSE;
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;
@ -714,7 +714,7 @@ static JSBool
Revive(JSContext *cx, jsval reviver, jsval *vp)
{
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;
@ -921,7 +921,7 @@ PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
static JSBool
OpenObject(JSContext *cx, JSONParser *jp)
{
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;

View File

@ -4644,7 +4644,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
return JS_FALSE;
}
if (xdr->mode == JSXDR_DECODE) {
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
if (!obj)
return JS_FALSE;
STOBJ_CLEAR_PARENT(obj);
@ -5012,7 +5012,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, 0);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
if (!obj)
return JS_FALSE;
@ -5068,7 +5068,7 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
re = js_NewRegExp(cx, ts, str, flags, JS_FALSE);
if (!re)
return NULL;
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
if (!obj || !JS_SetPrivate(cx, obj, re)) {
js_DestroyRegExp(cx, re);
obj = NULL;
@ -5085,7 +5085,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, 0);
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
if (!clone)
return NULL;
re = (JSRegExp *) JS_GetPrivate(cx, obj);

View File

@ -919,7 +919,7 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
/* If not constructing, replace obj with a new Script object. */
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
if (!obj)
return JS_FALSE;

View File

@ -2742,7 +2742,7 @@ js_NewString(JSContext *cx, jschar *chars, size_t length)
return NULL;
}
str = (JSString *) js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
str = js_NewGCString(cx, GCX_STRING);
if (!str)
return NULL;
str->initFlat(chars, length);
@ -2776,7 +2776,7 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start,
return js_NewStringCopyN(cx, base->chars() + start, length);
}
ds = (JSString *)js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
ds = js_NewGCString(cx, GCX_STRING);
if (!ds)
return NULL;
if (start == 0)

View File

@ -292,7 +292,7 @@ NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
{
JSObject *obj;
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
if (!obj)
return JS_FALSE;
JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
@ -505,7 +505,7 @@ NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName,
JSObject *obj;
JS_ASSERT(IsQNameClass(clasp));
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
obj = js_NewObject(cx, clasp, NULL, NULL);
if (!obj)
return NULL;
InitXMLQName(obj, uri, prefix, localName);
@ -617,7 +617,7 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
return JS_TRUE;
}
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -724,7 +724,7 @@ QNameHelper(JSContext *cx, JSObject *obj, JSClass *clasp, intN argc,
* Create and return a new QName or AttributeName object exactly as if
* constructed.
*/
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
obj = js_NewObject(cx, clasp, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -7317,19 +7317,6 @@ XMLList(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_TRUE;
}
#define JSXML_LIST_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLListVar))
#define JSXML_ELEMENT_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLElemVar))
#define JSXML_LEAF_SIZE (offsetof(JSXML, u) + sizeof(JSString *))
static size_t sizeof_JSXML[JSXML_CLASS_LIMIT] = {
JSXML_LIST_SIZE, /* JSXML_CLASS_LIST */
JSXML_ELEMENT_SIZE, /* JSXML_CLASS_ELEMENT */
JSXML_LEAF_SIZE, /* JSXML_CLASS_ATTRIBUTE */
JSXML_LEAF_SIZE, /* JSXML_CLASS_PROCESSING_INSTRUCTION */
JSXML_LEAF_SIZE, /* JSXML_CLASS_TEXT */
JSXML_LEAF_SIZE /* JSXML_CLASS_COMMENT */
};
#ifdef DEBUG_notme
JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks);
uint32 xml_serial;
@ -7340,7 +7327,7 @@ js_NewXML(JSContext *cx, JSXMLClass xml_class)
{
JSXML *xml;
xml = (JSXML *) js_NewGCThing(cx, GCX_XML, sizeof_JSXML[xml_class]);
xml = (JSXML *) js_NewGCXML(cx, GCX_XML);
if (!xml)
return NULL;
@ -7478,7 +7465,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
{
JSObject *obj;
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
if (!obj || !JS_SetPrivate(cx, obj, xml)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -7881,7 +7868,7 @@ js_GetAnyName(JSContext *cx, jsval *vp)
do {
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
NULL, 0);
NULL);
if (!obj) {
ok = JS_FALSE;
break;
@ -8178,7 +8165,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
}
filterobj = js_NewObjectWithGivenProto(cx, &js_XMLFilterClass,
NULL, NULL, 0);
NULL, NULL);
if (!filterobj)
return JS_FALSE;

View File

@ -122,15 +122,16 @@ struct JSXML {
JSObject *name;
uint16 xml_class; /* discriminates u, below */
uint16 xml_flags; /* flags, see below */
uint32 align;
union {
JSXMLListVar list;
JSXMLElemVar elem;
JSString *value;
} u;
/* Don't add anything after u -- see js_NewXML for why. */
};
JS_STATIC_ASSERT(JS_ROUNDUP(sizeof(JSXML), sizeof(JSGCThing)) == sizeof(JSXML));
/* union member shorthands */
#define xml_kids u.list.kids
#define xml_target u.list.target