public static new void Initialize()
 {
     ConcurrentMSCollector.InitializeAllButVisitors();
     // instance = new CoCoMSCollector();
     ConcurrentMSCollector.instance
           = CoCoMSCollector.instance
           = (CoCoMSCollector)
             BootstrapMemory.Allocate(typeof(CoCoMSCollector));
     ConcurrentMSCollector.markReferenceVisitor =
         (MarkReferenceVisitor)
         BootstrapMemory.Allocate(typeof(MarkAndForwardReferenceVisitor));
     CoCoMSCollector.normalStackMarker =
         (NonNullReferenceVisitor)
         BootstrapMemory.Allocate(typeof(StackForwardReferenceVisitor));
     CoCoMSCollector.pinStackMarker =
         (NonNullReferenceVisitor)
         BootstrapMemory.Allocate(typeof(StackMarkPinnedReferenceVisitor));
     CoCoMSCollector.nopStackMarker =
         (NonNullReferenceVisitor)
         BootstrapMemory.Allocate(typeof(StackNopReferenceVisitor));
     ConcurrentMSCollector.stackMarkReferenceVisitor =
         CoCoMSCollector.normalStackMarker;
     ConcurrentMSCollector.stackMarkPinnedReferenceVisitor =
         CoCoMSCollector.normalStackMarker;
     ConcurrentMSCollector.updateReferenceVisitor =
         (UpdateReferenceVisitor)
         BootstrapMemory.Allocate(typeof(UpdateAndForwardReferenceVisitor));
     ConcurrentMSCollector.partialFreePageVisitor =
         (SegregatedFreeList.PartialFreePageVisitor)
         BootstrapMemory.Allocate(typeof(TaggingPartialFreePageVisitor));
     // sweepVisitor = new SweepVisitor();
     sweepVisitor = (SweepVisitor)
                    BootstrapMemory.Allocate(typeof(SweepVisitor));
 }
Exemple #2
0
 protected static void UpdateReferentRefCounts
     (UIntPtr objAddr,
     VTable vtable,
     NonNullReferenceVisitor updater)
 {
     updater.VisitReferenceFields(objAddr, vtable);
 }
            GenericObjectVisitor(NonNullReferenceVisitor referenceVisitor)
            {
                this.referenceVisitor = referenceVisitor;
#if DEBUG_OFFSETTABLE
                lastObjPtr = UIntPtr.Zero;
#endif
            }
 internal void ScanLiveRegs(UIntPtr mask,
                            NonNullReferenceVisitor referenceVisitor)
 {
     EDI.ScanLiveReg((mask >> 2) & 0x3, referenceVisitor);
     ESI.ScanLiveReg((mask >> 4) & 0x3, referenceVisitor);
     EBX.ScanLiveReg((mask >> 0) & 0x3, referenceVisitor);
     EBP.ScanLiveReg((mask >> 6) & 0x3, referenceVisitor);
 }
Exemple #5
0
 protected static void purgeDeallocationList
     (NonNullReferenceVisitor decrementer)
 {
     while (beingDeallocatedBlock != null ||
            delayedDeallocationList != null)
     {
         deallocateObjects(decrementer);
     }
 }
 private static void VisitIfNotContext(Thread thread,
     NonNullReferenceVisitor threadReferenceVisitor,
     UIntPtr *p)
 {
     if (*p != (UIntPtr) thread.context &&
         (int *) *p != &thread.context->gcStates) {
         threadReferenceVisitor.Visit(p);
     }
 }
 internal Verifier(NonNullReferenceVisitor referenceVisitor,
                   NonNullReferenceVisitor threadReferenceVisitor,
                   ObjectLayout.ObjectVisitor objectVisitor,
                   StackVerifier stackVerifier)
 {
     this.referenceVisitor       = referenceVisitor;;
     this.threadReferenceVisitor = threadReferenceVisitor;
     this.objectVisitor          = objectVisitor;
     this.stackVerifier          = stackVerifier;
 }
