All those indirect inter-package calls can be tedious and inefficient particularly when there are lots of short calls between packages. Instead we can say this is true only for calls to packages that we might want to reload (or reload without also re-loading things that depend on them). One reason to do this is so that the GC does not need to trace code, but trace a closure’s environment. However, we can support direct calls if we require that the callee is pinned at that memory address and the caller provides a table of all its callees.

It would be possible to use direct calls for inter-package calls and still allow re-linking, but id prefer to use closures for this. Without using closures there are a few challenges, nothing insurmountable, just engineering, but they do add complexity: One problem is how the GC can find and update pointers in code. There are multiple solutions and the discussion is off topic for this article.

Therefore, we will use indirect calls by default and when we may want to re-link packages. But allow some packages to request that calls to them are direct, saying that that package probably won’t be re-loaded. This will be visible in the PZ bytecode as it will be a call or tcall instruction that takes an Import ID, the import will be looked up in the table at load time, not run time (as with load_named), and therefore restrict re-loading.