Beispiel #1
0
        internal static void Initialize()
        {
            switch (ptType)
            {
            case PTType.CentralPT: {
                CentralPT.Initialize();
                break;
            }

            case PTType.CentralPTHimem: {
                CentralPTHimem.Initialize();
                break;
            }

            case PTType.FlatDistributedPT: {
                FlatDistributedPT.Initialize();
                break;
            }

            case PTType.FlatDistributedPTTest: {
                FlatDistributedPTTest.Initialize();
                break;
            }

            default: {
                VTable.NotReached("Unknown PT type: " + ptType);
                break;
            }
            }
        }
            internal unsafe override void Visit(UIntPtr *loc)
            {
                UIntPtr  addr     = *loc;
                UIntPtr  page     = PageTable.Page(addr);
                PageType pageType = PageTable.Type(page);

                if (!PageTable.IsZombiePage(pageType))
                {
                    VTable.Assert(PageTable.IsGcPage(pageType) ||
                                  PageTable.IsNonGcPage(pageType) ||
                                  PageTable.IsStackPage(pageType) ||
                                  PageTable.IsSharedPage(pageType));
                    return;
                }
                UIntPtr vtableAddr = Allocator.GetObjectVTable(addr);

                // Mark object
                if (vtableAddr == UIntPtr.Zero)
                {
                    VTable.DebugPrint("Found null vtable in MarkReference (loc = 0x{0:x8}, addr = 0x{1:x8})\n",
                                      __arglist(((UIntPtr)loc), addr));
                    VTable.NotReached();
                }
                *loc = vtableAddr;
                Allocator.SetObjectVTable(addr, (UIntPtr)loc + 1);
                // If first visit to the object, schedule visit of fields
                if ((vtableAddr & 0x1) == 0)
                {
                    MarkVisit(addr, vtableAddr & (UIntPtr) ~2U);
                }
            }
Beispiel #3
0
 internal override void CheckForNeededGCWork(Thread currentThread)
 {
     if (NewBytesSinceGCExceeds((UIntPtr)1500000000))
     {
         VTable.NotReached
             ("OutOfMemory: NullCollector: Out of original memory quota");
     }
 }
        public static new void Initialize()
        {
            GenerationalCollector.Initialize();
            // copyScanners = new CopyScan[MAX_GENERATION+1];
            copyScanners = (CopyScan[])
                           BootstrapMemory.Allocate(typeof(CopyScan[]),
                                                    (uint)MAX_GENERATION + 1);
            for (int i = (int)MIN_GENERATION; i <= (int)MAX_GENERATION; i++)
            {
                switch (GC.copyscanType)
                {
                case CopyScanType.CheneyScan: {
                    copyScanners[i] = (CopyScan)
                                      BootstrapMemory.Allocate(typeof(CheneyScan));
                    break;
                }

                case CopyScanType.HierarchicalScan: {
                    copyScanners[i] = (CopyScan)
                                      BootstrapMemory.Allocate(typeof(HierarchicalScan));
                    break;
                }

                case CopyScanType.NestedHierarchicalScan: {
                    copyScanners[i] = (CopyScan)
                                      BootstrapMemory.Allocate(typeof(NestedHierarchicalScan));
                    break;
                }

                default: {
                    VTable.NotReached("Unknown CopyScan type: " +
                                      GC.copyscanType);
                    break;
                }
                }
                copyScanners[i].Initialize((PageType)i);
            }
            // SemispaceCollector.instance = new SemispaceCollector();
            SemispaceCollector.instance = (SemispaceCollector)
                                          BootstrapMemory.Allocate(typeof(SemispaceCollector));
            // generalReferenceVisitor = new ForwardReferenceVisitor();
            SemispaceCollector.generalReferenceVisitor = (ForwardReferenceVisitor)
                                                         BootstrapMemory.Allocate(typeof(ForwardReferenceVisitor));
            // threadReferenceVisitor = new ForwardThreadReference(generalReferenceVisitor);
            SemispaceCollector.threadReferenceVisitor = (ForwardThreadReference)
                                                        BootstrapMemory.Allocate(typeof(ForwardThreadReference));
            // pinnedReferenceVisitor = new RegisterPinnedReference();
            SemispaceCollector.pinnedReferenceVisitor = (RegisterPinnedReference)
                                                        BootstrapMemory.Allocate(typeof(RegisterPinnedReference));
            // forwardOnlyReferenceVisitor = new ForwardOnlyReferenceVisitor();
            SemispaceCollector.forwardOnlyReferenceVisitor = (ForwardOnlyReferenceVisitor)
                                                             BootstrapMemory.Allocate(typeof(ForwardOnlyReferenceVisitor));
        }
Beispiel #5
0
        internal static uint PageTableEntry(UIntPtr page)
        {
            switch (ptType)
            {
            case PTType.CentralPT:
            case PTType.CentralPTHimem:
                return(CentralPT.PageTableEntryImpl(page));

#if !SINGULARITY
            case PTType.FlatDistributedPT:
            case PTType.FlatDistributedPTTest:
                return(FlatDistributedPT.PageTableEntryImpl(page));
#endif
            default: {
                VTable.NotReached("Unknown PT type: " + ptType);
                return(0xffffffff);
            }
            }
        }
            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;
                }
                }
            }
Beispiel #7
0
        private static void InstallRemSet()
        {
            switch (GC.remsetType)
            {
            case RemSetType.SSB: {
                SequentialStoreBuffer.Initialize();
                installedRemSet = SequentialStoreBuffer.instance;
                break;
            }

            case RemSetType.Cards: {
                CardTable.Initialize();
                installedRemSet = CardTable.instance;
                break;
            }

            default: {
                VTable.NotReached("Unsupported remembered set: " +
                                  GC.remsetType);
                break;
            }
            }
        }
Beispiel #8
0
        internal static void SetPageTableEntry(UIntPtr page, uint value)
        {
            switch (ptType)
            {
            case PTType.CentralPT:
            case PTType.CentralPTHimem: {
                CentralPT.SetPageTableEntryImpl(page, value);
                break;
            }

#if !SINGULARITY
            case PTType.FlatDistributedPT:
            case PTType.FlatDistributedPTTest: {
                FlatDistributedPT.SetPageTableEntryImpl(page, value);
                break;
            }
#endif
            default: {
                VTable.NotReached("Unknown PT type: " + ptType);
                break;
            }
            }
        }
Beispiel #9
0
 internal override void CollectStoppable(int currentThreadIndex,
                                         int generation)
 {
     VTable.NotReached("OutOfMemory: NullCollector: Collect called");
 }
