Skip to content
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

Remove base type rooting for types in rooted assemblies #92864

Merged
merged 5 commits into from
Oct 5, 2023

Conversation

vitek-karas
Copy link
Member

When rooting entire assemblies NativeAOT also roots all base types of all the types in such assembly. Regardless of which assembly the base type comes from. Historically this was necessary to make certain combinations of generic instantiations to work, but that's no longer the case. The compiler has better mechanism of tracking necessary things for generics now.

This rooting behavior brings in more code than necessary. This is specifically problematic when using the assembly rooting as a mechanism to test library trim/AOT compatibility. If the tested library depends on another library which has some incompatible code in it, but it's not used, ideally the compiler should remove the unused code and thus not see the incompatibilities. Rooting entire base types sometimes breaks that behavior and produces unnecessary warnings.

The product change is really just "don't root the base type", all of the rest of the change is tests. Modified existing test to validate more things around rooting behavior across assemblies. And then infrastructure changes to make it possible to use this test from NativeAOT.

This brings the behavior of NativeAOT and trimmer much closer with regard to assembly rooting.

Fixes #92271.

@ghost
Copy link

ghost commented Oct 1, 2023

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Issue Details

When rooting entire assemblies NativeAOT also roots all base types of all the types in such assembly. Regardless of which assembly the base type comes from. Historically this was necessary to make certain combinations of generic instantiations to work, but that's no longer the case. The compiler has better mechanism of tracking necessary things for generics now.

This rooting behavior brings in more code than necessary. This is specifically problematic when using the assembly rooting as a mechanism to test library trim/AOT compatibility. If the tested library depends on another library which has some incompatible code in it, but it's not used, ideally the compiler should remove the unused code and thus not see the incompatibilities. Rooting entire base types sometimes breaks that behavior and produces unnecessary warnings.

The product change is really just "don't root the base type", all of the rest of the change is tests. Modified existing test to validate more things around rooting behavior across assemblies. And then infrastructure changes to make it possible to use this test from NativeAOT.

This brings the behavior of NativeAOT and trimmer much closer with regard to assembly rooting.

Fixes #92271.

Author: vitek-karas
Assignees: vitek-karas
Labels:

area-NativeAOT-coreclr

Milestone: 9.0.0

Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but tests might need adjusting. Please also run nativeaot-outerloop before mergimg

@vitek-karas
Copy link
Member Author

I changed it to only "Stop" the old behavior for rooted assemblies. rd.xml rooting will remain as before.
It doesn't feel worth to possible break people with this change for rd.xml.

Updated the trimming tests accordingly.

@MichalStrehovsky
Copy link
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@vitek-karas
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

When rooting entire assemblies NativeAOT also roots all base types of all the types in such assembly. Regardless of which assembly the base type comes from. Historically this was necessary to make certain combinations of generic instantiations to work, but that's no longer the case. The compiler has better mechanism of tracking necessary things for generics now.

This rooting behavior brings in more code than necessary. This is specifically problematic when using the assembly rooting as a mechanism to test library trim/AOT compatibility. If the tested library depends on another library which has some incompatible code in it, but it's not used, ideally the compiler should remove the unused code and thus not see the incompatibilities. Rooting entire base types sometimes breaks that behavior and produces unnecessary warnings.

The product change is really just "don't root the base type", all of the rest of the change is tests. Modified existing test to validate more things around rooting behavior across assemblies. And then infrastructure changes to make it possible to use this test from NativeAOT.

This brings the behavior of NativeAOT and trimmer much closer with regard to assembly rooting.
Rooting from rd.xml is kept as before (rooting a type will also root its base types). Given that rd.xml is already very problematic and tricky and people rely on all kinds of "accidental" behavior, it's not worth the break - there's not much complexity in keeping this behavior there.

Update trimming tests which started to fail after the infra updates. Mostly disable the tests for NativeAOT as they don't make sense on AOT.
@vitek-karas
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@vitek-karas
Copy link
Member Author

@MichalStrehovsky could you please take another look - specifically at the test changes.

Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still looks good, thanks!

@@ -171,15 +171,15 @@ protected override void Dispose(bool disposing)
public override void ImportParameters(DSAParameters parameters) => _dsa.ImportParameters(parameters);
public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) => _dsa.VerifySignature(rgbHash, rgbSignature);
protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
(byte[])_dsa.GetType().GetMethod(
(byte[])typeof(DSA).GetMethod(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple implementations of DSA/ECDSA so this is technically getting a different method, but since it's virtual it probably doesn't matter. Just wanted to point out for double checking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - I was aware of that, but as you stated, the method is declared as virtual on the DSA class, so unless some derived class does new this will work (and new would be really weird for a protected virtual method). If this was in product I would be much more worried, but for tests I think this is perfectly OK.

@vitek-karas vitek-karas merged commit b9de62a into dotnet:main Oct 5, 2023
174 of 179 checks passed
@vitek-karas vitek-karas deleted the NativeAOTRooting branch October 5, 2023 11:14
@agocke
Copy link
Member

agocke commented Oct 11, 2023

/backport to release/8.0

@github-actions
Copy link
Contributor

Started backporting to release/8.0: https://github.com/dotnet/runtime/actions/runs/6485720697

@ghost ghost locked as resolved and limited conversation to collaborators Nov 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NativeAOT's implementation of TrimmerRootAssembly is too aggressive
3 participants