mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 817343 - GC validation isn't happening r=billm
--HG-- rename : dom/tests/browser/browser_ConsoleStoragePBTest_perwindowpb.js => dom/tests/browser/browser_ConsoleStoragePBTest.js rename : toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js => toolkit/components/places/tests/browser/browser_visituri_privatebrowsing.js extra : rebase_source : 7deb5ea796a0dfd68a3baa5b616af5ec98db545f
This commit is contained in:
parent
e3cd8d0be2
commit
853469c636
@ -807,6 +807,9 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
|||||||
gcSweepCompartment(NULL),
|
gcSweepCompartment(NULL),
|
||||||
gcSweepKindIndex(0),
|
gcSweepKindIndex(0),
|
||||||
gcArenasAllocatedDuringSweep(NULL),
|
gcArenasAllocatedDuringSweep(NULL),
|
||||||
|
#ifdef DEBUG
|
||||||
|
gcMarkingValidator(NULL),
|
||||||
|
#endif
|
||||||
gcInterFrameGC(0),
|
gcInterFrameGC(0),
|
||||||
gcSliceBudget(SliceBudget::Unlimited),
|
gcSliceBudget(SliceBudget::Unlimited),
|
||||||
gcIncrementalEnabled(true),
|
gcIncrementalEnabled(true),
|
||||||
|
@ -450,6 +450,10 @@ class PerThreadData : public js::PerThreadDataFriendFields
|
|||||||
bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
|
bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace gc {
|
||||||
|
class MarkingValidator;
|
||||||
|
} // namespace gc
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
struct JSRuntime : js::RuntimeFriendFields
|
struct JSRuntime : js::RuntimeFriendFields
|
||||||
@ -729,6 +733,10 @@ struct JSRuntime : js::RuntimeFriendFields
|
|||||||
*/
|
*/
|
||||||
js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
|
js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
js::gc::MarkingValidator *gcMarkingValidator;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indicates that a GC slice has taken place in the middle of an animation
|
* Indicates that a GC slice has taken place in the middle of an animation
|
||||||
* frame, rather than at the beginning. In this case, the next slice will be
|
* frame, rather than at the beginning. In this case, the next slice will be
|
||||||
|
220
js/src/jsgc.cpp
220
js/src/jsgc.cpp
@ -2698,7 +2698,8 @@ BeginMarkPhase(JSRuntime *rt)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
template <class CompartmentIter>
|
||||||
|
static void
|
||||||
MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
||||||
{
|
{
|
||||||
GCMarker *gcmarker = &rt->gcMarker;
|
GCMarker *gcmarker = &rt->gcMarker;
|
||||||
@ -2709,7 +2710,7 @@ MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool markedAny = false;
|
bool markedAny = false;
|
||||||
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) {
|
for (CompartmentIter c(rt); !c.done(); c.next()) {
|
||||||
markedAny |= WatchpointMap::markCompartmentIteratively(c, gcmarker);
|
markedAny |= WatchpointMap::markCompartmentIteratively(c, gcmarker);
|
||||||
markedAny |= WeakMapBase::markCompartmentIteratively(c, gcmarker);
|
markedAny |= WeakMapBase::markCompartmentIteratively(c, gcmarker);
|
||||||
}
|
}
|
||||||
@ -2724,6 +2725,20 @@ MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
|||||||
JS_ASSERT(gcmarker->isDrained());
|
JS_ASSERT(gcmarker->isDrained());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MarkWeakReferencesInCurrentGroup(JSRuntime *rt, gcstats::Phase phase)
|
||||||
|
{
|
||||||
|
MarkWeakReferences<GCCompartmentGroupIter>(rt, phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static void
|
||||||
|
MarkAllWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
||||||
|
{
|
||||||
|
MarkWeakReferences<GCCompartmentsIter>(rt, phase);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
MarkGrayReferences(JSRuntime *rt)
|
MarkGrayReferences(JSRuntime *rt)
|
||||||
{
|
{
|
||||||
@ -2743,78 +2758,164 @@ MarkGrayReferences(JSRuntime *rt)
|
|||||||
gcmarker->drainMarkStack(budget);
|
gcmarker->drainMarkStack(budget);
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
|
MarkWeakReferencesInCurrentGroup(rt, gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
|
||||||
|
|
||||||
JS_ASSERT(gcmarker->isDrained());
|
JS_ASSERT(gcmarker->isDrained());
|
||||||
|
|
||||||
gcmarker->setMarkColorBlack();
|
gcmarker->setMarkColorBlack();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void
|
|
||||||
ValidateIncrementalMarking(JSRuntime *rt)
|
class js::gc::MarkingValidator
|
||||||
{
|
{
|
||||||
typedef HashMap<Chunk *, uintptr_t *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
|
public:
|
||||||
|
MarkingValidator(JSRuntime *rt);
|
||||||
|
~MarkingValidator();
|
||||||
|
void nonIncrementalMark();
|
||||||
|
void validate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
JSRuntime *runtime;
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
typedef HashMap<Chunk *, ChunkBitmap *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
|
||||||
BitmapMap map;
|
BitmapMap map;
|
||||||
|
};
|
||||||
|
|
||||||
|
js::gc::MarkingValidator::MarkingValidator(JSRuntime *rt)
|
||||||
|
: runtime(rt),
|
||||||
|
initialized(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
js::gc::MarkingValidator::~MarkingValidator()
|
||||||
|
{
|
||||||
|
if (!map.initialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (BitmapMap::Range r(map.all()); !r.empty(); r.popFront())
|
||||||
|
js_delete(r.front().value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::gc::MarkingValidator::nonIncrementalMark()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Perform a non-incremental mark for all collecting compartments and record
|
||||||
|
* the results for later comparison.
|
||||||
|
*
|
||||||
|
* Currently this does not validate gray marking.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!map.init())
|
if (!map.init())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GCMarker *gcmarker = &rt->gcMarker;
|
GCMarker *gcmarker = &runtime->gcMarker;
|
||||||
|
|
||||||
/* Save existing mark bits. */
|
/* Save existing mark bits. */
|
||||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||||
ChunkBitmap *bitmap = &r.front()->bitmap;
|
ChunkBitmap *bitmap = &r.front()->bitmap;
|
||||||
uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
|
ChunkBitmap *entry = js_new<ChunkBitmap>();
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap));
|
memcpy(entry->bitmap, bitmap->bitmap, sizeof(bitmap->bitmap));
|
||||||
if (!map.putNew(r.front(), entry))
|
if (!map.putNew(r.front(), entry))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save and reset the lists of live weakmaps for the compartments we are collecting. */
|
/*
|
||||||
|
* Save the lists of live weakmaps and array buffers for the compartments we
|
||||||
|
* are collecting.
|
||||||
|
*/
|
||||||
WeakMapVector weakmaps;
|
WeakMapVector weakmaps;
|
||||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
ArrayBufferVector arrayBuffers;
|
||||||
if (!WeakMapBase::saveCompartmentWeakMapList(c, weakmaps))
|
for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
|
||||||
|
if (!WeakMapBase::saveCompartmentWeakMapList(c, weakmaps) ||
|
||||||
|
!ArrayBufferObject::saveArrayBufferList(c, arrayBuffers))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (GCCompartmentsIter c(rt); !c.done(); c.next())
|
|
||||||
WeakMapBase::resetCompartmentWeakMapList(c);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After this point, the function should run to completion, so we shouldn't
|
* After this point, the function should run to completion, so we shouldn't
|
||||||
* do anything fallible.
|
* do anything fallible.
|
||||||
*/
|
*/
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the lists of live weakmaps and array buffers for the compartments we
|
||||||
|
* are collecting.
|
||||||
|
*/
|
||||||
|
for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
|
||||||
|
WeakMapBase::resetCompartmentWeakMapList(c);
|
||||||
|
ArrayBufferObject::resetArrayBufferList(c);
|
||||||
|
}
|
||||||
|
|
||||||
/* Re-do all the marking, but non-incrementally. */
|
/* Re-do all the marking, but non-incrementally. */
|
||||||
js::gc::State state = rt->gcIncrementalState;
|
js::gc::State state = runtime->gcIncrementalState;
|
||||||
rt->gcIncrementalState = MARK_ROOTS;
|
runtime->gcIncrementalState = MARK_ROOTS;
|
||||||
|
|
||||||
JS_ASSERT(gcmarker->isDrained());
|
JS_ASSERT(gcmarker->isDrained());
|
||||||
gcmarker->reset();
|
gcmarker->reset();
|
||||||
|
|
||||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
|
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront())
|
||||||
r.front()->bitmap.clear();
|
r.front()->bitmap.clear();
|
||||||
|
|
||||||
MarkRuntime(gcmarker, true);
|
{
|
||||||
|
gcstats::AutoPhase ap1(runtime->gcStats, gcstats::PHASE_MARK);
|
||||||
|
gcstats::AutoPhase ap2(runtime->gcStats, gcstats::PHASE_MARK_ROOTS);
|
||||||
|
MarkRuntime(gcmarker, true);
|
||||||
|
}
|
||||||
|
|
||||||
SliceBudget budget;
|
SliceBudget budget;
|
||||||
rt->gcIncrementalState = MARK;
|
runtime->gcIncrementalState = MARK;
|
||||||
rt->gcMarker.drainMarkStack(budget);
|
runtime->gcMarker.drainMarkStack(budget);
|
||||||
MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
|
|
||||||
MarkGrayReferences(rt);
|
|
||||||
|
|
||||||
/* Now verify that we have the same mark bits as before. */
|
{
|
||||||
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
gcstats::AutoPhase ap(runtime->gcStats, gcstats::PHASE_SWEEP);
|
||||||
|
MarkAllWeakReferences(runtime, gcstats::PHASE_SWEEP_MARK_WEAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take a copy of the non-incremental mark state and restore the original. */
|
||||||
|
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||||
Chunk *chunk = r.front();
|
Chunk *chunk = r.front();
|
||||||
ChunkBitmap *bitmap = &chunk->bitmap;
|
ChunkBitmap *bitmap = &chunk->bitmap;
|
||||||
uintptr_t *entry = map.lookup(r.front())->value;
|
ChunkBitmap *entry = map.lookup(chunk)->value;
|
||||||
ChunkBitmap incBitmap;
|
js::Swap(*entry, *bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(incBitmap.bitmap, entry, sizeof(incBitmap.bitmap));
|
/* Restore the weak map and array buffer lists. */
|
||||||
js_free(entry);
|
for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
|
||||||
|
WeakMapBase::resetCompartmentWeakMapList(c);
|
||||||
|
ArrayBufferObject::resetArrayBufferList(c);
|
||||||
|
}
|
||||||
|
WeakMapBase::restoreCompartmentWeakMapLists(weakmaps);
|
||||||
|
ArrayBufferObject::restoreArrayBufferLists(arrayBuffers);
|
||||||
|
|
||||||
|
runtime->gcIncrementalState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::gc::MarkingValidator::validate()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Validates the incremental marking for a single compartment by comparing
|
||||||
|
* the mark bits to those previously recorded for a non-incremental mark.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
|
||||||
|
Chunk *chunk = r.front();
|
||||||
|
BitmapMap::Ptr ptr = map.lookup(chunk);
|
||||||
|
if (!ptr)
|
||||||
|
continue; /* Allocated after we did the non-incremental mark. */
|
||||||
|
|
||||||
|
ChunkBitmap *bitmap = ptr->value;
|
||||||
|
ChunkBitmap *incBitmap = &chunk->bitmap;
|
||||||
|
|
||||||
for (size_t i = 0; i < ArenasPerChunk; i++) {
|
for (size_t i = 0; i < ArenasPerChunk; i++) {
|
||||||
if (chunk->decommittedArenas.get(i))
|
if (chunk->decommittedArenas.get(i))
|
||||||
@ -2822,7 +2923,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
|
|||||||
Arena *arena = &chunk->arenas[i];
|
Arena *arena = &chunk->arenas[i];
|
||||||
if (!arena->aheader.allocated())
|
if (!arena->aheader.allocated())
|
||||||
continue;
|
continue;
|
||||||
if (!arena->aheader.compartment->isCollecting())
|
if (!arena->aheader.compartment->isGCSweeping())
|
||||||
continue;
|
continue;
|
||||||
if (arena->aheader.allocatedDuringIncremental)
|
if (arena->aheader.allocatedDuringIncremental)
|
||||||
continue;
|
continue;
|
||||||
@ -2837,31 +2938,45 @@ ValidateIncrementalMarking(JSRuntime *rt)
|
|||||||
* If a non-incremental GC wouldn't have collected a cell, then
|
* If a non-incremental GC wouldn't have collected a cell, then
|
||||||
* an incremental GC won't collect it.
|
* an incremental GC won't collect it.
|
||||||
*/
|
*/
|
||||||
JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap.isMarked(cell, BLACK));
|
JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap->isMarked(cell, BLACK));
|
||||||
|
|
||||||
/*
|
|
||||||
* If the cycle collector isn't allowed to collect an object
|
|
||||||
* after a non-incremental GC has run, then it isn't allowed to
|
|
||||||
* collected it after an incremental GC.
|
|
||||||
*/
|
|
||||||
JS_ASSERT_IF(!bitmap->isMarked(cell, GRAY), !incBitmap.isMarked(cell, GRAY));
|
|
||||||
|
|
||||||
thing += Arena::thingSize(kind);
|
thing += Arena::thingSize(kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(bitmap->bitmap, incBitmap.bitmap, sizeof(incBitmap.bitmap));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the weak map lists. */
|
|
||||||
for (GCCompartmentsIter c(rt); !c.done(); c.next())
|
|
||||||
WeakMapBase::resetCompartmentWeakMapList(c);
|
|
||||||
WeakMapBase::restoreCompartmentWeakMapLists(weakmaps);
|
|
||||||
|
|
||||||
rt->gcIncrementalState = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
ComputeNonIncrementalMarkingForValidation(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
JS_ASSERT(!rt->gcMarkingValidator);
|
||||||
|
if (rt->gcIsIncremental && rt->gcValidate)
|
||||||
|
rt->gcMarkingValidator = js_new<MarkingValidator>(rt);
|
||||||
|
if (rt->gcMarkingValidator)
|
||||||
|
rt->gcMarkingValidator->nonIncrementalMark();
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ValidateIncrementalMarking(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (rt->gcMarkingValidator)
|
||||||
|
rt->gcMarkingValidator->validate();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FinishMarkingValidation(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
js_delete(rt->gcMarkingValidator);
|
||||||
|
rt->gcMarkingValidator = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DropStringWrappers(JSRuntime *rt)
|
DropStringWrappers(JSRuntime *rt)
|
||||||
@ -3206,7 +3321,7 @@ EndMarkingCompartmentGroup(JSRuntime *rt)
|
|||||||
*/
|
*/
|
||||||
MarkIncomingCrossCompartmentPointers(rt, BLACK);
|
MarkIncomingCrossCompartmentPointers(rt, BLACK);
|
||||||
|
|
||||||
MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
|
MarkWeakReferencesInCurrentGroup(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change state of current group to MarkGray to restrict marking to this
|
* Change state of current group to MarkGray to restrict marking to this
|
||||||
@ -3257,6 +3372,8 @@ BeginSweepingCompartmentGroup(JSRuntime *rt)
|
|||||||
sweepingAtoms = true;
|
sweepingAtoms = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValidateIncrementalMarking(rt);
|
||||||
|
|
||||||
FreeOp fop(rt, rt->gcSweepOnBackgroundThread);
|
FreeOp fop(rt, rt->gcSweepOnBackgroundThread);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -3358,6 +3475,9 @@ BeginSweepPhase(JSRuntime *rt)
|
|||||||
* true so that any attempt to allocate a GC-thing from a finalizer will
|
* true so that any attempt to allocate a GC-thing from a finalizer will
|
||||||
* fail, rather than nest badly and leave the unmarked newborn to be swept.
|
* fail, rather than nest badly and leave the unmarked newborn to be swept.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
ComputeNonIncrementalMarkingForValidation(rt);
|
||||||
|
|
||||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
|
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
@ -3567,6 +3687,8 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FinishMarkingValidation(rt);
|
||||||
|
|
||||||
rt->gcLastGCTime = PRMJ_Now();
|
rt->gcLastGCTime = PRMJ_Now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,11 +594,11 @@ ArrayBufferObject::sweep(JSCompartment *compartment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArrayBufferObject::resetArrayBufferList(JSCompartment *compartment)
|
ArrayBufferObject::resetArrayBufferList(JSCompartment *comp)
|
||||||
{
|
{
|
||||||
JSObject *buffer = compartment->gcLiveArrayBuffers;
|
JSObject *buffer = comp->gcLiveArrayBuffers;
|
||||||
JS_ASSERT(buffer != UNSET_BUFFER_LINK);
|
JS_ASSERT(buffer != UNSET_BUFFER_LINK);
|
||||||
compartment->gcLiveArrayBuffers = NULL;
|
comp->gcLiveArrayBuffers = NULL;
|
||||||
|
|
||||||
while (buffer) {
|
while (buffer) {
|
||||||
JSObject *view = *GetViewList(&buffer->asArrayBuffer());
|
JSObject *view = *GetViewList(&buffer->asArrayBuffer());
|
||||||
@ -612,6 +612,38 @@ ArrayBufferObject::resetArrayBufferList(JSCompartment *compartment)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
ArrayBufferObject::saveArrayBufferList(JSCompartment *comp, ArrayBufferVector &vector)
|
||||||
|
{
|
||||||
|
JSObject *obj = comp->gcLiveArrayBuffers;
|
||||||
|
while (obj) {
|
||||||
|
JS_ASSERT(obj != UNSET_BUFFER_LINK);
|
||||||
|
ArrayBufferObject *buffer = &obj->asArrayBuffer();
|
||||||
|
if (!vector.append(buffer))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSObject *view = *GetViewList(buffer);
|
||||||
|
JS_ASSERT(view);
|
||||||
|
obj = BufferLink(view);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
ArrayBufferObject::restoreArrayBufferLists(ArrayBufferVector &vector)
|
||||||
|
{
|
||||||
|
for (ArrayBufferObject **p = vector.begin(); p != vector.end(); p++) {
|
||||||
|
ArrayBufferObject *buffer = *p;
|
||||||
|
JSCompartment *comp = buffer->compartment();
|
||||||
|
JSObject *firstView = *GetViewList(&buffer->asArrayBuffer());
|
||||||
|
JS_ASSERT(firstView);
|
||||||
|
JS_ASSERT(firstView->compartment() == comp);
|
||||||
|
JS_ASSERT(BufferLink(firstView) == UNSET_BUFFER_LINK);
|
||||||
|
SetBufferLink(firstView, comp->gcLiveArrayBuffers);
|
||||||
|
comp->gcLiveArrayBuffers = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
MutableHandleObject objp, MutableHandleShape propp)
|
MutableHandleObject objp, MutableHandleShape propp)
|
||||||
|
@ -17,6 +17,8 @@ typedef struct JSProperty JSProperty;
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
typedef Vector<ArrayBufferObject *, 0, SystemAllocPolicy> ArrayBufferVector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ArrayBufferObject
|
* ArrayBufferObject
|
||||||
*
|
*
|
||||||
@ -133,6 +135,8 @@ class ArrayBufferObject : public JSObject
|
|||||||
static void sweep(JSCompartment *rt);
|
static void sweep(JSCompartment *rt);
|
||||||
|
|
||||||
static void resetArrayBufferList(JSCompartment *rt);
|
static void resetArrayBufferList(JSCompartment *rt);
|
||||||
|
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
|
||||||
|
static void restoreArrayBufferLists(ArrayBufferVector &vector);
|
||||||
|
|
||||||
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
|
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
|
||||||
uint8_t **data);
|
uint8_t **data);
|
||||||
|
Loading…
Reference in New Issue
Block a user