mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-30 01:59:29 +00:00
Bug 889682 - Eagerly check for remembered set membership before buffering; r=billm
--HG-- extra : rebase_source : 83da73e4ee40f2185b63b214b6710b9146109ff1
This commit is contained in:
parent
a9f166c137
commit
38af4d4234
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user