Exemple #8
0
        // A profiler can request a scan of all Roots, passing in a
        // visitor for callback.
        private void ProfileScanRoots(NonNullReferenceVisitor visitor)
        {
            CallStack.ScanStacks(visitor, visitor);
            Thread.VisitBootstrapData(visitor);
#if SINGULARITY_KERNEL
            Kernel.VisitSpecialData(visitor);
#endif
            MultiUseWord.VisitStrongRefs(visitor,
                                         false /* Don't use shadows */);
            StaticData.ScanStaticData(visitor);
        }
 internal void ScanLiveRegs(UIntPtr mask,
                            NonNullReferenceVisitor referenceVisitor)
 {
     r4.ScanLiveReg((mask >> 0) & 0x3, referenceVisitor);
     r5.ScanLiveReg((mask >> 2) & 0x3, referenceVisitor);
     r6.ScanLiveReg((mask >> 4) & 0x3, referenceVisitor);
     r7.ScanLiveReg((mask >> 6) & 0x3, referenceVisitor);
     r8.ScanLiveReg((mask >> 8) & 0x3, referenceVisitor);
     r9.ScanLiveReg((mask >> 10) & 0x3, referenceVisitor);
     r10.ScanLiveReg((mask >> 12) & 0x3, referenceVisitor);
     r11.ScanLiveReg((mask >> 14) & 0x3, referenceVisitor);
 }
 internal override void Scan(NonNullReferenceVisitor ptrVisitor,
                             PageType genToCollect)
 {
     for (int i = 0; i < writeBufferIndex; i++)
     {
         UIntPtr tag = *(writeBuffer + i);
         if (tag != UIntPtr.Zero)
         {
             if ((tag & 0x1) == 0)
             {
                 UIntPtr *fieldLoc = (UIntPtr *)tag;
                 if (*fieldLoc != UIntPtr.Zero)
                 {
                     ptrVisitor.Visit(fieldLoc);
                 }
             }
             else
             {
                 UIntPtr objectPtr = (UIntPtr)(tag - 1);
                 Object  obj       = Magic.fromAddress(objectPtr);
                 ptrVisitor.VisitReferenceFields(obj);
             }
         }
     }
     // Handle the overflow in the thread objects
     for (int i = 0; i < Thread.threadTable.Length; i++)
     {
         Thread t = Thread.threadTable[i];
         if (t != null)
         {
             UIntPtr tag = MixinThread(t).ssb.overflowValue;
             if (tag != UIntPtr.Zero)
             {
                 if ((tag & 0x1) == 0)
                 {
                     UIntPtr *fieldLoc = (UIntPtr *)tag;
                     if (*fieldLoc != UIntPtr.Zero)
                     {
                         ptrVisitor.Visit(fieldLoc);
                     }
                 }
                 else
                 {
                     UIntPtr objectPtr = (UIntPtr)(tag - 1);
                     Object  obj       = Magic.fromAddress(objectPtr);
                     ptrVisitor.VisitReferenceFields(obj);
                 }
             }
         }
     }
 }
 internal static int ScanStacks(NonNullReferenceVisitor VisitThreadReference,
     NonNullReferenceVisitor VisitPinnedReference)
 {
     int limit = Thread.threadTable.Length;
     int countThreads = 0;
     for (int i = 0; i < limit; i++) {
         Thread t = Thread.threadTable[i];
         if (t != null) {
             CollectorStatistics.Event(GCEvent.StackScanStart, i);
             ScanStack(t, VisitThreadReference, VisitPinnedReference);
             CollectorStatistics.Event(GCEvent.StackScanComplete, i);
             countThreads++;
         }
     }
     return countThreads;
 }
Exemple #12
0
        private static unsafe uint PurgeZCT(NonNullReferenceVisitor entryVisitor)
        {
            uint purgedSlots = 0;

            for (uint i = 1; i < maxEntries; i++)
            {
                UIntPtr content = zeroCountTable[i];
                if (((uint)content & 0x01) != 0)
                {
                    continue; // Node in free list, skip
                }
                purgedSlots++;
                entryVisitor.Visit(&content);
            }

            return(purgedSlots);
        }
Exemple #13
0
        uint ScanStack(Thread thread,
                       NonNullReferenceVisitor VisitThreadReference,
                       NonNullReferenceVisitor VisitPinnedReference)
        {
            Trace.Log(Trace.Area.Stack,
                      "Scanning stack for thread {0:x}",
                      __arglist(thread.threadIndex));

            uint numStackFrames = 0;

            threadBeingProcessed = thread;
            CalleeSaveLocations calleeSaves = new CalleeSaveLocations();

#if SINGULARITY_KERNEL
            TransitionRecord *marker = (TransitionRecord *)thread.context.stackMarkers;
#elif SINGULARITY_PROCESS
            TransitionRecord *marker = null;
            if (thread.context != null)
            {
                marker = (TransitionRecord *)thread.context->stackMarkers;
            }
#else
            TransitionRecord *marker = (TransitionRecord *)
                                       MixinThread(thread).asmStackMarker;
#endif
            while (marker != null)
            {
                Trace.Log(Trace.Area.Stack,
                          "Transition record: old={0:x}, callAddr={1:x}, stackBottom={2:x}", __arglist(marker->oldTransitionRecord, marker->callAddr, marker->stackBottom));
                marker->calleeSaveRegisters.DebugTrace();
                TransitionRecord *stopMarker = marker->oldTransitionRecord;
                UIntPtr           returnAddr = marker->callAddr;
                UIntPtr *         fp         = (UIntPtr *)
                                               marker->calleeSaveRegisters.GetFramePointer();
                UIntPtr *sp = (UIntPtr *)marker->stackBottom;
                calleeSaves.SetCalleeSaves(&marker->calleeSaveRegisters);
                numStackFrames +=
                    ScanStackSegment(ref calleeSaves, returnAddr, fp, sp,
                                     stopMarker, VisitThreadReference,
                                     VisitPinnedReference, thread);
                marker = marker->oldTransitionRecord;
            }
            threadBeingProcessed = null;
            return(numStackFrames);
        }
