Bug 706885 - Move post barrier verifier to JSRuntime; r=billm

--HG--
extra : rebase_source : 0ecc660996501fb54573cc0081a12bbca838e45d
This commit is contained in:
Terrence Cole 2013-01-28 15:59:02 -08:00
parent b18a8e9f53
commit 3dd5723697
25 changed files with 164 additions and 215 deletions

View File

@ -29,16 +29,16 @@ RelocatablePtr<T>::post()
{
#ifdef JSGC_GENERATIONAL
JS_ASSERT(this->value);
this->value->zone()->gcStoreBuffer.putRelocatableCell((gc::Cell **)&this->value);
this->value->runtime()->gcStoreBuffer.putRelocatableCell((gc::Cell **)&this->value);
#endif
}
template <typename T>
inline void
RelocatablePtr<T>::relocate(Zone *zone)
RelocatablePtr<T>::relocate(JSRuntime *rt)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.removeRelocatableCell((gc::Cell **)&this->value);
rt->gcStoreBuffer.removeRelocatableCell((gc::Cell **)&this->value);
#endif
}
@ -115,11 +115,11 @@ HeapValue::init(const Value &v)
}
inline void
HeapValue::init(Zone *zone, const Value &v)
HeapValue::init(JSRuntime *rt, const Value &v)
{
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(zone);
post(rt);
}
inline HeapValue &
@ -156,26 +156,24 @@ HeapValue::set(Zone *zone, const Value &v)
pre(zone);
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(zone);
post(zone->rt);
}
inline void
HeapValue::writeBarrierPost(const Value &value, Value *addr)
{
#ifdef JSGC_GENERATIONAL
if (value.isMarkable()) {
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
cell->zone()->gcStoreBuffer.putValue(addr);
}
if (value.isMarkable())
runtime(value)->gcStoreBuffer.putValue(addr);
#endif
}
inline void
HeapValue::writeBarrierPost(Zone *zone, const Value &value, Value *addr)
HeapValue::writeBarrierPost(JSRuntime *rt, const Value &value, Value *addr)
{
#ifdef JSGC_GENERATIONAL
if (value.isMarkable())
zone->gcStoreBuffer.putValue(addr);
rt->gcStoreBuffer.putValue(addr);
#endif
}
@ -186,9 +184,9 @@ HeapValue::post()
}
inline void
HeapValue::post(Zone *zone)
HeapValue::post(JSRuntime *rt)
{
writeBarrierPost(zone, value, &value);
writeBarrierPost(rt, value, &value);
}
inline
@ -244,19 +242,17 @@ inline void
RelocatableValue::post()
{
#ifdef JSGC_GENERATIONAL
if (value.isMarkable()) {
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
cell->zone()->gcStoreBuffer.putRelocatableValue(&value);
}
if (value.isMarkable())
runtime(value)->gcStoreBuffer.putRelocatableValue(&value);
#endif
}
inline void
RelocatableValue::post(Zone *zone)
RelocatableValue::post(JSRuntime *rt)
{
#ifdef JSGC_GENERATIONAL
if (value.isMarkable())
zone->gcStoreBuffer.putRelocatableValue(&value);
rt->gcStoreBuffer.putRelocatableValue(&value);
#endif
}
@ -264,10 +260,8 @@ inline void
RelocatableValue::relocate()
{
#ifdef JSGC_GENERATIONAL
if (value.isMarkable()) {
js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
cell->zone()->gcStoreBuffer.removeRelocatableValue(&value);
}
if (value.isMarkable())
runtime(value)->gcStoreBuffer.removeRelocatableValue(&value);
#endif
}
@ -301,10 +295,10 @@ HeapSlot::init(JSObject *obj, Kind kind, uint32_t slot, const Value &v)
}
inline void
HeapSlot::init(Zone *zone, JSObject *obj, Kind kind, uint32_t slot, const Value &v)
HeapSlot::init(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot, const Value &v)
{
value = v;
post(zone, obj, kind, slot);
post(rt, obj, kind, slot);
}
inline void
@ -329,34 +323,22 @@ HeapSlot::set(Zone *zone, JSObject *obj, Kind kind, uint32_t slot, const Value &
pre(zone);
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(zone, obj, kind, slot);
}
inline void
HeapSlot::setCrossCompartment(JSObject *obj, Kind kind, uint32_t slot, const Value &v, Zone *vzone)
{
JS_ASSERT_IF(kind == Slot, &obj->getSlotRef(slot) == this);
JS_ASSERT_IF(kind == Element, &obj->getDenseElement(slot) == (const Value *)this);
pre();
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(vzone, obj, kind, slot);
post(zone->rt, obj, kind, slot);
}
inline void
HeapSlot::writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot)
{
#ifdef JSGC_GENERATIONAL
obj->zone()->gcStoreBuffer.putSlot(obj, kind, slot);
obj->runtime()->gcStoreBuffer.putSlot(obj, kind, slot);
#endif
}
inline void
HeapSlot::writeBarrierPost(Zone *zone, JSObject *obj, Kind kind, uint32_t slot)
HeapSlot::writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.putSlot(obj, kind, slot);
rt->gcStoreBuffer.putSlot(obj, kind, slot);
#endif
}
@ -367,9 +349,9 @@ HeapSlot::post(JSObject *owner, Kind kind, uint32_t slot)
}
inline void
HeapSlot::post(Zone *zone, JSObject *owner, Kind kind, uint32_t slot)
HeapSlot::post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot)
{
HeapSlot::writeBarrierPost(zone, owner, kind, slot);
HeapSlot::writeBarrierPost(rt, owner, kind, slot);
}
#ifdef JSGC_GENERATIONAL
@ -404,11 +386,11 @@ class DenseRangeRef : public gc::BufferableRef
#endif
inline void
DenseRangeWriteBarrierPost(Zone *zone, JSObject *obj, uint32_t start, uint32_t count)
DenseRangeWriteBarrierPost(JSRuntime *rt, JSObject *obj, uint32_t start, uint32_t count)
{
#ifdef JSGC_GENERATIONAL
if (count > 0)
zone->gcStoreBuffer.putGeneric(DenseRangeRef(obj, start, start + count));
rt->gcStoreBuffer.putGeneric(DenseRangeRef(obj, start, start + count));
#endif
}

