Skip to content

Commit

Permalink
Support for multi-folder composite builds (#37130)
Browse files Browse the repository at this point in the history
This change adds support for Crossgen2 input files residing in a
directory structure; the same directory structure gets created
under the output path and the output composite image sits at its
root. The component R2R headers store the file name of the
composite image.

For unification and prevention of double loading we use a
dictionary keyed off simple names of the composite assemblies.
We can also use this mechanism for AssemblyLoadContext checking.
When we load a component assembly into two different ALC's, for the
second ALC (along the execution timeline) we cannot reuse the
composite image that got loaded into the first ALC and we cannot
load it a second time so we just pretend there's no image.

Thanks

Tomas
  • Loading branch information
trylek authored Jun 17, 2020
1 parent 147d3f1 commit 4a22294
Show file tree
Hide file tree
Showing 24 changed files with 492 additions and 145 deletions.
3 changes: 3 additions & 0 deletions src/coreclr/src/inc/CrstTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -702,3 +702,6 @@ End

Crst NativeImageEagerFixups
End

Crst NativeImageLoad
End
2 changes: 2 additions & 0 deletions src/coreclr/src/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_PartialNGen, W("PartialNGen"), (DWORD)-1, "Gen

CONFIG_DWORD_INFO(INTERNAL_NoASLRForNgen, W("NoASLRForNgen"), 0, "Turn off IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE bit in generated ngen images. Makes nidump output repeatable from run to run.")

RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_NativeImageSearchPaths, W("NativeImageSearchPaths"), "Extra search paths for native composite R2R images", CLRConfig::EEConfig_default)