Exemple #14
0
 static Verifier()
 {
     genericReferenceVisitor       = new GenericReferenceVisitor();
     genericThreadReferenceVisitor =
         new GenericThreadReferenceVisitor();
     genericObjectVisitor =
         new GenericObjectVisitor(genericReferenceVisitor);
     genericStackVerifier  = new GenericStackVerifier();
     bumpAllocatorVerifier = new Verifier(genericReferenceVisitor,
                                          genericThreadReferenceVisitor,
                                          genericObjectVisitor,
                                          genericStackVerifier);
     segregatedFreeListVerifier =
         new Verifier(genericReferenceVisitor,
                      genericThreadReferenceVisitor,
                      new SegregatedFreeList.ObjectVisitorWrapper(genericObjectVisitor),
                      genericStackVerifier);
 }
Exemple #15
0
        internal override bool Scan(NonNullReferenceVisitor visitor)
        {
            bool globalRepeat = false;

            while (true)
            {
                UIntPtr lowAddr, highAddr;
                if (this.destinationLow != this.allocator.AllocPtr)
                {
                    lowAddr             = this.destinationLow;
                    highAddr            = this.allocator.AllocPtr;
                    this.destinationLow = highAddr;
                }
                else if (!this.HaveWork)
                {
                    // No more work to do
                    break;
                }
                else
                {
                    lowAddr = this.GetWork(out highAddr);
                }
                globalRepeat    = true;
                this.sourceHigh = highAddr;
                lowAddr        += PreHeader.Size;
                lowAddr         =
                    BumpAllocator.SkipNonObjectData(lowAddr, highAddr);
                while (lowAddr < this.sourceHigh)
                {
                    Object obj = Magic.fromAddress(lowAddr);
                    lowAddr += visitor.VisitReferenceFields(obj);
                    lowAddr  =
                        BumpAllocator.SkipNonObjectData(lowAddr, highAddr);
                }
                if (lowAddr < highAddr)
                {
                    // The scanning must have been aborted early due to
                    // overflow into a new page.  Put the rest of the
                    // range on the work list.
                    this.AddWork(lowAddr - PreHeader.Size, highAddr);
                }
            }
            return(globalRepeat);
        }
        uint ScanStaticPointerData(NonNullReferenceVisitor referenceVisitor)
        {
            uint totalSize = 0;

            for (int section = 0; section < sectionCount; section++)
            {
                uint size = (uint)(*(dataSectionEnd + section) -
                                   *(dataSectionBase + section));
                totalSize += size;
                UIntPtr *ptr           = *(dataSectionBase + section);
                uint *   pointerBitmap = *(staticDataPointerBitMap + section);
                uint     iters         = (size + 31) / 32;
                for (uint i = 0; i < iters; i++)
                {
                    uint mask = *pointerBitmap++;
                    if (mask != 0)
                    {
                        for (int j = 0; j < 32; j++)
                        {
                            if ((mask & 1) != 0)
                            {
                                referenceVisitor.Visit(ptr);
                            }
                            ptr++;
                            mask >>= 1;
                        }
                    }
                    else
                    {
                        ptr += 32;
                    }
                }
            }

            for (int section = 0; section < sectionCount; section++)
            {
                uint size = (uint)(*(roDataSectionEnd + section) -
                                   *(roDataSectionBase + section));
                totalSize += size;
            }

            return(totalSize * (uint)UIntPtr.Size);
        }
        internal override void Scan(NonNullReferenceVisitor ptrVisitor,
                                    PageType genToCollect)
        {
#if DEBUG_CARDS
            VTable.DebugPrint("************  Scan to collect generation {0:x8} ******\n",
                              __arglist(genToCollect));
            for (UIntPtr i = firstCardNo; i < firstCardNo + totalCards; i++)
            {
                if (CardIsDirty(i))
                {
                    VTable.DebugPrint("dirty card {0:x8} gen {1:x8}\n", __arglist(i, CardGeneration(i)));
                }
            }
#endif

            for (UIntPtr c = firstCardNo; c < firstCardNo + totalCards;)
            {
                if (CardIsDirty(c) && IsMyLiveGcCard(c) &&
                    CardGeneration(c) > genToCollect)
                {
                    UIntPtr last = c + 1;
                    while (last < firstCardNo + totalCards && CardIsDirty(last) &&
                           IsMyLiveGcCard(last) &&
                           CardGeneration(last) > genToCollect)
                    {
                        last++;
                    }
#if DEBUG_CARDS
                    VTable.DebugPrint("Scan from {0:x8} to {1:x8} to collect gen {2:x8}\n",
                                      __arglist(c, last - 1, genToCollect));
#endif
                    VisitObjectsInCards(ptrVisitor, c, last - 1);
                    c = last;
                }
                else
                {
                    c++;
                }
            }
#if DEBUG_CARDS
            VTable.DebugPrint("************ End Scan ******\n");
#endif
        }
