For now, this GC is non-generational, and much slower than the old
version. It tracks objects by a fixed object ID rather than changeable
memory address. Small object (eight bytes or less) are stored directly
in the array, indexed by object ID, while larger object are allocated
with malloc() (for now) and stored in the array as a pointer. Object
IDs are stored as 32-bit integers, even on 64-bit platforms.
Advantages:
- Simpler design
- Requires less memory on 64-bit platforms
- Object IDs don't change when running the GC
- No need to store a random "hash" value in vectors/strings/structs
- Can hash pairs by identity, not just value
- Can move objects individually, without fixing up all references
- Can determine object type from value, without another memory access
Disadvantages:
- Lower initial performance (non-generational, relies on malloc())
- 32-bit values place a (high) limit on total number of objects
- Must explicitly free unreachable object IDs after GC
Each transient identifies the value of the corresponding previous bytecode.
This change (a) frees up many bytecodes formerly used by the conditional
expression (if c t f); (b) regularizes the bytecode by always placing opcodes
before operands; and (c) causes the bytecode to conform to the Single Static
Assignment (SSA) form preferred by e.g. LLVM.
Includes updates to the hand-assembled files (*.rla) and the bytecode compiler.
Pairs, boxes, and strings are hashed by values; vectors and structures
are "hashed" by reference. Takes into account the possibility of cycles.
This is a prelude to implementing hash-tables.
Reduce initial allocation to 1 MB now that it can by increased at runtime.
Also remove 'noreturn' attribute from the public API.
If out_of_memory() returns, GC will abort() internally.
Fix tree_replace() to handle recursive data structures.
Fix some other minor bugs in the reader and interpreter.
Implement comment-escapes in the string parser, for more readable input.
Allow input program files (*.rla) to be invoked directly, with arguments.
Add a simple string->number converter as a builtin function.
Also refactored some GC code into smaller functions.
Weak boxes and wills will be useful for implementing weak hash tables,
which in turn will be used to store dynamic parameters efficiently.