// static bool RedhawkGCInterface::InitializeSubsystems(GCType gcType) { g_pConfig->Construct(); #ifdef FEATURE_ETW MICROSOFT_WINDOWS_REDHAWK_GC_PRIVATE_PROVIDER_Context.IsEnabled = FALSE; MICROSOFT_WINDOWS_REDHAWK_GC_PUBLIC_PROVIDER_Context.IsEnabled = FALSE; // Register the Redhawk event provider with the system. RH_ETW_REGISTER_Microsoft_Windows_Redhawk_GC_Private(); RH_ETW_REGISTER_Microsoft_Windows_Redhawk_GC_Public(); MICROSOFT_WINDOWS_REDHAWK_GC_PRIVATE_PROVIDER_Context.RegistrationHandle = Microsoft_Windows_Redhawk_GC_PrivateHandle; MICROSOFT_WINDOWS_REDHAWK_GC_PUBLIC_PROVIDER_Context.RegistrationHandle = Microsoft_Windows_Redhawk_GC_PublicHandle; #endif // FEATURE_ETW if (!InitializeSystemInfo()) { return false; } // Initialize the special EEType used to mark free list entries in the GC heap. g_FreeObjectEEType.InitializeAsGcFreeType(); // Place the pointer to this type in a global cell (typed as the structurally equivalent MethodTable // that the GC understands). g_pFreeObjectMethodTable = (MethodTable *)&g_FreeObjectEEType; g_pFreeObjectEEType = &g_FreeObjectEEType; if (!g_SuspendEELock.InitNoThrow(CrstSuspendEE)) return false; // Set the GC heap type. bool fUseServerGC = (gcType == GCType_Server); GCHeap::InitializeHeapType(fUseServerGC); // Create the GC heap itself. GCHeap *pGCHeap = GCHeap::CreateGCHeap(); if (!pGCHeap) return false; // Initialize the GC subsystem. HRESULT hr = pGCHeap->Initialize(); if (FAILED(hr)) return false; if (!FinalizerThread::Initialize()) return false; // Initialize HandleTable. if (!Ref_Initialize()) return false; return true; }
int main(int argc, char* argv[]) { // // Initialize system info // InitializeSystemInfo(); // // Initialize free object methodtable. The GC uses a special array-like methodtable as placeholder // for collected free space. // static MethodTable freeObjectMT; freeObjectMT.InitializeFreeObject(); g_pFreeObjectMethodTable = &freeObjectMT; // // Initialize handle table // if (!Ref_Initialize()) return -1; // // Initialize GC heap // GCHeap *pGCHeap = GCHeap::CreateGCHeap(); if (!pGCHeap) return -1; if (FAILED(pGCHeap->Initialize())) return -1; // // Initialize current thread // ThreadStore::AttachCurrentThread(false); // // Create a Methodtable with GCDesc // class My : Object { public: Object * m_pOther1; int dummy_inbetween; Object * m_pOther2; }; static struct My_MethodTable { // GCDesc CGCDescSeries m_series[2]; size_t m_numSeries; // The actual methodtable MethodTable m_MT; } My_MethodTable; // 'My' contains the MethodTable* size_t baseSize = sizeof(My); // GC expects the size of ObjHeader (extra void*) to be included in the size. baseSize = baseSize + sizeof(ObjHeader); // Add padding as necessary. GC requires the object size to be at least MIN_OBJECT_SIZE. My_MethodTable.m_MT.m_baseSize = max(baseSize, MIN_OBJECT_SIZE); My_MethodTable.m_MT.m_componentSize = 0; // Array component size My_MethodTable.m_MT.m_flags = MTFlag_ContainsPointers; My_MethodTable.m_numSeries = 2; // The GC walks the series backwards. It expects the offsets to be sorted in descending order. My_MethodTable.m_series[0].SetSeriesOffset(offsetof(My, m_pOther2)); My_MethodTable.m_series[0].SetSeriesCount(1); My_MethodTable.m_series[0].seriessize -= My_MethodTable.m_MT.m_baseSize; My_MethodTable.m_series[1].SetSeriesOffset(offsetof(My, m_pOther1)); My_MethodTable.m_series[1].SetSeriesCount(1); My_MethodTable.m_series[1].seriessize -= My_MethodTable.m_MT.m_baseSize; MethodTable * pMyMethodTable = &My_MethodTable.m_MT; // Allocate instance of MyObject Object * pObj = AllocateObject(pMyMethodTable); if (pObj == NULL) return -1; // Create strong handle and store the object into it OBJECTHANDLE oh = CreateGlobalHandle(pObj); if (oh == NULL) return -1; for (int i = 0; i < 1000000; i++) { Object * pBefore = ((My *)ObjectFromHandle(oh))->m_pOther1; // Allocate more instances of the same object Object * p = AllocateObject(pMyMethodTable); if (p == NULL) return -1; Object * pAfter = ((My *)ObjectFromHandle(oh))->m_pOther1; // Uncomment this assert to see how GC triggered inside AllocateObject moved objects around // assert(pBefore == pAfter); // Store the newly allocated object into a field using WriteBarrier WriteBarrier(&(((My *)ObjectFromHandle(oh))->m_pOther1), p); } // Create weak handle that points to our object OBJECTHANDLE ohWeak = CreateGlobalWeakHandle(ObjectFromHandle(oh)); if (ohWeak == NULL) return -1; // Destroy the strong handle so that nothing will be keeping out object alive DestroyGlobalHandle(oh); // Explicitly trigger full GC pGCHeap->GarbageCollect(); // Verify that the weak handle got cleared by the GC assert(ObjectFromHandle(ohWeak) == NULL); printf("Done\n"); return 0; }