bug 491126 - sharing object map for non-native objects. r=brendan
This commit is contained in:
259
js/src/jsobj.cpp
259
js/src/jsobj.cpp
@@ -102,7 +102,7 @@ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
|
||||
#endif
|
||||
|
||||
JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
|
||||
js_NewObjectMap, js_DestroyObjectMap,
|
||||
NULL,
|
||||
js_LookupProperty, js_DefineProperty,
|
||||
js_GetProperty, js_SetProperty,
|
||||
js_GetAttributes, js_SetAttributes,
|
||||
@@ -2033,9 +2033,12 @@ js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
CreateMapForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* ops)
|
||||
InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto,
|
||||
JSObjectOps* ops)
|
||||
{
|
||||
JSObjectMap* map;
|
||||
JS_ASSERT(OPS_IS_NATIVE(ops));
|
||||
JS_ASSERT(proto == OBJ_GET_PROTO(cx, obj));
|
||||
|
||||
JSClass* protoclasp;
|
||||
JSClass* clasp = OBJ_GET_CLASS(cx, obj);
|
||||
|
||||
@@ -2048,33 +2051,36 @@ CreateMapForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* o
|
||||
* object classes must have the same (null or not) reserveSlots hook.
|
||||
*/
|
||||
if (proto &&
|
||||
((map = proto->map)->ops == ops &&
|
||||
((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||
|
||||
(!((protoclasp->flags ^ clasp->flags) &
|
||||
(JSCLASS_HAS_PRIVATE |
|
||||
(JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&
|
||||
protoclasp->reserveSlots == clasp->reserveSlots))))
|
||||
proto->map->ops == ops &&
|
||||
((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||
|
||||
(!((protoclasp->flags ^ clasp->flags) &
|
||||
(JSCLASS_HAS_PRIVATE |
|
||||
(JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&
|
||||
protoclasp->reserveSlots == clasp->reserveSlots)))
|
||||
{
|
||||
/* Share the given prototype's map. */
|
||||
obj->map = js_HoldObjectMap(cx, map);
|
||||
js_HoldScope(OBJ_SCOPE(proto));
|
||||
obj->map = proto->map;
|
||||
return true;
|
||||
}
|
||||
|
||||
map = ops->newObjectMap(cx, 1, ops, clasp, obj);
|
||||
if (!map)
|
||||
return false;
|
||||
obj->map = map;
|
||||
JSScope *scope = js_NewScope(cx, ops, clasp, obj);
|
||||
if (!scope)
|
||||
goto bad;
|
||||
|
||||
/* Let ops->newObjectMap set freeslot so as to reserve slots. */
|
||||
uint32 nslots = map->freeslot;
|
||||
JS_ASSERT(nslots >= JSSLOT_PRIVATE);
|
||||
if (nslots > JS_INITIAL_NSLOTS &&
|
||||
!js_ReallocSlots(cx, obj, nslots, JS_TRUE)) {
|
||||
js_DropObjectMap(cx, map, obj);
|
||||
return false;
|
||||
/* Let js_NewScope set freeslot so as to reserve slots. */
|
||||
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
|
||||
if (scope->freeslot > JS_INITIAL_NSLOTS &&
|
||||
!js_ReallocSlots(cx, obj, scope->freeslot, JS_TRUE)) {
|
||||
js_DestroyScope(cx, scope);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
obj->map = &scope->map;
|
||||
return true;
|
||||
|
||||
bad:
|
||||
/* Ensure that the map field is initialized for GC. */
|
||||
obj->map = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
@@ -2093,11 +2099,8 @@ NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto, JSObject *parent
|
||||
for (unsigned i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
|
||||
if (!CreateMapForObject(cx, obj, proto, &js_ObjectOps))
|
||||
return NULL;
|
||||
obj->dslots = NULL;
|
||||
|
||||
return obj;
|
||||
return InitScopeForObject(cx, obj, proto, &js_ObjectOps) ? obj : NULL;
|
||||
}
|
||||
|
||||
JSObject* FASTCALL
|
||||
@@ -2363,7 +2366,7 @@ with_ThisObject(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
|
||||
js_NewObjectMap, js_DestroyObjectMap,
|
||||
NULL,
|
||||
with_LookupProperty, js_DefineProperty,
|
||||
with_GetProperty, with_SetProperty,
|
||||
with_GetAttributes, with_SetAttributes,
|
||||
@@ -2455,7 +2458,7 @@ 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 to skip updating OBJ_SCOPE(obj)->map.freeslot after
|
||||
* object. This allows us to skip updating OBJ_SCOPE(obj)->freeslot after
|
||||
* we copy the stack slots into reserved slots.
|
||||
*/
|
||||
JS_ASSERT(OBJ_SCOPE(obj)->object != obj);
|
||||
@@ -2845,50 +2848,6 @@ bad:
|
||||
goto out;
|
||||
}
|
||||
|
||||
void
|
||||
js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
|
||||
JSClass *clasp)
|
||||
{
|
||||
map->nrefs = nrefs;
|
||||
map->ops = ops;
|
||||
map->freeslot = JSSLOT_FREE(clasp);
|
||||
}
|
||||
|
||||
JSObjectMap *
|
||||
js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
|
||||
JSClass *clasp, JSObject *obj)
|
||||
{
|
||||
return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj);
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyObjectMap(JSContext *cx, JSObjectMap *map)
|
||||
{
|
||||
js_DestroyScope(cx, (JSScope *)map);
|
||||
}
|
||||
|
||||
JSObjectMap *
|
||||
js_HoldObjectMap(JSContext *cx, JSObjectMap *map)
|
||||
{
|
||||
JS_ASSERT(map->nrefs >= 0);
|
||||
JS_ATOMIC_INCREMENT(&map->nrefs);
|
||||
return map;
|
||||
}
|
||||
|
||||
JSObjectMap *
|
||||
js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(map->nrefs > 0);
|
||||
JS_ATOMIC_DECREMENT(&map->nrefs);
|
||||
if (map->nrefs == 0) {
|
||||
map->ops->destroyObjectMap(cx, map);
|
||||
return NULL;
|
||||
}
|
||||
if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj)
|
||||
((JSScope *)map)->object = NULL;
|
||||
return map;
|
||||
}
|
||||
|
||||
static void
|
||||
FreeSlots(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
@@ -3072,11 +3031,6 @@ JSObject *
|
||||
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent, uintN objectSize)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSObjectOps *ops;
|
||||
uint32 i;
|
||||
JSTempValueRooter tvr;
|
||||
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
|
||||
jsdtrace_object_create_start(cx->fp, clasp);
|
||||
@@ -3097,16 +3051,18 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
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.
|
||||
*/
|
||||
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
|
||||
JSObject *obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
|
||||
if (!obj)
|
||||
goto earlybad;
|
||||
|
||||
obj->map = NULL;
|
||||
obj->dslots = NULL;
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Set the class slot with the initial value of the system and delegate
|
||||
@@ -3117,55 +3073,54 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
|
||||
JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
|
||||
|
||||
/* Set the proto and parent properties. */
|
||||
STOBJ_SET_PROTO(obj, proto);
|
||||
STOBJ_SET_PARENT(obj, parent);
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
|
||||
/*
|
||||
* Default parent to the parent of the prototype, which was set from
|
||||
* the parent of the prototype's constructor.
|
||||
*/
|
||||
obj->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL((!parent && proto)
|
||||
? OBJ_GET_PARENT(cx, proto)
|
||||
: parent);
|
||||
|
||||
/* Initialize the remaining fixed slots. */
|
||||
for (i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
|
||||
for (uint32 i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
|
||||
obj->dslots = NULL;
|
||||
|
||||
if (OPS_IS_NATIVE(ops)) {
|
||||
if (!InitScopeForObject(cx, obj, proto, ops)) {
|
||||
obj = NULL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(ops->objectMap->ops == ops);
|
||||
obj->map = const_cast<JSObjectMap *>(ops->objectMap);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
|
||||
objectSize - sizeof(JSObject));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Root obj to prevent it from being collected out from under this call to
|
||||
* js_NewObject. There's a possibilty of GC under the objectHook call-out
|
||||
* further below.
|
||||
*/
|
||||
JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
|
||||
|
||||
/* Always call the class's getObjectOps hook if it has one. */
|
||||
ops = clasp->getObjectOps
|
||||
? clasp->getObjectOps(cx, clasp)
|
||||
: &js_ObjectOps;
|
||||
|
||||
/*
|
||||
* Default parent to the parent of the prototype, which was set from
|
||||
* the parent of the prototype's constructor.
|
||||
*/
|
||||
if (proto && !parent)
|
||||
STOBJ_SET_PARENT(obj, OBJ_GET_PARENT(cx, proto));
|
||||
|
||||
if (!CreateMapForObject(cx, obj, proto, ops))
|
||||
goto bad;
|
||||
/* Check that the newborn root still holds the object. */
|
||||
JS_ASSERT_IF(!cx->localRootStack, cx->weakRoots.newborn[GCX_OBJECT] == obj);
|
||||
|
||||
/*
|
||||
* Do not call debug hooks on trace, because we might be in a non-_FAIL
|
||||
* builtin. See bug 481444.
|
||||
*/
|
||||
if (cx->debugHooks->objectHook && !JS_ON_TRACE(cx)) {
|
||||
JSAutoTempValueRooter tvr(cx, obj);
|
||||
JS_KEEP_ATOMS(cx->runtime);
|
||||
cx->debugHooks->objectHook(cx, obj, JS_TRUE,
|
||||
cx->debugHooks->objectHookData);
|
||||
JS_UNKEEP_ATOMS(cx->runtime);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = obj;
|
||||
}
|
||||
|
||||
out:
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = obj;
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
|
||||
jsdtrace_object_create(cx, clasp, obj);
|
||||
@@ -3173,28 +3128,21 @@ out:
|
||||
jsdtrace_object_create_done(cx->fp, clasp);
|
||||
#endif
|
||||
return obj;
|
||||
|
||||
bad:
|
||||
obj = NULL;
|
||||
goto out;
|
||||
|
||||
earlybad:
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
|
||||
jsdtrace_object_create(cx, clasp, NULL);
|
||||
if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
|
||||
jsdtrace_object_create_done(cx->fp, clasp);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto, uint32 slot)
|
||||
{
|
||||
JS_ASSERT(!clasp->getObjectOps);
|
||||
JS_ASSERT(proto->map->ops == &js_ObjectOps);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, proto) == clasp);
|
||||
|
||||
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
js_HoldScope(OBJ_SCOPE(proto));
|
||||
obj->map = proto->map;
|
||||
obj->classword = jsuword(clasp);
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
@@ -3203,9 +3151,6 @@ js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto, uint32 slot)
|
||||
while (slot < JS_INITIAL_NSLOTS)
|
||||
obj->fslots[slot++] = JSVAL_VOID;
|
||||
|
||||
JS_ASSERT(!clasp->getObjectOps);
|
||||
JS_ASSERT(proto->map->ops == &js_ObjectOps);
|
||||
obj->map = js_HoldObjectMap(cx, proto->map);
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
@@ -3456,11 +3401,8 @@ bad:
|
||||
void
|
||||
js_FinalizeObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObjectMap *map;
|
||||
|
||||
/* Cope with stillborn objects that have no map. */
|
||||
map = obj->map;
|
||||
if (!map)
|
||||
if (!obj->map)
|
||||
return;
|
||||
|
||||
if (cx->debugHooks->objectHook) {
|
||||
@@ -3476,8 +3418,8 @@ js_FinalizeObject(JSContext *cx, JSObject *obj)
|
||||
jsdtrace_object_finalize(obj);
|
||||
#endif
|
||||
|
||||
/* Drop map and free slots. */
|
||||
js_DropObjectMap(cx, map, obj);
|
||||
if (OBJ_IS_NATIVE(obj))
|
||||
js_DropScope(cx, OBJ_SCOPE(obj), obj);
|
||||
FreeSlots(cx, obj);
|
||||
}
|
||||
|
||||
@@ -3486,38 +3428,35 @@ js_FinalizeObject(JSContext *cx, JSObject *obj)
|
||||
JSBool
|
||||
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
|
||||
{
|
||||
JSObjectMap *map;
|
||||
JSClass *clasp;
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
|
||||
map = obj->map;
|
||||
JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
if (map->freeslot == JSSLOT_FREE(clasp) && clasp->reserveSlots) {
|
||||
/* Adjust map->freeslot to include computed reserved slots, if any. */
|
||||
map->freeslot += clasp->reserveSlots(cx, obj);
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSClass *clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
if (scope->freeslot == JSSLOT_FREE(clasp) && clasp->reserveSlots) {
|
||||
/* Adjust scope->freeslot to include computed reserved slots, if any. */
|
||||
scope->freeslot += clasp->reserveSlots(cx, obj);
|
||||
}
|
||||
|
||||
if (map->freeslot >= STOBJ_NSLOTS(obj) &&
|
||||
!js_ReallocSlots(cx, obj, map->freeslot + 1, JS_FALSE)) {
|
||||
if (scope->freeslot >= STOBJ_NSLOTS(obj) &&
|
||||
!js_ReallocSlots(cx, obj, scope->freeslot + 1, JS_FALSE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* js_ReallocSlots or js_FreeSlot should set the free slots to void. */
|
||||
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, map->freeslot)));
|
||||
*slotp = map->freeslot++;
|
||||
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot)));
|
||||
*slotp = scope->freeslot++;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
{
|
||||
JSObjectMap *map;
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
|
||||
map = obj->map;
|
||||
JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_VOID);
|
||||
if (map->freeslot == slot + 1) {
|
||||
map->freeslot = slot;
|
||||
if (scope->freeslot == slot + 1) {
|
||||
scope->freeslot = slot;
|
||||
|
||||
/* When shrinking, js_ReallocSlots always returns true. */
|
||||
js_ReallocSlots(cx, obj, slot, JS_FALSE);
|
||||
@@ -3914,8 +3853,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
proto = OBJ_GET_PROTO(cx, proto)) {
|
||||
protoIndex++;
|
||||
}
|
||||
scope = OBJ_SCOPE(obj2);
|
||||
if (!MAP_IS_NATIVE(&scope->map)) {
|
||||
if (!OBJ_IS_NATIVE(obj2)) {
|
||||
/* Whoops, newresolve handed back a foreign obj2. */
|
||||
JS_ASSERT(obj2 != obj);
|
||||
ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
|
||||
@@ -3931,6 +3869,7 @@ 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);
|
||||
if (scope->object == obj2)
|
||||
sprop = SCOPE_GET_PROPERTY(scope, id);
|
||||
}
|
||||
@@ -3953,8 +3892,8 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
if (!ok)
|
||||
goto cleanup;
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
scope = OBJ_SCOPE(obj);
|
||||
JS_ASSERT(MAP_IS_NATIVE(&scope->map));
|
||||
if (scope->object == obj)
|
||||
sprop = SCOPE_GET_PROPERTY(scope, id);
|
||||
}
|
||||
@@ -5842,8 +5781,8 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
* above.
|
||||
*/
|
||||
nslots = STOBJ_NSLOTS(obj);
|
||||
if (scope->object == obj && scope->map.freeslot < nslots)
|
||||
nslots = scope->map.freeslot;
|
||||
if (scope->object == obj && scope->freeslot < nslots)
|
||||
nslots = scope->freeslot;
|
||||
|
||||
for (i = 0; i != nslots; ++i) {
|
||||
v = STOBJ_GET_SLOT(obj, i);
|
||||
@@ -5877,7 +5816,7 @@ js_Clear(JSContext *cx, JSObject *obj)
|
||||
n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
|
||||
while (--i >= n)
|
||||
STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
|
||||
scope->map.freeslot = n;
|
||||
scope->freeslot = n;
|
||||
}
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
}
|
||||
@@ -5926,8 +5865,8 @@ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
}
|
||||
|
||||
/* Whether or not we grew nslots, we may need to advance freeslot. */
|
||||
if (scope->object == obj && slot >= scope->map.freeslot)
|
||||
scope->map.freeslot = slot + 1;
|
||||
if (scope->object == obj && slot >= scope->freeslot)
|
||||
scope->freeslot = slot + 1;
|
||||
|
||||
STOBJ_SET_SLOT(obj, slot, v);
|
||||
GC_POKE(cx, JS_NULL);
|
||||
@@ -6131,7 +6070,7 @@ js_DumpObject(JSObject *obj)
|
||||
uint32 i, slots;
|
||||
JSClass *clasp;
|
||||
jsuint reservedEnd;
|
||||
JSBool sharesScope = JS_FALSE;
|
||||
bool sharesScope = false;
|
||||
|
||||
fprintf(stderr, "object %p\n", (void *) obj);
|
||||
clasp = STOBJ_GET_CLASS(obj);
|
||||
@@ -6186,7 +6125,9 @@ js_DumpObject(JSObject *obj)
|
||||
if (clasp->flags & JSCLASS_HAS_PRIVATE)
|
||||
reservedEnd++;
|
||||
reservedEnd += JSCLASS_RESERVED_SLOTS(clasp);
|
||||
slots = sharesScope ? reservedEnd : obj->map->freeslot;
|
||||
slots = (OBJ_IS_NATIVE(obj) && !sharesScope)
|
||||
? OBJ_SCOPE(obj)->freeslot
|
||||
: STOBJ_NSLOTS(obj);
|
||||
for (i = 0; i < slots; i++) {
|
||||
fprintf(stderr, " %3d ", i);
|
||||
if (i == JSSLOT_PRIVATE && (clasp->flags & JSCLASS_HAS_PRIVATE)) {
|
||||
|
||||
Reference in New Issue
Block a user