Ban implicit GC for object heap allocations
The Problem
Currently when some memory is requested via Heap.allocateInObjectSegment or Heap.allocateInByteArraySegment, we first check whether we have enough memory and garbage collect if there isn't. This was fine when starting out; however, as the system got more complex, and we started having more and more cross-generational object pointers and tracking, this has become a huge problem; a garbage collection can happen at anytime and there's no real way to figure out that it happened. Currently the way to avoid your pointers from being swept under you is by calling Heap.ensureSpaceInEden, which will do the check for you. This allows you to perform a garbage collection before doing consecutive allocations, but is still very error-prone due to there being no guarantees that you actually specified the amount that you need (so if you miscalculated you can still cause a GC).
The Solution
- Remodel object heap allocation as follows:
- When a piece of code needs to do an allocation, it first has to ask for it by doing
Heap.getAllocation(.Object/.ByteArray, bytes);. This gives the caller an "allocation token", which they can then use for allocating objects. The token will store how many bytes of allocation it has remaining. - Memory can be requested from the allocation token by doing
token.allocate(bytes). This will subtract the amount of bytes needed from the token and return a byte slice to the caller. If there aren't enough bytes remaining in the token, the VM will crash.
- Change all
Object.createAPIs to take allocation tokens instead ofHeapobjects.
This solves the problem in the following ways:
- Garbage collection cannot happen randomly anymore; each garbage collection point can be found by searching for
Heap.getAllocation(). - Miscalculation of required memory at safepoints will now cause an immediate crash instead of hard-to-trace stale heap reference bugs.
- In the future the token can be further instrumented in order to find where each heap allocation request comes from, which might be useful for figuring out the biggest allocators (for optimization).
Notes
This will probably make the VM a bit more crashy initially as code relying on implicit GC and required memory miscalculations are discovered, but it will save a lot of headaches in the future.