View File

@ -262,7 +262,7 @@ class RelocatablePtr : public EncapsulatedPtr<T>
~RelocatablePtr() {
if (this->value)
relocate(this->value->zone());
relocate(this->value->runtime());
}
RelocatablePtr<T> &operator=(T *v) {
@ -272,9 +272,9 @@ class RelocatablePtr : public EncapsulatedPtr<T>
this->value = v;
post();
} else if (this->value) {
Zone *zone = this->value->zone();
JSRuntime *rt = this->value->runtime();
this->value = v;
relocate(zone);
relocate(rt);
}
return *this;
}
@ -286,16 +286,16 @@ class RelocatablePtr : public EncapsulatedPtr<T>
this->value = v.value;
post();
} else if (this->value) {
Zone *zone = this->value->zone();
JSRuntime *rt = this->value->runtime();
this->value = v;
relocate(zone);
relocate(rt);
}
return *this;
}
protected:
inline void post();
inline void relocate(Zone *zone);
inline void relocate(JSRuntime *rt);
};
/*
@ -400,6 +400,11 @@ class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
inline void pre();
inline void pre(Zone *zone);
static inline JSRuntime *runtime(const Value &v) {
JS_ASSERT(v.isMarkable());
return static_cast<js::gc::Cell *>(v.toGCThing())->runtime();
}
private:
friend class ValueOperations<EncapsulatedValue>;
const Value * extract() const { return &value; }
@ -414,7 +419,7 @@ class HeapValue : public EncapsulatedValue
inline ~HeapValue();
inline void init(const Value &v);
inline void init(Zone *zone, const Value &v);
inline void init(JSRuntime *rt, const Value &v);
inline HeapValue &operator=(const Value &v);
inline HeapValue &operator=(const HeapValue &v);
@ -428,11 +433,11 @@ class HeapValue : public EncapsulatedValue
inline void set(Zone *zone, const Value &v);
static inline void writeBarrierPost(const Value &v, Value *addr);
static inline void writeBarrierPost(Zone *zone, const Value &v, Value *addr);
static inline void writeBarrierPost(JSRuntime *rt, const Value &v, Value *addr);
private:
inline void post();
inline void post(Zone *zone);
inline void post(JSRuntime *rt);
};
class RelocatableValue : public EncapsulatedValue
@ -448,7 +453,7 @@ class RelocatableValue : public EncapsulatedValue
private:
inline void post();
inline void post(Zone *zone);
inline void post(JSRuntime *rt);
inline void relocate();
};
@ -474,19 +479,17 @@ class HeapSlot : public EncapsulatedValue
inline ~HeapSlot();
inline void init(JSObject *owner, Kind kind, uint32_t slot, const Value &v);
inline void init(Zone *zone, JSObject *owner, Kind kind, uint32_t slot, const Value &v);
inline void init(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot, const Value &v);
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);
inline void setCrossCompartment(JSObject *owner, Kind kind, uint32_t slot, const Value &v,
Zone *vzone);
static inline void writeBarrierPost(JSObject *obj, Kind kind, uint32_t slot);
static inline void writeBarrierPost(Zone *zone, JSObject *obj, Kind kind, uint32_t slot);
static inline void writeBarrierPost(JSRuntime *rt, JSObject *obj, Kind kind, uint32_t slot);
private:
inline void post(JSObject *owner, Kind kind, uint32_t slot);
inline void post(Zone *zone, JSObject *owner, Kind kind, uint32_t slot);
inline void post(JSRuntime *rt, JSObject *owner, Kind kind, uint32_t slot);
};
/*
@ -496,14 +499,14 @@ class HeapSlot : public EncapsulatedValue
* single step.
*/
inline void
DenseRangeWriteBarrierPost(Zone *zone, JSObject *obj, uint32_t start, uint32_t count);
DenseRangeWriteBarrierPost(JSRuntime *rt, JSObject *obj, uint32_t start, uint32_t count);
/*
* This is a post barrier for HashTables whose key can be moved during a GC.
*/
template <class Map, class Key>
inline void
HashTableWriteBarrierPost(Zone *zone, const Map *map, const Key &key)
HashTableWriteBarrierPost(JSRuntime *rt, const Map *map, const Key &key)
{
#ifdef JS_GCGENERATIONAL
if (key && comp->gcNursery.isInside(key))

View File

@ -808,7 +808,7 @@ struct Chunk
}
private:
inline void init();
inline void init(JSRuntime *rt);
/* Search for a decommitted arena to allocate. */
unsigned findDecommittedArenaOffset();