Exemple #18
0
        internal override bool Scan(NonNullReferenceVisitor visitor)
        {
            bool localRepeat  = false;
            bool globalRepeat = false;

            while (true)
            {
                while (this.HaveWork)
                {
                    localRepeat = true;
                    UIntPtr lowAddr, highAddr;
                    lowAddr  = this.GetWork(out highAddr);
                    lowAddr += PreHeader.Size;
                    lowAddr  =
                        BumpAllocator.SkipNonObjectData(lowAddr, highAddr);
                    while (lowAddr < highAddr)
                    {
                        Object obj = Magic.fromAddress(lowAddr);
                        lowAddr += visitor.VisitReferenceFields(obj);
                        lowAddr  =
                            BumpAllocator.SkipNonObjectData(lowAddr, highAddr);
                    }
                }
                if (this.destinationLow != this.allocator.AllocPtr)
                {
                    localRepeat = true;
                    UIntPtr lowAddr  = this.destinationLow;
                    UIntPtr highAddr = this.allocator.AllocPtr;
                    this.destinationLow = highAddr;
                    this.AddWork(lowAddr, highAddr);
                }
                if (!localRepeat)
                {
                    // Exit the loop if we have done nothing this time around
                    break;
                }
                globalRepeat = true;
                localRepeat  = false;
            }
            return(globalRepeat);
        }
            internal void ScanLiveReg(uint kind,
                                      NonNullReferenceVisitor visitor)
            {
                switch (kind)
                {
                case 0: {
                    // Value is not a traceable heap pointer
                    break;
                }

                case 1: {
                    // Value is a pointer variable
                    VTable.Deny(this.head == null);
                    if (value != UIntPtr.Zero)
                    {
                        fixed(UIntPtr *valueField = &this.value)
                        {
                            visitor.Visit(valueField);
                        }
                    }
                    ClearCalleeReg();
                    break;
                }

                case 2: {
                    // Value is unchanged since function entry
                    VTable.Deny(this.pending);
                    this.pending = true;
                    break;
                }

                case 3:
                default: {
                    VTable.NotReached("ScanLiveReg 3 or default");
                    break;
                }
                }
            }
        private static void VisitObjectsInCards(NonNullReferenceVisitor ptrVisitor,
                                                UIntPtr first, UIntPtr last)
        {
            UIntPtr objectPtr = OffsetTable.FirstObjPtrWithFieldInCard(first);

            VTable.Assert(objectPtr != UIntPtr.Zero, "No first obj ptr");

            // TODO: in semispace.Visit, update cards in visiting promoted objects.
            // So far, since we have only two generations, and after scanning, all nursery
            // objects are promoted to mature generation,  thus there is no inter-generational
            // pointers anymore, and we do not need to update cards during visit. But we
            // need to do that once we have more than two generations.

            UIntPtr limit = NextCardAddr(last);

            while (objectPtr != UIntPtr.Zero && objectPtr < limit)
            {
#if DEBUG_CARDS
                VTable.DebugPrint("     visiting obj ptr {0:x8}\n", __arglist(objectPtr));
#endif
                Object  obj           = Magic.fromAddress(objectPtr);
                UIntPtr objSize       = ptrVisitor.VisitReferenceFields(obj);
                UIntPtr nextObjectPtr = OffsetTable.PtrToNextObject(objectPtr, objSize, limit);
                VTable.Assert(CardNo(objectPtr) <= CardNo(nextObjectPtr),
                              "Next object should be below the current one");
                if (CardNo(objectPtr) < CardNo(nextObjectPtr))
                {
                    UIntPtr c      = CardNo(objectPtr);
                    UIntPtr offset = objectPtr - CardAddr(c);
                    if (offset > OffsetTable.GetOffset(c))
                    {
                        OffsetTable.SetOffset(c, offset);
                    }
                }
                objectPtr = nextObjectPtr;
            }
        }
