Bug 711626 - More missing barriers around object properties; r=billm

This adds post barriers in several locations where they are needed inside of
object manipulation.

--HG--
extra : rebase_source : ce956417a74d70551c1f9258ef7587d0563c0157
This commit is contained in:
Terrence Cole 2011-12-28 14:06:21 -08:00
parent 2e8557928f
commit 44161208ba
7 changed files with 73 additions and 22 deletions

View File

@ -104,6 +104,13 @@ HeapValue::init(const Value &v)
post();
}
inline void
HeapValue::init(JSCompartment *comp, const Value &v)
{
value = v;
post(comp);
}
inline void
HeapValue::writeBarrierPre(const Value &value)
{

View File

@ -302,6 +302,7 @@ class HeapValue
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);

View File

@ -1735,7 +1735,7 @@ JSFunction::initBoundFunction(JSContext *cx, const Value &thisArg,
setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg);
setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen));
copySlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen, false);
initSlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen);
return true;
}

View File

@ -3620,7 +3620,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
if (normalUnwind) {
uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT;
depth += fp->numFixed();
obj->copySlotRange(slot, fp->slots() + depth, count, true);
obj->copySlotRange(slot, fp->slots() + depth, count);
}
/* We must clear the private slot even with errors. */
@ -4037,7 +4037,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
a->shape_ = reserved.newashape;
a->slots = reserved.newaslots;
a->copySlotRange(0, reserved.bvals.begin(), bcap, false);
a->initSlotRange(0, reserved.bvals.begin(), bcap);
if (a->hasPrivate())
a->setPrivate(bpriv);
@ -4047,7 +4047,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
b->shape_ = reserved.newbshape;
b->slots = reserved.newbslots;
b->copySlotRange(0, reserved.avals.begin(), acap, false);
b->initSlotRange(0, reserved.avals.begin(), acap);
if (b->hasPrivate())
b->setPrivate(apriv);
@ -4524,27 +4524,57 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
}
void
JSObject::copySlotRange(size_t start, const Value *vector, size_t length, bool valid)
JSObject::getSlotRange(size_t start, size_t length,
HeapValue **fixedStart, HeapValue **fixedEnd,
HeapValue **slotsStart, HeapValue **slotsEnd)
{
if (valid)
prepareSlotRangeForOverwrite(start, start + length);
JS_ASSERT(!isDenseArray());
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
size_t fixed = numFixedSlots();
if (start < fixed) {
if (start + length < fixed) {
memcpy(fixedSlots() + start, vector, length * sizeof(Value));
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + length];
*slotsStart = *slotsEnd = NULL;
} else {
size_t localCopy = fixed - start;
memcpy(fixedSlots() + start, vector, localCopy * sizeof(Value));
memcpy(slots, vector + localCopy, (length - localCopy) * sizeof(Value));
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + localCopy];
*slotsStart = &slots[0];
*slotsEnd = &slots[length - localCopy];
}
} else {
memcpy(slots + start - fixed, vector, length * sizeof(Value));
*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;
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++);
}
void
JSObject::copySlotRange(size_t start, const Value *vector, size_t length)
{
JSCompartment *comp = compartment();
HeapValue *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++);
}
inline void
JSObject::invalidateSlotRange(size_t start, size_t length)
{

View File

@ -639,6 +639,14 @@ struct JSObject : js::gc::Cell
private:
inline js::HeapValue* fixedSlots() const;
/*
* 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);
public:
/* Accessors for properties. */
@ -690,7 +698,6 @@ struct JSObject : js::gc::Cell
inline bool updateSlotsForSpan(JSContext *cx, size_t oldSpan, size_t newSpan);
public:
/*
* Trigger the write barrier on a range of slots that will no longer be
* reachable.
@ -699,12 +706,16 @@ struct JSObject : js::gc::Cell
inline void prepareElementRangeForOverwrite(size_t start, size_t end);
/*
* Copy a flat array of slots to this object at a start slot. Caller must
* ensure there are enough slots in this object. If |valid|, then the slots
* being overwritten hold valid data and must be invalidated for the write
* barrier.
* Initialize a flat array of slots to this object at a start slot. The
* caller must ensure that are enough slots.
*/
void copySlotRange(size_t start, const js::Value *vector, size_t length, bool valid);
void initSlotRange(size_t start, const js::Value *vector, size_t length);
/*
* Copy a flat array of slots to this object at a start slot. Caller must
* ensure there are enough slots in this object.
*/
void copySlotRange(size_t start, const js::Value *vector, size_t length);
inline uint32_t slotSpan() const;

View File

@ -634,16 +634,18 @@ inline void
JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count)
{
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
JSCompartment *comp = compartment();
for (unsigned i = 0; i < count; ++i)
elements[dstStart + i] = src[i];
elements[dstStart + i].set(comp, src[i]);
}
inline void
JSObject::initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count)
{
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
JSCompartment *comp = compartment();
for (unsigned i = 0; i < count; ++i)
elements[dstStart + i].init(src[i]);
elements[dstStart + i].init(comp, src[i]);
}
inline void

View File

@ -165,8 +165,8 @@ inline void
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
{
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
copySlotRange(RESERVED_SLOTS, argv, nargs, true);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars, true);
copySlotRange(RESERVED_SLOTS, argv, nargs);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
}
inline js::HeapValueArray