Move ownership of p/invoke fixup cells (#4353)

The RVA static fields that represent p/invoke lazy fixup cells are
currently owned by the same type that owns the p/invoke. This means that
if the owning type has a static constructor, accessing the lazy fixup
cell with trigger it. The p/invoke should not trigger a beforefieldinit
class constructor though. I'm moving the field to be owned by the global
type in the compiler-generated pseudo assembly. It doesn't really matter
who owns it.
This commit is contained in:
Michal Strehovský 2017-08-22 08:23:30 -07:00 коммит произвёл GitHub
Родитель 5aca61df65
Коммит 61b3a728cf
3 изменённых файлов: 56 добавлений и 7 удалений

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

@ -238,8 +238,8 @@ namespace Internal.IL.Stubs
_importMetadata.Module, _importMetadata.Module,
_pInvokeILEmitterConfiguration)) _pInvokeILEmitterConfiguration))
{ {
MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); MetadataType lazyHelperType = context.GetHelperType("InteropHelpers");
FieldDesc lazyDispatchCell = new PInvokeLazyFixupField(_targetMethod); FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod);
fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell));
fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType
@ -251,7 +251,7 @@ namespace Internal.IL.Stubs
_targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType,
nativeParameterTypes); nativeParameterTypes);
ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(context
.GetWellKnownType(WellKnownType.IntPtr)); .GetWellKnownType(WellKnownType.IntPtr));
fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer);

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

@ -15,14 +15,24 @@ namespace Internal.IL.Stubs
/// </summary> /// </summary>
public sealed partial class PInvokeLazyFixupField : FieldDesc public sealed partial class PInvokeLazyFixupField : FieldDesc
{ {
private MethodDesc _targetMethod; private readonly DefType _owningType;
private readonly MethodDesc _targetMethod;
public PInvokeLazyFixupField(MethodDesc targetMethod) public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod)
{ {
Debug.Assert(targetMethod.IsPInvoke); Debug.Assert(targetMethod.IsPInvoke);
_owningType = owningType;
_targetMethod = targetMethod; _targetMethod = targetMethod;
} }
public MethodDesc TargetMethod
{
get
{
return _targetMethod;
}
}
public PInvokeMetadata PInvokeMetadata public PInvokeMetadata PInvokeMetadata
{ {
get get
@ -91,7 +101,7 @@ namespace Internal.IL.Stubs
{ {
get get
{ {
return (DefType)_targetMethod.OwningType; return _owningType;
} }
} }

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

@ -21,6 +21,7 @@ namespace Internal.TypeSystem
private readonly ForwardDelegateCreationStubHashtable _forwardDelegateCreationStubHashtable; private readonly ForwardDelegateCreationStubHashtable _forwardDelegateCreationStubHashtable;
private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable; private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable;
private readonly InlineArrayHashTable _inlineArrayHashtable; private readonly InlineArrayHashTable _inlineArrayHashtable;
private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable;
public InteropStateManager(ModuleDesc generatedAssembly) public InteropStateManager(ModuleDesc generatedAssembly)
{ {
@ -31,6 +32,7 @@ namespace Internal.TypeSystem
_forwardDelegateCreationStubHashtable = new ForwardDelegateCreationStubHashtable(this, _generatedAssembly.GetGlobalModuleType()); _forwardDelegateCreationStubHashtable = new ForwardDelegateCreationStubHashtable(this, _generatedAssembly.GetGlobalModuleType());
_pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly); _pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly);
_inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly); _inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly);
_pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType());
} }
// //
// Delegate Marshalling Stubs // Delegate Marshalling Stubs
@ -180,6 +182,10 @@ namespace Internal.TypeSystem
return _inlineArrayHashtable.GetOrCreateValue(candidate); return _inlineArrayHashtable.GetOrCreateValue(candidate);
} }
public FieldDesc GetPInvokeLazyFixupField(MethodDesc method)
{
return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method);
}
private class NativeStructTypeHashtable : LockFreeReaderHashtable<MetadataType, NativeStructType> private class NativeStructTypeHashtable : LockFreeReaderHashtable<MetadataType, NativeStructType>
{ {
@ -433,6 +439,39 @@ namespace Internal.TypeSystem
} }
} }
private class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable<MethodDesc, PInvokeLazyFixupField>
{
protected override int GetKeyHashCode(MethodDesc key)
{
return key.GetHashCode();
}
protected override int GetValueHashCode(PInvokeLazyFixupField value)
{
return value.TargetMethod.GetHashCode();
}
protected override bool CompareKeyToValue(MethodDesc key, PInvokeLazyFixupField value)
{
return key == value.TargetMethod;
}
protected override bool CompareValueToValue(PInvokeLazyFixupField value1, PInvokeLazyFixupField value2)
{
return value1.TargetMethod == value2.TargetMethod;
}
protected override PInvokeLazyFixupField CreateValueFromKey(MethodDesc key)
{
return new PInvokeLazyFixupField(_owningType, key);
}
private readonly DefType _owningType;
public PInvokeLazyFixupFieldHashtable(DefType owningType)
{
_owningType = owningType;
}
}
} }
} }