x-engine-c v0.2.13
The C engine for x-lang
Loading...
Searching...
No Matches
image.c File Reference

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_tx_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_tx_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_tx_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_tx_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_tx_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_tx_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_tx_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_tx_prim_image_register (x_obj_t *p_base, x_obj_t *p_args)
 

Detailed Description

State-image primitives – image save!, image rebuild!, image write!.

Author
Jon Ruttan (jonru.nosp@m.ttan.nosp@m.@gmai.nosp@m.l.co.nosp@m.m)

Macro Definition Documentation

◆ X_IMAGE_EXTERN_KEYS

#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.

◆ X_IMAGE_FLAGS_KEPT

#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.

◆ X_IMAGE_SAVE_UNITS

#define X_IMAGE_SAVE_UNITS   200000

The save buffer's capacity, in units: room for a 200k-slot vector.

◆ X_IMAGE_TABLE_KEY_SHIFT

#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.

◆ X_IMAGE_TABLE_MIN_SLOTS

#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.

◆ X_IMAGE_TABLE_SLOTS_PER_KEY

#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 Documentation

◆ x_assert_image_table_min_slots

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.

Enumeration Type Documentation

◆ anonymous enum

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

anonymous enum

The layout of one object record: [type][flags][n][kind word]*n.

Enumerator
X_IMAGE_RECORD_TYPE 

Object index of the type, or a role.

X_IMAGE_RECORD_FLAGS 

The object's flags as written.

X_IMAGE_RECORD_COUNT 

n, the unit count.

X_IMAGE_RECORD_UNITS 

First unit; each unit is a kind and a word.

X_IMAGE_UNIT_WORDS 

Words per unit.

Function Documentation

◆ x_image_alloc_pass()

static void x_image_alloc_pass ( x_obj_t p_base,
x_image_t img 
)
static

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.

◆ x_image_bytes_word()

static x_int_t x_image_bytes_word ( x_image_writer_t w,
x_int_t  word 
)
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.

◆ x_image_count_pass()

static void x_image_count_pass ( x_image_writer_t w)
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.

◆ x_image_emit_object()

static void x_image_emit_object ( x_image_writer_t w,
x_obj_t p_obj 
)
static

Write one object's record: [type][flags][n][kind word]*n.

◆ x_image_emit_pass()

static void x_image_emit_pass ( x_image_writer_t w)
static

Pass 2: every flagged object's record, in index order.

◆ x_image_extern()

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 
)
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.

◆ x_image_extern_int()

static x_int_t x_image_extern_int ( const x_image_t img,
x_int_t  k 
)
static

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.

◆ x_image_extern_obj()

static x_obj_t * x_image_extern_obj ( const x_image_t img,
x_int_t  k 
)
static

External entry k as an object, or NULL past the table.

◆ x_image_foreign_word()

static x_int_t x_image_foreign_word ( x_image_writer_t w,
x_int_t  word,
x_obj_t p_obj 
)
static

A foreign unit's word: the external index, or 0.

◆ x_image_imaged()

static int x_image_imaged ( const x_image_writer_t w,
x_obj_t p_obj 
)
static

Whether p_obj is in the image: it carries the writer's flag.

◆ x_image_load_handler()

static x_obj_t * x_image_load_handler ( x_obj_t p_base,
x_obj_t p_obj 
)
static

The type's load handler for p_obj, or NULL when it has none.

◆ x_image_load_pass()

static void x_image_load_pass ( x_obj_t p_base,
x_image_t img 
)
static

Pass 3: each type's own load handler, now that the graph is whole.

Applied as (load obj) with an evaluated argument.

◆ x_image_patch_pass()

static void x_image_patch_pass ( x_image_t img)
static

Pass 2: type each object by index and fill its units.

◆ x_image_patch_unit()

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 
)
static

Store one unit of p_obj from its kind and word.

◆ x_image_record_words()

static x_int_t x_image_record_words ( x_int_t  units)
static

Words occupied by a record with units units.

◆ x_image_ref()

static x_obj_t * x_image_ref ( const x_image_t img,
x_int_t  v 
)
static

A ref unit: an object index, or the negated external index.

◆ x_image_ref_word()

static x_int_t x_image_ref_word ( x_image_writer_t w,
x_int_t  word,
x_obj_t p_obj 
)
static

A reference unit's word: the object's index, or the negated external index of an object outside the image.

◆ x_image_role_type()

static x_obj_t * x_image_role_type ( x_int_t  type)
static

The type tag for a role, or NULL for a type set later by index.

◆ x_image_save()

static x_int_t x_image_save ( x_obj_t p_base,
x_obj_t p_obj,
x_obj_t p_buf 
)
static

Save one object into p_buf by its role or its type; the unit count.

◆ x_image_save_spair()

static void x_image_save_spair ( x_obj_t p_obj,
x_int_t buf 
)
static

Save a type-struct node: two references.

◆ x_image_save_typed()

static void x_image_save_typed ( x_obj_t p_base,
x_obj_t p_obj,
x_obj_t p_buf 
)
static

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.

◆ x_image_save_word()

static void x_image_save_word ( x_obj_t p_obj,
x_int_t buf 
)
static

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.

◆ x_image_table_free()

static void x_image_table_free ( x_image_table_t t)
static

Release t's storage.

◆ x_image_table_get()

static x_int_t x_image_table_get ( const x_image_table_t t,
x_int_t  key 
)
static

The value stored for key, or 0 when there is none.

◆ x_image_table_init()

static void x_image_table_init ( x_image_table_t t,
x_int_t  n 
)
static

Give t room for n keys at the table's occupancy.

◆ x_image_table_put()

static void x_image_table_put ( x_image_table_t t,
x_int_t  key,
x_int_t  val 
)
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.

◆ x_image_table_slot()

static x_int_t x_image_table_slot ( const x_image_table_t t,
x_int_t  key 
)
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.

◆ x_image_type_word()

static x_int_t x_image_type_word ( x_image_writer_t w,
x_obj_t p_obj 
)
static

A record's type word: a role, or the index of the type struct.

◆ x_prim_image_rebuild()

static x_obj_t * x_prim_image_rebuild ( x_obj_t p_base,
x_obj_t p_args 
)
static

Rebuild an image's object graph – docs/state-image-format.md, section 5.

x-lang form:

(image rebuild! buf ostart nobj externals nextern blob index)

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.

Parameters
p_baseBase (execution context); the objects join its chain.
p_argsUnevaluated: (self buf ostart nobj externals nextern blob index).
Returns
index, filled so that entry i is object i.

◆ x_prim_image_register()

x_obj_t * x_prim_image_register ( x_obj_t p_base,
x_obj_t p_args 
)

Register the state-image primitives.

◆ x_prim_image_save()

static x_obj_t * x_prim_image_save ( x_obj_t p_base,
x_obj_t p_args 
)
static

Save one object's payload through its type – docs/state-image-format.md, section 4.3.

x-lang form:

(image save! obj buf)

The three roles are structural; everything else is its type's. buf receives [n][kind word]*n.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self obj buf).
Returns
The unit count n, as an integer.

◆ x_prim_image_write()

static x_obj_t * x_prim_image_write ( x_obj_t p_base,
x_obj_t p_args 
)
static

Write an image's object table and blob – docs/state-image-format.md, section 4.

x-lang form:

(image write! cursor flag table blob name roots result)
x_spair_t roots[2]
Definition x-prim.h:99

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.

Parameters
p_baseBase (execution context); the callable runs here.
p_argsUnevaluated: (self cursor flag table blob name roots result).
Returns
The object count, as an integer.