Esempio n. 1
0
        private static unsafe void removeFromPLCList(PLCLink *pLinkAddr)
        {
            // The object needs to be removed from the PLC list.
            PLCLink *currPLCLink = pLinkAddr;

#if DEBUG
            VTable.Assert(currPLCLink->next != null,
                          @"currPLCLink->next != null");
#endif // DEBUG

            PLCLink *linkToSkip = currPLCLink->next;
            PLCLink *linkAfter  = linkToSkip->next;
            currPLCLink->next = linkAfter;
            linkToSkip->next  = plcListChunk;
            plcListChunk      = linkToSkip;

            // Update the PLC link pointer in the following object.
            if (linkAfter != null)
            {
                UIntPtr nextObjAddr = linkAfter->objAddr;
                Object  nextObj     = Magic.fromAddress(nextObjAddr);
#if DEBUG
                VTable.Assert(getPLCLink(nextObj) == linkToSkip,
                              @"getPLCLink(nextObj) == linkToSkip");
#endif // DEBUG

                setPLCLink(nextObj, currPLCLink);
            }
        }
Esempio n. 2
0
        private static unsafe void addToPLCList(Object obj)
        {
            // Check if free PLC links are available.
            if (plcListChunk == null)
            {
                if (numPLCChunks < maxPLCChunks)
                {
                    // Allocate a chunk of PLC links.
                    int     threadIndex = Thread.GetCurrentThreadIndex();
                    Thread  t           = Thread.threadTable[threadIndex];
                    UIntPtr resultAddr  =
                        t.segregatedFreeList.
                        Allocate(plcListChunkBytes,
                                 plcListVtable.baseAlignment);
                    Object result = Magic.fromAddress(resultAddr);
                    result.REF_STATE = 2 & ~countingONFlagMask;
                    result.vtable    = plcListVtable;
                    numPLCChunks++;

                    // Point <plcListChunk> to the first element
                    // in the allocated array of PLC links and string
                    // the elements into a free PLC links' list.
                    plcListChunk = (PLCLink *)
                                   (resultAddr + PostHeader.Size + UIntPtr.Size);
                    for (PLCLink *link = plcListChunk;
                         link < plcListChunk +
                         plcListChunkLength - 1;
                         link++)
                    {
                        link->next = link + 1;
                    }
                }
                else
                {
                    processPLCList();
                }
            }
            VTable.Assert(plcListChunk != null,
                          @"plcListChunk != null");

            // Insert object into the PLC list by moving a link
            // from the free PLC links' chunk.
            firstPLCLink->objAddr = Magic.addressOf(obj);
            PLCLink *currPLCLink = plcListChunk;

            plcListChunk          = plcListChunk->next;
            currPLCLink->next     = firstPLCLink;
            firstPLCLink          = currPLCLink;
            firstPLCLink->objAddr = UIntPtr.Zero;

            // Point the object to its link in the PLC list.
            setPLCLink(obj, firstPLCLink);
        }
Esempio n. 3
0
            internal override unsafe void Visit(UIntPtr *loc)
            {
                UIntPtr objAddr  = *loc;
                Object  obj      = Magic.fromAddress(objAddr);
                uint    refState = obj.REF_STATE;

                if ((refState & countingONFlagMask) == 0)
                {
                    return;
                }
                uint refCount = refState & refCountMask;

                VTable.Assert(refCount < refCountMask,
                              @"refCount < refCountMask");

                refState++;
                if ((refState & markFlagMask) != 0)
                {
                    // The object hasn't been visited either
                    // by the scanner or the incrementer.
                    obj.REF_STATE = refState & ~markFlagMask;
                    this.workList.Write(objAddr);
                    // This object isn't leaked data, so
                    // clear the PLC link in its header.
                    setPLCLink(obj, null);
                }
                else if ((refState & refCountMask) == 1)
                {
                    // The object has been visited in the
                    // past, but only by the scanner.
                    obj.REF_STATE = refState;
                    this.workList.Write(objAddr);
                    // This object isn't leaked data, so
                    // clear the PLC link in its header.
                    setPLCLink(obj, null);
                }
                else
                {
                    obj.REF_STATE = refState;
#if DEBUG
                    // The PLC link in this object's header
                    // should already be cleared.
                    PLCLink *pLinkAddr = getPLCLink(obj);
                    VTable.Assert(pLinkAddr == null,
                                  @"pLinkAddr == UIntPtr.Zero");
#endif // DEBUG
                }
            }