View File

@ -213,6 +213,9 @@ StoreBuffer::enable()
void
StoreBuffer::disable()
{
if (!enabled)
return;
bufferVal.disable();
bufferCell.disable();
bufferSlot.disable();

View File

@ -15,8 +15,7 @@
#include "jsgc.h"
#include "jsalloc.h"
#include "gc/Marking.h"
#include "jsobj.h"
namespace js {
namespace gc {
@ -44,6 +43,11 @@ class Nursery
nursery.finish();
}
bool clear() {
disable();
return enable();
}
bool isInside(void *cell) const {
JS_ASSERT((uintptr_t(cell) & 0x3) == 0);
return nursery.initialized() && nursery.has(cell);
@ -358,6 +362,11 @@ class StoreBuffer
void disable();
bool isEnabled() { return enabled; }
bool clear() {
disable();
return enable();
}
/* Get the overflowed status. */
bool hasOverflowed() const { return overflowed; }

View File

@ -656,25 +656,18 @@ gc::StartVerifyPostBarriers(JSRuntime *rt)
rt->gcNumber++;
trc->number = rt->gcNumber;
trc->count = 0;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (IsAtomsCompartment(c))
continue;
if (!c->gcNursery.enable())
goto oom;
if (!rt->gcNursery.clear())
goto oom;
if (!rt->gcStoreBuffer.clear())
goto oom;
if (!c->gcStoreBuffer.enable())
goto oom;
}
return;
oom:
trc->~VerifyPostTracer();
js_free(trc);
rt->gcVerifyPostData = NULL;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->gcNursery.disable();
c->gcStoreBuffer.disable();
}
#endif
}
@ -697,17 +690,10 @@ PostVerifierVisitEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
{
VerifyPostTracer *trc = (VerifyPostTracer *)jstrc;
Cell *dst = (Cell *)*thingp;
JSCompartment *comp = dst->compartment();
/*
* Note: watchpoint markAll will give us cross-compartment pointers into the
* atoms compartment.
*/
if (IsAtomsCompartment(comp))
return;
JSRuntime *rt = dst->runtime();
/* Filter out non cross-generational edges. */
if (!comp->gcNursery.isInside(dst))
if (!rt->gcNursery.isInside(dst))
return;
/*
@ -717,7 +703,7 @@ PostVerifierVisitEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
*/
Cell *loc = (Cell *)(trc->realLocation != NULL ? trc->realLocation : thingp);
AssertStoreBufferContainsEdge(&comp->gcStoreBuffer, loc, dst);
AssertStoreBufferContainsEdge(&rt->gcStoreBuffer, loc, dst);
}
#endif
@ -731,21 +717,16 @@ js::gc::EndVerifyPostBarriers(JSRuntime *rt)
JS_TracerInit(trc, rt, PostVerifierVisitEdge);
trc->count = 0;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (c->gcStoreBuffer.hasOverflowed())
continue;
if (!c->gcStoreBuffer.coalesceForVerification())
goto oom;
}
if (rt->gcStoreBuffer.hasOverflowed())
goto oom;
if (!rt->gcStoreBuffer.coalesceForVerification())
goto oom;
/* Walk the heap. */
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (!c->gcStoreBuffer.isEnabled() ||
c->gcStoreBuffer.hasOverflowed() ||
IsAtomsCompartment(c))
{
if (IsAtomsCompartment(c))
continue;
}
if (c->watchpointMap)
c->watchpointMap->markAll(trc);
@ -753,7 +734,7 @@ js::gc::EndVerifyPostBarriers(JSRuntime *rt)
for (size_t kind = 0; kind < FINALIZE_LIMIT; ++kind) {
for (CellIterUnderGC cells(c, AllocKind(kind)); !cells.done(); cells.next()) {
Cell *src = cells.getCell();
if (!c->gcNursery.isInside(src))
if (!rt->gcNursery.isInside(src))
JS_TraceChildren(trc, src, MapAllocToTraceKind(AllocKind(kind)));
}
}
@ -763,11 +744,9 @@ oom:
trc->~VerifyPostTracer();
js_free(trc);
rt->gcVerifyPostData = NULL;
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->gcNursery.disable();
c->gcStoreBuffer.disable();
c->gcStoreBuffer.releaseVerificationData();
}
rt->gcNursery.disable();
rt->gcStoreBuffer.disable();
rt->gcStoreBuffer.releaseVerificationData();
#endif
}
@ -854,10 +833,8 @@ js::gc::FinishVerifier(JSRuntime *rt)
if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
trc->~VerifyPostTracer();
js_free(trc);
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->gcNursery.disable();
c->gcStoreBuffer.disable();
}
rt->gcNursery.disable();
rt->gcStoreBuffer.disable();
}
#endif
}

