Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Use cross-module R2R generics from main module with version bubble (#…
Browse files Browse the repository at this point in the history
…27720)

* Ability to lookup the root module for precompiled R2R generics code
  • Loading branch information
Fadi Hanna authored Nov 8, 2019
1 parent e5add1d commit 69a5702
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ partial class CompilationModuleGroup
/// <returns>True if the given method versions with the current compilation module group</returns>
public virtual bool VersionsWithMethodBody(MethodDesc methodDesc) => ContainsMethodBody(methodDesc, unboxingStub: false);

/// <summary>
/// Returns true when a given module belongs to the same version bubble as the compilation module group.
/// </summary>
/// <param name="module">Module to check</param>
/// <returns>True if the given module versions with the current compilation module group</returns>
public abstract bool VersionsWithModule(ModuleDesc module);

public abstract bool GeneratesPInvoke(MethodDesc method);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ public class ManifestMetadataTableNode : HeaderTableNode
/// </summary>
private string _inputModuleName;

public ManifestMetadataTableNode(EcmaModule inputModule)
/// <summary>
/// Node factory for the compilation
/// </summary>
private readonly NodeFactory _nodeFactory;

public ManifestMetadataTableNode(EcmaModule inputModule, NodeFactory nodeFactory)
: base(inputModule.Context.Target)
{
_assemblyRefToModuleIdMap = new Dictionary<string, int>();
_manifestAssemblies = new List<AssemblyName>();
_signatureEmitters = new List<ISignatureEmitter>();
_nodeFactory = nodeFactory;

_inputModuleName = inputModule.Assembly.GetName().Name;

Expand All @@ -90,19 +96,26 @@ public void RegisterEmitter(ISignatureEmitter emitter)
public int ModuleToIndex(EcmaModule module)
{
AssemblyName assemblyName = module.Assembly.GetName();
int assemblyRefIndex;
if (!_assemblyRefToModuleIdMap.TryGetValue(assemblyName.Name, out assemblyRefIndex))

if (!_manifestAssemblies.Contains(assemblyName))
{
if (_emissionCompleted)
{
throw new Exception("mustn't add new assemblies after signatures have been materialized");
throw new InvalidOperationException("Adding a new assembly after signatures have been materialized.");
}

assemblyRefIndex = _nextModuleId++;
// If we're going to add a module to the manifest, it has to be part of the version bubble, otherwise
// the verification logic would be broken at runtime.
Debug.Assert(_nodeFactory.CompilationModuleGroup.VersionsWithModule(module));

_manifestAssemblies.Add(assemblyName);
_assemblyRefToModuleIdMap.Add(assemblyName.Name, assemblyRefIndex);
if (!_assemblyRefToModuleIdMap.ContainsKey(assemblyName.Name))
_assemblyRefToModuleIdMap.Add(assemblyName.Name, _nextModuleId);

_nextModuleId++;
}
return assemblyRefIndex;

return _assemblyRefToModuleIdMap[assemblyName.Name];
}

public override int ClassCode => 791828335;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ public override void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory>
MethodEntryPointTable = new MethodEntryPointTableNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.MethodDefEntryPoints, MethodEntryPointTable, MethodEntryPointTable);

ManifestMetadataTable = new ManifestMetadataTableNode(InputModuleContext.GlobalContext);
ManifestMetadataTable = new ManifestMetadataTableNode(InputModuleContext.GlobalContext, this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable);

Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ private bool ContainsTypeLayoutUncached(TypeDesc type)
return true;
}

public override bool VersionsWithModule(ModuleDesc module)
{
return _versionBubbleModuleSet.Contains(module);
}

public override bool VersionsWithType(TypeDesc typeDesc)
{
return typeDesc.GetTypeDefinition() is EcmaType ecmaType &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.

using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using System.Reflection.Metadata.Ecma335;

namespace ILCompiler
{
Expand All @@ -29,6 +31,11 @@ public override bool ContainsType(TypeDesc type)
return type == _method.OwningType;
}

public override bool VersionsWithModule(ModuleDesc module)
{
return ((EcmaMethod)_method.GetTypicalMethodDefinition()).Module == module;
}

public override bool GeneratesPInvoke(MethodDesc method)
{
return true;
Expand Down
12 changes: 12 additions & 0 deletions src/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,18 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig)
{
pCode = pModule->GetReadyToRunInfo()->GetEntryPoint(this, pConfig, TRUE /* fFixups */);
}

// Lookup in the entry point assembly for a R2R entrypoint (generics with large version bubble enabled)
if (pCode == NULL && HasClassOrMethodInstantiation() && SystemDomain::System()->DefaultDomain()->GetRootAssembly() != NULL)
{
pModule = SystemDomain::System()->DefaultDomain()->GetRootAssembly()->GetManifestModule();
_ASSERT(pModule != NULL);

if (pModule->IsReadyToRun() && pModule->IsInSameVersionBubble(GetModule()))
{
pCode = pModule->GetReadyToRunInfo()->GetEntryPoint(this, pConfig, TRUE /* fFixups */);
}
}
#endif
return pCode;
}
Expand Down

0 comments on commit 69a5702

Please sign in to comment.