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:
Terrence Cole 2012-02-17 18:43:48 -08:00
parent 6c2b16a1a1
commit 7e0032bea8
24 changed files with 486 additions and 329 deletions

View File

@ -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)

View File

@ -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

View File

@ -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. */

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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___ */

View File

@ -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());

View File

@ -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);

View File

@ -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___ */

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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;

View File

@ -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

View File

@ -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)));
}

View File

@ -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
/*

View File

@ -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");

View File

@ -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 &

View File

@ -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;

View File

@ -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