bool gmGarbageCollector::Collect() { if(m_fullThrottle) { m_workLeftToGo = GM_MAX_INT32; } else { m_workLeftToGo = m_workPerIncrement; } m_doneTracing = false; if(m_firstCollectionIncrement) { // Scan each root object and gray it GM_ASSERT(m_scanRootsCallback); m_scanRootsCallback(m_gmMachine, this); m_firstCollectionIncrement = false; return false; } // If any grays exist, scan them first if(m_colorSet.AnyGrays()) { if(BlackenGrays()) // Returns 0 if no more grays, and 1 if done with an increment of collection. { return false; // Out of time, so exit function } } m_doneTracing = true; // Let the collect continue until garbage memory has been reclaimed // This could be done as an external phase if(ReclaimSomeFreeObjects()) { return false; } #if GM_GC_TURN_OFF_ABLE // Turn off gc until almost out of memory. // Can only do when allocating black. m_gcTurnedOff = true; #else //GM_GC_TURN_OFF_ABLE Flip(); #endif //GM_GC_TURN_OFF_ABLE return true; }
void gmGarbageCollector::FullCollect() { m_fullThrottle = true; if(IsOff()) // If GC is off { ReclaimObjectsAndRestartCollection(); // Do flip and turn it back on } while(!Collect()) { // Do the collect phase } ReclaimObjectsAndRestartCollection(); // Do flip and turn it back on // Collect a second time to catch floating black objects while(!Collect()) { // Do the collect phase } // NOTE: (Below) Moved the restart after freeing objects so GC is logically off during object destruction // Free memory of garbage objects while(ReclaimSomeFreeObjects()) { // Reclaim all garbage } ReclaimObjectsAndRestartCollection(); // Do flip and turn it back on // NOTE: The GC is now restarted and in an 'On' state, meaning it will now collect again from the machine. // This behavior may not be desirable, so this function really needs more analysis to determine the // optimum sequence for a full collect with minimal redundancy. m_fullThrottle = false; }