Memory representation of extensible variants

Is there somewhere in the compiler codebase/documentation that I can’t find which describes the memory layout of extensible variants? From messing around a bit with -dlambda:

type t = ..
type t += Foobar
  (let (Foobar/268 = (makeblock 248 "Abc.Foobar" (caml_fresh_oo_id 0)))
    (setfield_ptr(root-init) 0 (global Abc!) Foobar/268))

It seems like they’re encoded as objects (tag 248) where the class field is a string that contains the name of the variant (here Abc.Foobar) and the ID field being a unique ID generated by caml_fresh_oo_id.

Are extensible variants the only case in which the class field of an object is a string?

The motivation here is the instability of unmarshalling extensible variants. I’m wondering if it’s possible to add a flag to Marshal.extern_flags which raises if the input contains an extensible variant, similar to how the Marshal.to_{format} functions raise when a closure is passed without the Closures flag.