void growStackCurrent (GC_state s) { size_t reserved; GC_stack stack; reserved = sizeofStackGrowReserved (s, getStackCurrent(s)); if (DEBUG_STACKS or s->controls.messages) fprintf (stderr, "[GC: Growing stack of size %s bytes to size %s bytes, using %s bytes.]\n", uintmaxToCommaString(getStackCurrent(s)->reserved), uintmaxToCommaString(reserved), uintmaxToCommaString(getStackCurrent(s)->used)); assert (hasHeapBytesFree (s, sizeofStackWithHeader (s, reserved), 0)); stack = newStack (s, reserved, TRUE); copyStack (s, getStackCurrent(s), stack); getThreadCurrent(s)->stack = pointerToObjptr ((pointer)stack, s->heap.start); markCard (s, objptrToPointer (getThreadCurrentObjptr(s), s->heap.start)); }
void setGCStateCurrentThreadAndStack (GC_state s) { GC_thread thread; GC_stack stack; thread = getThreadCurrent (s); s->exnStack = thread->exnStack; stack = getStackCurrent (s); s->stackBottom = getStackBottom (s, stack); s->stackTop = getStackTop (s, stack); s->stackLimit = getStackLimit (s, stack); markCard (s, (pointer)stack); }
/* enter and leave should be called at the start and end of every GC * function that is exported to the outside world. They make sure * that the function is run in a critical section and check the GC * invariant. */ void enter (GC_state s) { if (DEBUG) fprintf (stderr, "enter\n"); /* used needs to be set because the mutator has changed s->stackTop. */ getStackCurrent(s)->used = sizeofGCStateCurrentStackUsed (s); getThreadCurrent(s)->exnStack = s->exnStack; if (DEBUG) displayGCState (s, stderr); beginAtomic (s); assert (invariantForGC (s)); if (DEBUG) fprintf (stderr, "enter ok\n"); }
void performGC (GC_state s, size_t oldGenBytesRequested, size_t nurseryBytesRequested, bool forceMajor, bool mayResize) { uintmax_t gcTime; bool stackTopOk; size_t stackBytesRequested; struct rusage ru_start; size_t totalBytesRequested; enterGC (s); s->cumulativeStatistics.numGCs++; if (DEBUG or s->controls.messages) { size_t nurserySize = s->heap.size - ((size_t)(s->heap.nursery - s->heap.start)); size_t nurseryUsed = (size_t)(s->frontier - s->heap.nursery); fprintf (stderr, "[GC: Starting gc #%s; requesting %s nursery bytes and %s old-gen bytes,]\n", uintmaxToCommaString(s->cumulativeStatistics.numGCs), uintmaxToCommaString(nurseryBytesRequested), uintmaxToCommaString(oldGenBytesRequested)); fprintf (stderr, "[GC:\theap at "FMTPTR" of size %s bytes (+ %s bytes card/cross map),]\n", (uintptr_t)(s->heap.start), uintmaxToCommaString(s->heap.size), uintmaxToCommaString(s->heap.withMapsSize - s->heap.size)); fprintf (stderr, "[GC:\twith old-gen of size %s bytes (%.1f%% of heap),]\n", uintmaxToCommaString(s->heap.oldGenSize), 100.0 * ((double)(s->heap.oldGenSize) / (double)(s->heap.size))); fprintf (stderr, "[GC:\tand nursery of size %s bytes (%.1f%% of heap),]\n", uintmaxToCommaString(nurserySize), 100.0 * ((double)(nurserySize) / (double)(s->heap.size))); fprintf (stderr, "[GC:\tand nursery using %s bytes (%.1f%% of heap, %.1f%% of nursery).]\n", uintmaxToCommaString(nurseryUsed), 100.0 * ((double)(nurseryUsed) / (double)(s->heap.size)), 100.0 * ((double)(nurseryUsed) / (double)(nurserySize))); } assert (invariantForGC (s)); if (needGCTime (s)) startTiming (&ru_start); minorGC (s); stackTopOk = invariantForMutatorStack (s); stackBytesRequested = stackTopOk ? 0 : sizeofStackWithHeader (s, sizeofStackGrowReserved (s, getStackCurrent (s))); totalBytesRequested = oldGenBytesRequested + nurseryBytesRequested + stackBytesRequested; if (forceMajor or totalBytesRequested > s->heap.size - s->heap.oldGenSize) majorGC (s, totalBytesRequested, mayResize); setGCStateCurrentHeap (s, oldGenBytesRequested + stackBytesRequested, nurseryBytesRequested); assert (hasHeapBytesFree (s, oldGenBytesRequested + stackBytesRequested, nurseryBytesRequested)); unless (stackTopOk) growStackCurrent (s); setGCStateCurrentThreadAndStack (s); if (needGCTime (s)) { gcTime = stopTiming (&ru_start, &s->cumulativeStatistics.ru_gc); s->cumulativeStatistics.maxPauseTime = max (s->cumulativeStatistics.maxPauseTime, gcTime); } else gcTime = 0; /* Assign gcTime to quell gcc warning. */ if (DEBUG or s->controls.messages) { size_t nurserySize = s->heap.size - (size_t)(s->heap.nursery - s->heap.start); fprintf (stderr, "[GC: Finished gc #%s; time %s ms,]\n", uintmaxToCommaString(s->cumulativeStatistics.numGCs), uintmaxToCommaString(gcTime)); fprintf (stderr, "[GC:\theap at "FMTPTR" of size %s bytes (+ %s bytes card/cross map),]\n", (uintptr_t)(s->heap.start), uintmaxToCommaString(s->heap.size), uintmaxToCommaString(s->heap.withMapsSize - s->heap.size)); fprintf (stderr, "[GC:\twith old-gen of size %s bytes (%.1f%% of heap),]\n", uintmaxToCommaString(s->heap.oldGenSize), 100.0 * ((double)(s->heap.oldGenSize) / (double)(s->heap.size))); fprintf (stderr, "[GC:\tand nursery of size %s bytes (%.1f%% of heap).]\n", uintmaxToCommaString(nurserySize), 100.0 * ((double)(nurserySize) / (double)(s->heap.size))); } /* Send a GC signal. */ if (s->signalsInfo.gcSignalHandled and s->signalHandlerThread != BOGUS_OBJPTR) { if (DEBUG_SIGNALS) fprintf (stderr, "GC Signal pending.\n"); s->signalsInfo.gcSignalPending = TRUE; unless (s->signalsInfo.amInSignalHandler) s->signalsInfo.signalIsPending = TRUE; } if (DEBUG) displayGCState (s, stderr); assert (hasHeapBytesFree (s, oldGenBytesRequested, nurseryBytesRequested)); assert (invariantForGC (s)); leaveGC (s); }