Esempio n. 4
0
 private static unsafe void setPLCLink(Object obj, PLCLink *link)
 {
     ((PreHeader)(obj.preHeader)).plcLink = link;
 }
Esempio n. 5
0
        private static unsafe void processPLCList()
        {
            int  startTicks     = 0;
            bool enableGCTiming = VTable.enableGCTiming;

            if (enableGCTiming)
            {
                VTable.enableGCTiming = false;
                startTicks            = Environment.TickCount;
            }
            if (VTable.enableGCWatermarks)
            {
                MemoryAccounting.RecordHeapWatermarks();
            }

#if DEBUG
            VTable.Assert(firstPLCLink->objAddr == UIntPtr.Zero,
                          @"firstPLCLink->objAddr == UIntPtr.Zero");
#endif // DEBUG

            // Let S be the subgraph of heap objects reachable from
            // the PLC list. Decrement counts due to references in S.
            for (PLCLink *link = firstPLCLink->next; link != null;
                 link = link->next)
            {
                UIntPtr objAddr = link->objAddr;
                VTable.Assert(objAddr != UIntPtr.Zero,
                              @"objAddr != UIntPtr.Zero");

                Object obj = Magic.fromAddress(objAddr);
                VTable.Assert((obj.REF_STATE &
                               countingONFlagMask) != 0,
                              @"(obj.REF_STATE &
                               countingONFlagMask) != 0");

                uint refState = obj.REF_STATE;
                if ((refState & markFlagMask) == 0)
                {
                    obj.REF_STATE = refState | markFlagMask;
                    internalDecrementer.Traverse(objAddr);
                }
            }

            // Objects that now have non-zero counts are those that
            // have references external to S incident on them.
            // Recompute counts due to reachability from such objects.
            for (PLCLink *link = firstPLCLink->next; link != null;
                 link = link->next)
            {
                UIntPtr objAddr = link->objAddr;
                internalScanner.Traverse(objAddr);
            }

            // String together objects with reference count
            // of zero for reclamation.
            internalReclaimer.Initialize();
            for (PLCLink *link = firstPLCLink->next; link != null;
                 link = link->next)
            {
                UIntPtr objAddr = link->objAddr;
                internalReclaimer.Traverse(objAddr);
            }
            ulong  reclaimedBytes = 0;
            Object reclaimedObj   = internalReclaimer.ReclaimedObjects;
            while (reclaimedObj != null)
            {
                if (VTable.enableGCProfiling)
                {
                    UIntPtr size = ObjectLayout.Sizeof(reclaimedObj);
                    reclaimedBytes += (ulong)size;
                }
                Object nextReclaimedObj = getNextLink(reclaimedObj);
                SegregatedFreeList.Free(reclaimedObj);
                reclaimedObj = nextReclaimedObj;
            }

            // Recycle the PLC list.
            if (firstPLCLink->next != null)
            {
                PLCLink *lastPLCLink = firstPLCLink;
                do
                {
                    lastPLCLink = lastPLCLink->next;
                } while (lastPLCLink->next != null);
                lastPLCLink->next  = plcListChunk;
                plcListChunk       = firstPLCLink->next;
                firstPLCLink->next = null;
            }

            // Release the memory used up by work lists.
            UIntPtrQueue.ReleaseStandbyPages(null);

            SegregatedFreeList.RecycleGlobalPages();
            SegregatedFreeList.CommitFreedData();
            GC.newBytesSinceGC = UIntPtr.Zero;

            if (enableGCTiming)
            {
                int elapsedTicks = Environment.TickCount - startTicks;
                System.GC.gcTotalTime += elapsedTicks;
                if (System.GC.maxPauseTime < elapsedTicks)
                {
                    System.GC.maxPauseTime = elapsedTicks;
                }
                System.GC.pauseCount++;
                VTable.enableGCTiming = true;
            }

            if (VTable.enableGCProfiling)
            {
                if (maxCyclicGarbage < reclaimedBytes)
                {
                    maxCyclicGarbage = reclaimedBytes;
                }
                totalCyclicGarbage += reclaimedBytes;
                cycleCollections++;
            }
        }
