Version resilient cross module code compilation and inlining - #71271
Conversation
…e generic compilation to Crossgen2 (dotnet#68919)" (dotnet#71076)" This reverts commit 89dc073.
New command line option: --opt-cross-module-pgo-module which adds modules where if they are specified via this switch, and there is PGO data then, methods with generics involving this module will be cross module inline eligible. This adds a requirement that loads of the specified modules must be loadable at any time during method resolution from the POV of the defined module. New handling in the runtime loader for cross module token loads from directly allowable extra modules as well as dependent loads. - The difference is that the dependent stuff should not be able to force load during the ILBody resolution phase of the fixup logic(Not yet implemented), and that the assembly is not necessarily directly loadable from the module that was compiled as R2R.
- The version resilience test had 2 major bugs in it 1. It was not properly specifying references, so references to other dlls were not being handled 2. It was generating .ni.dll files, which are not actually loaded by the runtime anymore, so even for the code it did generate, the cross module references were not in use. - In addition, fixing the build, caused us to generate an assertion when handling fields of sequential/explicit types from another module, where we did not generate a correct cross module version resilient fixup. (That's what the fix is in CorInfoImpl.ReadyToRun.cs) Disable pinvoke inlining across version bubbles Address assertion around byte array load of R2R file on unix
| @@ -264,6 +276,8 @@ fixup kind, the rest of the signature varies based on the fixup kind. | |||
| | READYTORUN_FIXUP_Verify_TypeLayout | 0x32 | Generate a runtime check to ensure that the field offset matches between compile and runtime. Unlike CheckFieldOffset, this will generate a runtime exception on failure instead of silently dropping the method | |||
| | READYTORUN_FIXUP_Check_VirtualFunctionOverride | 0x33 | Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, code will not be used. See [Virtual override signatures](virtual-override-signatures) for details of the signature used. | |||
| | READYTORUN_FIXUP_Verify_VirtualFunctionOverride | 0x33 | Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, generate runtime failure. See [Virtual override signatures](virtual-override-signatures) for details of the signature used. | |||
There was a problem hiding this comment.
Yes. that should be fixed.
…on of R2R versioning test. Its not needed and given the existence of bug 71507 is a problem
| Console.WriteLine($@"Duplicate symbol - 2nd occurrence: [{nodeIndex}:{symbolIndex}], {definedSymbol.GetMangledName(_nodeFactory.NameMangler)}"); | ||
| Debug.Fail("Duplicate node name emitted to file", | ||
| $"Symbol {definedSymbol.GetMangledName(_nodeFactory.NameMangler)} has already been written to the output object file {_objectFilePath} with symbol {alreadyWrittenSymbol}"); | ||
| // Debug.Fail("Duplicate node name emitted to file", |
There was a problem hiding this comment.
This looks like a useful assertion. Did you intend to leave it commented out?
There was a problem hiding this comment.
Sigh, yes, I'll turn this assert back on. I found a place where our name mangler wasn't completely competent at generating unique names. As I recall, it caused problems compiling Roslyn with the optimizations entirely enabled, but it was two method fixups which were very subtly distinct in their behavior.
There was a problem hiding this comment.
It's not a problem for crossgen in reality, as duplicate symbols are not actually a fault, but as we share a name mangler with NativeAOT it's probably worth chasing down sooner rather than later.
| { | ||
| if (_asyncStateMachineBox == null) | ||
| { | ||
| _asyncStateMachineBox = SystemModule.GetType("System.Runtime.CompilerServices", "AsyncTaskMethodBuilder`1").GetNestedType("AsyncStateMachineBox`1"); |
There was a problem hiding this comment.
Nit: We have a GetKnownType and GetKnownNestedType extension method that throws "nicer" exceptions when things are missing.
|
|
||
| if (localsBlob.Length == 0) | ||
| { | ||
| // No locals. Encode a 0 to indicate this |
There was a problem hiding this comment.
Could we just not write anything? I assume the length of the signature is part of the comparison at runtime, otherwise we would compare a method with no locals (0 written here) and a method with skiplocalsinit (0 written below) as equal.
There was a problem hiding this comment.
I want to be able to theoretically parse this thing in R2RDump one day. I'll change the encoding to encode a 2, which is reliably unique.
|
/azp run runtime-coreclr outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| OwnerCompositeExecutable = 116, // Added in 4.1 | ||
| PgoInstrumentationData = 117, // Added in 5.2 | ||
| ManifestAssemblyMvids = 118, // Added in 5.3 | ||
| CrossModuleInlineInfo = 119, // Added in 6.2 |
There was a problem hiding this comment.
Ah, yes. Jakob added 6.2 after I wrote this doc and I missed updating this detail.
Refactor Module into ModuleBase and Module
Build fixup to describe a single method as a standalone blob of data
Adjust module indices used within the R2R format to support a module index which refers to the R2R manifest metadata. This requires bumping the R2R version to 6.2
Adjust compilation dependency rules to include a few critical AsyncStateMachineBox methods
Remove PEImage handling of native metadata which was duplicative
Do not enable any more devirtualization than was already in use, even in the cross module compilation scenario. In particular, do not enable devirtualization of methods where the decl method isn't within the version bubble, even if the decl method could be represented with a cross module reference token. (This could be fixed, but is out of scope for this initial investigation)
Make the compilation deterministic in this new model, even though we are generating new tokens on demand
Compile the right set of methods with cross module inlining enabled
Add support for compiling the called virtual methods on generic types
Support input of PGO data to control the set of methods
Enable new
READYTORUN_FLAG_UNRELATED_R2R_CODEflag on R2R images which is used to indicate which modules may have generic code not directly related to the metadata of the imageLookup R2R methods in an
alternatelocation as well as the metadata defining module. This allows for many generics to be embedded without needing to use the newREADYTORUN_FLAG_UNRELATED_R2R_CODEflag, which has global effects on performance.Add command line switches to enable/disable the new behavior
Enhance the verion resilience test to cover this new behavior