Пример #1
0
        public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, string logFile)
            : base(group, typeSystemContext, new BlockedInternalsBlockingPolicy())
        {
            _metadataLogFile = logFile;

            if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext))
            {
                _dynamicInvokeThunks = new Dictionary <DynamicInvokeMethodSignature, MethodDesc>();
            }
        }
Пример #2
0
        public GeneratingMetadataManager(ModuleDesc generatedAssembly, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy)
            : base(typeSystemContext, blockingPolicy)
        {
            _metadataLogFile          = logFile;
            _stackTraceEmissionPolicy = stackTracePolicy;
            _generatedAssembly        = generatedAssembly;

            if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext))
            {
                _dynamicInvokeThunks = new Dictionary <DynamicInvokeMethodSignature, MethodDesc>();
            }
        }
        /// <summary>
        /// Gets a stub that can be used to reflection-invoke a method with a given signature.
        /// </summary>
        public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
        {
            TypeSystemContext context = method.Context;
            var sig = method.Signature;

            // Get a generic method that can be used to invoke method with this shape.
            MethodDesc thunk;
            var lookupSig = new DynamicInvokeMethodSignature(sig);
            if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
            {
                thunk = new DynamicInvokeMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), lookupSig);
                _dynamicInvokeThunks.Add(lookupSig, thunk);
            }

            return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method);
        }
Пример #4
0
 public static bool SupportsDynamicInvoke(TypeSystemContext context)
 {
     return(DynamicInvokeMethodThunk.SupportsDynamicInvoke(context));
 }
Пример #5
0
        /// <summary>
        /// Gets a stub that can be used to reflection-invoke a method with a given signature.
        /// </summary>
        public MethodDesc GetReflectionInvokeStub(MethodDesc method)
        {
            // Methods we see here shouldn't be canonicalized, or we'll end up creating bastardized instantiations
            // (e.g. we instantiate over System.Object below.)
            Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any));

            TypeSystemContext context = method.Context;
            var sig = method.Signature;

            ParameterMetadata[] paramMetadata = null;

            // Get a generic method that can be used to invoke method with this shape.
            MethodDesc thunk;
            var        lookupSig = new DynamicInvokeMethodSignature(sig);

            if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
            {
                thunk = new DynamicInvokeMethodThunk(_nodeFactory.CompilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), lookupSig);
                _dynamicInvokeThunks.Add(lookupSig, thunk);
            }

            // If the method has no parameters and returns void, we don't need to specialize
            if (sig.ReturnType.IsVoid && sig.Length == 0)
            {
                Debug.Assert(!thunk.HasInstantiation);
                return(thunk);
            }

            //
            // Instantiate the generic thunk over the parameters and the return type of the target method
            //

            TypeDesc[] instantiation = new TypeDesc[sig.ReturnType.IsVoid ? sig.Length : sig.Length + 1];
            Debug.Assert(thunk.Instantiation.Length == instantiation.Length);
            for (int i = 0; i < sig.Length; i++)
            {
                TypeDesc parameterType = sig[i];
                if (parameterType.IsByRef)
                {
                    // strip ByRefType off the parameter (the method already has ByRef in the signature)
                    parameterType = ((ByRefType)parameterType).ParameterType;
                }

                if (parameterType.IsPointer || parameterType.IsFunctionPointer)
                {
                    // For pointer typed parameters, instantiate the method over IntPtr
                    parameterType = context.GetWellKnownType(WellKnownType.IntPtr);
                }
                else if (parameterType.IsEnum)
                {
                    // If the invoke method takes an enum as an input parameter and there is no default value for
                    // that paramter, we don't need to specialize on the exact enum type (we only need to specialize
                    // on the underlying integral type of the enum.)
                    if (paramMetadata == null)
                    {
                        paramMetadata = method.GetParameterMetadata();
                    }

                    bool hasDefaultValue = false;
                    foreach (var p in paramMetadata)
                    {
                        // Parameter metadata indexes are 1-based (0 is reserved for return "parameter")
                        if (p.Index == (i + 1) && p.HasDefault)
                        {
                            hasDefaultValue = true;
                            break;
                        }
                    }

                    if (!hasDefaultValue)
                    {
                        parameterType = parameterType.UnderlyingType;
                    }
                }

                instantiation[i] = parameterType;
            }

            if (!sig.ReturnType.IsVoid)
            {
                TypeDesc returnType = sig.ReturnType;
                Debug.Assert(!returnType.IsByRef);

                // If the invoke method return an object reference, we don't need to specialize on the
                // exact type of the object reference, as the behavior is not different.
                if ((returnType.IsDefType && !returnType.IsValueType) || returnType.IsArray)
                {
                    returnType = context.GetWellKnownType(WellKnownType.Object);
                }

                instantiation[sig.Length] = returnType;
            }

            return(context.GetInstantiatedMethod(thunk, new Instantiation(instantiation)));
        }
