-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Some cleanups in Assembly/Loader area #57023
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
Conversation
|
Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov Issue Details
|
d300f4c to
731f68c
Compare
6a3199c to
624f386
Compare
|
I think this is ready for review. |
|
Thinking forward a bit (future changes, not this one): could we please rename all of the "binder context" variables/names to just "binder"? It's just confusing. Or alternatively (and maybe even better) - merge AssemblyBinder and AssemblyLoadContext to a single AssemblyLoadContext. This might be a bit tricky with keeping the binder separation, but maybe that should go as well. In which case the whole "binder" term could go away as well. |
vitek-karas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really nice!
Mostly just nits and suggestions for possible future improvements. Feel free to keep this as is since it's already big enough :-)
src/coreclr/binder/assembly.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove this comment - I don't think it makes sense anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Some comments moved with the code and the style could be out of place in the new location or may not be very helpful. Some were not very helpful to start with and likely were forced by some kind of "every method/class must have a comment" policy.
'An assembly represents a particular set of bits.' is my favorite :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I would prefer DefaultAssemblyLoadContext. It just feels weird that the inheritance is AssemblyBinder -> AssemblyLoadContext -> DefaultAssemblyBinder.
Same for CustomAssemblyLoadContext.
But it's just a subjective naming - so feel free to keep as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "Context" works better for something passive - like environment used for binding. When the class itself provides binding functionality it should be Binder, since it is more than just context.
The base class main purpose is to provide "Bind" APIs, so it feels like it should be "Binder".
The AssemblyLoadContext feels a bit odd in the hierarchy until you realize its purpose is to link to the managed AssemblyLoadContext counterpart.
ALC does not add any "Bind" methods and is not normally used for binding (or should not be encouraged). We could in theory imagine a Binder that inherits from AssemblyBinder directly and does not have ALC stuff on it. In theory.
Technically ALC could be merged with the base class, but since it serves distinct purposes, it feels better to keep it a separate concern in the hierarchy and keep its name too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ALC does not add any "Bind" methods and is not normally used for binding (or should not be encouraged).
I'm not sure I follow this. Logically ALC.LoadFromAssemblyPath is the managed equivalent of AssemblyBinder.BindUsingPEImage (this is actually pretty much exactly the relationship). ALC.LoadFromAssemblyName
maps onto AssemblyBinder.BindUsingAssemblyName (it's also a pretty good match in reality). It's not exact since there are additional layers between the managed code and native (to deal with marshalling validation and so on). So while I agree that nobody in the runtime should call the Bind methods directly, they are sort of called "directly" from managed a lot.
But I guess I see your point. Runtime has a separate concept of "binding" (finding the right file for a given assembly spec) and a separate concept of "loading" (actually parsing a file and making it available to run code from). The managed APIs don't have these as separate concepts (although in the past we discussed that having it would be beneficial in some cases).
I still think that the sealed classes should be called DefaultAssemblyLoadContext/CustomAssemblyLoadContext - since they're a specialization of AssemblyLoadContext - but it's just a subjective naming thing :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefaultAssemblyLoadContext/CustomAssemblyLoadContext would fit in my brain better as well. Although I also have the native AssemblyLoadContext and AssemblyBinder classes lumped together in my brain, so that may be why.
it serves distinct purposes, it feels better to keep it a separate concern in the hierarchy and keep its name too.
Since what is clearer / or less clear to each person is pretty subjective, it might help to have comments in the headers with the intent / describing the intentional separation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discuss this I am getting more and more convinced that native AssemblyLoadContext should probably be merged with its base.
Native AssemblyLoadContext is not a native representation of the managed one, it just has a link to the managed, and can provide it via GetManagedAssemblyLoadContext. As a matter of completely mechanical naming it would be something like AssemblyBinderWithManagedAssemblyLoadContext.
However we do not really have concrete binders that cannot provide a managed context. If we do not envision such a case, then maybe we do not need an abstract one either.
Native AssemblyLoadContext seems to add more naming confusion than actual functionality (which is not all that much).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Native AssemblyLoadContext is not a native representation of the managed one, it just has a link to the managed, and can provide it via GetManagedAssemblyLoadContext
True, but for all intents and purposes AssemblyLoadContext-native has 1:1 relationship with AssemblyLoadContext-managed. The native one has a pointer to the managed one (and vice versa). Also all of the functionality of managed ALC is implemented (indirectly) in the native ALC (lot of this is hidden in the ApplicationContext which is embeded in the native ALC - and yes - that name is TERRIBLE and has to go :-), but that's a different refactoring)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
ApplicationContextwhich is embeded in the native ALC - and yes - that name is TERRIBLE and has to go
The ApplicationContext which also contains an ExecutionContext which is a subclass of LoadContext! So much context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: indentation seems to be off
src/coreclr/vm/multicorejitimpl.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: match indentation of the code around
src/coreclr/vm/multicorejitimpl.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: match indentation
src/coreclr/vm/pefile.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: fileBinderId -> fileBinder and also thisBinderId -> thisBinder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I missed that these are still Ids
src/coreclr/vm/pefile.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious: This means that all AssemblyBinder instances are also AssemblyLoadContext instances. Maybe in the future we can remove another layer of abstraction...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about merging AssemblyBinder and AssemblyLoadContext an decided to keep them separate on purpose.
AssemblyLoadContext should keep providing the link to the managed ALC, but should itself not be involved in binding business.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well - it has to be involved by the virtue of having a link to the managed extensions points (events and so on). But I guess it's OK to view them as slightly separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the first glance I saw enough usage of AssemblyLoadContext on the native side, but looking closer it mostly refers to the the managed one or to its name. The part that there is a native class that matches the name of the managed type may not be all that helpful.
Perhaps we do not need AssemblyLoadContext on the native side and should just move its stuff to the AssemblyBinder.
I need to think about this.
It is easier to merge types than to un-merge them back later, if we regret it :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is easier to merge types than to un-merge them back later, if we regret it :-)
That is very true. 👍
src/coreclr/vm/appdomain.hpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like if we could rename this method to GetDefaultBinderContext - or even better GetDefaultBinder. And in general get rid of the "binder context" term, and just use "binder".
The "TPA" part should be more or less an implementation detail. I know we're now keeping it on per-assembly level, but eventually that should go away as well (as a term and maybe even as the functionality - I'm having certain doubts about its usefulness - but that's a different discussion).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It might be ok to use "TPA" when referring to the actual set of assemblies, but there is really no such thing as TPA binder - there is DefaultBinder who's binding behavior mostly guided by TPA set, but that is an implementation detail for the binder.
src/coreclr/vm/assemblyspec.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we even need the specific cast here? This should cast implicitly just fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually - we don't any of this now - if pParentAssemblyBinder is already the default binder - then this will assign the exact same value to it - no change.
We should simply remove this entire if and just keep the one below which uses default binder if it's null.
Maybe keep the comments in some way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I also think adding IsDefault() to the AssemblyBinder could simplify a few places that do if (binder == GetDomain()->GetBinder()) { . . . }
src/coreclr/vm/assemblynative.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
|
Side note: First time for me to use the |
YES, just did not want to put too much into one change. |
elinor-fung
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: alignment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throughout due to a bunch of the AssemblyBinder -> AssemblyBinderCommon renames.
src/coreclr/vm/assemblynative.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think you need pCurDomain or pTPABinder anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefaultAssemblyLoadContext/CustomAssemblyLoadContext would fit in my brain better as well. Although I also have the native AssemblyLoadContext and AssemblyBinder classes lumped together in my brain, so that may be why.
it serves distinct purposes, it feels better to keep it a separate concern in the hierarchy and keep its name too.
Since what is clearer / or less clear to each person is pretty subjective, it might help to have comments in the headers with the intent / describing the intentional separation.
|
Hello @VSadov! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
|
|
||
| static HRESULT DefaultBinderSetupContext(DefaultAssemblyBinder** ppTPABinder); | ||
|
|
||
| // TODO: The call indicates that this can come from a case where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VSadov is this TODO obsolete? If not, it would be nice to have an issue for it and reference it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly obsolete. CorLib may have NULL binder, but I am not sure if it goes through here.
I will check on this TODO in later changes.
I also think the statics on AssemblyBinderCommon may be moved to AssemblyBinder, but have not decided on that yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think some of this code will go to managed eventually, just want to clean it up a bit as-is beforehand. It seems like a good thing to do regardless.
For the most part just mechanical changes and refactoring with no impact to functionality.
ICLRPrivAssemblyinterfaceICLRPrivBinderinterface withAssemblyBinder- a base binder class.Assemblydoes not need to be a binder. (it has a binder, but no longer is a binder itself)ApplicationContextdown toAssemblyBinderto remove some redundancy.GetBinderIDfrom everything that had it as BinderID appears to be a self-supporting feature.CLRPrivBinderCoreCLRandCLRPrivBinderAssemblyLoadContextto more sensible
DefaultAssemblyBinderandCustomAssemblyBinderSince
ICLRPriv. . .and COM related stuff is gone, we can now have a simple hierarchy of binders that looks like this: