diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs new file mode 100644 index 00000000000..5bb37b622e7 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs @@ -0,0 +1,28 @@ +// 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 Internal.IL.Stubs +{ + public partial class CalliMarshallingMethodThunk : IPrefixMangledSignature + { + MethodSignature IPrefixMangledSignature.BaseSignature + { + get + { + return _targetSignature; + } + } + + string IPrefixMangledSignature.Prefix + { + get + { + return "Calli"; + } + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs new file mode 100644 index 00000000000..2ac126d1108 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs @@ -0,0 +1,20 @@ +// 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.TypeSystem; + +namespace Internal.IL.Stubs +{ + // Functionality related to deterministic ordering of methods + partial class CalliMarshallingMethodThunk + { + protected internal override int ClassCode => 1594107963; + + protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) + { + var otherMethod = (CalliMarshallingMethodThunk)other; + return comparer.Compare(_targetSignature, otherMethod._targetSignature); + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs new file mode 100644 index 00000000000..a70ceb5fed5 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs @@ -0,0 +1,89 @@ +// 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; +using Internal.TypeSystem.Interop; +using Debug = System.Diagnostics.Debug; +using Internal.TypeSystem.Ecma; + +namespace Internal.IL.Stubs +{ + /// + /// Thunk to marshal calli PInvoke parameters and invoke the appropriate function pointer + /// + public partial class CalliMarshallingMethodThunk : ILStubMethod + { + private readonly MethodSignature _targetSignature; + private readonly InteropStateManager _interopStateManager; + private readonly TypeDesc _owningType; + + private MethodSignature _signature; + + public CalliMarshallingMethodThunk(MethodSignature targetSignature, TypeDesc owningType, + InteropStateManager interopStateManager) + { + _targetSignature = targetSignature; + _owningType = owningType; + _interopStateManager = interopStateManager; + } + + public MethodSignature TargetSignature + { + get + { + return _targetSignature; + } + } + + public override TypeSystemContext Context + { + get + { + return _owningType.Context; + } + } + + public override TypeDesc OwningType + { + get + { + return _owningType; + } + } + + public override MethodSignature Signature + { + get + { + if (_signature == null) + { + // Prepend fnptr argument to the signature + TypeDesc[] parameterTypes = new TypeDesc[_targetSignature.Length + 1]; + + parameterTypes[0] = Context.GetWellKnownType(WellKnownType.IntPtr); + for (int i = 0; i < _targetSignature.Length; i++) + parameterTypes[i + 1] = _targetSignature[i]; + + _signature = new MethodSignature(MethodSignatureFlags.Static, 0, _targetSignature.ReturnType, parameterTypes); + } + return _signature; + } + } + + public override string Name + { + get + { + return "CalliMarshallingMethodThunk"; + } + } + + public override MethodIL EmitIL() + { + // TODO + throw null; + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs index 7813d0318ea..bd140239c81 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs @@ -7,9 +7,6 @@ namespace Internal.IL.Stubs { - /// - /// contains functionality related to name mangling - /// public partial class DelegateMarshallingMethodThunk : IPrefixMangledType { TypeDesc IPrefixMangledType.BaseType diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index 650b244c139..dd4f182de1e 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs @@ -109,5 +109,13 @@ public override bool HasCustomAttribute(string attributeNamespace, string attrib { return false; } + + public override string Name + { + get + { + return _targetMethod.Name; + } + } } } diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs index 2a2cae4e82f..5aab575a28e 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs @@ -72,6 +72,15 @@ public override bool IsPInvoke } } + public override bool IsNoInlining + { + get + { + // This method does not have real IL body. NoInlining stops the JIT asking for it. + return true; + } + } + public override PInvokeMetadata GetPInvokeMethodMetadata() { return _declMethod.GetPInvokeMethodMetadata(); diff --git a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs index c28ca119dda..3e71c1382c2 100644 --- a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs +++ b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs @@ -22,6 +22,7 @@ public sealed class InteropStateManager private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable; private readonly InlineArrayHashTable _inlineArrayHashtable; private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable; + private readonly PInvokeCalliHashtable _pInvokeCalliHashtable; public InteropStateManager(ModuleDesc generatedAssembly) { @@ -33,6 +34,7 @@ public InteropStateManager(ModuleDesc generatedAssembly) _pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly); _inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly); _pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType()); + _pInvokeCalliHashtable = new PInvokeCalliHashtable(this, _generatedAssembly.GetGlobalModuleType()); } // // Delegate Marshalling Stubs @@ -185,6 +187,11 @@ public FieldDesc GetPInvokeLazyFixupField(MethodDesc method) return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); } + public MethodDesc GetPInvokeCalliStub(MethodSignature signature) + { + return _pInvokeCalliHashtable.GetOrCreateValue(signature); + } + private class NativeStructTypeHashtable : LockFreeReaderHashtable { protected override int GetKeyHashCode(MetadataType key) @@ -471,5 +478,42 @@ public PInvokeLazyFixupFieldHashtable(DefType owningType) _owningType = owningType; } } + + private class PInvokeCalliHashtable : LockFreeReaderHashtable + { + private readonly InteropStateManager _interopStateManager; + private readonly TypeDesc _owningType; + + protected override int GetKeyHashCode(MethodSignature key) + { + return key.GetHashCode(); + } + + protected override int GetValueHashCode(CalliMarshallingMethodThunk value) + { + return value.TargetSignature.GetHashCode(); + } + + protected override bool CompareKeyToValue(MethodSignature key, CalliMarshallingMethodThunk value) + { + return key.Equals(value.TargetSignature); + } + + protected override bool CompareValueToValue(CalliMarshallingMethodThunk value1, CalliMarshallingMethodThunk value2) + { + return value1.TargetSignature.Equals(value2.TargetSignature); + } + + protected override CalliMarshallingMethodThunk CreateValueFromKey(MethodSignature key) + { + return new CalliMarshallingMethodThunk(key, _owningType, _interopStateManager); + } + + public PInvokeCalliHashtable(InteropStateManager interopStateManager, TypeDesc owningType) + { + _interopStateManager = interopStateManager; + _owningType = owningType; + } + } } } diff --git a/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs new file mode 100644 index 00000000000..3dabbc53a67 --- /dev/null +++ b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.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. + +namespace Internal.TypeSystem +{ + /// + /// When implemented by a , instructs a name mangler to use the same mangled name + /// as another entity while prepending a specific prefix to that mangled name. + /// + public interface IPrefixMangledSignature + { + /// + /// Signature whose mangled name to use. + /// + MethodSignature BaseSignature { get; } + + /// + /// Prefix to apply when mangling. + /// + string Prefix { get; } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs index 5c292f87f7b..8c5636c21a4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs @@ -410,6 +410,35 @@ private Utf8String GetPrefixMangledTypeName(IPrefixMangledType prefixMangledType return sb.ToUtf8String(); } + private Utf8String GetPrefixMangledSignatureName(IPrefixMangledSignature prefixMangledSignature) + { + Utf8StringBuilder sb = new Utf8StringBuilder(); + sb.Append(EnterNameScopeSequence).Append(prefixMangledSignature.Prefix).Append(ExitNameScopeSequence); + + var signature = prefixMangledSignature.BaseSignature; + sb.Append(signature.Flags.ToStringInvariant()); + + sb.Append(EnterNameScopeSequence); + + string sigRetTypeName = GetMangledTypeName(signature.ReturnType); + if (_mangleForCplusPlus) + sigRetTypeName = sigRetTypeName.Replace("::", "_"); + sb.Append(sigRetTypeName); + + for (int i = 0; i < signature.Length; i++) + { + sb.Append("__"); + string sigArgName = GetMangledTypeName(signature[i]); + if (_mangleForCplusPlus) + sigArgName = sigArgName.Replace("::", "_"); + sb.Append(sigArgName); + } + + sb.Append(ExitNameScopeSequence); + + return sb.ToUtf8String(); + } + private Utf8String GetPrefixMangledMethodName(IPrefixMangledMethod prefixMangledMetod) { Utf8StringBuilder sb = new Utf8StringBuilder(); @@ -497,6 +526,10 @@ private Utf8String ComputeUnqualifiedMangledMethodName(MethodDesc method) { utf8MangledName = GetPrefixMangledTypeName((IPrefixMangledType)method); } + else if (method is IPrefixMangledSignature) + { + utf8MangledName = GetPrefixMangledSignatureName((IPrefixMangledSignature)method); + } else { // Assume that Name is unique for all other methods diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs index 4aec04036d8..7ae483dbcc4 100644 --- a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs +++ b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs @@ -29,5 +29,10 @@ public MethodIL EmitIL(MethodDesc method) { return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager); } + + public MethodDesc GetCalliStub(MethodSignature signature) + { + return _interopStateManager.GetPInvokeCalliStub(signature); + } } } diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj index aab6301a4b4..ec7b134e6ec 100644 --- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj +++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj @@ -358,9 +358,6 @@ IL\DelegateInfo.cs - - IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs - IL\Stubs\DelegateThunks.Sorting.cs @@ -475,12 +472,24 @@ IL\Stubs\DebuggerSteppingHelpers.cs + + IL\Stubs\CalliMarshallingMethodThunk.cs + + + IL\Stubs\CalliMarshallingMethodThunk.Mangling.cs + + + IL\Stubs\CalliMarshallingMethodThunk.Sorting.cs + IL\Stubs\DelegateMarshallingMethodThunk.cs IL\Stubs\DelegateMarshallingMethodThunk.Mangling.cs + + IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs + IL\Stubs\ForwardDelegateCreationThunk.cs @@ -562,6 +571,9 @@ TypeSystem\Mangling\IPrefixMangledType.cs + + TypeSystem\Mangling\IPrefixMangledSignature.cs + Utilities\ArrayBuilder.cs diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs index e628978b9ee..2c5f06f72e5 100644 --- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs +++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs @@ -21,7 +21,8 @@ public Compilation(TypeSystemContext context) { _typeSystemContext = context; _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(context.GetWellKnownType(WellKnownType.Object)); - _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null)); + _pInvokeILProvider = new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null); + _methodILCache = new ILProvider(_pInvokeILProvider); _nodeFactory = new NodeFactory(context); _devirtualizationManager = new DevirtualizationManager(); } @@ -31,9 +32,11 @@ public Compilation(TypeSystemContext context) protected readonly Logger _logger = Logger.Null; private readonly TypeGetTypeMethodThunkCache _typeGetTypeMethodThunks; private ILProvider _methodILCache; + private PInvokeILProvider _pInvokeILProvider; private readonly DevirtualizationManager _devirtualizationManager; internal Logger Logger => _logger; + internal PInvokeILProvider PInvokeILProvider => _pInvokeILProvider; public TypeSystemContext TypeSystemContext { get { return _typeSystemContext; } } public NodeFactory NodeFactory { get { return _nodeFactory; } } @@ -51,7 +54,7 @@ internal MethodIL GetMethodIL(MethodDesc method) { // Flush the cache when it grows too big if (_methodILCache.Count > 1000) - _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null)); + _methodILCache = new ILProvider(_pInvokeILProvider); return _methodILCache.GetMethodIL(method); } @@ -142,4 +145,4 @@ public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc ta return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch); } } -} \ No newline at end of file +} diff --git a/src/System.Private.Jit/src/System.Private.Jit.csproj b/src/System.Private.Jit/src/System.Private.Jit.csproj index 662339fa586..39cb058ccf8 100644 --- a/src/System.Private.Jit/src/System.Private.Jit.csproj +++ b/src/System.Private.Jit/src/System.Private.Jit.csproj @@ -69,6 +69,7 @@ +