Hey Phil, thanks for the write up! Curious why this is only used for JSC's JIT, and not to back its heap? Did the design of the JSC GC influence libpas at all?
It's used for JSC's JIT and for all heap allocations in JavaScriptCore and WebKit that aren't GC allocations.
Riptide (the JSC GC) has a similar design and some of the key ideas were first pioneered there:
- The use of fast bitvector searches to find an eligible page (Riptide calls it first eligible block, I think).
- The use of bitvector simd to change object states in bulk.
- Riptide uses a mark bitvector that is indexed by minalign atom (16 bytes) and a block size of 16KB. Libpas's default "small segregated" configuration is 16 byte minalign, 16KB block, and an alloc bitvector indexed by minalign.
I have since thought about how Riptide could be wired up to use libpas. It's possible to do it. Already today you could create a libpas page_config that leaves room for mark bits in the page header, and makes them use the same indexing as the alloc bits. Riptide has a "newly allocated" bitvector that serves almost the same purpose as the alloc bits (kinda, if you squint really hard) - so you'd go from Riptides newly_allocated and mark bitvectors, to libpas's alloc bitvector and a custom mark bitvector stuffed into page headers using an exotic page_config. If JSC did this, it would buy:
- Better decommit policies than Riptide. I did a lot of tuning in libpas to make decommit Just Right (TM).
- Faster allocation of medium-sized objects.
- Possibly better memory efficiency.
But, Riptide is already very nicely tuned, and it gets some benefit from libpas's decommit rules because Riptide calls fastMalloc to get memory and sometimes uses fastFree to return it. fastFree calls bmalloc::api::free, which calls libpas's bmalloc_deallocate, which then goes to pas_deallocate with the BMALLOC_HEAP_CONFIG. So, Riptide already gets some of the goodness of libpas by sitting on top of it.