Reading the Perceus tech report, I'm wondering about a possible adaptation to Go:

  1. For each incoming pointer to a function, add an extra hidden bool parameter and result. The parameter indicates whether the pointer is owned or borrowed, and the result whether a borrowed pointer was retained. (The result is irrelevant for owned pointers.)
  2. And for each outgoing pointer from a function, add another hidden result to again indicate owned or borrowed.

That should allow us to immediately place objects back onto the free list, or potentially reuse them using FBIP (functional but in place—see the Perceus report, § 2.4).

The bool parameters and results can of course be bit packed too, and clever bit shuffling instructions should prove useful.

An unfortunate limitation though is that any pointers stored through another pointer must be retained. And similarly, any pointers loaded through another pointer must be borrowed. But escape analysis has similar limitations around pointer indirections, so maybe it's still net positive.

Another possibility that comes to mind is putting the “owned” bool directly into the pointer value as a tag bit so that it can be tracked through pointer indirections. I suspect we'd also need to track a “thread shared” bool too.

To experimentally quantify this idea, I think it should be possible to hack up the x/tools SSA compiler and interpreter to measure what percentage of heap allocations could be eagerly reclaimed.

Note that in Go, struct fields and array indices are addressable, so Perceus-style reference counting code would need to call runtime.findObject to find the reference count for an arbitrary pointer. I expect this would be too slow for the GC savings to be a win, but it could still be worth experimenting with and quantifying.