Bug 889682 - Eagerly check for remembered set membership before buffering; r=billm

--HG--
extra : rebase_source : 83da73e4ee40f2185b63b214b6710b9146109ff1
This commit is contained in:
Terrence Cole 2013-07-10 10:13:46 -07:00
parent a9f166c137
commit 38af4d4234
6 changed files with 60 additions and 59 deletions

View File

@ -309,7 +309,7 @@ HeapSlot::HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
: EncapsulatedValue(v)
{
JS_ASSERT(!IsPoisonedValue(v));
post(obj, kind, slot);
post(obj, kind, slot, v);
}
inline
@ -317,7 +317,7 @@ HeapSlot::HeapSlot(JSObject *obj, Kind kind, uint32_t slot, const HeapSlot &s)
: EncapsulatedValue(s.value)
{
JS_ASSERT(!IsPoisonedValue(s.value));
post(obj, kind, slot);
post(obj, kind, slot, s);
}
inline
@ -330,14 +330,14 @@ inline void
HeapSlot::init(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
{
value = v;
post(obj, kind, slot);
post(obj, kind, slot, v);
}
inline void
HeapSlot::init(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot, const Value &v)
{
value = v;
post(rt, obj, kind, slot);
post(rt, obj, kind, slot, v);
}
inline void
@ -349,7 +349,7 @@ HeapSlot::set(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
pre();
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(obj, kind, slot);
post(obj, kind, slot, v);
}
inline void
@ -362,35 +362,40 @@ HeapSlot::set(Zone *zone, JSObject *obj, Kind kind, uint32_t slot, const Value &
pre(zone);
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(zone->rt, obj, kind, slot);
post(zone->rt, obj, kind, slot, v);
}
inline void
HeapSlot::writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot)
HeapSlot::writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target)
{
#ifdef JSGC_GENERATIONAL
obj->runtime()->gcStoreBuffer.putSlot(obj, kind, slot);
writeBarrierPost(obj->runtime(), obj, kind, slot, target);
#endif
}
inline void
HeapSlot::writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot)
HeapSlot::writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot, Value target)
{
#ifdef JSGC_GENERATIONAL
rt->gcStoreBuffer.putSlot(obj, kind, slot);
JS_ASSERT_IF(kind == Slot, obj->getSlotAddressUnchecked(slot)->get() == target);
JS_ASSERT_IF(kind == Element,
static_cast<HeapSlot *>(obj->getDenseElements() + slot)->get() == target);
if (target.isObject())
rt->gcStoreBuffer.putSlot(obj, kind, slot, &target.toObject());
#endif
}
inline void
HeapSlot::post(JSObject *owner, Kind kind, uint32_t slot)
HeapSlot::post(JSObject *owner, Kind kind, uint32_t slot, Value target)
{
HeapSlot::writeBarrierPost(owner, kind, slot);
HeapSlot::writeBarrierPost(owner, kind, slot, target);
}
inline void
HeapSlot::post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot)
HeapSlot::post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target)
{
HeapSlot::writeBarrierPost(rt, owner, kind, slot);
HeapSlot::writeBarrierPost(rt, owner, kind, slot, target);
}
#ifdef JSGC_GENERATIONAL

View File

@ -502,12 +502,13 @@ class HeapSlot : public EncapsulatedValue
inline void set(JSObject *owner, Kind kind, uint32_t slot, const Value &v);
inline void set(Zone *zone, JSObject *owner, Kind kind, uint32_t slot, const Value &v);
static inline void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot);
static inline void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot);
static inline void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot, Value target);
static inline void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot,
Value target);
private:
inline void post(JSObject *owner, Kind kind, uint32_t slot);
inline void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot);
inline void post(JSObject *owner, Kind kind, uint32_t slot, Value target);
inline void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, Value target);
};
/*

View File

@ -118,12 +118,13 @@ static inline void
CheckMarkedThing(JSTracer *trc, T *thing)
{
#ifdef DEBUG
JS_ASSERT(trc);
JS_ASSERT(thing);
/* This function uses data that's not available in the nursery. */
if (IsInsideNursery(trc->runtime, thing))
return;
JS_ASSERT(trc);
JS_ASSERT(thing);
JS_ASSERT(thing->zone());
JS_ASSERT(thing->zone()->rt == trc->runtime);
JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);

View File

@ -106,18 +106,6 @@ StoreBuffer::MonoTypeBuffer<T>::clear()
pos = base;
}
template <typename T>
void
StoreBuffer::MonoTypeBuffer<T>::compactNotInSet(const Nursery &nursery)
{
T *insert = base;
for (T *v = base; v != pos; ++v) {
if (v->inRememberedSet(nursery))
*insert++ = *v;
}
pos = insert;
}
template <typename T>
void
StoreBuffer::MonoTypeBuffer<T>::compactRemoveDuplicates()
@ -140,7 +128,6 @@ template <typename T>
void
StoreBuffer::MonoTypeBuffer<T>::compact()
{
compactNotInSet(owner->runtime->gcNursery);
compactRemoveDuplicates();
}
@ -192,14 +179,14 @@ StoreBuffer::RelocatableMonoTypeBuffer<T>::compactMoved()
for (T *r = this->base; r != v; ++r) {
T check = r->untagged();
if (check == match)
*r = NULL;
*r = T(NULL);
}
*v = NULL;
*v = T(NULL);
}
}
T *insert = this->base;
for (T *cursor = this->base; cursor != this->pos; ++cursor) {
if (*cursor != NULL)
if (*cursor != T(NULL))
*insert++ = *cursor;
}
this->pos = insert;

