Exemple #1
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
        }