Beispiel #10
0
 static bool CopyObject(Object from)
 {
     if (fDietVerboseCopyDebug)
     {
         VTable.DebugPrint("   Copying ");
         VTable.DebugPrint((ulong)Magic.addressOf(from));
         VTable.DebugPrint(" with CoCoWord = ");
         VTable.DebugPrint((ulong)MixinObject(from).preHeader.CoCoWord);
         VTable.DebugPrint("\n");
     }
     for (;;)
     {
         UIntPtr CoCoWord = MixinObject(from).preHeader.CoCoWord;
         if (IsSimple(CoCoWord))
         {
             // got pinned .. ignore
             return(false);
         }
         else if (IsTagged(CoCoWord))
         {
             if (ShouldPin(Magic.addressOf(from)))
             {
                 if (CASCoCoWord(from, Simple(), CoCoWord))
                 {
                     // pinned
                     NotifyPin(Magic.addressOf(from));
                     return(false);
                 }
             }
             else
             {
                 CASCoCoWord(from, Copying(CoCoWord), CoCoWord);
             }
         }
         else if (IsCopying(CoCoWord))
         {
             Object  to    = Magic.fromAddress(ForwardPtr(CoCoWord));
             UIntPtr begin = UIntPtr.Zero - (UIntPtr)PreHeader.Size;
             UIntPtr end   =
                 ((ObjectLayout.Sizeof(from) + sizeof(UIntPtr) - 1)
                  & ~((UIntPtr)sizeof(UIntPtr) - 1))
                 - PreHeader.Size;
             if (fDietVerboseCopyDebug)
             {
                 VTable.DebugPrint("      copying to ");
                 VTable.DebugPrint((ulong)Magic.addressOf(to));
                 VTable.DebugPrint("; begin = ");
                 VTable.DebugPrint((ulong)begin);
                 VTable.DebugPrint("; end = ");
                 VTable.DebugPrint((ulong)end);
                 VTable.DebugPrint("; PreHeader.Size = ");
                 VTable.DebugPrint((ulong)PreHeader.Size);
                 VTable.DebugPrint("; Sizeof(from) = ");
                 VTable.DebugPrint((ulong)ObjectLayout.Sizeof(from));
                 VTable.DebugPrint("; Sizeof(to) = ");
                 VTable.DebugPrint((ulong)ObjectLayout.Sizeof(to));
                 VTable.DebugPrint("\n");
             }
             for (UIntPtr offset = begin;
                  offset != end;
                  offset += sizeof(UIntPtr))
             {
                 if (!IgnoreOffset(offset))
                 {
                     UIntPtr *fptr = (UIntPtr *)(Magic.addressOf(from) + offset);
                     UIntPtr *tptr = (UIntPtr *)(Magic.addressOf(to) + offset);
                     for (;;)
                     {
                         UIntPtr word = *fptr;
                         if (word == Alpha)
                         {
                             // NOTE: this case will only be hit the first time
                             // around the loop.  if it's not hit the first time
                             // it'll never get hit.
                             break;
                         }
                         *tptr = word;
                         if (InternalImmutableOffset(from, offset) ||
                             CAS(fptr, Alpha, word) == word)
                         {
                             break;
                         }
                     }
                 }
             }
             MixinObject(from).preHeader.CoCoWord = Forwarded(CoCoWord);
             return(true);
         }
         else
         {
             VTable.NotReached();
         }
     }
 }
