Addressed more feedbacks: Moved TryGetMarshallerForDelegate from TypeLoader to S.P.I

This commit is contained in:
Faizur Rahman 2017-02-23 11:54:38 -08:00
Родитель bbc6b35d41
Коммит 5877f29e59
20 изменённых файлов: 175 добавлений и 100 удалений

Просмотреть файл

@ -3,13 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Text;
using Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
using Interlocked = System.Threading.Interlocked;
namespace Internal.IL.Stubs
{
/// <summary>
@ -22,12 +17,14 @@ namespace Internal.IL.Stubs
private MethodSignature _signature; // signature of the native callable marshalling stub
private TypeDesc _delegateType;
private MethodIL _methodIL;
private string _name;
public DelegateMarshallingMethodThunk(TypeDesc owningType, TypeDesc delegateType)
public DelegateMarshallingMethodThunk(TypeDesc owningType, TypeDesc delegateType, string name)
{
_owningType = owningType;
_delegateType = delegateType;
MethodDesc invokeMethod = delegateType.GetMethod("Invoke", null);
_name = name;
_delegateSignature = invokeMethod.Signature;
_methodIL = PInvokeILEmitter.EmitIL(this, null);
_signature = ((PInvokeILStubMethodIL)_methodIL).NativeCallableSignature;
@ -41,6 +38,14 @@ namespace Internal.IL.Stubs
}
}
public override bool IsNativeCallable
{
get
{
return true;
}
}
public override TypeDesc OwningType
{
get
@ -78,7 +83,7 @@ namespace Internal.IL.Stubs
{
get
{
return "ReverseDelegateStub__" + ILCompiler.DependencyAnalysis.NodeFactory.NameMangler.GetMangledTypeName(_delegateType);
return _name;
}
}
@ -88,42 +93,10 @@ namespace Internal.IL.Stubs
}
}
internal enum DelegateInvokeMethodParameterKind
{
None,
Value,
Reference
}
internal struct DelegateInvokeMethodSignature : IEquatable<DelegateInvokeMethodSignature>
{
public MethodSignature Signature;
public bool HasReturnValue
{
get
{
return !Signature.ReturnType.IsVoid;
}
}
public int Length
{
get
{
return Signature.Length;
}
}
public DelegateInvokeMethodParameterKind this[int index]
{
get
{
return Signature[index].IsByRef ?
DelegateInvokeMethodParameterKind.Reference :
DelegateInvokeMethodParameterKind.Value;
}
}
public readonly MethodSignature Signature;
public DelegateInvokeMethodSignature(TypeDesc delegateType)
{
@ -133,28 +106,21 @@ namespace Internal.IL.Stubs
public override int GetHashCode()
{
int hashCode = HasReturnValue ? 17 : 23;
for (int i = 0; i < Length; i++)
{
int value = (int)this[i] * 0x5498341 + 0x832424;
hashCode = hashCode * 31 + value;
}
return hashCode;
return Signature.GetHashCode();
}
// TODO: Use the MarshallerKind for each parameter to compare whether two signatures are similar(ie. whether two delegates can share marshalling stubs)
public bool Equals(DelegateInvokeMethodSignature other)
{
if (HasReturnValue != other.HasReturnValue)
if (Signature.ReturnType != other.Signature.ReturnType)
return false;
if (Length != other.Length)
if (Signature.Length != other.Signature.Length)
return false;
for (int i = 0; i < Length; i++)
for (int i = 0; i < Signature.Length; i++)
{
if (this[i] != other[i])
if (Signature[i] != other.Signature[i])
return false;
}

Просмотреть файл

@ -1155,6 +1155,9 @@ namespace Internal.TypeSystem.Interop
protected override void EmitMarshalReturnValueManagedToNative()
{
}
protected override void EmitMarshalReturnValueNativeToManaged()
{
}
}
class BlittableValueMarshaller : BlittableByRefMarshaller
@ -1187,9 +1190,21 @@ namespace Internal.TypeSystem.Interop
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdArg(PInvokeParameterMetadata.Index - 1);
}
}
protected override void EmitMarshalArgumentNativeToManaged()
{
if (Out)
{
base.EmitMarshalArgumentNativeToManaged();
}
else
{
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdArg(PInvokeParameterMetadata.Index - 1);
}
}
}
class ArrayMarshaller : Marshaller
class ArrayMarshaller : Marshaller
{
private Marshaller _elementMarshaller;

Просмотреть файл

@ -52,7 +52,7 @@ namespace ILCompiler.DependencyAnalysis
foreach (var delegateEntry in factory.MetadataManager.DelegateMarshalingThunks)
{
Internal.TypeSystem.TypeDesc delegateType = ((Internal.IL.Stubs.DelegateMarshallingMethodThunk)delegateEntry.Value).DelegateType;
Internal.TypeSystem.TypeDesc delegateType = delegateEntry.Value.DelegateType;
Vertex vertex = writer.GetTuple(
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(delegateType))),
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(delegateEntry.Value)))

