Skip to content

Unify threading between crossgen2 and ilc #63282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/workflow/debugging/coreclr/debugging-aot-compilers.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Built in debugging aids in the managed compilers
---------------------------------

- When debugging a multi-threaded component of the compiler and not investigating a multi-threading issue itself, it is generally advisable to disable the use of multiple threads.
To do this use the `--parallelism 1` switch (for crossgen2) or `--singlethreaded` (for ILC) to specify that the maximum parallelism of the process shall be 1.
To do this use the `--parallelism 1` switch to specify that the maximum parallelism of the process shall be 1.

- When debugging the behavior of compiling a single method, the compiler may be instructed to only compile a single method. This is done via the various --singlemethod options

Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/tools/Common/Compiler/CompilationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public abstract partial class CompilationBuilder
private DependencyTrackingLevel _dependencyTrackingLevel = DependencyTrackingLevel.None;
protected IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>();
protected OptimizationMode _optimizationMode = OptimizationMode.None;
protected int _parallelism = -1;

public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler)
{
Expand All @@ -41,6 +42,12 @@ public CompilationBuilder UseLogger(Logger logger)
return this;
}

public CompilationBuilder UseParallelism(int parallelism)
{
_parallelism = parallelism;
return this;
}

public CompilationBuilder UseCompilationUnitPrefix(string prefix)
{
_nameMangler.CompilationUnitPrefix = prefix;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ partial class CompilationBuilder
protected MethodImportationErrorProvider _methodImportationErrorProvider = new MethodImportationErrorProvider();
protected IInliningPolicy _inliningPolicy;
protected bool _methodBodyFolding;
protected bool _singleThreaded;
protected InstructionSetSupport _instructionSetSupport;
protected SecurityMitigationOptions _mitigationOptions;

Expand Down Expand Up @@ -92,12 +91,6 @@ public CompilationBuilder UseMethodBodyFolding(bool enable)
return this;
}

public CompilationBuilder UseSingleThread(bool enable)
{
_singleThreaded = enable;
return this;
}

public CompilationBuilder UsePreinitializationManager(PreinitializationManager manager)
{
_preinitializationManager = manager;
Expand Down
34 changes: 10 additions & 24 deletions src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;

using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysisFramework;

using Internal.IL;
using Internal.IL.Stubs;
using Internal.JitInterface;
using Internal.TypeSystem;
using Internal.ReadyToRunConstants;

using Debug = System.Diagnostics.Debug;
using Internal.JitInterface;

namespace ILCompiler
{
Expand All @@ -26,8 +26,7 @@ namespace ILCompiler
/// </summary>
internal sealed class ILScanner : Compilation, IILScanner
{
private CountdownEvent _compilationCountdown;
private readonly bool _singleThreaded;
private readonly int _parallelism;

internal ILScanner(
DependencyAnalyzerBase<NodeFactory> dependencyGraph,
Expand All @@ -36,11 +35,11 @@ internal ILScanner(
ILProvider ilProvider,
DebugInformationProvider debugInformationProvider,
Logger logger,
bool singleThreaded)
int parallelism)
: base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, null, nodeFactory.CompilationModuleGroup, logger)
{
_helperCache = new HelperCache(this);
_singleThreaded = singleThreaded;
_parallelism = parallelism;
}

protected override void CompileInternal(string outputFile, ObjectDumper dumper)
Expand Down Expand Up @@ -78,7 +77,7 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
methodsToCompile.Add(methodCodeNodeNeedingCode);
}

if (_singleThreaded)
if (_parallelism == 1)
{
CompileSingleThreaded(methodsToCompile);
}
Expand All @@ -95,18 +94,10 @@ private void CompileMultiThreaded(List<ScannedMethodNode> methodsToCompile)
Logger.Writer.WriteLine($"Scanning {methodsToCompile.Count} methods...");
}

WaitCallback compileSingleMethodDelegate = m => CompileSingleMethod((ScannedMethodNode)m);

using (_compilationCountdown = new CountdownEvent(methodsToCompile.Count))
{
foreach (ScannedMethodNode methodCodeNodeNeedingCode in methodsToCompile)
{
ThreadPool.QueueUserWorkItem(compileSingleMethodDelegate, methodCodeNodeNeedingCode);
}

_compilationCountdown.Wait();
_compilationCountdown = null;
}
Parallel.ForEach(
methodsToCompile,
new ParallelOptions { MaxDegreeOfParallelism = _parallelism },
CompileSingleMethod);
}