#ifdef CROSSGEN_COMPILE
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CrossGenAssumeInputSigned, W("CrossGenAssumeInputSigned"), 1, "CrossGen should assume that its input assemblies will be signed before deployment")
#endif
Expand Down
125 changes: 64 additions & 61 deletions src/coreclr/src/inc/crsttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,67 +108,68 @@ enum CrstType
CrstNativeBinderInit = 89,
CrstNativeImageCache = 90,
CrstNativeImageEagerFixups = 91,
CrstNls = 92,
CrstNotifyGdb = 93,
CrstObjectList = 94,
CrstOnEventManager = 95,
CrstPatchEntryPoint = 96,
CrstPEImage = 97,
CrstPEImagePDBStream = 98,
CrstPendingTypeLoadEntry = 99,
CrstPinHandle = 100,
CrstPinnedByrefValidation = 101,
CrstProfilerGCRefDataFreeList = 102,
CrstProfilingAPIStatus = 103,
CrstPublisherCertificate = 104,
CrstRCWCache = 105,
CrstRCWCleanupList = 106,
CrstRCWRefCache = 107,
CrstReadyToRunEntryPointToMethodDescMap = 108,
CrstReDacl = 109,
CrstReflection = 110,
CrstReJITGlobalRequest = 111,
CrstRemoting = 112,
CrstRetThunkCache = 113,
CrstRWLock = 114,
CrstSavedExceptionInfo = 115,
CrstSaveModuleProfileData = 116,
CrstSecurityStackwalkCache = 117,
CrstSharedAssemblyCreate = 118,
CrstSigConvert = 119,
CrstSingleUseLock = 120,
CrstSpecialStatics = 121,
CrstSqmManager = 122,
CrstStackSampler = 123,
CrstStressLog = 124,
CrstStrongName = 125,
CrstStubCache = 126,
CrstStubDispatchCache = 127,
CrstStubUnwindInfoHeapSegments = 128,
CrstSyncBlockCache = 129,
CrstSyncHashLock = 130,
CrstSystemBaseDomain = 131,
CrstSystemDomain = 132,
CrstSystemDomainDelayedUnloadList = 133,
CrstThreadIdDispenser = 134,
CrstThreadpoolEventCache = 135,
CrstThreadpoolTimerQueue = 136,
CrstThreadpoolWaitThreads = 137,
CrstThreadpoolWorker = 138,
CrstThreadStaticDataHashTable = 139,
CrstThreadStore = 140,
CrstTieredCompilation = 141,
CrstTPMethodTable = 142,
CrstTypeEquivalenceMap = 143,
CrstTypeIDMap = 144,
CrstUMEntryThunkCache = 145,
CrstUMThunkHash = 146,
CrstUniqueStack = 147,
CrstUnresolvedClassLock = 148,
CrstUnwindInfoTableLock = 149,
CrstVSDIndirectionCellLock = 150,
CrstWrapperTemplate = 151,
kNumberOfCrstTypes = 152
CrstNativeImageLoad = 92,
CrstNls = 93,
CrstNotifyGdb = 94,
CrstObjectList = 95,
CrstOnEventManager = 96,
CrstPatchEntryPoint = 97,
CrstPEImage = 98,
CrstPEImagePDBStream = 99,
CrstPendingTypeLoadEntry = 100,
CrstPinHandle = 101,
CrstPinnedByrefValidation = 102,
CrstProfilerGCRefDataFreeList = 103,
CrstProfilingAPIStatus = 104,
CrstPublisherCertificate = 105,
CrstRCWCache = 106,
CrstRCWCleanupList = 107,
CrstRCWRefCache = 108,
CrstReadyToRunEntryPointToMethodDescMap = 109,
CrstReDacl = 110,
CrstReflection = 111,
CrstReJITGlobalRequest = 112,
CrstRemoting = 113,
CrstRetThunkCache = 114,
CrstRWLock = 115,
CrstSavedExceptionInfo = 116,
CrstSaveModuleProfileData = 117,
CrstSecurityStackwalkCache = 118,
CrstSharedAssemblyCreate = 119,
CrstSigConvert = 120,
CrstSingleUseLock = 121,
CrstSpecialStatics = 122,
CrstSqmManager = 123,
CrstStackSampler = 124,
CrstStressLog = 125,
CrstStrongName = 126,
CrstStubCache = 127,
CrstStubDispatchCache = 128,
CrstStubUnwindInfoHeapSegments = 129,
CrstSyncBlockCache = 130,
CrstSyncHashLock = 131,
CrstSystemBaseDomain = 132,
CrstSystemDomain = 133,
CrstSystemDomainDelayedUnloadList = 134,
CrstThreadIdDispenser = 135,
CrstThreadpoolEventCache = 136,
CrstThreadpoolTimerQueue = 137,
CrstThreadpoolWaitThreads = 138,
CrstThreadpoolWorker = 139,
CrstThreadStaticDataHashTable = 140,
CrstThreadStore = 141,
CrstTieredCompilation = 142,
CrstTPMethodTable = 143,
CrstTypeEquivalenceMap = 144,
CrstTypeIDMap = 145,
CrstUMEntryThunkCache = 146,
CrstUMThunkHash = 147,
CrstUniqueStack = 148,
CrstUnresolvedClassLock = 149,
CrstUnwindInfoTableLock = 150,
CrstVSDIndirectionCellLock = 151,
CrstWrapperTemplate = 152,
kNumberOfCrstTypes = 153
};

#endif // __CRST_TYPES_INCLUDED
Expand Down Expand Up @@ -271,6 +272,7 @@ int g_rgCrstLevelMap[] =
-1, // CrstNativeBinderInit
-1, // CrstNativeImageCache
0, // CrstNativeImageEagerFixups
0, // CrstNativeImageLoad
0, // CrstNls
0, // CrstNotifyGdb
2, // CrstObjectList
Expand Down Expand Up @@ -428,6 +430,7 @@ LPCSTR g_rgCrstNameMap[] =
"CrstNativeBinderInit",
"CrstNativeImageCache",
"CrstNativeImageEagerFixups",
"CrstNativeImageLoad",
"CrstNls",
"CrstNotifyGdb",
"CrstObjectList",
Expand Down
18 changes: 1 addition & 17 deletions src/coreclr/src/inc/shash.h
Original file line number Diff line number Diff line change
Expand Up @@ -1028,23 +1028,7 @@ class EMPTY_BASES_DECL MapSHash : public SHash< TRAITS >
PARENT::Add(KeyValuePair<KEY,VALUE>(key, value));
}

BOOL Lookup(KEY key, VALUE* pValue) const
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
PRECONDITION(key != (KEY)0);
}
CONTRACTL_END;

