|Part of Yhc|
In YHC modules are loaded at runtime by yhi from .hbc bytecode files. For a precise specification of the bytecode format see Yhc/RTS/hbc.
This file details how the loading process works, to see what structures are loaded into memory by the module system see Yhc/RTS/Heap.
Loading by demand
The program starts by loading the module with the 'main' function in it. Statically main will have a list of functions that it might call at runtime, these functions are loaded and their dependencies chased similarly. This is all handled by the code in "module.c" in src/runtime/BCKernel.
Yhi is careful to only load functions from the bytecode that could potentially be used, so as to minimize runtime memory use. Resolution then proceeds as follows:
- Suppose the runtime needs to load "Prelude.foldr" first it would open the right Prelude.hbc file and minimally load it, if it isn't loaded already.
- To minimally load a module:
- first the module string table is read from the .hbc file. The string table associates each unique string index with a StringRef. A StringRef holds either the contents of the loaded string or an offset to where it can be found in the file. When the module is first loaded only the offsets are loaded into the string table.
- Then when the actual string data for a string is needed later on in the process the string table will either return the stored string data or it will go to the right place in the file and load the string data.
- Having read the string table the object table is read. Again a similar trick is used the object table associates object indexes with ObjectRefs, and again ObjectRefs hold either the object data or its file offset.
- However this time a lookup table is used to map object names to object indexes. Note that this will cause the strings representing object names to be loaded as a side effect.
- Having minimally loaded the Prelude module the resolution process would use the module lookup table to resolve 'foldr' to a object index. Using this index the corresponding ObjectRef would be looked up in the object table. The ObjectRef either has the object data associated with it or not. If not then the data is loaded from the offset of the file specified by the ObjectRef.
- Since Prelude.foldr is a function it has a function constant table. Thus table is loaded with the bytecode instructions for foldr and all the names referenced in the constant table are resolved. In this manor the process continues recursively.
- Cyclic dependencies are handled by updating the object data associated with an ObjectRef before recursing to load it's dependencies; even though the object data might not be fully loaded yet.