public override ICompilation ToCompilation() { ArrayBuilder <CorJitFlag> jitFlagBuilder = new ArrayBuilder <CorJitFlag>(); switch (_optimizationMode) { case OptimizationMode.None: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_DEBUG_CODE); break; case OptimizationMode.PreferSize: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_SIZE_OPT); break; case OptimizationMode.PreferSpeed: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_SPEED_OPT); break; default: // Not setting a flag results in BLENDED_CODE. break; } if (_optimizationMode != OptimizationMode.None && _profileDataManager != null) { jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_BBOPT); } // Do not bother with debug information if the debug info provider never gives anything. if (!(_debugInformationProvider is NullDebugInformationProvider)) { jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_DEBUG_INFO); } RyuJitCompilationOptions options = 0; 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)); }
public override ICompilation ToCompilation() { ArrayBuilder <CorJitFlag> jitFlagBuilder = new ArrayBuilder <CorJitFlag>(); switch (_optimizationMode) { case OptimizationMode.None: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_DEBUG_CODE); break; case OptimizationMode.PreferSize: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_SIZE_OPT); break; case OptimizationMode.PreferSpeed: jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_SPEED_OPT); break; default: // Not setting a flag results in BLENDED_CODE. break; } // Do not bother with debug information if the debug info provider never gives anything. if (!(_debugInformationProvider is NullDebugInformationProvider)) { jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_DEBUG_INFO); } if (_context.Target.MaximumSimdVectorLength != SimdVectorLength.None) { // TODO: AVX Debug.Assert(_context.Target.MaximumSimdVectorLength == SimdVectorLength.Vector128Bit); jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_FEATURE_SIMD); } RyuJitCompilationOptions options = 0; if (_methodBodyFolding) { options |= RyuJitCompilationOptions.MethodBodyFolding; } if (_singleThreaded) { options |= RyuJitCompilationOptions.SingleThreadedCompilation; } var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider, GetPreinitializationManager()); JitConfigProvider.Initialize(jitFlagBuilder.ToArray(), _ryujitOptions); DependencyAnalyzerBase <NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer())); return(new RyuJitCompilation(graph, factory, _compilationRoots, _ilProvider, _debugInformationProvider, _logger, _devirtualizationManager, _instructionSetSupport, options)); }
public override ICompilation ToCompilation() { // TODO: only copy COR headers for single-assembly build and for composite build with embedded MSIL IEnumerable <EcmaModule> inputModules = _compilationGroup.CompilationModuleSet; EcmaModule singleModule = _compilationGroup.IsCompositeBuildMode ? null : inputModules.First(); CopiedCorHeaderNode corHeaderNode = new CopiedCorHeaderNode(singleModule); // TODO: proper support for multiple input files DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(singleModule, _outputFile); // Produce a ResourceData where the IBC PROFILE_DATA entry has been filtered out // TODO: proper support for multiple input files ResourceData win32Resources = new ResourceData(inputModules.First(), (object type, object name, ushort language) => { if (!(type is string) || !(name is string)) { return(true); } if (language != 0) { return(true); } string typeString = (string)type; string nameString = (string)name; if ((typeString == "IBC") && (nameString == "PROFILE_DATA")) { return(false); } return(true); }); ReadyToRunFlags flags = ReadyToRunFlags.READYTORUN_FLAG_NonSharedPInvokeStubs; if (inputModules.All(module => module.IsPlatformNeutral)) { flags |= ReadyToRunFlags.READYTORUN_FLAG_PlatformNeutralSource; } flags |= _compilationGroup.GetReadyToRunFlags(); NodeFactory factory = new NodeFactory( _context, _compilationGroup, _nameMangler, corHeaderNode, debugDirectoryNode, win32Resources, flags); IComparer <DependencyNodeCore <NodeFactory> > comparer = new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer()); DependencyAnalyzerBase <NodeFactory> graph = CreateDependencyGraph(factory, comparer); List <CorJitFlag> corJitFlags = new List <CorJitFlag> { CorJitFlag.CORJIT_FLAG_DEBUG_INFO }; switch (_optimizationMode) { case OptimizationMode.None: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_DEBUG_CODE); break; case OptimizationMode.PreferSize: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_SIZE_OPT); break; case OptimizationMode.PreferSpeed: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_SPEED_OPT); break; default: // Not setting a flag results in BLENDED_CODE. break; } if (_ibcTuning) { corJitFlags.Add(CorJitFlag.CORJIT_FLAG_BBINSTR); } JitConfigProvider.Initialize(_context.Target, corJitFlags, _ryujitOptions, _jitPath); return(new ReadyToRunCodegenCompilation( graph, factory, _compilationRoots, _ilProvider, _logger, new DependencyAnalysis.ReadyToRun.DevirtualizationManager(_compilationGroup), _inputFiles, _compositeRootPath, _instructionSetSupport, _resilient, _generateMapFile, _parallelism, _profileData, _r2rMethodLayoutAlgorithm, _r2rFileLayoutAlgorithm, _customPESectionAlignment, _verifyTypeAndFieldLayout)); }
public override ICompilation ToCompilation() { ModuleTokenResolver moduleTokenResolver = new ModuleTokenResolver(_compilationGroup, _context); SignatureContext signatureContext = new SignatureContext(_inputModule, moduleTokenResolver); CopiedCorHeaderNode corHeaderNode = new CopiedCorHeaderNode(_inputModule); AttributePresenceFilterNode attributePresenceFilterNode = null; // Core library attributes are checked FAR more often than other dlls // attributes, so produce a highly efficient table for determining if they are // present. Other assemblies *MAY* benefit from this feature, but it doesn't show // as useful at this time. if (_inputModule == _inputModule.Context.SystemModule) { attributePresenceFilterNode = new AttributePresenceFilterNode(_inputModule); } // Produce a ResourceData where the IBC PROFILE_DATA entry has been filtered out ResourceData win32Resources = new ResourceData(_inputModule, (object type, object name, ushort language) => { if (!(type is string) || !(name is string)) { return(true); } if (language != 0) { return(true); } string typeString = (string)type; string nameString = (string)name; if ((typeString == "IBC") && (nameString == "PROFILE_DATA")) { return(false); } return(true); }); ReadyToRunCodegenNodeFactory factory = new ReadyToRunCodegenNodeFactory( _context, _compilationGroup, _nameMangler, moduleTokenResolver, signatureContext, corHeaderNode, win32Resources, attributePresenceFilterNode); IComparer <DependencyNodeCore <NodeFactory> > comparer = new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer()); DependencyAnalyzerBase <NodeFactory> graph = CreateDependencyGraph(factory, comparer); List <CorJitFlag> corJitFlags = new List <CorJitFlag> { CorJitFlag.CORJIT_FLAG_DEBUG_INFO }; switch (_optimizationMode) { case OptimizationMode.None: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_DEBUG_CODE); break; case OptimizationMode.PreferSize: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_SIZE_OPT); break; case OptimizationMode.PreferSpeed: corJitFlags.Add(CorJitFlag.CORJIT_FLAG_SPEED_OPT); break; default: // Not setting a flag results in BLENDED_CODE. break; } if (_ibcTuning) { corJitFlags.Add(CorJitFlag.CORJIT_FLAG_BBINSTR); } corJitFlags.Add(CorJitFlag.CORJIT_FLAG_FEATURE_SIMD); JitConfigProvider.Initialize(corJitFlags, _ryujitOptions, _jitPath); return(new ReadyToRunCodegenCompilation( graph, factory, _compilationRoots, _ilProvider, _logger, new DependencyAnalysis.ReadyToRun.DevirtualizationManager(_compilationGroup), _inputFilePath, new ModuleDesc[] { _inputModule }, _resilient, _generateMapFile, _parallelism)); }
public override IntPtr OnEntryPoint(MethodEntrypointPtr methodEntrypoint, IntPtr callerArgs) { lock (this) { if (_corInfoImpl == null) { InitJitCodeManager(RuntimeAugments.RhGetOSModuleForMrt()); // TODO: Recycle jit interface object and TypeSystemContext _context = TypeSystemContextFactory.Create(); Compilation compilation = new Compilation(_context); _nodeFactory = compilation.NodeFactory; JitConfigProvider.Initialize(new CorJitFlag[] { CorJitFlag.CORJIT_FLAG_DEBUG_CODE }, Array.Empty <KeyValuePair <string, string> >()); _corInfoImpl = new CorInfoImpl(compilation); } MethodDesc methodToCompile = methodEntrypoint.MethodIdentifier.ToMethodDesc(_context); JitMethodCodeNode codeNode = new JitMethodCodeNode(methodToCompile); _corInfoImpl.CompileMethod(codeNode); ObjectNode.ObjectData codeData = codeNode.GetData(null, false); List <ObjectNode> nodesToEmit = new List <ObjectNode>(); Dictionary <DependencyNodeCore <NodeFactory>, object> relocTargets = new Dictionary <DependencyNodeCore <NodeFactory>, object>(); int totalAllocSizeNeeded = 0; int nonObjectRelocTargets = 0; nodesToEmit.Add(codeNode); UpdateBytesUsed(codeNode.GetData(_nodeFactory), ref totalAllocSizeNeeded); int offsetOfEHData = totalAllocSizeNeeded; if (codeNode.EHInfo != null) { Debug.Assert(codeNode.EHInfo.Alignment == 1); // Assert needed as otherwise offsetOfEHData will be wrong UpdateBytesUsed(codeNode.EHInfo, ref totalAllocSizeNeeded); ComputeDependencySizeAndRelocData(codeNode.EHInfo, relocTargets, nodesToEmit, ref totalAllocSizeNeeded, ref nonObjectRelocTargets); } for (int i = 0; i < nodesToEmit.Count; i++) { ObjectNode objNode = nodesToEmit[i]; ComputeDependencySizeAndRelocData(objNode.GetData(_nodeFactory, true), relocTargets, nodesToEmit, ref totalAllocSizeNeeded, ref nonObjectRelocTargets); } if (nonObjectRelocTargets != 0) { totalAllocSizeNeeded = totalAllocSizeNeeded.AlignUp(IntPtr.Size); } int relocTargetOffsetStart = totalAllocSizeNeeded; DependencyNodeCore <NodeFactory>[] relocTargetsArray = new DependencyNodeCore <NodeFactory> [nonObjectRelocTargets]; { int iRelocTarget = 0; foreach (var relocTarget in relocTargets) { if (!(relocTarget.Key is ObjectNode)) { relocTargetsArray[iRelocTarget] = relocTarget.Key; totalAllocSizeNeeded += IntPtr.Size; iRelocTarget++; } } Debug.Assert(iRelocTarget == nonObjectRelocTargets); } GenericDictionaryCell[] genDictCells = new GenericDictionaryCell[relocTargetsArray.Length]; for (int iRelocTarget = 0; iRelocTarget < relocTargetsArray.Length; iRelocTarget++) { DependencyNodeCore <NodeFactory> relocTarget = relocTargetsArray[iRelocTarget]; GenericDictionaryCell newCell = null; if (relocTarget is ExternObjectSymbolNode) { var externObjectSymbolNode = (ExternObjectSymbolNode)relocTarget; var newMethodCell = externObjectSymbolNode.GetDictionaryCell(); newCell = newMethodCell; } if (newCell == null) { Environment.FailFast("Unknown reloc target type"); } genDictCells[iRelocTarget] = newCell; } IntPtr[] relocTargetsAsIntPtr = null; TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock( () => { TypeBuilderApi.ResolveMultipleCells(genDictCells, out relocTargetsAsIntPtr); }); // Layout of allocated memory... // ObjectNodes (aligned as appropriate) IntPtr pCodeManager; IntPtr jittedCode = AllocJittedCode(checked ((uint)totalAllocSizeNeeded), 8 /* TODO, alignment calculation */, out pCodeManager); int currentOffset = 0; foreach (var node in nodesToEmit) { ObjectNode.ObjectData objectData = node.GetData(_nodeFactory); EmitAndRelocData(objectData, jittedCode, relocTargetOffsetStart, ref currentOffset, relocTargetsArray, relocTargetsAsIntPtr); // EHInfo doesn't get its own node, but it does get emitted into the stream. if ((node == codeNode) && (codeNode.EHInfo != null)) { Debug.Assert(offsetOfEHData == currentOffset); EmitAndRelocData(codeNode.EHInfo, jittedCode, relocTargetOffsetStart, ref currentOffset, relocTargetsArray, relocTargetsAsIntPtr); } } foreach (IntPtr ptr in relocTargetsAsIntPtr) { currentOffset = currentOffset.AlignUp(IntPtr.Size); Marshal.WriteIntPtr(jittedCode, currentOffset, ptr); currentOffset += IntPtr.Size; } SetEHInfoPtr(pCodeManager, jittedCode, jittedCode + offsetOfEHData); IntPtr mainRuntimeFunction = IntPtr.Zero; for (int i = 0; i < codeNode.FrameInfos.Length; i++) { FrameInfo frame = codeNode.FrameInfos[i]; byte[] frameData = frame.BlobData; byte[] gcInfoData = Array.Empty <byte>(); byte[] gcInfoDataDeref = frameData; if (i == 0) { // For main function, add the gc info to the data gcInfoDataDeref = gcInfoData = codeNode.GCInfo; } IntPtr publishedFunction = PublishRuntimeFunction(pCodeManager, jittedCode, mainRuntimeFunction, checked ((uint)frame.StartOffset), checked ((uint)frame.EndOffset), frameData, checked ((uint)frameData.Length), gcInfoDataDeref, checked ((uint)gcInfoData.Length)); if (i == 0) { mainRuntimeFunction = publishedFunction; } } if (mainRuntimeFunction != IntPtr.Zero) { UpdateRuntimeFunctionTable(pCodeManager); } methodEntrypoint.MethodCode = jittedCode; return(jittedCode); } }