Exemplo n.º 1
0
    MinorCollectionTracer(JSRuntime *rt, Nursery *nursery)
      : JSTracer(rt, Nursery::MinorGCCallback, TraceWeakMapKeysValues),
        nursery(nursery),
        session(rt, MinorCollecting),
        tenuredSize(0),
        head(nullptr),
        tail(&head),
        savedRuntimeNeedBarrier(rt->needsBarrier()),
        disableStrictProxyChecking(rt)
    {
        rt->gcNumber++;

        /*
         * We disable the runtime needsBarrier() check so that pre-barriers do
         * not fire on objects that have been relocated. The pre-barrier's
         * call to obj->zone() will try to look through shape_, which is now
         * the relocation magic and will crash. However, zone->needsBarrier()
         * must still be set correctly so that allocations we make in minor
         * GCs between incremental slices will allocate their objects marked.
         */
        rt->setNeedsBarrier(false);

        /*
         * We use the live array buffer lists to track traced buffers so we can
         * sweep their dead views. Incremental collection also use these lists,
         * so we may need to save and restore their contents here.
         */
        if (rt->gcIncrementalState != NO_INCREMENTAL) {
            for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
                if (!ArrayBufferObject::saveArrayBufferList(c, liveArrayBuffers))
                    CrashAtUnhandlableOOM("OOM while saving live array buffers");
                ArrayBufferObject::resetArrayBufferList(c);
            }
        }
    }
Exemplo n.º 2
0
ForkJoinNursery::ForkJoinNursery(ForkJoinContext *cx, ForkJoinGCShared *shared, Allocator *tenured)
  : cx_(cx)
  , tenured_(tenured)
  , shared_(shared)
  , evacuationZone_(nullptr)
  , currentStart_(0)
  , currentEnd_(0)
  , position_(0)
  , currentChunk_(0)
  , numActiveChunks_(0)
  , numFromspaceChunks_(0)
  , mustEvacuate_(false)
  , isEvacuating_(false)
  , movedSize_(0)
  , head_(nullptr)
  , tail_(&head_)
  , hugeSlotsNew(0)
  , hugeSlotsFrom(1)
{
    for ( size_t i=0 ; i < MaxNurseryChunks ; i++ ) {
        newspace[i] = nullptr;
        fromspace[i] = nullptr;
    }
    if (!hugeSlots[hugeSlotsNew].init() || !hugeSlots[hugeSlotsFrom].init())
        CrashAtUnhandlableOOM("Cannot initialize PJS nursery");
    initNewspace();             // This can fail to return
}
Exemplo n.º 3
0
void *
ForkJoinNursery::moveObjectToTospace(JSObject *src)
{
    AllocKind dstKind = getObjectAllocKind(src);
    JSObject *dst = static_cast<JSObject *>(allocateInTospace(dstKind));
    if (!dst)
        CrashAtUnhandlableOOM("Failed to allocate object while moving object.");

    movedSize_ += copyObjectToTospace(dst, src, dstKind);

    RelocationOverlay *overlay = reinterpret_cast<RelocationOverlay *>(src);
    overlay->forwardTo(dst);
    insertIntoFixupList(overlay);

    return static_cast<void *>(dst);
}
Exemplo n.º 4
0
inline void
ForkJoinNursery::setCurrentChunk(int index)
{
    JS_ASSERT((size_t)index < numActiveChunks_);
    JS_ASSERT(!newspace[index]);

    currentChunk_ = index;
    ForkJoinNurseryChunk *c = shared_->allocateNurseryChunk();
    if (!c)
        CrashAtUnhandlableOOM("Cannot expand PJS nursery");
    c->trailer.runtime = shared_->runtime();
    c->trailer.location = gc::ChunkLocationBitPJSNewspace;
    c->trailer.storeBuffer = nullptr;
    currentStart_ = c->start();
    currentEnd_ = c->end();
    position_ = currentStart_;
    newspace[index] = c;
}
Exemplo n.º 5
0
size_t
ForkJoinNursery::copyElementsToTospace(JSObject *dst, JSObject *src, AllocKind dstKind)
{
    if (src->hasEmptyElements())
        return 0;

    ObjectElements *srcHeader = src->getElementsHeader();
    ObjectElements *dstHeader;

    // TODO Bug 874151: Prefer to put element data inline if we have space.
    // (Note, not a correctness issue.)
    if (!isInsideFromspace(srcHeader)) {
        JS_ASSERT(src->elements == dst->elements);
        hugeSlots[hugeSlotsFrom].remove(reinterpret_cast<HeapSlot*>(srcHeader));
        if (!isEvacuating_)
            hugeSlots[hugeSlotsNew].put(reinterpret_cast<HeapSlot*>(srcHeader));
        return 0;
    }

    size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity;

    // Unlike other objects, Arrays can have fixed elements.
    if (src->is<ArrayObject>() && nslots <= GetGCKindSlots(dstKind)) {
        dst->setFixedElements();
        dstHeader = dst->getElementsHeader();
        js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
        setElementsForwardingPointer(srcHeader, dstHeader, nslots);
        return nslots * sizeof(HeapSlot);
    }

    JS_ASSERT(nslots >= 2);
    dstHeader = reinterpret_cast<ObjectElements *>(allocateInTospace(nslots, sizeof(HeapSlot)));
    if (!dstHeader)
        CrashAtUnhandlableOOM("Failed to allocate elements while moving object.");
    js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
    setElementsForwardingPointer(srcHeader, dstHeader, nslots);
    dst->elements = dstHeader->elements();
    return nslots * sizeof(HeapSlot);
}
Exemplo n.º 6
0
size_t
ForkJoinNursery::copySlotsToTospace(JSObject *dst, JSObject *src, AllocKind dstKind)
{
    // Fixed slots have already been copied over.
    if (!src->hasDynamicSlots())
        return 0;

    if (!isInsideFromspace(src->slots)) {
        hugeSlots[hugeSlotsFrom].remove(src->slots);
        if (!isEvacuating_)
            hugeSlots[hugeSlotsNew].put(src->slots);
        return 0;
    }

    size_t count = src->numDynamicSlots();
    dst->slots = reinterpret_cast<HeapSlot *>(allocateInTospace(count, sizeof(HeapSlot)));
    if (!dst->slots)
        CrashAtUnhandlableOOM("Failed to allocate slots while moving object.");
    js_memcpy(dst->slots, src->slots, count * sizeof(HeapSlot));
    setSlotsForwardingPointer(src->slots, dst->slots, count);
    return count * sizeof(HeapSlot);
}