p4c
p4c copied to clipboard
Replace BDWGC with shared pointers.
Tracking a comment. We can maybe achieve this at some point in time.
Related to this, I've been working on code (in https://github.com/ChrisDodd/p4c/tree/cdodd-disablegc) to allow removing the garbage collector and use
std::shared_ptr
instead. It still requires work though, and its been a low-priority background project for me.
Originally posted by @ChrisDodd in https://github.com/p4lang/p4c/issues/4359#issuecomment-1937927450
Can it use intrusive reference counters? Instead of shared_ptr wrappers?
Can it use intrusive reference counters? Instead of shared_ptr wrappers?
Probably yes. I'd say the IR hierarchy is the easier part of the problem to solve as it is almost completely generated. Therefore I guess we could even experiment and compare (e.g. shared_ptr vs. intrusive pointers vs. GC). The hard part will be getting rid of all the places where we took shortcuts and just allocated memory and just for convenience did not manage it (in many such cases it will be sufficient to use unique_ptr
, but some will need more refactoring).
I also include my comment, which offers a possible alternative (that still shares the bulk of the work outside the IR hierarchy) (https://github.com/p4lang/p4c/pull/4359#issuecomment-1909412447):
I think it would make sense to use GC just as opt-in for certain classes/places, for example the IR::Node-derived once, but not for everything. The current state with replaced malloc tests to be quite fragile and it most cases there is no real reason to use GC, the C++ way of managing memory is just fine (for IR nodes the argument could be that GC is likely better than ref-counting which is the only reasonable alternative there).
... that could be done by override nested operator new
I believe. That should also be more robust as it does not rely on function interposition as replacing malloc
(and even global new
) does.
... that could be done by override nested
operator new
I believe. That should also be more robust as it does not rely on function interposition as replacingmalloc
(and even globalnew
) does.
To be entirely safe we can make constructors private. And do something like static create
methods that would call necessary private constructors. Also, allocating nodes from pools might speedup things here.
To be entirely safe we can make constructors private. And do something like static
create
methods that would call necessary private constructors.
I'm afraid that would be a very unpopular change as it would require changes to a lot of passes, including downstream once. What would you want to solve by that? Prohibit instatiating IR nodes on stack?
I'm afraid that would be a very unpopular change as it would require changes to a lot of passes, including downstream once. What would you want to solve by that? Prohibit instatiating IR nodes on stack?
Replacement with shared pointers would require massive changes in many places as one will be unable to use IR::Node*
, instead some wrapper would be required as we'd need to increase / decrease reference counts on copies and destructions. In @ChrisDodd's branch there is IR::Ptr
for this purpose.
While one could certainly have smart pointers to stack objects, this is very dangerous, as you cannot control their lifetime. You certainly do not want dangling pointers to exist here and there.