Dynamic linking - inolen/emscripten GitHub Wiki

Dynamic Linking / Separate Compilation

This is an outline of a plan for dynamic linking of emscripten-generated code.

Goals

  • Allow modules to be compiled separately and linked dynamically at runtime, in order to enable
  • Reusable standalone modules
  • Shorter compile times (by only recompiling the modules you are working on)
  • Allow different optimizations in different parts of code (e.g., inlining vs. non-inlining, asm vs. non asm, etc.)
  • Do not regress single-compilation performance. It is expected that dynamically-linked modules will not be as fast as a single standalone compilation, final production builds should likely not be dynamically linked.
  • Support asm.js

Assumptions

  • Modules will share a single arrayBuffer. If they do not do that, every interaction involves copying which is expensive.
  • Consequently, modules will need to be built with compatible memory types. We will always assume TA2 (C-style memory layout). But otherwise they can differ in optimization level, inlining or not, asm.js or not, minified or not, etc.

Questions/Issues

  • Separate stacks or shared stacks? Shared is more efficient, but means passing around the stack pointer.
  • Serialize all the module state at inter-module calls? __THREW__, tempRetX, etc. - stuff we put in globals in the closure for speed purposes?
  • Share a single copy of the entire JS library in the main module, as in the past?
  • Function pointers. We need each module to be able to call function pointers in other modules, but not be slow on calling their own. Bridging wrappers like we have in Runtime.addFunction?
  • Memory relocation: The main module can be built normally wrt memory initialization and hardcoded offsets of globals, but shared libraries cannot. We can either have a relocation step where we do a string replace and new Function, or we can add an offset variable (tradeoff of startup versus throughput).
  • Function pointer relocation will be necessary, since we can't hardcode them at compile time. That means we can't use a memory initializer file for libraries (but we can for the main module).