Hi all. I’ve been trying to study the GC part of OCaml runtime, and as I was reading caml_oldify_one in runtime/minor_gc.c, 2 questions came up:
caml_oldify_one seems to assume that the pointer being “oldified” always points to the memory region right after block header. Does that mean the compiler backend must make sure there is no interior pointer? (I know this seems to hold naturally since we can’t do pointer arithmetics in OCaml, but what if some optimization generates interior pointer?)
caml_make_vect in runtime/array.c shows that an empty array is represented as Atom(0), but it falls under the if (tag < Infix_tag){ category in caml_oldify_one, which assumes the block contains at least 1 element (naturally, since that’s where we put the forwarding pointer). However, Atom(0) is an empty block. How and where is this handled?
Any help is appreciated!
Edit: If this is not the right place to post such questions, please let me know too.
As you said, there is no pointer arithmetic, so the compiler does not even need to make sure there are no interior pointers. (Actually, there are some interior pointers in case of mutually recursive functions, but they use special headers.)
Atoms are statically allocated; they are not part of the minor heap, so the GC just ignores them and the size-0 block does not matter.
… there is no pointer arithmetic, so the compiler does not even need to make sure there are no interior pointers
Hmm but if caml_oldify_one assumes the pointer argument is never an interior pointer, the compiler must ensure that too, right? I was wondering what if some backend optimization generates interior pointer, if we treat the optimizations as blackbox pseudo-machine-code transformations? (I can’t think of any examples, but even if the compiler never generates interior pointer, doesn’t minor-gc still need this soft invariant?)
Atoms are statically allocated; they are not part of the minor heap, so the GC just ignores them and the size-0 block does not matter.
This makes sense, I should’ve thought of that. So the invariant is for values living in the “minor heap” only.
Let us say it another way. If an optimization creates an interior pointer, then the optimization contains a bug. Thus, the compiler does not perform anything special to avoid interior pointers; it assumes the user code does not create interior pointers (through Obj.magic for example) and that none of its optimizations do either.