mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 727306 - Specialize HeapValue::postWriteBarrier for object slots; r=billm
Because we need to re-alloc the object slots pointers for slots growth and actively move the slots buffer between objects in TradeGuts, we cannot safely store pointers to slots in our write buffer. Instead we want to store a pair of JSObject* + offset in the write buffer. This effectively means that we need to specialize the HeapValue::postWriteBarrier used when storing to slots. This patch sub-classes HeapValue and uses this sub-class for object slots. --HG-- extra : rebase_source : 632ad9fd74f638cf9cadc19d6bc0aac8d6cc1cb1
This commit is contained in:
parent
6c2b16a1a1
commit
7e0032bea8
@ -46,40 +46,51 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
ClearValueRange(JSCompartment *comp, HeapValue *vec, uintN len, bool useHoles)
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(const Value &value)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].set(comp, MagicValue(JS_ARRAY_HOLE));
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].set(comp, UndefinedValue());
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (value.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
|
||||
writeBarrierPre(cell->compartment(), value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
InitValueRange(HeapValue *vec, uintN len, bool useHoles)
|
||||
inline void
|
||||
EncapsulatedValue::writeBarrierPre(JSCompartment *comp, const Value &value)
|
||||
{
|
||||
if (useHoles) {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].init(MagicValue(JS_ARRAY_HOLE));
|
||||
} else {
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].init(UndefinedValue());
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (comp->needsBarrier()) {
|
||||
Value tmp(value);
|
||||
js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
DestroyValueRange(HeapValue *vec, uintN len)
|
||||
inline void
|
||||
EncapsulatedValue::pre()
|
||||
{
|
||||
for (uintN i = 0; i < len; i++)
|
||||
vec[i].~HeapValue();
|
||||
writeBarrierPre(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
EncapsulatedValue::pre(JSCompartment *comp)
|
||||
{
|
||||
writeBarrierPre(comp, value);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue()
|
||||
: EncapsulatedValue(UndefinedValue())
|
||||
{
|
||||
post();
|
||||
}
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue(const Value &v)
|
||||
: value(v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post();
|
||||
@ -87,7 +98,7 @@ HeapValue::HeapValue(const Value &v)
|
||||
|
||||
inline
|
||||
HeapValue::HeapValue(const HeapValue &v)
|
||||
: value(v.value)
|
||||
: EncapsulatedValue(v.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v.value));
|
||||
post();
|
||||
@ -114,61 +125,6 @@ HeapValue::init(JSCompartment *comp, const Value &v)
|
||||
post(comp);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPre(const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (value.isMarkable()) {
|
||||
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
|
||||
writeBarrierPre(cell->compartment(), value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPre(JSCompartment *comp, const Value &value)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (comp->needsBarrier()) {
|
||||
Value tmp(value);
|
||||
js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::pre()
|
||||
{
|
||||
writeBarrierPre(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post()
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::pre(JSCompartment *comp)
|
||||
{
|
||||
writeBarrierPre(comp, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post(JSCompartment *comp)
|
||||
{
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
HeapValue::operator=(const Value &v)
|
||||
{
|
||||
@ -206,6 +162,109 @@ HeapValue::set(JSCompartment *comp, const Value &v)
|
||||
post(comp);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post()
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapValue::post(JSCompartment *comp)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const Value &v)
|
||||
: EncapsulatedValue(v)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &s)
|
||||
: EncapsulatedValue(s.value)
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedValue(s.value));
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapSlot::~HeapSlot()
|
||||
{
|
||||
pre();
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::init(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
value = v;
|
||||
post(comp, obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(!obj->isArray(), &obj->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
|
||||
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::set(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
|
||||
{
|
||||
JS_ASSERT_IF(!obj->isArray(), &const_cast<JSObject *>(obj)->getSlotRef(slot) == this);
|
||||
JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
|
||||
JS_ASSERT(obj->compartment() == comp);
|
||||
|
||||
pre(comp);
|
||||
JS_ASSERT(!IsPoisonedValue(v));
|
||||
value = v;
|
||||
post(comp, obj, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSObject *obj, uint32_t slot)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSObject *owner, uint32_t slot)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(owner, slot);
|
||||
}
|
||||
|
||||
inline void
|
||||
HeapSlot::post(JSCompartment *comp, JSObject *owner, uint32_t slot)
|
||||
{
|
||||
HeapSlot::writeBarrierPost(comp, owner, slot);
|
||||
}
|
||||
|
||||
inline
|
||||
HeapId::HeapId(jsid id)
|
||||
: value(id)
|
||||
|
@ -299,31 +299,24 @@ struct HeapPtrHasher
|
||||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
||||
|
||||
class HeapValue
|
||||
class EncapsulatedValue
|
||||
{
|
||||
protected:
|
||||
Value value;
|
||||
|
||||
public:
|
||||
explicit HeapValue() : value(UndefinedValue()) {}
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
|
||||
inline ~HeapValue();
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSCompartment *comp, const Value &v);
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
* determine the compartment of the value before it can decide whether to do
|
||||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
* Ensure that EncapsulatedValue is not constructable, except by our
|
||||
* implementations.
|
||||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
EncapsulatedValue() MOZ_DELETE;
|
||||
EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
|
||||
EncapsulatedValue(const Value &v) : value(v) {}
|
||||
~EncapsulatedValue() {}
|
||||
|
||||
public:
|
||||
const Value &get() const { return value; }
|
||||
Value *unsafeGet() { return &value; }
|
||||
operator const Value &() const { return value; }
|
||||
@ -360,38 +353,93 @@ class HeapValue
|
||||
#endif
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
|
||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(JSCompartment *comp);
|
||||
};
|
||||
|
||||
class HeapValue : public EncapsulatedValue
|
||||
{
|
||||
public:
|
||||
explicit inline HeapValue();
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
inline ~HeapValue();
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSCompartment *comp, const Value &v);
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
* determine the compartment of the value before it can decide whether to do
|
||||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
|
||||
|
||||
private:
|
||||
inline void pre();
|
||||
inline void post();
|
||||
|
||||
inline void pre(JSCompartment *comp);
|
||||
inline void post(JSCompartment *comp);
|
||||
};
|
||||
|
||||
static inline const Value *
|
||||
Valueify(const HeapValue *array)
|
||||
class HeapSlot : public EncapsulatedValue
|
||||
{
|
||||
JS_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||
/*
|
||||
* Operator= is not valid for HeapSlot because is must take the object and
|
||||
* slot offset to provide to the post/generational barrier.
|
||||
*/
|
||||
inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
explicit inline HeapSlot() MOZ_DELETE;
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
|
||||
inline ~HeapSlot();
|
||||
|
||||
inline void init(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
inline void set(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno);
|
||||
|
||||
private:
|
||||
inline void post(JSObject *owner, uint32_t slot);
|
||||
inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
|
||||
};
|
||||
|
||||
static inline const Value *
|
||||
Valueify(const EncapsulatedValue *array)
|
||||
{
|
||||
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
|
||||
return (const Value *)array;
|
||||
}
|
||||
|
||||
class HeapValueArray
|
||||
class HeapSlotArray
|
||||
{
|
||||
HeapValue *array;
|
||||
HeapSlot *array;
|
||||
|
||||
public:
|
||||
HeapValueArray(HeapValue *array) : array(array) {}
|
||||
HeapSlotArray(HeapSlot *array) : array(array) {}
|
||||
|
||||
operator const Value *() const { return Valueify(array); }
|
||||
operator HeapValue *() const { return array; }
|
||||
operator HeapSlot *() const { return array; }
|
||||
|
||||
HeapValueArray operator +(int offset) const { return HeapValueArray(array + offset); }
|
||||
HeapValueArray operator +(uint32_t offset) const { return HeapValueArray(array + offset); }
|
||||
HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
|
||||
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
||||
};
|
||||
|
||||
class HeapId
|
||||
|
@ -1194,7 +1194,7 @@ array_trace(JSTracer *trc, JSObject *obj)
|
||||
JS_ASSERT(obj->isDenseArray());
|
||||
|
||||
uint32_t initLength = obj->getDenseArrayInitializedLength();
|
||||
MarkValueRange(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
MarkSlotRange(trc, initLength, obj->getDenseArrayElements(), "element");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -1377,7 +1377,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
this->shape_ = shape;
|
||||
|
||||
/* Take ownership of the dense elements, reset to an empty dense array. */
|
||||
HeapValue *elems = elements;
|
||||
HeapSlot *elems = elements;
|
||||
elements = emptyObjectElements;
|
||||
|
||||
/* Root all values in the array during conversion. */
|
||||
|
@ -64,7 +64,12 @@ JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32_t index, uint3
|
||||
markDenseArrayNotPacked(cx);
|
||||
|
||||
if (initlen < index + extra) {
|
||||
js::InitValueRange(elements + initlen, index + extra - initlen, true);
|
||||
JSCompartment *comp = compartment();
|
||||
size_t offset = initlen;
|
||||
for (js::HeapSlot *sp = elements + initlen;
|
||||
sp != elements + (index + extra);
|
||||
sp++, offset++)
|
||||
sp->init(comp, this, offset, js::MagicValue(JS_ARRAY_HOLE));
|
||||
initlen = index + extra;
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,8 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
|
||||
return NULL;
|
||||
|
||||
data->callee.init(ObjectValue(callee));
|
||||
InitValueRange(data->slots, argc, false);
|
||||
for (HeapValue *vp = data->slots; vp != data->slots + argc; vp++)
|
||||
vp->init(UndefinedValue());
|
||||
|
||||
/* We have everything needed to fill in the object, so make the object. */
|
||||
JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyArgumentsShape, type, NULL);
|
||||
|
@ -356,6 +356,41 @@ MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
/*** Slot Marking ***/
|
||||
|
||||
void
|
||||
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
MarkValueInternal(trc, s->unsafeGet());
|
||||
}
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JS_SET_TRACING_INDEX(trc, name, i);
|
||||
MarkValueInternal(trc, vec[i].unsafeGet());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
|
||||
{
|
||||
if (s->isMarkable()) {
|
||||
Cell *cell = (Cell *)s->toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
/* In case we're called from a write barrier. */
|
||||
if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
|
||||
return;
|
||||
|
||||
MarkSlot(trc, s, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Special Marking ***/
|
||||
|
||||
/*
|
||||
@ -376,23 +411,6 @@ MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
|
||||
MarkValueInternal(trc, v);
|
||||
}
|
||||
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name)
|
||||
{
|
||||
if (v->isMarkable()) {
|
||||
Cell *cell = (Cell *)v->toGCThing();
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
|
||||
return;
|
||||
|
||||
/* In case we're called from a write barrier. */
|
||||
if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
|
||||
return;
|
||||
|
||||
MarkValue(trc, v, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Push Mark Stack ***/
|
||||
|
||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||
@ -896,21 +914,21 @@ PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
|
||||
|
||||
using namespace js::gc;
|
||||
|
||||
struct ValueArrayLayout
|
||||
struct SlotArrayLayout
|
||||
{
|
||||
union {
|
||||
HeapValue *end;
|
||||
HeapSlot *end;
|
||||
js::Class *clasp;
|
||||
};
|
||||
union {
|
||||
HeapValue *start;
|
||||
HeapSlot *start;
|
||||
uintptr_t index;
|
||||
};
|
||||
JSObject *obj;
|
||||
|
||||
static void staticAsserts() {
|
||||
/* This should have the same layout as three mark stack items. */
|
||||
JS_STATIC_ASSERT(sizeof(ValueArrayLayout) == 3 * sizeof(uintptr_t));
|
||||
JS_STATIC_ASSERT(sizeof(SlotArrayLayout) == 3 * sizeof(uintptr_t));
|
||||
}
|
||||
};
|
||||
|
||||
@ -933,16 +951,16 @@ GCMarker::saveValueRanges()
|
||||
uintptr_t tag = *--p & StackTagMask;
|
||||
if (tag == ValueArrayTag) {
|
||||
p -= 2;
|
||||
ValueArrayLayout *arr = reinterpret_cast<ValueArrayLayout *>(p);
|
||||
SlotArrayLayout *arr = reinterpret_cast<SlotArrayLayout *>(p);
|
||||
JSObject *obj = arr->obj;
|
||||
|
||||
if (obj->getClass() == &ArrayClass) {
|
||||
HeapValue *vp = obj->getDenseArrayElements();
|
||||
HeapSlot *vp = obj->getDenseArrayElements();
|
||||
JS_ASSERT(arr->start >= vp &&
|
||||
arr->end == vp + obj->getDenseArrayInitializedLength());
|
||||
arr->index = arr->start - vp;
|
||||
} else {
|
||||
HeapValue *vp = obj->fixedSlots();
|
||||
HeapSlot *vp = obj->fixedSlots();
|
||||
unsigned nfixed = obj->numFixedSlots();
|
||||
if (arr->start >= vp && arr->start < vp + nfixed) {
|
||||
JS_ASSERT(arr->end == vp + Min(nfixed, obj->slotSpan()));
|
||||
@ -975,7 +993,7 @@ GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
|
||||
return false;
|
||||
|
||||
uint32_t initlen = obj->getDenseArrayInitializedLength();
|
||||
HeapValue *vp = obj->getDenseArrayElements();
|
||||
HeapSlot *vp = obj->getDenseArrayElements();
|
||||
if (start < initlen) {
|
||||
*vpp = vp + start;
|
||||
*endp = vp + initlen;
|
||||
@ -984,7 +1002,7 @@ GCMarker::restoreValueArray(JSObject *obj, void **vpp, void **endp)
|
||||
*vpp = *endp = vp;
|
||||
}
|
||||
} else {
|
||||
HeapValue *vp = obj->fixedSlots();
|
||||
HeapSlot *vp = obj->fixedSlots();
|
||||
unsigned nfixed = obj->numFixedSlots();
|
||||
unsigned nslots = obj->slotSpan();
|
||||
if (start < nfixed) {
|
||||
@ -1011,7 +1029,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
* object directly. It allows to eliminate the tail recursion and
|
||||
* significantly improve the marking performance, see bug 641025.
|
||||
*/
|
||||
HeapValue *vp, *end;
|
||||
HeapSlot *vp, *end;
|
||||
JSObject *obj;
|
||||
|
||||
uintptr_t addr = stack.pop();
|
||||
@ -1026,8 +1044,8 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
uintptr_t addr3 = stack.pop();
|
||||
JS_ASSERT(addr2 <= addr3);
|
||||
JS_ASSERT((addr3 - addr2) % sizeof(Value) == 0);
|
||||
vp = reinterpret_cast<HeapValue *>(addr2);
|
||||
end = reinterpret_cast<HeapValue *>(addr3);
|
||||
vp = reinterpret_cast<HeapSlot *>(addr2);
|
||||
end = reinterpret_cast<HeapSlot *>(addr3);
|
||||
goto scan_value_array;
|
||||
}
|
||||
|
||||
|
@ -114,18 +114,26 @@ MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
|
||||
MarkValueRootRange(trc, end - begin, begin, name);
|
||||
}
|
||||
|
||||
/*** Special Cases ***/
|
||||
/*** Slot Marking ***/
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
void
|
||||
MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
|
||||
|
||||
/*
|
||||
* Mark a value that may be in a different compartment from the compartment
|
||||
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
|
||||
*/
|
||||
void
|
||||
MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name);
|
||||
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name);
|
||||
|
||||
/*** Special Cases ***/
|
||||
|
||||
/* Direct value access used by the write barriers and the methodjit. */
|
||||
void
|
||||
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
|
||||
|
||||
/*
|
||||
* MarkChildren<JSObject> is exposed solely for preWriteBarrier on
|
||||
|
@ -352,6 +352,22 @@ Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, size_t len)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsinterp_h___ */
|
||||
|
101
js/src/jsobj.cpp
101
js/src/jsobj.cpp
@ -2753,7 +2753,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type, JSObject *parent
|
||||
if (!shape)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
HeapSlot *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
|
||||
return NULL;
|
||||
|
||||
@ -3250,8 +3250,8 @@ struct JSObject::TradeGutsReserved {
|
||||
int newbfixed;
|
||||
Shape *newashape;
|
||||
Shape *newbshape;
|
||||
HeapValue *newaslots;
|
||||
HeapValue *newbslots;
|
||||
HeapSlot *newaslots;
|
||||
HeapSlot *newbslots;
|
||||
|
||||
TradeGutsReserved(JSContext *cx)
|
||||
: cx(cx), avals(cx), bvals(cx),
|
||||
@ -3350,16 +3350,16 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
|
||||
unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan());
|
||||
|
||||
if (adynamic) {
|
||||
reserved.newaslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * adynamic);
|
||||
reserved.newaslots = (HeapSlot *) cx->malloc_(sizeof(HeapSlot) * adynamic);
|
||||
if (!reserved.newaslots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(reserved.newaslots, adynamic);
|
||||
Debug_SetSlotRangeToCrashOnTouch(reserved.newaslots, adynamic);
|
||||
}
|
||||
if (bdynamic) {
|
||||
reserved.newbslots = (HeapValue *) cx->malloc_(sizeof(HeapValue) * bdynamic);
|
||||
reserved.newbslots = (HeapSlot *) cx->malloc_(sizeof(HeapSlot) * bdynamic);
|
||||
if (!reserved.newbslots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(reserved.newbslots, bdynamic);
|
||||
Debug_SetSlotRangeToCrashOnTouch(reserved.newbslots, bdynamic);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3421,11 +3421,10 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
* Trigger post barriers for fixed slots. JSObject bits are barriered
|
||||
* below, in common with the other case.
|
||||
*/
|
||||
JSCompartment *comp = cx->compartment;
|
||||
for (size_t i = 0; i < a->numFixedSlots(); ++i) {
|
||||
HeapValue *slotA = &a->getFixedSlotRef(i);
|
||||
HeapValue *slotB = &b->getFixedSlotRef(i);
|
||||
HeapValue::writeBarrierPost(*slotA, slotA);
|
||||
HeapValue::writeBarrierPost(*slotB, slotB);
|
||||
HeapSlot::writeBarrierPost(comp, a, i);
|
||||
HeapSlot::writeBarrierPost(comp, b, i);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -3815,56 +3814,28 @@ js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto,
|
||||
ps, fs, static_ps, static_fs, ctorp, ctorKind);
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::getSlotRange(size_t start, size_t length,
|
||||
HeapValue **fixedStart, HeapValue **fixedEnd,
|
||||
HeapValue **slotsStart, HeapValue **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(!isDenseArray());
|
||||
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + length];
|
||||
*slotsStart = *slotsEnd = NULL;
|
||||
} else {
|
||||
size_t localCopy = fixed - start;
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + localCopy];
|
||||
*slotsStart = &slots[0];
|
||||
*slotsEnd = &slots[length - localCopy];
|
||||
}
|
||||
} else {
|
||||
*fixedStart = *fixedEnd = NULL;
|
||||
*slotsStart = &slots[start - fixed];
|
||||
*slotsEnd = &slots[start - fixed + length];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::initSlotRange(size_t start, const Value *vector, size_t length)
|
||||
{
|
||||
JSCompartment *comp = compartment();
|
||||
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
|
||||
vp->init(comp, *vector++);
|
||||
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
|
||||
vp->init(comp, *vector++);
|
||||
for (HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->init(comp, this, start++, *vector++);
|
||||
for (HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->init(comp, this, start++, *vector++);
|
||||
}
|
||||
|
||||
void
|
||||
JSObject::copySlotRange(size_t start, const Value *vector, size_t length)
|
||||
{
|
||||
JSCompartment *comp = compartment();
|
||||
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
|
||||
vp->set(comp, *vector++);
|
||||
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
|
||||
vp->set(comp, *vector++);
|
||||
for (HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->set(comp, this, start++, *vector++);
|
||||
for (HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->set(comp, this, start++, *vector++);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -3873,20 +3844,10 @@ JSObject::invalidateSlotRange(size_t start, size_t length)
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(!isDenseArray());
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
|
||||
/* No bounds checks, allocated space has been updated but not the shape. */
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
Debug_SetValueRangeToCrashOnTouch(fixedSlots() + start, length);
|
||||
} else {
|
||||
size_t localClear = fixed - start;
|
||||
Debug_SetValueRangeToCrashOnTouch(fixedSlots() + start, localClear);
|
||||
Debug_SetValueRangeToCrashOnTouch(slots, length - localClear);
|
||||
}
|
||||
} else {
|
||||
Debug_SetValueRangeToCrashOnTouch(slots + start - fixed, length);
|
||||
}
|
||||
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
@ -4006,24 +3967,24 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||
}
|
||||
|
||||
if (!oldCount) {
|
||||
slots = (HeapValue *) cx->malloc_(newCount * sizeof(HeapValue));
|
||||
slots = (HeapSlot *) cx->malloc_(newCount * sizeof(HeapSlot));
|
||||
if (!slots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(slots, newCount);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slots, newCount);
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, newSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapValue *newslots = (HeapValue*) cx->realloc_(slots, oldCount * sizeof(HeapValue),
|
||||
newCount * sizeof(HeapValue));
|
||||
HeapSlot *newslots = (HeapSlot*) cx->realloc_(slots, oldCount * sizeof(HeapSlot),
|
||||
newCount * sizeof(HeapSlot));
|
||||
if (!newslots)
|
||||
return false; /* Leave slots at its old size. */
|
||||
|
||||
bool changed = slots != newslots;
|
||||
slots = newslots;
|
||||
|
||||
Debug_SetValueRangeToCrashOnTouch(slots + oldCount, newCount - oldCount);
|
||||
Debug_SetSlotRangeToCrashOnTouch(slots + oldCount, newCount - oldCount);
|
||||
|
||||
/* Changes in the slots of global objects can trigger recompilation. */
|
||||
if (changed && isGlobal())
|
||||
@ -4063,7 +4024,7 @@ JSObject::shrinkSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||
|
||||
JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
HeapValue *newslots = (HeapValue*) cx->realloc_(slots, newCount * sizeof(HeapValue));
|
||||
HeapSlot *newslots = (HeapSlot *) cx->realloc_(slots, newCount * sizeof(HeapSlot));
|
||||
if (!newslots)
|
||||
return; /* Leave slots at its old size. */
|
||||
|
||||
@ -4136,7 +4097,7 @@ JSObject::growElements(JSContext *cx, uintN newcap)
|
||||
newheader->capacity = actualCapacity;
|
||||
elements = newheader->elements();
|
||||
|
||||
Debug_SetValueRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
|
||||
Debug_SetSlotRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
|
||||
|
||||
if (Probes::objectResizeActive())
|
||||
Probes::resizeObject(cx, this, oldSize, computedSizeOfThisSlotsElements());
|
||||
|
@ -434,7 +434,7 @@ struct JSObject : public js::ObjectImpl
|
||||
js::gc::AllocKind kind,
|
||||
js::HandleShape shape,
|
||||
js::HandleTypeObject type,
|
||||
js::HeapValue *slots);
|
||||
js::HeapSlot *slots);
|
||||
|
||||
/* Make a dense array object with the specified initial state. */
|
||||
static inline JSObject *createDenseArray(JSContext *cx,
|
||||
@ -546,9 +546,12 @@ struct JSObject : public js::ObjectImpl
|
||||
* Get internal pointers to the range of values starting at start and
|
||||
* running for length.
|
||||
*/
|
||||
void getSlotRange(size_t start, size_t length,
|
||||
js::HeapValue **fixedStart, js::HeapValue **fixedEnd,
|
||||
js::HeapValue **slotsStart, js::HeapValue **slotsEnd);
|
||||
inline void getSlotRangeUnchecked(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
|
||||
inline void getSlotRange(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
|
||||
public:
|
||||
|
||||
/* Accessors for properties. */
|
||||
@ -560,7 +563,7 @@ struct JSObject : public js::ObjectImpl
|
||||
inline size_t dynamicSlotIndex(size_t slot);
|
||||
|
||||
/* Get a raw pointer to the object's properties. */
|
||||
inline const js::HeapValue *getRawSlots();
|
||||
inline const js::HeapSlot *getRawSlots();
|
||||
|
||||
/*
|
||||
* Grow or shrink slots immediately before changing the slot span.
|
||||
@ -620,14 +623,16 @@ struct JSObject : public js::ObjectImpl
|
||||
bool slotInRange(uintN slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
|
||||
#endif
|
||||
|
||||
js::HeapValue *getSlotAddressUnchecked(uintN slot) {
|
||||
private:
|
||||
js::HeapSlot *getSlotAddressUnchecked(uintN slot) {
|
||||
size_t fixed = numFixedSlots();
|
||||
if (slot < fixed)
|
||||
return fixedSlots() + slot;
|
||||
return slots + (slot - fixed);
|
||||
}
|
||||
|
||||
js::HeapValue *getSlotAddress(uintN slot) {
|
||||
public:
|
||||
js::HeapSlot *getSlotAddress(uintN slot) {
|
||||
/*
|
||||
* This can be used to get the address of the end of the slots for the
|
||||
* object, which may be necessary when fetching zero-length arrays of
|
||||
@ -637,12 +642,12 @@ struct JSObject : public js::ObjectImpl
|
||||
return getSlotAddressUnchecked(slot);
|
||||
}
|
||||
|
||||
js::HeapValue &getSlotRef(uintN slot) {
|
||||
js::HeapSlot &getSlotRef(uintN slot) {
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
return *getSlotAddress(slot);
|
||||
}
|
||||
|
||||
inline js::HeapValue &nativeGetSlotRef(uintN slot);
|
||||
inline js::HeapSlot &nativeGetSlotRef(uintN slot);
|
||||
|
||||
const js::Value &getSlot(uintN slot) const {
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
@ -663,12 +668,13 @@ struct JSObject : public js::ObjectImpl
|
||||
inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
|
||||
|
||||
inline const js::Value &getReservedSlot(uintN index) const;
|
||||
inline js::HeapValue &getReservedSlotRef(uintN index);
|
||||
inline js::HeapSlot &getReservedSlotRef(uintN index);
|
||||
inline void initReservedSlot(uintN index, const js::Value &v);
|
||||
inline void setReservedSlot(uintN index, const js::Value &v);
|
||||
|
||||
/* For slots which are known to always be fixed, due to the way they are allocated. */
|
||||
|
||||
js::HeapValue &getFixedSlotRef(uintN slot) {
|
||||
js::HeapSlot &getFixedSlotRef(uintN slot) {
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
return fixedSlots()[slot];
|
||||
}
|
||||
@ -834,7 +840,7 @@ struct JSObject : public js::ObjectImpl
|
||||
inline void setDenseArrayLength(uint32_t length);
|
||||
inline void setDenseArrayInitializedLength(uint32_t length);
|
||||
inline void ensureDenseArrayInitializedLength(JSContext *cx, uintN index, uintN extra);
|
||||
inline js::HeapValueArray getDenseArrayElements();
|
||||
inline js::HeapSlotArray getDenseArrayElements();
|
||||
inline const js::Value &getDenseArrayElement(uintN idx);
|
||||
inline void setDenseArrayElement(uintN idx, const js::Value &val);
|
||||
inline void initDenseArrayElement(uintN idx, const js::Value &val);
|
||||
|
@ -101,7 +101,7 @@ JSObject::privateRef(uint32_t nfixed) const
|
||||
*/
|
||||
JS_ASSERT(nfixed == numFixedSlots());
|
||||
JS_ASSERT(hasPrivate());
|
||||
js::HeapValue *end = &fixedSlots()[nfixed];
|
||||
js::HeapSlot *end = &fixedSlots()[nfixed];
|
||||
return *reinterpret_cast<void**>(end);
|
||||
}
|
||||
|
||||
@ -406,7 +406,7 @@ JSObject::canRemoveLastProperty()
|
||||
&& previous->getObjectFlags() == lastProperty()->getObjectFlags();
|
||||
}
|
||||
|
||||
inline const js::HeapValue *
|
||||
inline const js::HeapSlot *
|
||||
JSObject::getRawSlots()
|
||||
{
|
||||
JS_ASSERT(isGlobal());
|
||||
@ -420,7 +420,7 @@ JSObject::getReservedSlot(uintN index) const
|
||||
return getSlot(index);
|
||||
}
|
||||
|
||||
inline js::HeapValue &
|
||||
inline js::HeapSlot &
|
||||
JSObject::getReservedSlotRef(uintN index)
|
||||
{
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
@ -434,6 +434,13 @@ JSObject::setReservedSlot(uintN index, const js::Value &v)
|
||||
setSlot(index, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initReservedSlot(uintN index, const js::Value &v)
|
||||
{
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
initSlot(index, v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::hasContiguousSlots(size_t start, size_t count) const
|
||||
{
|
||||
@ -449,7 +456,7 @@ inline void
|
||||
JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end)
|
||||
{
|
||||
for (size_t i = start; i < end; i++)
|
||||
getSlotAddressUnchecked(i)->js::HeapValue::~HeapValue();
|
||||
getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -458,7 +465,7 @@ JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
|
||||
JS_ASSERT(isDenseArray());
|
||||
JS_ASSERT(end <= getDenseArrayInitializedLength());
|
||||
for (size_t i = start; i < end; i++)
|
||||
elements[i].js::HeapValue::~HeapValue();
|
||||
elements[i].js::HeapSlot::~HeapSlot();
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
@ -529,11 +536,11 @@ JSObject::ensureElements(JSContext *cx, uint32_t capacity)
|
||||
return true;
|
||||
}
|
||||
|
||||
inline js::HeapValueArray
|
||||
inline js::HeapSlotArray
|
||||
JSObject::getDenseArrayElements()
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
return js::HeapValueArray(elements);
|
||||
return js::HeapSlotArray(elements);
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
@ -547,14 +554,14 @@ inline void
|
||||
JSObject::setDenseArrayElement(uintN idx, const js::Value &val)
|
||||
{
|
||||
JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
|
||||
elements[idx] = val;
|
||||
elements[idx].set(this, idx, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initDenseArrayElement(uintN idx, const js::Value &val)
|
||||
{
|
||||
JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
|
||||
elements[idx].init(val);
|
||||
elements[idx].init(this, idx, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -577,7 +584,7 @@ JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN cou
|
||||
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
|
||||
JSCompartment *comp = compartment();
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
elements[dstStart + i].set(comp, src[i]);
|
||||
elements[dstStart + i].set(comp, this, dstStart + i, src[i]);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -586,7 +593,7 @@ JSObject::initDenseArrayElements(uintN dstStart, const js::Value *src, uintN cou
|
||||
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
|
||||
JSCompartment *comp = compartment();
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
elements[dstStart + i].init(comp, src[i]);
|
||||
elements[dstStart + i].init(comp, this, dstStart + i, src[i]);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -607,20 +614,21 @@ JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count)
|
||||
* write barrier is invoked here on B, despite the fact that it exists in
|
||||
* the array before and after the move.
|
||||
*/
|
||||
if (compartment()->needsBarrier()) {
|
||||
JSCompartment *comp = compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
if (dstStart < srcStart) {
|
||||
js::HeapValue *dst = elements + dstStart;
|
||||
js::HeapValue *src = elements + srcStart;
|
||||
js::HeapSlot *dst = elements + dstStart;
|
||||
js::HeapSlot *src = elements + srcStart;
|
||||
for (unsigned i = 0; i < count; i++, dst++, src++)
|
||||
*dst = *src;
|
||||
dst->set(comp, this, dst - elements, *src);
|
||||
} else {
|
||||
js::HeapValue *dst = elements + dstStart + count - 1;
|
||||
js::HeapValue *src = elements + srcStart + count - 1;
|
||||
js::HeapSlot *dst = elements + dstStart + count - 1;
|
||||
js::HeapSlot *src = elements + srcStart + count - 1;
|
||||
for (unsigned i = 0; i < count; i++, dst--, src--)
|
||||
*dst = *src;
|
||||
dst->set(comp, this, dst - elements, *src);
|
||||
}
|
||||
} else {
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
|
||||
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
|
||||
}
|
||||
}
|
||||
|
||||
@ -970,6 +978,42 @@ JSObject::isQName() const
|
||||
|| hasClass(&js::AnyNameClass);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::getSlotRangeUnchecked(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(!isDenseArray());
|
||||
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + length];
|
||||
*slotsStart = *slotsEnd = NULL;
|
||||
} else {
|
||||
size_t localCopy = fixed - start;
|
||||
*fixedStart = &fixedSlots()[start];
|
||||
*fixedEnd = &fixedSlots()[start + localCopy];
|
||||
*slotsStart = &slots[0];
|
||||
*slotsEnd = &slots[length - localCopy];
|
||||
}
|
||||
} else {
|
||||
*fixedStart = *fixedEnd = NULL;
|
||||
*slotsStart = &slots[start - fixed];
|
||||
*slotsEnd = &slots[start - fixed + length];
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::getSlotRange(size_t start, size_t length,
|
||||
js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
|
||||
js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd)
|
||||
{
|
||||
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
|
||||
getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initializeSlotRange(size_t start, size_t length)
|
||||
{
|
||||
@ -977,24 +1021,20 @@ JSObject::initializeSlotRange(size_t start, size_t length)
|
||||
* No bounds check, as this is used when the object's shape does not
|
||||
* reflect its allocated slots (updateSlotsForSpan).
|
||||
*/
|
||||
JS_ASSERT(!isDenseArray());
|
||||
size_t fixed = numFixedSlots();
|
||||
if (start < fixed) {
|
||||
if (start + length < fixed) {
|
||||
js::InitValueRange(fixedSlots() + start, length, false);
|
||||
} else {
|
||||
size_t localClear = fixed - start;
|
||||
js::InitValueRange(fixedSlots() + start, localClear, false);
|
||||
js::InitValueRange(slots, length - localClear, false);
|
||||
}
|
||||
} else {
|
||||
js::InitValueRange(slots + start - fixed, length, false);
|
||||
}
|
||||
js::HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
|
||||
getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
|
||||
|
||||
JSCompartment *comp = compartment();
|
||||
size_t offset = start;
|
||||
for (js::HeapSlot *sp = fixedStart; sp != fixedEnd; sp++)
|
||||
sp->init(comp, this, offset++, js::UndefinedValue());
|
||||
for (js::HeapSlot *sp = slotsStart; sp != slotsEnd; sp++)
|
||||
sp->init(comp, this, offset++, js::UndefinedValue());
|
||||
}
|
||||
|
||||
/* static */ inline JSObject *
|
||||
JSObject::create(JSContext *cx, js::gc::AllocKind kind,
|
||||
js::HandleShape shape, js::HandleTypeObject type, js::HeapValue *slots)
|
||||
js::HandleShape shape, js::HandleTypeObject type, js::HeapSlot *slots)
|
||||
{
|
||||
/*
|
||||
* Callers must use dynamicSlotsCount to size the initial slot array of the
|
||||
@ -1102,7 +1142,7 @@ JSObject::slotSpan() const
|
||||
return lastProperty()->slotSpan();
|
||||
}
|
||||
|
||||
inline js::HeapValue &
|
||||
inline js::HeapSlot &
|
||||
JSObject::nativeGetSlotRef(uintN slot)
|
||||
{
|
||||
JS_ASSERT(isNative());
|
||||
@ -1344,7 +1384,7 @@ inline JSBool
|
||||
JSObject::getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp)
|
||||
{
|
||||
js::GenericAttributesOp op = getOps()->getGenericAttributes;
|
||||
return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
|
||||
return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
@ -1813,13 +1853,13 @@ NewObjectGCKind(JSContext *cx, js::Class *clasp)
|
||||
* may or may not need dynamic slots.
|
||||
*/
|
||||
inline bool
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapValue **slots)
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapSlot **slots)
|
||||
{
|
||||
if (size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
|
||||
*slots = (HeapValue *) cx->malloc_(count * sizeof(HeapValue));
|
||||
*slots = (HeapSlot *) cx->malloc_(count * sizeof(HeapSlot));
|
||||
if (!*slots)
|
||||
return false;
|
||||
Debug_SetValueRangeToCrashOnTouch(*slots, count);
|
||||
Debug_SetSlotRangeToCrashOnTouch(*slots, count);
|
||||
return true;
|
||||
}
|
||||
*slots = NULL;
|
||||
@ -1969,7 +2009,7 @@ inline void
|
||||
JSObject::setSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slotInRange(slot));
|
||||
getSlotRef(slot).set(compartment(), value);
|
||||
getSlotRef(slot).set(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -1983,21 +2023,21 @@ JSObject::initSlot(uintN slot, const js::Value &value)
|
||||
inline void
|
||||
JSObject::initSlotUnchecked(uintN slot, const js::Value &value)
|
||||
{
|
||||
getSlotAddressUnchecked(slot)->init(value);
|
||||
getSlotAddressUnchecked(slot)->init(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setFixedSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
fixedSlots()[slot] = value;
|
||||
fixedSlots()[slot].set(this, slot, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initFixedSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
JS_ASSERT(slot < numFixedSlots());
|
||||
fixedSlots()[slot].init(value);
|
||||
fixedSlots()[slot].init(this, slot, value);
|
||||
}
|
||||
|
||||
#endif /* jsobjinlines_h___ */
|
||||
|
@ -59,7 +59,7 @@
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
static inline HeapValue &
|
||||
static inline HeapSlot &
|
||||
GetCall(JSObject *proxy)
|
||||
{
|
||||
JS_ASSERT(IsFunctionProxy(proxy));
|
||||
@ -74,7 +74,7 @@ GetConstruct(JSObject *proxy)
|
||||
return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT);
|
||||
}
|
||||
|
||||
static inline HeapValue &
|
||||
static inline HeapSlot &
|
||||
GetFunctionProxyConstruct(JSObject *proxy)
|
||||
{
|
||||
JS_ASSERT(IsFunctionProxy(proxy));
|
||||
@ -1248,12 +1248,12 @@ static void
|
||||
proxy_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
GetProxyHandler(obj)->trace(trc, obj);
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private");
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0");
|
||||
MarkCrossCompartmentValue(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0");
|
||||
MarkCrossCompartmentSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1");
|
||||
if (IsFunctionProxy(obj)) {
|
||||
MarkCrossCompartmentValue(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1261,8 +1261,8 @@ static void
|
||||
proxy_TraceFunction(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
proxy_TraceObject(trc, obj);
|
||||
MarkCrossCompartmentValue(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentValue(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
|
||||
MarkCrossCompartmentSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1099,7 +1099,7 @@ class TypedArrayTemplate
|
||||
static void
|
||||
obj_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
MarkValue(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer");
|
||||
MarkSlot(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer");
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -363,7 +363,7 @@ Wrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp)
|
||||
void
|
||||
Wrapper::trace(JSTracer *trc, JSObject *wrapper)
|
||||
{
|
||||
MarkValue(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject");
|
||||
MarkSlot(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject");
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@ -871,8 +871,8 @@ CrossCompartmentWrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *v
|
||||
void
|
||||
CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper)
|
||||
{
|
||||
MarkCrossCompartmentValue(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE),
|
||||
"wrappedObject");
|
||||
MarkCrossCompartmentSlot(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE),
|
||||
"wrappedObject");
|
||||
}
|
||||
|
||||
CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u);
|
||||
|
@ -7538,7 +7538,7 @@ namespace js {
|
||||
bool
|
||||
GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp)
|
||||
{
|
||||
HeapValue &v = getSlotRef(FUNCTION_NS);
|
||||
HeapSlot &v = getSlotRef(FUNCTION_NS);
|
||||
if (v.isUndefined()) {
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JSLinearString *prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION];
|
||||
@ -7557,7 +7557,7 @@ GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp)
|
||||
if (!obj->clearType(cx))
|
||||
return false;
|
||||
|
||||
v.set(compartment(), ObjectValue(*obj));
|
||||
v.set(this, FUNCTION_NS, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
*vp = v;
|
||||
|
@ -6395,7 +6395,7 @@ mjit::Compiler::jsop_getgname(uint32_t index)
|
||||
*/
|
||||
const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(name));
|
||||
if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
|
||||
HeapValue *value = &globalObj->getSlotRef(shape->slot());
|
||||
HeapSlot *value = &globalObj->getSlotRef(shape->slot());
|
||||
if (!value->isUndefined() &&
|
||||
!propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
|
||||
watchGlobalReallocation();
|
||||
@ -6521,7 +6521,7 @@ mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
|
||||
shape->writable() && shape->hasSlot() &&
|
||||
!types->isOwnProperty(cx, globalObj->getType(cx), true)) {
|
||||
watchGlobalReallocation();
|
||||
HeapValue *value = &globalObj->getSlotRef(shape->slot());
|
||||
HeapSlot *value = &globalObj->getSlotRef(shape->slot());
|
||||
RegisterID reg = frame.allocReg();
|
||||
#ifdef JSGC_INCREMENTAL_MJ
|
||||
/* Write barrier. */
|
||||
|
@ -404,7 +404,7 @@ class Compiler : public BaseCompiler
|
||||
analyze::CrossScriptSSA ssa;
|
||||
|
||||
GlobalObject *globalObj;
|
||||
const HeapValue *globalSlots; /* Original slots pointer. */
|
||||
const HeapSlot *globalSlots; /* Original slots pointer. */
|
||||
|
||||
Assembler masm;
|
||||
FrameState frame;
|
||||
|
@ -58,15 +58,12 @@ GlobalObject::initFlags(int32_t flags)
|
||||
inline void
|
||||
GlobalObject::setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto)
|
||||
{
|
||||
HeapValue &ctorVal = getSlotRef(key);
|
||||
HeapValue &protoVal = getSlotRef(JSProto_LIMIT + key);
|
||||
HeapValue &visibleVal = getSlotRef(2 * JSProto_LIMIT + key);
|
||||
JS_ASSERT(ctorVal.isUndefined());
|
||||
JS_ASSERT(protoVal.isUndefined());
|
||||
JS_ASSERT(visibleVal.isUndefined());
|
||||
ctorVal = ObjectValue(*ctor);
|
||||
protoVal = ObjectValue(*proto);
|
||||
visibleVal = ctorVal;
|
||||
JS_ASSERT(getSlotRef(key).isUndefined());
|
||||
JS_ASSERT(getSlotRef(JSProto_LIMIT + key).isUndefined());
|
||||
JS_ASSERT(getSlotRef(2 * JSProto_LIMIT + key).isUndefined());
|
||||
setSlot(key, ObjectValue(*ctor));
|
||||
setSlot(JSProto_LIMIT + key, ObjectValue(*proto));
|
||||
setSlot(2 * JSProto_LIMIT + key, ObjectValue(*ctor));
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -84,17 +81,15 @@ GlobalObject::setFunctionClassDetails(JSFunction *ctor, JSObject *proto)
|
||||
void
|
||||
GlobalObject::setThrowTypeError(JSFunction *fun)
|
||||
{
|
||||
HeapValue &v = getSlotRef(THROWTYPEERROR);
|
||||
JS_ASSERT(v.isUndefined());
|
||||
v = ObjectValue(*fun);
|
||||
JS_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
|
||||
setSlot(THROWTYPEERROR, ObjectValue(*fun));
|
||||
}
|
||||
|
||||
void
|
||||
GlobalObject::setOriginalEval(JSObject *evalobj)
|
||||
{
|
||||
HeapValue &v = getSlotRef(EVAL);
|
||||
JS_ASSERT(v.isUndefined());
|
||||
v = ObjectValue(*evalobj);
|
||||
JS_ASSERT(getSlotRef(EVAL).isUndefined());
|
||||
setSlot(EVAL, ObjectValue(*evalobj));
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
@ -384,7 +384,7 @@ GlobalObject::clear(JSContext *cx)
|
||||
bool
|
||||
GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
|
||||
{
|
||||
HeapValue &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
|
||||
HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
|
||||
if (v.isUndefined()) {
|
||||
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
|
||||
|
||||
@ -392,7 +392,7 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
|
||||
* If there are callbacks, make sure that the CSP callback is installed
|
||||
* and that it permits runtime code generation, then cache the result.
|
||||
*/
|
||||
v.set(compartment(),
|
||||
v.set(this, RUNTIME_CODEGEN_ENABLED,
|
||||
BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
|
||||
callbacks->contentSecurityPolicyAllows(cx)));
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ using namespace js;
|
||||
static ObjectElements emptyElementsHeader(0, 0);
|
||||
|
||||
/* Objects with no elements share one empty set of elements. */
|
||||
HeapValue *js::emptyObjectElements =
|
||||
reinterpret_cast<HeapValue *>(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements));
|
||||
HeapSlot *js::emptyObjectElements =
|
||||
reinterpret_cast<HeapSlot *>(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements));
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
/*
|
||||
|
@ -57,8 +57,8 @@ class ObjectElements
|
||||
: capacity(capacity), initializedLength(0), length(length)
|
||||
{}
|
||||
|
||||
HeapValue * elements() { return (HeapValue *)(uintptr_t(this) + sizeof(ObjectElements)); }
|
||||
static ObjectElements * fromElements(HeapValue *elems) {
|
||||
HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); }
|
||||
static ObjectElements * fromElements(HeapSlot *elems) {
|
||||
return (ObjectElements *)(uintptr_t(elems) - sizeof(ObjectElements));
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ class ObjectElements
|
||||
};
|
||||
|
||||
/* Shared singleton for objects with no elements. */
|
||||
extern HeapValue *emptyObjectElements;
|
||||
extern HeapSlot *emptyObjectElements;
|
||||
|
||||
struct Class;
|
||||
struct GCMarker;
|
||||
@ -149,8 +149,8 @@ class ObjectImpl : public gc::Cell
|
||||
*/
|
||||
HeapPtrTypeObject type_;
|
||||
|
||||
HeapValue *slots; /* Slots for object properties. */
|
||||
HeapValue *elements; /* Slots for object elements. */
|
||||
HeapSlot *slots; /* Slots for object properties. */
|
||||
HeapSlot *elements; /* Slots for object elements. */
|
||||
|
||||
private:
|
||||
static void staticAsserts() {
|
||||
@ -179,8 +179,8 @@ class ObjectImpl : public gc::Cell
|
||||
/* Minimum size for dynamically allocated slots. */
|
||||
static const uint32_t SLOT_CAPACITY_MIN = 8;
|
||||
|
||||
HeapValue * fixedSlots() const {
|
||||
return reinterpret_cast<HeapValue *>(uintptr_t(this) + sizeof(ObjectImpl));
|
||||
HeapSlot *fixedSlots() const {
|
||||
return reinterpret_cast<HeapSlot *>(uintptr_t(this) + sizeof(ObjectImpl));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -259,7 +259,7 @@ class ObjectImpl : public gc::Cell
|
||||
return ObjectElements::fromElements(elements);
|
||||
}
|
||||
|
||||
inline HeapValue * fixedElements() const {
|
||||
inline HeapSlot *fixedElements() const {
|
||||
MOZ_STATIC_ASSERT(2 * sizeof(Value) == sizeof(ObjectElements),
|
||||
"when elements are stored inline, the first two "
|
||||
"slots will hold the ObjectElements header");
|
||||
|
@ -184,21 +184,21 @@ CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
|
||||
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
|
||||
}
|
||||
|
||||
inline HeapValueArray
|
||||
inline HeapSlotArray
|
||||
CallObject::argArray()
|
||||
{
|
||||
DebugOnly<JSFunction*> fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS, fun->nargs));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS));
|
||||
return HeapSlotArray(getSlotAddress(RESERVED_SLOTS));
|
||||
}
|
||||
|
||||
inline HeapValueArray
|
||||
inline HeapSlotArray
|
||||
CallObject::varArray()
|
||||
{
|
||||
JSFunction *fun = getCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(RESERVED_SLOTS + fun->nargs,
|
||||
fun->script()->bindings.countVars()));
|
||||
return HeapValueArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
|
||||
return HeapSlotArray(getSlotAddress(RESERVED_SLOTS + fun->nargs));
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
@ -225,7 +225,7 @@ BlockObject::slotCount() const
|
||||
return propertyCount();
|
||||
}
|
||||
|
||||
inline HeapValue &
|
||||
inline HeapSlot &
|
||||
BlockObject::slotValue(unsigned i)
|
||||
{
|
||||
return getSlotRef(RESERVED_SLOTS + i);
|
||||
@ -248,14 +248,14 @@ inline void
|
||||
StaticBlockObject::setStackDepth(uint32_t depth)
|
||||
{
|
||||
JS_ASSERT(getReservedSlot(DEPTH_SLOT).isUndefined());
|
||||
getReservedSlotRef(DEPTH_SLOT).init(PrivateUint32Value(depth));
|
||||
initReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
|
||||
}
|
||||
|
||||
inline void
|
||||
StaticBlockObject::setDefinitionParseNode(unsigned i, Definition *def)
|
||||
{
|
||||
JS_ASSERT(slotValue(i).isUndefined());
|
||||
slotValue(i).init(PrivateValue(def));
|
||||
slotValue(i).init(this, i, PrivateValue(def));
|
||||
}
|
||||
|
||||
inline Definition *
|
||||
@ -268,7 +268,7 @@ StaticBlockObject::maybeDefinitionParseNode(unsigned i)
|
||||
inline void
|
||||
StaticBlockObject::poisonDefinitionParseNode(unsigned i)
|
||||
{
|
||||
slotValue(i).init(PrivateValue(NULL));
|
||||
slotValue(i).init(this, i, PrivateValue(NULL));
|
||||
}
|
||||
|
||||
inline StaticBlockObject &
|
||||
|
@ -78,7 +78,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &enclosing, JSObjec
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
HeapSlot *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
|
||||
return NULL;
|
||||
|
||||
@ -433,7 +433,7 @@ ClonedBlockObject::create(JSContext *cx, StaticBlockObject &block, StackFrame *f
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
HeapValue *slots;
|
||||
HeapSlot *slots;
|
||||
if (!PreallocateObjectDynamicSlots(cx, block.lastProperty(), &slots))
|
||||
return NULL;
|
||||
|
||||
|
@ -152,8 +152,8 @@ class CallObject : public ScopeObject
|
||||
* inference is enabled, where we ensure that call object variables are in
|
||||
* contiguous slots (see NewCallObject).
|
||||
*/
|
||||
inline js::HeapValueArray argArray();
|
||||
inline js::HeapValueArray varArray();
|
||||
inline js::HeapSlotArray argArray();
|
||||
inline js::HeapSlotArray varArray();
|
||||
|
||||
inline void copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots);
|
||||
};
|
||||
@ -210,7 +210,7 @@ class BlockObject : public NestedScopeObject
|
||||
|
||||
protected:
|
||||
/* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */
|
||||
inline HeapValue &slotValue(unsigned i);
|
||||
inline HeapSlot &slotValue(unsigned i);
|
||||
};
|
||||
|
||||
class StaticBlockObject : public BlockObject
|
||||
|
Loading…
Reference in New Issue
Block a user