Exemple #21
0
 internal override bool Scan(NonNullReferenceVisitor visitor)
 {
     // BUGBUG:
     return(false);
 }
Exemple #22
0
 internal void Initialize(NonNullReferenceVisitor v)
 {
     this.visitor = v;
 }
Exemple #23
0
        protected static unsafe uint incrementalDecrement
            (UIntPtr objAddr,
            VTable vtable,
            NonNullReferenceVisitor decrementer)
        {
            uint pointerTracking = (uint)vtable.pointerTrackingMask;
            uint objTag          = pointerTracking & 0xf;
            uint workDone        = 0;

            switch (objTag)
            {
            case ObjectLayout.SPARSE_TAG: {
                UIntPtr *sparseObject        = (UIntPtr *)objAddr;
                uint     lastPointerTracking = getLastTracked(objAddr);
                for (pointerTracking = lastPointerTracking;
                     pointerTracking != 0 &&
                     workDone < decrementSpan; workDone++)
                {
                    uint index = pointerTracking & 0xf;
                    pointerTracking >>= 4;
                    UIntPtr *loc  = sparseObject + (int)index;
                    UIntPtr  addr = *loc;
                    if (addr != UIntPtr.Zero)
                    {
                        decrementer.Visit(addr);
                    }
                }
                setLastTracked(objAddr, pointerTracking);
                break;
            }

            case ObjectLayout.DENSE_TAG: {
                UIntPtr *denseObject = (UIntPtr *)
                                       (objAddr + PostHeader.Size);
                int lastIndex =
                    unchecked ((int)getLastTracked(objAddr));
                pointerTracking >>= lastIndex + 4;
                for (denseObject += lastIndex; pointerTracking != 0 &&
                     workDone < decrementSpan; workDone++,
                     lastIndex++, denseObject++)
                {
                    if ((pointerTracking & 0x1) != 0 &&
                        *denseObject != UIntPtr.Zero)
                    {
                        decrementer.Visit(denseObject);
                    }
                    pointerTracking >>= 1;
                }
                setLastTracked(objAddr, unchecked ((uint)lastIndex));
                break;
            }

            case ObjectLayout.PTR_VECTOR_TAG: {
                uint     length      = *(uint *)(objAddr + PostHeader.Size);
                UIntPtr *elemAddress = (UIntPtr *)
                                       (objAddr + vtable.baseLength - PreHeader.Size);
                uint lastIndex = getLastTracked(objAddr);
                for (elemAddress += lastIndex; lastIndex < length &&
                     workDone < decrementSpan; workDone++,
                     lastIndex++, elemAddress++)
                {
                    if (*elemAddress != UIntPtr.Zero)
                    {
                        decrementer.Visit(elemAddress);
                    }
                }
                setLastTracked(objAddr, lastIndex);
                break;
            }

            case ObjectLayout.OTHER_VECTOR_TAG: {
                if (vtable.arrayOf == StructuralType.Struct)
                {
                    uint    length      = *(uint *)(objAddr + PostHeader.Size);
                    UIntPtr elemAddress = objAddr + vtable.baseLength -
                                          PreHeader.Size - PostHeader.Size;
                    VTable elemVTable = vtable.arrayElementClass;
                    int    elemSize   = vtable.arrayElementSize;
                    uint   lastIndex  = getLastTracked(objAddr);
                    for (elemAddress += (UIntPtr)(elemSize * lastIndex);
                         lastIndex < length &&
                         workDone < decrementSpan; workDone++,
                         lastIndex++, elemAddress += elemSize)
                    {
                        decrementer.VisitReferenceFields(elemAddress,
                                                         elemVTable);
                    }
                    setLastTracked(objAddr, lastIndex);
                }
                break;
            }

            case ObjectLayout.PTR_ARRAY_TAG: {
                uint length =
                    *(uint *)(objAddr + PostHeader.Size + sizeof(uint));
                UIntPtr *elemAddress = (UIntPtr *)
                                       (objAddr + vtable.baseLength - PreHeader.Size);
                uint lastIndex = getLastTracked(objAddr);
                for (elemAddress += lastIndex; lastIndex < length &&
                     workDone < decrementSpan; workDone++,
                     lastIndex++, elemAddress++)
                {
                    if (*elemAddress != UIntPtr.Zero)
                    {
                        decrementer.Visit(elemAddress);
                    }
                }
                setLastTracked(objAddr, lastIndex);
                break;
            }

            case ObjectLayout.OTHER_ARRAY_TAG: {
                if (vtable.arrayOf == StructuralType.Struct)
                {
                    uint length =
                        *(uint *)(objAddr +
                                  PostHeader.Size + sizeof(uint));
                    UIntPtr elemAddress = objAddr + vtable.baseLength -
                                          PreHeader.Size - PostHeader.Size;
                    VTable elemVTable = vtable.arrayElementClass;
                    int    elemSize   = vtable.arrayElementSize;
                    uint   lastIndex  = getLastTracked(objAddr);
                    for (elemAddress += (UIntPtr)(elemSize * lastIndex);
                         lastIndex < length &&
                         workDone < decrementSpan; workDone++,
                         lastIndex++, elemAddress += elemSize)
                    {
                        decrementer.VisitReferenceFields(elemAddress,
                                                         elemVTable);
                    }
                    setLastTracked(objAddr, lastIndex);
                }
                break;
            }

            case ObjectLayout.STRING_TAG: {
                break;
            }

            default: {
                VTable.Assert((objTag & 0x1) == 0,
                              @"(objTag & 0x1) == 0");

                UIntPtr *largeObject        = (UIntPtr *)objAddr;
                int *    pointerDescription =
                    (int *)vtable.pointerTrackingMask;
                int lastCount =
                    unchecked ((int)getLastTracked(objAddr));
                for (int count = *pointerDescription;
                     lastCount <= count && workDone < decrementSpan;
                     workDone++, lastCount++)
                {
                    UIntPtr *loc = largeObject +
                                   *(pointerDescription + lastCount);
                    if (*loc != UIntPtr.Zero)
                    {
                        decrementer.Visit(loc);
                    }
                }
                setLastTracked(objAddr, unchecked ((uint)lastCount));
                break;
            }
            }

            return(workDone);
        }
