예제 #1
0
 public GCRefMapEntry(int offset, CORCOMPILE_GCREFMAP_TOKENS token)
 {
     Offset = offset;
     Token  = token;
 }
예제 #2
0
        public void GetCallRefMap(MethodDesc method)
        {
            TransitionBlock transitionBlock = TransitionBlock.FromTarget(method.Context.Target);

            bool       hasThis    = (method.Signature.Flags & MethodSignatureFlags.Static) == 0;
            bool       isVarArg   = false;
            TypeHandle returnType = new TypeHandle(method.Signature.ReturnType);

            TypeHandle[] parameterTypes = new TypeHandle[method.Signature.Length];
            for (int parameterIndex = 0; parameterIndex < parameterTypes.Length; parameterIndex++)
            {
                parameterTypes[parameterIndex] = new TypeHandle(method.Signature[parameterIndex]);
            }
            CallingConventions callingConventions = (hasThis ? CallingConventions.ManagedInstance : CallingConventions.ManagedStatic);
            bool hasParamType            = method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg();
            bool extraFunctionPointerArg = false;

            bool[]          forcedByRefParams   = new bool[parameterTypes.Length];
            bool            skipFirstArg        = false;
            bool            extraObjectFirstArg = false;
            ArgIteratorData argIteratorData     = new ArgIteratorData(hasThis, isVarArg, parameterTypes, returnType);

            ArgIterator argit = new ArgIterator(
                method.Context,
                argIteratorData,
                callingConventions,
                hasParamType,
                extraFunctionPointerArg,
                forcedByRefParams,
                skipFirstArg,
                extraObjectFirstArg);

            int nStackBytes = argit.SizeOfFrameArgumentArray();

            // Allocate a fake stack
            CORCOMPILE_GCREFMAP_TOKENS[] fakeStack = new CORCOMPILE_GCREFMAP_TOKENS[transitionBlock.SizeOfTransitionBlock + nStackBytes];

            // Fill it in
            FakeGcScanRoots(method, argit, fakeStack);

            // Encode the ref map
            uint nStackSlots;

            if (_factory.Target.Architecture == TargetArchitecture.X86)
            {
                uint cbStackPop = argit.CbStackPop();
                WriteStackPop(cbStackPop / (uint)_factory.Target.PointerSize);

                nStackSlots = (uint)(nStackBytes / _factory.Target.PointerSize + _transitionBlock.NumArgumentRegisters);
            }
            else
            {
                nStackSlots = (uint)((transitionBlock.SizeOfTransitionBlock + nStackBytes - _transitionBlock.OffsetOfFirstGCRefMapSlot) / _factory.Target.PointerSize);
            }

            for (uint pos = 0; pos < nStackSlots; pos++)
            {
                int ofs;

                if (_factory.Target.Architecture == TargetArchitecture.X86)
                {
                    ofs = (int)(pos < _transitionBlock.NumArgumentRegisters ?
                                _transitionBlock.OffsetOfArgumentRegisters + _transitionBlock.SizeOfArgumentRegisters - (pos + 1) * _factory.Target.PointerSize :
                                _transitionBlock.OffsetOfArgs + (pos - _transitionBlock.NumArgumentRegisters) * _factory.Target.PointerSize);
                }
                else
                {
                    ofs = (int)(_transitionBlock.OffsetOfFirstGCRefMapSlot + pos * _factory.Target.PointerSize);
                }

                CORCOMPILE_GCREFMAP_TOKENS token = fakeStack[ofs];

                if (token != CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_SKIP)
                {
                    WriteToken(pos, (byte)token);
                }
            }

            Flush();
        }
예제 #3
0
        public void GetCallRefMap(MethodDesc method, bool isUnboxingStub)
        {
            TransitionBlock transitionBlock = TransitionBlock.FromTarget(method.Context.Target);

            MethodSignature signature = method.Signature;

            bool hasThis = (signature.Flags & MethodSignatureFlags.Static) == 0;

            // This pointer is omitted for string constructors
            bool fCtorOfVariableSizedObject = hasThis && method.OwningType.IsString && method.IsConstructor;

            if (fCtorOfVariableSizedObject)
            {
                hasThis = false;
            }

            bool       isVarArg   = false;
            TypeHandle returnType = new TypeHandle(signature.ReturnType);

            TypeHandle[] parameterTypes = new TypeHandle[signature.Length];
            for (int parameterIndex = 0; parameterIndex < parameterTypes.Length; parameterIndex++)
            {
                parameterTypes[parameterIndex] = new TypeHandle(signature[parameterIndex]);
            }
            CallingConventions callingConventions = (hasThis ? CallingConventions.ManagedInstance : CallingConventions.ManagedStatic);
            bool hasParamType = method.RequiresInstArg() && !isUnboxingStub;

            // On X86 the Array address method doesn't use IL stubs, and instead has a custom calling convention
            if ((method.Context.Target.Architecture == TargetArchitecture.X86) &&
                method.IsArrayAddressMethod())
            {
                hasParamType = true;
            }

            bool extraFunctionPointerArg = false;

            bool[]          forcedByRefParams   = new bool[parameterTypes.Length];
            bool            skipFirstArg        = false;
            bool            extraObjectFirstArg = false;
            ArgIteratorData argIteratorData     = new ArgIteratorData(hasThis, isVarArg, parameterTypes, returnType);

            ArgIterator argit = new ArgIterator(
                method.Context,
                argIteratorData,
                callingConventions,
                hasParamType,
                extraFunctionPointerArg,
                forcedByRefParams,
                skipFirstArg,
                extraObjectFirstArg);

            int nStackBytes = argit.SizeOfFrameArgumentArray();

            // Allocate a fake stack
            CORCOMPILE_GCREFMAP_TOKENS[] fakeStack = new CORCOMPILE_GCREFMAP_TOKENS[transitionBlock.SizeOfTransitionBlock + nStackBytes];

            // Fill it in
            FakeGcScanRoots(method, argit, fakeStack, isUnboxingStub);

            // Encode the ref map
            uint nStackSlots;

            if (_target.Architecture == TargetArchitecture.X86)
            {
                uint cbStackPop = argit.CbStackPop();
                WriteStackPop(cbStackPop / (uint)_target.PointerSize);

                nStackSlots = (uint)(nStackBytes / _target.PointerSize + _transitionBlock.NumArgumentRegisters);
            }
            else
            {
                nStackSlots = (uint)((transitionBlock.SizeOfTransitionBlock + nStackBytes - _transitionBlock.OffsetOfFirstGCRefMapSlot) / _target.PointerSize);
            }

            for (uint pos = 0; pos < nStackSlots; pos++)
            {
                int offset = _transitionBlock.OffsetFromGCRefMapPos(checked ((int)pos));
                CORCOMPILE_GCREFMAP_TOKENS token = fakeStack[offset];

                if (token != CORCOMPILE_GCREFMAP_TOKENS.GCREFMAP_SKIP)
                {
                    WriteToken(pos, (byte)token);
                }
            }

            Flush();
        }