예제 #1
0
        /// <summary>
        /// Fill in the GC-relevant stack frame locations.
        /// </summary>
        private void FakeGcScanRoots(MethodDesc method, ArgIterator argit, CORCOMPILE_GCREFMAP_TOKENS[] frame)
        {
            // Encode generic instantiation arg
            if (argit.HasParamType)
            {
                if (method.RequiresInstMethodDescArg())
                {
                    frame[argit.GetParamTypeArgOffset()] = CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_METHOD_PARAM;
                }
                else if (method.RequiresInstMethodTableArg())
                {
                    frame[argit.GetParamTypeArgOffset()] = CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_TYPE_PARAM;
                }
            }

            // If the function has a this pointer, add it to the mask
            if (argit.HasThis)
            {
                bool isUnboxingStub = false; // TODO: is this correct?
                bool interior       = method.OwningType.IsValueType && !isUnboxingStub;

                frame[_transitionBlock.ThisOffset] = (interior ? CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_INTERIOR : CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_REF);
            }

            if (argit.IsVarArg)
            {
                frame[argit.GetVASigCookieOffset()] = CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_VASIG_COOKIE;

                // We are done for varargs - the remaining arguments are reported via vasig cookie
                return;
            }

            // Also if the method has a return buffer, then it is the first argument, and could be an interior ref,
            // so always promote it.
            if (argit.HasRetBuffArg())
            {
                frame[_transitionBlock.GetRetBuffArgOffset(argit.HasThis)] = CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_INTERIOR;
            }

            //
            // Now iterate the arguments
            //

            // Cycle through the arguments, and call GcScanRoots for each
            int argIndex = 0;
            int argOffset;

            while ((argOffset = argit.GetNextOffset()) != TransitionBlock.InvalidOffset)
            {
                ArgLocDesc?    argLocDescForStructInRegs = argit.GetArgLoc(argOffset);
                ArgDestination argDest = new ArgDestination(_transitionBlock, argOffset, argLocDescForStructInRegs);
                GcScanRoots(method.Signature[argIndex], in argDest, delta: 0, frame);
                argIndex++;
            }
        }