Exemple #24
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;
            }
        }
Exemple #25
0
 void Verify(NonNullReferenceVisitor threadReferenceVisitor,
             Thread thread)
 {
     CallStack.ScanStack(thread, threadReferenceVisitor,
                         threadReferenceVisitor);
 }
Exemple #26
0
        protected static unsafe void UpdateReferentRefCounts
            (UIntPtr objAddr,
            VTable vtable,
            int start,
            int span,
            NonNullReferenceVisitor updater)
        {
            uint pointerTracking = (uint)vtable.pointerTrackingMask;
            uint objTag          = pointerTracking & 0xf;

            switch (objTag)
            {
            case ObjectLayout.PTR_VECTOR_TAG: {
                uint length = *(uint *)(objAddr + PostHeader.Size);
                VTable.Assert(span <= length,
                              @"span <= length");

                UIntPtr *elemAddress = (UIntPtr *)(objAddr +
                                                   vtable.baseLength - PreHeader.Size) + start;
                for (int i = 0; i < span; i++, elemAddress++)
                {
                    updater.Visit(elemAddress);
                }
                break;
            }

            case ObjectLayout.OTHER_VECTOR_TAG: {
                uint length = *(uint *)(objAddr + PostHeader.Size);
                VTable.Assert(span <= length,
                              @"span <= length");

                if (vtable.arrayOf == StructuralType.Struct)
                {
                    int     elemSize    = vtable.arrayElementSize;
                    UIntPtr elemAddress = objAddr + vtable.baseLength -
                                          PreHeader.Size - PostHeader.Size + elemSize * start;
                    VTable elemVTable = vtable.arrayElementClass;
                    for (int i = 0; i < span; i++,
                         elemAddress += elemSize)
                    {
                        updater.VisitReferenceFields(elemAddress,
                                                     elemVTable);
                    }
                }
                break;
            }

            case ObjectLayout.PTR_ARRAY_TAG: {
                uint length =
                    *(uint *)(objAddr + PostHeader.Size + sizeof(uint));
                VTable.Assert(span <= length,
                              @"span <= length");

                UIntPtr *elemAddress = (UIntPtr *)
                                       (objAddr + vtable.baseLength - PreHeader.Size) + start;
                for (int i = 0; i < span; i++, elemAddress++)
                {
                    updater.Visit(elemAddress);
                }
                break;
            }

            case ObjectLayout.OTHER_ARRAY_TAG: {
                uint length =
                    *(uint *)(objAddr + PostHeader.Size + sizeof(uint));
                VTable.Assert(span <= length,
                              @"span <= length");

                if (vtable.arrayOf == StructuralType.Struct)
                {
                    int     elemSize    = vtable.arrayElementSize;
                    UIntPtr elemAddress = objAddr + vtable.baseLength -
                                          PreHeader.Size - PostHeader.Size + elemSize * start;
                    VTable elemVTable = vtable.arrayElementClass;
                    for (int i = 0; i < span; i++,
                         elemAddress += elemSize)
                    {
                        updater.VisitReferenceFields(elemAddress,
                                                     elemVTable);
                    }
                }
                break;
            }

            case ObjectLayout.STRING_TAG: {
                break;
            }

            default: {
                VTable.NotReached("An unsupported tag found!");
                break;
            }
            }
        }
