Fix NeedsAlignedBaseOffset for composite R2R#35231
Conversation
|
/azp list |
There was a problem hiding this comment.
Exactly the same logic is now duplicated here and in the MethodTableBuilder::CheckLayoutDependsOnOtherModules. So it seems that this whole block can be replaced by
return pParentMT->GetClass()->HasLayoutDependsOnOtherModules();
trylek
left a comment
There was a problem hiding this comment.
LGTM, thanks for fixing these inconsistencies!
|
Add a multitude of tests and fix issues related to composite, input bubble and regular r2r crossgen build. The tests will need some refactoring once @nattress finishes his test harness work, but for now there is a batch script. |
- Crossgen2 and the runtime had different models for when the base type size needed to be aligned up - This only caused issues for composite crossgen2 builds as the logic was heavily module focussed - Also, the IsInSameVersionBubble logic was non-functional for composite build All of the following conditions must hold, or there shall be alignment inserted between a base and derived type - The derived type must declare that the base type is in the same version bubble as the derived type - The base type must declare that it was able to derive from its base type without needing alignment - The base type must not be instantiated over a valuetype where the valuetype instantiation contributes to the instance field layout of the base type, and that valuetype is not wholly defined in one bubble
crossgen, crossgen2, and crossgen2 with input bubble enable
Mostly works
99cb4f7 to
39d28b2
Compare
|
@dotnet/crossgen-contrib @jkotas This changes the field layout for non-R2R to follow rules similar to R2R in some somewhat rare cases. I'd like your opinion on that. |
It was a review of an earlier change
not the static layout.
| m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES; | ||
| } | ||
|
|
||
| inline BOOL HasLayoutDependsOnOtherVersionBubbles() |
There was a problem hiding this comment.
Do we really need both HasLayoutDependsOnOtherModules and HasLayoutDependsOnOtherVersionBubbles ?
I would expect to have just the version bubble one.
|
I am having hard time figuring out the reasons behind the rules. I would expect the rules to be: All of the following conditions must hold, or there shall be alignment inserted between a base and derived type
What am I missing? |
|
There are several issues fixed in this change, and the change description does not currently describe them well.
Layer 1 - All assemblies AOT compiled here will be compiled with /inputbubble enabled. Layer 2 Layer 3 The concern is for the layout of a class For The type clearly cannot exist during compilation of Layer1, as When Layer2 is being compiled, it will consider all components of However, when running the application, the version bubble algorithm will declare that The new algorithm as written uses a stricter definition for version bubble when considering layout that is caused by a generic instantiation. In particular, the version bubble rule retreats to consider the indivisible unit of the module which will cause both runtime and crossgen time compilation of The practical effect is that the /inputbubble switch becomes reliable as long as the assemblies statically depended on by the assembly under compilation are also compiled with the /inputbubble switch, or not compiled at all. The system no longer requires that ALL assemblies that might be compiled with the inputbubble switch be compiled knowing exactly the same set of references. |
|
Ok, your example makes sense. Would it make sense to have the R2R layout to be based exclusively on module boundaries, and never consider version bubbles for it to keep the rules simple? |
|
I believe we would have to force ALL type layout to follow the module local rules, not just R2R layout. As you say, its much simpler, and less complex to explain, and probably less risky going forward. I'm not convinced this new algorithm worth the risk, as I don't have good data either way how much we win from the non-aligned layout optimization. |
What would be the example that demonstrates we need to force ALL type layout to follow the module local rules? |
|
Its the same example as above, except for some reason we were unable to use the R2R image for the assembly which defined |
|
@mangod9 I've confirmed that this fix addresses the failures seen in running asp.net with composite enabled. |
We may be unable to use code from the R2R image, but we should be still able to see that this is R2R image and it should follow the R2R layout rules. |
|
That's a detail I don't actually believe is certain, and I'm somewhat uncomfortable with relying on every dependent image to be R2R'd. It could happen, but we have historically had discussion about crossgening only some files, etc. To be honest, I'm somewhat uncomfortable with the algorithm I wrote up as well, as it assumes that all crossgen used on a dependent must be compiled with inputbubble if some other module with inputbubble exists which depends on it. I feel this is somewhat more likely to be reliable, but again, its not something I'm convinced is a safe model. |
|
I wonder whether part of the trouble with --inputbubble may be in that it was designed with this "all-or-nothing" policy in mind. Now we're trying to improve on composability, would it help to just ditch the switch and instead use a new type of reference to define "those modules that won't be compiled into the R2R executable currently being produced but logically form a part of its version bubble", something like -rb (reference-bubble)? |
|
@trylek you're right, but @jkotas talked after the meeting today and came up with an approach that doesn't require that complexity.
|
…putbubble compiled assembly must be r2r compiled Fix R2RDump for composite images
| while (true) | ||
| { | ||
| Thread.Sleep(1000); | ||
| s_testFailObj = o; |
There was a problem hiding this comment.
Ah, that was temporary logic in the test to make it easier to debug. I'll delete the new code.
| </data> | ||
| <data name="CompileNoMethodsOption" xml:space="preserve"> | ||
| <value>True to not compile any methods into the R2R image (default = false)</value> | ||
| </data> |
There was a problem hiding this comment.
maybe: True to skip compiling methods into the R2R image?
There was a problem hiding this comment.
Again, I should never be allowed to write customer visible text. :) I like your wording better.
trylek
left a comment
There was a problem hiding this comment.
Looks awesome, thanks David for driving this to successful resolution!
| } | ||
| } | ||
|
|
||
| // Indicate |
There was a problem hiding this comment.
I fell asleep before finishing writing it... update on the way along with use of an enum instead of an int.
| { | ||
| EcmaModule module = (EcmaModule)nonEcmaModule; | ||
| if (IsModuleInCompilationGroup(module)) | ||
| return 2; |
There was a problem hiding this comment.
It would be nice to have enum or named constants for these 2 and 3.
There was a problem hiding this comment.
Agreed. I'm putting an enum together which should make this code somewhat easier to parse.
| } | ||
| } | ||
| #endif // FEATURE_READYTORUN_COMPILER | ||
| GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules(); |
There was a problem hiding this comment.
What is the case when this bit was not already set by the CheckLayoutDependsOnOtherModules?
There was a problem hiding this comment.
Hmm, it appears to be legacy from the other algorithm I wrote up. I'll remove it, and verify that the tests all pass.
|
|
||
| if "%COMPOSITENAME%"=="" goto done | ||
|
|
||
| set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll --composite %COMPILEARG% |
There was a problem hiding this comment.
I am surprised that "-r %CORE_ROOT%*" doesn't cause crossgen2 to fail for files that are not managed dlls.
There was a problem hiding this comment.
Crossgen2 filters out native dlls automatically; the only reason we're using more explicit reference file groups in CLRTest.Crossgen.targets and build-test.cmd/sh is to make it a bit faster and get rid of the annoying warning messages.
|
|
||
| if "%COMPOSITENAME%"=="" goto done | ||
|
|
||
| set BUILDCMD=%TESTBATCHROOT%\..\..\..\..\..\..\.dotnet\dotnet %CORE_ROOT%\crossgen2\crossgen2.dll -r %CORE_ROOT%\* -r %TESTINITIALBINPATH%\*.dll -o %TESTINITIALBINPATH%\%TESTTARGET_DIR%\%COMPOSITENAME%Composite.dll --composite %COMPILEARG% |
There was a problem hiding this comment.
A nit - it would be nice to extract the dotnet path to a variable. I also think that it is not guaranteed that the .dotnet folder exists. I believe that Viktor told me some time ago that it is not created in case you have the same version of dotnet installed on your machine. I think the right way is to use the dotnet.cmd/sh script in the root of the repo that takes care of locating the dotnet exe.
There was a problem hiding this comment.
This entire test harness of ugly batch files is temporary, to be replaced with whatever @nattress comes up with. The reason I use the exact path to the dotnet exe is that it allows for copying/pasting the printed build command and passing it as a launch argument to the debugger which saved me quite a lot of time during development. I don't intend to fix this before checkin.
| @@ -0,0 +1,322 @@ | |||
| echo off | |||
| setlocal | |||
| set TESTDIR=%~dp0\..\..\..\..\..\..\artifacts\tests\coreclr\Windows_NT.x64.Debug\readytorun\crossboundarylayout\crossboundarytest\crossboundarytest | |||
There was a problem hiding this comment.
Should this script get the arch / build flavor as arguments?
There was a problem hiding this comment.
In theory yes, but in practice, as this logic is entirely cross arch/os it only needs testing in one environment, and the goal is to delete these scripts as soon as @nattress produces a way to write these tests that is actually reasonable.
| @@ -0,0 +1,322 @@ | |||
| echo off | |||
There was a problem hiding this comment.
I wonder if this script (and the other ones) should be located in src/coreclr/tests/scripts instead.
janvorli
left a comment
There was a problem hiding this comment.
LGTM, just one tiny grammar nit.
…/ReadyToRunCompilationModuleGroupBase.cs Co-Authored-By: Jan Vorlicek <janvorli@microsoft.com>
Synchronize and correct NeedsAlignedBaseOffset
All of the following conditions must hold, or there shall be alignment inserted between a base and derived type
Also add a test for various mixed combinations