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 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())); }