private void CompileSingleThreaded(List<ScannedMethodNode> methodsToCompile)
Expand Down Expand Up @@ -142,11 +133,6 @@ private void CompileSingleMethod(ScannedMethodNode methodCodeNodeNeedingCode)
{
throw new CodeGenerationFailedException(method, ex);
}
finally
{
if (_compilationCountdown != null)
_compilationCountdown.Signal();
}
}

ILScanResults IILScanner.Scan()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public sealed class ILScannerBuilder
private IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>();
private MetadataManager _metadataManager;
private InteropStubManager _interopStubManager = new EmptyInteropStubManager();
private bool _singleThreaded;
private int _parallelism = -1;

internal ILScannerBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler mangler, ILProvider ilProvider, PreinitializationManager preinitializationManager)
{
Expand Down Expand Up @@ -63,9 +63,9 @@ public ILScannerBuilder UseInteropStubManager(InteropStubManager interopStubMana
return this;
}

public ILScannerBuilder UseSingleThread(bool enable)
public ILScannerBuilder UseParallelism(int parallelism)
{
_singleThreaded = enable;
_parallelism = parallelism;
return this;
}

Expand All @@ -74,7 +74,7 @@ public IILScanner ToILScanner()
var nodeFactory = new ILScanNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _preinitializationManager);
DependencyAnalyzerBase<NodeFactory> graph = _dependencyTrackingLevel.CreateDependencyGraph(nodeFactory);

return new ILScanner(graph, nodeFactory, _compilationRoots, _ilProvider, new NullDebugInformationProvider(), _logger, _singleThreaded);
return new ILScanner(graph, nodeFactory, _compilationRoots, _ilProvider, new NullDebugInformationProvider(), _logger, _parallelism);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
private string _perfMapPath;
private int _perfMapFormatVersion;
private bool _generateProfileFile;
private int _parallelism;
Func<MethodDesc, string> _printReproInstructions;
private InstructionSetSupport _instructionSetSupport;
private ProfileDataManager _profileData;
Expand Down Expand Up @@ -170,12 +169,6 @@ public ReadyToRunCodegenCompilationBuilder UseProfileFile(bool generateProfileFi
return this;
}

public ReadyToRunCodegenCompilationBuilder UseParallelism(int parallelism)
{
_parallelism = parallelism;
return this;
}

public ReadyToRunCodegenCompilationBuilder UsePrintReproInstructions(Func<MethodDesc, string> printReproInstructions)
{
_printReproInstructions = printReproInstructions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysisFramework;
Expand All @@ -21,10 +22,10 @@ public sealed class RyuJitCompilation : Compilation
private readonly ConditionalWeakTable<Thread, CorInfoImpl> _corinfos = new ConditionalWeakTable<Thread, CorInfoImpl>();
internal readonly RyuJitCompilationOptions _compilationOptions;
private readonly ExternSymbolMappedField _hardwareIntrinsicFlags;
private CountdownEvent _compilationCountdown;
private readonly Dictionary<string, InstructionSet> _instructionSetMap;
private readonly ProfileDataManager _profileDataManager;
private readonly MethodImportationErrorProvider _methodImportationErrorProvider;
private readonly int _parallelism;

public InstructionSetSupport InstructionSetSupport { get; }

Expand All @@ -40,7 +41,8 @@ internal RyuJitCompilation(
InstructionSetSupport instructionSetSupport,
ProfileDataManager profileDataManager,
MethodImportationErrorProvider errorProvider,
RyuJitCompilationOptions options)
RyuJitCompilationOptions options,
int parallelism)
: base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, devirtualizationManager, inliningPolicy, logger)
{
_compilationOptions = options;
Expand All @@ -59,6 +61,8 @@ internal RyuJitCompilation(
_profileDataManager = profileDataManager;

_methodImportationErrorProvider = errorProvider;

_parallelism = parallelism;
}

public ProfileDataManager ProfileData => _profileDataManager;
Expand Down Expand Up @@ -125,7 +129,7 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
methodsToCompile.Add(methodCodeNodeNeedingCode);
}

if ((_compilationOptions & RyuJitCompilationOptions.SingleThreadedCompilation) != 0)
if (_parallelism == 1)
{
CompileSingleThreaded(methodsToCompile);
}
Expand All @@ -141,23 +145,10 @@ private void CompileMultiThreaded(List<MethodCodeNode> methodsToCompile)
Logger.Writer.WriteLine($"Compiling {methodsToCompile.Count} methods...");
}

WaitCallback compileSingleMethodDelegate = m =>
{
CorInfoImpl corInfo = _corinfos.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this));
CompileSingleMethod(corInfo, (MethodCodeNode)m);
};

