|
|
@@ -232,7 +232,69 @@ void gmGCColorSet::GrayThisObject(gmGCObjBase* a_obj)
|
|
|
#endif //GM_GC_DEBUG
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+void gmGCColorSet::GrayThisRootObject(gmGCObjBase* a_obj)
|
|
|
+{
|
|
|
+ // Normally, a object will never go from black to gray, only black to white or white to gray/black.
|
|
|
+ // We need to enforce that roots are treated as gray, and in this language and GC implementation
|
|
|
+ // it is convenient to force roots to gray from whatever logical state they are in.
|
|
|
+ // This is due to GC design choices including: atomic root snapshot, write barrier and allocate black.
|
|
|
+
|
|
|
+ gmGCObjBase* objPrev = a_obj->GetPrev();
|
|
|
+ gmGCObjBase* objNext = a_obj->GetNext();
|
|
|
+
|
|
|
+#if GM_GC_DEBUG
|
|
|
+ GM_ASSERT(a_obj->m_curPosColor != GM_GC_DEBUG_COL_FREE);
|
|
|
+ GM_ASSERT(a_obj->m_curPosColor != GM_GC_DEBUG_COL_INVALID);
|
|
|
+ a_obj->m_curPosColor = GM_GC_DEBUG_COL_GRAY;
|
|
|
+#endif //GM_GC_DEBUG
|
|
|
+
|
|
|
+ // Set object`s color to shaded first.
|
|
|
+ a_obj->SetColor(m_gc->GetCurShadeColor());
|
|
|
+
|
|
|
+ // The object must be shaded
|
|
|
+ GM_ASSERT(m_gc->IsShaded(a_obj));
|
|
|
+
|
|
|
+ // Splice the object out of the list
|
|
|
+ objPrev->SetNext(objNext);
|
|
|
+ objNext->SetPrev(objPrev);
|
|
|
+
|
|
|
+ // Fix sentinels
|
|
|
+ if( m_scan == a_obj )
|
|
|
+ {
|
|
|
+ m_scan = m_scan->GetNext(); // Not Prev as scan should be the start of black inclusive
|
|
|
+ }
|
|
|
+ if( m_free == a_obj )
|
|
|
+ {
|
|
|
+ m_free = m_free->GetNext();
|
|
|
+ }
|
|
|
|
|
|
+ // We are scanning roots, not tracing, check that this is so
|
|
|
+ GM_ASSERT( m_gc->GetTraceState().m_done );
|
|
|
+
|
|
|
+ // Put the object into the correct place in the gray list
|
|
|
+
|
|
|
+#if DEPTH_FIRST
|
|
|
+ // Put the gray object at the head of the gray list.
|
|
|
+ a_obj->SetPrev(m_scan->GetPrev());
|
|
|
+ a_obj->SetNext(m_scan);
|
|
|
+ m_scan->GetPrev()->SetNext(a_obj);
|
|
|
+ m_scan->SetPrev(a_obj);
|
|
|
+#else // BREADTH_FIRST
|
|
|
+ // Put the gray object at the tail of the gray list.
|
|
|
+ a_obj->SetPrev(m_gray);
|
|
|
+ a_obj->SetNext(m_gray->GetNext());
|
|
|
+ m_gray->GetNext()->SetPrev(a_obj);
|
|
|
+ m_gray->SetNext(a_obj);
|
|
|
+#endif // BREADTH_FIRST
|
|
|
+
|
|
|
+#if GM_GC_DEBUG
|
|
|
+ // Slow, paranoid check
|
|
|
+ VerifyIntegrity();
|
|
|
+#endif //GM_GC_DEBUG
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void gmGCColorSet::Revive(gmGCObjBase* a_obj)
|
|
|
{
|
|
|
// NOTE: Once objects are in the free list, we can't trust the color mark,
|
|
|
@@ -291,6 +353,12 @@ void gmGCColorSet::ReclaimGarbage()
|
|
|
{
|
|
|
GM_ASSERT(m_scan->GetPrev() == m_gray);
|
|
|
|
|
|
+#if GM_GC_DEBUG
|
|
|
+ // Slow, paranoid check
|
|
|
+ VerifyIntegrity();
|
|
|
+#endif //GM_GC_DEBUG
|
|
|
+
|
|
|
+
|
|
|
#if GM_GC_DEBUG
|
|
|
{
|
|
|
// Traverse the newly found garbage objects just to make sure there
|
|
|
@@ -373,6 +441,11 @@ void gmGCColorSet::ReclaimGarbage()
|
|
|
|
|
|
GM_ASSERT(m_gray->GetNext() == m_scan);
|
|
|
|
|
|
+#if GM_GC_DEBUG
|
|
|
+ // Slow, paranoid check
|
|
|
+ VerifyIntegrity();
|
|
|
+#endif //GM_GC_DEBUG
|
|
|
+
|
|
|
#if GM_GC_DEBUG
|
|
|
{
|
|
|
int count = 0;
|
|
|
@@ -439,6 +512,12 @@ int gmGCColorSet::DestructSomeFreeObjects(int a_maxToDestruct)
|
|
|
m_scan = m_free;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+#if GM_GC_DEBUG
|
|
|
+ // Slow, paranoid check
|
|
|
+ VerifyIntegrity();
|
|
|
+#endif //GM_GC_DEBUG
|
|
|
+
|
|
|
return numDestructed;
|
|
|
}
|
|
|
|
|
|
@@ -736,7 +815,6 @@ void gmGarbageCollector::FullCollect()
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
//////////////////////////////////////////////////
|
|
|
// Helper functions for VM and debugger
|
|
|
//////////////////////////////////////////////////
|