Remove JSObject::privateData, bug 693479.

This commit is contained in:
Brian Hackett 2011-10-10 17:14:38 -07:00
parent f5a853bac0
commit e9b876258d
23 changed files with 202 additions and 93 deletions

View File

@ -52,7 +52,6 @@ bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
CHECK(savedCopy->flags == obj->flags); CHECK(savedCopy->flags == obj->flags);
CHECK(savedCopy->getProto() == obj->getProto()); CHECK(savedCopy->getProto() == obj->getProto());
CHECK(savedCopy->parent == obj->parent); CHECK(savedCopy->parent == obj->parent);
CHECK(savedCopy->privateData == obj->privateData);
return true; return true;
} }

View File

@ -1259,7 +1259,6 @@ Class js::ArrayClass = {
Class js::SlowArrayClass = { Class js::SlowArrayClass = {
"Array", "Array",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array), JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
slowarray_addProperty, slowarray_addProperty,
JS_PropertyStub, /* delProperty */ JS_PropertyStub, /* delProperty */

View File

@ -191,19 +191,20 @@ struct Object {
TypeObject *type; TypeObject *type;
uint32 flags; uint32 flags;
JSObject *parent; JSObject *parent;
void *privateData;
js::Value *slots; js::Value *slots;
js::Value *_1; js::Value *_1;
#if JS_BITS_PER_WORD == 32
js::Value *_2;
#endif
static const uint32 FIXED_SLOTS_SHIFT = 27; static const uint32 FIXED_SLOTS_SHIFT = 27;
size_t numFixedSlots() const { return flags >> FIXED_SLOTS_SHIFT; }
Value *fixedSlots() const {
return (Value *)((jsuword) this + sizeof(shadow::Object));
}
js::Value &slotRef(size_t slot) const { js::Value &slotRef(size_t slot) const {
size_t nfixed = flags >> FIXED_SLOTS_SHIFT; size_t nfixed = numFixedSlots();
if (slot < nfixed) if (slot < nfixed)
return ((Value *)((jsuword) this + sizeof(shadow::Object)))[slot]; return fixedSlots()[slot];
return slots[slot - nfixed]; return slots[slot - nfixed];
} }
}; };
@ -250,7 +251,9 @@ GetObjectProto(const JSObject *obj)
inline void * inline void *
GetObjectPrivate(const JSObject *obj) GetObjectPrivate(const JSObject *obj)
{ {
return reinterpret_cast<const shadow::Object*>(obj)->privateData; const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
return *addr;
} }
/* /*

View File

@ -199,7 +199,7 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee)
JS_STATIC_ASSERT(NormalArgumentsObject::RESERVED_SLOTS == 2); JS_STATIC_ASSERT(NormalArgumentsObject::RESERVED_SLOTS == 2);
JS_STATIC_ASSERT(StrictArgumentsObject::RESERVED_SLOTS == 2); JS_STATIC_ASSERT(StrictArgumentsObject::RESERVED_SLOTS == 2);
JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT2); JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
if (!obj) if (!obj)
return NULL; return NULL;
@ -215,7 +215,7 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee)
SetValueRangeToUndefined(data->slots, argc); SetValueRangeToUndefined(data->slots, argc);
/* Can't fail from here on, so initialize everything in argsobj. */ /* Can't fail from here on, so initialize everything in argsobj. */
obj->init(cx, type, proto->getParent(), NULL, false); obj->init(cx, type, proto->getParent(), false);
obj->setInitialPropertyInfallible(emptyArgumentsShape); obj->setInitialPropertyInfallible(emptyArgumentsShape);
ArgumentsObject *argsobj = obj->asArguments(); ArgumentsObject *argsobj = obj->asArguments();
@ -225,6 +225,9 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee)
argsobj->setCalleeAndData(callee, data); argsobj->setCalleeAndData(callee, data);
JS_ASSERT(argsobj->numFixedSlots() == NormalArgumentsObject::NFIXED_SLOTS);
JS_ASSERT(argsobj->numFixedSlots() == StrictArgumentsObject::NFIXED_SLOTS);
return argsobj; return argsobj;
} }
@ -768,8 +771,9 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp)
EmptyShape *emptyDeclEnvShape = EmptyShape::getEmptyDeclEnvShape(cx); EmptyShape *emptyDeclEnvShape = EmptyShape::getEmptyDeclEnvShape(cx);
if (!emptyDeclEnvShape) if (!emptyDeclEnvShape)
return NULL; return NULL;
envobj->init(cx, type, &fp->scopeChain(), fp, false); envobj->init(cx, type, &fp->scopeChain(), false);
envobj->setInitialPropertyInfallible(emptyDeclEnvShape); envobj->setInitialPropertyInfallible(emptyDeclEnvShape);
envobj->setPrivate(fp);
return envobj; return envobj;
} }

View File

@ -100,7 +100,7 @@
#define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure #define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
optimization level -- see above */ optimization level -- see above */
struct JSFunction : public JSObject_Slots2 struct JSFunction : public JSObject_Slots4
{ {
/* Functions always have two fixed slots (FUN_CLASS_RESERVED_SLOTS). */ /* Functions always have two fixed slots (FUN_CLASS_RESERVED_SLOTS). */

View File

@ -77,6 +77,15 @@ GetGCObjectKind(size_t numSlots)
return slotsToThingKind[numSlots]; return slotsToThingKind[numSlots];
} }
static inline AllocKind
GetGCObjectKind(Class *clasp)
{
uint32 nslots = JSCLASS_RESERVED_SLOTS(clasp);
if (clasp->flags & JSCLASS_HAS_PRIVATE)
nslots++;
return GetGCObjectKind(nslots);
}
/* As for GetGCObjectKind, but for dense array allocation. */ /* As for GetGCObjectKind, but for dense array allocation. */
static inline AllocKind static inline AllocKind
GetGCArrayKind(size_t numSlots) GetGCArrayKind(size_t numSlots)
@ -400,7 +409,7 @@ js_NewGCFunction(JSContext *cx)
{ {
JSFunction *fun = NewGCThing<JSFunction>(cx, js::gc::FINALIZE_FUNCTION, sizeof(JSFunction)); JSFunction *fun = NewGCThing<JSFunction>(cx, js::gc::FINALIZE_FUNCTION, sizeof(JSFunction));
if (fun) if (fun)
fun->earlyInit(JSObject::FUN_CLASS_RESERVED_SLOTS); fun->earlyInit(JSObject::FUN_CLASS_NFIXED_SLOTS + 1); /* Add one for private data. */
return fun; return fun;
} }

