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);
                 }
             }
         }
     }
 }
Example #2
0
 private static void VisitIfNotContext(Thread thread,
     NonNullReferenceVisitor threadReferenceVisitor,
     UIntPtr *p)
 {
     if (*p != (UIntPtr) thread.context &&
         (int *) *p != &thread.context->gcStates) {
         threadReferenceVisitor.Visit(p);
     }
 }
Example #3
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);
        }
Example #4
0
        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);
        }
Example #5
0
            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;
                }
                }
            }
Example #6
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);
        }
Example #7
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;
            }
            }
        }
Example #8
0
 void VisitIfNotContext(Thread thread,
                        NonNullReferenceVisitor threadReferenceVisitor,
                        UIntPtr *p)
 {
     threadReferenceVisitor.Visit(p);
 }
Example #9
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
        }