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);
            }
Example #2
0
        internal static bool IsMyGcCard(UIntPtr c)
        {
            VTable.Assert(IsValidCardNo(c), "IsMyGcCard invalid");
            UIntPtr page = PageTable.Page(CardAddr(c));

            return(PageTable.IsMyGcPage(page));
        }
Example #3
0
 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;
         }
     }
 }
Example #4
0
        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;
            }
        }
Example #5
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);
        }