View File

@ -405,7 +405,7 @@ NewIteratorObject(JSContext *cx, uintN flags)
* helper objects) expect it to have a non-null map pointer, so we * helper objects) expect it to have a non-null map pointer, so we
* share an empty Enumerator scope in the runtime. * share an empty Enumerator scope in the runtime.
*/ */
JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT0); JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT2);
if (!obj) if (!obj)
return NULL; return NULL;
@ -417,8 +417,10 @@ NewIteratorObject(JSContext *cx, uintN flags)
if (!emptyEnumeratorShape) if (!emptyEnumeratorShape)
return NULL; return NULL;
obj->init(cx, type, NULL, NULL, false); obj->init(cx, type, NULL, false);
obj->setInitialPropertyInfallible(emptyEnumeratorShape); obj->setInitialPropertyInfallible(emptyEnumeratorShape);
JS_ASSERT(obj->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
return obj; return obj;
} }

View File

@ -3464,13 +3464,13 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
if (!type) if (!type)
return NULL; return NULL;
obj = js_NewGCObject(cx, FINALIZE_OBJECT2); obj = js_NewGCObject(cx, FINALIZE_OBJECT4);
if (!obj) if (!obj)
return NULL; return NULL;
StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp()); StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
obj->init(cx, type, parent, priv, false); obj->init(cx, type, parent, false);
EmptyShape *emptyWithShape = EmptyShape::getEmptyWithShape(cx); EmptyShape *emptyWithShape = EmptyShape::getEmptyWithShape(cx);
if (!emptyWithShape) if (!emptyWithShape)
@ -3479,6 +3479,8 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
obj->setInitialPropertyInfallible(emptyWithShape); obj->setInitialPropertyInfallible(emptyWithShape);
OBJ_SET_BLOCK_DEPTH(cx, obj, depth); OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
obj->setPrivate(priv);
AutoObjectRooter tvr(cx, obj); AutoObjectRooter tvr(cx, obj);
JSObject *thisp = proto->thisObject(cx); JSObject *thisp = proto->thisObject(cx);
if (!thisp) if (!thisp)
@ -3509,7 +3511,7 @@ js_NewBlockObject(JSContext *cx)
if (!emptyBlockShape) if (!emptyBlockShape)
return NULL; return NULL;
blockObj->init(cx, type, NULL, NULL, false); blockObj->init(cx, type, NULL, false);
blockObj->setInitialPropertyInfallible(emptyBlockShape); blockObj->setInitialPropertyInfallible(emptyBlockShape);
return blockObj; return blockObj;
@ -3757,7 +3759,7 @@ JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent)
return NULL; return NULL;
} }
if (obj->getClass()->flags & JSCLASS_HAS_PRIVATE) if (obj->hasPrivate())
clone->setPrivate(obj->getPrivate()); clone->setPrivate(obj->getPrivate());
} else { } else {
JS_ASSERT(obj->isProxy()); JS_ASSERT(obj->isProxy());
@ -3772,11 +3774,15 @@ struct JSObject::TradeGutsReserved {
JSContext *cx; JSContext *cx;
Vector<Value> avals; Vector<Value> avals;
Vector<Value> bvals; Vector<Value> bvals;
uint32 newafixed;
uint32 newbfixed;
Value *newaslots; Value *newaslots;
Value *newbslots; Value *newbslots;
TradeGutsReserved(JSContext *cx) TradeGutsReserved(JSContext *cx)
: cx(cx), avals(cx), bvals(cx), newaslots(NULL), newbslots(NULL) : cx(cx), avals(cx), bvals(cx),
newafixed(0), newbfixed(0),
newaslots(NULL), newbslots(NULL)
{} {}
~TradeGutsReserved() ~TradeGutsReserved()
@ -3798,7 +3804,7 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
* swaps can be performed infallibly. * swaps can be performed infallibly.
*/ */
if (a->structSize() == b->structSize()) if (a->structSize() == b->structSize() && a->hasPrivate() == b->hasPrivate())
return true; return true;
/* /*
@ -3821,17 +3827,32 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
JS_ASSERT(a->elements == emptyObjectElements); JS_ASSERT(a->elements == emptyObjectElements);
JS_ASSERT(b->elements == emptyObjectElements); JS_ASSERT(b->elements == emptyObjectElements);
/*
* The newafixed/newbfixed hold the number of fixed slots in the objects
* after the swap. Adjust these counts according to whether the objects
* use their last fixed slot for storing private data.
*/
reserved.newafixed = a->numFixedSlots();
reserved.newbfixed = b->numFixedSlots();
if (a->hasPrivate()) {
reserved.newafixed++;
reserved.newbfixed--;
}
if (b->hasPrivate()) {
reserved.newbfixed++;
reserved.newafixed--;
}
/* /*
* The newaslots/newbslots arrays hold any dynamic slots for the objects * The newaslots/newbslots arrays hold any dynamic slots for the objects
* if they do not have enough fixed slots to accomodate the slots in the * if they do not have enough fixed slots to accomodate the slots in the
* other object. * other object.
*/ */
unsigned afixed = a->numFixedSlots(); unsigned adynamic = dynamicSlotsCount(reserved.newafixed, b->slotSpan());
unsigned bfixed = b->numFixedSlots(); unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan());
unsigned adynamic = dynamicSlotsCount(afixed, b->slotSpan());
unsigned bdynamic = dynamicSlotsCount(bfixed, a->slotSpan());
if (adynamic) { if (adynamic) {
reserved.newaslots = (Value *) cx->malloc_(sizeof(Value) * adynamic); reserved.newaslots = (Value *) cx->malloc_(sizeof(Value) * adynamic);
@ -3880,7 +3901,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
/* Trade the guts of the objects. */ /* Trade the guts of the objects. */
const size_t size = a->structSize(); const size_t size = a->structSize();
if (size == b->structSize()) { if (size == b->structSize() && a->hasPrivate() == b->hasPrivate()) {
/* /*
* If the objects are the same size, then we make no assumptions about * If the objects are the same size, then we make no assumptions about
* whether they have dynamically allocated slots and instead just copy * whether they have dynamically allocated slots and instead just copy
@ -3914,21 +3935,25 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
if (b->hasDynamicSlots()) if (b->hasDynamicSlots())
cx->free_(b->slots); cx->free_(b->slots);
unsigned afixed = a->numFixedSlots(); void *apriv = a->hasPrivate() ? a->getPrivate() : NULL;
unsigned bfixed = b->numFixedSlots(); void *bpriv = b->hasPrivate() ? b->getPrivate() : NULL;
JSObject tmp; JSObject tmp;
memcpy(&tmp, a, sizeof tmp); memcpy(&tmp, a, sizeof tmp);
memcpy(a, b, sizeof tmp); memcpy(a, b, sizeof tmp);
memcpy(b, &tmp, sizeof tmp); memcpy(b, &tmp, sizeof tmp);
a->updateFixedSlots(afixed); a->updateFixedSlots(reserved.newafixed);
a->slots = reserved.newaslots; a->slots = reserved.newaslots;
a->copySlotRange(0, reserved.bvals.begin(), bcap); a->copySlotRange(0, reserved.bvals.begin(), bcap);
if (a->hasPrivate())
a->setPrivate(bpriv);
b->updateFixedSlots(bfixed); b->updateFixedSlots(reserved.newbfixed);
b->slots = reserved.newbslots; b->slots = reserved.newbslots;
b->copySlotRange(0, reserved.avals.begin(), acap); b->copySlotRange(0, reserved.avals.begin(), acap);
if (b->hasPrivate())
b->setPrivate(apriv);
/* Make sure the destructor for reserved doesn't free the slots. */ /* Make sure the destructor for reserved doesn't free the slots. */
reserved.newaslots = NULL; reserved.newaslots = NULL;
@ -4495,6 +4520,19 @@ JSObject::updateSlotsForSpan(size_t oldSpan, size_t newSpan)
invalidateSlotRange(newSpan, oldSpan - newSpan); invalidateSlotRange(newSpan, oldSpan - newSpan);
} }
inline void
JSObject::initializePrivate()
{
size_t nfixed = numFixedSlots();
JS_ASSERT(nfixed != 0);
/* Remove a fixed slot, to make room for the private data. */
flags = flags ^ (nfixed << FIXED_SLOTS_SHIFT);
flags |= (nfixed - 1) << FIXED_SLOTS_SHIFT;
setPrivate(NULL);
}
bool bool
JSObject::setInitialProperty(JSContext *cx, const js::Shape *shape) JSObject::setInitialProperty(JSContext *cx, const js::Shape *shape)
{ {
@ -4502,6 +4540,9 @@ JSObject::setInitialProperty(JSContext *cx, const js::Shape *shape)
JS_ASSERT(shape->compartment() == compartment()); JS_ASSERT(shape->compartment() == compartment());
JS_ASSERT(!shape->inDictionary()); JS_ASSERT(!shape->inDictionary());
if (shape->getClass()->flags & JSCLASS_HAS_PRIVATE)
initializePrivate();
size_t span = shape->slotSpan(); size_t span = shape->slotSpan();
if (!span) { if (!span) {
@ -4524,6 +4565,10 @@ JSObject::setInitialPropertyInfallible(const js::Shape *shape)
JS_ASSERT(isNewborn()); JS_ASSERT(isNewborn());
JS_ASSERT(shape->compartment() == compartment()); JS_ASSERT(shape->compartment() == compartment());
JS_ASSERT(!shape->inDictionary()); JS_ASSERT(!shape->inDictionary());
if (shape->getClass()->flags & JSCLASS_HAS_PRIVATE)
initializePrivate();
JS_ASSERT(dynamicSlotsCount(numFixedSlots(), shape->slotSpan()) == 0); JS_ASSERT(dynamicSlotsCount(numFixedSlots(), shape->slotSpan()) == 0);
shape_ = const_cast<js::Shape *>(shape); shape_ = const_cast<js::Shape *>(shape);

View File

@ -544,18 +544,12 @@ struct JSObject : js::gc::Cell
}; };
uint32 flags; /* flags */ uint32 flags; /* flags */
JSObject *parent; /* object's parent */ JSObject *parent; /* object's parent */
void *privateData; /* private data */
private: private:
js::Value *slots; /* Slots for object properties. */ js::Value *slots; /* Slots for object properties. */
js::Value *elements; /* Slots for object elements. */ js::Value *elements; /* Slots for object elements. */
#if JS_BITS_PER_WORD == 32
void *padding;
#endif
public: public:
inline bool isNative() const; inline bool isNative() const;
@ -668,6 +662,8 @@ struct JSObject : js::gc::Cell
inline size_t numFixedSlots() const; inline size_t numFixedSlots() const;
static const uint32 MAX_FIXED_SLOTS = 16;
private: private:
inline js::Value* fixedSlots() const; inline js::Value* fixedSlots() const;
public: public:
@ -685,6 +681,7 @@ struct JSObject : js::gc::Cell
/* JIT Accessors */ /* JIT Accessors */
static inline size_t getFixedSlotOffset(size_t slot); static inline size_t getFixedSlotOffset(size_t slot);
static inline size_t getPrivateDataOffset(size_t nfixed);
static inline size_t offsetOfSlots() { return offsetof(JSObject, slots); } static inline size_t offsetOfSlots() { return offsetof(JSObject, slots); }
/* Minimum size for dynamically allocated slots. */ /* Minimum size for dynamically allocated slots. */
@ -891,7 +888,9 @@ struct JSObject : js::gc::Cell
inline bool isGlobal() const; inline bool isGlobal() const;
inline js::GlobalObject *asGlobal(); inline js::GlobalObject *asGlobal();
inline bool hasPrivate() const;
inline void *getPrivate() const; inline void *getPrivate() const;
inline void *getPrivate(size_t nfixed) const;
inline void setPrivate(void *data); inline void setPrivate(void *data);
/* N.B. Infallible: NULL means 'no principal', not an error. */ /* N.B. Infallible: NULL means 'no principal', not an error. */
@ -914,6 +913,9 @@ struct JSObject : js::gc::Cell
bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp); bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp);
inline void *&privateAddress(uint32 nfixed) const;
inline void initializePrivate();
public: public:
bool isExtensible() const { return !(flags & NOT_EXTENSIBLE); } bool isExtensible() const { return !(flags & NOT_EXTENSIBLE); }
bool preventExtensions(JSContext *cx, js::AutoIdVector *props); bool preventExtensions(JSContext *cx, js::AutoIdVector *props);
@ -1095,6 +1097,7 @@ struct JSObject : js::gc::Cell
public: public:
static const uint32 FUN_CLASS_RESERVED_SLOTS = 2; static const uint32 FUN_CLASS_RESERVED_SLOTS = 2;
static const uint32 FUN_CLASS_NFIXED_SLOTS = 3;
static size_t getFlatClosureUpvarsOffset() { static size_t getFlatClosureUpvarsOffset() {
return getFixedSlotOffset(JSSLOT_FLAT_CLOSURE_UPVARS); return getFixedSlotOffset(JSSLOT_FLAT_CLOSURE_UPVARS);
@ -1161,6 +1164,8 @@ struct JSObject : js::gc::Cell
* Iterator-specific getters and setters. * Iterator-specific getters and setters.
*/ */
static const uint32 ITER_CLASS_NFIXED_SLOTS = 1;
inline js::NativeIterator *getNativeIterator() const; inline js::NativeIterator *getNativeIterator() const;
inline void setNativeIterator(js::NativeIterator *); inline void setNativeIterator(js::NativeIterator *);
@ -1236,7 +1241,7 @@ struct JSObject : js::gc::Cell
/* The last property is not initialized here and should be set separately. */ /* The last property is not initialized here and should be set separately. */
void init(JSContext *cx, js::types::TypeObject *type, void init(JSContext *cx, js::types::TypeObject *type,
JSObject *parent, void *priv, bool denseArray); JSObject *parent, bool denseArray);
inline void finish(JSContext *cx); inline void finish(JSContext *cx);
JS_ALWAYS_INLINE void finalize(JSContext *cx, bool background); JS_ALWAYS_INLINE void finalize(JSContext *cx, bool background);
@ -1433,7 +1438,6 @@ struct JSObject : js::gc::Cell
JS_STATIC_ASSERT(offsetof(JSObject, shape_) == offsetof(js::shadow::Object, shape)); JS_STATIC_ASSERT(offsetof(JSObject, shape_) == offsetof(js::shadow::Object, shape));
JS_STATIC_ASSERT(offsetof(JSObject, flags) == offsetof(js::shadow::Object, flags)); JS_STATIC_ASSERT(offsetof(JSObject, flags) == offsetof(js::shadow::Object, flags));
JS_STATIC_ASSERT(offsetof(JSObject, parent) == offsetof(js::shadow::Object, parent)); JS_STATIC_ASSERT(offsetof(JSObject, parent) == offsetof(js::shadow::Object, parent));
JS_STATIC_ASSERT(offsetof(JSObject, privateData) == offsetof(js::shadow::Object, privateData));
JS_STATIC_ASSERT(offsetof(JSObject, slots) == offsetof(js::shadow::Object, slots)); JS_STATIC_ASSERT(offsetof(JSObject, slots) == offsetof(js::shadow::Object, slots));
JS_STATIC_ASSERT(offsetof(JSObject, type_) == offsetof(js::shadow::Object, type)); JS_STATIC_ASSERT(offsetof(JSObject, type_) == offsetof(js::shadow::Object, type));
JS_STATIC_ASSERT(sizeof(JSObject) == sizeof(js::shadow::Object)); JS_STATIC_ASSERT(sizeof(JSObject) == sizeof(js::shadow::Object));
@ -1474,6 +1478,11 @@ JSObject::getFixedSlotOffset(size_t slot) {
return sizeof(JSObject) + (slot * sizeof(js::Value)); return sizeof(JSObject) + (slot * sizeof(js::Value));
} }
/* static */ inline size_t
JSObject::getPrivateDataOffset(size_t nfixed) {
return getFixedSlotOffset(nfixed);
}
struct JSObject_Slots2 : JSObject { js::Value fslots[2]; }; struct JSObject_Slots2 : JSObject { js::Value fslots[2]; };
struct JSObject_Slots4 : JSObject { js::Value fslots[4]; }; struct JSObject_Slots4 : JSObject { js::Value fslots[4]; };
struct JSObject_Slots8 : JSObject { js::Value fslots[8]; }; struct JSObject_Slots8 : JSObject { js::Value fslots[8]; };

View File

@ -93,25 +93,43 @@ JSObject::asGlobal()
return reinterpret_cast<js::GlobalObject *>(this); return reinterpret_cast<js::GlobalObject *>(this);
} }
inline void * inline bool
JSObject::getPrivate() const JSObject::hasPrivate() const
{ {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); return getClass()->flags & JSCLASS_HAS_PRIVATE;
return privateData;
} }
inline void *&
JSObject::privateAddress(uint32 nfixed) const
{
/*
* The private pointer of an object can hold any word sized value.
* Private pointers are stored immediately after the last fixed slot of
* the object.
*/
JS_ASSERT(nfixed == numFixedSlots());
JS_ASSERT_IF(!isNewborn(), hasPrivate());
js::Value *end = &fixedSlots()[nfixed];
return *reinterpret_cast<void**>(end);
}
inline void *
JSObject::getPrivate() const { return privateAddress(numFixedSlots()); }
inline void *
JSObject::getPrivate(size_t nfixed) const { return privateAddress(nfixed); }
inline JSFunction * inline JSFunction *
JSObject::getFunctionPrivate() const JSObject::getFunctionPrivate() const
{ {
JS_ASSERT(isFunction()); JS_ASSERT(isFunction());
return reinterpret_cast<JSFunction *>(getPrivate()); return reinterpret_cast<JSFunction *>(getPrivate(FUN_CLASS_NFIXED_SLOTS));
} }
inline void inline void
JSObject::setPrivate(void *data) JSObject::setPrivate(void *data)
{ {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); privateAddress(numFixedSlots()) = data;
privateData = data;
} }
inline bool inline bool
@ -315,7 +333,7 @@ JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent
if (!type) if (!type)
return false; return false;
init(cx, type, parent, NULL, false); init(cx, type, parent, false);
if (!setInitialProperty(cx, bindings.lastShape())) if (!setInitialProperty(cx, bindings.lastShape()))
return false; return false;
@ -338,11 +356,13 @@ JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent
inline bool inline bool
JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *frame) JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *frame)
{ {
init(cx, type, NULL, frame, false); init(cx, type, NULL, false);
if (!setInitialProperty(cx, getProto()->lastProperty())) if (!setInitialProperty(cx, getProto()->lastProperty()))
return false; return false;
setPrivate(frame);
JS_ASSERT(!inDictionaryMode()); JS_ASSERT(!inDictionaryMode());
JS_ASSERT(isClonedBlock()); JS_ASSERT(isClonedBlock());
@ -929,10 +949,8 @@ JSObject::isQName() const
inline void inline void
JSObject::init(JSContext *cx, js::types::TypeObject *type, JSObject::init(JSContext *cx, js::types::TypeObject *type,
JSObject *parent, void *priv, bool denseArray) JSObject *parent, bool denseArray)
{ {
privateData = priv;
JS_STATIC_ASSERT(sizeof(js::ObjectElements) == 2 * sizeof(js::Value)); JS_STATIC_ASSERT(sizeof(js::ObjectElements) == 2 * sizeof(js::Value));
uint32 numSlots = numFixedSlots(); uint32 numSlots = numFixedSlots();
@ -948,7 +966,6 @@ JSObject::init(JSContext *cx, js::types::TypeObject *type,
new (getElementsHeader()) js::ObjectElements(numSlots - 2); new (getElementsHeader()) js::ObjectElements(numSlots - 2);
} else { } else {
elements = js::emptyObjectElements; elements = js::emptyObjectElements;
js::ClearValueRange(fixedSlots(), numSlots);
} }
setType(type); setType(type);
@ -972,7 +989,7 @@ JSObject::initSharingEmptyShape(JSContext *cx,
void *privateValue, void *privateValue,
js::gc::AllocKind kind) js::gc::AllocKind kind)
{ {
init(cx, type, parent, privateValue, false); init(cx, type, parent, false);
js::EmptyShape *empty = type->getEmptyShape(cx, aclasp, kind); js::EmptyShape *empty = type->getEmptyShape(cx, aclasp, kind);
if (!empty) if (!empty)
@ -981,6 +998,9 @@ JSObject::initSharingEmptyShape(JSContext *cx,
if (!setInitialProperty(cx, empty)) if (!setInitialProperty(cx, empty))
return false; return false;
if (privateValue)
setPrivate(privateValue);
JS_ASSERT(!isDenseArray()); JS_ASSERT(!isDenseArray());
return true; return true;
} }
@ -1132,9 +1152,10 @@ JSObject::hasPropertyTable() const
inline size_t inline size_t
JSObject::structSize() const JSObject::structSize() const
{ {
return (isFunction() && !getPrivate()) if (isFunction() && !getFunctionPrivate())
? sizeof(JSFunction) return sizeof(JSFunction);
: (sizeof(JSObject) + sizeof(js::Value) * numFixedSlots()); uint32 nfixed = numFixedSlots() + (hasPrivate() ? 1 : 0);
return sizeof(JSObject) + (nfixed * sizeof(js::Value));
} }
inline size_t inline size_t
@ -1424,7 +1445,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto,
* the parent of the prototype's constructor. * the parent of the prototype's constructor.
*/ */
bool denseArray = (clasp == &ArrayClass); bool denseArray = (clasp == &ArrayClass);
obj->init(cx, type, parent, NULL, denseArray); obj->init(cx, type, parent, denseArray);
JS_ASSERT(type->canProvideEmptyShape(clasp)); JS_ASSERT(type->canProvideEmptyShape(clasp));
js::EmptyShape *empty = type->getEmptyShape(cx, clasp, kind); js::EmptyShape *empty = type->getEmptyShape(cx, clasp, kind);
@ -1437,7 +1458,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto,
static inline JSObject * static inline JSObject *
NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *parent) NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *parent)
{ {
gc::AllocKind kind = gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(clasp)); gc::AllocKind kind = gc::GetGCObjectKind(clasp);
return NewNativeClassInstance(cx, clasp, proto, parent, kind); return NewNativeClassInstance(cx, clasp, proto, parent, kind);
} }
@ -1486,7 +1507,7 @@ NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind kind)
static inline JSObject * static inline JSObject *
NewBuiltinClassInstance(JSContext *cx, Class *clasp) NewBuiltinClassInstance(JSContext *cx, Class *clasp)
{ {
gc::AllocKind kind = gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(clasp)); gc::AllocKind kind = gc::GetGCObjectKind(clasp);
return NewBuiltinClassInstance(cx, clasp, kind); return NewBuiltinClassInstance(cx, clasp, kind);
} }
@ -1578,8 +1599,8 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
if (!obj) if (!obj)
goto out; goto out;
/* This needs to match up with the size of JSFunction::data_padding. */ /* This needs to match up with the superclass of JSFunction. */
JS_ASSERT_IF(isFunction, kind == gc::FINALIZE_OBJECT2); JS_ASSERT_IF(isFunction, kind == gc::FINALIZE_OBJECT4);
/* /*
* Default parent to the parent of the prototype, which was set from * Default parent to the parent of the prototype, which was set from
@ -1587,7 +1608,7 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
*/ */
obj->init(cx, type, obj->init(cx, type,
(!parent && proto) ? proto->getParent() : parent, (!parent && proto) ? proto->getParent() : parent,
NULL, clasp == &ArrayClass); clasp == &ArrayClass);
if (clasp->isNative() if (clasp->isNative()
? !InitScopeForObject(cx, obj, clasp, type, kind) ? !InitScopeForObject(cx, obj, clasp, type, kind)
@ -1608,14 +1629,14 @@ NewFunction(JSContext *cx, js::GlobalObject &global)
if (!js_GetClassPrototype(cx, &global, JSProto_Function, &proto)) if (!js_GetClassPrototype(cx, &global, JSProto_Function, &proto))
return NULL; return NULL;
return detail::NewObject<WithProto::Given, true>(cx, &FunctionClass, proto, &global, return detail::NewObject<WithProto::Given, true>(cx, &FunctionClass, proto, &global,
gc::FINALIZE_OBJECT2); gc::FINALIZE_OBJECT4);
} }
static JS_ALWAYS_INLINE JSObject * static JS_ALWAYS_INLINE JSObject *
NewFunction(JSContext *cx, JSObject *parent) NewFunction(JSContext *cx, JSObject *parent)
{ {
return detail::NewObject<WithProto::Class, true>(cx, &FunctionClass, NULL, parent, return detail::NewObject<WithProto::Class, true>(cx, &FunctionClass, NULL, parent,
gc::FINALIZE_OBJECT2); gc::FINALIZE_OBJECT4);
} }
template <WithProto::e withProto> template <WithProto::e withProto>
@ -1630,7 +1651,7 @@ template <WithProto::e withProto>
static JS_ALWAYS_INLINE JSObject * static JS_ALWAYS_INLINE JSObject *
NewNonFunction(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent) NewNonFunction(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
{ {
gc::AllocKind kind = gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(clasp)); gc::AllocKind kind = gc::GetGCObjectKind(clasp);
return detail::NewObject<withProto, false>(cx, clasp, proto, parent, kind); return detail::NewObject<withProto, false>(cx, clasp, proto, parent, kind);
} }
@ -1648,7 +1669,7 @@ template <WithProto::e withProto>
static JS_ALWAYS_INLINE JSObject * static JS_ALWAYS_INLINE JSObject *
NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent) NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
{ {
gc::AllocKind kind = gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(clasp)); gc::AllocKind kind = gc::GetGCObjectKind(clasp);
return NewObject<withProto>(cx, clasp, proto, parent, kind); return NewObject<withProto>(cx, clasp, proto, parent, kind);
} }
@ -1674,7 +1695,7 @@ NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::
*/ */
obj->init(cx, type, obj->init(cx, type,
(!parent && type->proto) ? type->proto->getParent() : parent, (!parent && type->proto) ? type->proto->getParent() : parent,
NULL, false); false);
if (!InitScopeForObject(cx, obj, &ObjectClass, type, kind)) { if (!InitScopeForObject(cx, obj, &ObjectClass, type, kind)) {
obj = NULL; obj = NULL;

View File

@ -74,8 +74,12 @@ using namespace js;
using namespace js::gc; using namespace js::gc;
using namespace js::types; using namespace js::types;
/* slots can only be upto 255 */ /*
static const uint8 ARRAYBUFFER_RESERVED_SLOTS = 16; * Allocate array buffers with the maximum number of fixed slots marked as
* reserved, so that the fixed slots may be used for the buffer's contents.
* The last fixed slot is kept for the object's private data.
*/
static const uint8 ARRAYBUFFER_RESERVED_SLOTS = JSObject::MAX_FIXED_SLOTS - 1;
static bool static bool
ValueIsLength(JSContext *cx, const Value &v, jsuint *len) ValueIsLength(JSContext *cx, const Value &v, jsuint *len)
@ -765,7 +769,7 @@ TypedArray::lengthOffset()
/* static */ int /* static */ int
TypedArray::dataOffset() TypedArray::dataOffset()
{ {
return offsetof(JSObject, privateData); return JSObject::getPrivateDataOffset(NUM_FIXED_SLOTS);
} }
/* Helper clamped uint8 type */ /* Helper clamped uint8 type */
@ -1298,6 +1302,8 @@ class TypedArrayTemplate
return false; return false;
obj->setLastPropertyInfallible(empty); obj->setLastPropertyInfallible(empty);
JS_ASSERT(obj->numFixedSlots() == NUM_FIXED_SLOTS);
// FIXME Bug 599008: make it ok to call preventExtensions here. // FIXME Bug 599008: make it ok to call preventExtensions here.
obj->flags |= JSObject::NOT_EXTENSIBLE; obj->flags |= JSObject::NOT_EXTENSIBLE;

View File

@ -193,7 +193,8 @@ struct JS_FRIEND_API(TypedArray) {
FIELD_BYTELENGTH, FIELD_BYTELENGTH,
FIELD_TYPE, FIELD_TYPE,
FIELD_BUFFER, FIELD_BUFFER,
FIELD_MAX FIELD_MAX,
NUM_FIXED_SLOTS = 7
}; };
// and MUST NOT be used to construct new objects. // and MUST NOT be used to construct new objects.

View File

@ -95,7 +95,7 @@ TypedArray::getBuffer(JSObject *obj) {
inline void * inline void *
TypedArray::getDataOffset(JSObject *obj) { TypedArray::getDataOffset(JSObject *obj) {
return (void *)obj->getPrivate(); return (void *)obj->getPrivate(NUM_FIXED_SLOTS);
} }
} }

View File

@ -1253,6 +1253,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
JS_ASSERT(cx->typeInferenceEnabled()); JS_ASSERT(cx->typeInferenceEnabled());
JS_ASSERT(!templateObject->hasDynamicSlots()); JS_ASSERT(!templateObject->hasDynamicSlots());
JS_ASSERT(!templateObject->hasDynamicElements()); JS_ASSERT(!templateObject->hasDynamicElements());
JS_ASSERT(!(templateObject->getClass()->flags & JSCLASS_HAS_PRIVATE));
#ifdef JS_GC_ZEAL #ifdef JS_GC_ZEAL
if (cx->runtime->needZealousGC()) if (cx->runtime->needZealousGC())
@ -1304,7 +1305,6 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
store32(Imm32(templateObject->flags), Address(result, offsetof(JSObject, flags))); store32(Imm32(templateObject->flags), Address(result, offsetof(JSObject, flags)));
storePtr(ImmPtr(NULL), Address(result, JSObject::offsetOfSlots())); storePtr(ImmPtr(NULL), Address(result, JSObject::offsetOfSlots()));
storePtr(ImmPtr(templateObject->parent), Address(result, offsetof(JSObject, parent))); storePtr(ImmPtr(templateObject->parent), Address(result, offsetof(JSObject, parent)));
storePtr(ImmPtr(templateObject->privateData), Address(result, offsetof(JSObject, privateData)));
if (templateObject->isDenseArray()) { if (templateObject->isDenseArray()) {
/* Fill in the elements header. */ /* Fill in the elements header. */

View File

@ -3340,7 +3340,7 @@ mjit::Compiler::checkCallApplySpeculation(uint32 callImmArgc, uint32 speculatedA
if (origCalleeType.isSet()) if (origCalleeType.isSet())
isObj = masm.testObject(Assembler::NotEqual, origCalleeType.reg()); isObj = masm.testObject(Assembler::NotEqual, origCalleeType.reg());
Jump isFun = masm.testFunction(Assembler::NotEqual, origCalleeData, temp); Jump isFun = masm.testFunction(Assembler::NotEqual, origCalleeData, temp);
masm.loadObjPrivate(origCalleeData, origCalleeData); masm.loadObjPrivate(origCalleeData, origCalleeData, JSObject::FUN_CLASS_NFIXED_SLOTS);
Native native = *PC == JSOP_FUNCALL ? js_fun_call : js_fun_apply; Native native = *PC == JSOP_FUNCALL ? js_fun_call : js_fun_apply;
Jump isNative = masm.branchPtr(Assembler::NotEqual, Jump isNative = masm.branchPtr(Assembler::NotEqual,
Address(origCalleeData, JSFunction::offsetOfNativeOrScript()), Address(origCalleeData, JSFunction::offsetOfNativeOrScript()),
@ -3621,7 +3621,7 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew, FrameSize
Jump notFunction = stubcc.masm.testFunction(Assembler::NotEqual, icCalleeData, tmp); Jump notFunction = stubcc.masm.testFunction(Assembler::NotEqual, icCalleeData, tmp);
/* Test if the function is scripted. */ /* Test if the function is scripted. */
stubcc.masm.loadObjPrivate(icCalleeData, funPtrReg); stubcc.masm.loadObjPrivate(icCalleeData, funPtrReg, JSObject::FUN_CLASS_NFIXED_SLOTS);
stubcc.masm.load16(Address(funPtrReg, offsetof(JSFunction, flags)), tmp); stubcc.masm.load16(Address(funPtrReg, offsetof(JSFunction, flags)), tmp);
stubcc.masm.and32(Imm32(JSFUN_KINDMASK), tmp); stubcc.masm.and32(Imm32(JSFUN_KINDMASK), tmp);
Jump isNative = stubcc.masm.branch32(Assembler::Below, tmp, Imm32(JSFUN_INTERPRETED)); Jump isNative = stubcc.masm.branch32(Assembler::Below, tmp, Imm32(JSFUN_INTERPRETED));
@ -5670,7 +5670,7 @@ mjit::Compiler::iter(uintN flags)
stubcc.linkExit(nullIterator, Uses(1)); stubcc.linkExit(nullIterator, Uses(1));
/* Get NativeIterator from iter obj. */ /* Get NativeIterator from iter obj. */
masm.loadObjPrivate(ioreg, nireg); masm.loadObjPrivate(ioreg, nireg, JSObject::ITER_CLASS_NFIXED_SLOTS);
/* Test for active iterator. */ /* Test for active iterator. */
Address flagsAddr(nireg, offsetof(NativeIterator, flags)); Address flagsAddr(nireg, offsetof(NativeIterator, flags));
@ -5759,7 +5759,7 @@ mjit::Compiler::iterNext(ptrdiff_t offset)
stubcc.linkExit(notFast, Uses(1)); stubcc.linkExit(notFast, Uses(1));
/* Get private from iter obj. */ /* Get private from iter obj. */
masm.loadObjPrivate(reg, T1); masm.loadObjPrivate(reg, T1, JSObject::ITER_CLASS_NFIXED_SLOTS);
RegisterID T3 = frame.allocReg(); RegisterID T3 = frame.allocReg();
RegisterID T4 = frame.allocReg(); RegisterID T4 = frame.allocReg();
@ -5814,7 +5814,7 @@ mjit::Compiler::iterMore(jsbytecode *target)
stubcc.linkExitForBranch(notFast); stubcc.linkExitForBranch(notFast);
/* Get private from iter obj. */ /* Get private from iter obj. */
masm.loadObjPrivate(reg, reg); masm.loadObjPrivate(reg, reg, JSObject::ITER_CLASS_NFIXED_SLOTS);
/* Test that the iterator supports fast iteration. */ /* Test that the iterator supports fast iteration. */
notFast = masm.branchTest32(Assembler::NonZero, Address(reg, offsetof(NativeIterator, flags)), notFast = masm.branchTest32(Assembler::NonZero, Address(reg, offsetof(NativeIterator, flags)),
@ -5853,7 +5853,7 @@ mjit::Compiler::iterEnd()
stubcc.linkExit(notIterator, Uses(1)); stubcc.linkExit(notIterator, Uses(1));
/* Get private from iter obj. */ /* Get private from iter obj. */
masm.loadObjPrivate(reg, T1); masm.loadObjPrivate(reg, T1, JSObject::ITER_CLASS_NFIXED_SLOTS);
RegisterID T2 = frame.allocReg(); RegisterID T2 = frame.allocReg();

View File

@ -747,7 +747,7 @@ class CallCompiler : public BaseCompiler
/* Guard that it's the same function. */ /* Guard that it's the same function. */
JSFunction *fun = obj->getFunctionPrivate(); JSFunction *fun = obj->getFunctionPrivate();
masm.loadObjPrivate(ic.funObjReg, t0); masm.loadObjPrivate(ic.funObjReg, t0, JSObject::FUN_CLASS_NFIXED_SLOTS);
Jump funGuard = masm.branchPtr(Assembler::NotEqual, t0, ImmPtr(fun)); Jump funGuard = masm.branchPtr(Assembler::NotEqual, t0, ImmPtr(fun));
Jump done = masm.jump(); Jump done = masm.jump();

View File

@ -345,8 +345,8 @@ class NunboxAssembler : public JSC::MacroAssembler
loadPtr(payloadOf(privAddr), to); loadPtr(payloadOf(privAddr), to);
} }
void loadObjPrivate(RegisterID base, RegisterID to) { void loadObjPrivate(RegisterID base, RegisterID to, uint32 nfixed) {
Address priv(base, offsetof(JSObject, privateData)); Address priv(base, JSObject::getPrivateDataOffset(nfixed));
loadPtr(priv, to); loadPtr(priv, to);
} }

View File

@ -357,7 +357,7 @@ class SetPropCompiler : public PICStubCompiler
uint16 slot = uint16(shape->shortid()); uint16 slot = uint16(shape->shortid());
/* Guard that the call object has a frame. */ /* Guard that the call object has a frame. */
masm.loadObjPrivate(pic.objReg, pic.shapeReg); masm.loadObjPrivate(pic.objReg, pic.shapeReg, obj->numFixedSlots());
Jump escapedFrame = masm.branchTestPtr(Assembler::Zero, pic.shapeReg, pic.shapeReg); Jump escapedFrame = masm.branchTestPtr(Assembler::Zero, pic.shapeReg, pic.shapeReg);
{ {
@ -1554,7 +1554,7 @@ class ScopeNameCompiler : public PICStubCompiler
} }
/* Get callobj's stack frame. */ /* Get callobj's stack frame. */
masm.loadObjPrivate(pic.objReg, pic.shapeReg); masm.loadObjPrivate(pic.objReg, pic.shapeReg, getprop.holder->numFixedSlots());
JSFunction *fun = getprop.holder->asCall().getCalleeFunction(); JSFunction *fun = getprop.holder->asCall().getCalleeFunction();
uint16 slot = uint16(shape->shortid()); uint16 slot = uint16(shape->shortid());
@ -2556,7 +2556,7 @@ GetElementIC::attachArguments(JSContext *cx, JSObject *obj, const Value &v, jsid
} }
Jump holeCheck = masm.branchPtr(Assembler::Equal, objReg, ImmType(JSVAL_TYPE_MAGIC)); Jump holeCheck = masm.branchPtr(Assembler::Equal, objReg, ImmType(JSVAL_TYPE_MAGIC));
Address privateData(typeReg, offsetof(JSObject, privateData)); Address privateData(typeReg, JSObject::getPrivateDataOffset(ArgumentsObject::NFIXED_SLOTS));
Jump liveArguments = masm.branchPtr(Assembler::NotEqual, privateData, ImmPtr(0)); Jump liveArguments = masm.branchPtr(Assembler::NotEqual, privateData, ImmPtr(0));
masm.loadPrivate(Address(typeReg, JSObject::getFixedSlotOffset(ArgumentsObject::DATA_SLOT)), objReg); masm.loadPrivate(Address(typeReg, JSObject::getFixedSlotOffset(ArgumentsObject::DATA_SLOT)), objReg);

View File

@ -274,8 +274,8 @@ class PunboxAssembler : public JSC::MacroAssembler
lshiftPtr(Imm32(1), to); lshiftPtr(Imm32(1), to);
} }
void loadObjPrivate(RegisterID base, RegisterID to) { void loadObjPrivate(RegisterID base, RegisterID to, uint32 nfixed) {
Address priv(base, offsetof(JSObject, privateData)); Address priv(base, JSObject::getPrivateDataOffset(nfixed));
loadPtr(priv, to); loadPtr(priv, to);
} }

View File

@ -436,10 +436,13 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet ac
case ACCSET_OBJ_PRIVATE: case ACCSET_OBJ_PRIVATE:
// base = <JSObject> // base = <JSObject>
// ins = {ld,st}p.objprivate base[offsetof(JSObject, privateData)] // ins = {ld,st}p.objprivate base[offsetof(JSObject, privateData)]
ok = false;
/*
ok = (op == LIR_ldi || op == LIR_ldp || ok = (op == LIR_ldi || op == LIR_ldp ||
op == LIR_sti || op == LIR_stp) && op == LIR_sti || op == LIR_stp) &&
disp == offsetof(JSObject, privateData) && disp == offsetof(JSObject, privateData) &&
couldBeObjectOrString(base); couldBeObjectOrString(base);
*/
break; break;
case ACCSET_OBJ_CAPACITY: case ACCSET_OBJ_CAPACITY:
@ -497,9 +500,12 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet ac
case ACCSET_ITER: case ACCSET_ITER:
// base = ldp.objprivate ...[offsetof(JSObject, privateData)] // base = ldp.objprivate ...[offsetof(JSObject, privateData)]
// ins = {ld,st}p.iter base[<disp within NativeIterator>] // ins = {ld,st}p.iter base[<disp within NativeIterator>]
ok = false;
/*
ok = (op == LIR_ldp || op == LIR_stp) && ok = (op == LIR_ldp || op == LIR_stp) &&
dispWithin(NativeIterator) && dispWithin(NativeIterator) &&
match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
*/
break; break;
case ACCSET_ITER_PROPS: case ACCSET_ITER_PROPS:

View File

@ -510,19 +510,22 @@ class Writer
} }
nj::LIns *ldpObjPrivate(nj::LIns *obj) const { nj::LIns *ldpObjPrivate(nj::LIns *obj) const {
return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, privateData), JS_NOT_REACHED("FIXME");
return name(lir->insLoad(nj::LIR_ldp, obj, 0,
ACCSET_OBJ_PRIVATE), ACCSET_OBJ_PRIVATE),
"private"); "private");
} }
nj::LIns *lduiObjPrivate(nj::LIns *obj) const { nj::LIns *lduiObjPrivate(nj::LIns *obj) const {
return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, privateData), JS_NOT_REACHED("FIXME");
return name(lir->insLoad(nj::LIR_ldi, obj, 0,
ACCSET_OBJ_PRIVATE), ACCSET_OBJ_PRIVATE),
"private_uint32"); "private_uint32");
} }
nj::LIns *stuiObjPrivate(nj::LIns *obj, nj::LIns *value) const { nj::LIns *stuiObjPrivate(nj::LIns *obj, nj::LIns *value) const {
return name(lir->insStore(nj::LIR_sti, value, obj, offsetof(JSObject, privateData), JS_NOT_REACHED("FIXME");
return name(lir->insStore(nj::LIR_sti, value, obj, 0,
ACCSET_OBJ_PRIVATE), ACCSET_OBJ_PRIVATE),
"private_uint32"); "private_uint32");
} }
@ -557,7 +560,8 @@ class Writer
} }
nj::LIns *ldpConstTypedArrayData(nj::LIns *obj) const { nj::LIns *ldpConstTypedArrayData(nj::LIns *obj) const {
return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, privateData), ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayData"); JS_NOT_REACHED("FIXME");
return name(lir->insLoad(nj::LIR_ldp, obj, 0, ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayData");
} }
nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const {

View File

@ -151,6 +151,7 @@ class ArgumentsObject : public ::JSObject
public: public:
static const uint32 RESERVED_SLOTS = 2; static const uint32 RESERVED_SLOTS = 2;
static const uint32 NFIXED_SLOTS = 3;
private: private:
/* Lower-order bit stolen from the length slot. */ /* Lower-order bit stolen from the length slot. */

View File

@ -56,7 +56,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
{ {
Bindings &bindings = script->bindings; Bindings &bindings = script->bindings;
size_t argsVars = bindings.countArgsAndVars(); size_t argsVars = bindings.countArgsAndVars();
size_t slots = RESERVED_SLOTS + argsVars; size_t slots = RESERVED_SLOTS + argsVars + 1; /* Add one for privateData. */
gc::AllocKind kind = gc::GetGCObjectKind(slots); gc::AllocKind kind = gc::GetGCObjectKind(slots);
/* /*