Turns out function objects can be on parent chains

This commit is contained in:
Luke Wagner 2010-05-18 14:23:23 -07:00
parent 4efd7171cc
commit 19c9bbad15
11 changed files with 29 additions and 25 deletions

View File

@ -3005,8 +3005,8 @@ struct NonFunObjTag {
JSObject &obj;
};
struct NonFunObjOrNull {
explicit NonFunObjOrNull(JSObject *obj) : obj(obj) {}
struct NonFunObjOrNullTag {
explicit NonFunObjOrNullTag(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
@ -3132,12 +3132,12 @@ class Value
}
Value(NonFunObjTag arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg.obj));
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg.obj));
mask = JSVAL_NONFUNOBJ_MASK;
data.obj = &arg.obj;
}
Value(NonFunObjOrNull arg) {
Value(NonFunObjOrNullTag arg) {
JS_ASSERT_IF(arg.obj, !JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? JSVAL_NONFUNOBJ_MASK : JSVAL_NULL_MASK;
data.obj = arg.obj;

View File

@ -3102,7 +3102,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
/* Initialize all fields of JSObject. */
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
obj->init(&js_ArrayClass, NonFunObjTag(*proto), proto->getParent(), NullTag());
obj->init(&js_ArrayClass, NonFunObjTag(*proto), proto->getParentValue(), NullTag());
obj->setDenseArrayLength(0);
obj->setDenseArrayCount(0);
return obj;

View File

@ -1331,7 +1331,7 @@ js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
{
js_PushStatement(tc, stmt, STMT_BLOCK, top);
stmt->flags |= SIF_SCOPE;
blockObj->setParent(tc->blockChain);
blockObj->setParent(NonFunObjOrNullTag(tc->blockChain));
stmt->downScope = tc->topScopeStmt;
tc->topScopeStmt = stmt;
tc->blockChain = blockObj;

View File

@ -176,7 +176,7 @@ NewArguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee)
return NULL;
/* Init immediately to avoid GC seeing a half-init'ed object. */
argsobj->init(&js_ArgumentsClass, NonFunObjTag(*proto), parent, NullTag());
argsobj->init(&js_ArgumentsClass, NonFunObjTag(*proto), NonFunObjTag(*parent), NullTag());
argsobj->setArgsCallee(ObjectOrNullTag(callee));
argsobj->setArgsLength(argc);
@ -2365,7 +2365,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, Native native, uintN nargs,
if (funobj) {
JS_ASSERT(funobj->isFunction());
funobj->setParent(parent);
funobj->setParent(ObjectOrNullTag(parent));
} else {
funobj = NewObject(cx, &js_FunctionClass, NULL, parent);
if (!funobj)

View File

@ -2345,7 +2345,7 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
obj->setProto(ObjectOrNullTag(pobj));
} else {
JS_ASSERT(slot == JSSLOT_PARENT);
obj->setParent(pobj);
obj->setParent(ObjectOrNullTag(pobj));
}
}

View File

@ -205,10 +205,10 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
if (!clone)
return NULL;
newChild->setParent(clone);
newChild->setParent(NonFunObjTag(*clone));
newChild = clone;
}
newChild->setParent(fp->scopeChain);
newChild->setParent(NonFunObjTag(*fp->scopeChain));
/*

View File

@ -241,7 +241,7 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
if (slot == JSSLOT_PROTO)
obj->setProto(ObjectOrNullTag(pobj));
else
obj->setParent(pobj);
obj->setParent(ObjectOrNullTag(pobj));
} else {
/*
* Use the GC machinery to serialize access to all objects on the
@ -3228,7 +3228,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
parent = NULL;
else
parent = xdr->script->getObject(parentId);
obj->setParent(parent);
obj->setParent(NonFunObjOrNullTag(parent));
}
AutoObjectRooter tvr(cx, obj);

View File

@ -403,9 +403,9 @@ struct JSObject {
fslots[JSSLOT_PARENT].setNull();
}
void setParent(JSObject *newParent) {
setDelegateNullSafe(newParent);
fslots[JSSLOT_PARENT].setNonFunObjOrNull(newParent);
void setParent(const js::Value &newParent) {
setDelegateNullSafe(newParent.asObjectOrNull());
fslots[JSSLOT_PARENT] = newParent;
}
void traceProtoAndParent(JSTracer *trc) const {
@ -580,7 +580,7 @@ struct JSObject {
bool isCallable();
/* The map field is not initialized here and should be set separately. */
void init(js::Class *clasp, const js::Value &proto, JSObject *parent,
void init(js::Class *clasp, const js::Value &proto, const js::Value &parent,
const js::Value &privateSlotValue) {
JS_ASSERT(((jsuword) clasp & 3) == 0);
JS_STATIC_ASSERT(JSSLOT_PRIVATE + 3 == JS_INITIAL_NSLOTS);
@ -602,7 +602,8 @@ struct JSObject {
* of a call to js_InitClass(...clasp, ...).
*/
inline void initSharingEmptyScope(js::Class *clasp,
const js::Value &proto, JSObject *parent,
const js::Value &proto,
const js::Value &parent,
const js::Value &privateSlotValue);
inline bool hasSlotsArray() const { return !!dslots; }

View File

@ -400,7 +400,9 @@ JSObject::setNativeIterator(NativeIterator *ni)
}
inline void
JSObject::initSharingEmptyScope(js::Class *clasp, const js::Value &proto, JSObject *parent,
JSObject::initSharingEmptyScope(js::Class *clasp,
const js::Value &proto,
const js::Value &parent,
const js::Value &privateSlotValue)
{
init(clasp, proto, parent, privateSlotValue);
@ -592,7 +594,8 @@ NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto,
*/
obj->init(clasp,
js::ObjectOrNullTag(proto),
(!parent && proto) ? proto->getParent() : parent,
(!parent && proto) ? proto->getParentValue()
: ObjectOrNullTag(parent),
JSObject::defaultPrivate(clasp));
if (ops->isNative()) {
@ -634,8 +637,8 @@ GetClassProtoKey(js::Class *clasp)
}
static inline JSObject *
NewObject(JSContext *cx, js::Class *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0)
NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
size_t objectSize = 0)
{
/* Bootstrap the ur-object, and make it the default prototype object. */
if (!proto) {

View File

@ -5457,7 +5457,7 @@ Parser::statement()
JS_SCOPE_DEPTH_METERING(++tc->scopeDepth > tc->maxScopeDepth &&
(tc->maxScopeDepth = tc->scopeDepth));
obj->setParent(tc->blockChain);
obj->setParent(NonFunObjOrNullTag(tc->blockChain));
tc->blockChain = obj;
stmt->blockObj = obj;

View File

@ -1538,14 +1538,14 @@ js_ReparentTypedArrayToScope(JSContext *cx, JSObject *obj, JSObject *scope)
return JS_FALSE;
obj->setProto(NonFunObjTag(*proto));
obj->setParent(scope);
obj->setParent(NonFunObjTag(*scope));
key = JSCLASS_CACHED_PROTO_KEY(&ArrayBuffer::jsclass);
if (!js_GetClassPrototype(cx, scope, key, &proto))
return JS_FALSE;
buffer->setProto(NonFunObjTag(*proto));
buffer->setParent(scope);
buffer->setParent(NonFunObjTag(*scope));
return JS_TRUE;
}