Просмотреть файл

@ -88,16 +88,14 @@ namespace ILCompiler.DependencyAnalysis
MethodSignature methodSig = _method.Signature;
if (methodSig.ReturnType.IsDelegate)
{
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(methodSig.ReturnType);
dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub"));
AddPInvokeDelegateParameterDependencies(ref dependencies, factory, methodSig.ReturnType);
}
for (int i=0; i < methodSig.Length; i++)
{
if (methodSig[i].IsDelegate)
{
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(methodSig[i]);
dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub"));
AddPInvokeDelegateParameterDependencies(ref dependencies, factory, methodSig[i]);
}
}
}
@ -105,6 +103,17 @@ namespace ILCompiler.DependencyAnalysis
return dependencies;
}
private void AddPInvokeDelegateParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter)
{
if (dependencies == null)
dependencies = new DependencyList();
dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub");
var stubMethod = factory.MetadataManager.GetDelegateMarshallingStub(parameter);
dependencies.Add(factory.MethodEntrypoint(stubMethod), "Delegate Marshalling Stub");
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
{
return _methodCode;

Просмотреть файл

@ -28,6 +28,7 @@ namespace ILCompiler
new LibraryInitializerInfo("System.Private.TypeLoader"),
new LibraryInitializerInfo("System.Private.Reflection.Execution"),
new LibraryInitializerInfo("System.Private.DeveloperExperience.Console"),
new LibraryInitializerInfo("System.Private.Interop"),
};
private List<MethodDesc> _libraryInitializerMethods;

Просмотреть файл

@ -42,7 +42,7 @@ namespace ILCompiler
private HashSet<MethodDesc> _methodsGenerated = new HashSet<MethodDesc>();
private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>();
private List<TypeGVMEntriesNode> _typeGVMEntries = new List<TypeGVMEntriesNode>();
internal Dictionary<DelegateInvokeMethodSignature, MethodDesc> DelegateMarshalingThunks = new Dictionary<DelegateInvokeMethodSignature, MethodDesc>();
internal Dictionary<DelegateInvokeMethodSignature, DelegateMarshallingMethodThunk> DelegateMarshalingThunks = new Dictionary<DelegateInvokeMethodSignature, DelegateMarshallingMethodThunk>();
internal NativeLayoutInfoNode NativeLayoutInfo { get; private set; }
@ -324,13 +324,14 @@ namespace ILCompiler
return instantiatedDynamicInvokeMethod;
}
public MethodDesc GetDelegateMarshallingStub(TypeDesc del)
internal MethodDesc GetDelegateMarshallingStub(TypeDesc delegateType)
{
MethodDesc thunk;
var lookupSig = new DelegateInvokeMethodSignature(del);
DelegateMarshallingMethodThunk thunk;
var lookupSig = new DelegateInvokeMethodSignature(delegateType);
if (!DelegateMarshalingThunks.TryGetValue(lookupSig, out thunk))
{
thunk = new DelegateMarshallingMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), del);
string stubName = "ReverseDelegateStub__" + NodeFactory.NameMangler.GetMangledTypeName(delegateType);
thunk = new DelegateMarshallingMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), delegateType, stubName);
DelegateMarshalingThunks.Add(lookupSig, thunk);
}
return thunk;

Просмотреть файл

@ -61,7 +61,7 @@ LEAF_ENTRY RhpCommonStub, _TEXT
;; rax = base address of TLS data
;; r10 = address of context cell in thunk's data
;; r11 = trashed
;; r12 = trashed
;; r8 = trashed
;; store thunk address in thread static
mov r11, [r10]

Просмотреть файл