View File

@ -103,7 +103,7 @@ class StoreBuffer
mozilla::DebugOnly<bool> entered;
MonoTypeBuffer(StoreBuffer *owner)
explicit MonoTypeBuffer(StoreBuffer *owner)
: owner(owner), base(NULL), pos(NULL), top(NULL), entered(false)
{
duplicates.init();
@ -120,7 +120,6 @@ class StoreBuffer
bool isAboutToOverflow() const { return pos >= highwater; }
/* Compaction algorithms. */
void compactNotInSet(const Nursery &nursery);
void compactRemoveDuplicates();
/*
@ -145,9 +144,10 @@ class StoreBuffer
*/
*pos++ = v;
if (isAboutToOverflow()) {
owner->setAboutToOverflow();
compact();
if (isAboutToOverflow())
owner->setAboutToOverflow();
if (isFull()) {
compact();
if (isFull()) {
owner->setOverflowed();
clear();
@ -169,7 +169,7 @@ class StoreBuffer
{
friend class StoreBuffer;
RelocatableMonoTypeBuffer(StoreBuffer *owner)
explicit RelocatableMonoTypeBuffer(StoreBuffer *owner)
: MonoTypeBuffer<T>(owner)
{}
@ -197,7 +197,7 @@ class StoreBuffer
mozilla::DebugOnly<bool> entered;
GenericBuffer(StoreBuffer *owner)
explicit GenericBuffer(StoreBuffer *owner)
: owner(owner), base(NULL), pos(NULL), top(NULL), entered(false)
{}
@ -245,7 +245,7 @@ class StoreBuffer
Cell **edge;
CellPtrEdge(Cell **v) : edge(v) {}
explicit CellPtrEdge(Cell **v) : edge(v) {}
bool operator==(const CellPtrEdge &other) const { return edge == other.edge; }
bool operator!=(const CellPtrEdge &other) const { return edge != other.edge; }
@ -274,7 +274,7 @@ class StoreBuffer
Value *edge;
ValueEdge(Value *v) : edge(v) {}
explicit ValueEdge(Value *v) : edge(v) {}
bool operator==(const ValueEdge &other) const { return edge == other.edge; }
bool operator!=(const ValueEdge &other) const { return edge != other.edge; }
@ -320,11 +320,8 @@ class StoreBuffer
JS_ALWAYS_INLINE HeapSlot *slotLocation() const;
JS_ALWAYS_INLINE void *deref() const;
JS_ALWAYS_INLINE void *location() const;
JS_ALWAYS_INLINE bool inRememberedSet(const Nursery &nursery) const;
JS_ALWAYS_INLINE bool isNullEdge() const;
void mark(JSTracer *trc);
@ -420,14 +417,24 @@ class StoreBuffer
bool hasOverflowed() const { return overflowed; }
/* Insert a single edge into the buffer/remembered set. */
void putValue(Value *v) {
bufferVal.put(v);
void putValue(Value *valuep) {
ValueEdge edge(valuep);
if (!edge.inRememberedSet(nursery_))
return;
bufferVal.put(edge);
}
void putCell(Cell **o) {
bufferCell.put(o);
void putCell(Cell **cellp) {
CellPtrEdge edge(cellp);
if (!edge.inRememberedSet(nursery_))
return;
bufferCell.put(edge);
}
void putSlot(JSObject *obj, HeapSlot::Kind kind, uint32_t slot) {
bufferSlot.put(SlotEdge(obj, kind, slot));
void putSlot(JSObject *obj, HeapSlot::Kind kind, uint32_t slot, void *target) {
SlotEdge edge(obj, kind, slot);
/* This is manually inlined because slotLocation cannot be defined here. */
if (nursery_.isInside(obj) || !nursery_.isInside(target))
return;
bufferSlot.put(edge);
}
void putWholeCell(Cell *cell) {
bufferWholeCell.put(WholeCellEdges(cell));
@ -435,16 +442,16 @@ class StoreBuffer
/* Insert or update a single edge in the Relocatable buffer. */
void putRelocatableValue(Value *v) {
bufferRelocVal.put(v);
bufferRelocVal.put(ValueEdge(v));
}
void putRelocatableCell(Cell **c) {
bufferRelocCell.put(c);
bufferRelocCell.put(CellPtrEdge(c));
}
void removeRelocatableValue(Value *v) {
bufferRelocVal.unput(v);
bufferRelocVal.unput(ValueEdge(v));
}
void removeRelocatableCell(Cell **c) {
bufferRelocCell.unput(c);
bufferRelocCell.unput(CellPtrEdge(c));
}
/* Insert an entry into the generic buffer. */

View File

@ -2086,8 +2086,8 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
* below, in common with the other case.
*/
for (size_t i = 0; i < a->numFixedSlots(); ++i) {
HeapSlot::writeBarrierPost(cx->runtime(), a, HeapSlot::Slot, i);
HeapSlot::writeBarrierPost(cx->runtime(), b, HeapSlot::Slot, i);
HeapSlot::writeBarrierPost(cx->runtime(), a, HeapSlot::Slot, i, a->getSlot(i));
HeapSlot::writeBarrierPost(cx->runtime(), b, HeapSlot::Slot, i, b->getSlot(i));
}
#endif
} else {