public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, string logFile) : base(group, typeSystemContext, new BlockedInternalsBlockingPolicy()) { _metadataLogFile = logFile; if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext)) { _dynamicInvokeThunks = new Dictionary <DynamicInvokeMethodSignature, MethodDesc>(); } }
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); }
public static bool SupportsDynamicInvoke(TypeSystemContext context) { return(DynamicInvokeMethodThunk.SupportsDynamicInvoke(context)); }
/// <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))); }
/// <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); } }
public MethodDesc GetDynamicInvokeThunk(MethodSignature signature, bool valueTypeInstanceMethod) { return(_dynamicInvokeThunks.GetOrCreateValue( DynamicInvokeMethodThunk.NormalizeSignature(signature, valueTypeInstanceMethod))); }