@ -428,6 +428,19 @@ COOP_PINVOKE_HELPER(void, CallingConventionConverter_GetStubs, (UIntNative* pRet
{
ASSERT_UNCONDITIONALLY("NYI");
}
COOP_PINVOKE_HELPER(void *, RhpGetCommonStubAddress, ())
{
ASSERT_UNCONDITIONALLY("NYI");
return NULL;
}
COOP_PINVOKE_HELPER(void *, RhpGetCurrentThunkContext, ())
{
ASSERT_UNCONDITIONALLY("NYI");
return NULL;
}
#endif
COOP_PINVOKE_HELPER(void, RhpETWLogLiveCom, (Int32 eventType, void * ccwHandle, void * objectId, void * typeRawValue, void * iUnknown, void * vTable, Int32 comRefCount, Int32 jupiterRefCount, Int32 flags))
@ -440,16 +453,3 @@ COOP_PINVOKE_HELPER(bool, RhpETWShouldWalkCom, ())
ASSERT_UNCONDITIONALLY("NYI");
return false;
}
#ifdef USE_PORTABLE_HELPERS
COOP_PINVOKE_HELPER(void *, RhpGetCommonStubAddress, ())
{
ASSERT_UNCONDITIONALLY("NYI");
return NULL;
}
COOP_PINVOKE_HELPER(void *, RhpGetCurrentThunkContext, ())
{
ASSERT_UNCONDITIONALLY("NYI");
return NULL;
}
#endif

Просмотреть файл

@ -0,0 +1,15 @@
// 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.Runtime.CompilerServices;
namespace Internal.Runtime.Augments
{
[CLSCompliant(false)]
public abstract class InteropCallbacks
{
public abstract IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle);
}
}

Просмотреть файл

@ -61,6 +61,12 @@ namespace Internal.Runtime.Augments
s_typeLoaderCallbacks = callbacks;
}
[CLSCompliant(false)]
public static void InitializeInteropLookups(InteropCallbacks callbacks)
{
s_interopCallbacks = callbacks;
}
[CLSCompliant(false)]
public static void InitializeDesktopSupport(DesktopSupportCallbacks callbacks)
{
@ -770,8 +776,20 @@ namespace Internal.Runtime.Augments
}
}
internal static InteropCallbacks InteropCallbacks
{
get
{
InteropCallbacks callbacks = s_interopCallbacks;
if (callbacks != null)
return callbacks;
throw new InvalidOperationException(SR.InvalidOperation_TooEarly);
}
}
private static volatile ReflectionExecutionDomainCallbacks s_reflectionExecutionDomainCallbacks;
private static TypeLoaderCallbacks s_typeLoaderCallbacks;
private static InteropCallbacks s_interopCallbacks;
public static void ReportUnhandledException(Exception exception)
{

Просмотреть файл

@ -18,7 +18,6 @@ namespace Internal.Runtime.Augments
public abstract IntPtr GetDelegateThunk(Delegate delegateObject, int thunkKind);
public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle);
public abstract bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated);
public abstract IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle);
/// <summary>
/// Register a new runtime-allocated code thunk in the diagnostic stream.

Просмотреть файл

