Hunting down a crash (which eventually turned out to be a bug of mine), I had a look at the implementation of interiorAllocatedPtr() and am wondering if it handles references pointing to the end of the chunk correctly. While this wasn't the cause of my bug, I'd still like to know if it's correct the way it is written.
Specifically, interiorAllocatedPtr() seems to (both for small and large chunks) treat pointers from start to start+size-1 as interior pointers, where start is the beginning of the chunk and size the size of the chunk. However, typical compiler optimizations (e.g., strength reduction for induction variables) can result in pointers referencing the location start+size (see Hans Boehm's paper "Simple Garbage-Collector Safety", and "A Proposal for Garbage-Collector-Safe C Compilation'', co-authored with David Chase).
In the rare case where such an optimization occurs and a memory block is referenced from the stack and registers only, conservative stack scanning may result in premature deallocation (assuming I'm correct and am not overlooking a subtlety in the code).
The reality is much worse. A typical code generator is free to keep X+N as pointer on the stack and perform all address computations with X-N instead where N is completely arbitrary...
Precise stack marking is planned however and there are also lots of other workarounds which in practice force the C compiler to not eliminate stack roots. They all turned out to be expensive though so we don't do any of them.
You're correct that it only handles start+size-1 and rely on luck, but then start+size might already be the start of some other object and so we would need to mark 2 objects which seems crazy given that start+size is only a heuristic too. The proper fix is to use precise stack marking. Then we can get rid of all the checking for interior pointers which is expensive anyway.