void js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason) { JS_AbortIfWrongThread(rt); if (rt->mainThread.suppressGC) return; if (!isEnabled()) return; if (position() == start()) return; rt->gcHelperThread.waitBackgroundSweepEnd(); AutoStopVerifyingBarriers av(rt, false); /* Move objects pointed to by roots from the nursery to the major heap. */ MinorCollectionTracer trc(rt, this); MarkRuntime(&trc); Debugger::markAll(&trc); for (CompartmentsIter comp(rt); !comp.done(); comp.next()) { comp->markAllCrossCompartmentWrappers(&trc); comp->markAllInitialShapeTableEntries(&trc); } markStoreBuffer(&trc); rt->newObjectCache.clearNurseryObjects(rt); /* * Most of the work is done here. This loop iterates over objects that have * been moved to the major heap. If these objects have any outgoing pointers * to the nursery, then those nursery objects get moved as well, until no * objects are left to move. That is, we iterate to a fixed point. */ for (RelocationOverlay *p = trc.head; p; p = p->next()) { JSObject *obj = static_cast<JSObject*>(p->forwardingAddress()); JS_TraceChildren(&trc, obj, MapAllocToTraceKind(obj->tenuredGetAllocKind())); } /* Resize the nursery. */ double promotionRate = trc.tenuredSize / double(allocationEnd() - start()); if (promotionRate > 0.5) growAllocableSpace(); else if (promotionRate < 0.1) shrinkAllocableSpace(); /* Sweep. */ sweep(rt->defaultFreeOp()); rt->gcStoreBuffer.clear(); /* * We ignore gcMaxBytes when allocating for minor collection. However, if we * overflowed, we disable the nursery. The next time we allocate, we'll fail * because gcBytes >= gcMaxBytes. */ if (rt->gcBytes >= rt->gcMaxBytes) disable(); }
void js::Nursery::collectToFixedPoint(MinorCollectionTracer *trc) { for (RelocationOverlay *p = trc->head; p; p = p->next()) { JSObject *obj = static_cast<JSObject*>(p->forwardingAddress()); traceObject(trc, obj); } }
void js::Nursery::collectToFixedPoint(MinorCollectionTracer *trc, TenureCountCache &tenureCounts) { for (RelocationOverlay *p = trc->head; p; p = p->next()) { JSObject *obj = static_cast<JSObject*>(p->forwardingAddress()); traceObject(trc, obj); TenureCount &entry = tenureCounts.findEntry(obj->type()); if (entry.type == obj->type()) { entry.count++; } else if (!entry.type) { entry.type = obj->type(); entry.count = 1; } } }
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); }
void * js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src) { Zone *zone = src->zone(); AllocKind dstKind = GetObjectAllocKindForCopy(trc->runtime(), src); JSObject *dst = static_cast<JSObject *>(allocateFromTenured(zone, dstKind)); if (!dst) CrashAtUnhandlableOOM("Failed to allocate object while tenuring."); trc->tenuredSize += moveObjectToTenured(dst, src, dstKind); RelocationOverlay *overlay = reinterpret_cast<RelocationOverlay *>(src); overlay->forwardTo(dst); trc->insertIntoFixupList(overlay); return static_cast<void *>(dst); }
void * js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src) { Zone *zone = src->zone(); AllocKind dstKind = GetObjectAllocKindForCopy(src); JSObject *dst = static_cast<JSObject *>(allocateFromTenured(zone, dstKind)); if (!dst) MOZ_CRASH(); moveObjectToTenured(dst, src, dstKind); RelocationOverlay *overlay = reinterpret_cast<RelocationOverlay *>(src); overlay->forwardTo(dst); trc->insertIntoFixupList(overlay); return static_cast<void *>(dst); }
void js::Nursery::collectToFixedPoint(MinorCollectionTracer *trc) { for (RelocationOverlay *p = trc->head; p; p = p->next()) { JSObject *obj = static_cast<JSObject*>(p->forwardingAddress()); traceObject(trc, obj); /* * Increment tenure count and recompile the script for pre-tenuring if * long-lived. Attempt to distinguish between tenuring because the * object is long lived and tenuring while the nursery is still * smaller than the working set size. */ if (isFullyGrown() && !obj->hasLazyType() && obj->type()->hasNewScript() && obj->type()->incrementTenureCount()) { MaybeInvalidateScriptUsedWithNew(trc->runtime, obj->type()); } } }
void ForkJoinNursery::collectToFixedPoint(ForkJoinNurseryCollectionTracer *trc) { for (RelocationOverlay *p = head_; p; p = p->next()) traceObject(trc, static_cast<JSObject *>(p->forwardingAddress())); }