internal unsafe override void Visit(UIntPtr *loc) { UIntPtr addr = *loc; // Ignore pointers out of our memory area if (PageTable.IsForeignAddr(addr)) { return; } UIntPtr page = PageTable.Page(addr); if (!PageTable.IsMyGcPage(page)) { PageType pageType = PageTable.Type(page); #if SINGULARITY_PROCESS // We have to allow reference pointers to the // ThreadContext, which lives in the kernel space. VTable.Assert((PageTable.IsNonGcPage(pageType) && PageTable.IsMyPage(page)) || PageTable.IsStackPage(pageType) || PageTable.IsSharedPage(pageType) || (PageTable.IsGcPage(pageType) && PageTable.IsKernelPage(page))); #else VTable.Assert((PageTable.IsNonGcPage(pageType) && PageTable.IsMyPage(page)) || PageTable.IsStackPage(pageType) || PageTable.IsSharedPage(pageType)); #endif return; } UIntPtr objectAddr = SegregatedFreeList.Find(addr); markAndProcessReferenceVisitor.Visit(&objectAddr); }
internal static bool IsMyGcCard(UIntPtr c) { VTable.Assert(IsValidCardNo(c), "IsMyGcCard invalid"); UIntPtr page = PageTable.Page(CardAddr(c)); return(PageTable.IsMyGcPage(page)); }
private static void visitAllObjects(ObjectLayout.ObjectVisitor visitor, UIntPtr lowPage, UIntPtr highPage) { for (UIntPtr first = lowPage; first < highPage; first++) { if (PageTable.IsMyGcPage(first)) { UIntPtr last = first + 1; while (last < highPage) { if (!PageTable.IsMyGcPage(last)) { break; } last++; } UIntPtr start = PageTable.PageAddr(first); UIntPtr end = PageTable.PageAddr(last); GC.installedGC.VisitObjects(visitor, start, end); first = last; } } }
internal static void ReportHeapDetails() { VTable.DebugPrint("\nHeap details:\n"); uint pageCount = 0; for (UIntPtr i = UIntPtr.Zero; i < PageTable.pageTableCount; i++) { if (PageTable.IsMyGcPage(i)) { pageCount++; } } VTable.DebugPrint("\tTotal number of heap pages: {0}", __arglist(pageCount)); // The following obtains counts of heap objects against types. UIntPtr lowPage = UIntPtr.Zero; UIntPtr highPage = PageTable.pageTableCount; assertRuntimeTypeHeaders(lowPage, highPage); // First count the RuntimeType instances for heap objects. runtimeTypeReckoner.Initialize(true); visitAllObjects(forGCRuntimeTypeReckoner, lowPage, highPage); // Next, create a table for RuntimeType instance accounting. // NOTE: Storage for the table is marked "non-GC". Since // static data accounting is done before this, it's okay. int numSlots = runtimeTypeReckoner.Count; if (numSlots > TABLE_SIZE) { VTable.DebugPrint("Need {0} slots, have {1}\n", __arglist(numSlots, TABLE_SIZE)); VTable.NotReached("MemoryAccounting table not large enough"); } // Associate a table slot for each RuntimeType instance. runtimeTypeMapper.Initialize(false, MemoryAccounting.table); visitAllObjects(forGCRuntimeTypeMapper, lowPage, highPage); // Map each relevant RuntimeType instance to its table slot. for (uint i = 0; i < numSlots; i++) { RuntimeType rType = MemoryAccounting.table[i].RuntimeTypeObject; VTable.Assert(!MultiUseWord.IsMarked(rType), @"!MultiUseWord.IsMarked(rType)"); MemoryAccounting.table[i].SavedMUW = MultiUseWord.GetForObject(rType); MultiUseWord.SetValForObject(rType, (UIntPtr)i); } // Count heap object instances by RuntimeType using table. instanceReckoner.Initialize(MemoryAccounting.table); visitAllObjects(forGCInstanceReckoner, lowPage, highPage); // Bubble sort the table in decreasing order of total size. for (int i = 0; i < numSlots; i++) { for (int j = numSlots - 1; j > i; j--) { if (MemoryAccounting.table[j].TotalSize > MemoryAccounting.table[j - 1].TotalSize) { // Swap contents. RuntimeTypeAccounting temp = MemoryAccounting.table[j]; MemoryAccounting.table[j] = MemoryAccounting.table[j - 1]; MemoryAccounting.table[j - 1] = temp; } } } // Display table. VTable.DebugPrint("\n\tCounts of objects against types:\n"); for (uint i = 0; i < numSlots; i++) { if ((uint)MemoryAccounting.table[i].TotalSize < 1024) { continue; } VTable.DebugPrint ("\t\t{0,36} instances: {1,6}, bytes: {2,10}\n", __arglist(MemoryAccounting.table[i].RuntimeTypeObject.Name, (uint)MemoryAccounting.table[i].Count, (uint)MemoryAccounting.table[i].TotalSize)); } // Reset book-keeping information maintained in headers and the global // table. for (uint i = 0; i < numSlots; i++) { RuntimeType rType = MemoryAccounting.table[i].RuntimeTypeObject; MultiUseWord.SetForObject (rType, MemoryAccounting.table[i].SavedMUW); VTable.Assert(!MultiUseWord.IsMarked(rType), "@!MultiUseWord.IsMarked(rType)"); MemoryAccounting.table[i].RuntimeTypeObject = null; MemoryAccounting.table[i].SavedMUW = new MultiUseWord(new UIntPtr(0)); MemoryAccounting.table[i].TotalSize = new UIntPtr(0); MemoryAccounting.table[i].Count = 0; } }
internal static UIntPtr MarkZombiePages(int generation) { for (int i = (int)MIN_GENERATION; i <= generation; i++) { fromSpacePageCounts[i] = 0; } // Count the number of pages belonging to each generation. // Mark pages in the target generations as zombies. UIntPtr heapPageCount = UIntPtr.Zero; // determine the range of pages to loop through. // Our target generations are "generation" and all younger ones. // Therefore to ensure we get the right range, we must union the // ranges of all the target generations UIntPtr minPage = MinGenPage[generation]; UIntPtr maxPage = MaxGenPage[generation]; for (int i = 0; i < generation; i++) { if (MinGenPage[i] < minPage) { minPage = MinGenPage[i]; } if (MaxGenPage[i] > maxPage) { maxPage = MaxGenPage[i]; } } // This is used to determine the new range for the target generations UIntPtr newMinPage = PageTable.pageTableCount; UIntPtr newMaxPage = (UIntPtr)0; for (UIntPtr i = minPage; i <= maxPage; i++) { if (PageTable.IsMyGcPage(i)) { heapPageCount++; PageType pageType = PageTable.Type(i); int pageGen = (int)pageType; if (pageGen <= generation) { fromSpacePageCounts[pageGen]++; if (pageGen < (int)MAX_GENERATION) { MakeZombiePage(i, (PageType)(pageGen + 1)); } else { MakeZombiePage(i, MAX_GENERATION); } if (i < newMinPage) { newMinPage = i; } // for loop is always increasing, so MaxNurseryPage will // never be greater than i newMaxPage = i; } } } // update this generation with the new range. // This info is used by ReclaimZombiePages MinGenPage[generation] = newMinPage; MaxGenPage[generation] = newMaxPage; return(heapPageCount); }