View File

@ -814,6 +814,10 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
gcObjectsMarkedInDeadCompartments(0),
gcPoke(false),
heapState(Idle),
#ifdef JSGC_GENERATIONAL
gcNursery(),
gcStoreBuffer(&gcNursery),
#endif
#ifdef JS_GC_ZEAL
gcZeal_(0),
gcZealFrequency(0),

View File

@ -30,6 +30,7 @@
#include "ds/LifoAlloc.h"
#include "gc/Statistics.h"
#include "gc/StoreBuffer.h"
#include "js/HashTable.h"
#include "js/Vector.h"
#include "vm/DateTime.h"
@ -903,6 +904,11 @@ struct JSRuntime : js::RuntimeFriendFields,
bool isHeapCollecting() { return heapState == js::Collecting; }
#ifdef JSGC_GENERATIONAL
js::gc::Nursery gcNursery;
js::gc::StoreBuffer gcStoreBuffer;
#endif
/*
* These options control the zealousness of the GC. The fundamental values
* are gcNextScheduled and gcDebugCompartmentGC. At every allocation,

View File

@ -52,10 +52,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
global_(NULL),
enterCompartmentDepth(0),
allocator(this),
#ifdef JSGC_GENERATIONAL
gcNursery(),
gcStoreBuffer(&gcNursery),
#endif
ionUsingBarriers_(false),
gcScheduled(false),
gcState(NoGC),
@ -135,23 +131,6 @@ JSCompartment::init(JSContext *cx)
if (cx)
InitRandom(cx->runtime, &rngState);
#ifdef JSGC_GENERATIONAL
/*
* If we are in the middle of post-barrier verification, we need to
* immediately begin collecting verification data on new compartments.
*/
if (rt->gcVerifyPostData) {
if (!gcNursery.enable())
return false;
if (!gcStoreBuffer.enable())
return false;
} else {
gcNursery.disable();
gcStoreBuffer.disable();
}
#endif
enumerators = NativeIterator::allocateSentinel(cx);
if (!enumerators)
return false;

View File

@ -17,7 +17,6 @@
#include "jsgc.h"
#include "jsobj.h"
#include "gc/StoreBuffer.h"
#include "gc/FindSCCs.h"
#include "vm/GlobalObject.h"
#include "vm/RegExpObject.h"
@ -195,11 +194,6 @@ struct JSCompartment : private JS::shadow::Zone, public js::gc::GraphNodeBase<JS
*/
void adoptWorkerAllocator(js::Allocator *workerAllocator);
#ifdef JSGC_GENERATIONAL
js::gc::Nursery gcNursery;
js::gc::StoreBuffer gcStoreBuffer;
#endif
private:
bool ionUsingBarriers_;
public:

View File