using (_compilationCountdown = new CountdownEvent(methodsToCompile.Count))
{

foreach (MethodCodeNode methodCodeNodeNeedingCode in methodsToCompile)
{
ThreadPool.QueueUserWorkItem(compileSingleMethodDelegate, methodCodeNodeNeedingCode);
}

_compilationCountdown.Wait();
_compilationCountdown = null;
}
Parallel.ForEach(
methodsToCompile,
new ParallelOptions { MaxDegreeOfParallelism = _parallelism },
CompileSingleMethod);
}


Expand All @@ -176,52 +167,50 @@ private void CompileSingleThreaded(List<MethodCodeNode> methodsToCompile)
}
}

private void CompileSingleMethod(MethodCodeNode methodCodeNodeNeedingCode)
{
CorInfoImpl corInfo = _corinfos.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this));
CompileSingleMethod(corInfo, methodCodeNodeNeedingCode);
}

private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeNodeNeedingCode)
{
try
{
MethodDesc method = methodCodeNodeNeedingCode.Method;
MethodDesc method = methodCodeNodeNeedingCode.Method;

TypeSystemException exception = _methodImportationErrorProvider.GetCompilationError(method);
TypeSystemException exception = _methodImportationErrorProvider.GetCompilationError(method);

// If we previously failed to import the method, do not try to import it again and go
// directly to the error path.
if (exception == null)
// If we previously failed to import the method, do not try to import it again and go
// directly to the error path.
if (exception == null)
{
try
{
try
{
corInfo.CompileMethod(methodCodeNodeNeedingCode);
}
catch (TypeSystemException ex)
{
exception = ex;
}
corInfo.CompileMethod(methodCodeNodeNeedingCode);
}

if (exception != null)
catch (TypeSystemException ex)
{
// TODO: fail compilation if a switch was passed

// Try to compile the method again, but with a throwing method body this time.
MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception);
corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL);

if (exception is TypeSystemException.InvalidProgramException
&& method.OwningType is MetadataType mdOwningType
&& mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute"))
{
Logger.LogWarning("COM interop is not supported with full ahead of time compilation", 3052, method, MessageSubCategory.AotAnalysis);
}
else
{
Logger.LogWarning($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis);
}
exception = ex;
}
}
finally

if (exception != null)
{
if (_compilationCountdown != null)
_compilationCountdown.Signal();
// TODO: fail compilation if a switch was passed

// Try to compile the method again, but with a throwing method body this time.
MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception);
corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL);

if (exception is TypeSystemException.InvalidProgramException
&& method.OwningType is MetadataType mdOwningType
&& mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute"))
{
Logger.LogWarning("COM interop is not supported with full ahead of time compilation", 3052, method, MessageSubCategory.AotAnalysis);
}
else
{
Logger.LogWarning($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis);
}
}
}

Expand Down Expand Up @@ -252,7 +241,6 @@ public override MethodIL GetMethodIL(MethodDesc method)
public enum RyuJitCompilationOptions
{
MethodBodyFolding = 0x1,
SingleThreadedCompilation = 0x2,
ControlFlowGuardAnnotations = 0x4,
ControlFlowGuardAnnotations = 0x2,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,14 @@ public override ICompilation ToCompilation()
if (_methodBodyFolding)
options |= RyuJitCompilationOptions.MethodBodyFolding;

if (_singleThreaded)
options |= RyuJitCompilationOptions.SingleThreadedCompilation;

if ((_mitigationOptions & SecurityMitigationOptions.ControlFlowGuardAnnotations) != 0)
options |= RyuJitCompilationOptions.ControlFlowGuardAnnotations;

var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider, GetPreinitializationManager());

JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions);
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer()));
return new RyuJitCompilation(graph, factory, _compilationRoots, _ilProvider, _debugInformationProvider, _logger, _devirtualizationManager, _inliningPolicy ?? _compilationGroup, _instructionSetSupport, _profileDataManager, _methodImportationErrorProvider, options);
return new RyuJitCompilation(graph, factory, _compilationRoots, _ilProvider, _debugInformationProvider, _logger, _devirtualizationManager, _inliningPolicy ?? _compilationGroup, _instructionSetSupport, _profileDataManager, _methodImportationErrorProvider, options, _parallelism);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<OutputType>Library</OutputType>
<RootNamespace>ILCompiler</RootNamespace>
<AssemblyName>ILCompiler.RyuJit</AssemblyName>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Platforms>x64;x86</Platforms>
Expand Down
Loading