p4c icon indicating copy to clipboard operation
p4c copied to clipboard

Replace BDWGC with shared pointers.

Open fruffy opened this issue 1 year ago • 5 comments

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

fruffy avatar Feb 12 '24 16:02 fruffy

Can it use intrusive reference counters? Instead of shared_ptr wrappers?

asl avatar Feb 13 '24 02:02 asl

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.

vlstill avatar Feb 13 '24 06:02 vlstill

... 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.

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.

asl avatar Feb 13 '24 13:02 asl

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?

vlstill avatar Feb 14 '24 07:02 vlstill

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.

asl avatar Feb 14 '24 07:02 asl