Some random notes, influenced by reading the following http://www.boblycat.org/~malc/scaml/index1.html http://www.boblycat.org/~malc/scaml/index2.html The dynlink option: make sure to add -Wl,-E to the gcc command-line (invoked by ocamlopt to _assemble_ the code) The natdynlink still needs caml_start_shared, fini_shared, init_shared symbols in the file being loaded. and shared_dyn_post_process ()... Actually, it seems that fini_shares is located, checked that it is found, but not used. "init_shared" symbol in the loaded file is located and invoked. shared_dyn_post_process (); is then invoked. "caml_start_shared" symbol in the loaded file is located and invoked. The symbol "init_shared" is located in the shinit.c, the start-up file that is linked with the dynamically-loaded module: ocaml/asmrun/shinit.c is the startup file. It calls shared_register(&decs) and caml_init_shared (); According to the decsription in the ChangeLog of the scaml patch, + (shared_init): create function caml_init_shared(pseudo): + map (function + Module module -> () + | Shared library -> library.init ()) + all_modules_shared_libraries_referenced. it seems that caml_init_shared only matters for shared libraries (to invoke libtrary's init function) rather than for dynamically loaded modules. The function shared_register (see asmrun/shared.c) Adds the shdesc: it will be only one descriptor in the desc_roor chain. shared_frametable: if not null, invoke add_frametable (desc); which adds all the frametables from shared_desc (in our case, probably only one) at the end of shared_frametable table (unless the frametable was already mentioned). The shared_frametable is resized approporiately. The last slot of shared_frametable is NULL. But originally, shared_frametable must be null... shared_frametable is only allocated in process_frametables(), which is invoked only from shared_post_process(). The latter is not invoked by the dynamic loader. Rather, the loader invokes shared_dyn_post_process (). The latter merely does process_segments (); and sets "shared_new_frames = 1;" The latter flag is only used in the predicate shared_modules_added(). The latter is used in roots.c: when gc routines are invoked, root.c checks is shared modules are added. If they have been, it invokes init_frame_descriptors(); + (oldify_local_roots): added call to shared_get_globals and code to + reintialize frame descriptors if new module was added. + (do_roots): likewise. See ocaml/asmrun/roots.c +#ifdef SHARED_CAML + long **caml_frametable = shared_get_frametable (); + + if (frame_descriptors != NULL) { + stat_free (frame_descriptors); + frame_descriptors = NULL; + } +#endif CSP values can be resolved by dynamic linking? In more detail: introduce table : (unit array) and make it a pervasive. translate . in let a = something in .. as begin increment table_id; table.(table_id) <- Obj.magic a; .< !Obj.magic (table.(table_id)) >. Walid said that something like that is already being though of. (And this is how it works in a byte compiler?) Note that MetaOCaml draws the distinction between a CSP which is a pervasive, and a regular CSP. The former is compiled in AST just like Var "name" (so the compiler of AST can handle it as a native pervasive). Note that data in OCaml should not be referred to by a ptr, because GC may move it. Code pointers are stable. Pervasive pointers are stable too. --- Dynamic linking must essentially do the same job as Ocaml static linking does when generating /tmp/camlstartup4978fc.s Namely, for each compiled OCaml module, need to generate tables .L216: addl $1, caml_globals_inited call camlArray__entry caml_globals: .long camlPervasives .long camlArray caml_globals_map: .ascii "..." caml_data_segments: .long caml_startup__data_begin .long caml_startup__data_end .long camlPervasives__data_begin .long camlPervasives__data_end .long camlArray__data_begin .long camlArray__data_end caml_code_segments: .long caml_startup__code_begin .long caml_startup__code_end .long camlPervasives__code_begin .long camlPervasives__code_end .long camlArray__code_begin .long camlArray__code_end caml_frametable: .long caml_startup__frametable .long caml_system__frametable .long camlPervasives__frametable See make_startup_file in asmcomp/asmlink.ml One idea is to get the compiler generate a new camlstartup.s file (using all the existing build plus the new module to link in dynamically), and then effectively `replace' the existing camlstartup.s (perhaps playing with weak links, etc). A better idea is to observe the absense of globals in the module to dynamically load, and the absence of new exception declarations. Requirement: no new apply, send and curry functions in the generated fragment! There may be a rare condition when dynamic loading fails, if the generated code uses functions of higher arity or does currying to a larger extent than that in the main code. This is because currying/apply_n code is generated in the start-up file. I'd expect this to be a rare condition that may occur only when the main code is "too simple" (usually it is never the case because the main code includes stdlib, and the latter is quite complex already). The problem will manifest itself is the failure of .! (exception will be thrown). The workaround is easy: just add to the main code some functions of higher-arity. You don't have to execute them; they just have to be present. caml_frametable[] is referenced only in asmrun/roots.c caml_code_segments, caml_data_segments are referenced only in asmrun/startup.c and only as far as minmax table is concerned. So, we only need to adjust char * caml_static_data_start, * caml_static_data_end; char * caml_code_area_start, * caml_code_area_end; --- Also, we may wish to unify dynamic loading. Currently, there are three! Ocaml interfaces to exactly the same dlopen API: one in OCaml itself, one used in off-shoring and one for metanative. Somehow all three Ocaml interfaces are slightly different, that's why currently we need all three of them...