未验证 提交 c74a3fdf 编写于 作者: J Jan Kotas 提交者: GitHub

Delete AssemblyBuilderData and ModuleBuilderData (#66996)

There is no good reason for these to be separate types.
Co-authored-by: NTheodore Tsirpanis <teo@tsirpanis.gr>
上级 d22aceff
......@@ -156,7 +156,6 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\Associates.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\ConstructorInfo.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilderData.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\ConstructorBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\CustomAttributeBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicILGenerator.cs" />
......@@ -170,7 +169,6 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\MethodBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\MethodBuilderInstantiation.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\ModuleBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\ModuleBuilderData.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\ParameterBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\PropertyBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\SignatureHelper.cs" />
......
......@@ -23,31 +23,13 @@ public sealed partial class AssemblyBuilder : Assembly
#region Internal Data Members
// This is only valid in the "external" AssemblyBuilder
internal AssemblyBuilderData _assemblyData;
internal readonly AssemblyBuilderAccess _access;
private readonly RuntimeAssembly _internalAssembly;
private ModuleBuilder _manifestModuleBuilder;
private readonly ModuleBuilder _manifestModuleBuilder;
// Set to true if the manifest module was returned by code:DefineDynamicModule to the user
private bool _isManifestModuleUsedAsDefinedModule;
private const string ManifestModuleName = "RefEmit_InMemoryManifestModule";
internal ModuleBuilder GetModuleBuilder(RuntimeModule module)
{
Debug.Assert(module != null);
Debug.Assert(InternalAssembly == module.Assembly);
lock (SyncRoot)
{
// in CoreCLR there is only one module in each dynamic assembly, the manifest module
if (_manifestModuleBuilder.InternalModule == module)
{
return _manifestModuleBuilder;
}
throw new ArgumentException(null, nameof(module));
}
}
private const int AssemblyDefToken = 0x20000001;
internal object SyncRoot => InternalAssembly.SyncRoot;
......@@ -99,11 +81,16 @@ internal ModuleBuilder GetModuleBuilder(RuntimeModule module)
ObjectHandleOnStack.Create(ref retAssembly));
_internalAssembly = retAssembly!;
_assemblyData = new AssemblyBuilderData(access);
_access = access;
// Make sure that ManifestModule is properly initialized
// We need to do this before setting any CustomAttribute
InitManifestModule();
RuntimeModule internalModule = (RuntimeModule)GetInMemoryAssemblyModule(InternalAssembly);
// Note that this ModuleBuilder cannot be used for RefEmit yet
// because it hasn't been initialized.
// However, it can be used to set the custom attribute on the Assembly
_manifestModuleBuilder = new ModuleBuilder(this, internalModule);
if (assemblyAttributes != null)
{
......@@ -114,27 +101,6 @@ internal ModuleBuilder GetModuleBuilder(RuntimeModule module)
}
}
[MemberNotNull(nameof(_manifestModuleBuilder))]
private void InitManifestModule()
{
RuntimeModule modBuilder = (RuntimeModule)GetInMemoryAssemblyModule(InternalAssembly);
// Note that this ModuleBuilder cannot be used for RefEmit yet
// because it hasn't been initialized.
// However, it can be used to set the custom attribute on the Assembly
_manifestModuleBuilder = new ModuleBuilder(this, modBuilder);
// We are only setting the name in the managed ModuleBuilderData here.
// The name in the underlying metadata will be set when the
// manifest module is created during CreateDynamicAssembly.
// This name needs to stay in sync with that used in
// Assembly::Init to call ReflectionModule::Create (in VM)
_manifestModuleBuilder.Init(ManifestModuleName);
_isManifestModuleUsedAsDefinedModule = false;
}
#endregion
#region DefineDynamicAssembly
......@@ -220,24 +186,22 @@ private ModuleBuilder DefineDynamicModuleInternalNoLock(string name)
throw new InvalidOperationException(SR.InvalidOperation_NoMultiModuleAssembly);
}
Debug.Assert(_assemblyData != null, "_assemblyData is null in DefineDynamicModuleInternal");
// Init(...) has already been called on _manifestModuleBuilder in InitManifestModule()
ModuleBuilder dynModule = _manifestModuleBuilder;
_assemblyData._moduleBuilderList.Add(dynModule);
if (dynModule == _manifestModuleBuilder)
{
// We are reusing manifest module as user-defined dynamic module
_isManifestModuleUsedAsDefinedModule = true;
}
// We are reusing manifest module as user-defined dynamic module
_isManifestModuleUsedAsDefinedModule = true;
return dynModule;
return _manifestModuleBuilder;
}
#endregion
/// <summary>
/// Helper to ensure the type name is unique underneath assemblyBuilder.
/// </summary>
internal void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingType)
{
_manifestModuleBuilder.CheckTypeNameConflict(strTypeName, enclosingType);
}
internal static void CheckContext(params Type[]?[]? typess)
{
if (typess == null)
......@@ -355,12 +319,11 @@ internal static void CheckContext(params Type?[]? types)
{
ArgumentException.ThrowIfNullOrEmpty(name);
for (int i = 0; i < _assemblyData._moduleBuilderList.Count; i++)
if (_isManifestModuleUsedAsDefinedModule)
{
ModuleBuilder moduleBuilder = _assemblyData._moduleBuilderList[i];
if (moduleBuilder._moduleData._moduleName.Equals(name))
if (ModuleBuilder.ManifestModuleName == name)
{
return moduleBuilder;
return _manifestModuleBuilder;
}
}
return null;
......@@ -375,7 +338,7 @@ public void SetCustomAttribute(ConstructorInfo con!!, byte[] binaryAttribute!!)
{
TypeBuilder.DefineCustomAttribute(
_manifestModuleBuilder, // pass in the in-memory assembly module
AssemblyBuilderData.AssemblyDefToken,
AssemblyDefToken,
_manifestModuleBuilder.GetConstructorToken(con),
binaryAttribute);
}
......@@ -388,7 +351,7 @@ public void SetCustomAttribute(CustomAttributeBuilder customBuilder!!)
{
lock (SyncRoot)
{
customBuilder.CreateCustomAttribute(_manifestModuleBuilder, AssemblyBuilderData.AssemblyDefToken);
customBuilder.CreateCustomAttribute(_manifestModuleBuilder, AssemblyDefToken);
}
}
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
namespace System.Reflection.Emit
{
/// <summary>
/// This is a package private class. This class hold all of the managed
/// data member for AssemblyBuilder. Note that what ever data members added to
/// this class cannot be accessed from the EE.
/// </summary>
internal sealed class AssemblyBuilderData
{
public const int AssemblyDefToken = 0x20000001;
public readonly List<ModuleBuilder> _moduleBuilderList;
public readonly AssemblyBuilderAccess _access;
internal AssemblyBuilderData(AssemblyBuilderAccess access)
{
_access = access;
_moduleBuilderList = new List<ModuleBuilder>();
}
/// <summary>
/// Helper to ensure the type name is unique underneath assemblyBuilder.
/// </summary>
public void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingType)
{
for (int i = 0; i < _moduleBuilderList.Count; i++)
{
ModuleBuilder curModule = _moduleBuilderList[i];
curModule.CheckTypeNameConflict(strTypeName, enclosingType);
}
}
}
}
......@@ -47,15 +47,19 @@ internal static string UnmangleTypeName(string typeName)
#region Internal Data Members
// _TypeBuilder contains both TypeBuilder and EnumBuilder objects
private Dictionary<string, Type> _typeBuilderDict = null!;
internal ModuleBuilderData _moduleData = null!;
internal RuntimeModule _internalModule;
// _typeBuilderDict contains both TypeBuilder and EnumBuilder objects
private readonly Dictionary<string, Type> _typeBuilderDict;
private readonly TypeBuilder _globalTypeBuilder;
private bool _hasGlobalBeenCreated;
internal readonly RuntimeModule _internalModule;
// This is the "external" AssemblyBuilder
// only the "external" ModuleBuilder has this set
private readonly AssemblyBuilder _assemblyBuilder;
internal AssemblyBuilder ContainingAssemblyBuilder => _assemblyBuilder;
internal const string ManifestModuleName = "RefEmit_InMemoryManifestModule";
#endregion
#region Constructor
......@@ -64,6 +68,9 @@ internal ModuleBuilder(AssemblyBuilder assemblyBuilder, RuntimeModule internalMo
{
_internalModule = internalModule;
_assemblyBuilder = assemblyBuilder;
_globalTypeBuilder = new TypeBuilder(this);
_typeBuilderDict = new Dictionary<string, Type>();
}
#endregion
......@@ -94,7 +101,7 @@ internal void CheckTypeNameConflict(string strTypeName, Type? enclosingType)
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ModuleBuilder_GetTypeRef", StringMarshalling = StringMarshalling.Utf16)]
private static partial int GetTypeRef(QCallModule module, string strFullName, QCallModule refedModule, string? strRefedModuleFileName, int tkResolution);
private static partial int GetTypeRef(QCallModule module, string strFullName, QCallModule refedModule, int tkResolution);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ModuleBuilder_GetMemberRef")]
private static partial int GetMemberRef(QCallModule module, QCallModule refedModule, int tr, int defToken);
......@@ -195,7 +202,7 @@ private int GetTokenFromTypeSpec(byte[] signature, int length)
return null;
}
private int GetTypeRefNested(Type type, Module? refedModule, string? strRefedModuleFileName)
private int GetTypeRefNested(Type type, Module? refedModule)
{
// This function will generate correct TypeRef token for top level type and nested type.
Type? enclosingType = type.DeclaringType;
......@@ -204,7 +211,7 @@ private int GetTypeRefNested(Type type, Module? refedModule, string? strRefedMod
if (enclosingType != null)
{
tkResolution = GetTypeRefNested(enclosingType, refedModule, strRefedModuleFileName);
tkResolution = GetTypeRefNested(enclosingType, refedModule);
typeName = UnmangleTypeName(typeName);
}
......@@ -213,7 +220,7 @@ private int GetTypeRefNested(Type type, Module? refedModule, string? strRefedMod
ModuleBuilder thisModule = this;
RuntimeModule refedRuntimeModule = GetRuntimeModuleFromModule(refedModule);
return GetTypeRef(new QCallModule(ref thisModule), typeName, new QCallModule(ref refedRuntimeModule), strRefedModuleFileName, tkResolution);
return GetTypeRef(new QCallModule(ref thisModule), typeName, new QCallModule(ref refedRuntimeModule), tkResolution);
}
internal int InternalGetConstructorToken(ConstructorInfo con!!, bool usingRef)
......@@ -281,12 +288,6 @@ internal int InternalGetConstructorToken(ConstructorInfo con!!, bool usingRef)
return mr;
}
internal void Init(string strModuleName)
{
_moduleData = new ModuleBuilderData(this, strModuleName);
_typeBuilderDict = new Dictionary<string, Type>();
}
internal object SyncRoot => ContainingAssemblyBuilder.SyncRoot;
#endregion
......@@ -641,19 +642,7 @@ internal Type[] GetTypesNoLock()
if (baseType == null)
{
// try to find it among the unbaked types.
// starting with the current module first of all.
baseType = FindTypeBuilderWithName(baseName, ignoreCase);
if (baseType == null && Assembly is AssemblyBuilder)
{
// now goto Assembly level to find the type.
List<ModuleBuilder> modList = ContainingAssemblyBuilder._assemblyData._moduleBuilderList;
int size = modList.Count;
for (int i = 0; i < size && baseType == null; i++)
{
ModuleBuilder mBuilder = modList[i];
baseType = mBuilder.FindTypeBuilderWithName(baseName, ignoreCase);
}
}
if (baseType == null)
{
return null;
......@@ -669,7 +658,7 @@ internal Type[] GetTypesNoLock()
}
[RequiresAssemblyFiles(UnknownStringMessageInRAF)]
public override string FullyQualifiedName => _moduleData._moduleName;
public override string FullyQualifiedName => ManifestModuleName;
[RequiresUnreferencedCode("Trimming changes metadata tokens")]
public override byte[] ResolveSignature(int metadataToken)
......@@ -881,7 +870,7 @@ private EnumBuilder DefineEnumNoLock(string name, TypeAttributes visibility, Typ
AssemblyBuilder.CheckContext(returnType);
AssemblyBuilder.CheckContext(parameterTypes);
return _moduleData._globalTypeBuilder.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
return _globalTypeBuilder.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
}
}
......@@ -912,7 +901,7 @@ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes
Type? returnType, Type[]? requiredReturnTypeCustomModifiers, Type[]? optionalReturnTypeCustomModifiers,
Type[]? parameterTypes, Type[][]? requiredParameterTypeCustomModifiers, Type[][]? optionalParameterTypeCustomModifiers)
{
if (_moduleData._hasGlobalBeenCreated)
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
......@@ -927,7 +916,7 @@ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes
AssemblyBuilder.CheckContext(requiredParameterTypeCustomModifiers);
AssemblyBuilder.CheckContext(optionalParameterTypeCustomModifiers);
return _moduleData._globalTypeBuilder.DefineMethod(name, attributes, callingConvention,
return _globalTypeBuilder.DefineMethod(name, attributes, callingConvention,
returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
}
......@@ -942,13 +931,13 @@ public void CreateGlobalFunctions()
private void CreateGlobalFunctionsNoLock()
{
if (_moduleData._hasGlobalBeenCreated)
if (_hasGlobalBeenCreated)
{
// cannot create globals twice
throw new InvalidOperationException(SR.InvalidOperation_NotADebugModule);
}
_moduleData._globalTypeBuilder.CreateType();
_moduleData._hasGlobalBeenCreated = true;
_globalTypeBuilder.CreateType();
_hasGlobalBeenCreated = true;
}
#endregion
......@@ -972,12 +961,12 @@ private FieldBuilder DefineInitializedDataNoLock(string name, byte[] data, Field
// This method will define an initialized Data in .sdata.
// We will create a fake TypeDef to represent the data with size. This TypeDef
// will be the signature for the Field.
if (_moduleData._hasGlobalBeenCreated)
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
return _moduleData._globalTypeBuilder.DefineInitializedData(name, data, attributes);
return _globalTypeBuilder.DefineInitializedData(name, data, attributes);
}
public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
......@@ -994,12 +983,12 @@ private FieldBuilder DefineUninitializedDataNoLock(string name, int size, FieldA
// We will create a fake TypeDef to represent the data with size. This TypeDef
// will be the signature for the Field.
if (_moduleData._hasGlobalBeenCreated)
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
return _moduleData._globalTypeBuilder.DefineUninitializedData(name, size, attributes);
return _globalTypeBuilder.DefineUninitializedData(name, size, attributes);
}
#endregion
......@@ -1072,30 +1061,10 @@ private int GetTypeTokenWorkerNoLock(Type type!!, bool getGenericDefinition)
return paramBuilder.MetadataToken;
}
return GetTypeRefNested(type, this, string.Empty);
}
// After this point, the referenced module is not the same as the referencing
// module.
ModuleBuilder? refedModuleBuilder = refedModule as ModuleBuilder;
string referencedModuleFileName = string.Empty;
if (refedModule.Assembly.Equals(Assembly))
{
// if the referenced module is in the same assembly, the resolution
// scope of the type token will be a module ref, we will need
// the file name of the referenced module for that.
// if the refed module is in a different assembly, the resolution
// scope of the type token will be an assembly ref. We don't need
// the file name of the referenced module.
if (refedModuleBuilder == null)
{
refedModuleBuilder = ContainingAssemblyBuilder.GetModuleBuilder((RuntimeModule)refedModule);
}
referencedModuleFileName = refedModuleBuilder._moduleData._moduleName;
return GetTypeRefNested(type, this);
}
return GetTypeRefNested(type, refedModule, referencedModuleFileName);
return GetTypeRefNested(type, refedModule);
}
internal int GetMethodToken(MethodInfo method)
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Reflection.Emit
{
// This is a package private class. This class hold all of the managed
// data member for ModuleBuilder. Note that what ever data members added to
// this class cannot be accessed from the EE.
internal sealed class ModuleBuilderData
{
public const string MultiByteValueClass = "$ArrayType$";
public readonly TypeBuilder _globalTypeBuilder;
public readonly string _moduleName;
public bool _hasGlobalBeenCreated;
internal ModuleBuilderData(ModuleBuilder module, string moduleName)
{
_globalTypeBuilder = new TypeBuilder(module);
_moduleName = moduleName;
}
}
}
......@@ -485,7 +485,7 @@ private TypeBuilder(string szName, int genParamPos, TypeBuilder declType)
AssemblyBuilder containingAssem = m_module.ContainingAssemblyBuilder;
// cannot have two types within the same assembly of the same name
containingAssem._assemblyData.CheckTypeNameConflict(fullname, enclosingType);
containingAssem.CheckTypeNameConflict(fullname, enclosingType);
if (enclosingType != null)
{
......@@ -573,7 +573,7 @@ private FieldBuilder DefineDataHelper(string name, byte[]? data, int size, Field
ThrowIfCreated();
// form the value class name
strValueClassName = ModuleBuilderData.MultiByteValueClass + size.ToString();
strValueClassName = $"$ArrayType${size}";
// Is this already defined in this module?
Type? temp = m_module.FindTypeBuilderWithName(strValueClassName, false);
......@@ -2002,7 +2002,7 @@ private EventBuilder DefineEventNoLock(string name, EventAttributes attributes,
exceptions, (exceptions != null) ? exceptions.Length : 0,
tokenFixups, (tokenFixups != null) ? tokenFixups.Length : 0);
if (m_module.ContainingAssemblyBuilder._assemblyData._access == AssemblyBuilderAccess.Run)
if (m_module.ContainingAssemblyBuilder._access == AssemblyBuilderAccess.Run)
{
// if we don't need the data structures to build the method any more
// throw them away.
......
......@@ -24,7 +24,6 @@
extern "C" mdTypeRef QCALLTYPE ModuleBuilder_GetTypeRef(QCall::ModuleHandle pModule,
LPCWSTR wszFullName,
QCall::ModuleHandle pRefedModule,
LPCWSTR wszRefedModuleFileName,
INT32 tkResolutionArg)
{
QCALL_CONTRACT;
......@@ -85,35 +84,25 @@ extern "C" mdTypeRef QCALLTYPE ModuleBuilder_GetTypeRef(QCall::ModuleHandle pMod
else
{
// reference to top level type
if ( pThisAssembly != pRefedAssembly )
{
SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
// Generate AssemblyRef
IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit);
// Add the assembly ref token and the manifest module it is referring to this module's rid map.
// This is needed regardless of whether the dynamic assembly has run access. Even in Save-only
// or Refleciton-only mode, CreateType() of the referencing type may still need the referenced
// type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type.
//
// Don't cache if there is assembly associated with the token already. The assembly ref resolution
// can be ambiguous because of reflection emit does not require unique assembly names.
// We always let the first association win. Ideally, we would disallow this situation by throwing
// exception, but that would be a breaking change.
if(pModule->LookupAssemblyRef(tkResolution) == NULL)
{
pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly);
}
}
else
{
_ASSERTE(pModule != pRefedModule);
_ASSERTE(wszRefedModuleFileName != NULL);
// Generate ModuleRef
IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution));
SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
// Generate AssemblyRef
IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit);
// Add the assembly ref token and the manifest module it is referring to this module's rid map.
// This is needed regardless of whether the dynamic assembly has run access. Even in Save-only
// or Refleciton-only mode, CreateType() of the referencing type may still need the referenced
// type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type.
//
// Don't cache if there is assembly associated with the token already. The assembly ref resolution
// can be ambiguous because of reflection emit does not require unique assembly names.
// We always let the first association win. Ideally, we would disallow this situation by throwing
// exception, but that would be a breaking change.
if(pModule->LookupAssemblyRef(tkResolution) == NULL)
{
pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly);
}
}
......
......@@ -26,7 +26,6 @@ public:
extern "C" mdTypeRef QCALLTYPE ModuleBuilder_GetTypeRef(QCall::ModuleHandle pModule,
LPCWSTR wszFullName,
QCall::ModuleHandle pRefedModule,
LPCWSTR wszRefedModuleFileName,
INT32 tkResolution);
// SetFieldRVAContent
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册