Inline the object allocation path (558003, r=sayrer).

This commit is contained in:
Andreas Gal 2010-04-10 16:16:35 -07:00
Родитель ca72207125
Коммит 3799de9f75
16 изменённых файлов: 249 добавлений и 249 удалений

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

@ -89,6 +89,7 @@
#include "jsatominlines.h"
#include "jsscopeinlines.h"
#include "jsobjinlines.h"
#if JS_HAS_XML_SUPPORT
#include "jsxml.h"
@ -2735,7 +2736,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 NewObject(cx, clasp, proto, parent);
}
JS_PUBLIC_API(JSObject *)
@ -2745,7 +2746,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 NewObjectWithGivenProto(cx, clasp, proto, parent);
}
JS_PUBLIC_API(JSBool)
@ -2901,7 +2902,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 = NewObject(cx, clasp, proto, obj);
if (!nobj)
return NULL;
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
@ -3944,7 +3945,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
JSIdArray *ida;
CHECK_REQUEST(cx);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
iterobj = NewObject(cx, &prop_iter_class, NULL, obj);
if (!iterobj)
return NULL;
@ -4615,14 +4616,14 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
CHECK_REQUEST(cx);
if (!script)
return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
return NewObject(cx, &js_ScriptClass, NULL, NULL);
JS_ASSERT(!script->u.object);
{
AutoScriptRooter root(cx, script);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
obj = NewObject(cx, &js_ScriptClass, NULL, NULL);
if (obj) {
obj->setPrivate(script);
script->u.object = obj;

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

@ -3322,7 +3322,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);
obj = NewObject(cx, &js_ArrayClass, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -3418,7 +3418,7 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
JSObject *
js_NewArrayObject(JSContext *cx, jsuint length, const jsval *vector, bool holey)
{
JSObject *obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
JSObject *obj = NewObject(cx, &js_ArrayClass, NULL, NULL);
if (!obj)
return NULL;
@ -3442,7 +3442,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, const jsval *vector, bool holey)
JSObject *
js_NewSlowArrayObject(JSContext *cx)
{
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
JSObject *obj = NewObject(cx, &js_SlowArrayClass, NULL, NULL);
if (obj)
obj->setArrayLength(0);
return obj;

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

@ -71,6 +71,8 @@
#include "jsobj.h"
#include "jsstr.h"
#include "jsobjinlines.h"
using namespace js;
/*
@ -2385,7 +2387,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
JS_FRIEND_API(JSObject *)
js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
{
JSObject *obj = js_NewObject(cx, &js_DateClass, NULL, NULL);
JSObject *obj = NewObject(cx, &js_DateClass, NULL, NULL);
if (!obj || !SetUTCTime(cx, obj, msec_time))
return NULL;
return obj;

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

@ -1798,7 +1798,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
{
JSObject *obj;
obj = js_NewObject(cx, clasp, proto, parent);
obj = NewObject(cx, clasp, proto, parent);
if (obj && system)
obj->setSystem();
return obj;

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

@ -63,6 +63,8 @@
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jsobjinlines.h"
using namespace js;
/* Forward declarations for js_ErrorClass's initializer. */
@ -693,7 +695,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
* called as functions, without operator new. But as we do not give
* each constructor a distinct JSClass, whose .name member is used by
* js_NewObject to find the class prototype, we must get the class
* NewObject to find the class prototype, we must get the class
* prototype ourselves.
*/
if (!JSVAL_TO_OBJECT(argv[-2])->getProperty(cx,
@ -702,7 +704,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
rval)) {
return JS_FALSE;
}
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
obj = NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -977,11 +979,11 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
* If lazy class initialization occurs for any Error subclass, then all
* classes are initialized, starting with Error. To avoid reentry and
* redundant initialization, we must not pass a null proto parameter to
* js_NewObject below, when called for the Error superclass. We need to
* NewObject below, when called for the Error superclass. We need to
* ensure that Object.prototype is the proto of Error.prototype.
*
* See the equivalent code to ensure that parent_proto is non-null when
* JS_InitClass calls js_NewObject, in jsapi.c.
* JS_InitClass calls NewObject, in jsapi.c.
*/
if (!js_GetClassPrototype(cx, obj, JSProto_Object, &obj_proto))
return NULL;
@ -1001,9 +1003,9 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
JSFunction *fun;
/* Make the prototype for the current constructor name. */
proto = js_NewObject(cx, &js_ErrorClass,
(i != JSEXN_ERR) ? error_proto : obj_proto,
obj);
proto = NewObject(cx, &js_ErrorClass,
(i != JSEXN_ERR) ? error_proto : obj_proto,
obj);
if (!proto)
return NULL;
if (i == JSEXN_ERR) {
@ -1157,7 +1159,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 = NewObject(cx, &js_ErrorClass, errProto, NULL);
if (!errObject) {
ok = JS_FALSE;
goto out;

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

@ -247,7 +247,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
/*
* Give arguments an intrinsic scope chain link to fp's global object.
* Since the arguments object lacks a prototype because js_ArgumentsClass
* is not initialized, js_NewObject won't assign a default parent to it.
* is not initialized, NewObject won't assign a default parent to it.
*
* Therefore if arguments is used as the head of an eval scope chain (via
* a direct or indirect call to eval(program, arguments)), any reference
@ -349,8 +349,8 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio
if (!scopeChain)
return NULL;
JSObject *wfunobj = js_NewObjectWithGivenProto(cx, &js_FunctionClass,
funobj, scopeChain);
JSObject *wfunobj = NewObjectWithGivenProto(cx, &js_FunctionClass,
funobj, scopeChain);
if (!wfunobj)
return NULL;
AutoValueRooter tvr(cx, wfunobj);
@ -788,7 +788,7 @@ CalleeGetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
static JSObject *
NewCallObject(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
{
JSObject *callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, scopeChain);
JSObject *callobj = NewObjectWithGivenProto(cx, &js_CallClass, NULL, scopeChain);
if (!callobj ||
!js_EnsureReservedSlots(cx, callobj, fun->countArgsAndVars())) {
return NULL;
@ -822,8 +822,8 @@ 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);
JSObject *env = NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,
fp->scopeChain);
if (!env)
return NULL;
env->setPrivate(fp);
@ -1518,8 +1518,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.
*/
JSObject *proto =
js_NewObject(cx, &js_ObjectClass, NULL, obj->getParent());
JSObject *proto = NewObject(cx, &js_ObjectClass, NULL, obj->getParent());
if (!proto)
return JS_FALSE;
@ -2213,7 +2212,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
TokenKind tt;
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
obj = NewObject(cx, &js_FunctionClass, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -2459,7 +2458,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
JS_ASSERT(funobj->isFunction());
funobj->setParent(parent);
} else {
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
funobj = NewObject(cx, &js_FunctionClass, NULL, parent);
if (!funobj)
return NULL;
}
@ -2517,8 +2516,8 @@ 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_NewObjectWithGivenProto(cx, &js_FunctionClass, proto,
parent, sizeof(JSObject));
JSObject *clone = NewObjectWithGivenProto(cx, &js_FunctionClass, proto,
parent, sizeof(JSObject));
if (!clone)
return NULL;
clone->setPrivate(fun);

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

@ -492,8 +492,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
vp[0] = ID_TO_VALUE(id);
}
#endif
obj = js_NewObjectWithGivenProto(cx, &js_NoSuchMethodClass,
NULL, NULL);
obj = NewObjectWithGivenProto(cx, &js_NoSuchMethodClass, NULL, NULL);
if (!obj)
return false;
obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.value();
@ -1345,7 +1344,7 @@ js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
clasp = fun2->u.n.clasp;
}
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = NewObject(cx, clasp, proto, parent);
if (!obj)
return JS_FALSE;

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

@ -72,6 +72,8 @@
#include "jsxml.h"
#endif
#include "jsobjinlines.h"
using namespace js;
JS_STATIC_ASSERT(JSSLOT_ITER_FLAGS < JS_INITIAL_NSLOTS);
@ -407,7 +409,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
if ((iterobj = JS_THREAD_DATA(cx)->cachedIteratorObject) != NULL) {
JS_THREAD_DATA(cx)->cachedIteratorObject = NULL;
} else {
if (!(iterobj = js_NewObjectWithGivenProto(cx, &js_IteratorClass, NULL, NULL)))
if (!(iterobj = NewObjectWithGivenProto(cx, &js_IteratorClass, NULL, NULL)))
return false;
}
} else {
@ -416,7 +418,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
* StopIteration exception based on the parent of the iterator
* object, so we need the correct parent here.
*/
if (!(iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL)))
if (!(iterobj = NewObject(cx, &js_IteratorClass, NULL, NULL)))
return false;
}
@ -727,7 +729,7 @@ js_NewGenerator(JSContext *cx)
JSGenerator *gen;
jsval *slots;
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
obj = NewObject(cx, &js_GeneratorClass, NULL, NULL);
if (!obj)
return NULL;

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

@ -79,6 +79,7 @@
#include "jsscopeinlines.h"
#include "jsscriptinlines.h"
#include "jsobjinlines.h"
#if JS_HAS_GENERATORS
#include "jsiter.h"
@ -1927,7 +1928,7 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
/* We have our own property, so start creating the descriptor. */
JSObject *desc = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
JSObject *desc = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!desc)
return false;
*vp = OBJECT_TO_JSVAL(desc); /* Root and return. */
@ -2621,7 +2622,7 @@ obj_create(JSContext *cx, uintN argc, jsval *vp)
* but since we're not completely sure, better safe than sorry.
*/
JSObject *obj =
js_NewObjectWithGivenProto(cx, &js_ObjectClass, JSVAL_TO_OBJECT(v), JS_GetScopeChain(cx));
NewObjectWithGivenProto(cx, &js_ObjectClass, JSVAL_TO_OBJECT(v), JS_GetScopeChain(cx));
if (!obj)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(obj); /* Root and prepare for eventual return. */
@ -2712,168 +2713,6 @@ static JSFunctionSpec object_static_methods[] = {
JS_FS_END
};
static bool
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
static inline bool
InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* ops)
{
JS_ASSERT(ops->isNative());
JS_ASSERT(proto == obj->getProto());
/* Share proto's emptyScope only if obj is similar to proto. */
JSClass *clasp = obj->getClass();
JSScope *scope = NULL;
if (proto && proto->isNative()) {
JS_LOCK_OBJ(cx, proto);
scope = proto->scope();
if (scope->canProvideEmptyScope(ops, clasp)) {
JSScope *emptyScope = scope->getEmptyScope(cx, clasp);
JS_UNLOCK_SCOPE(cx, scope);
if (!emptyScope)
goto bad;
scope = emptyScope;
} else {
JS_UNLOCK_SCOPE(cx, scope);
scope = NULL;
}
}
if (!scope) {
scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false));
if (!scope)
goto bad;
/* Let JSScope::create set freeslot so as to reserve slots. */
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
if (scope->freeslot > JS_INITIAL_NSLOTS &&
!AllocSlots(cx, obj, scope->freeslot)) {
scope->destroy(cx);
goto bad;
}
}
obj->map = scope;
return true;
bad:
/* The GC nulls map initially. It should still be null on error. */
JS_ASSERT(!obj->map);
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);
#ifdef DEBUG
if (obj) {
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
sizeof(JSFunction) - sizeof(JSObject));
}
#endif
} else {
JS_ASSERT(!objectSize || objectSize == sizeof(JSObject));
obj = (clasp == &js_IteratorClass)
? js_NewGCIter(cx)
: js_NewGCObject(cx);
}
if (!obj)
goto out;
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->init(clasp,
proto,
(!parent && proto) ? proto->getParent() : parent,
JSObject::defaultPrivate(clasp));
if (ops->isNative()) {
if (!InitScopeForObject(cx, obj, proto, ops)) {
obj = NULL;
goto out;
}
} else {
JS_ASSERT(ops->objectMap->ops == ops);
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
}
/*
* 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)) {
AutoValueRooter tvr(cx, obj);
AutoKeepAtoms keep(cx->runtime);
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
cx->debugHooks->objectHookData);
cx->weakRoots.finalizableNewborns[FINALIZE_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;
}
inline JSProtoKey
GetClassProtoKey(JSClass *clasp)
{
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
if (key != JSProto_Null)
return key;
if (clasp->flags & JSCLASS_IS_ANONYMOUS)
return JSProto_Object;
return JSProto_Null;
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize)
{
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
JSProtoKey protoKey = GetClassProtoKey(clasp);
if (!js_GetClassPrototype(cx, parent, protoKey, &proto, clasp))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent, 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)
{
@ -2889,7 +2728,7 @@ js_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 (JS_IsConstructing(cx))
return JS_TRUE;
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
obj = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;
}
@ -2950,6 +2789,7 @@ js_NonEmptyObject(JSContext* cx, JSObject* proto)
JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NonEmptyObject, CONTEXT, CALLEE_PROTOTYPE, 0,
nanojit::ACC_STORE_ANY)
static inline JSObject*
NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto,
JSObject *parent, jsval privateSlotValue)
@ -2960,7 +2800,7 @@ NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto,
return NULL;
obj->init(clasp, proto, parent, privateSlotValue);
return InitScopeForObject(cx, obj, proto, &js_ObjectOps) ? obj : NULL;
return InitScopeForObject(cx, obj, clasp, proto, &js_ObjectOps) ? obj : NULL;
}
JSObject* FASTCALL
@ -2990,7 +2830,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, ctor->getParent());
proto = NewObject(cx, clasp, NULL, ctor->getParent());
if (!proto)
return NULL;
if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_ENUMERATE | JSPROP_PERMANENT))
@ -3264,7 +3104,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
obj = js_NewObject(cx, &js_WithClass, proto, parent);
obj = NewObject(cx, &js_WithClass, proto, parent);
if (!obj)
return NULL;
obj->setPrivate(cx->fp);
@ -3279,7 +3119,7 @@ js_NewBlockObject(JSContext *cx)
* Null obj's proto slot so that Object.prototype.* does not pollute block
* scopes and to give the block object its own scope.
*/
JSObject *blockObj = js_NewObjectWithGivenProto(cx, &js_BlockClass, NULL, NULL);
JSObject *blockObj = NewObjectWithGivenProto(cx, &js_BlockClass, NULL, NULL);
JS_ASSERT_IF(blockObj, !OBJ_IS_CLONED_BLOCK(blockObj));
return blockObj;
}
@ -3346,7 +3186,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
if (normalUnwind && count > 1) {
--count;
JS_LOCK_OBJ(cx, obj);
if (!AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
if (!js_AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
normalUnwind = JS_FALSE;
else
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
@ -3626,7 +3466,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 = NewObject(cx, clasp, parent_proto, obj);
if (!proto)
return NULL;
@ -3737,8 +3577,8 @@ bad:
(JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
static bool
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
bool
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
{
JS_ASSERT(!obj->dslots);
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
@ -3798,7 +3638,7 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
*/
jsval* slots = obj->dslots;
if (!slots)
return AllocSlots(cx, obj, nslots);
return js_AllocSlots(cx, obj, nslots);
size_t oslots = size_t(slots[-1]);
@ -3844,7 +3684,7 @@ js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
JS_ASSERT(!obj->dslots);
uintN nslots = JSSLOT_FREE(obj->getClass()) + nreserved;
if (nslots > obj->numSlots() && !AllocSlots(cx, obj, nslots))
if (nslots > obj->numSlots() && !js_AllocSlots(cx, obj, nslots))
return false;
JSScope *scope = obj->scope();
@ -4058,7 +3898,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
proto = JSVAL_TO_OBJECT(rval);
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = NewObject(cx, clasp, proto, parent);
if (!obj)
return NULL;
@ -6250,7 +6090,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);
obj = NewObject(cx, clasp, NULL, NULL);
if (!obj)
return JS_FALSE;
obj->fslots[JSSLOT_PRIMITIVE_THIS] = *vp;
@ -6648,7 +6488,7 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
if (clasp->reserveSlots)
nslots += clasp->reserveSlots(cx, obj);
JS_ASSERT(slot < nslots);
if (!AllocSlots(cx, obj, nslots)) {
if (!js_AllocSlots(cx, obj, nslots)) {
JS_UNLOCK_OBJ(cx, obj);
return false;
}

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

@ -721,17 +721,6 @@ extern const char js_lookupGetter_str[];
extern const char js_lookupSetter_str[];
#endif
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0);
/*
* See jsapi.h, JS_NewObjectWithGivenProto.
*/
extern JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0);
/*
* Allocate a new native object with the given value of the proto and private
* slots. The parent slot is set to the value of proto's parent slot.
@ -776,6 +765,9 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
extern void
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
extern bool
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
extern bool
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots);

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

@ -42,8 +42,11 @@
#define jsobjinlines_h___
#include "jsobj.h"
#include "jsiter.h"
#include "jsscope.h"
#include "jsscopeinlines.h"
inline jsval
JSObject::getSlotMT(JSContext *cx, uintN slot)
{
@ -209,6 +212,164 @@ class AutoDescriptorArray : private AutoGCRooter
PropertyDescriptorArray descriptors;
};
static inline bool
InitScopeForObject(JSContext* cx, JSObject* obj, JSClass *clasp, JSObject* proto, JSObjectOps* ops)
{
JS_ASSERT(ops->isNative());
JS_ASSERT(proto == obj->getProto());
/* Share proto's emptyScope only if obj is similar to proto. */
JSScope *scope = NULL;
if (proto && proto->isNative()) {
JS_LOCK_OBJ(cx, proto);
scope = proto->scope();
if (scope->canProvideEmptyScope(ops, clasp)) {
JSScope *emptyScope = scope->getEmptyScope(cx, clasp);
JS_UNLOCK_SCOPE(cx, scope);
if (!emptyScope)
goto bad;
scope = emptyScope;
} else {
JS_UNLOCK_SCOPE(cx, scope);
scope = NULL;
}
}
if (!scope) {
scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false));
if (!scope)
goto bad;
/* Let JSScope::create set freeslot so as to reserve slots. */
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
if (scope->freeslot > JS_INITIAL_NSLOTS &&
!js_AllocSlots(cx, obj, scope->freeslot)) {
scope->destroy(cx);
goto bad;
}
}
obj->map = scope;
return true;
bad:
/* The GC nulls map initially. It should still be null on error. */
JS_ASSERT(!obj->map);
return false;
}
static inline JSObject *
NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0)
{
#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);
#ifdef DEBUG
if (obj) {
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
sizeof(JSFunction) - sizeof(JSObject));
}
#endif
} else {
JS_ASSERT(!objectSize || objectSize == sizeof(JSObject));
obj = (clasp == &js_IteratorClass)
? js_NewGCIter(cx)
: js_NewGCObject(cx);
}
if (!obj)
goto out;
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->init(clasp,
proto,
(!parent && proto) ? proto->getParent() : parent,
JSObject::defaultPrivate(clasp));
if (ops->isNative()) {
if (!InitScopeForObject(cx, obj, clasp, proto, ops)) {
obj = NULL;
goto out;
}
} else {
JS_ASSERT(ops->objectMap->ops == ops);
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
}
/*
* 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)) {
AutoValueRooter tvr(cx, obj);
AutoKeepAtoms keep(cx->runtime);
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
cx->debugHooks->objectHookData);
cx->weakRoots.finalizableNewborns[FINALIZE_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;
}
static inline JSProtoKey
GetClassProtoKey(JSClass *clasp)
{
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
if (key != JSProto_Null)
return key;
if (clasp->flags & JSCLASS_IS_ANONYMOUS)
return JSProto_Object;
return JSProto_Null;
}
static inline JSObject *
NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0)
{
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {
JSProtoKey protoKey = GetClassProtoKey(clasp);
if (!js_GetClassPrototype(cx, parent, protoKey, &proto, clasp))
return NULL;
if (!proto &&
!js_GetClassPrototype(cx, parent, JSProto_Object, &proto)) {
return NULL;
}
}
return NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
}
}
#endif /* jsobjinlines_h___ */

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