@ -262,7 +262,7 @@ namespace Internal.Runtime.CompilerHelpers
}
else
{
IntPtr pTarget = RuntimeAugments.TypeLoaderCallbacks.TryGetMarshallerForDelegate(del.GetTypeHandle());
IntPtr pTarget = RuntimeAugments.InteropCallbacks.TryGetMarshallerForDelegate(del.GetTypeHandle());
IntPtr pContext;
unsafe
{

Просмотреть файл

@ -118,6 +118,7 @@
<Compile Include="Internal\Runtime\Augments\RuntimeAugments.cs" />
<Compile Include="Internal\Runtime\Augments\ReflectionExecutionDomainCallbacks.cs" />
<Compile Include="Internal\Runtime\Augments\TypeLoaderCallbacks.cs" />
<Compile Include="Internal\Runtime\Augments\InteropCallbacks.cs" />
<Compile Include="Internal\Runtime\Augments\DesktopSupportCallbacks.cs" />
<Compile Include="Internal\Runtime\Augments\DynamicDelegateAugments.cs" />
<Compile Include="Internal\Runtime\Augments\EnumInfo.cs" />

Просмотреть файл

@ -1,26 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// 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.Runtime;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using Internal.Runtime;
using Internal.Runtime.Augments;
using Internal.Runtime.CompilerServices;
using Internal.NativeFormat;
using Internal.TypeSystem;
using Internal.Runtime.TypeLoader;
using Internal.Reflection.Execution;
namespace Internal.Runtime.TypeLoader
namespace Internal.Runtime.CompilerHelpers
{
public sealed partial class TypeLoaderEnvironment
internal class Callbacks : InteropCallbacks
{
public override IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
{
return InteropCallbackManager.Instance.TryGetMarshallerForDelegate(delegateTypeHandle);
}
}
[CLSCompliant(false)]
public sealed class InteropCallbackManager
{
public static InteropCallbackManager Instance { get; private set; }
// Eager initialization called from LibraryInitializer for the assembly.
internal static void Initialize()
{
Instance = new InteropCallbackManager();
RuntimeAugments.InitializeInteropLookups(new Callbacks());
}
private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
{
byte* pBlob;
uint cbBlob;
if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
{
reader = new NativeReader(pBlob, cbBlob);
return true;
}
reader = default(NativeReader);
return false;
}
public unsafe IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
{
int delegateHashcode = delegateTypeHandle.GetHashCode();

Просмотреть файл

@ -17,8 +17,12 @@ namespace Internal.Runtime.CompilerHelpers
{
public static void InitializeLibrary()
{
#if CORERT
InteropCallbackManager.Initialize();
#else
__vtable_IUnknown.Initialize();
McgModuleManager.Initialize();
#endif
}
}
}

Просмотреть файл

@ -27,6 +27,7 @@
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
</ItemGroup>
<!-- TODO We should not include anything from CompilerServices directly -->
<ItemGroup>
@ -143,6 +144,12 @@
<Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
<Compile Include="Interop\Interop.Memory.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
<Compile Include="Internal\Runtime\CompilerHelpers\InteropCallbackManager.cs"/>
<Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs">
<Link>MetadataBlob.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="System\Runtime\InteropServices\ComTypes\advf.cs" />
<Compile Include="System\Runtime\InteropServices\ComTypes\bindopts.cs" />

Просмотреть файл

@ -66,11 +66,6 @@ namespace Internal.Runtime.TypeLoader
return TypeLoaderEnvironment.Instance.TryGetGenericVirtualTargetForTypeAndSlot(targetHandle, ref declaringType, genericArguments, ref methodName, ref methodSignature, out methodPointer, out dictionaryPointer, out slotUpdated);
}
public override IntPtr TryGetMarshallerForDelegate(RuntimeTypeHandle delegateTypeHandle)
{
return TypeLoaderEnvironment.Instance.TryGetMarshallerForDelegate(delegateTypeHandle);
}
/// <summary>
/// Register a new runtime-allocated code thunk in the diagnostic stream.
/// </summary>

Просмотреть файл

@ -399,7 +399,6 @@
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericsRegistration.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.ConstructedGenericTypesLookup.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.DelegateMarshallerLookup.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.FieldAccess.cs" />
<Compile Include="Internal\Runtime\TypeLoader\TypeLoaderEnvironment.GVMResolution.cs" />

Просмотреть файл

@ -59,6 +59,10 @@ namespace PInvokeTests
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
static extern bool ReversePInvoke_Int(Delegate_Int del);
delegate void Delegate_Unused();
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
static extern unsafe int* ReversePInvoke_Unused(Delegate_Unused del);
public static int Main(string[] args)
{
TestBlittableType();
@ -210,7 +214,17 @@ namespace PInvokeTests
Console.WriteLine("Testing Delegate");
Delegate_Int del = new Delegate_Int(Cube);
ThrowIfNotEquals(true, ReversePInvoke_Int(del), "Delegate marshalling failed.");
unsafe
{
//
// We haven't instantiated Delegate_Unused and nobody
// allocates it. If a EEType is not constructed for Delegate_Unused
// it will fail during linking.
//
ReversePInvoke_Unused(null);
}
}
static int Cube(int a)
{
return a*a*a;

Просмотреть файл

@ -204,3 +204,9 @@ DLL_EXPORT void __stdcall VerifyStringBuilder(unsigned short *val)
val[i] = (unsigned short)str[i];
val[i] = 0;
}
DLL_EXPORT int* __stdcall ReversePInvoke_Unused(void(__stdcall *fnPtr) (void))
{
return 0;
}