|
protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCore<NodeFactory>> obj) |
|
{ |
|
using (PerfEventSource.StartStopEvents.JitEvents()) |
|
{ |
|
Action<DependencyNodeCore<NodeFactory>> compileOneMethod = (DependencyNodeCore<NodeFactory> dependency) => |
|
{ |
|
MethodWithGCInfo methodCodeNodeNeedingCode = dependency as MethodWithGCInfo; |
|
if (methodCodeNodeNeedingCode == null) |
|
{ |
|
if (dependency is DeferredTillPhaseNode deferredPhaseNode) |
|
{ |
|
if (Logger.IsVerbose) |
|
_logger.Writer.WriteLine($"Moved to phase {_nodeFactory.CompilationCurrentPhase}"); |
|
deferredPhaseNode.NotifyCurrentPhase(_nodeFactory.CompilationCurrentPhase); |
|
return; |
|
} |
|
} |
|
|
|
Debug.Assert((_nodeFactory.CompilationCurrentPhase == 0) || ((_nodeFactory.CompilationCurrentPhase == 2) && !_finishedFirstCompilationRunInPhase2)); |
|
|
|
MethodDesc method = methodCodeNodeNeedingCode.Method; |
|
|
|
if (Logger.IsVerbose) |
|
{ |
|
string methodName = method.ToString(); |
|
Logger.Writer.WriteLine("Compiling " + methodName); |
|
} |
|
|
|
if (_printReproInstructions != null) |
|
{ |
|
Logger.Writer.WriteLine($"Single method repro args:{_printReproInstructions(method)}"); |
|
} |
|
|
|
try |
|
{ |
|
using (PerfEventSource.StartStopEvents.JitMethodEvents()) |
|
{ |
|
// Create only 1 CorInfoImpl per thread. |
|
// This allows SuperPMI to rely on non-reuse of handles in ObjectToHandle |
|
CorInfoImpl corInfoImpl = _corInfoImpls.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this)); |
|
corInfoImpl.CompileMethod(methodCodeNodeNeedingCode, Logger); |
|
} |
|
} |
|
catch (TypeSystemException ex) |
|
{ |
|
// If compilation fails, don't emit code for this method. It will be Jitted at runtime |
|
if (Logger.IsVerbose) |
|
Logger.Writer.WriteLine($"Warning: Method `{method}` was not compiled because: {ex.Message}"); |
|
} |
|
catch (RequiresRuntimeJitException ex) |
|
{ |
|
if (Logger.IsVerbose) |
|
Logger.Writer.WriteLine($"Info: Method `{method}` was not compiled because `{ex.Message}` requires runtime JIT"); |
|
} |
|
catch (CodeGenerationFailedException ex) when (_resilient) |
|
{ |
|
if (Logger.IsVerbose) |
|
Logger.Writer.WriteLine($"Warning: Method `{method}` was not compiled because `{ex.Message}` requires runtime JIT"); |
|
} |
|
}; |
|
|
|
// Use only main thread to compile if parallelism is 1. This allows SuperPMI to rely on non-reuse of handles in ObjectToHandle |
|
if (Logger.IsVerbose) |
|
Logger.Writer.WriteLine($"Processing {obj.Count} dependencies"); |
|
if (_parallelism == 1) |
|
{ |
|
foreach (var dependency in obj) |
|
compileOneMethod(dependency); |
|
} |
|
else |
|
{ |
|
ParallelOptions options = new ParallelOptions |
|
{ |
|
MaxDegreeOfParallelism = _parallelism |
|
}; |
|
|
|
Parallel.ForEach(obj, options, compileOneMethod); |
|
} |
|
} |
|
|
|
if (_methodILCache.Count > 1000) |
|
{ |
|
_methodILCache = new ILCache(_methodILCache.ILProvider, NodeFactory.CompilationModuleGroup); |
|
} |
|
|
|
if (_nodeFactory.CompilationCurrentPhase == 2) |
|
{ |
|
_finishedFirstCompilationRunInPhase2 = true; |
|
} |
|
} |