const KeyValuePair<KEY,VALUE> *pRet = PARENT::LookupPtr(key);
if (pRet == NULL)
return FALSE;

*pValue = pRet->Value();
return TRUE;
}
BOOL Lookup(KEY key, VALUE* pValue) const;
};

template <typename KEY, typename VALUE>
Expand Down
18 changes: 18 additions & 0 deletions src/coreclr/src/inc/shash.inl
Original file line number Diff line number Diff line change
Expand Up @@ -947,5 +947,23 @@ bool SHash<TRAITS>::CheckAddInPhases(
// 4. addCall's destructor will take care of any required cleanup.
}

template <typename KEY, typename VALUE, typename TRAITS>
BOOL MapSHash<KEY, VALUE, TRAITS>::Lookup(KEY key, VALUE* pValue) const
{
CONTRACTL
{
NOTHROW_UNLESS_TRAITS_THROWS;
GC_NOTRIGGER;
PRECONDITION(key != (KEY)0);
}
CONTRACTL_END;

const KeyValuePair<KEY,VALUE> *pRet = PARENT::LookupPtr(key);
if (pRet == NULL)
return FALSE;

*pValue = pRet->Value();
return TRUE;
}

#endif // _SHASH_INL_
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ public sealed class ReadyToRunCodegenCompilation : Compilation
/// </summary>
private readonly IEnumerable<string> _inputFiles;

private readonly string _compositeRootPath;

private bool _resilient;