Esempio n. 6
0
        protected static void deallocateObjects
            (NonNullReferenceVisitor decrementer)
        {
            int  startTicks     = 0;
            bool enableGCTiming = VTable.enableGCTiming;

            if (enableGCTiming)
            {
                VTable.enableGCTiming = false;
                startTicks            = Environment.TickCount;
            }
            if (VTable.enableGCWatermarks)
            {
                MemoryAccounting.RecordHeapWatermarks();
            }

            // Set up a block to deallocate, if one doesn't exist.
            if (beingDeallocatedBlock == null &&
                delayedDeallocationList != null)
            {
                beingDeallocatedBlock   = delayedDeallocationList;
                delayedDeallocationList =
                    getNextLink(delayedDeallocationList);
                delayedDeallocationLength--;

                UIntPtr objAddr = Magic.addressOf(beingDeallocatedBlock);
                VTable  vtable  = beingDeallocatedBlock.vtable;
                initIncrementalDecrement(objAddr, vtable);
            }

            // Perform up to a constant number of work chunks on the
            // block being deallocated. A "work chunk" is either
            // decrementing up to a fixed number of references held in
            // an object, decrementing up to a fixed number of slots
            // if the object is an array, or reclaiming the object
            // after all decrements on its internal contents are done.
            for (uint workDone = 0; beingDeallocatedBlock != null &&
                 workDone < deallocationSpan; workDone++)
            {
                // Continue work on block.
                UIntPtr objAddr = Magic.addressOf(beingDeallocatedBlock);
 #if DEBUG
                UIntPtr page = PageTable.Page(objAddr);
                VTable.Assert(PageTable.IsGcPage(page),
                              @"PageTable.IsGcPage(page)");
 #endif // DEBUG

                VTable vtable = beingDeallocatedBlock.vtable;
                if (incrementalDecrement(objAddr, vtable,
                                         decrementer) != 0)
                {
                    continue;
                }

                // All decrements on contained references are over.
                Object obj = beingDeallocatedBlock;
                VTable.Assert((obj.REF_STATE & RSMasks.refCount) == 0,
                              @"(obj.REF_STATE & RSMasks.refCount) == 0");
#if DEBUG
                PLCLink *plcLinkAddr = GetPLCLink(obj);
                VTable.Assert(plcLinkAddr == null,
                              @"plcLinkAddr == null");
#endif // DEBUG

                SegregatedFreeList.Free(obj);

                // Set up block to work on next.
                beingDeallocatedBlock = delayedDeallocationList;
                if (delayedDeallocationList != null)
                {
                    delayedDeallocationList =
                        getNextLink(delayedDeallocationList);
                    delayedDeallocationLength--;

                    objAddr = Magic.addressOf(beingDeallocatedBlock);
                    vtable  = beingDeallocatedBlock.vtable;
                    initIncrementalDecrement(objAddr, vtable);
                }
            }

            SegregatedFreeList.RecycleGlobalPages();
            SegregatedFreeList.CommitFreedData();
            GC.newBytesSinceGC = UIntPtr.Zero;

            if (enableGCTiming)
            {
                int elapsedTicks = Environment.TickCount - startTicks;
                System.GC.gcTotalTime += elapsedTicks;
                if (System.GC.maxPauseTime < elapsedTicks)
                {
                    System.GC.maxPauseTime = elapsedTicks;
                }
                System.GC.pauseCount++;
                VTable.enableGCTiming = true;
            }
        }