Beispiel #11
0
        internal static void ChangePhase(Phase phase_,
                                         bool forwarding_,
                                         bool pinning_)
        {
            if (fDebug)
            {
                VTable.DebugPrint("    --> CoCo going to ");
                switch (phase_)
                {
                case Phase.Idle: VTable.DebugPrint("Idle"); break;

                case Phase.Prep: VTable.DebugPrint("Prep"); break;

                case Phase.Copy: VTable.DebugPrint("Copy"); break;

                case Phase.Fixup: VTable.DebugPrint("Fixup"); break;

                default: VTable.NotReached(); break;
                }
                VTable.DebugPrint(" (with");
                if (!forwarding_)
                {
                    VTable.DebugPrint("out");
                }
                VTable.DebugPrint(" forwarding, with");
                if (!pinning_)
                {
                    VTable.DebugPrint("out");
                }
                VTable.DebugPrint(" pinning)\n");
            }
            lock (interlock) {
                phase      = phase_;
                forwarding = forwarding_ || forceForwarding;
                pinning    = pinning_ || forcePinning;
                SetAllowFastPath();
                isNotIdle = phase != Phase.Idle || forceNotIdle;
                CoCoThread t = MixinThread(Thread.CurrentThread);
                t.acknowledgedPhase      = (int)phase;
                t.acknowledgedForwarding = forwarding;
                t.acknowledgedPinning    = pinning;
                t.phaseVersion++;
                Monitor.PulseAll(interlock);
                for (;;)
                {
                    bool needToWait = false;
                    bool doPulseAll = false;
                    for (int i = 0; i < Thread.threadTable.Length; ++i)
                    {
                        Thread t_ = Thread.threadTable[i];
                        if (t_ == null)
                        {
                            continue;
                        }
                        t = MixinThread(t_);
                        if (Transitions.InDormantState(i) ||
                            !t.readyForCoCo ||
                            t.pinnedOut)
                        {
                            t.acknowledgedPhase      = (int)phase;
                            t.acknowledgedForwarding = forwarding;
                            t.acknowledgedPinning    = pinning;
                        }
                        if (t.pinnedOut && phase == Phase.Idle)
                        {
                            t.pinnedOut = false;
                            doPulseAll  = true;
                        }
                        if ((Phase)t.acknowledgedPhase != phase ||
                            t.acknowledgedForwarding != forwarding ||
                            t.acknowledgedPinning != pinning)
                        {
                            if (fDebug)
                            {
                                VTable.DebugPrint("         !! thread ");
                                VTable.DebugPrint((ulong)Magic.addressOf(t));
                                VTable.DebugPrint(" not ack\n");
                            }
                            needToWait = true;
                        }
                    }
                    if (doPulseAll)
                    {
                        Monitor.PulseAll(interlock);
                    }
                    if (!needToWait)
                    {
                        break;
                    }
                    // REVIEW: make the timeout less than 500 ms
                    Monitor.Wait(interlock, 500);
                }
            }
        }
        internal static void ReportHeapDetails()
        {
            VTable.DebugPrint("\nHeap details:\n");
            uint pageCount = 0;

            for (UIntPtr i = UIntPtr.Zero; i < PageTable.pageTableCount;
                 i++)
            {
                if (PageTable.IsMyGcPage(i))
                {
                    pageCount++;
                }
            }
            VTable.DebugPrint("\tTotal number of heap pages: {0}",
                              __arglist(pageCount));

            // The following obtains counts of heap objects against types.
            UIntPtr lowPage  = UIntPtr.Zero;
            UIntPtr highPage = PageTable.pageTableCount;

            assertRuntimeTypeHeaders(lowPage, highPage);

            // First count the RuntimeType instances for heap objects.
            runtimeTypeReckoner.Initialize(true);
            visitAllObjects(forGCRuntimeTypeReckoner, lowPage, highPage);

            // Next, create a table for RuntimeType instance accounting.
            // NOTE: Storage for the table is marked "non-GC". Since
            // static data accounting is done before this, it's okay.
            int numSlots = runtimeTypeReckoner.Count;

            if (numSlots > TABLE_SIZE)
            {
                VTable.DebugPrint("Need {0} slots, have {1}\n",
                                  __arglist(numSlots, TABLE_SIZE));
                VTable.NotReached("MemoryAccounting table not large enough");
            }

            // Associate a table slot for each RuntimeType instance.
            runtimeTypeMapper.Initialize(false, MemoryAccounting.table);
            visitAllObjects(forGCRuntimeTypeMapper, lowPage, highPage);

            // Map each relevant RuntimeType instance to its table slot.
            for (uint i = 0; i < numSlots; i++)
            {
                RuntimeType rType = MemoryAccounting.table[i].RuntimeTypeObject;
                VTable.Assert(!MultiUseWord.IsMarked(rType),
                              @"!MultiUseWord.IsMarked(rType)");
                MemoryAccounting.table[i].SavedMUW =
                    MultiUseWord.GetForObject(rType);
                MultiUseWord.SetValForObject(rType, (UIntPtr)i);
            }

            // Count heap object instances by RuntimeType using table.
            instanceReckoner.Initialize(MemoryAccounting.table);
            visitAllObjects(forGCInstanceReckoner, lowPage, highPage);

            // Bubble sort the table in decreasing order of total size.
            for (int i = 0; i < numSlots; i++)
            {
                for (int j = numSlots - 1; j > i; j--)
                {
                    if (MemoryAccounting.table[j].TotalSize
                        > MemoryAccounting.table[j - 1].TotalSize)
                    {
                        // Swap contents.
                        RuntimeTypeAccounting temp = MemoryAccounting.table[j];
                        MemoryAccounting.table[j]     = MemoryAccounting.table[j - 1];
                        MemoryAccounting.table[j - 1] = temp;
                    }
                }
            }

            // Display table.
            VTable.DebugPrint("\n\tCounts of objects against types:\n");
            for (uint i = 0; i < numSlots; i++)
            {
                if ((uint)MemoryAccounting.table[i].TotalSize < 1024)
                {
                    continue;
                }
                VTable.DebugPrint
                    ("\t\t{0,36} instances: {1,6}, bytes: {2,10}\n",
                    __arglist(MemoryAccounting.table[i].RuntimeTypeObject.Name,
                              (uint)MemoryAccounting.table[i].Count,
                              (uint)MemoryAccounting.table[i].TotalSize));
            }

            // Reset book-keeping information maintained in headers and the global
            // table.
            for (uint i = 0; i < numSlots; i++)
            {
                RuntimeType rType = MemoryAccounting.table[i].RuntimeTypeObject;
                MultiUseWord.SetForObject
                    (rType, MemoryAccounting.table[i].SavedMUW);
                VTable.Assert(!MultiUseWord.IsMarked(rType),
                              "@!MultiUseWord.IsMarked(rType)");

                MemoryAccounting.table[i].RuntimeTypeObject = null;
                MemoryAccounting.table[i].SavedMUW          =
                    new MultiUseWord(new UIntPtr(0));
                MemoryAccounting.table[i].TotalSize = new UIntPtr(0);
                MemoryAccounting.table[i].Count     = 0;
            }
        }
        internal unsafe static void Report(GCType gcType)
        {
            if (!MemoryAccounting.initialized)
            {
                VTable.DebugPrint("MemoryAccounting invoked before"
                                  + " initialization was completed!\n");
                return;
            }

            VTable.DebugPrint("\nCollector: ");
            switch (gcType)
            {
            case GCType.AdaptiveCopyingCollector: {
                VTable.DebugPrint("Adaptive Copying\n");
                break;
            }

            case GCType.MarkSweepCollector: {
                VTable.DebugPrint("Mark-Sweep\n");
                break;
            }

            case GCType.SemispaceCollector: {
                VTable.DebugPrint("Semispace\n");
                break;
            }

            case GCType.SlidingCollector: {
                VTable.DebugPrint("Sliding\n");
                break;
            }

            case GCType.ConcurrentMSCollector: {
                VTable.DebugPrint("Concurrent Mark-Sweep\n");
                break;
            }

            case GCType.ReferenceCountingCollector: {
                VTable.DebugPrint("Reference Counting\n");
                VTable.NotImplemented();
                return;   // Not supported yet.
            }

#if !SINGULARITY
            case GCType.DeferredReferenceCountingCollector: {
                VTable.DebugPrint("Deferred Reference Counting\n");
                VTable.NotImplemented();
                return;   // Not supported yet.
            }
#endif
            default: {
                VTable.NotReached("Unknown GC type: " + gcType);
                break;
            }
            }

            uint pageSize = (uint)(PageTable.PageSize >> 10);
            VTable.DebugPrint("\nPage size: {0}KB\nVM size: {1} KB\n",
                              __arglist(pageSize,
                                        pageSize * (uint)PageTable.pageTableCount));

            ReportNonGCDetails();
            ReportStackDetails();
            ReportHeapDetails();
        }
Beispiel #14
0
 internal override UIntPtr FindObjectAddr(UIntPtr interiorPtr)
 {
     VTable.NotReached
         ("OutOfMemory: NullCollector: FindObjectAddr called");
     return(UIntPtr.Zero);
 }
Beispiel #15
0
 internal override int CollectionGeneration(int gen)
 {
     VTable.NotReached
         ("OutOfMemory: NullCollector: CollectionGeneration called");
     return(MinGeneration);
 }
Beispiel #16
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
        }
Beispiel #17
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);
        }
Beispiel #18
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;
            }
            }
        }