@ -604,7 +604,7 @@ Chunk::allocate(JSRuntime *rt)
if (!chunk)
return NULL;
chunk->init();
chunk->init(rt);
rt->gcStats.count(gcstats::STAT_NEW_CHUNK);
return chunk;
}
@ -635,7 +635,7 @@ Chunk::prepareToBeFreed(JSRuntime *rt)
}
void
Chunk::init()
Chunk::init(JSRuntime *rt)
{
JS_POISON(this, JS_FREE_PATTERN, ChunkSize);
@ -654,6 +654,7 @@ Chunk::init()
info.numArenasFree = ArenasPerChunk;
info.numArenasFreeCommitted = ArenasPerChunk;
info.age = 0;
info.runtime = rt;
/* Initialize the arena header state. */
for (unsigned i = 0; i < ArenasPerChunk; i++) {
@ -971,6 +972,14 @@ js_InitGC(JSRuntime *rt, uint32_t maxbytes)
rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
#endif
#ifdef JSGC_GENERATIONAL
if (!rt->gcNursery.enable())
return false;
if (!rt->gcStoreBuffer.enable())
return false;
#endif
#ifdef JS_GC_ZEAL
if (!InitGCZeal(rt))
return false;

View File

@ -518,7 +518,7 @@ NewGCThing(JSContext *cx, AllocKind kind, size_t thingSize, InitialHeap heap)
!IsAtomsCompartment(cx->compartment) &&
heap != TenuredHeap)
{
zone->gcNursery.insertPointer(t);
cx->runtime->gcNursery.insertPointer(t);
}
#endif

View File

@ -1935,10 +1935,9 @@ 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) {
HeapSlot::writeBarrierPost(comp, a, HeapSlot::Slot, i);
HeapSlot::writeBarrierPost(comp, b, HeapSlot::Slot, i);
HeapSlot::writeBarrierPost(cx->runtime, a, HeapSlot::Slot, i);
HeapSlot::writeBarrierPost(cx->runtime, b, HeapSlot::Slot, i);
}
#endif
} else {

View File

@ -523,9 +523,9 @@ inline void
JSObject::initDenseElements(unsigned dstStart, const js::Value *src, unsigned count)
{
JS_ASSERT(dstStart + count <= getDenseCapacity());
JS::Zone *zone = this->zone();
JSRuntime *rt = runtime();
for (unsigned i = 0; i < count; ++i)
elements[dstStart + i].init(zone, this, js::HeapSlot::Element, dstStart + i, src[i]);
elements[dstStart + i].init(rt, this, js::HeapSlot::Element, dstStart + i, src[i]);
}
inline void
@ -561,7 +561,7 @@ JSObject::moveDenseElements(unsigned dstStart, unsigned srcStart, unsigned count
}
} else {
memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
DenseRangeWriteBarrierPost(zone, this, dstStart, count);
DenseRangeWriteBarrierPost(runtime(), this, dstStart, count);
}
}
@ -597,12 +597,12 @@ JSObject::ensureDenseInitializedLength(JSContext *cx, uint32_t index, uint32_t e
markDenseElementsNotPacked(cx);
if (initlen < index + extra) {
JS::Zone *zone = this->zone();
JSRuntime *rt = runtime();
size_t offset = initlen;
for (js::HeapSlot *sp = elements + initlen;
sp != elements + (index + extra);
sp++, offset++)
sp->init(zone, this, js::HeapSlot::Element, offset, js::MagicValue(JS_ELEMENTS_HOLE));
sp->init(rt, this, js::HeapSlot::Element, offset, js::MagicValue(JS_ELEMENTS_HOLE));
initlen = index + extra;
}
}
@ -668,10 +668,10 @@ JSObject::parExtendDenseElements(js::Allocator *alloc, js::Value *v, uint32_t ex
js::HeapSlot *sp = elements + initializedLength;
if (v) {
for (uint32_t i = 0; i < extra; i++)
sp[i].init(zone(), this, js::HeapSlot::Element, initializedLength+i, v[i]);
sp[i].init(runtime(), this, js::HeapSlot::Element, initializedLength+i, v[i]);
} else {
for (uint32_t i = 0; i < extra; i++) {
sp[i].init(zone(), this, js::HeapSlot::Element,
sp[i].init(runtime(), this, js::HeapSlot::Element,
initializedLength + i, js::MagicValue(JS_ELEMENTS_HOLE));
}
}

View File

@ -337,7 +337,7 @@ static void
WeakObjectSlotBarrierPost(JSObject *obj, size_t slot, const char *desc)
{
#ifdef JSGC_GENERATIONAL
obj->compartment()->gcStoreBuffer.putGeneric(WeakObjectSlotRef(obj, slot, desc));
obj->runtime()->gcStoreBuffer.putGeneric(WeakObjectSlotRef(obj, slot, desc));
#endif
}

View File

@ -205,10 +205,8 @@ InitTypedArrayDataPointer(JSObject *obj, ArrayBufferObject *buffer, size_t byteO
*/
obj->initPrivate(buffer->dataPointer() + byteOffset);
#ifdef JSGC_GENERATIONAL
JSCompartment *comp = obj->compartment();
JS_ASSERT(comp == buffer->compartment());
if (comp->gcNursery.isInside(buffer))
comp->gcStoreBuffer.putGeneric(TypedArrayPrivateRef(obj, buffer, byteOffset));
if (obj->runtime()->gcNursery.isInside(buffer))
obj->runtime()->gcStoreBuffer.putGeneric(TypedArrayPrivateRef(obj, buffer, byteOffset));
#endif
}

View File

@ -50,17 +50,17 @@ WatchpointMap::init()
}
static void
WatchpointWriteBarrierPost(JSCompartment *comp, WatchpointMap::Map *map, const WatchKey &key,
WatchpointWriteBarrierPost(JSRuntime *rt, WatchpointMap::Map *map, const WatchKey &key,
const Watchpoint &val)
{
#ifdef JSGC_GENERATIONAL
if ((JSID_IS_OBJECT(key.id) && comp->gcNursery.isInside(JSID_TO_OBJECT(key.id))) ||
(JSID_IS_STRING(key.id) && comp->gcNursery.isInside(JSID_TO_STRING(key.id))) ||
comp->gcNursery.isInside(key.object) ||
comp->gcNursery.isInside(val.closure))
if ((JSID_IS_OBJECT(key.id) && rt->gcNursery.isInside(JSID_TO_OBJECT(key.id))) ||
(JSID_IS_STRING(key.id) && rt->gcNursery.isInside(JSID_TO_STRING(key.id))) ||
rt->gcNursery.isInside(key.object) ||
rt->gcNursery.isInside(val.closure))
{
typedef HashKeyRef<WatchpointMap::Map, WatchKey> WatchKeyRef;
comp->gcStoreBuffer.putGeneric(WatchKeyRef(map, key));
rt->gcStoreBuffer.putGeneric(WatchKeyRef(map, key));
}
#endif
}
@ -82,7 +82,7 @@ WatchpointMap::watch(JSContext *cx, HandleObject obj, HandleId id,
js_ReportOutOfMemory(cx);
return false;
}
WatchpointWriteBarrierPost(obj->compartment(), &map, WatchKey(obj, id), w);
WatchpointWriteBarrierPost(cx->runtime, &map, WatchKey(obj, id), w);
return true;
}

View File

@ -322,7 +322,7 @@ WeakMap_set_impl(JSContext *cx, CallArgs args)
JS_ReportOutOfMemory(cx);
return false;
}
HashTableWriteBarrierPost(cx->zone(), map, key);
HashTableWriteBarrierPost(cx->runtime, map, key);
args.rval().setUndefined();
return true;

