On 11 February 2017 at 14:02, Christoph Höger < christoph.hoeger@celeraone.com> wrote: > Dear all, > > while studying camls native code generation and garbage collection > strategy, I came upon Connor Benner's bachelor thesis from 2012, where he > implemented a llvm backend for ocamlopt. One intriguing remark mentioned > OCamls exception mechanism as basically consisting a pointer to the stack > frame of the last exception handler in a special register (r14, when I > recall correctly). Throwing an exception that becomes a mov/pop/ret > operation. This however, seems to interfere with garbage collection: From > the C-API, it seems that all local roots are stored in the frametable via > some special macros (e.g. CAMLParam, CAMLlocal). > > When control just returns from a stack frame, how are the entries removed > from the frametable? > The frametable is a static data structure, which is a hashtable mapping return addresses in OCaml functions to sets of stack offsets. When the GC wants to traverse the stack, it walks the stack, picking out the return address for each stack frame and looking them up in the frametable to find out which stack slots are live. When OCaml code raises an exception, it simply discards the stack up to the exception handler. Code using the C API registers local roots in a different data structure (caml_local_roots) using the CAMLlocal/param macros. When C code raises an exception using caml_raise (see asmrun/fail.c), local roots are popped off caml_local_roots one by one before raising the exception. The tricky case is when OCaml code raises an exception, but there are C frames between the top of the stack and the exception handler. To handle this case, the implementation of caml_callback (calling OCaml from C) unconditionally adds an exception handler. Should this exception handler catch anything, it's rethrown with caml_raise. The effect of this is that if an exception is thrown and the stack has a mixture of OCaml and C frames before the exception handler, then the exception will propagate by alternately cutting off OCaml segments of the stack, and unwinding C segments of the stack. Stephen