-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[mono] Initial support for unloadable ALCs #77399
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: Issue Detailsnull
|
984a476 to
abe02a7
Compare
|
Great start @vargaz! Should we see if we can make some unloading tests work and pass as part of this PR before we merge or should we merge this initial implementation as a wip experimental opt in feature while we work through scenarios case by case? |
|
Disabled it by default for now. |
docs/design/mono/unloadability.md
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.
@vargaz would it be possible to walk stack as part of GC and collect managed frames, use IP's to locate the jit info for the IP's and then from there get the matching types memory manager and LoaderAlloctor object and pin it instead of storing a volatile local variable in each method prolog?
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 volatile var hack is kind of nice. you only have to emit it if you're JITing a method from an unloadable ALC, so it's pay for play. I don't know if we plan to support AOT with unloadable ALCs, in which case I guess we need some other idea, but for the JIT and interp it's kind of a nice hack
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.
Anyone aware of anything fundamentally blocking us to support AOT with unloadable ALC's?
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 AOT code is associated with a specific loaded assembly, so it can't handle the case where an assembly is loaded multiple times in multiple ALCs, or unloaded.
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.
@vargaz would it be possible to walk stack as part of GC and collect managed frames, use IP's to locate the jit info for the IP's and then from there get the matching types memory manager and LoaderAlloctor object and pin it instead of storing a volatile local variable in each method prolog?
It is possible but it having to do a stack walk for all threads would slow down GCs a lot.
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.
OK, yes, with a lot of threads that would have impact on GC and maybe an additional volatile store to the stack per method prolog will be fast enough and as long as we do conservative stack scanning of complete thread stack it will automatically be kept alive.
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 AOT code is associated with a specific loaded assembly, so it can't handle the case where an assembly is loaded multiple times in multiple ALCs, or unloaded.
I suspected that was the case, they have similar limitation in R2R, so not unique to Mono, https://github.com/dotnet/runtime/blob/main/docs/design/features/assemblyloadcontext.md#constraints.
Will that case be handled in some way, if you try to load the same AOT:ed assembly in different ALC, will the second load then JIT the methods and if running full AOT, fail and assert or will it share the same native method implementation in both ALC's?
I guess the best way to handle AOT:ed assemblies is to load them into the default ALC and then use JIT or Interpreter for code loaded in custom ALC's.
docs/design/mono/unloadability.md
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'm doing a very similar thing when hot reload adds instance fields to an existing object.
Maybe there's something common we can share?
docs/design/mono/unloadability.md
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.
The volatile var hack is kind of nice. you only have to emit it if you're JITing a method from an unloadable ALC, so it's pay for play. I don't know if we plan to support AOT with unloadable ALCs, in which case I guess we need some other idea, but for the JIT and interp it's kind of a nice hack
ed7d88c to
f507003
Compare
… called with a non-zero context and a non-generic signature.
on the GC heap. Normally, static variables are stored in an array inside MonoVTable which is registered as a GC root. For collectible alcs, this would not work, since GC references in these arrays would keep the alc alive. Instead, store them in arrays referenced by the LoaderAllocator object. This assumes the static variables will no longer be accessed after the LoaderAllocator object dies.
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.
Great start! LGTM!
af2acc4 to
cb3076f
Compare
|
/azp run runtime |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
The interpreter failures are relevant. |
|
Failures are unrelated. |
No description provided.