View File

@ -699,7 +699,7 @@ Debugger::wrapDebuggeeValue(JSContext *cx, MutableHandleValue vp)
js_ReportOutOfMemory(cx);
return false;
}
HashTableWriteBarrierPost(cx->zone(), &objects, obj);
HashTableWriteBarrierPost(cx->runtime, &objects, obj);
if (obj->compartment() != object->compartment()) {
CrossCompartmentKey key(CrossCompartmentKey::DebuggerObject, object, obj);

View File

@ -161,12 +161,12 @@ js::ObjectImpl::initializeSlotRange(uint32_t start, uint32_t length)
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
Zone *zone = this->zone();
JSRuntime *rt = runtime();
uint32_t offset = start;
for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
sp->init(zone, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
sp->init(zone, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, offset++, UndefinedValue());
}
inline bool
@ -198,13 +198,6 @@ ValueCompartment(const js::Value &value)
return static_cast<js::gc::Cell *>(value.toGCThing())->compartment();
}
static JS_ALWAYS_INLINE JS::Zone *
ValueZone(const js::Value &value)
{
JS_ASSERT(value.isMarkable());
return static_cast<js::gc::Cell *>(value.toGCThing())->zone();
}
#ifdef DEBUG
inline bool
IsValueInCompartment(js::Value v, JSCompartment *comp)
@ -228,11 +221,7 @@ inline void
js::ObjectImpl::setCrossCompartmentSlot(uint32_t slot, const js::Value &value)
{
MOZ_ASSERT(slotInRange(slot));
if (value.isMarkable())
getSlotRef(slot).setCrossCompartment(this->asObjectPtr(), HeapSlot::Slot, slot, value,
ValueZone(value));
else
setSlot(slot, value);
getSlotRef(slot).set(this->asObjectPtr(), HeapSlot::Slot, slot, value);
}
inline void
@ -249,10 +238,7 @@ js::ObjectImpl::initCrossCompartmentSlot(uint32_t slot, const js::Value &value)
{
MOZ_ASSERT(getSlot(slot).isUndefined());
MOZ_ASSERT(slotInRange(slot));
if (value.isMarkable())
getSlotRef(slot).init(ValueZone(value), this->asObjectPtr(), HeapSlot::Slot, slot, value);
else
initSlot(slot, value);
initSlotUnchecked(slot, value);
}
inline void
@ -369,7 +355,7 @@ inline void
js::ObjectImpl::privateWriteBarrierPost(void **pprivate)
{
#ifdef JSGC_GENERATIONAL
zone()->gcStoreBuffer.putCell(reinterpret_cast<js::gc::Cell **>(pprivate));
runtime()->gcStoreBuffer.putCell(reinterpret_cast<js::gc::Cell **>(pprivate));
#endif
}
@ -400,7 +386,7 @@ js::ObjectImpl::writeBarrierPost(ObjectImpl *obj, void *addr)
#ifdef JSGC_GENERATIONAL
if (uintptr_t(obj) < 32)
return;
obj->zone()->gcStoreBuffer.putCell((Cell **)addr);
obj->runtime()->gcStoreBuffer.putCell((Cell **)addr);
#endif
}

