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 @@
+