-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Allow eliminating virtual methods on abstract classes #80607
Conversation
Allow removing method bodies of virtual methods on abstract classes when the methods were overriden by descendants. E.g. ```csharp Base b = new Derived(); b.Expensive(); abstract class Base { public virtual void Expensive() { expensive stuff; } } class Derived : Base { public override void Expensive() { other stuff; } } ``` The method body of `Base.Expensive` is unreachable, but we're still generating it because it's referenced from the `Base` vtable. Not anymore. This is pretty much a rollback of dotnet#66145 with a small fix in ILScanner that fixes the problematic scenarios. I don't know why I gave up so quickly last time. What we do is instead of generating hard dependencies on the implementation method entrypoints in abstract classes, we delay the dependency on the entrypoint until a derived non-abstract MethodTable. If no non-abstract `MethodTable` that uses this shows up, the entrypoint turns into a throw helper.
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsContributes to #80165. Allow removing method bodies of virtual methods on abstract classes when the methods were overriden by descendants. E.g. Base b = new Derived();
b.Expensive();
abstract class Base
{
public virtual void Expensive() { expensive stuff; }
}
class Derived : Base
{
public override void Expensive() { other stuff; }
} The method body of This is pretty much a rollback of #66145 with a small fix in ILScanner that fixes the problematic scenarios. I don't know why I gave up so quickly last time. What we do is instead of generating hard dependencies on the implementation method entrypoints in abstract classes, we delay the dependency on the entrypoint until a derived non-abstract MethodTable. If no non-abstract Cc @dotnet/ilc-contrib
|
Doing the same with regular trimming is tracked by dotnet/linker#2910. |
This PR only does it if the base class is abstract. This is hard enough already :). It's my second attempt after dotnet/runtimelab#658 had to be rolled back. It's hard to do it on non-abstract classes because the base could still be reflection-constructed when one is not paying attention and break this. |
/asp run runtime-extra-platforms |
@MichalStrehovsky it reminds me that a fix for #54781 might also reduce size (don't compile methods if they're inlined at all callsites) - will take a look this weekend |
I think @jkoritzinsky fixed that one |
Yes, I fixed that one. It's not 100% perfect (doesn't strip as much as possible when dealing with virtual methods), but it does a decent job |
cool! should the issue be closed then? 🙂 |
I think it's worthwhile to keep it open to track the holes in the analysis (in particular how if a method is an explicit interface implementation of an internal interface method that is never called, it will still be crossgen'd) with the milestone updated to Future as getting the analysis 100% correct is lower priority unless we think it will help us hit size goals for the product. |
Contributes to #80165.
Allow removing method bodies of virtual methods on abstract classes when the methods were overriden by descendants.
E.g.
The method body of
Base.Expensive
is unreachable, but we're still generating it because it's referenced from theBase
vtable. Not anymore.This is pretty much a rollback of #66145 with a small fix in ILScanner that fixes the problematic scenarios. I don't know why I gave up so quickly last time.
What we do is instead of generating hard dependencies on the implementation method entrypoints in abstract classes, we delay the dependency on the entrypoint until a derived non-abstract MethodTable. If no non-abstract
MethodTable
that uses this shows up, the entrypoint turns into a throw helper.Cc @dotnet/ilc-contrib