Document detailing the VP function format and the unified calling mechanism.
In conventional systems, a firm distinction exists between executable functions and the data structures that support object-oriented polymorphism, such as virtual method tables (vtables). This separation introduces complexity into the compiler, linker, and runtime. ChrysaLisp fundamentally rejects this dichotomy by employing a single, self-describing binary format for all callable entities. A VP class vtable is not a special data structure; it is, at a binary level, a VP function with a zero-length code section.
This unifying design, combined with a multi-stage "linkerless" build process, eliminates the need for a traditional system linker, enables sub-second full-system rebuilds, and results in a runtime where static function calls and virtual method dispatch are mechanically almost identical and maximally efficient. A key optimization in this process is the consolidation and stripping of symbolic dependency information, resulting in a minimal boot image.
Every compiled unit in ChrysaLisp, be it a standalone function or a class
vtable, adheres to a single, consistent binary layout. This structure is
defined by +fn_header in lib/asm/lisp.inc. The core principle is that a
function is a block of data containing a descriptive header whose fields are
offsets from the start of the block itself.
On-Disk .vp File Layout:
+---------------------------------+ <-- Function Address (F)
| FN_HEADER |
| - uint64 ln_fnode | (For linking into lists by the loader)
| - ushort length (total size) |
| - ushort entry | ---------> relative offset to code start
| - ushort links | ---------> relative offset to links table
| - ushort paths | ---------> relative offset to paths table
| - ushort stack (req'd size) |
| - offset pathname (symbolic) |
+---------------------------------+ <-- Address (F + entry offset)
| |
| EXECUTABLE CODE |
| (VP Instructions) |
| |
+---------------------------------+ <-- Address (F + links offset)
| |
| LINKS TABLE |
| (Parallel to Paths Table) |
| |
+---------------------------------+ <-- Address (F + paths offset)
| |
| PATHS TABLE |
| (Symbolic names for links) |
| |
+---------------------------------+
-
Header: Provides metadata, including offsets to the other sections.
-
Executable Code: A sequence of VP instructions. This is the "body" of the function.
-
Links Table: A table of placeholders for pointers. For a normal function, these will point to external dependencies.
-
Paths Table: A table of null-terminated strings that holds the symbolic names for the entries in the
linkstable.paths[i]is the name for the function that will be referenced bylinks[i].
The architectural elegance of ChrysaLisp is revealed in its implementation of
a class vtable. A vtable is simply a VP function with a zero-length code
section, where the entry offset points directly to the links table.
The def-class function in lib/asm/class.inc generates this structure:
-
It calls
(def-func 'class/my_widget/vtable)to begin creating a standard function block. -
It emits zero VP instructions.
-
For each method (e.g.,
:draw), it adds the method's implementation function path (e.g.,'gui/view/draw') to the*links*list and the method's name (":draw") to the*paths*list. -
When
def-func-endis called, it sets theentryoffset in the header to be identical to thelinksoffset.
The resulting binary layout for a vtable-function is identical in structure to a normal function, allowing the boot process to treat them the same way.
A pointer in a links table (whether for a static call or a vtable slot)
evolves through three distinct states from source code to a running system.
-
Actor:
asmtool (asm.lisp). -
State: The
.vpfile on disk contains symbolic dependencies. Each function has its ownpathstable containing the string names of its dependencies. If ten different functions call:sys_mem :alloc, the string"sys/mem/alloc"is duplicated in ten separate files.
-
Actor: The
boot-imagefunction (lib/boot/image.inc). -
Process: This tool performs two critical optimizations:
-
Path Stripping: It scans every function's
pathstable and the original, per-function path tables are completely discarded, shrinking the image. -
Link Resolution: Using the original path information (before it's discarded), it finds the final offset of each target function within the image. It then patches the
linkstable with a relative offset from the link's own address to the header path names.
-
-
Result: The on-disk
boot_imageis a compact binary with relative code offsets and no path string table.
Optimized boot_image Layout on Disk:
+-----------------------------------------------+
| Func A Header |
| Func A Code |
| Func A Links (rel. offsets to header paths) |
+-----------------------------------------------+ <-- Original paths table STRIPPED
| VTable B Header |
| VTable B Links (rel. offsets to header paths) |
+-----------------------------------------------+ <-- Original paths table STRIPPED
| ... etc ... |
+-----------------------------------------------+
-
Actor:
sys/load/init. -
Process: This is the first code to run and is carefully written to be self-contained, making no external calls until its work is done.
-
It receives the
image_base_addresswhere the OS was loaded. -
It iterates through every function block's
linkstable. -
For each slot, it reads the
relative_offset, calculates the target's absolute memory code address, and writes this absolute address back into thelinksslot.
-
-
Result: The system is now live. Every
linkstable and therefore every static and virtual call site been transformed into absolute function pointers.
This architecture ensures that by the time any application code runs, all symbolic resolution is complete.
-
Static Call (
f-call): A call to a known function like(f-call :sys_mem :alloc ...)is resolved by theboot_imageandloaderinto an absolute memory address. The final machine code performs a directcall [absolute_address_of_sys_mem_alloc]. -
Virtual Call (
v-call): A virtual method call like(v-call :my_widget :draw ...)is resolved at runtime with maximum efficiency:-
Get VTable Address: The address of the object's vtable-function is retrieved from its header:
mov r1, [my_widget_instance + +obj_vtable].r1now points to the code section of a function likeclass/button/vtable. -
Get Method Pointer: The compiler knows the method index for
:draw(e.g.,0). It generates code to load the pointer from the already-patched vtable:mov r2, [r1 + (method_index * ptr_size)]. This is a single memory read that loads the absolute address of the correct:drawimplementation. -
Call: The final instruction is an indirect call:
call r2.
-
The ChrysaLisp VP function format is the architectural lynchpin of the
system. By treating functions and vtables as the same binary primitive, it
leverages a single set of tools for compilation and loading. The
boot_image optimizer is essential, performing both link resolution and
string table consolidation to produce a compact, efficient binary. The
load-time wiring is a trivial, single-pass operation.
The result is an architecture of radical simplicity and performance. There is no complex linker, and no runtime overhead for virtual method dispatch beyond a single memory indirection, making it as fast as a standard C++ vtable call while being part of a far more dynamic and flexible system. This unified concept is a prime example of ChrysaLisp's core philosophy: achieving superior performance and robustness through elegant, first-principles design.