-
-
Notifications
You must be signed in to change notification settings - Fork 422
Allow GC implementations to be swappable. #1581
Conversation
| import gc.stats; | ||
| import core.stdc.stdlib; | ||
|
|
||
| private | ||
| { | ||
| __gshared GC _gc; | ||
| __gshared conservative.GC _conservativeGC; | ||
| __gshared malloc.GC _mallocGC; |
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.
Those instances should be in the correspond gc implementation modules.
|
The proxy struct is emulating a virtual function table. Has it been discussed to make it an interface that each GC variant implements? This would remove all the boilerplate with function literals. That's actually what I considered the way to go when Martin converted the GC class to a struct. |
|
Even when I think being able to specify completely different implementations, for the case of manual vs. conservative, I wonder if it doesn't make more sense to just make it a feature, not a full implementation. Is there any practical difference between conservative and manual other than trying a collection before getting more memory when the heap is exhausted? |
|
@leandro-lucarella-sociomantic |
|
Do you really expect to someone for use that implementation or is it there just an example of a minimal GC implementation? |
|
A bit of both, really. It probably won't be common, but it is fully usable and there are cases when using a gc would be more than necessary. Do you have anything against it being accessible? |
|
Did some updates based on comments. The function I added to config.d to parse string arguments will probably need to be changed though. It works, but I don't know what is expected for this situation. |
That a replacement for gc_stub and one of it's usecases is to run valgrind (if you have enough memory). |
| { | ||
| if(!isspace(str[start])) | ||
| break; | ||
| } |
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 options are already space separated, so this will never do anything useful. There were also 2 helpers skip!isspace and find!isspace to avoid the loop.
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.
Let's just use the whole str as-is, no further parsing.
|
Mostly looks good now.
I agree, that's a better idea. Let's do that as next step. |
|
|
||
| void initialize() | ||
| { | ||
| if(config.gc != "manual") |
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 don't agree with Martin here (but not very strongly). I think it's better to make the decision which GC implementation to initialize in gc_init, because it's more obvious that only one of them is being selected.
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.
Nope! One goal of the implementation is that it's possible to link in new GCs, previously unknown to the runtime. Therefor it must be done like that.
We'll later switch to C constructors or run gc. module constructors earlier to make this work.
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.
Hmm, not sure how this will work. Right now, gc_init needs to know and even import each implementation.
If you register implementations from a C constructor, you can just pass the name. That would be helpful to list available GCs, too.
What is the correct way to allocate a class in druntime without a gc? |
Allocate memory and blit the initializer over it: |
|
Nice. Is my understanding correct that this replaces the old GC hot swappability introduced by @complexmath ? He already had an interface based on pointers to functions. |
|
And yes it would be nice if we took advantage of vtables instead of manual tables of pointers to functions. |
|
Classes and an Interface would be already much cleaner, you want to do it as part of this PR @Jebbs? |
|
Yeah, I like that a lot. |
|
Might need some more formatting, but this is ready for more reviewing. Some key things:
Other than that, it is more or less at the same spot the last commit was except now it uses an interface instead of the Proxy structure. |
|
This looks much cleaner. |
| struct Config | ||
| { | ||
| { bool initialized; |
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.
is initialized used anywhere? BTW: bad old dmd-style formatting.
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.
Whoops! Nope, this isn't used anywhere. I had intended to test something with this, but forgot to double check the diff before I pushed and it wasn't deleted.
That might indeed cause trouble when compiling with invariants, as they are also run when exiting |
|
We can even get away without a deprecation cycle, if we add: |
Yes, vtbls and interfaces should just work when loaded dynamically, no problem here.
Let's keep gc stuff in gc.* until we know more. We still want to support runtime GC selection which requires to preinitialize all linked GCs, using the module constructors of the |
| alias pbot this; // only consider pbot for relative ordering (opCmp) | ||
| } | ||
|
|
||
| const uint GCVERSION = 1; // increment every time we change interface |
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.
No need for that, you can use __VERSION__ to get the dmd frontend version, and we're releasing druntime w/ that as well.
Also it's our duty to keep this interface somewhat backwards compatible.
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.
Seems like that already existed before, but isn't used anywhere.
|
Except from #1581 (comment), LGTM. |
Also removes some unnecessary lines dealing with GC versioning.
| pthis.gc_addRoot = &gc_addRoot; | ||
| pthis.gc_addRange = &gc_addRange; | ||
| __gshared GC currentGC; //used for making the GC calls | ||
| __gshared GC initialGC; //used to reset currentGC if gc_clrProxy was called |
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.
We shouldn't need initialGC. You are only allowed to use a single GC during a program's lifetime.
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.
What about in the case of gc_clrProxy?
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.
You're right it's needed for the whacky Windows DLL support, I renamed and added comments.
Jebbs@8f99b22
|
I updated those bits to use |
- also avoid {} initialization syntax, it doesn't allow to add a
constructor later on, use `auto r = Range(p)` instead
- only need to keep the initial GC to iterate roots of the broken DLL implementation
|
I made a PR for your branch with a few things I found, once that is merged, it will show up here. |
a bunch of smaller improvements
|
LGTM |
|
Auto-merge toggled on |
|
I'll take care of the support for unknown GCs that get linked into a program. It requires quite a bit of low-level linker understanding. Support for unknown GCs linked into an executable. on Backlog | Trello |
|
This is still lacking a changelog entry and updated documentation on dlang.org @Jebbs, could you please add those. |
|
Yep, I'll take care of that tomorrow. |
|
@Jebbs thx! |
|
Since it wasn't in a change log before this, should I add it to changelog.dd for pending 2.072 changes? |
Yes @Jebbs, it hasn't yet been released and will be part of 2.072. |
Updated changelog to reflect #1581
This wraps up GC implementations in a proxy so that they can easily be picked and initialized at runtime before the user program starts according to the config options passed or embedded.
This also adds a secondary "GC implementation" to swap to based on gc_stub. This implementation allows memory to be managed in a manual style using 'new' and 'delete' instead of relying on the GC.