mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Remove JSObject::privateData, bug 693479.
This commit is contained in:
parent
f5a853bac0
commit
e9b876258d
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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). */
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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]; };
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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. */
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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 {
|
||||||
|
@ -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. */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user