private int _parallelism;
Expand All @@ -243,6 +245,7 @@ internal ReadyToRunCodegenCompilation(
Logger logger,
DevirtualizationManager devirtualizationManager,
IEnumerable<string> inputFiles,
string compositeRootPath,
InstructionSetSupport instructionSetSupport,
bool resilient,
bool generateMapFile,
Expand All @@ -268,6 +271,7 @@ internal ReadyToRunCodegenCompilation(
SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory);
_corInfoImpls = new ConditionalWeakTable<Thread, CorInfoImpl>();
_inputFiles = inputFiles;
_compositeRootPath = compositeRootPath;
CompilationModuleGroup = (ReadyToRunCompilationModuleGroupBase)nodeFactory.CompilationModuleGroup;

// Generate baseline support specification for InstructionSetSupport. This will prevent usage of the generated
Expand All @@ -281,7 +285,7 @@ internal ReadyToRunCodegenCompilation(
_fileLayoutOptimizer = new ReadyToRunFileLayoutOptimizer(methodLayoutAlgorithm, fileLayoutAlgorithm, profileData, _nodeFactory);
}


private readonly static string s_folderUpPrefix = ".." + Path.DirectorySeparatorChar;

public override void Compile(string outputFile)
{
Expand All @@ -299,13 +303,19 @@ public override void Compile(string outputFile)
if (moduleGroup.IsCompositeBuildMode)
{
// In composite mode with standalone MSIL we rewrite all input MSIL assemblies to the
// output folder, adding a format R2R header to them with forwarding information to
// output folder, adding a formal R2R header to them with forwarding information to
// the composite executable.
string outputDirectory = Path.GetDirectoryName(outputFile);
string ownerExecutableName = Path.GetFileName(outputFile);
foreach (string inputFile in _inputFiles)
{
string standaloneMsilOutputFile = Path.Combine(outputDirectory, Path.GetFileName(inputFile));
string relativeMsilPath = Path.GetRelativePath(_compositeRootPath, inputFile);
if (relativeMsilPath.StartsWith(s_folderUpPrefix))
{
// Input file not in the composite root, emit to root output folder
relativeMsilPath = Path.GetFileName(inputFile);
}
string standaloneMsilOutputFile = Path.Combine(outputDirectory, relativeMsilPath);
RewriteComponentFile(inputFile: inputFile, outputFile: standaloneMsilOutputFile, ownerExecutableName: ownerExecutableName);
}
}
Expand All @@ -316,6 +326,8 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow
{
EcmaModule inputModule = NodeFactory.TypeSystemContext.GetModuleFromPath(inputFile);

Directory.CreateDirectory(Path.GetDirectoryName(outputFile));

CopiedCorHeaderNode copiedCorHeader = new CopiedCorHeaderNode(inputModule);
DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule, outputFile);
NodeFactory componentFactory = new NodeFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace ILCompiler
public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
{
private readonly IEnumerable<string> _inputFiles;
private readonly string _compositeRootPath;
private bool _ibcTuning;
private bool _resilient;
private bool _generateMapFile;
Expand All @@ -38,10 +39,15 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
private KeyValuePair<string, string>[] _ryujitOptions = Array.Empty<KeyValuePair<string, string>>();
private ILProvider _ilProvider = new ReadyToRunILProvider();

public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, ReadyToRunCompilationModuleGroupBase group, IEnumerable<string> inputFiles)
public ReadyToRunCodegenCompilationBuilder(
CompilerTypeSystemContext context,
ReadyToRunCompilationModuleGroupBase group,
IEnumerable<string> inputFiles,
string compositeRootPath)
: base(context, group, new CoreRTNameMangler())
{
_inputFiles = inputFiles;
_compositeRootPath = compositeRootPath;

// R2R field layout needs compilation group information
((ReadyToRunCompilerContext)context).SetCompilationGroup(group);
Expand Down Expand Up @@ -224,6 +230,7 @@ public override ICompilation ToCompilation()
_logger,
new DependencyAnalysis.ReadyToRun.DevirtualizationManager(_compilationGroup),
_inputFiles,
_compositeRootPath,
_instructionSetSupport,
_resilient,
_generateMapFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class CommandLineOptions
public string[] Reference { get; set; }
public string InstructionSet { get; set; }
public FileInfo OutputFilePath { get; set; }

public DirectoryInfo CompositeRootPath { get; set; }
public bool Optimize { get; set; }
public bool OptimizeSpace { get; set; }
public bool OptimizeTime { get; set; }
Expand Down Expand Up @@ -92,6 +94,10 @@ public static Command RootCommand()
{
Argument = new Argument<FileInfo>()
},
new Option(new[] { "--compositerootpath", "--crp" }, SR.CompositeRootPath)
{
Argument = new Argument<DirectoryInfo>()
},
new Option(new[] { "--optimize", "-O" }, SR.EnableOptimizationsOption)
{
Argument = new Argument<bool>()
Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/src/tools/crossgen2/crossgen2/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ private int Run()
var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector());
CompilerTypeSystemContext typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode);

string compositeRootPath = _commandLineOptions.CompositeRootPath?.FullName;

//
// TODO: To support our pre-compiled test tree, allow input files that aren't managed assemblies since
// some tests contain a mixture of both managed and native binaries.
Expand All @@ -311,6 +313,10 @@ private int Run()
allInputFilePaths.Add(inputFile.Key, inputFile.Value);
inputFilePaths.Add(inputFile.Key, inputFile.Value);
referenceableModules.Add(module);
if (compositeRootPath == null)
{
compositeRootPath = Path.GetDirectoryName(inputFile.Value);
}
}
catch (TypeSystemException.BadImageFormatException)
{
Expand All @@ -329,6 +335,10 @@ private int Run()
allInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
unrootedInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
referenceableModules.Add(module);
if (compositeRootPath == null)
{
compositeRootPath = Path.GetDirectoryName(unrootedInputFile.Value);
}
}
}
catch (TypeSystemException.BadImageFormatException)
Expand Down Expand Up @@ -490,7 +500,7 @@ private int Run()
//

ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(
typeSystemContext, compilationGroup, allInputFilePaths.Values);
typeSystemContext, compilationGroup, allInputFilePaths.Values, compositeRootPath);
string compilationUnitPrefix = "";
builder.UseCompilationUnitPrefix(compilationUnitPrefix);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,7 @@
<data name="FileLayoutOption" xml:space="preserve">
<value>Layout non-method contents of file using profile driven optimization assuming the layout algorithm specified. The default value is DefaultSort, which indicates that complex layout is disabled</value>
</data>
<data name="CompositeRootPath" xml:space="preserve">
<value>Logical root folder for composite builds; defaults to directory of 1st input file.</value>
</data>
</root>
Loading

0 comments on commit 4a22294

Please sign in to comment.