@ -64,6 +64,7 @@
#include "json.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
using namespace js;
@ -555,7 +556,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);
JSObject *obj = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;
@ -646,7 +647,7 @@ static bool
Revive(JSContext *cx, jsval reviver, jsval *vp)
{
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
JSObject *obj = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return false;
@ -838,7 +839,7 @@ PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
static JSBool
OpenObject(JSContext *cx, JSONParser *jp)
{
JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
JSObject *obj = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
return JS_FALSE;

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

@ -1975,9 +1975,9 @@ BEGIN_CASE(JSOP_NEW)
goto error;
}
rval = vp[1];
obj2 = js_NewObject(cx, &js_ObjectClass,
JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL,
obj->getParent());
obj2 = NewObject(cx, &js_ObjectClass,
JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL,
obj->getParent());
if (!obj2)
goto error;
@ -3300,7 +3300,7 @@ BEGIN_CASE(JSOP_NEWINIT)
if (!obj)
goto error;
} else {
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
obj = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!obj)
goto error;

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

@ -74,6 +74,8 @@ using namespace avmplus;
using namespace nanojit;
#endif
#include "jsobjinlines.h"
using namespace js;
typedef enum REOp {
@ -5428,7 +5430,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
return JS_FALSE;
}
if (xdr->mode == JSXDR_DECODE) {
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
obj = NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
if (!obj)
return JS_FALSE;
obj->clearParent();
@ -5786,7 +5788,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 = NewObject(cx, &js_RegExpClass, NULL, NULL);
if (!obj)
return JS_FALSE;
@ -5842,7 +5844,7 @@ js_NewRegExpObject(JSContext *cx, TokenStream *ts,
re = js_NewRegExp(cx, ts, str, flags, JS_FALSE);
if (!re)
return NULL;
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
obj = NewObject(cx, &js_RegExpClass, NULL, NULL);
if (!obj) {
js_DestroyRegExp(cx, re);
return NULL;
@ -5858,8 +5860,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
JS_ASSERT(obj->getClass() == &js_RegExpClass);
JS_ASSERT(proto);
JS_ASSERT(proto->getClass() == &js_RegExpClass);
JSObject *clone = js_NewObjectWithGivenProto(cx, &js_RegExpClass, proto,
NULL);
JSObject *clone = NewObjectWithGivenProto(cx, &js_RegExpClass, proto, NULL);
if (!clone)
return NULL;
JSRegExp *re = static_cast<JSRegExp *>(obj->getPrivate());

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

@ -107,7 +107,7 @@ ArrayBuffer::class_constructor(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *rval)
{
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, &ArrayBuffer::jsclass, NULL, NULL);
obj = NewObject(cx, &ArrayBuffer::jsclass, NULL, NULL);
if (!obj)
return false;
*rval = OBJECT_TO_JSVAL(obj);
@ -681,7 +681,7 @@ class TypedArrayTemplate
//
if (!JS_IsConstructing(cx)) {
obj = js_NewObject(cx, slowClass(), NULL, NULL);
obj = NewObject(cx, slowClass(), NULL, NULL);
if (!obj)
return false;
*rval = OBJECT_TO_JSVAL(obj);

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

@ -305,7 +305,7 @@ NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
{
JSObject *obj;
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
if (!obj)
return JS_FALSE;
JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
@ -518,7 +518,7 @@ NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName,
JSObject *obj;
JS_ASSERT(IsQNameClass(clasp));
obj = js_NewObject(cx, clasp, NULL, NULL);
obj = NewObject(cx, clasp, NULL, NULL);
if (!obj)
return NULL;
InitXMLQName(obj, uri, prefix, localName);
@ -630,7 +630,7 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
return JS_TRUE;
}
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -737,7 +737,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);
obj = NewObject(cx, clasp, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -7172,7 +7172,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
{
JSObject *obj;
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
obj = NewObject(cx, &js_XMLClass, NULL, NULL);
if (!obj)
return NULL;
obj->setPrivate(xml);
@ -7562,8 +7562,8 @@ js_GetAnyName(JSContext *cx, jsval *vp)
return JS_FALSE;
do {
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
NULL);
obj = NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
NULL);
if (!obj) {
ok = JS_FALSE;
break;
@ -7845,8 +7845,8 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
return JS_FALSE;
}
filterobj = js_NewObjectWithGivenProto(cx, &js_XMLFilterClass,
NULL, NULL);
filterobj = NewObjectWithGivenProto(cx, &js_XMLFilterClass,
NULL, NULL);
if (!filterobj)
return JS_FALSE;