153 lines
3.7 KiB
C++
153 lines
3.7 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "gc/StoreBuffer-inl.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "jscompartment.h"
|
|
|
|
#include "gc/Statistics.h"
|
|
#include "vm/ArgumentsObject.h"
|
|
#include "vm/Runtime.h"
|
|
|
|
#include "jsgcinlines.h"
|
|
|
|
using namespace js;
|
|
using namespace js::gc;
|
|
|
|
void
|
|
StoreBuffer::GenericBuffer::trace(StoreBuffer* owner, JSTracer* trc)
|
|
{
|
|
mozilla::ReentrancyGuard g(*owner);
|
|
MOZ_ASSERT(owner->isEnabled());
|
|
if (!storage_)
|
|
return;
|
|
|
|
for (LifoAlloc::Enum e(*storage_); !e.empty();) {
|
|
unsigned size = *e.get<unsigned>();
|
|
e.popFront<unsigned>();
|
|
BufferableRef* edge = e.get<BufferableRef>(size);
|
|
edge->trace(trc);
|
|
e.popFront(size);
|
|
}
|
|
}
|
|
|
|
bool
|
|
StoreBuffer::enable()
|
|
{
|
|
if (enabled_)
|
|
return true;
|
|
|
|
if (!bufferVal.init() ||
|
|
!bufferCell.init() ||
|
|
!bufferSlot.init() ||
|
|
!bufferGeneric.init())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
enabled_ = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
StoreBuffer::disable()
|
|
{
|
|
if (!enabled_)
|
|
return;
|
|
|
|
aboutToOverflow_ = false;
|
|
|
|
enabled_ = false;
|
|
}
|
|
|
|
void
|
|
StoreBuffer::clear()
|
|
{
|
|
if (!enabled_)
|
|
return;
|
|
|
|
aboutToOverflow_ = false;
|
|
cancelIonCompilations_ = false;
|
|
|
|
bufferVal.clear();
|
|
bufferCell.clear();
|
|
bufferSlot.clear();
|
|
bufferGeneric.clear();
|
|
|
|
for (ArenaCellSet* set = bufferWholeCell; set; set = set->next)
|
|
set->arena->bufferedCells = nullptr;
|
|
bufferWholeCell = nullptr;
|
|
}
|
|
|
|
void
|
|
StoreBuffer::setAboutToOverflow()
|
|
{
|
|
if (!aboutToOverflow_) {
|
|
aboutToOverflow_ = true;
|
|
runtime_->gc.stats.count(gcstats::STAT_STOREBUFFER_OVERFLOW);
|
|
}
|
|
runtime_->gc.requestMinorGC(JS::gcreason::FULL_STORE_BUFFER);
|
|
}
|
|
|
|
void
|
|
StoreBuffer::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSizes
|
|
*sizes)
|
|
{
|
|
sizes->storeBufferVals += bufferVal.sizeOfExcludingThis(mallocSizeOf);
|
|
sizes->storeBufferCells += bufferCell.sizeOfExcludingThis(mallocSizeOf);
|
|
sizes->storeBufferSlots += bufferSlot.sizeOfExcludingThis(mallocSizeOf);
|
|
sizes->storeBufferGenerics += bufferGeneric.sizeOfExcludingThis(mallocSizeOf);
|
|
|
|
for (ArenaCellSet* set = bufferWholeCell; set; set = set->next)
|
|
sizes->storeBufferWholeCells += sizeof(ArenaCellSet);
|
|
}
|
|
|
|
void
|
|
StoreBuffer::addToWholeCellBuffer(ArenaCellSet* set)
|
|
{
|
|
set->next = bufferWholeCell;
|
|
bufferWholeCell = set;
|
|
}
|
|
|
|
ArenaCellSet ArenaCellSet::Empty(nullptr);
|
|
|
|
ArenaCellSet::ArenaCellSet(Arena* arena)
|
|
: arena(arena), next(nullptr)
|
|
{
|
|
bits.clear(false);
|
|
}
|
|
|
|
ArenaCellSet*
|
|
js::gc::AllocateWholeCellSet(Arena* arena)
|
|
{
|
|
Zone* zone = arena->zone;
|
|
JSRuntime* rt = zone->runtimeFromMainThread();
|
|
if (!rt->gc.nursery.isEnabled())
|
|
return nullptr;
|
|
|
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
|
Nursery& nursery = rt->gc.nursery;
|
|
void* data = nursery.allocateBuffer(zone, sizeof(ArenaCellSet));
|
|
if (!data) {
|
|
oomUnsafe.crash("Failed to allocate WholeCellSet");
|
|
return nullptr;
|
|
}
|
|
|
|
if (nursery.freeSpace() < ArenaCellSet::NurseryFreeThresholdBytes)
|
|
rt->gc.storeBuffer.setAboutToOverflow();
|
|
|
|
auto cells = static_cast<ArenaCellSet*>(data);
|
|
new (cells) ArenaCellSet(arena);
|
|
arena->bufferedCells = cells;
|
|
rt->gc.storeBuffer.addToWholeCellBuffer(cells);
|
|
return cells;
|
|
}
|
|
|
|
template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
|
|
template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>;
|
|
template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotsEdge>;
|