Пример #6
0
        /// <summary>
        /// Gets a stub that can be used to reflection-invoke a method with a given signature.
        /// </summary>
        public MethodDesc GetReflectionInvokeStub(MethodDesc method)
        {
            // Methods we see here shouldn't be canonicalized, or we'll end up creating bastardized instantiations
            // (e.g. we instantiate over System.Object below.)
            Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any));

            TypeSystemContext context = method.Context;
            var sig = method.Signature;

            // Get a generic method that can be used to invoke method with this shape.
            MethodDesc thunk;
            var        lookupSig = new DynamicInvokeMethodSignature(sig);

            if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
            {
                // TODO: figure out a better owning type (for multifile)
                thunk = new DynamicInvokeMethodThunk(context.SystemModule.GetGlobalModuleType(), lookupSig);
                _dynamicInvokeThunks.Add(lookupSig, thunk);
            }

            // If the method has no parameters and returns void, we don't need to specialize
            if (sig.ReturnType.IsVoid && sig.Length == 0)
            {
                Debug.Assert(!thunk.HasInstantiation);
                return(thunk);
            }

            //
            // Instantiate the generic thunk over the parameters and the return type of the target method
            //

            TypeDesc[] instantiation = new TypeDesc[sig.ReturnType.IsVoid ? sig.Length : sig.Length + 1];
            Debug.Assert(thunk.Instantiation.Length == instantiation.Length);
            for (int i = 0; i < sig.Length; i++)
            {
                TypeDesc parameterType = sig[i];
                if (parameterType.IsByRef)
                {
                    // strip ByRefType off the parameter (the method already has ByRef in the signature)
                    parameterType = ((ByRefType)parameterType).ParameterType;
                }

                if (parameterType.IsPointer || parameterType.IsFunctionPointer)
                {
                    // For pointer typed parameters, instantiate the method over IntPtr
                    parameterType = context.GetWellKnownType(WellKnownType.IntPtr);
                }
                else if (parameterType.IsDefType)
                {
                    // TODO: optimize enum types with no default value
                    // DefType* paramDefType = parameterType->as<DefType> ();
                    // // If the invoke method takes an enum as an input paramter and there is no default value for
                    // // that paramter, we don't need to specialize on the exact enum type (we only need to specialize
                    // // on the underlying integral type of the enum.)
                    // if (paramDefType && (!IsPdHasDefault(methodToInvoke->Parameters()[index].Attributes())) && paramDefType->IsEnum())
                    // {
                    //     CorElementType underlyingElemType = paramDefType->InternalElementType();
                    //     parameterType = paramDefType->GetLoaderContext()->GetElementType(underlyingElemType);
                    // }
                }

                instantiation[i] = parameterType;
            }

            if (!sig.ReturnType.IsVoid)
            {
                TypeDesc returnType = sig.ReturnType;
                Debug.Assert(!returnType.IsByRef);

                // If the invoke method return an object reference, we don't need to specialize on the
                // exact type of the object reference, as the behavior is not different.
                if ((returnType.IsDefType && !returnType.IsValueType) || returnType.IsArray)
                {
                    returnType = context.GetWellKnownType(WellKnownType.Object);
                }

                instantiation[sig.Length] = returnType;
            }

            return(context.GetInstantiatedMethod(thunk, new Instantiation(instantiation)));
        }
        internal DelegateThunkCollection(DelegateInfo owningDelegate)
        {
            _openStaticThunk           = new DelegateInvokeOpenStaticThunk(owningDelegate);
            _multicastThunk            = new DelegateInvokeMulticastThunk(owningDelegate);
            _closedStaticThunk         = new DelegateInvokeClosedStaticThunk(owningDelegate);
            _closedInstanceOverGeneric = new DelegateInvokeInstanceClosedOverGenericMethodThunk(owningDelegate);

            // Methods that have a byref-like type in the signature cannot be invoked with the object array thunk.
            // We would need to box the parameter and these can't be boxed.
            // Neither can be methods that have pointers in the signature.
            MethodSignature delegateSignature        = owningDelegate.Signature;
            bool            generateObjectArrayThunk = true;

            for (int i = 0; i < delegateSignature.Length; i++)
            {
                TypeDesc paramType = delegateSignature[i];
                if (paramType.IsByRef)
                {
                    paramType = ((ByRefType)paramType).ParameterType;
                }
                if (!paramType.IsSignatureVariable && paramType.IsByRefLike)
                {
                    generateObjectArrayThunk = false;
                    break;
                }
                if (paramType.IsPointer || paramType.IsFunctionPointer)
                {
                    generateObjectArrayThunk = false;
                    break;
                }
            }
            TypeDesc normalizedReturnType = delegateSignature.ReturnType;

            if (normalizedReturnType.IsByRef)
            {
                normalizedReturnType = ((ByRefType)normalizedReturnType).ParameterType;
            }
            if (!normalizedReturnType.IsSignatureVariable && normalizedReturnType.IsByRefLike)
            {
                generateObjectArrayThunk = false;
            }
            if (normalizedReturnType.IsPointer || normalizedReturnType.IsFunctionPointer)
            {
                generateObjectArrayThunk = false;
            }

            if ((owningDelegate.SupportedFeatures & DelegateFeature.ObjectArrayThunk) != 0 && generateObjectArrayThunk)
            {
                _invokeObjectArrayThunk = new DelegateInvokeObjectArrayThunk(owningDelegate);
            }

            //
            // Check whether we have a reverse p/invoke thunk
            //

            if (!owningDelegate.Type.HasInstantiation && IsNativeCallingConventionCompatible(delegateSignature))
            {
                _reversePInvokeThunk = new DelegateReversePInvokeThunk(owningDelegate);
            }

            //
            // Check whether we have an open instance thunk
            //

            if (delegateSignature.Length > 0)
            {
                TypeDesc firstParam = delegateSignature[0];

                bool generateOpenInstanceMethod;

                switch (firstParam.Category)
                {
                case TypeFlags.Pointer:
                case TypeFlags.FunctionPointer:
                    generateOpenInstanceMethod = false;
                    break;

                case TypeFlags.ByRef:
                    firstParam = ((ByRefType)firstParam).ParameterType;
                    generateOpenInstanceMethod = firstParam.IsSignatureVariable || firstParam.IsValueType;
                    break;

                case TypeFlags.Array:
                case TypeFlags.SzArray:
                case TypeFlags.SignatureTypeVariable:
                    generateOpenInstanceMethod = true;
                    break;

                default:
                    Debug.Assert(firstParam.IsDefType);
                    generateOpenInstanceMethod = !firstParam.IsValueType;
                    break;
                }

                if (generateOpenInstanceMethod)
                {
                    _openInstanceThunk = new DelegateInvokeOpenInstanceThunk(owningDelegate);
                }
            }

            //
            // Check whether we have a dynamic invoke stub
            //

            if ((owningDelegate.SupportedFeatures & DelegateFeature.DynamicInvoke) != 0 &&
                DynamicInvokeMethodThunk.SupportsSignature(delegateSignature))
            {
                var sig = new DynamicInvokeMethodSignature(delegateSignature);
                _invokeThunk = owningDelegate.Type.Context.GetDynamicInvokeThunk(sig);
            }
        }
Пример #8
0
 public MethodDesc GetDynamicInvokeThunk(MethodSignature signature, bool valueTypeInstanceMethod)
 {
     return(_dynamicInvokeThunks.GetOrCreateValue(
                DynamicInvokeMethodThunk.NormalizeSignature(signature, valueTypeInstanceMethod)));
 }