|
x-engine-c v0.2.13
The C engine for x-lang
|
State-image primitives – image save!, image rebuild!, image write!. More...
#include "x-prim.h"#include "x-eval.h"#include "x-heap.h"#include "x-type.h"#include "x-type/int.h"#include "x-type/prim.h"#include "x-type/ptr.h"Data Structures | |
| struct | x_image_t |
| Everything a rebuild pass reads. More... | |
| struct | x_image_table_t |
| An address-to-integer table: open addressing over a power of two. More... | |
| struct | x_image_writer_t |
| Everything a write pass reads and fills. More... | |
Macros | |
| #define | X_IMAGE_FLAGS_KEPT (X_OBJ_FLAG_ATTR_MASK | X_OBJ_FLAG_RO) |
| The flags a rebuilt object keeps from its record. | |
| #define | X_IMAGE_SAVE_UNITS 200000 |
| The save buffer's capacity, in units: room for a 200k-slot vector. | |
| #define | X_IMAGE_EXTERN_KEYS 256 |
| The naming cache's starting room, in keys. | |
| #define | X_IMAGE_TABLE_MIN_SLOTS 16 |
| The smallest object table, in slots. | |
| #define | X_IMAGE_TABLE_SLOTS_PER_KEY 2 |
| Slots kept per key: two, so at most half are ever taken. | |
| #define | X_IMAGE_TABLE_KEY_SHIFT 4 |
| Low bits dropped from an address before it is masked to a slot. | |
Typedefs | |
| typedef char | x_assert_image_table_min_slots[(X_IMAGE_TABLE_MIN_SLOTS &(X_IMAGE_TABLE_MIN_SLOTS - 1))==0 ? 1 :-1] |
Enumerations | |
| enum | { X_IMAGE_ROLE_SPAIR = -1 , X_IMAGE_ROLE_SATOM = -2 , X_IMAGE_ROLE_NIL = -3 } |
| The type word of an object record, when it is not an object index. More... | |
| enum | { X_IMAGE_RECORD_TYPE = 0 , X_IMAGE_RECORD_FLAGS = 1 , X_IMAGE_RECORD_COUNT = 2 , X_IMAGE_RECORD_UNITS = 3 , X_IMAGE_UNIT_WORDS = 2 } |
| The layout of one object record: [type][flags][n][kind word]*n. More... | |
Functions | |
| static x_int_t | x_image_record_words (x_int_t units) |
Words occupied by a record with units units. | |
| static x_obj_t * | x_image_role_type (x_int_t type) |
| The type tag for a role, or NULL for a type set later by index. | |
| static x_obj_t * | x_image_extern_obj (const x_image_t *img, x_int_t k) |
External entry k as an object, or NULL past the table. | |
| static x_int_t | x_image_extern_int (const x_image_t *img, x_int_t k) |
External entry k as an integer, or 0 past the table. | |
| static x_obj_t * | x_image_ref (const x_image_t *img, x_int_t v) |
| A ref unit: an object index, or the negated external index. | |
| static void | x_image_patch_unit (const x_image_t *img, x_obj_t *p_obj, x_int_t j, x_int_t kind, x_int_t v) |
Store one unit of p_obj from its kind and word. | |
| static void | x_image_alloc_pass (x_obj_t *p_base, x_image_t *img) |
| Pass 1: allocate every object on this base's chain. | |
| static void | x_image_patch_pass (x_image_t *img) |
| Pass 2: type each object by index and fill its units. | |
| static x_obj_t * | x_image_load_handler (x_obj_t *p_base, x_obj_t *p_obj) |
The type's load handler for p_obj, or NULL when it has none. | |
| static void | x_image_load_pass (x_obj_t *p_base, x_image_t *img) |
| Pass 3: each type's own load handler, now that the graph is whole. | |
| static x_obj_t * | x_prim_image_rebuild (x_obj_t *p_base, x_obj_t *p_args) |
| Rebuild an image's object graph – docs/state-image-format.md, section 5. | |
| static void | x_image_save_spair (x_obj_t *p_obj, x_int_t *buf) |
| Save a type-struct node: two references. | |
| static void | x_image_save_word (x_obj_t *p_obj, x_int_t *buf) |
| Save a static-tagged atom or an untyped object: one unit. | |
| static void | x_image_save_typed (x_obj_t *p_base, x_obj_t *p_obj, x_obj_t *p_buf) |
| Save a typed object through its type's save handler. | |
| static x_int_t | x_image_save (x_obj_t *p_base, x_obj_t *p_obj, x_obj_t *p_buf) |
Save one object into p_buf by its role or its type; the unit count. | |
| static x_obj_t * | x_prim_image_save (x_obj_t *p_base, x_obj_t *p_args) |
| Save one object's payload through its type – docs/state-image-format.md, section 4.3. | |
| static void | x_image_table_init (x_image_table_t *t, x_int_t n) |
Give t room for n keys at the table's occupancy. | |
| static void | x_image_table_free (x_image_table_t *t) |
Release t's storage. | |
| static x_int_t | x_image_table_slot (const x_image_table_t *t, x_int_t key) |
The slot holding key, or the empty slot it would take. | |
| static x_int_t | x_image_table_get (const x_image_table_t *t, x_int_t key) |
The value stored for key, or 0 when there is none. | |
| static void | x_image_table_put (x_image_table_t *t, x_int_t key, x_int_t val) |
Store val for key, doubling the table when another key would take it past its occupancy. | |
| static int | x_image_imaged (const x_image_writer_t *w, x_obj_t *p_obj) |
Whether p_obj is in the image: it carries the writer's flag. | |
| static void | x_image_count_pass (x_image_writer_t *w) |
| Pass 1: count the flagged objects and give each its index. | |
| static x_int_t | x_image_extern (x_image_writer_t *w, x_int_t word, x_int_t kind, x_obj_t *p_obj) |
The external index for word, asking the naming callable once. | |
| static x_int_t | x_image_ref_word (x_image_writer_t *w, x_int_t word, x_obj_t *p_obj) |
| A reference unit's word: the object's index, or the negated external index of an object outside the image. | |
| static x_int_t | x_image_bytes_word (x_image_writer_t *w, x_int_t word) |
| A bytes unit's word: the blob offset of [len][bytes NUL]. | |
| static x_int_t | x_image_foreign_word (x_image_writer_t *w, x_int_t word, x_obj_t *p_obj) |
| A foreign unit's word: the external index, or 0. | |
| static x_int_t | x_image_type_word (x_image_writer_t *w, x_obj_t *p_obj) |
| A record's type word: a role, or the index of the type struct. | |
| static void | x_image_emit_object (x_image_writer_t *w, x_obj_t *p_obj) |
| Write one object's record: [type][flags][n][kind word]*n. | |
| static void | x_image_emit_pass (x_image_writer_t *w) |
| Pass 2: every flagged object's record, in index order. | |
| static x_obj_t * | x_prim_image_write (x_obj_t *p_base, x_obj_t *p_args) |
| Write an image's object table and blob – docs/state-image-format.md, section 4. | |
| x_obj_t * | x_prim_image_register (x_obj_t *p_base, x_obj_t *p_args) |
State-image primitives – image save!, image rebuild!, image write!.
| #define X_IMAGE_EXTERN_KEYS 256 |
The naming cache's starting room, in keys.
A guess at how many words an image refers to outside itself; the table grows past it.
| #define X_IMAGE_FLAGS_KEPT (X_OBJ_FLAG_ATTR_MASK | X_OBJ_FLAG_RO) |
The flags a rebuilt object keeps from its record.
The attribute bits and RO are meaning; the rest describe the allocation that made the original, which this one does not share.
| #define X_IMAGE_SAVE_UNITS 200000 |
The save buffer's capacity, in units: room for a 200k-slot vector.
| #define X_IMAGE_TABLE_KEY_SHIFT 4 |
Low bits dropped from an address before it is masked to a slot.
The allocator places objects on sixteen-byte boundaries, so an address's low four bits are always zero and would pick one slot in sixteen. An allocator that aligns less costs longer probes, nothing else.
| #define X_IMAGE_TABLE_MIN_SLOTS 16 |
The smallest object table, in slots.
A power of two: a slot index is an address masked by the slot count less one, and doubling keeps it one.
| #define X_IMAGE_TABLE_SLOTS_PER_KEY 2 |
Slots kept per key: two, so at most half are ever taken.
A lookup probes from a key's slot until it meets the key or an empty slot. Half the slots empty is what guarantees it meets one, and keeps the runs short.
| typedef char x_assert_image_table_min_slots[(X_IMAGE_TABLE_MIN_SLOTS &(X_IMAGE_TABLE_MIN_SLOTS - 1))==0 ? 1 :-1] |
Compile-time assertion that the smallest table is a power of two.
| anonymous enum |
The type word of an object record, when it is not an object index.
A positive type word is the object index of the type struct; these three are the objects that have no struct in the image. See docs/state-image-format.md, section 3.3.
| Enumerator | |
|---|---|
| X_IMAGE_ROLE_SPAIR | A type-struct node, tagged x_type_pair_obj. |
| X_IMAGE_ROLE_SATOM | A static atom, tagged x_type_atom_obj. |
| X_IMAGE_ROLE_NIL | An untyped object. |
| anonymous enum |
The layout of one object record: [type][flags][n][kind word]*n.
Pass 1: allocate every object on this base's chain.
A role is typed now; an indexed type is set once its struct exists. Every object is SHARED: the image lives as long as the process.
|
static |
A bytes unit's word: the blob offset of [len][bytes NUL].
A NULL pointer becomes an empty string. Byte offsets, unaligned: the length is copied in, not stored.
|
static |
Pass 1: count the flagged objects and give each its index.
Indices follow the chain, most recent allocation first, as the loader will rebuild them.
|
static |
Write one object's record: [type][flags][n][kind word]*n.
|
static |
Pass 2: every flagged object's record, in index order.
|
static |
The external index for word, asking the naming callable once.
Applied as (name word kind obj) with evaluated arguments; an integer answer is the index, anything else means the word has no name and is written as the sentinel. Every answer is cached, one up since the table reads 0 as no entry, so a word is asked about once however often it occurs.
External entry k as an integer, or 0 past the table.
X fills the table through (obj set!), which stores an OBJECT; the word is the INT atom's value, not the slot's.
External entry k as an object, or NULL past the table.
|
static |
A foreign unit's word: the external index, or 0.
|
static |
Whether p_obj is in the image: it carries the writer's flag.
The type's load handler for p_obj, or NULL when it has none.
Pass 3: each type's own load handler, now that the graph is whole.
Applied as (load obj) with an evaluated argument.
|
static |
Pass 2: type each object by index and fill its units.
|
static |
Store one unit of p_obj from its kind and word.
Words occupied by a record with units units.
A ref unit: an object index, or the negated external index.
|
static |
A reference unit's word: the object's index, or the negated external index of an object outside the image.
The type tag for a role, or NULL for a type set later by index.
Save one object into p_buf by its role or its type; the unit count.
Save a type-struct node: two references.
Save a typed object through its type's save handler.
Applied as (save obj buf) with evaluated arguments; a type without a handler of its own gets the default, which walks the units shape.
Save a static-tagged atom or an untyped object: one unit.
The word is bytes when the object owns them – a type handle is its name atom, x_type_atom_obj-tagged and OWN, its word a C string (type.c, make-type) – and a machine word otherwise. The rebuild does not keep OWN, so the loaded atom never frees the blob it then points into.
|
static |
Release t's storage.
|
static |
The value stored for key, or 0 when there is none.
|
static |
Give t room for n keys at the table's occupancy.
|
static |
Store val for key, doubling the table when another key would take it past its occupancy.
The bigger table is given the old slot count as its key room, which is twice the slots.
|
static |
The slot holding key, or the empty slot it would take.
Meets one or the other because at most half the slots are ever taken.
|
static |
A record's type word: a role, or the index of the type struct.
Rebuild an image's object graph – docs/state-image-format.md, section 5.
x-lang form:
The object table at word ostart of buf holds nobj records with no length word: n is the unit count and each unit carries its kind, exactly as the type's save handler wrote it. Three passes – allocate, patch, load – so that a type struct exists before an instance names it, and every reference is in place before a load handler runs.
| p_base | Base (execution context); the objects join its chain. |
| p_args | Unevaluated: (self buf ostart nobj externals nextern blob index). |
index, filled so that entry i is object i. Register the state-image primitives.
Save one object's payload through its type – docs/state-image-format.md, section 4.3.
x-lang form:
The three roles are structural; everything else is its type's. buf receives [n][kind word]*n.
| p_base | Base (execution context). |
| p_args | Unevaluated: (self obj buf). |
Write an image's object table and blob – docs/state-image-format.md, section 4.
x-lang form:
Walks the allocation chain from cursor twice: once to index every object carrying flag, once to write each one's record through its type's save. The loop names nothing: a reference to an object outside the image and every foreign word go to name, applied as (name word kind obj), once per distinct word, and its integer answer is the external index – nil, the sentinel. result holds the table's capacity in words and the blob's in bytes on the way in, and the object count, table words, blob bytes and sentinel count on the way out, followed by the object index of each root in roots, a list of the objects the roots table will name – 0 for one outside the image.
| p_base | Base (execution context); the callable runs here. |
| p_args | Unevaluated: (self cursor flag table blob name roots result). |