Exemple #27
0
 internal abstract bool Scan(NonNullReferenceVisitor visitor);
Exemple #28
0
        bool WalkStackFrame(ref UIntPtr *framePointer,
                            ref UIntPtr *stackPointer,
                            ref CalleeSaveLocations calleeSaves,
                            ref UIntPtr returnAddr,
                            NonNullReferenceVisitor threadReferenceVisitor,
                            NonNullReferenceVisitor pinnedReferenceVisitor,
                            CompressedFrameDescriptor smallFrameDescriptor,
                            TransitionRecord *stopMarker,
                            Thread thread)
        // BUGBUG: Remove thread argument when ThreadContext is on stack!
        {
            FrameDescriptor frameDescriptor =
                new FrameDescriptor(smallFrameDescriptor);

            if (frameDescriptor.isFramePointerOmitted)
            {
                framePointer = stackPointer + frameDescriptor.frameSize;
            }
            if (FrameContainsTransitionRecord(framePointer, stackPointer,
                                              stopMarker))
            {
                return(true);    // true: done
            }
            switch (frameDescriptor.argumentTag)
            {
            case FrameDescriptor.ESCAPE32_TAG: {
                int *table       = (int *)frameDescriptor.argumentMaskOrTable;
                int  count       = table[0];
                int  pinnedCount = table[1];
                int *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.ESCAPE16_TAG: {
                short *table       = (short *)frameDescriptor.argumentMaskOrTable;
                int    count       = table[0];
                int    pinnedCount = table[1];
                short *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.ESCAPE8_TAG: {
                sbyte *table       = (sbyte *)frameDescriptor.argumentMaskOrTable;
                int    count       = table[0];
                int    pinnedCount = table[1];
                sbyte *offsets     = &table[2];
                if (threadReferenceVisitor != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(loc);
                            VisitIfNotContext(thread, threadReferenceVisitor, loc);
                        }
                    }
                }
                if (frameDescriptor.hasPinnedVariables &&
                    pinnedReferenceVisitor != null)
                {
                    offsets = &offsets[count];
                    for (int i = 0; i < pinnedCount; i++)
                    {
                        UIntPtr *loc = framePointer + offsets[i];
                        if (*loc != UIntPtr.Zero)
                        {
                            pinnedReferenceVisitor.Visit(loc);
                        }
                    }
                }
                break;
            }

            case FrameDescriptor.COMPRESSED_MASK_TAG: {
                // Process the arguments
                int inBetweenSlotsAbove =
                    frameDescriptor.inBetweenSlotsAbove;
                uint    stackArgSize = frameDescriptor.argumentCount;
                UIntPtr mask         = frameDescriptor.argumentMaskOrTable;
                if (threadReferenceVisitor != null && stackArgSize > 0)
                {
                    UIntPtr *argumentPointer =
                        framePointer + stackArgSize - 1 + inBetweenSlotsAbove;
                    for (int i = 0; mask != 0 && i < stackArgSize; i++)
                    {
                        if ((mask & 0x1) != 0 &&
                            *argumentPointer != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(p);
                            VisitIfNotContext(thread, threadReferenceVisitor,
                                              argumentPointer);
                        }
                        mask >>= 1;
                        argumentPointer--;
                    }
                }
                else
                {
                    for (int i = 0; mask != 0 && i < stackArgSize; i++)
                    {
                        mask >>= 1;
                    }
                }
                // Process the local variables
                if (threadReferenceVisitor != null)
                {
                    int transitionRecordSize =
                        frameDescriptor.hasTransitionRecord ?
                        sizeof(TransitionRecord) / sizeof(UIntPtr) :
                        0;
                    int registerCount =
                        CountBits(frameDescriptor.calleeSaveMask);
                    int inBetweenSlotsBelow =
                        frameDescriptor.inBetweenSlotsBelow;
                    UIntPtr *variablePtr =
                        framePointer - inBetweenSlotsBelow - registerCount
                        - transitionRecordSize - 1;    // -1 because FP is pointing in "above" region.
                    while (mask != UIntPtr.Zero)
                    {
                        if ((mask & 0x1) != 0 &&
                            *variablePtr != UIntPtr.Zero)
                        {
                            // BUGBUG: threadReferenceVisitor.Visit(p);
                            VisitIfNotContext(thread, threadReferenceVisitor,
                                              variablePtr);
                        }
                        mask >>= 1;
                        variablePtr--;
                    }
                }
                break;
            }

            default: {
                VTable.NotReached("FrameDescriptor mask switch failed");
                break;
            }
            }
            if (frameDescriptor.calleeSaveValueMask != 0 &&
                threadReferenceVisitor != null)
            {
                calleeSaves.ScanLiveRegs(frameDescriptor.calleeSaveValueMask,
                                         threadReferenceVisitor);
            }

#if X86 || AMD64 || ISA_IX86 || ISA_IX64
            UIntPtr nextReturnAddr;
            if (frameDescriptor.isFramePointerOmitted)
            {
                nextReturnAddr = *framePointer;
                stackPointer   = framePointer + 1;
            }
            else
            {
                nextReturnAddr = *(framePointer + 1);
                stackPointer   = framePointer + 2;
            }
#elif ARM || ISA_ARM
            // CompressedFrameDescriptor is the target specific portion.
            // This will be refactored to FrameDescriptor via partial classes.
            UIntPtr nextReturnAddr = CompressedFrameDescriptor.NextCallSite(frameDescriptor.isFramePointerOmitted, framePointer, out stackPointer);
#else
#error Unknown Architecture
#endif

            // In Singularity, the final return address of a thread is zero
            if (nextReturnAddr != UIntPtr.Zero)
            {
                calleeSaves.PopFrame(framePointer,
                                     frameDescriptor.calleeSaveMask,
                                     frameDescriptor.isFramePointerOmitted,
                                     frameDescriptor.hasTransitionRecord);
            }
            else
            {
                calleeSaves.ClearFrame(frameDescriptor.calleeSaveMask,
                                       frameDescriptor.isFramePointerOmitted);
            }
            UIntPtr *calcedfp = (UIntPtr *)calleeSaves.GetFramePointer();
            if (calcedfp != null)
            {
                framePointer = calcedfp;
            }
            returnAddr = nextReturnAddr;
            return(false); // false: not done scanning: proceed to next frame
        }
