diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-03-28 09:35:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-28 09:35:28 +0300 |
commit | dfcd12f92c37d7533dcf7a48e9ab16295d84cf31 (patch) | |
tree | 36f98cf44ba75e41d27729edc1ecf763e93f5652 /src | |
parent | e0b0120beb94f211664e2c9f71a680b8ba926d0b (diff) |
Use a shared DynamicInvoke for delegates and reflection (#5615)
When I did the `System.Reflection.Pointer` support for reflection invoke and delegate `DynamicInvoke`, I found these two thunks do pretty much the same thing. They got implemented separately because I was just porting Project N IL2IL code, but there's no reason why we need two.
With this change, Delegate.DynamicInvoke will just call into the shared helper that is also used for reflection invoke.
This is a bigger diff due to bunch of mechanical changes:
* The set of generated helpers had to be moved to a place from where both delegate and reflection infrastructure can see it. A type system context dot file did the trick. (Contributes to #3873.)
* The generated assembly got moved to the type system context so that the thunks can stay homed in it.
* Fix to CppCodegen name mangling so that these can be still referenced in CppCodegen.
Diffstat (limited to 'src')
35 files changed, 587 insertions, 690 deletions
diff --git a/src/Common/src/TypeSystem/IL/DelegateInfo.cs b/src/Common/src/TypeSystem/IL/DelegateInfo.cs index 8da4a6d58..8b5fc4dfb 100644 --- a/src/Common/src/TypeSystem/IL/DelegateInfo.cs +++ b/src/Common/src/TypeSystem/IL/DelegateInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using Internal.IL.Stubs; @@ -17,13 +18,19 @@ namespace Internal.IL /// </summary> public class DelegateInfo { - private TypeDesc _delegateType; + private readonly TypeDesc _delegateType; + private readonly DelegateFeature _supportedFeatures; private MethodSignature _signature; private MethodDesc _getThunkMethod; private DelegateThunkCollection _thunks; + public static bool SupportsDynamicInvoke(TypeSystemContext context) + { + return DynamicInvokeMethodThunk.SupportsDynamicInvoke(context); + } + /// <summary> /// Gets the synthetic methods that support this delegate type. /// </summary> @@ -78,6 +85,14 @@ namespace Internal.IL } } + public DelegateFeature SupportedFeatures + { + get + { + return _supportedFeatures; + } + } + /// <summary> /// Gets the type of the delegate. /// </summary> @@ -89,12 +104,13 @@ namespace Internal.IL } } - public DelegateInfo(TypeDesc delegateType) + public DelegateInfo(TypeDesc delegateType, DelegateFeature features) { Debug.Assert(delegateType.IsDelegate); Debug.Assert(delegateType.IsTypeDefinition); _delegateType = delegateType; + _supportedFeatures = features; } } @@ -119,7 +135,6 @@ namespace Internal.IL _openStaticThunk = new DelegateInvokeOpenStaticThunk(owningDelegate); _multicastThunk = new DelegateInvokeMulticastThunk(owningDelegate); _closedStaticThunk = new DelegateInvokeClosedStaticThunk(owningDelegate); - _invokeThunk = new DelegateDynamicInvokeThunk(owningDelegate); _closedInstanceOverGeneric = new DelegateInvokeInstanceClosedOverGenericMethodThunk(owningDelegate); // Methods that have a byref-like type in the signature cannot be invoked with the object array thunk. @@ -151,12 +166,20 @@ namespace Internal.IL if (normalizedReturnType.IsPointer || normalizedReturnType.IsFunctionPointer) generateObjectArrayThunk = false; - if (generateObjectArrayThunk) + 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]; @@ -193,6 +216,16 @@ namespace Internal.IL } } + // + // 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); + } } #region Temporary interop logic @@ -285,4 +318,11 @@ namespace Internal.IL ReversePinvokeThunk = 6, // This may not exist ObjectArrayThunk = 7, // This may not exist } + + [Flags] + public enum DelegateFeature + { + DynamicInvoke = 0x1, + ObjectArrayThunk = 0x2, + } } diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs index f30a11c9c..d921c9c3b 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs @@ -51,17 +51,6 @@ namespace Internal.IL.Stubs protected internal override int ClassCode => 1993292344; } - partial class DelegateDynamicInvokeThunk - { - protected internal override int ClassCode => -1127289330; - - protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) - { - var otherMethod = (DelegateDynamicInvokeThunk)other; - return comparer.Compare(_delegateInfo.Type, otherMethod._delegateInfo.Type); - } - } - partial class DelegateGetThunkMethodOverride { protected internal override int ClassCode => -321263379; diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs index ed29e211f..a4e4b8896 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs @@ -661,232 +661,6 @@ namespace Internal.IL.Stubs } /// <summary> - /// Delegate thunk that supports Delegate.DynamicInvoke. This thunk has heavy dependencies on the - /// general dynamic invocation infrastructure in System.InvokeUtils and gets called from there - /// at runtime. See comments in System.InvokeUtils for a more thorough explanation. - /// </summary> - public sealed partial class DelegateDynamicInvokeThunk : ILStubMethod - { - private DelegateInfo _delegateInfo; - private MethodSignature _signature; - - public DelegateDynamicInvokeThunk(DelegateInfo delegateInfo) - { - _delegateInfo = delegateInfo; - } - - public override TypeSystemContext Context - { - get - { - return _delegateInfo.Type.Context; - } - } - - public override TypeDesc OwningType - { - get - { - return _delegateInfo.Type; - } - } - - public override MethodSignature Signature - { - get - { - if (_signature == null) - { - _signature = new MethodSignature(0, 0, - Context.GetWellKnownType(WellKnownType.Object), - new TypeDesc[] { - Context.GetWellKnownType(WellKnownType.Object), - Context.GetWellKnownType(WellKnownType.IntPtr), - ArgSetupStateType.MakeByRefType() }); - } - return _signature; - } - } - - public override Instantiation Instantiation - { - get - { - return Instantiation.Empty; - } - } - - public override string Name - { - get - { - return "DynamicInvokeImpl"; - } - } - - private MetadataType InvokeUtilsType - { - get - { - return Context.SystemModule.GetKnownType("System", "InvokeUtils"); - } - } - - private MetadataType ArgSetupStateType - { - get - { - return InvokeUtilsType.GetNestedType("ArgSetupState"); - } - } - - public override MethodIL EmitIL() - { - ILEmitter emitter = new ILEmitter(); - ILCodeStream argSetupStream = emitter.NewCodeStream(); - ILCodeStream callSiteSetupStream = emitter.NewCodeStream(); - - // This function will look like - // - // !For each parameter to the delegate - // !if (parameter is In Parameter) - // localX is TypeOfParameterX& - // ldtoken TypeOfParameterX - // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) - // stloc localX - // !else - // localX is TypeOfParameter - // ldtoken TypeOfParameterX - // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) - // stloc localX - - // ldarg.3 - // call DynamicInvokeArgSetupComplete(ref ArgSetupState) - - // *** Second instruction stream starts here *** - - // ldarg.1 // Load this pointer - // !For each parameter - // !if (parameter is In Parameter) - // ldloc localX - // ldobj TypeOfParameterX - // !else - // ldloc localX - // ldarg.1 - // calli ReturnType thiscall(TypeOfParameter1, ...) - // !if ((ReturnType == void) - // ldnull - // !else if (ReturnType is pointer) - // System.Reflection.Pointer.Box(ReturnType) - // !else if (ReturnType is a byref) - // ldobj StripByRef(ReturnType) - // box StripByRef(ReturnType) - // !else - // box ReturnType - // ret - - callSiteSetupStream.EmitLdArg(1); - - MethodSignature delegateSignature = _delegateInfo.Signature; - - TypeDesc[] targetMethodParameters = new TypeDesc[delegateSignature.Length]; - - for (int paramIndex = 0; paramIndex < delegateSignature.Length; paramIndex++) - { - TypeDesc paramType = delegateSignature[paramIndex]; - TypeDesc localType = paramType; - - targetMethodParameters[paramIndex] = paramType; - - if (localType.IsByRef) - { - // Strip ByRef - localType = ((ByRefType)localType).ParameterType; - } - else - { - // Only if this is not a ByRef, convert the parameter type to something boxable. - // Everything but pointer types are boxable. - localType = ConvertToBoxableType(localType); - } - - ILLocalVariable local = emitter.NewLocal(localType.MakeByRefType()); - - callSiteSetupStream.EmitLdLoc(local); - - argSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(localType)); - - if (paramType.IsByRef) - { - argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null))); - } - else - { - argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null))); - - callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(paramType)); - } - argSetupStream.EmitStLoc(local); - } - - argSetupStream.EmitLdArg(3); - argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); - - callSiteSetupStream.EmitLdArg(2); - - TypeDesc returnType = delegateSignature.ReturnType; - MethodSignature targetMethodSig = new MethodSignature(0, 0, returnType, targetMethodParameters); - - callSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSig)); - - - if (returnType.IsVoid) - { - callSiteSetupStream.Emit(ILOpcode.ldnull); - } - else if (returnType.IsByRef) - { - TypeDesc targetType = ((ByRefType)returnType).ParameterType; - callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(targetType)); - callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(targetType)); - } - else if (returnType.IsPointer) - { - callSiteSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnType)); - MethodDesc getTypeFromHandleMethod = - Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null); - callSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); - - MethodDesc pointerBoxMethod = - Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null); - callSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); - } - else if (returnType.IsFunctionPointer) - { - callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(Context.GetWellKnownType(WellKnownType.IntPtr))); - } - else - { - callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(returnType)); - } - - callSiteSetupStream.Emit(ILOpcode.ret); - - return emitter.Link(this); - } - - internal static TypeDesc ConvertToBoxableType(TypeDesc type) - { - if (type.IsFunctionPointer) - { - return type.Context.GetWellKnownType(WellKnownType.IntPtr); - } - - return type; - } - } - - /// <summary> /// Synthetic method override of "IntPtr Delegate.GetThunk(Int32)". This method is injected /// into all delegate types and provides means for System.Delegate to access the various thunks /// generated by the compiler. @@ -964,7 +738,25 @@ namespace Internal.IL.Stubs { codeStream.EmitLabel(labels[(int)i]); - codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen())); + if (i == DelegateThunkKind.DelegateInvokeThunk) + { + // Dynamic invoke thunk is special since we're calling into a shared helper + MethodDesc targetMethod; + if (thunk.HasInstantiation) + { + TypeDesc[] inst = DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(_delegateInfo.Type.InstantiateAsOpen().GetMethod("Invoke", null)); + targetMethod = Context.GetInstantiatedMethod(thunk, new Instantiation(inst)); + } + else + { + targetMethod = thunk; + } + codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(targetMethod)); + } + else + { + codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen())); + } codeStream.Emit(ILOpcode.ret); } } diff --git a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs index 4fc9fcfba..041d3fa3e 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs @@ -12,9 +12,9 @@ namespace Internal.IL.Stubs // Functionality related to determinstic ordering of types partial class DynamicInvokeMethodThunk { - protected override int ClassCode => -1980933220; + protected internal override int ClassCode => -1980933220; - protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) + protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) { return CompareTo((DynamicInvokeMethodThunk)other); } @@ -58,9 +58,9 @@ namespace Internal.IL.Stubs partial class DynamicInvokeThunkGenericParameter { - protected override int ClassCode => -234393261; + protected internal override int ClassCode => -234393261; - protected override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) + protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) { var otherType = (DynamicInvokeThunkGenericParameter)other; int result = Index - otherType.Index; diff --git a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs index 23698813f..e10aac6c2 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs @@ -18,7 +18,7 @@ namespace Internal.IL.Stubs /// dependencies on the general dynamic invocation infrastructure in System.InvokeUtils and gets called from there /// at runtime. See comments in System.InvokeUtils for a more thorough explanation. /// </summary> - internal partial class DynamicInvokeMethodThunk : ILStubMethod + public partial class DynamicInvokeMethodThunk : ILStubMethod { private TypeDesc _owningType; private DynamicInvokeMethodSignature _targetSignature; @@ -32,11 +32,125 @@ namespace Internal.IL.Stubs _targetSignature = signature; } - public static bool SupportsThunks(TypeSystemContext context) + internal static bool SupportsDynamicInvoke(TypeSystemContext context) { return context.SystemModule.GetType("System", "InvokeUtils", false) != null; } + public static bool SupportsSignature(MethodSignature signature) + { + for (int i = 0; i < signature.Length; i++) + if (signature[i].IsByRef && ((ByRefType)signature[i]).ParameterType.IsPointer) + return false; + + // ---------------------------------------------------------------- + // TODO: function pointer types are odd: https://github.com/dotnet/corert/issues/1929 + // ---------------------------------------------------------------- + + if (signature.ReturnType.IsFunctionPointer) + return false; + + for (int i = 0; i < signature.Length; i++) + if (signature[i].IsFunctionPointer) + return false; + + // ---------------------------------------------------------------- + // Methods with ByRef returns can't be reflection invoked + // ---------------------------------------------------------------- + + if (signature.ReturnType.IsByRef) + return false; + + // ---------------------------------------------------------------- + // Methods that return ByRef-like types or take them by reference can't be reflection invoked + // ---------------------------------------------------------------- + + if (!signature.ReturnType.IsSignatureVariable && signature.ReturnType.IsByRefLike) + return false; + + for (int i = 0; i < signature.Length; i++) + { + ByRefType paramType = signature[i] as ByRefType; + if (paramType != null && !paramType.ParameterType.IsSignatureVariable && paramType.ParameterType.IsByRefLike) + return false; + } + + return true; + } + + public static TypeDesc[] GetThunkInstantiationForMethod(MethodDesc method) + { + MethodSignature sig = method.Signature; + + ParameterMetadata[] paramMetadata = null; + TypeDesc[] instantiation = new TypeDesc[sig.ReturnType.IsVoid ? sig.Length : sig.Length + 1]; + + 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; + + Debug.Assert(!parameterType.IsPointer); // TODO: support for methods returning pointer types - https://github.com/dotnet/corert/issues/2113 + } + else if (parameterType.IsPointer) + { + // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that + // by being specialized for the specific pointer depth. + while (parameterType.IsPointer) + parameterType = ((PointerType)parameterType).ParameterType; + } + 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 = method.Context.GetWellKnownType(WellKnownType.Object); + } + + // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that + // by being specialized for the specific pointer depth. + while (returnType.IsPointer) + returnType = ((PointerType)returnType).ParameterType; + + instantiation[sig.Length] = returnType; + } + + return instantiation; + } + public override TypeSystemContext Context { get @@ -69,6 +183,14 @@ namespace Internal.IL.Stubs } } + public DynamicInvokeMethodSignature TargetSignature + { + get + { + return _targetSignature; + } + } + public override MethodSignature Signature { get @@ -380,10 +502,12 @@ namespace Internal.IL.Stubs /// <summary> /// Wraps a <see cref="MethodSignature"/> to reduce it's fidelity. /// </summary> - internal struct DynamicInvokeMethodSignature : IEquatable<DynamicInvokeMethodSignature> + public struct DynamicInvokeMethodSignature : IEquatable<DynamicInvokeMethodSignature> { private MethodSignature _signature; + public TypeSystemContext Context => _signature.ReturnType.Context; + public bool HasReturnValue { get @@ -400,7 +524,7 @@ namespace Internal.IL.Stubs } } - public DynamicInvokeMethodParameterKind this[int index] + internal DynamicInvokeMethodParameterKind this[int index] { get { @@ -437,7 +561,7 @@ namespace Internal.IL.Stubs return GetNumberOfIndirections(_signature.ReturnType); } - public DynamicInvokeMethodParameterKind ReturnType + internal DynamicInvokeMethodParameterKind ReturnType { get { @@ -455,9 +579,7 @@ namespace Internal.IL.Stubs public DynamicInvokeMethodSignature(MethodSignature concreteSignature) { - // ByRef returns should have been filtered out elsewhere. We don't handle them - // because reflection can't invoke such methods. - Debug.Assert(!concreteSignature.ReturnType.IsByRef); + Debug.Assert(DynamicInvokeMethodThunk.SupportsSignature(concreteSignature)); _signature = concreteSignature; } diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs index 4f186e219..a835b47d0 100644 --- a/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs +++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using Internal.IL; @@ -13,6 +12,10 @@ namespace Internal.TypeSystem { private class DelegateInfoHashtable : LockFreeReaderHashtable<TypeDesc, DelegateInfo> { + private enum CoreLibSupportLevel { Unknown, Supported, Unsupported } + + private CoreLibSupportLevel _supportLevel; + protected override int GetKeyHashCode(TypeDesc key) { return key.GetHashCode(); @@ -31,7 +34,18 @@ namespace Internal.TypeSystem } protected override DelegateInfo CreateValueFromKey(TypeDesc key) { - return new DelegateInfo(key); + if (_supportLevel == CoreLibSupportLevel.Unknown) + { + // Check if the core library supports dynamic invoke. + _supportLevel = DelegateInfo.SupportsDynamicInvoke(key.Context) ? + CoreLibSupportLevel.Supported : CoreLibSupportLevel.Unsupported; + } + + DelegateFeature supportedFeatures = _supportLevel == CoreLibSupportLevel.Supported ? + DelegateFeature.DynamicInvoke | DelegateFeature.ObjectArrayThunk : 0; + + + return new DelegateInfo(key, supportedFeatures); } } diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs new file mode 100644 index 000000000..cdad3d9ef --- /dev/null +++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.IL.Stubs; + +using Debug = System.Diagnostics.Debug; + +namespace Internal.TypeSystem +{ + partial class TypeSystemContext + { + private class DynamicInvokeThunkHashtable : LockFreeReaderHashtable<DynamicInvokeMethodSignature, DynamicInvokeMethodThunk> + { + protected override bool CompareKeyToValue(DynamicInvokeMethodSignature key, DynamicInvokeMethodThunk value) => key.Equals(value.TargetSignature); + protected override bool CompareValueToValue(DynamicInvokeMethodThunk value1, DynamicInvokeMethodThunk value2) => value1.TargetSignature.Equals(value2.TargetSignature) && value1.OwningType == value2.OwningType; + protected override int GetKeyHashCode(DynamicInvokeMethodSignature key) => key.GetHashCode(); + protected override int GetValueHashCode(DynamicInvokeMethodThunk value) => value.TargetSignature.GetHashCode(); + protected override DynamicInvokeMethodThunk CreateValueFromKey(DynamicInvokeMethodSignature key) + { + return new DynamicInvokeMethodThunk(key.Context.GeneratedAssembly.GetGlobalModuleType(), key); + } + } + DynamicInvokeThunkHashtable _dynamicInvokeThunks = new DynamicInvokeThunkHashtable(); + + public MethodDesc GetDynamicInvokeThunk(DynamicInvokeMethodSignature signature) + { + return _dynamicInvokeThunks.GetOrCreateValue(signature); + } + } +} diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs new file mode 100644 index 000000000..5c3301262 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Internal.TypeSystem +{ + partial class TypeSystemContext + { + // Functionality related to determinstic ordering of types and members + partial class CompilerGeneratedType : MetadataType + { + protected internal override int ClassCode => -1036681447; + + protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) + { + // Should be a singleton + throw new NotSupportedException(); + } + } + } +} diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs new file mode 100644 index 000000000..5b3e59616 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs @@ -0,0 +1,252 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using TypeHashingAlgorithms = Internal.NativeFormat.TypeHashingAlgorithms; +using Interlocked = System.Threading.Interlocked; +using AssemblyName = System.Reflection.AssemblyName; +using Debug = System.Diagnostics.Debug; + +namespace Internal.TypeSystem +{ + partial class TypeSystemContext + { + private ModuleDesc _generatedAssembly; + + public ModuleDesc GeneratedAssembly + { + get + { + if (_generatedAssembly == null) + { + Interlocked.CompareExchange(ref _generatedAssembly, new CompilerGeneratedAssembly(this), null); + } + + return _generatedAssembly; + } + } + + private class CompilerGeneratedAssembly : ModuleDesc, IAssemblyDesc + { + private MetadataType _globalModuleType; + + public CompilerGeneratedAssembly(TypeSystemContext context) + : base(context) + { + _globalModuleType = new CompilerGeneratedType(this, "<Module>"); + } + + public override IEnumerable<MetadataType> GetAllTypes() + { + return Array.Empty<MetadataType>(); + } + + public override MetadataType GetGlobalModuleType() + { + return _globalModuleType; + } + + public AssemblyName GetName() + { + return new AssemblyName("System.Private.CompilerGenerated"); + } + + public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true) + { + Debug.Fail("Resolving a TypeRef in the compiler generated assembly?"); + + if (throwIfNotFound) + ThrowHelper.ThrowTypeLoadException(nameSpace, name, this); + + return null; + } + } + + /// <summary> + /// A pseudo-type that owns helper methods generated by the compiler. + /// This type should never be allocated (we should never see an EEType for it). + /// </summary> + internal sealed partial class CompilerGeneratedType : MetadataType + { + private int _hashcode; + + public CompilerGeneratedType(ModuleDesc module, string name) + { + Module = module; + Name = name; + } + + public override TypeSystemContext Context + { + get + { + return Module.Context; + } + } + + public override string Name + { + get; + } + + public override string Namespace + { + get + { + return "Internal.CompilerGenerated"; + } + } + + public override int GetHashCode() + { + if (_hashcode != 0) + return _hashcode; + return InitializeHashCode(); + } + + private int InitializeHashCode() + { + string ns = Namespace; + var hashCodeBuilder = new TypeHashingAlgorithms.HashCodeBuilder(ns); + if (ns.Length > 0) + hashCodeBuilder.Append("."); + hashCodeBuilder.Append(Name); + _hashcode = hashCodeBuilder.ToHashCode(); + + return _hashcode; + } + + public override bool IsCanonicalSubtype(CanonicalFormKind policy) + { + Debug.Assert(!HasInstantiation, "Why is this generic?"); + return false; + } + + protected override TypeFlags ComputeTypeFlags(TypeFlags mask) + { + return TypeFlags.Class | + TypeFlags.HasGenericVarianceComputed | + TypeFlags.HasStaticConstructorComputed | + TypeFlags.HasFinalizerComputed | + TypeFlags.AttributeCacheComputed; + } + + public override ClassLayoutMetadata GetClassLayout() + { + return new ClassLayoutMetadata + { + Offsets = null, + PackingSize = 0, + Size = 0, + }; + } + + public override bool HasCustomAttribute(string attributeNamespace, string attributeName) + { + return false; + } + + public override IEnumerable<MetadataType> GetNestedTypes() + { + return Array.Empty<MetadataType>(); + } + + public override MetadataType GetNestedType(string name) + { + return null; + } + + protected override MethodImplRecord[] ComputeVirtualMethodImplsForType() + { + return Array.Empty<MethodImplRecord>(); + } + + public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name) + { + return Array.Empty<MethodImplRecord>(); + } + + public override ModuleDesc Module + { + get; + } + + public override PInvokeStringFormat PInvokeStringFormat + { + get + { + return PInvokeStringFormat.AutoClass; + } + } + + public override bool IsExplicitLayout + { + get + { + return false; + } + } + + public override bool IsSequentialLayout + { + get + { + return false; + } + } + + public override bool IsBeforeFieldInit + { + get + { + return false; + } + } + + public override MetadataType MetadataBaseType + { + get + { + // Since this type should never be allocated and only serves the purpose of grouping things, + // it can act like a <Module> type and have no base type. + return null; + } + } + + public override bool IsSealed + { + get + { + return true; + } + } + + public override bool IsAbstract + { + get + { + return false; + } + } + + public override DefType ContainingType + { + get + { + return null; + } + } + + public override DefType[] ExplicitlyImplementedInterfaces + { + get + { + return Array.Empty<DefType>(); + } + } + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs index 3a51c070d..64b2b33ad 100644 --- a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs @@ -25,7 +25,6 @@ namespace ILCompiler private readonly Dictionary<FieldDesc, MetadataCategory> _reflectableFields = new Dictionary<FieldDesc, MetadataCategory>(); public AnalysisBasedMetadataManager( - ModuleDesc generatedAssembly, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, string logFile, @@ -34,7 +33,7 @@ namespace ILCompiler IEnumerable<ReflectableEntity<TypeDesc>> reflectableTypes, IEnumerable<ReflectableEntity<MethodDesc>> reflectableMethods, IEnumerable<ReflectableEntity<FieldDesc>> reflectableFields) - : base(generatedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy) + : base(typeSystemContext, blockingPolicy, logFile, stackTracePolicy) { _modulesWithMetadata = new List<ModuleDesc>(modulesWithMetadata); diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs index d686a0d7b..634a1c097 100644 --- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs +++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs @@ -58,7 +58,7 @@ namespace ILCompiler foreach (var rootProvider in compilationRoots) rootProvider.AddCompilationRoots(rootingService); - MetadataType globalModuleGeneratedType = nodeFactory.CompilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(); + MetadataType globalModuleGeneratedType = nodeFactory.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType(); _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(globalModuleGeneratedType); _assemblyGetExecutingAssemblyMethodThunks = new AssemblyGetExecutingAssemblyMethodThunkCache(globalModuleGeneratedType); _methodBaseGetCurrentMethodThunks = new MethodBaseGetCurrentMethodThunkCache(); diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs index 8fa73ff20..92354badb 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs @@ -22,17 +22,6 @@ namespace ILCompiler public abstract class CompilationModuleGroup { /// <summary> - /// Gets the synthetic assembly that holds types generated by the compiler as part of the compilation process. - /// Types and members that declare this module as their owning module are always generated. - /// </summary> - public ModuleDesc GeneratedAssembly { get; } - - public CompilationModuleGroup(TypeSystemContext context) - { - GeneratedAssembly = new CompilerGeneratedAssembly(context); - } - - /// <summary> /// If true, "type" is in the set of input assemblies being compiled /// </summary> public abstract bool ContainsType(TypeDesc type); @@ -94,41 +83,5 @@ namespace ILCompiler /// accessed through the target platform's import mechanism (ie, Import Address Table on Windows) /// </summary> public abstract bool CanHaveReferenceThroughImportTable { get; } - - private class CompilerGeneratedAssembly : ModuleDesc, IAssemblyDesc - { - private MetadataType _globalModuleType; - - public CompilerGeneratedAssembly(TypeSystemContext context) - : base(context) - { - _globalModuleType = new CompilerGeneratedType(this, "<Module>"); - } - - public override IEnumerable<MetadataType> GetAllTypes() - { - return Array.Empty<MetadataType>(); - } - - public override MetadataType GetGlobalModuleType() - { - return _globalModuleType; - } - - public AssemblyName GetName() - { - return new AssemblyName("System.Private.CompilerGenerated"); - } - - public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true) - { - Debug.Fail("Resolving a TypeRef in the compiler generated assembly?"); - - if (throwIfNotFound) - ThrowHelper.ThrowTypeLoadException(nameSpace, name, this); - - return null; - } - } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs deleted file mode 100644 index 99457b98f..000000000 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -using Internal.TypeSystem; - -namespace ILCompiler -{ - // Functionality related to determinstic ordering of types and members - internal sealed partial class CompilerGeneratedType : MetadataType - { - protected override int ClassCode => -1036681447; - - protected override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer) - { - // Should be a singleton - throw new NotSupportedException(); - } - } -} diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs deleted file mode 100644 index e562d9500..000000000 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; - -using Internal.TypeSystem; - -using Debug = System.Diagnostics.Debug; -using TypeHashingAlgorithms = Internal.NativeFormat.TypeHashingAlgorithms; - -namespace ILCompiler -{ - /// <summary> - /// A pseudo-type that owns helper methods generated by the compiler. - /// This type should never be allocated (we should never see an EEType for it). - /// </summary> - internal sealed partial class CompilerGeneratedType : MetadataType - { - private int _hashcode; - - public CompilerGeneratedType(ModuleDesc module, string name) - { - Module = module; - Name = name; - } - - public override TypeSystemContext Context - { - get - { - return Module.Context; - } - } - - public override string Name - { - get; - } - - public override string Namespace - { - get - { - return "Internal.CompilerGenerated"; - } - } - - public override int GetHashCode() - { - if (_hashcode != 0) - return _hashcode; - return InitializeHashCode(); - } - - private int InitializeHashCode() - { - string ns = Namespace; - var hashCodeBuilder = new TypeHashingAlgorithms.HashCodeBuilder(ns); - if (ns.Length > 0) - hashCodeBuilder.Append("."); - hashCodeBuilder.Append(Name); - _hashcode = hashCodeBuilder.ToHashCode(); - - return _hashcode; - } - - public override bool IsCanonicalSubtype(CanonicalFormKind policy) - { - Debug.Assert(!HasInstantiation, "Why is this generic?"); - return false; - } - - protected override TypeFlags ComputeTypeFlags(TypeFlags mask) - { - return TypeFlags.Class | - TypeFlags.HasGenericVarianceComputed | - TypeFlags.HasStaticConstructorComputed | - TypeFlags.HasFinalizerComputed | - TypeFlags.AttributeCacheComputed; - } - - public override ClassLayoutMetadata GetClassLayout() - { - return new ClassLayoutMetadata - { - Offsets = null, - PackingSize = 0, - Size = 0, - }; - } - - public override bool HasCustomAttribute(string attributeNamespace, string attributeName) - { - return false; - } - - public override IEnumerable<MetadataType> GetNestedTypes() - { - return Array.Empty<MetadataType>(); - } - - public override MetadataType GetNestedType(string name) - { - return null; - } - - protected override MethodImplRecord[] ComputeVirtualMethodImplsForType() - { - return Array.Empty<MethodImplRecord>(); - } - - public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name) - { - return Array.Empty<MethodImplRecord>(); - } - - public override ModuleDesc Module - { - get; - } - - public override PInvokeStringFormat PInvokeStringFormat - { - get - { - return PInvokeStringFormat.AutoClass; - } - } - - public override bool IsExplicitLayout - { - get - { - return false; - } - } - - public override bool IsSequentialLayout - { - get - { - return false; - } - } - - public override bool IsBeforeFieldInit - { - get - { - return false; - } - } - - public override MetadataType MetadataBaseType - { - get - { - // Since this type should never be allocated and only serves the purpose of grouping things, - // it can act like a <Module> type and have no base type. - return null; - } - } - - public override bool IsSealed - { - get - { - return true; - } - } - - public override bool IsAbstract - { - get - { - return false; - } - } - - public override DefType ContainingType - { - get - { - return null; - } - } - - public override DefType[] ExplicitlyImplementedInterfaces - { - get - { - return Array.Empty<DefType>(); - } - } - } -} diff --git a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs index 86cac8dc0..5c292f87f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs @@ -331,7 +331,13 @@ namespace ILCompiler } else { + // This is a type definition. Since we didn't fall in the `is EcmaType` case above, + // it's likely a compiler-generated type. mangledName = SanitizeName(((DefType)type).GetFullName(), true); + + // Always generate a fully qualified name + if (_mangleForCplusPlus) + mangledName = "::" + mangledName; } break; } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs index 6f061c02f..3069c5f53 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs @@ -63,7 +63,7 @@ namespace ILCompiler.DependencyAnalysis // 'this' and also provides an instantiation argument (we do a calling convention conversion). // We don't do this for generic instance methods though because they don't use the EEType // for the generic context anyway. - return new ScannedMethodNode(TypeSystemContext.GetSpecialUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly)); + return new ScannedMethodNode(TypeSystemContext.GetSpecialUnboxingThunk(method, TypeSystemContext.GeneratedAssembly)); } else { diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs index cce88f810..1db0a5948 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs @@ -60,7 +60,7 @@ namespace ILCompiler.DependencyAnalysis // 'this' and also provides an instantiation argument (we do a calling convention conversion). // We don't do this for generic instance methods though because they don't use the EEType // for the generic context anyway. - return new MethodCodeNode(TypeSystemContext.GetSpecialUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly)); + return new MethodCodeNode(TypeSystemContext.GetSpecialUnboxingThunk(method, TypeSystemContext.GeneratedAssembly)); } else { diff --git a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs index b01a4bb5f..c4216775c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs @@ -9,7 +9,6 @@ using System.Text; using Internal.IL.Stubs; using Internal.TypeSystem; -using Internal.TypeSystem.Ecma; using Internal.Metadata.NativeFormat.Writer; using ILCompiler.Metadata; @@ -26,20 +25,14 @@ namespace ILCompiler { protected readonly string _metadataLogFile; protected readonly StackTraceEmissionPolicy _stackTraceEmissionPolicy; - private readonly Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks; private readonly ModuleDesc _generatedAssembly; - public GeneratingMetadataManager(ModuleDesc generatedAssembly, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy) + public GeneratingMetadataManager(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>(); - } + _generatedAssembly = typeSystemContext.GeneratedAssembly; } public sealed override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method) @@ -182,9 +175,6 @@ namespace ILCompiler { Debug.Assert(IsReflectionInvokable(method)); - if (_dynamicInvokeThunks == null) - return false; - // Place an upper limit on how many parameters a method can have to still get a static stub. // From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations // in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations. @@ -199,17 +189,9 @@ namespace ILCompiler /// </summary> public sealed 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(_generatedAssembly.GetGlobalModuleType(), lookupSig); - _dynamicInvokeThunks.Add(lookupSig, thunk); - } + var lookupSig = new DynamicInvokeMethodSignature(method.Signature); + MethodDesc thunk = _typeSystemContext.GetDynamicInvokeThunk(lookupSig); return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method); } diff --git a/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs index 340c5603a..2202f93d6 100644 --- a/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs @@ -53,7 +53,7 @@ namespace ILCompiler public IILScanner ToILScanner() { - var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly)); + var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly)); var nodeFactory = new ILScanNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler); DependencyAnalyzerBase<NodeFactory> graph = _dependencyTrackingLevel.CreateDependencyGraph(nodeFactory); diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs index 07e8fd4d8..d7f5dc695 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs @@ -218,53 +218,10 @@ namespace ILCompiler /// </summary> public virtual bool IsReflectionInvokable(MethodDesc method) { - return IsMethodSignatureSupportedInReflectionInvoke(method) + return Internal.IL.Stubs.DynamicInvokeMethodThunk.SupportsSignature(method.Signature) && IsMethodSupportedInReflectionInvoke(method); } - protected bool IsMethodSignatureSupportedInReflectionInvoke(MethodDesc method) - { - var signature = method.Signature; - - for (int i = 0; i < signature.Length; i++) - if (signature[i].IsByRef && ((ByRefType)signature[i]).ParameterType.IsPointer) - return false; - - // ---------------------------------------------------------------- - // TODO: function pointer types are odd: https://github.com/dotnet/corert/issues/1929 - // ---------------------------------------------------------------- - - if (signature.ReturnType.IsFunctionPointer) - return false; - - for (int i = 0; i < signature.Length; i++) - if (signature[i].IsFunctionPointer) - return false; - - // ---------------------------------------------------------------- - // Methods with ByRef returns can't be reflection invoked - // ---------------------------------------------------------------- - - if (signature.ReturnType.IsByRef) - return false; - - // ---------------------------------------------------------------- - // Methods that return ByRef-like types or take them by reference can't be reflection invoked - // ---------------------------------------------------------------- - - if (signature.ReturnType.IsByRefLike) - return false; - - for (int i = 0; i < signature.Length; i++) - { - ByRefType paramType = signature[i] as ByRefType; - if (paramType != null && paramType.ParameterType.IsByRefLike) - return false; - } - - return true; - } - protected bool IsMethodSupportedInReflectionInvoke(MethodDesc method) { TypeDesc owningType = method.OwningType; @@ -463,72 +420,7 @@ namespace ILCompiler // Instantiate the generic thunk over the parameters and the return type of the target method // - ParameterMetadata[] paramMetadata = null; - 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; - - Debug.Assert(!parameterType.IsPointer); // TODO: support for methods returning pointer types - https://github.com/dotnet/corert/issues/2113 - } - else if (parameterType.IsPointer) - { - // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that - // by being specialized for the specific pointer depth. - while (parameterType.IsPointer) - parameterType = ((PointerType)parameterType).ParameterType; - } - 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); - } - - // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that - // by being specialized for the specific pointer depth. - while (returnType.IsPointer) - returnType = ((PointerType)returnType).ParameterType; - - instantiation[sig.Length] = returnType; - } - + TypeDesc[] instantiation = Internal.IL.Stubs.DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(method); Debug.Assert(thunk.Instantiation.Length == instantiation.Length); // Check if at least one of the instantiation arguments is a universal canonical type, and if so, we diff --git a/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs index 9541e4285..5afac3563 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs @@ -17,12 +17,11 @@ namespace ILCompiler private HashSet<ModuleDesc> _compilationModuleSet; public MultiFileCompilationModuleGroup(TypeSystemContext context, IEnumerable<ModuleDesc> compilationModuleSet) - : base(context) { _compilationModuleSet = new HashSet<ModuleDesc>(compilationModuleSet); // The fake assembly that holds compiler generated types is part of the compilation. - _compilationModuleSet.Add(this.GeneratedAssembly); + _compilationModuleSet.Add(context.GeneratedAssembly); } public sealed override bool ContainsType(TypeDesc type) diff --git a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs index 773560798..f02559b4e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs @@ -86,7 +86,7 @@ namespace ILCompiler jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_FEATURE_SIMD); } - var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly)); + var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly)); var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider); var jitConfig = new JitConfigProvider(jitFlagBuilder.ToArray(), _ryujitOptions); diff --git a/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs index ba4c23d79..a305ad026 100644 --- a/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs +++ b/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs @@ -10,11 +10,6 @@ namespace ILCompiler { public class SingleFileCompilationModuleGroup : CompilationModuleGroup { - public SingleFileCompilationModuleGroup(TypeSystemContext context) - : base(context) - { - } - public override bool ContainsType(TypeDesc type) { return true; diff --git a/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs index 61f220e09..9f734c1e0 100644 --- a/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs +++ b/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs @@ -17,7 +17,6 @@ namespace ILCompiler private MethodDesc _method; public SingleMethodCompilationModuleGroup(MethodDesc method) - : base(method.Context) { _method = method; } diff --git a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs index b5845786c..a9f638d7b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs @@ -36,7 +36,7 @@ namespace ILCompiler MetadataBlockingPolicy blockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy) - : base(group.GeneratedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy) + : base(typeSystemContext, blockingPolicy, logFile, stackTracePolicy) { // We use this to mark places that would behave differently if we tracked exact fields used. _hasPreciseFieldUsageInformation = false; @@ -353,7 +353,7 @@ namespace ILCompiler } } - return new AnalysisBasedMetadataManager(_compilationModuleGroup.GeneratedAssembly, + return new AnalysisBasedMetadataManager( _typeSystemContext, _blockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _modulesWithMetadata, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(), reflectableFields.ToEnumerable()); diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index b799fb700..9744fa933 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -58,9 +58,6 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ComparerIntrinsics.cs"> <Link>IL\Stubs\ComparerIntrinsics.cs</Link> </Compile> - <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs"> - <Link>IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs</Link> - </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\GetCanonTypeIntrinsic.cs"> <Link>IL\Stubs\GetCanonTypeIntrinsic.cs</Link> </Compile> @@ -73,9 +70,6 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMethodILEmitter.cs"> <Link>IL\Stubs\DelegateMethodILEmitter.cs</Link> </Compile> - <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs"> - <Link>IL\Stubs\DynamicInvokeMethodThunk.cs</Link> - </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EETypePtrOfIntrinsic.cs"> <Link>IL\Stubs\EETypePtrOfIntrinsic.cs</Link> </Compile> @@ -100,8 +94,6 @@ <Compile Include="Compiler\AnalysisBasedMetadataManager.cs" /> <Compile Include="Compiler\BlockedInternalsBlockingPolicy.cs" /> <Compile Include="Compiler\CodeGenerationFailedException.cs" /> - <Compile Include="Compiler\CompilerGeneratedType.cs" /> - <Compile Include="Compiler\CompilerGeneratedType.Sorting.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.BoxedTypes.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.Mangling.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.Sorting.cs" /> diff --git a/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs b/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs index c4ace726b..a0a60efda 100644 --- a/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs +++ b/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs @@ -64,7 +64,7 @@ namespace ILCompiler.Compiler.Tests // var context = (CompilerTypeSystemContext)method.Context; - CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(context); + CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(); CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup); IILScanner scanner = builder.GetILScannerBuilder() diff --git a/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs b/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs index 6b320fb17..0ebda0cbc 100644 --- a/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs +++ b/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs @@ -32,7 +32,7 @@ namespace ILCompiler.Compiler.Tests private DevirtualizationManager GetDevirtualizationManagerFromScan(MethodDesc method) { - CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(_context); + CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(); CompilationBuilder builder = new RyuJitCompilationBuilder(_context, compilationGroup); IILScanner scanner = builder.GetILScannerBuilder() diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs index 8b4fe6360..0068f2da8 100644 --- a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs +++ b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs @@ -31,7 +31,7 @@ namespace ILCompiler public override ICompilation ToCompilation() { - var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly)); + var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly)); CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider); DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory); diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj index 162c941a7..aab6301a4 100644 --- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj +++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj @@ -364,6 +364,12 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateThunks.Sorting.cs"> <Link>IL\Stubs\DelegateThunks.Sorting.cs</Link> </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs"> + <Link>IL\Stubs\DynamicInvokeMethodThunk.cs</Link> + </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs"> + <Link>IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs</Link> + </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EnumThunks.cs"> <Link>IL\Stubs\EnumThunks.cs</Link> </Compile> @@ -391,6 +397,15 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DelegateInfo.cs"> <Link>IL\TypeSystemContext.DelegateInfo.cs</Link> </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DynamicInvoke.cs"> + <Link>IL\TypeSystemContext.DynamicInvoke.cs</Link> + </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.cs"> + <Link>IL\TypeSystemContext.GeneratedAssembly.cs</Link> + </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.Sorting.cs"> + <Link>IL\TypeSystemContext.GeneratedAssembly.Sorting.cs</Link> + </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\EcmaMethodIL.cs"> <Link>IL\EcmaMethodIL.cs</Link> </Compile> diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs index a43a1e572..2c09fc8fd 100644 --- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs +++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs @@ -51,7 +51,7 @@ namespace ILCompiler.DependencyAnalysis protected override IMethodNode CreateUnboxingStubNode(MethodDesc method) { - return new WebAssemblyMethodCodeNode(TypeSystemContext.GetUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly)); + return new WebAssemblyMethodCodeNode(TypeSystemContext.GetUnboxingThunk(method, TypeSystemContext.GeneratedAssembly)); } protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall) diff --git a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs index 48bfaa15b..e6f82061e 100644 --- a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs +++ b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs @@ -31,7 +31,7 @@ namespace ILCompiler public override ICompilation ToCompilation() { - var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly)); + var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly)); WebAssemblyCodegenNodeFactory factory = new WebAssemblyCodegenNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider); DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory); diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs index 58d549ec0..03ae9284d 100644 --- a/src/ILCompiler/src/Program.cs +++ b/src/ILCompiler/src/Program.cs @@ -17,6 +17,8 @@ namespace ILCompiler { internal class Program { + private const string DefaultSystemModule = "System.Private.CoreLib"; + private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private Dictionary<string, string> _referenceFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); @@ -37,7 +39,7 @@ namespace ILCompiler private OptimizationMode _optimizationMode; private bool _enableDebugInfo; private string _ilDump; - private string _systemModuleName = "System.Private.CoreLib"; + private string _systemModuleName = DefaultSystemModule; private bool _multiFile; private bool _nativeLib; private string _exportsFile; @@ -341,7 +343,7 @@ namespace ILCompiler throw new Exception("No entrypoint module"); compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule)); - compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext); + compilationGroup = new SingleFileCompilationModuleGroup(); } if (_nativeLib) @@ -349,7 +351,7 @@ namespace ILCompiler // Set owning module of generated native library startup method to compiler generated module, // to ensure the startup method is included in the object file during multimodule mode build LibraryInitializers libraryInitializers = new LibraryInitializers(typeSystemContext, _isCppCodegen); - compilationRoots.Add(new NativeLibraryInitializerRootProvider(compilationGroup.GeneratedAssembly, libraryInitializers.LibraryInitializerMethods)); + compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, libraryInitializers.LibraryInitializerMethods)); } if (_rdXmlFilePaths.Count > 0) @@ -392,7 +394,9 @@ namespace ILCompiler useScanner &= !_noScanner; - MetadataManager compilationMetadataManager = _isWasmCodegen ? (MetadataManager)new EmptyMetadataManager(typeSystemContext) : metadataManager; + bool supportsReflection = !_isWasmCodegen && !_isCppCodegen && _systemModuleName == DefaultSystemModule; + + MetadataManager compilationMetadataManager = supportsReflection ? metadataManager : (MetadataManager)new EmptyMetadataManager(typeSystemContext); ILScanResults scanResults = null; if (useScanner) { diff --git a/src/System.Private.CoreLib/src/System/Delegate.cs b/src/System.Private.CoreLib/src/System/Delegate.cs index e4746b1ab..9f8808fdd 100644 --- a/src/System.Private.CoreLib/src/System/Delegate.cs +++ b/src/System.Private.CoreLib/src/System/Delegate.cs @@ -373,7 +373,22 @@ namespace System else { IntPtr invokeThunk = this.GetThunk(DelegateInvokeThunk); - object result = System.InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true); +#if PROJECTN + object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true); +#else + IntPtr genericDictionary = IntPtr.Zero; + if (FunctionPointerOps.IsGenericMethodPointer(invokeThunk)) + { + unsafe + { + GenericMethodDescriptor* descriptor = FunctionPointerOps.ConvertToGenericDescriptor(invokeThunk); + genericDictionary = descriptor->InstantiationArgument; + invokeThunk = descriptor->MethodFunctionPointer; + } + } + + object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, null, invokeThunk, genericDictionary, this, args, binderBundle: null, wrapInTargetInvocationException: true, invokeMethodHelperIsThisCall: false); +#endif DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } diff --git a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index 09fdd65da..11afdf633 100644 --- a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -75,6 +75,7 @@ <Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\TypeSystemContext.RuntimeDetermined.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ILEmitter.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateThunks.cs" /> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EnumThunks.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\HelperExtensions.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\ILDisassembler.cs" /> @@ -87,7 +88,9 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\MethodILDebugView.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\DelegateInfo.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DelegateInfo.cs" /> + <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DynamicInvoke.cs" /> <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.EnumMethods.cs" /> + <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.cs" /> <Compile Include="Internal\TypeSystem\ILStubMethod.Runtime.cs" /> <Compile Include="Internal\TypeSystem\MethodForRuntimeDeterminedType.Runtime.cs" /> <Compile Include="Internal\Runtime\TypeLoader\JitSupport.MethodEntrypointStubs.cs" /> |