View File

@ -246,13 +246,13 @@ js::ObjectImpl::checkShapeConsistency()
void
js::ObjectImpl::initSlotRange(uint32_t start, const Value *vector, uint32_t length)
{
JS::Zone *zone = this->zone();
JSRuntime *rt = runtime();
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
sp->init(zone, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
sp->init(zone, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
sp->init(rt, this->asObjectPtr(), HeapSlot::Slot, start++, *vector++);
}
void

View File

@ -1688,7 +1688,7 @@ DebugScopes::addDebugScope(JSContext *cx, ScopeObject &scope, DebugScopeObject &
return false;
}
HashTableWriteBarrierPost(cx->zone(), &scopes->proxiedScopes, &scope);
HashTableWriteBarrierPost(cx->runtime, &scopes->proxiedScopes, &scope);
return true;
}

View File

@ -31,18 +31,18 @@
namespace js {
static inline void
GetterSetterWriteBarrierPost(JS::Zone *zone, JSObject **objp)
GetterSetterWriteBarrierPost(JSRuntime *rt, JSObject **objp)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.putRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
rt->gcStoreBuffer.putRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
#endif
}
static inline void
GetterSetterWriteBarrierPostRemove(JS::Zone *zone, JSObject **objp)
GetterSetterWriteBarrierPostRemove(JSRuntime *rt, JSObject **objp)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.removeRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
rt->gcStoreBuffer.removeRelocatableCell(reinterpret_cast<gc::Cell **>(objp));
#endif
}
@ -69,11 +69,11 @@ BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags,
this->rawSetter = rawSetter;
if ((attrs & JSPROP_GETTER) && rawGetter) {
this->flags |= HAS_GETTER_OBJECT;
GetterSetterWriteBarrierPost(zone(), &this->getterObj);
GetterSetterWriteBarrierPost(runtime(), &this->getterObj);
}
if ((attrs & JSPROP_SETTER) && rawSetter) {
this->flags |= HAS_SETTER_OBJECT;
GetterSetterWriteBarrierPost(zone(), &this->setterObj);
GetterSetterWriteBarrierPost(runtime(), &this->setterObj);
}
}
@ -87,9 +87,9 @@ BaseShape::BaseShape(const StackBaseShape &base)
this->rawGetter = base.rawGetter;
this->rawSetter = base.rawSetter;
if ((base.flags & HAS_GETTER_OBJECT) && base.rawGetter)
GetterSetterWriteBarrierPost(zone(), &this->getterObj);
GetterSetterWriteBarrierPost(runtime(), &this->getterObj);
if ((base.flags & HAS_SETTER_OBJECT) && base.rawSetter)
GetterSetterWriteBarrierPost(zone(), &this->setterObj);
GetterSetterWriteBarrierPost(runtime(), &this->setterObj);
}
inline BaseShape &
@ -101,17 +101,17 @@ BaseShape::operator=(const BaseShape &other)
slotSpan_ = other.slotSpan_;
if (flags & HAS_GETTER_OBJECT) {
getterObj = other.getterObj;
GetterSetterWriteBarrierPost(zone(), &getterObj);
GetterSetterWriteBarrierPost(runtime(), &getterObj);
} else {
rawGetter = other.rawGetter;
GetterSetterWriteBarrierPostRemove(zone(), &getterObj);
GetterSetterWriteBarrierPostRemove(runtime(), &getterObj);
}
if (flags & HAS_SETTER_OBJECT) {
setterObj = other.setterObj;
GetterSetterWriteBarrierPost(zone(), &setterObj);
GetterSetterWriteBarrierPost(runtime(), &setterObj);
} else {
rawSetter = other.rawSetter;
GetterSetterWriteBarrierPostRemove(zone(), &setterObj);
GetterSetterWriteBarrierPostRemove(runtime(), &setterObj);
}
return *this;
}