Exemple #29
0
        uint ScanStackSegment(ref CalleeSaveLocations calleeSaves,
                              UIntPtr returnAddr,
                              UIntPtr *fp,
                              UIntPtr *sp,
                              TransitionRecord *stopMarker,
                              NonNullReferenceVisitor VisitThreadReference,
                              NonNullReferenceVisitor VisitPinnedReference,
                              Thread thread)
        // BUGBUG: Remove thread argument when ThreadContext is on stack!
        {
            uint numStackFrames = 0;

            while (true)
            {
#if SINGULARITY
                if (returnAddr >= LinkStackFunctionsBegin &&
                    returnAddr <= LinkStackFunctionsLimit)
                {
                    if (returnAddr >= LinkStackBegin &&
                        returnAddr <= LinkStackLimit)
                    {
                        returnAddr = SkipLinkStackFrame(ref fp, ref sp);
                    }
                    else if (returnAddr >= UnlinkStackBegin &&
                             returnAddr <= UnlinkStackLimit)
                    {
                        returnAddr = SkipUnlinkStackFrame(ref fp, ref sp);
                    }
                    else if (returnAddr >= LinkStackStubsBegin &&
                             returnAddr <= LinkStackStubsLimit)
                    {
                        returnAddr = SkipLinkStackStubFrame(ref fp, ref sp);
                    }
                    else
                    {
                        VTable.NotReached("Unexpected link stack function");
                    }
                }
#endif

                // Exit loop if we have reached the of the stack segment
                if (fp >= stopMarker && sp < stopMarker)
                {
                    break;
                }
                int tableIndex = CallSiteTableNumber(returnAddr);
                if (tableIndex < 0)
                {
                    break;
                }
                int callSiteSet = CallSiteSetNumber(returnAddr, tableIndex);
                if (callSiteSet < 0)
                {
                    break;
                }
                ushort *callSiteToIndexTable =
                    callSetSiteNumberToIndex[tableIndex];
                int activationIndex = (int)callSiteToIndexTable[callSiteSet];
                VTable.Assert(activationIndex >= 0);
                CompressedFrameDescriptor *descriptorTable =
                    activationDescriptorTable[tableIndex];
                CompressedFrameDescriptor frameDescriptor =
                    descriptorTable[activationIndex];
                bool done = WalkStackFrame(ref fp, ref sp, ref calleeSaves,
                                           ref returnAddr,
                                           VisitThreadReference,
                                           VisitPinnedReference,
                                           frameDescriptor,
                                           stopMarker, thread);
                if (done)
                {
                    break;
                }
                numStackFrames++;
            }
            calleeSaves.ClearCalleeSaves();
            return(numStackFrames);
        }
Exemple #30
0
 void VisitIfNotContext(Thread thread,
                        NonNullReferenceVisitor threadReferenceVisitor,
                        UIntPtr *p)
 {
     threadReferenceVisitor.Visit(p);
 }