mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
Bug 558144 - un-macroize OBJ_SCOPE, OBJ_SHAPE, LOCKED_OBJ_SET_SLOT, LOCKED_OBJ_GET_SLOT (r=Waldo)
This commit is contained in:
parent
e94e8073c1
commit
515c38eb66
@ -1471,7 +1471,7 @@ static JSBool
|
||||
AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
|
||||
{
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
bool found = scope->hasProperty(ATOM_TO_JSID(atom));
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return found;
|
||||
@ -2766,13 +2766,13 @@ JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
/* Insist on scope being used exclusively by cx's thread. */
|
||||
if (scope->title.ownercx != cx) {
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JS_ASSERT(OBJ_SCOPE(obj) == scope);
|
||||
JS_ASSERT(obj->scope() == scope);
|
||||
JS_ASSERT(scope->title.ownercx == cx);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
}
|
||||
@ -3073,12 +3073,12 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop,
|
||||
AutoScopePropertyRooter root(cx, sprop);
|
||||
JS_UNLOCK_OBJ(cx, obj2);
|
||||
*vp = sprop->methodValue();
|
||||
return OBJ_SCOPE(obj2)->methodReadBarrier(cx, sprop, vp);
|
||||
return obj2->scope()->methodReadBarrier(cx, sprop, vp);
|
||||
}
|
||||
|
||||
/* Peek at the native property's slot value, without doing a Get. */
|
||||
*vp = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
|
||||
? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
|
||||
*vp = SPROP_HAS_VALID_SLOT(sprop, obj2->scope())
|
||||
? obj2->lockedGetSlot(sprop->slot)
|
||||
: JSVAL_TRUE;
|
||||
} else if (obj2->isDenseArray()) {
|
||||
ok = js_GetDenseArrayElementValue(cx, obj2, prop, vp);
|
||||
@ -3121,8 +3121,8 @@ GetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
|
||||
desc->getter = sprop->getter();
|
||||
desc->setter = sprop->setter();
|
||||
desc->value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
|
||||
? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
|
||||
desc->value = SPROP_HAS_VALID_SLOT(sprop, obj2->scope())
|
||||
? obj2->lockedGetSlot(sprop->slot)
|
||||
: JSVAL_VOID;
|
||||
} else {
|
||||
desc->getter = NULL;
|
||||
@ -3262,7 +3262,7 @@ AlreadyHasOwnPropertyHelper(JSContext *cx, JSObject *obj, jsid id,
|
||||
}
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
*foundp = scope->hasProperty(id);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return JS_TRUE;
|
||||
@ -3950,7 +3950,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
|
||||
|
||||
if (obj->isNative()) {
|
||||
/* Native case: start with the last property in obj's own scope. */
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
pdata = scope->lastProperty();
|
||||
index = -1;
|
||||
} else {
|
||||
@ -3989,7 +3989,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
|
||||
/* Native case: private data is a property tree node pointer. */
|
||||
obj = iterobj->getParent();
|
||||
JS_ASSERT(obj->isNative());
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
sprop = (JSScopeProperty *) iterobj->getPrivate();
|
||||
|
||||
/*
|
||||
|
@ -891,7 +891,7 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
|
||||
*/
|
||||
if (!obj->isNative())
|
||||
return JS_TRUE;
|
||||
if (OBJ_SCOPE(obj)->hadIndexedProperties())
|
||||
if (obj->scope()->hadIndexedProperties())
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
@ -1303,7 +1303,7 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
|
||||
} else {
|
||||
/* arrayProto is Array.prototype. */
|
||||
JS_ASSERT(arrayProto->getClass() == &js_SlowArrayClass);
|
||||
emptyShape = OBJ_SCOPE(arrayProto)->emptyScope->shape;
|
||||
emptyShape = arrayProto->scope()->emptyScope->shape;
|
||||
}
|
||||
JSScope *scope = JSScope::create(cx, &js_SlowArrayObjectOps, &js_SlowArrayClass, obj,
|
||||
emptyShape);
|
||||
|
@ -204,7 +204,7 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
||||
uint32 slot = sprop->slot;
|
||||
JSScope* scope = OBJ_SCOPE(obj);
|
||||
JSScope* scope = obj->scope();
|
||||
if (slot != scope->freeslot)
|
||||
goto exit_trace;
|
||||
JS_ASSERT(sprop->parent == scope->lastProperty());
|
||||
|
@ -465,7 +465,7 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
|
||||
DBG_UNLOCK(cx->runtime);
|
||||
if (!setter) {
|
||||
JS_LOCK_OBJ(cx, wp->object);
|
||||
scope = OBJ_SCOPE(wp->object);
|
||||
scope = wp->object->scope();
|
||||
|
||||
/*
|
||||
* If the property wasn't found on wp->object, or it isn't still being
|
||||
@ -555,7 +555,7 @@ FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
&wp->links != &rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if (OBJ_SCOPE(wp->object) == scope && wp->sprop->id == id)
|
||||
if (wp->object->scope() == scope && wp->sprop->id == id)
|
||||
return wp;
|
||||
}
|
||||
return NULL;
|
||||
@ -591,7 +591,7 @@ js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
&wp->links != &rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if ((!scope || OBJ_SCOPE(wp->object) == scope) && wp->sprop == sprop) {
|
||||
if ((!scope || wp->object->scope() == scope) && wp->sprop == sprop) {
|
||||
setter = wp->setter;
|
||||
break;
|
||||
}
|
||||
@ -625,7 +625,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
propid = ID_TO_VALUE(sprop->id);
|
||||
userid = SPROP_USERID(sprop);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
|
||||
/* NB: wp is held, so we can safely dereference it still. */
|
||||
@ -858,7 +858,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
||||
rt = cx->runtime;
|
||||
if (!sprop) {
|
||||
/* Check for a deleted symbol watchpoint, which holds its property. */
|
||||
sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
|
||||
sprop = js_FindWatchPoint(rt, obj->scope(), propid);
|
||||
if (!sprop) {
|
||||
/* Make a new property in obj so we can watch for the first set. */
|
||||
if (!js_DefineNativeProperty(cx, obj, propid, JSVAL_VOID, NULL, NULL,
|
||||
@ -875,8 +875,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
||||
intN shortid;
|
||||
|
||||
if (pobj->isNative()) {
|
||||
value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))
|
||||
? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
|
||||
value = SPROP_HAS_VALID_SLOT(sprop, pobj->scope())
|
||||
? pobj->lockedGetSlot(sprop->slot)
|
||||
: JSVAL_VOID;
|
||||
getter = sprop->getter();
|
||||
setter = sprop->setter();
|
||||
@ -909,7 +909,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
||||
*/
|
||||
ok = JS_TRUE;
|
||||
DBG_LOCK(rt);
|
||||
wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
|
||||
wp = FindWatchPoint(rt, obj->scope(), propid);
|
||||
if (!wp) {
|
||||
DBG_UNLOCK(rt);
|
||||
watcher = js_WrapWatchedSetter(cx, propid, sprop->attributes(), sprop->setter());
|
||||
@ -949,7 +949,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
||||
* a watchpoint for (obj, propid).
|
||||
*/
|
||||
DBG_LOCK(rt);
|
||||
JS_ASSERT(!FindWatchPoint(rt, OBJ_SCOPE(obj), propid));
|
||||
JS_ASSERT(!FindWatchPoint(rt, obj->scope(), propid));
|
||||
JS_APPEND_LINK(&wp->links, &rt->watchPointList);
|
||||
++rt->debuggerMutations;
|
||||
}
|
||||
@ -1429,7 +1429,7 @@ JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
|
||||
JSScope *scope;
|
||||
|
||||
sprop = *iteratorp;
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
|
||||
/* XXXbe minor(?) incompatibility: iterate in reverse definition order */
|
||||
sprop = sprop ? sprop->parent : scope->lastProperty();
|
||||
@ -1478,7 +1478,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
}
|
||||
pd->alias = JSVAL_VOID;
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||
JSScopeProperty *aprop;
|
||||
for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) {
|
||||
@ -1510,7 +1510,7 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
||||
return JS_FALSE;
|
||||
|
||||
/* have no props, or object's scope has not mutated from that of proto */
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
if (scope->entryCount == 0) {
|
||||
pda->length = 0;
|
||||
pda->array = NULL;
|
||||
@ -1655,7 +1655,7 @@ JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
|
||||
* sizeof obj->dslots[0];
|
||||
}
|
||||
if (obj->isNative()) {
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
if (!scope->isSharedEmpty()) {
|
||||
nbytes += sizeof *scope;
|
||||
nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *);
|
||||
|
@ -1589,7 +1589,7 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
||||
|
||||
obj = stmt->blockObj;
|
||||
JS_ASSERT(obj->getClass() == &js_BlockClass);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
sprop = scope->lookup(ATOM_TO_JSID(atom));
|
||||
if (sprop) {
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
@ -1880,7 +1880,7 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
|
||||
#endif
|
||||
}
|
||||
|
||||
OBJ_SCOPE(blockObj)->freeslot = JSSLOT_FREE(&js_BlockClass);
|
||||
blockObj->scope()->freeslot = JSSLOT_FREE(&js_BlockClass);
|
||||
return js_GrowSlots(cx, blockObj, JSSLOT_FREE(&js_BlockClass));
|
||||
}
|
||||
|
||||
|
@ -2539,7 +2539,7 @@ FinalizeObject(JSContext *cx, JSObject *obj, unsigned thingKind)
|
||||
#endif
|
||||
|
||||
if (JS_LIKELY(obj->isNative())) {
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (scope->isSharedEmpty())
|
||||
static_cast<JSEmptyScope *>(scope)->dropFromGC(cx);
|
||||
else
|
||||
|
@ -2158,7 +2158,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
|
||||
}
|
||||
if (!ok)
|
||||
return false;
|
||||
if (cx->runtime->gcNumber != sample || entry->vshape() != OBJ_SHAPE(pobj)) {
|
||||
if (cx->runtime->gcNumber != sample || entry->vshape() != pobj->shape()) {
|
||||
pobj->dropProperty(cx, prop);
|
||||
return true;
|
||||
}
|
||||
@ -2172,15 +2172,15 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
|
||||
} else if (entry->vword.isSprop()) {
|
||||
JS_ASSERT(entry->vword.toSprop() == sprop);
|
||||
JS_ASSERT_IF(sprop->isMethod(),
|
||||
sprop->methodValue() == LOCKED_OBJ_GET_SLOT(pobj, sprop->slot));
|
||||
sprop->methodValue() == pobj->lockedGetSlot(sprop->slot));
|
||||
} else {
|
||||
jsval v;
|
||||
JS_ASSERT(entry->vword.isObject());
|
||||
JS_ASSERT(!entry->vword.isNull());
|
||||
JS_ASSERT(OBJ_SCOPE(pobj)->brandedOrHasMethodBarrier());
|
||||
JS_ASSERT(pobj->scope()->brandedOrHasMethodBarrier());
|
||||
JS_ASSERT(sprop->hasDefaultGetterOrIsMethod());
|
||||
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
|
||||
v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, pobj->scope()));
|
||||
v = pobj->lockedGetSlot(sprop->slot);
|
||||
JS_ASSERT(VALUE_IS_FUNCTION(cx, v));
|
||||
JS_ASSERT(entry->vword.toObject() == JSVAL_TO_OBJECT(v));
|
||||
|
||||
|
@ -690,7 +690,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
* Native object locking is inlined here to optimize the single-threaded
|
||||
* and contention-free multi-threaded cases.
|
||||
*/
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
title = &scope->title;
|
||||
JS_ASSERT(title->ownercx != cx);
|
||||
JS_ASSERT(slot < scope->freeslot);
|
||||
@ -718,7 +718,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
* require either a restart from the top of this routine, or a thin
|
||||
* lock release followed by fat lock acquisition.
|
||||
*/
|
||||
if (scope == OBJ_SCOPE(obj)) {
|
||||
if (scope == obj->scope()) {
|
||||
v = obj->getSlot(slot);
|
||||
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
|
||||
/* Assert that scope locks never revert to flyweight. */
|
||||
@ -749,7 +749,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
* object's scope (whose lock was not flyweight, else we wouldn't be here
|
||||
* in the first place!).
|
||||
*/
|
||||
title = &OBJ_SCOPE(obj)->title;
|
||||
title = &obj->scope()->title;
|
||||
if (title->ownercx != cx)
|
||||
js_UnlockTitle(cx, title);
|
||||
return v;
|
||||
@ -778,7 +778,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
* Native object locking is inlined here to optimize the single-threaded
|
||||
* and contention-free multi-threaded cases.
|
||||
*/
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
title = &scope->title;
|
||||
JS_ASSERT(title->ownercx != cx);
|
||||
JS_ASSERT(slot < scope->freeslot);
|
||||
@ -792,7 +792,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
if (CX_THREAD_IS_RUNNING_GC(cx) ||
|
||||
scope->sealed() ||
|
||||
(title->ownercx && ClaimTitle(title, cx))) {
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, v);
|
||||
obj->lockedSetSlot(slot, v);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -801,8 +801,8 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
me = CX_THINLOCK_ID(cx);
|
||||
JS_ASSERT(CURRENT_THREAD_IS_ME(me));
|
||||
if (NativeCompareAndSwap(&tl->owner, 0, me)) {
|
||||
if (scope == OBJ_SCOPE(obj)) {
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, v);
|
||||
if (scope == obj->scope()) {
|
||||
obj->lockedSetSlot(slot, v);
|
||||
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
|
||||
/* Assert that scope locks never revert to flyweight. */
|
||||
JS_ASSERT(title->ownercx != cx);
|
||||
@ -815,18 +815,18 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
if (!NativeCompareAndSwap(&tl->owner, me, 0))
|
||||
js_Dequeue(tl);
|
||||
} else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, v);
|
||||
obj->lockedSetSlot(slot, v);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
js_LockObj(cx, obj);
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, v);
|
||||
obj->lockedSetSlot(slot, v);
|
||||
|
||||
/*
|
||||
* Same drill as above, in js_GetSlotThreadSafe.
|
||||
*/
|
||||
title = &OBJ_SCOPE(obj)->title;
|
||||
title = &obj->scope()->title;
|
||||
if (title->ownercx != cx)
|
||||
js_UnlockTitle(cx, title);
|
||||
}
|
||||
@ -1321,7 +1321,7 @@ js_LockObj(JSContext *cx, JSObject *obj)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
title = &scope->title;
|
||||
if (scope->sealed() && !cx->lockedSealedTitle) {
|
||||
cx->lockedSealedTitle = title;
|
||||
@ -1331,7 +1331,7 @@ js_LockObj(JSContext *cx, JSObject *obj)
|
||||
js_LockTitle(cx, title);
|
||||
|
||||
/* If obj still has this scope, we're done. */
|
||||
if (scope == OBJ_SCOPE(obj))
|
||||
if (scope == obj->scope())
|
||||
return;
|
||||
|
||||
/* Lost a race with a mutator; retry with obj's new scope. */
|
||||
@ -1343,7 +1343,7 @@ void
|
||||
js_UnlockObj(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title);
|
||||
js_UnlockTitle(cx, &obj->scope()->title);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1392,7 +1392,7 @@ js_IsRuntimeLocked(JSRuntime *rt)
|
||||
JSBool
|
||||
js_IsObjLocked(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return js_IsTitleLocked(cx, &OBJ_SCOPE(obj)->title);
|
||||
return js_IsTitleLocked(cx, &obj->scope()->title);
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -134,7 +134,7 @@ struct JSTitle {
|
||||
#ifdef JS_DEBUG_TITLE_LOCKS
|
||||
|
||||
#define JS_SET_OBJ_INFO(obj_, file_, line_) \
|
||||
JS_SET_SCOPE_INFO(OBJ_SCOPE(obj_), file_, line_)
|
||||
JS_SET_SCOPE_INFO((obj_)->scope(), file_, line_)
|
||||
|
||||
#define JS_SET_SCOPE_INFO(scope_, file_, line_) \
|
||||
js_SetScopeInfo(scope_, file_, line_)
|
||||
@ -156,12 +156,21 @@ struct JSTitle {
|
||||
*/
|
||||
#define CX_OWNS_SCOPE_TITLE(cx,scope) ((scope)->title.ownercx == (cx))
|
||||
|
||||
#define JS_LOCK_OBJ(cx,obj) (CX_OWNS_SCOPE_TITLE(cx, OBJ_SCOPE(obj)) \
|
||||
? (void)0 \
|
||||
: (js_LockObj(cx, obj), \
|
||||
JS_SET_OBJ_INFO(obj,__FILE__,__LINE__)))
|
||||
#define JS_UNLOCK_OBJ(cx,obj) (CX_OWNS_SCOPE_TITLE(cx, OBJ_SCOPE(obj)) \
|
||||
? (void)0 : js_UnlockObj(cx, obj))
|
||||
#define JS_LOCK_OBJ(cx,obj) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSObject *obj_ = (obj); \
|
||||
if (!CX_OWNS_SCOPE_TITLE(cx, obj_->scope())) { \
|
||||
js_LockObj(cx, obj_); \
|
||||
JS_SET_OBJ_INFO(obj_, __FILE__, __LINE__); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_UNLOCK_OBJ(cx,obj) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSObject *obj_ = (obj); \
|
||||
if (!CX_OWNS_SCOPE_TITLE(cx, obj_->scope())) \
|
||||
js_UnlockObj(cx, obj_); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_LOCK_TITLE(cx,title) \
|
||||
((title)->ownercx == (cx) ? (void)0 \
|
||||
@ -282,7 +291,7 @@ extern void js_SetScopeInfo(JSScope *scope, const char *file, int line);
|
||||
JS_NO_TIMEOUT)
|
||||
#define JS_NOTIFY_REQUEST_DONE(rt) JS_NOTIFY_CONDVAR((rt)->requestDone)
|
||||
|
||||
#define CX_OWNS_OBJECT_TITLE(cx,obj) CX_OWNS_SCOPE_TITLE(cx, OBJ_SCOPE(obj))
|
||||
#define CX_OWNS_OBJECT_TITLE(cx,obj) CX_OWNS_SCOPE_TITLE(cx, (obj)->scope())
|
||||
|
||||
#ifndef JS_SET_OBJ_INFO
|
||||
#define JS_SET_OBJ_INFO(obj,f,l) ((void)0)
|
||||
|
114
js/src/jsobj.cpp
114
js/src/jsobj.cpp
@ -265,7 +265,7 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
|
||||
JSObject *oldproto = obj;
|
||||
while (oldproto && oldproto->isNative()) {
|
||||
JS_LOCK_OBJ(cx, oldproto);
|
||||
JSScope *scope = OBJ_SCOPE(oldproto);
|
||||
JSScope *scope = oldproto->scope();
|
||||
scope->protoShapeChange(cx);
|
||||
JSObject *tmp = oldproto->getProto();
|
||||
JS_UNLOCK_OBJ(cx, oldproto);
|
||||
@ -2245,7 +2245,7 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
|
||||
JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty);
|
||||
|
||||
/* 8.12.9 steps 2-4. */
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (!current) {
|
||||
if (scope->sealed())
|
||||
return Reject(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
|
||||
@ -2785,7 +2785,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* o
|
||||
|
||||
if (proto && proto->isNative()) {
|
||||
JS_LOCK_OBJ(cx, proto);
|
||||
scope = OBJ_SCOPE(proto);
|
||||
scope = proto->scope();
|
||||
if (scope->canProvideEmptyScope(ops, clasp)) {
|
||||
JSScope *emptyScope = scope->getEmptyScope(cx, clasp);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
@ -3026,7 +3026,7 @@ js_NewInstance(JSContext *cx, JSClass *clasp, JSObject *ctor)
|
||||
|
||||
JSAtom *atom = cx->runtime->atomState.classPrototypeAtom;
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(ctor);
|
||||
JSScope *scope = ctor->scope();
|
||||
#ifdef JS_THREADSAFE
|
||||
if (scope->title.ownercx != cx)
|
||||
return NULL;
|
||||
@ -3380,10 +3380,10 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
||||
/*
|
||||
* Block objects should never be exposed to scripts. Thus the clone should
|
||||
* not own the property map and rather always share it with the prototype
|
||||
* object. This allows us to skip updating OBJ_SCOPE(obj)->freeslot after
|
||||
* object. This allows us to skip updating obj->scope()->freeslot after
|
||||
* we copy the stack slots into reserved slots.
|
||||
*/
|
||||
JS_ASSERT(OBJ_SCOPE(obj)->object != obj);
|
||||
JS_ASSERT(obj->scope()->object != obj);
|
||||
|
||||
/* Block objects should not have reserved slots before they are put. */
|
||||
JS_ASSERT(obj->numSlots() == JS_INITIAL_NSLOTS);
|
||||
@ -3582,7 +3582,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
|
||||
/* Find a property to XDR. */
|
||||
do {
|
||||
/* If sprop is NULL, this is the first property. */
|
||||
sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProperty();
|
||||
sprop = sprop ? sprop->parent : obj->scope()->lastProperty();
|
||||
} while (!sprop->hasShortID());
|
||||
|
||||
JS_ASSERT(sprop->getter() == block_getProperty);
|
||||
@ -3769,7 +3769,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
*
|
||||
* All callers of JSObject::initSharingEmptyScope depend on this.
|
||||
*/
|
||||
if (!OBJ_SCOPE(proto)->ensureEmptyScope(cx, clasp))
|
||||
if (!proto->scope()->ensureEmptyScope(cx, clasp))
|
||||
goto bad;
|
||||
|
||||
/* If this is a standard class, cache its prototype. */
|
||||
@ -3903,7 +3903,7 @@ js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
|
||||
if (nslots > obj->numSlots() && !AllocSlots(cx, obj, nslots))
|
||||
return false;
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (!scope->isSharedEmpty()) {
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(scope->title.ownercx->thread == cx->thread);
|
||||
@ -4065,8 +4065,8 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
|
||||
if (prop) {
|
||||
if (pobj->isNative()) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))) {
|
||||
v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, pobj->scope())) {
|
||||
v = pobj->lockedGetSlot(sprop->slot);
|
||||
if (JSVAL_IS_PRIMITIVE(v))
|
||||
v = JSVAL_VOID;
|
||||
}
|
||||
@ -4150,7 +4150,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSBool
|
||||
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
|
||||
{
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
JS_ASSERT(scope->object == obj);
|
||||
|
||||
JSClass *clasp = obj->getClass();
|
||||
@ -4173,9 +4173,9 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
|
||||
void
|
||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
{
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
JS_ASSERT(scope->object == obj);
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_VOID);
|
||||
obj->lockedSetSlot(slot, JSVAL_VOID);
|
||||
if (scope->freeslot == slot + 1)
|
||||
scope->freeslot = slot;
|
||||
}
|
||||
@ -4257,7 +4257,7 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
continue;
|
||||
}
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
sprop = scope->lookup(id);
|
||||
if (sprop) {
|
||||
PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++);
|
||||
@ -4373,7 +4373,7 @@ AddPropertyHelper(JSContext *cx, JSClass *clasp, JSObject *obj, JSScope *scope,
|
||||
return false;
|
||||
if (*vp != nominal) {
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
||||
LOCKED_OBJ_SET_SLOT(obj, sprop->slot, *vp);
|
||||
obj->lockedSetSlot(sprop->slot, *vp);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -4419,14 +4419,14 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
return JS_FALSE;
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (sprop && pobj == obj && sprop->isAccessorDescriptor()) {
|
||||
sprop = OBJ_SCOPE(obj)->changeProperty(cx, sprop, attrs,
|
||||
JSPROP_GETTER | JSPROP_SETTER,
|
||||
(attrs & JSPROP_GETTER)
|
||||
? getter
|
||||
: sprop->getter(),
|
||||
(attrs & JSPROP_SETTER)
|
||||
? setter
|
||||
: sprop->setter());
|
||||
sprop = obj->scope()->changeProperty(cx, sprop, attrs,
|
||||
JSPROP_GETTER | JSPROP_SETTER,
|
||||
(attrs & JSPROP_GETTER)
|
||||
? getter
|
||||
: sprop->getter(),
|
||||
(attrs & JSPROP_SETTER)
|
||||
? setter
|
||||
: sprop->setter());
|
||||
|
||||
/* NB: obj == pobj, so we can share unlock code at the bottom. */
|
||||
if (!sprop)
|
||||
@ -4501,7 +4501,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
|
||||
/* Store value before calling addProperty, in case the latter GC's. */
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
||||
LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value);
|
||||
obj->lockedSetSlot(sprop->slot, value);
|
||||
|
||||
/* XXXbe called with lock held */
|
||||
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, &value)) {
|
||||
@ -4560,7 +4560,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
start = obj;
|
||||
for (protoIndex = 0; ; protoIndex++) {
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
sprop = scope->lookup(id);
|
||||
|
||||
/* Try obj's class resolve hook if id was not found in obj's scope. */
|
||||
@ -4638,12 +4638,12 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
* not on obj's proto chain. That last case is a
|
||||
* "too bad!" case.
|
||||
*/
|
||||
scope = OBJ_SCOPE(obj2);
|
||||
scope = obj2->scope();
|
||||
if (!scope->isSharedEmpty())
|
||||
sprop = scope->lookup(id);
|
||||
}
|
||||
if (sprop) {
|
||||
JS_ASSERT(scope == OBJ_SCOPE(obj2));
|
||||
JS_ASSERT(scope == obj2->scope());
|
||||
JS_ASSERT(!scope->isSharedEmpty());
|
||||
obj = obj2;
|
||||
} else if (obj2 != obj) {
|
||||
@ -4663,7 +4663,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
goto cleanup;
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JS_ASSERT(obj->isNative());
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
if (!scope->isSharedEmpty())
|
||||
sprop = scope->lookup(id);
|
||||
}
|
||||
@ -4679,7 +4679,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
|
||||
if (sprop) {
|
||||
SCOPE_DEPTH_ACCUM(&cx->runtime->protoLookupDepthStats, protoIndex);
|
||||
JS_ASSERT(OBJ_SCOPE(obj) == scope);
|
||||
JS_ASSERT(obj->scope() == scope);
|
||||
*objp = obj;
|
||||
|
||||
*propp = (JSProperty *) sprop;
|
||||
@ -4706,7 +4706,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
* be on the prototype chain of other objects.
|
||||
*/
|
||||
JS_ASSERT_IF(obj->getClass() != &js_BlockClass,
|
||||
OBJ_SCOPE(obj) != OBJ_SCOPE(proto));
|
||||
obj->scope() != proto->scope());
|
||||
|
||||
obj = proto;
|
||||
}
|
||||
@ -4896,11 +4896,11 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
|
||||
|
||||
JS_ASSERT(pobj->isNative());
|
||||
JS_ASSERT(JS_IS_OBJ_LOCKED(cx, pobj));
|
||||
scope = OBJ_SCOPE(pobj);
|
||||
scope = pobj->scope();
|
||||
|
||||
slot = sprop->slot;
|
||||
*vp = (slot != SPROP_INVALID_SLOT)
|
||||
? LOCKED_OBJ_GET_SLOT(pobj, slot)
|
||||
? pobj->lockedGetSlot(slot)
|
||||
: JSVAL_VOID;
|
||||
if (sprop->hasDefaultGetter())
|
||||
return true;
|
||||
@ -4928,7 +4928,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return false;
|
||||
}
|
||||
LOCKED_OBJ_SET_SLOT(pobj, slot, v);
|
||||
pobj->lockedSetSlot(slot, v);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -4946,7 +4946,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
|
||||
|
||||
JS_ASSERT(obj->isNative());
|
||||
JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
|
||||
slot = sprop->slot;
|
||||
if (slot != SPROP_INVALID_SLOT) {
|
||||
@ -4958,7 +4958,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return false;
|
||||
}
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, *vp);
|
||||
obj->lockedSetSlot(slot, *vp);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -4989,7 +4989,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return false;
|
||||
}
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, v);
|
||||
obj->lockedSetSlot(slot, v);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -5188,10 +5188,10 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||
id = js_CheckForStringIndex(id);
|
||||
|
||||
/*
|
||||
* We peek at OBJ_SCOPE(obj) without locking obj. Any race means a failure
|
||||
* We peek at obj->scope() without locking obj. Any race means a failure
|
||||
* to seal before sharing, which is inherently ambiguous.
|
||||
*/
|
||||
if (OBJ_SCOPE(obj)->sealed() && OBJ_SCOPE(obj)->object == obj)
|
||||
if (obj->scope()->sealed() && obj->scope()->object == obj)
|
||||
return ReportReadOnly(cx, id, JSREPORT_ERROR);
|
||||
|
||||
protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
|
||||
@ -5233,7 +5233,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||
* we know pobj owns it (i.e., scope->object == pobj). Therefore we
|
||||
* optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope).
|
||||
*/
|
||||
scope = OBJ_SCOPE(pobj);
|
||||
scope = pobj->scope();
|
||||
|
||||
/* ES5 8.12.4 [[Put]] step 2. */
|
||||
if (sprop->isAccessorDescriptor()) {
|
||||
@ -5373,7 +5373,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||
* in js_DefineNativeProperty.
|
||||
*/
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
||||
LOCKED_OBJ_SET_SLOT(obj, sprop->slot, JSVAL_VOID);
|
||||
obj->lockedSetSlot(sprop->slot, JSVAL_VOID);
|
||||
|
||||
/* XXXbe called with obj locked */
|
||||
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, vp)) {
|
||||
@ -5513,9 +5513,9 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
||||
GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
|
||||
GC_POKE(cx, obj->lockedGetSlot(sprop->slot));
|
||||
|
||||
ok = scope->removeProperty(cx, id);
|
||||
obj->dropProperty(cx, prop);
|
||||
@ -5540,7 +5540,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
||||
jsid toStringId = ATOM_TO_JSID(cx->runtime->atomState.toStringAtom);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
JSScopeProperty *sprop = scope->lookup(toStringId);
|
||||
JSObject *pobj = obj;
|
||||
|
||||
@ -5550,13 +5550,13 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
||||
if (pobj && pobj->getClass() == &js_StringClass) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
JS_LOCK_OBJ(cx, pobj);
|
||||
scope = OBJ_SCOPE(pobj);
|
||||
scope = pobj->scope();
|
||||
sprop = scope->lookup(toStringId);
|
||||
}
|
||||
}
|
||||
|
||||
if (sprop && sprop->hasDefaultGetter() && SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||
jsval fval = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
jsval fval = pobj->lockedGetSlot(sprop->slot);
|
||||
|
||||
if (VALUE_IS_FUNCTION(cx, fval)) {
|
||||
JSObject *funobj = JSVAL_TO_OBJECT(fval);
|
||||
@ -5719,7 +5719,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
JSNativeEnumerator *ne;
|
||||
uint32 length;
|
||||
do {
|
||||
uint32 shape = OBJ_SHAPE(obj);
|
||||
uint32 shape = obj->shape();
|
||||
|
||||
ENUM_CACHE_METER(nativeEnumProbes);
|
||||
jsuword *cachep = &JS_THREAD_DATA(cx)->
|
||||
@ -5748,7 +5748,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
||||
/* Count all enumerable properties in object's scope. */
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
length = 0;
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if (sprop->enumerable() && !sprop->isAlias())
|
||||
@ -5938,8 +5938,8 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
sprop = (JSScopeProperty *)prop;
|
||||
*attrsp = sprop->attributes();
|
||||
if (!writing) {
|
||||
*vp = (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)))
|
||||
? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
|
||||
*vp = (SPROP_HAS_VALID_SLOT(sprop, pobj->scope()))
|
||||
? pobj->lockedGetSlot(sprop->slot)
|
||||
: JSVAL_VOID;
|
||||
}
|
||||
pobj->dropProperty(cx, prop);
|
||||
@ -6518,7 +6518,7 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
||||
|
||||
JSScopeProperty *sprop;
|
||||
if (obj->isNative()) {
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
sprop = scope->lastProperty();
|
||||
while (sprop && sprop->slot != slot)
|
||||
sprop = sprop->parent;
|
||||
@ -6560,7 +6560,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
JSContext *cx = trc->context;
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (!scope->isSharedEmpty() && IS_GC_MARKING_TRACER(trc)) {
|
||||
/*
|
||||
* Check whether we should shrink the object's slots. Skip this check
|
||||
@ -6627,7 +6627,7 @@ js_Clear(JSContext *cx, JSObject *obj)
|
||||
* NB: we do not clear any reserved slots lying below JSSLOT_FREE(clasp).
|
||||
*/
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
if (!scope->isSharedEmpty()) {
|
||||
/* Now that we're done using scope->lastProp/table, clear scope. */
|
||||
scope->clear(cx);
|
||||
@ -6720,7 +6720,7 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
|
||||
* their own scopes before mutating, and elsewhere (e.g. js_TraceObject) we
|
||||
* use obj->numSlots() rather than rely on freeslot.
|
||||
*/
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (!scope->isSharedEmpty() && slot >= scope->freeslot)
|
||||
scope->freeslot = slot + 1;
|
||||
|
||||
@ -6950,7 +6950,7 @@ js_DumpObject(JSObject *obj)
|
||||
}
|
||||
|
||||
if (obj->isNative()) {
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (scope->sealed())
|
||||
fprintf(stderr, "sealed\n");
|
||||
|
||||
@ -6980,8 +6980,8 @@ js_DumpObject(JSObject *obj)
|
||||
|
||||
fprintf(stderr, "slots:\n");
|
||||
reservedEnd = i + JSCLASS_RESERVED_SLOTS(clasp);
|
||||
slots = (obj->isNative() && !OBJ_SCOPE(obj)->isSharedEmpty())
|
||||
? OBJ_SCOPE(obj)->freeslot
|
||||
slots = (obj->isNative() && !obj->scope()->isSharedEmpty())
|
||||
? obj->scope()->freeslot
|
||||
: obj->numSlots();
|
||||
for (; i < slots; i++) {
|
||||
fprintf(stderr, " %3d ", i);
|
||||
|
@ -269,6 +269,9 @@ struct JSObject {
|
||||
return clasp == getClass();
|
||||
}
|
||||
|
||||
inline JSScope *scope() const;
|
||||
inline uint32 shape() const;
|
||||
|
||||
bool isDelegate() const {
|
||||
return (classword & jsuword(1)) != jsuword(0);
|
||||
}
|
||||
@ -317,6 +320,9 @@ struct JSObject {
|
||||
}
|
||||
}
|
||||
|
||||
inline jsval lockedGetSlot(uintN slot) const;
|
||||
inline void lockedSetSlot(uintN slot, jsval value);
|
||||
|
||||
/*
|
||||
* These ones are for multi-threaded ("MT") objects. Use getSlot(),
|
||||
* getSlotRef(), setSlot() to directly manipulate slots in obj when only
|
||||
@ -536,12 +542,7 @@ struct JSObject {
|
||||
#define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(jsval) - 1)
|
||||
|
||||
#define OBJ_CHECK_SLOT(obj,slot) \
|
||||
(JS_ASSERT(obj->isNative()), JS_ASSERT(slot < OBJ_SCOPE(obj)->freeslot))
|
||||
|
||||
#define LOCKED_OBJ_GET_SLOT(obj,slot) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), obj->getSlot(slot))
|
||||
#define LOCKED_OBJ_SET_SLOT(obj,slot,value) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), obj->setSlot(slot, value))
|
||||
(JS_ASSERT((obj)->isNative()), JS_ASSERT(slot < (obj)->scope()->freeslot))
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
@ -617,7 +618,7 @@ extern JSBool
|
||||
js_DefineBlockVariable(JSContext *cx, JSObject *obj, jsid id, intN index);
|
||||
|
||||
#define OBJ_BLOCK_COUNT(cx,obj) \
|
||||
(OBJ_SCOPE(OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->entryCount)
|
||||
((OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->scope()->entryCount)
|
||||
#define OBJ_BLOCK_DEPTH(cx,obj) \
|
||||
JSVAL_TO_INT(obj->getSlot(JSSLOT_BLOCK_DEPTH))
|
||||
#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
|
||||
|
@ -51,18 +51,18 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
|
||||
/*
|
||||
* If thread-safe, define a getSlotMT() that bypasses, for a native
|
||||
* object, the lock-free "fast path" test of
|
||||
* (OBJ_SCOPE(obj)->ownercx == cx), to avoid needlessly switching from
|
||||
* (obj->scope()->ownercx == cx), to avoid needlessly switching from
|
||||
* lock-free to lock-full scope when doing GC on a different context
|
||||
* from the last one to own the scope. The caller in this case is
|
||||
* probably a JSClass.mark function, e.g., fun_mark, or maybe a
|
||||
* finalizer.
|
||||
*/
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
return (OBJ_SCOPE(this)->title.ownercx == cx)
|
||||
? LOCKED_OBJ_GET_SLOT(this, slot)
|
||||
return (scope()->title.ownercx == cx)
|
||||
? this->lockedGetSlot(slot)
|
||||
: js_GetSlotThreadSafe(cx, this, slot);
|
||||
#else
|
||||
return LOCKED_OBJ_GET_SLOT(this, slot);
|
||||
return this->lockedGetSlot(slot);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -72,12 +72,12 @@ JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value)
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Thread-safe way to set a slot. */
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
if (OBJ_SCOPE(this)->title.ownercx == cx)
|
||||
LOCKED_OBJ_SET_SLOT(this, slot, value);
|
||||
if (scope()->title.ownercx == cx)
|
||||
this->lockedSetSlot(slot, value);
|
||||
else
|
||||
js_SetSlotThreadSafe(cx, this, slot, value);
|
||||
#else
|
||||
LOCKED_OBJ_SET_SLOT(this, slot, value);
|
||||
this->lockedSetSlot(slot, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ JSObject::initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *paren
|
||||
{
|
||||
init(clasp, proto, parent, privateSlotValue);
|
||||
|
||||
JSEmptyScope *emptyScope = OBJ_SCOPE(proto)->emptyScope;
|
||||
JSEmptyScope *emptyScope = proto->scope()->emptyScope;
|
||||
JS_ASSERT(emptyScope->clasp == clasp);
|
||||
emptyScope->hold();
|
||||
map = emptyScope;
|
||||
@ -167,7 +167,7 @@ JSObject::unbrand(JSContext *cx)
|
||||
{
|
||||
if (this->isNative()) {
|
||||
JS_LOCK_OBJ(cx, this);
|
||||
JSScope *scope = OBJ_SCOPE(this);
|
||||
JSScope *scope = this->scope();
|
||||
if (scope->isSharedEmpty()) {
|
||||
scope = js_GetMutableScope(cx, this);
|
||||
if (!scope) {
|
||||
|
@ -279,7 +279,7 @@ ToDisassemblySource(JSContext *cx, jsval v)
|
||||
|
||||
if (clasp == &js_BlockClass) {
|
||||
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
|
||||
for (JSScopeProperty *sprop = OBJ_SCOPE(obj)->lastProperty();
|
||||
for (JSScopeProperty *sprop = obj->scope()->lastProperty();
|
||||
sprop;
|
||||
sprop = sprop->parent) {
|
||||
const char *bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id));
|
||||
@ -1324,7 +1324,7 @@ GetLocal(SprintStack *ss, jsint i)
|
||||
}
|
||||
|
||||
i -= depth;
|
||||
for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
for (sprop = obj->scope()->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if (sprop->shortid == i)
|
||||
break;
|
||||
}
|
||||
@ -2645,7 +2645,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
MUST_FLOW_THROUGH("enterblock_out");
|
||||
#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
|
||||
goto enterblock_out)
|
||||
for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop;
|
||||
for (sprop = obj->scope()->lastProperty(); sprop;
|
||||
sprop = sprop->parent) {
|
||||
if (!sprop->hasShortID())
|
||||
continue;
|
||||
|
@ -608,7 +608,7 @@ END_CASE(JSOP_PICK)
|
||||
JS_ASSERT((sprop)->slot != SPROP_INVALID_SLOT || \
|
||||
!sprop->hasDefaultSetter()); \
|
||||
*vp = ((sprop)->slot != SPROP_INVALID_SLOT) \
|
||||
? LOCKED_OBJ_GET_SLOT(pobj, (sprop)->slot) \
|
||||
? (pobj)->lockedGetSlot((sprop)->slot) \
|
||||
: JSVAL_VOID; \
|
||||
} else { \
|
||||
if (!js_NativeGet(cx, obj, pobj, sprop, getHow, vp)) \
|
||||
@ -621,9 +621,9 @@ END_CASE(JSOP_PICK)
|
||||
TRACE_2(SetPropHit, entry, sprop); \
|
||||
if (sprop->hasDefaultSetter() && \
|
||||
(sprop)->slot != SPROP_INVALID_SLOT && \
|
||||
!OBJ_SCOPE(obj)->brandedOrHasMethodBarrier()) { \
|
||||
!(obj)->scope()->brandedOrHasMethodBarrier()) { \
|
||||
/* Fast path for, e.g., plain Object instance properties. */ \
|
||||
LOCKED_OBJ_SET_SLOT(obj, (sprop)->slot, *vp); \
|
||||
(obj)->lockedSetSlot((sprop)->slot, *vp); \
|
||||
} else { \
|
||||
if (!js_NativeSet(cx, obj, sprop, false, vp)) \
|
||||
goto error; \
|
||||
@ -1208,14 +1208,14 @@ BEGIN_CASE(JSOP_NAMEDEC)
|
||||
ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
|
||||
if (obj == obj2 && entry->vword.isSlot()) {
|
||||
slot = entry->vword.toSlot();
|
||||
JS_ASSERT(slot < OBJ_SCOPE(obj)->freeslot);
|
||||
rval = LOCKED_OBJ_GET_SLOT(obj, slot);
|
||||
JS_ASSERT(slot < obj->scope()->freeslot);
|
||||
rval = obj->lockedGetSlot(slot);
|
||||
if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
|
||||
rtmp = rval;
|
||||
rval += (js_CodeSpec[op].format & JOF_INC) ? 2 : -2;
|
||||
if (!(js_CodeSpec[op].format & JOF_POST))
|
||||
rtmp = rval;
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, rval);
|
||||
obj->lockedSetSlot(slot, rval);
|
||||
PUSH_OPND(rtmp);
|
||||
len = JSOP_INCNAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
@ -1472,8 +1472,8 @@ BEGIN_CASE(JSOP_GETXPROP)
|
||||
rval = entry->vword.toJsval();
|
||||
} else if (entry->vword.isSlot()) {
|
||||
slot = entry->vword.toSlot();
|
||||
JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);
|
||||
rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
|
||||
JS_ASSERT(slot < obj2->scope()->freeslot);
|
||||
rval = obj2->lockedGetSlot(slot);
|
||||
} else {
|
||||
JS_ASSERT(entry->vword.isSprop());
|
||||
sprop = entry->vword.toSprop();
|
||||
@ -1564,8 +1564,8 @@ BEGIN_CASE(JSOP_CALLPROP)
|
||||
rval = entry->vword.toJsval();
|
||||
} else if (entry->vword.isSlot()) {
|
||||
slot = entry->vword.toSlot();
|
||||
JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);
|
||||
rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
|
||||
JS_ASSERT(slot < obj2->scope()->freeslot);
|
||||
rval = obj2->lockedGetSlot(slot);
|
||||
} else {
|
||||
JS_ASSERT(entry->vword.isSprop());
|
||||
sprop = entry->vword.toSprop();
|
||||
@ -1682,7 +1682,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||
JS_ASSERT(sprop->writable());
|
||||
JS_ASSERT_IF(sprop->hasSlot(), entry->vcapTag() == 0);
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
JS_ASSERT(!scope->sealed());
|
||||
|
||||
/*
|
||||
@ -1696,7 +1696,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||
if (entry->vcapTag() == 0 ||
|
||||
((obj2 = obj->getProto()) &&
|
||||
obj2->isNative() &&
|
||||
OBJ_SHAPE(obj2) == entry->vshape())) {
|
||||
obj2->shape() == entry->vshape())) {
|
||||
goto fast_set_propcache_hit;
|
||||
}
|
||||
|
||||
@ -1790,7 +1790,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||
* branded scope.
|
||||
*/
|
||||
TRACE_2(SetPropHit, entry, sprop);
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, rval);
|
||||
obj->lockedSetSlot(slot, rval);
|
||||
|
||||
/*
|
||||
* Purge the property cache of the id we may have just
|
||||
@ -1812,7 +1812,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||
if (obj == obj2) {
|
||||
sprop = entry->vword.toSprop();
|
||||
JS_ASSERT(sprop->writable());
|
||||
JS_ASSERT(!OBJ_SCOPE(obj2)->sealed());
|
||||
JS_ASSERT(!obj2->scope()->sealed());
|
||||
NATIVE_SET(cx, obj, sprop, entry, &rval);
|
||||
}
|
||||
if (sprop)
|
||||
@ -2284,8 +2284,8 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
|
||||
if (entry->vword.isSlot()) {
|
||||
slot = entry->vword.toSlot();
|
||||
JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);
|
||||
rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
|
||||
JS_ASSERT(slot < obj2->scope()->freeslot);
|
||||
rval = obj2->lockedGetSlot(slot);
|
||||
goto do_push_rval;
|
||||
}
|
||||
|
||||
@ -2708,8 +2708,8 @@ BEGIN_CASE(JSOP_CALLDSLOT)
|
||||
|
||||
index = GET_UINT16(regs.pc);
|
||||
JS_ASSERT(JS_INITIAL_NSLOTS + index < jsatomid(obj->dslots[-1]));
|
||||
JS_ASSERT_IF(OBJ_SCOPE(obj)->object == obj,
|
||||
JS_INITIAL_NSLOTS + index < OBJ_SCOPE(obj)->freeslot);
|
||||
JS_ASSERT_IF(obj->scope()->object == obj,
|
||||
JS_INITIAL_NSLOTS + index < obj->scope()->freeslot);
|
||||
|
||||
PUSH_OPND(obj->dslots[index]);
|
||||
if (op == JSOP_CALLDSLOT)
|
||||
@ -2760,12 +2760,12 @@ BEGIN_CASE(JSOP_SETGVAR)
|
||||
} else {
|
||||
slot = JSVAL_TO_INT(lval);
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
if (!scope->methodWriteBarrier(cx, slot, rval)) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
goto error;
|
||||
}
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, rval);
|
||||
obj->lockedSetSlot(slot, rval);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
}
|
||||
END_SET_CASE(JSOP_SETGVAR)
|
||||
@ -2825,7 +2825,7 @@ BEGIN_CASE(JSOP_DEFVAR)
|
||||
obj->isNative()) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (!sprop->configurable() &&
|
||||
SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
|
||||
SPROP_HAS_VALID_SLOT(sprop, obj->scope()) &&
|
||||
sprop->hasDefaultGetterOrIsMethod() &&
|
||||
sprop->hasDefaultSetter()) {
|
||||
/*
|
||||
@ -3137,7 +3137,7 @@ BEGIN_CASE(JSOP_LAMBDA)
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
|
||||
obj2 = JSVAL_TO_OBJECT(lval);
|
||||
JS_ASSERT(obj2->getClass() == &js_ObjectClass);
|
||||
JS_ASSERT(OBJ_SCOPE(obj2)->object == obj2);
|
||||
JS_ASSERT(obj2->scope()->object == obj2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3350,7 +3350,7 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
||||
JS_ASSERT(!obj->getClass()->reserveSlots);
|
||||
JS_ASSERT(!(obj->getClass()->flags & JSCLASS_SHARE_ALL_PROPERTIES));
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
PropertyCacheEntry *entry;
|
||||
|
||||
/*
|
||||
@ -3403,7 +3403,7 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
||||
* contain a method of a branded scope.
|
||||
*/
|
||||
TRACE_2(SetPropHit, entry, sprop);
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, rval);
|
||||
obj->lockedSetSlot(slot, rval);
|
||||
} else {
|
||||
PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
|
||||
|
||||
|
@ -3211,7 +3211,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
||||
|
||||
/*
|
||||
* Define the let binding's property before storing pn in a reserved slot,
|
||||
* since block_reserveSlots depends on OBJ_SCOPE(blockObj)->entryCount.
|
||||
* since block_reserveSlots depends on blockObj->scope()->entryCount.
|
||||
*/
|
||||
if (!js_DefineBlockVariable(cx, blockObj, ATOM_TO_JSID(atom), n))
|
||||
return JS_FALSE;
|
||||
@ -3227,7 +3227,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
|
||||
!js_GrowSlots(cx, blockObj, slot + 1)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
OBJ_SCOPE(blockObj)->freeslot = slot + 1;
|
||||
blockObj->scope()->freeslot = slot + 1;
|
||||
blockObj->setSlot(slot, PRIVATE_TO_JSVAL(pn));
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -3239,7 +3239,7 @@ PopStatement(JSTreeContext *tc)
|
||||
|
||||
if (stmt->flags & SIF_SCOPE) {
|
||||
JSObject *obj = stmt->blockObj;
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSScope *scope = obj->scope();
|
||||
JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj));
|
||||
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
|
@ -71,7 +71,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
* Check for fill from js_SetPropertyHelper where the setter removed sprop
|
||||
* from pobj's scope (via unwatch or delete, e.g.).
|
||||
*/
|
||||
scope = OBJ_SCOPE(pobj);
|
||||
scope = pobj->scope();
|
||||
if (!scope->hasProperty(sprop)) {
|
||||
PCMETER(oddfills++);
|
||||
return JS_NO_PROP_CACHE_FILL;
|
||||
@ -149,7 +149,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
JS_ASSERT(scope->hasMethodBarrier());
|
||||
v = sprop->methodValue();
|
||||
JS_ASSERT(VALUE_IS_FUNCTION(cx, v));
|
||||
JS_ASSERT(v == LOCKED_OBJ_GET_SLOT(pobj, sprop->slot));
|
||||
JS_ASSERT(v == pobj->lockedGetSlot(sprop->slot));
|
||||
vword.setObject(JSVAL_TO_OBJECT(v));
|
||||
break;
|
||||
}
|
||||
@ -157,7 +157,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
if (!scope->generic() &&
|
||||
sprop->hasDefaultGetter() &&
|
||||
SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||
v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
v = pobj->lockedGetSlot(sprop->slot);
|
||||
if (VALUE_IS_FUNCTION(cx, v)) {
|
||||
/*
|
||||
* Great, we have a function-valued prototype property
|
||||
@ -179,7 +179,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
pobj, pobj->getClass()->name,
|
||||
JSVAL_TO_OBJECT(v),
|
||||
JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))),
|
||||
OBJ_SHAPE(obj));
|
||||
obj->shape());
|
||||
#endif
|
||||
if (!scope->brand(cx, sprop->slot, v))
|
||||
return JS_NO_PROP_CACHE_FILL;
|
||||
@ -246,7 +246,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
JSObject *proto = obj->getProto();
|
||||
if (!proto || !proto->isNative())
|
||||
return JS_NO_PROP_CACHE_FILL;
|
||||
JSScope *protoscope = OBJ_SCOPE(proto);
|
||||
JSScope *protoscope = proto->scope();
|
||||
if (!protoscope->emptyScope ||
|
||||
protoscope->emptyScope->clasp != obj->getClass()) {
|
||||
return JS_NO_PROP_CACHE_FILL;
|
||||
@ -264,7 +264,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
|
||||
} while (0);
|
||||
|
||||
if (kshape == 0) {
|
||||
kshape = OBJ_SHAPE(obj);
|
||||
kshape = obj->shape();
|
||||
vshape = scope->shape;
|
||||
}
|
||||
JS_ASSERT(kshape < SHAPE_OVERFLOW_BIT);
|
||||
@ -354,7 +354,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
pc - cx->fp->script->code,
|
||||
entry->kpc - cx->fp->script->code,
|
||||
entry->kshape,
|
||||
OBJ_SHAPE(obj));
|
||||
obj->shape());
|
||||
js_Disassemble1(cx, cx->fp->script, pc,
|
||||
pc - cx->fp->script->code,
|
||||
JS_FALSE, stderr);
|
||||
@ -401,8 +401,8 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
jsid id = ATOM_TO_JSID(atom);
|
||||
|
||||
id = js_CheckForStringIndex(id);
|
||||
JS_ASSERT(OBJ_SCOPE(pobj)->lookup(id));
|
||||
JS_ASSERT_IF(OBJ_SCOPE(pobj)->object, OBJ_SCOPE(pobj)->object == pobj);
|
||||
JS_ASSERT(pobj->scope()->lookup(id));
|
||||
JS_ASSERT_IF(pobj->scope()->object, pobj->scope()->object == pobj);
|
||||
#endif
|
||||
*pobjp = pobj;
|
||||
return NULL;
|
||||
|
@ -252,7 +252,7 @@ class PropertyCache
|
||||
/*
|
||||
* Fill property cache entry for key cx->fp->pc, optimized value word
|
||||
* computed from obj and sprop, and entry capability forged from 24-bit
|
||||
* OBJ_SHAPE(obj), 4-bit scopeIndex, and 4-bit protoIndex.
|
||||
* obj->shape(), 4-bit scopeIndex, and 4-bit protoIndex.
|
||||
*
|
||||
* Return the filled cache entry or JS_NO_PROP_CACHE_FILL if caching was
|
||||
* not possible.
|
||||
|
@ -50,7 +50,7 @@ using namespace js;
|
||||
/* static */ inline bool
|
||||
PropertyCache::matchShape(JSContext *cx, JSObject *obj, uint32 shape)
|
||||
{
|
||||
return CX_OWNS_OBJECT_TITLE(cx, obj) && OBJ_SHAPE(obj) == shape;
|
||||
return CX_OWNS_OBJECT_TITLE(cx, obj) && obj->shape() == shape;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -97,7 +97,7 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
|
||||
JSClass *clasp;
|
||||
uint32 freeslot;
|
||||
|
||||
scope = OBJ_SCOPE(obj);
|
||||
scope = obj->scope();
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
|
||||
if (!scope->isSharedEmpty())
|
||||
return scope;
|
||||
@ -120,8 +120,8 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
|
||||
clasp = obj->getClass();
|
||||
if (clasp->reserveSlots) {
|
||||
/*
|
||||
* FIXME: Here we change OBJ_SCOPE(obj)->freeslot without changing
|
||||
* OBJ_SHAPE(obj). If we strengthen the shape guarantees to cover
|
||||
* FIXME: Here we change obj->scope()->freeslot without changing
|
||||
* obj->shape(). If we strengthen the shape guarantees to cover
|
||||
* freeslot, we can eliminate a check in JSOP_SETPROP and in
|
||||
* js_AddProperty. See bug 535416.
|
||||
*/
|
||||
@ -1143,7 +1143,7 @@ JSScope::clear(JSContext *cx)
|
||||
uint32 newShape;
|
||||
if (proto &&
|
||||
proto->isNative() &&
|
||||
(emptyScope = OBJ_SCOPE(proto)->emptyScope) &&
|
||||
(emptyScope = proto->scope()->emptyScope) &&
|
||||
emptyScope->clasp == clasp) {
|
||||
newShape = emptyScope->shape;
|
||||
} else {
|
||||
@ -1167,7 +1167,7 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval)
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
if (sprop->isMethod()) {
|
||||
#ifdef DEBUG
|
||||
jsval prev = LOCKED_OBJ_GET_SLOT(object, sprop->slot);
|
||||
jsval prev = object->lockedGetSlot(sprop->slot);
|
||||
JS_ASSERT(sprop->methodValue() == prev);
|
||||
JS_ASSERT(hasMethodBarrier());
|
||||
JS_ASSERT(object->getClass() == &js_ObjectClass);
|
||||
|
@ -541,17 +541,31 @@ JS_IS_SCOPE_LOCKED(JSContext *cx, JSScope *scope)
|
||||
}
|
||||
|
||||
inline JSScope *
|
||||
OBJ_SCOPE(JSObject *obj)
|
||||
JSObject::scope() const
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
return (JSScope *) obj->map;
|
||||
JS_ASSERT(isNative());
|
||||
return (JSScope *) map;
|
||||
}
|
||||
|
||||
inline uint32
|
||||
OBJ_SHAPE(JSObject *obj)
|
||||
JSObject::shape() const
|
||||
{
|
||||
JS_ASSERT(obj->map->shape != JSObjectMap::SHAPELESS);
|
||||
return obj->map->shape;
|
||||
JS_ASSERT(map->shape != JSObjectMap::SHAPELESS);
|
||||
return map->shape;
|
||||
}
|
||||
|
||||
inline jsval
|
||||
JSObject::lockedGetSlot(uintN slot) const
|
||||
{
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
return this->getSlot(slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::lockedSetSlot(uintN slot, jsval value)
|
||||
{
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
this->setSlot(slot, value);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -973,7 +987,7 @@ JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp)
|
||||
if (isMethod()) {
|
||||
*vp = methodValue();
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(pobj);
|
||||
JSScope *scope = pobj->scope();
|
||||
JS_ASSERT(scope->object == pobj);
|
||||
return scope->methodReadBarrier(cx, this, vp);
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ inline bool
|
||||
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v)
|
||||
{
|
||||
if (flags & (BRANDED | METHOD_BARRIER)) {
|
||||
jsval prev = LOCKED_OBJ_GET_SLOT(object, sprop->slot);
|
||||
jsval prev = object->lockedGetSlot(sprop->slot);
|
||||
|
||||
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
|
||||
return methodShapeChange(cx, sprop, v);
|
||||
@ -149,7 +149,7 @@ inline bool
|
||||
JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, jsval v)
|
||||
{
|
||||
if (flags & (BRANDED | METHOD_BARRIER)) {
|
||||
jsval prev = LOCKED_OBJ_GET_SLOT(object, slot);
|
||||
jsval prev = object->lockedGetSlot(slot);
|
||||
|
||||
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
|
||||
return methodShapeChange(cx, slot, v);
|
||||
|
@ -1120,7 +1120,7 @@ GlobalSlotHash(JSContext* cx, unsigned slot)
|
||||
fp = fp->down;
|
||||
|
||||
HashAccum(h, uintptr_t(fp->script), ORACLE_MASK);
|
||||
HashAccum(h, uintptr_t(OBJ_SHAPE(fp->scopeChain->getGlobal())), ORACLE_MASK);
|
||||
HashAccum(h, uintptr_t(fp->scopeChain->getGlobal()->shape()), ORACLE_MASK);
|
||||
HashAccum(h, uintptr_t(slot), ORACLE_MASK);
|
||||
return int(h);
|
||||
}
|
||||
@ -1539,7 +1539,7 @@ AttemptCompilation(JSContext *cx, JSObject* globalObj, jsbytecode* pc, uint32 ar
|
||||
ResetRecordingAttempts(cx, pc);
|
||||
|
||||
/* Breathe new life into all peer fragments at the designated loop header. */
|
||||
TreeFragment* f = LookupLoop(tm, pc, globalObj, OBJ_SHAPE(globalObj), argc);
|
||||
TreeFragment* f = LookupLoop(tm, pc, globalObj, globalObj->shape(), argc);
|
||||
if (!f) {
|
||||
/*
|
||||
* If the global object's shape changed, we can't easily find the
|
||||
@ -2212,7 +2212,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
|
||||
fragment->profFragID);
|
||||
|
||||
debug_only_printf(LC_TMTracer, "globalObj=%p, shape=%d\n",
|
||||
(void*)this->globalObj, OBJ_SHAPE(this->globalObj));
|
||||
(void*)this->globalObj, this->globalObj->shape());
|
||||
debug_only_printf(LC_TMTreeVis, "TREEVIS RECORD FRAG=%p ANCHOR=%p\n", (void*)fragment,
|
||||
(void*)anchor);
|
||||
#endif
|
||||
@ -5255,11 +5255,11 @@ TraceRecorder::hasMethod(JSObject* obj, jsid id, bool& found)
|
||||
// it's there now, if found in a non-native object.
|
||||
status = RECORD_STOP;
|
||||
} else {
|
||||
JSScope* scope = OBJ_SCOPE(pobj);
|
||||
JSScope* scope = pobj->scope();
|
||||
JSScopeProperty* sprop = (JSScopeProperty*) prop;
|
||||
|
||||
if (sprop->hasDefaultGetterOrIsMethod() && SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||
jsval v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
jsval v = pobj->lockedGetSlot(sprop->slot);
|
||||
if (VALUE_IS_FUNCTION(cx, v)) {
|
||||
found = true;
|
||||
if (!scope->generic() && !scope->branded() && !scope->brand(cx, sprop->slot, v))
|
||||
@ -5300,7 +5300,7 @@ CheckGlobalObjectShape(JSContext* cx, TraceMonitor* tm, JSObject* globalObj,
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 globalShape = OBJ_SHAPE(globalObj);
|
||||
uint32 globalShape = globalObj->shape();
|
||||
|
||||
if (tm->recorder) {
|
||||
TreeFragment* root = tm->recorder->getFragment()->root;
|
||||
@ -5915,7 +5915,7 @@ JS_REQUIRES_STACK bool
|
||||
TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (OBJ_SCOPE(cx->fp->scopeChain->getGlobal())->title.ownercx != cx) {
|
||||
if (cx->fp->scopeChain->getGlobal()->scope()->title.ownercx != cx) {
|
||||
AbortRecording(cx, "Global object not owned by this context");
|
||||
return false; /* we stay away from shared global objects */
|
||||
}
|
||||
@ -6445,7 +6445,7 @@ ScopeChainCheck(JSContext* cx, TreeFragment* f)
|
||||
JS_ASSERT(f->globalObj->numSlots() <= MAX_GLOBAL_SLOTS);
|
||||
JS_ASSERT(f->nGlobalTypes() == f->globalSlots->length());
|
||||
JS_ASSERT_IF(f->globalSlots->length() != 0,
|
||||
OBJ_SHAPE(f->globalObj) == f->globalShape);
|
||||
f->globalObj->shape() == f->globalShape);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7864,7 +7864,7 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, jsval*& vp, LIns*& ins, NameR
|
||||
obj2->dropProperty(cx, prop);
|
||||
RETURN_STOP_A("prototype property");
|
||||
}
|
||||
if (!isValidSlot(OBJ_SCOPE(obj), sprop)) {
|
||||
if (!isValidSlot(obj->scope(), sprop)) {
|
||||
obj2->dropProperty(cx, prop);
|
||||
return ARECORD_STOP;
|
||||
}
|
||||
@ -9012,7 +9012,7 @@ static FILE* shapefp = NULL;
|
||||
static void
|
||||
DumpShape(JSObject* obj, const char* prefix)
|
||||
{
|
||||
JSScope* scope = OBJ_SCOPE(obj);
|
||||
JSScope* scope = obj->scope();
|
||||
|
||||
if (!shapefp) {
|
||||
shapefp = fopen("/tmp/shapes.dump", "w");
|
||||
@ -9265,7 +9265,7 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins,
|
||||
// For any hit that goes up the scope and/or proto chains, we will need to
|
||||
// guard on the shape of the object containing the property.
|
||||
if (entry->vcapTag() >= 1) {
|
||||
JS_ASSERT(OBJ_SHAPE(obj2) == vshape);
|
||||
JS_ASSERT(obj2->shape() == vshape);
|
||||
if (obj2 == globalObj)
|
||||
RETURN_STOP("hitting the global object via a prototype chain");
|
||||
|
||||
@ -9567,7 +9567,7 @@ TraceRecorder::guardPrototypeHasNoIndexedProperties(JSObject* obj, LIns* obj_ins
|
||||
return RECORD_STOP;
|
||||
|
||||
while (guardHasPrototype(obj, obj_ins, &obj, &obj_ins, exit))
|
||||
CHECK_STATUS(guardShape(obj_ins, obj, OBJ_SHAPE(obj), "guard(shape)", exit));
|
||||
CHECK_STATUS(guardShape(obj_ins, obj, obj->shape(), "guard(shape)", exit));
|
||||
return RECORD_CONTINUE;
|
||||
}
|
||||
|
||||
@ -10359,7 +10359,7 @@ TraceRecorder::getClassPrototype(JSObject* ctor, LIns*& proto_ins)
|
||||
// that pval is usable.
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(pval));
|
||||
JSObject *proto = JSVAL_TO_OBJECT(pval);
|
||||
JS_ASSERT_IF(clasp != &js_ArrayClass, OBJ_SCOPE(proto)->emptyScope->clasp == clasp);
|
||||
JS_ASSERT_IF(clasp != &js_ArrayClass, proto->scope()->emptyScope->clasp == clasp);
|
||||
|
||||
proto_ins = INS_CONSTOBJ(proto);
|
||||
return RECORD_CONTINUE;
|
||||
@ -10383,7 +10383,7 @@ TraceRecorder::getClassPrototype(JSProtoKey key, LIns*& proto_ins)
|
||||
/* Double-check that a native proto has a matching emptyScope. */
|
||||
if (key != JSProto_Array) {
|
||||
JS_ASSERT(proto->isNative());
|
||||
JSEmptyScope *emptyScope = OBJ_SCOPE(proto)->emptyScope;
|
||||
JSEmptyScope *emptyScope = proto->scope()->emptyScope;
|
||||
JS_ASSERT(emptyScope);
|
||||
JS_ASSERT(JSCLASS_CACHED_PROTO_KEY(emptyScope->clasp) == key);
|
||||
}
|
||||
@ -11165,7 +11165,7 @@ JS_REQUIRES_STACK RecordingStatus
|
||||
TraceRecorder::nativeSet(JSObject* obj, LIns* obj_ins, JSScopeProperty* sprop,
|
||||
jsval v, LIns* v_ins)
|
||||
{
|
||||
JSScope* scope = OBJ_SCOPE(obj);
|
||||
JSScope* scope = obj->scope();
|
||||
uint32 slot = sprop->slot;
|
||||
|
||||
/*
|
||||
@ -11219,7 +11219,7 @@ MethodWriteBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObjec
|
||||
{
|
||||
AutoValueRooter tvr(cx, funobj);
|
||||
|
||||
return OBJ_SCOPE(obj)->methodWriteBarrier(cx, sprop, tvr.value());
|
||||
return obj->scope()->methodWriteBarrier(cx, sprop, tvr.value());
|
||||
}
|
||||
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, MethodWriteBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT,
|
||||
0, ACC_STORE_ANY)
|
||||
@ -11246,7 +11246,7 @@ TraceRecorder::setProp(jsval &l, PropertyCacheEntry* entry, JSScopeProperty* spr
|
||||
JSObject* obj = JSVAL_TO_OBJECT(l);
|
||||
LIns* obj_ins = get(&l);
|
||||
|
||||
JS_ASSERT_IF(entry->directHit(), OBJ_SCOPE(obj)->hasProperty(sprop));
|
||||
JS_ASSERT_IF(entry->directHit(), obj->scope()->hasProperty(sprop));
|
||||
|
||||
// Fast path for CallClass. This is about 20% faster than the general case.
|
||||
v_ins = get(&v);
|
||||
@ -11259,7 +11259,7 @@ TraceRecorder::setProp(jsval &l, PropertyCacheEntry* entry, JSScopeProperty* spr
|
||||
obj2 = obj2->getParent();
|
||||
for (jsuword j = entry->protoIndex(); j; j--)
|
||||
obj2 = obj2->getProto();
|
||||
JSScope *scope = OBJ_SCOPE(obj2);
|
||||
JSScope *scope = obj2->scope();
|
||||
JS_ASSERT_IF(entry->adding(), obj2 == obj);
|
||||
|
||||
// Guard before anything else.
|
||||
@ -12747,7 +12747,7 @@ TraceRecorder::name(jsval*& vp, LIns*& ins, NameResult& nr)
|
||||
/* Don't trace getter or setter calls, our caller wants a direct slot. */
|
||||
if (pcval.isSprop()) {
|
||||
JSScopeProperty* sprop = pcval.toSprop();
|
||||
if (!isValidSlot(OBJ_SCOPE(obj), sprop))
|
||||
if (!isValidSlot(obj->scope(), sprop))
|
||||
RETURN_STOP_A("name() not accessing a valid slot");
|
||||
slot = sprop->slot;
|
||||
} else {
|
||||
@ -12770,7 +12770,7 @@ MethodReadBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObject
|
||||
{
|
||||
AutoValueRooter tvr(cx, funobj);
|
||||
|
||||
if (!OBJ_SCOPE(obj)->methodReadBarrier(cx, sprop, tvr.addr()))
|
||||
if (!obj->scope()->methodReadBarrier(cx, sprop, tvr.addr()))
|
||||
return NULL;
|
||||
JS_ASSERT(VALUE_IS_FUNCTION(cx, tvr.value()));
|
||||
return JSVAL_TO_OBJECT(tvr.value());
|
||||
@ -12840,7 +12840,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp,
|
||||
VMSideExit* exit = snapshot(BRANCH_EXIT);
|
||||
do {
|
||||
if (obj->isNative()) {
|
||||
CHECK_STATUS_A(InjectStatus(guardShape(obj_ins, obj, OBJ_SHAPE(obj),
|
||||
CHECK_STATUS_A(InjectStatus(guardShape(obj_ins, obj, obj->shape(),
|
||||
"guard(shape)", exit)));
|
||||
} else if (!guardDenseArray(obj, obj_ins, exit)) {
|
||||
RETURN_STOP_A("non-native object involved in undefined property access");
|
||||
@ -12868,7 +12868,7 @@ TraceRecorder::propTail(JSObject* obj, LIns* obj_ins, JSObject* obj2, PCVal pcva
|
||||
|
||||
if (pcval.isSprop()) {
|
||||
sprop = pcval.toSprop();
|
||||
JS_ASSERT(OBJ_SCOPE(obj2)->hasProperty(sprop));
|
||||
JS_ASSERT(obj2->scope()->hasProperty(sprop));
|
||||
|
||||
if (setflags && !sprop->hasDefaultSetter())
|
||||
RETURN_STOP_A("non-stub setter");
|
||||
@ -12883,11 +12883,11 @@ TraceRecorder::propTail(JSObject* obj, LIns* obj_ins, JSObject* obj2, PCVal pcva
|
||||
return InjectStatus(getPropertyWithNativeGetter(obj_ins, sprop, outp));
|
||||
return InjectStatus(getPropertyById(obj_ins, outp));
|
||||
}
|
||||
if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)))
|
||||
if (!SPROP_HAS_VALID_SLOT(sprop, obj2->scope()))
|
||||
RETURN_STOP_A("no valid slot");
|
||||
slot = sprop->slot;
|
||||
isMethod = sprop->isMethod();
|
||||
JS_ASSERT_IF(isMethod, OBJ_SCOPE(obj2)->hasMethodBarrier());
|
||||
JS_ASSERT_IF(isMethod, obj2->scope()->hasMethodBarrier());
|
||||
} else {
|
||||
if (!pcval.isSlot())
|
||||
RETURN_STOP_A("PCE is not a slot");
|
||||
@ -13634,7 +13634,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target
|
||||
if (!exit)
|
||||
exit = snapshot(BRANCH_EXIT);
|
||||
guard(true,
|
||||
addName(lir->ins2i(LIR_eq, shape_ins, OBJ_SHAPE(obj)), "guard_shape"),
|
||||
addName(lir->ins2i(LIR_eq, shape_ins, obj->shape()), "guard_shape"),
|
||||
exit);
|
||||
}
|
||||
}
|
||||
|
@ -4912,7 +4912,7 @@ xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
||||
* property's getter or setter. But now it's time to remove any such
|
||||
* property, to purge the property cache and remove the scope entry.
|
||||
*/
|
||||
if (OBJ_SCOPE(obj)->object == obj && !js_DeleteProperty(cx, obj, id, rval))
|
||||
if (obj->scope()->object == obj && !js_DeleteProperty(cx, obj, id, rval))
|
||||
return JS_FALSE;
|
||||
|
||||
*rval = JSVAL_TRUE;
|
||||
@ -7283,7 +7283,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
JS_ASSERT(prop);
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
|
||||
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, pobj->scope()));
|
||||
cval = pobj->getSlotMT(cx, sprop->slot);
|
||||
pobj->dropProperty(cx, prop);
|
||||
JS_ASSERT(VALUE_IS_FUNCTION(cx, cval));
|
||||
|
@ -3106,7 +3106,7 @@ ShapeOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
*vp = INT_TO_JSVAL(-1);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_NewNumberValue(cx, OBJ_SHAPE(obj), vp);
|
||||
return JS_NewNumberValue(cx, obj->shape(), vp);
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
Loading…
Reference in New Issue
Block a user