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

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

@ -15,14 +15,24 @@ namespace Internal.IL.Stubs
/// </summary>
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);
_owningType = owningType;
_targetMethod = targetMethod;
}
public MethodDesc TargetMethod
{
get
{
return _targetMethod;
}
}
public PInvokeMetadata PInvokeMetadata
{
get
@ -91,7 +101,7 @@ namespace Internal.IL.Stubs
{
get
{
return (DefType)_targetMethod.OwningType;
return _owningType;
}
}

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

@ -21,6 +21,7 @@ namespace Internal.TypeSystem
private readonly ForwardDelegateCreationStubHashtable _forwardDelegateCreationStubHashtable;
private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable;
private readonly InlineArrayHashTable _inlineArrayHashtable;
private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable;
public InteropStateManager(ModuleDesc generatedAssembly)
{
@ -31,6 +32,7 @@ namespace Internal.TypeSystem
_forwardDelegateCreationStubHashtable = new ForwardDelegateCreationStubHashtable(this, _generatedAssembly.GetGlobalModuleType());
_pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly);
_inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly);
_pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType());
}
//
// Delegate Marshalling Stubs
@ -180,6 +182,10 @@ namespace Internal.TypeSystem
return _inlineArrayHashtable.GetOrCreateValue(candidate);
}
public FieldDesc GetPInvokeLazyFixupField(MethodDesc method)
{
return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method);
}
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;
}
}
}
}
}