View File

@ -95,18 +95,18 @@ NewShortString(JSContext *cx, TwoByteChars chars)
}
static inline void
StringWriteBarrierPost(JS::Zone *zone, JSString **strp)
StringWriteBarrierPost(JSRuntime *rt, JSString **strp)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.putRelocatableCell(reinterpret_cast<gc::Cell **>(strp));
rt->gcStoreBuffer.putRelocatableCell(reinterpret_cast<gc::Cell **>(strp));
#endif
}
static inline void
StringWriteBarrierPostRemove(JS::Zone *zone, JSString **strp)
StringWriteBarrierPostRemove(JSRuntime *rt, JSString **strp)
{
#ifdef JSGC_GENERATIONAL
zone->gcStoreBuffer.removeRelocatableCell(reinterpret_cast<gc::Cell **>(strp));
rt->gcStoreBuffer.removeRelocatableCell(reinterpret_cast<gc::Cell **>(strp));
#endif
}
@ -134,7 +134,7 @@ JSString::writeBarrierPost(JSString *str, void *addr)
#ifdef JSGC_GENERATIONAL
if (!str)
return;
str->zone()->gcStoreBuffer.putCell((Cell **)addr);
str->runtime()->gcStoreBuffer.putCell((Cell **)addr);
#endif
}
@ -178,8 +178,8 @@ JSRope::init(JSString *left, JSString *right, size_t length)
d.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
d.u1.left = left;
d.s.u2.right = right;
js::StringWriteBarrierPost(zone(), &d.u1.left);
js::StringWriteBarrierPost(zone(), &d.s.u2.right);
js::StringWriteBarrierPost(runtime(), &d.u1.left);
js::StringWriteBarrierPost(runtime(), &d.s.u2.right);
}
template <js::AllowGC allowGC>
@ -212,7 +212,7 @@ JSDependentString::init(JSLinearString *base, const jschar *chars, size_t length
d.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
d.u1.chars = chars;
d.s.u2.base = base;
js::StringWriteBarrierPost(zone(), reinterpret_cast<JSString **>(&d.s.u2.base));
js::StringWriteBarrierPost(runtime(), reinterpret_cast<JSString **>(&d.s.u2.base));
}
JS_ALWAYS_INLINE JSLinearString *

View File

@ -201,7 +201,7 @@ JSRope::flattenInternal(JSContext *maybecx)
jschar *wholeChars;
JSString *str = this;
jschar *pos;
Zone *zone = this->zone();
JSRuntime *rt = runtime();
if (this->leftChild()->isExtensible()) {
JSExtensibleString &left = this->leftChild()->asExtensible();
@ -219,8 +219,8 @@ JSRope::flattenInternal(JSContext *maybecx)
JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
left.d.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
left.d.s.u2.base = (JSLinearString *)this; /* will be true on exit */
StringWriteBarrierPostRemove(zone, &left.d.u1.left);
StringWriteBarrierPost(zone, (JSString **)&left.d.s.u2.base);
StringWriteBarrierPostRemove(rt, &left.d.u1.left);
StringWriteBarrierPost(rt, (JSString **)&left.d.s.u2.base);
goto visit_right_child;
}
}
@ -237,7 +237,7 @@ JSRope::flattenInternal(JSContext *maybecx)
JSString &left = *str->d.u1.left;
str->d.u1.chars = pos;
StringWriteBarrierPostRemove(zone, &str->d.u1.left);
StringWriteBarrierPostRemove(rt, &str->d.u1.left);
if (left.isRope()) {
left.d.s.u3.parent = str; /* Return to this when 'left' done, */
left.d.lengthAndFlags = 0x200; /* but goto visit_right_child. */
@ -267,14 +267,14 @@ JSRope::flattenInternal(JSContext *maybecx)
str->d.lengthAndFlags = buildLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
str->d.u1.chars = wholeChars;
str->d.s.u2.capacity = wholeCapacity;
StringWriteBarrierPostRemove(zone, &str->d.u1.left);
StringWriteBarrierPostRemove(zone, &str->d.s.u2.right);
StringWriteBarrierPostRemove(rt, &str->d.u1.left);
StringWriteBarrierPostRemove(rt, &str->d.s.u2.right);
return &this->asFlat();
}
size_t progress = str->d.lengthAndFlags;
str->d.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_FLAGS);
str->d.s.u2.base = (JSLinearString *)this; /* will be true on exit */
StringWriteBarrierPost(zone, (JSString **)&str->d.s.u2.base);
StringWriteBarrierPost(rt, (JSString **)&str->d.s.u2.base);
str = str->d.s.u3.parent;
if (progress == 0x200)
goto visit_right_child;