Extending exception tag blocks #5009
Original bug ID: 5009
We have recently run into a problem (efficient S-expression converters for exceptions) that could be easily solved with a presumably small change to the OCaml-runtime.
Currently exception values have a pointer as first field that points to a block whose address uniquely identifies the kind of exception (lets call it "exception tag block"), e.g. as required for local modules, functor instantiations, etc. This block only stores a pointer to the string representing the exception constructor.
This makes it seemingly impossible to look up a converter for an exception in less than linear time, which may not be good enough for applications that e.g. instantiate a large number of functors or create many local modules in a loop.
The reason is that the address of the exception tag block is the only thing unique about it and it can change due to garbage collection, which prohibits the use of lookup tables/maps.
By extending the exception tag block, which currently only holds the pointer to the constructor string, by another word (or maybe two on 32bit architectures), it would be possible to store another, non-volatile piece of information that could uniquely identify the kind of exception. This would allow us to create the lookup tables required for O(log(N)) lookups.
A global 64bit counter in the OCaml runtime, for example, could then be used to generate unique ids at acceptably low cost. Exception values would not suffer any penalty. Only new instantiations of exceptions (as with functors, local modules, possibly first-class modules in the future, etc.) would see a tiny amount of extra cost.
Do you think this extension to exception tag blocks could make it into the OCaml runtime?
Comment author: @alainfrisch
Commit 14239 on the raise_variants branch modifies the representation of exception slots, reusing the existing unique id machinery from object values.
Commit 14240 introduces a function Printexc.exn_slot_id (exn -> int) returning the unique id of the constructor used to create an exception value.