Bug 1203273 - Add a canary to check gray buffers are valid r=sfink a=abillings

This commit is contained in:
Jon Coppeard 2018-03-20 10:19:37 +00:00
Родитель 7b0e5ad3eb
Коммит 84e70f499e
1 изменённых файлов: 22 добавлений и 1 удалений

Просмотреть файл

@ -460,6 +460,7 @@ class BufferGrayRootsTracer final : public JS::CallbackTracer
{}
bool failed() const { return bufferingGrayRootsFailed; }
void setFailed() { bufferingGrayRootsFailed = true; }
#ifdef DEBUG
TracerKind getTracerKind() const override { return TracerKind::GrayBuffering; }
@ -477,6 +478,9 @@ js::IsBufferGrayRootsTracer(JSTracer* trc)
}
#endif
// A canary value used to check the gray buffer contents are valid.
static Cell* const GrayBufferCanary = reinterpret_cast<Cell*>(0x47726179); // "Gray"
void
js::gc::GCRuntime::bufferGrayRoots()
{
@ -490,6 +494,12 @@ js::gc::GCRuntime::bufferGrayRoots()
if (JSTraceDataOp op = grayRootTracer.op)
(*op)(&grayBufferer, grayRootTracer.data);
// Push a canary value onto the end of the list.
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
if (!zone->gcGrayRoots().empty() && !zone->gcGrayRoots().append(GrayBufferCanary))
grayBufferer.setFailed();
}
// Propagate the failure flag from the marker to the runtime.
if (grayBufferer.failed()) {
grayBufferState = GrayBufferState::Failed;
@ -531,8 +541,19 @@ GCRuntime::markBufferedGrayRoots(JS::Zone* zone)
MOZ_ASSERT(grayBufferState == GrayBufferState::Okay);
MOZ_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting());
for (auto cell : zone->gcGrayRoots())
auto& roots = zone->gcGrayRoots();
if (roots.empty())
return;
// Check for and remove canary value.
MOZ_RELEASE_ASSERT(roots.length() > 1);
MOZ_RELEASE_ASSERT(roots.back() == GrayBufferCanary);
roots.popBack();
for (auto cell : zone->gcGrayRoots()) {
MOZ_ASSERT(IsCellPointerValid(cell));
TraceManuallyBarrieredGenericPointerEdge(&marker, &cell, "buffered gray root");
}
}
void