diff --git a/Makefile b/Makefile index e04ab9cd27..d71f1ef2d6 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ CWFLAGS=-Wall F_OFILES=\ f/rail.o \ + f/meme.o \ f/loom.o \ f/wire.o \ f/chad.o \ diff --git a/f/meme.c b/f/meme.c index bcb0e5a3c9..a5ea98ad58 100644 --- a/f/meme.c +++ b/f/meme.c @@ -2,14 +2,7 @@ ** ** This file is in the public domain. */ -#include "all.h" -#include -#include -#include -#include -#include -#include -#include "v/vere.h" +#include "f/meme.h" /* _me_boot_north(): install a north road. */ @@ -63,49 +56,70 @@ u2_me_boot(void* mem_v, c3_w len_w) u2H = u2R = _me_boot_north(mem_v, len_w); } -/* _me_road_all_hat(): in u2R, allocate directly on the hat. +/* _me_road_all_hat(): in u2R, allocate directly on the hat_w. */ static c3_w* _me_road_all_hat(c3_w len_w) { if ( len_w > u2_me_open ) { - return u2_me_bail(c3__meme); + u2_me_bail(c3__meme); return 0; } if ( u2_yes == u2_me_is_north ) { c3_w* all_w; - all_w = u2R->hat; - u2R->hat += len_w; + all_w = u2R->hat_w; + u2R->hat_w += len_w; return all_w; } else { - u2R->hat -= len_w; - return u2R->hat; + u2R->hat_w -= len_w; + return u2R->hat_w; } } +#if 0 // not yet used /* _me_road_all_cap(): in u2R, allocate directly on the cap. */ static c3_w* -_me_road_all_hat(c3_w len_w) +_me_road_all_cap(c3_w len_w) { if ( len_w > u2_me_open ) { - return u2_me_bail(c3__meme); + u2_me_bail(c3__meme); return 0; } if ( u2_yes == u2_me_is_north ) { - u2R->cap -= len_w; - return u2R->cap; + u2R->cap_w -= len_w; + return u2R->cap_w; } else { c3_w* all_w; - all_w = u2R->cap; - u2R->cap += len_w; + all_w = u2R->cap_w; + u2R->cap_w += len_w; return all_w; } } +#endif + +/* u2_me_bail(): bail out. Does not return. +** +** Bail motes: +** +** %evil :: erroneous cryptography +** %exit :: semantic failure +** %oops :: assertion failure +** %intr :: interrupt +** %fail :: computability failure +** %need :: namespace block +** %meme :: out of memory +*/ +c3_i +u2_me_bail(c3_m how_m) +{ + _longjmp(u2R->esc.buf, how_m); + return how_m; +} /* u2_me_leap(): in u2R, create a new road within the existing one. */ @@ -134,40 +148,40 @@ u2_me_fall() { c3_assert(0 != u2R->par_u); - u2R->par_u->cap_w = u2R->hat_u; + u2R->par_u->cap_w = u2R->hat_w; u2R = u2R->par_u; } -/* u2_me_golf(): record cap length for u2_flog(). +/* u2_me_golf(): record cap_w length for u2_flog(). */ c3_w u2_me_golf(void) { if ( u2_yes == u2_me_is_north ) { - return u2R->mat - u2R->cap; + return u2R->mat_w - u2R->cap_w; } else { - return u2R->cap - u2R->mat; + return u2R->cap_w - u2R->mat_w; } } -/* u2_me_flog(): reset cap. +/* u2_me_flog(): reset cap_w. */ void u2_me_flog(c3_w gof_w) { if ( u2_yes == u2_me_is_north ) { - u2R->cap = u2R->mat - gof_w; + u2R->cap_w = u2R->mat_w - gof_w; } else { - u2R->cap = u2R->mat + gof_w; + u2R->cap_w = u2R->mat_w + gof_w; } } /* u2_me_water(): produce watermarks. */ void -u2_me_water(c3_w* low_w, c3_w* hig_w); +u2_me_water(c3_w* low_w, c3_w* hig_w) { c3_assert(u2R == u2H); @@ -187,7 +201,7 @@ _me_box_slot(c3_w siz_w) c3_w i_w = 1; while ( 1 ) { - if ( i_w == u2_me_free_no ) { + if ( i_w == u2_me_fbox_no ) { return (i_w - 1); } if ( siz_w < 16 ) { @@ -202,19 +216,19 @@ _me_box_slot(c3_w siz_w) /* _me_box_make(): construct a box. */ u2_me_box* -_me_box_make(c3_v* box_v, c3_w siz_w, c3_w use_w) +_me_box_make(void* box_v, c3_w siz_w, c3_w use_w) { u2_me_box* box_u = box_v; c3_w* box_w = box_v; box_w[0] = siz_w; box_w[siz_w - 1] = siz_w; - -#ifdef U2_MEMORY_DEBUG - box_u->cod_w = COD_w; -#endif box_u->use_w = use_w; +# ifdef U2_MEMORY_DEBUG + box_u->cod_w = COD_w; +# endif + return box_u; } @@ -223,11 +237,11 @@ _me_box_make(c3_v* box_v, c3_w siz_w, c3_w use_w) void _me_box_attach(u2_me_box* box_u) { - c3_assert(box_u->siz_w >= (1 + c3_wiseof(u2_me_free))); + c3_assert(box_u->siz_w >= (1 + c3_wiseof(u2_me_fbox))); { c3_w sel_w = _me_box_slot(box_u->siz_w); - u2_me_free* fre_u = (void *)box_u; - u2_me_free** pfr_u = &u2R->all.fre_u[sel_w]; + u2_me_fbox* fre_u = (void *)box_u; + u2_me_fbox** pfr_u = &u2R->all.fre_u[sel_w]; fre_u->pre_u = 0; fre_u->nex_u = (*pfr_u); @@ -240,7 +254,7 @@ _me_box_attach(u2_me_box* box_u) void _me_box_detach(u2_me_box* box_u) { - u2_me_free* fre_u = (void*) box_u; + u2_me_fbox* fre_u = (void*) box_u; if ( fre_u->pre_u ) { fre_u->pre_u->nex_u = fre_u->nex_u; @@ -252,7 +266,7 @@ _me_box_detach(u2_me_box* box_u) } } -/* u2_me_walloc(): allocate storage words on hat. +/* u2_me_walloc(): allocate storage words on hat_w. */ void* u2_me_walloc(c3_w len_w) @@ -262,27 +276,27 @@ u2_me_walloc(c3_w len_w) // XX: this logic is totally bizarre, but preserve it. // - if ( (sel_w != 0) && (sel_w != u2_me_free_no - 1) ) { + if ( (sel_w != 0) && (sel_w != u2_me_fbox_no - 1) ) { sel_w += 1; } while ( 1 ) { - u2_me_free** pfr_u = &u2R->all.fre_u[sel_w]; + u2_me_fbox** pfr_u = &u2R->all.fre_u[sel_w]; while ( 1 ) { if ( 0 == *pfr_u ) { - if ( sel_w < (u2_me_free_no - 1) ) { + if ( sel_w < (u2_me_fbox_no - 1) ) { sel_w += 1; break; } else { - /* Nothing in top free list. Chip away at the hat. + /* Nothing in top free list. Chip away at the hat_w. */ return u2_me_boxto(_me_box_make(_me_road_all_hat(siz_w), siz_w, 1)); } } else { - if ( siz_w > (*pfr_u)->box_u->siz_w ) { + if ( siz_w > (*pfr_u)->box_u.siz_w ) { /* This free block is too small. Continue searching. */ pfr_u = &((*pfr_u)->nex_u); @@ -309,10 +323,10 @@ u2_me_walloc(c3_w len_w) /* If we can chop off another block, do it. */ - if ( (siz_w + c3_wiseof(u2_me_free) + 1) <= box_u->siz_w ) { + if ( (siz_w + c3_wiseof(u2_me_fbox) + 1) <= box_u->siz_w ) { /* Split the block. */ - c3_w* box_w = ((c3_w *)(void *)box_uy); + c3_w* box_w = ((c3_w *)(void *)box_u); c3_w* end_w = box_w + siz_w; c3_w lef_w = (box_u->siz_w - siz_w); @@ -325,13 +339,13 @@ u2_me_walloc(c3_w len_w) box_u->cod_w = COD_w; #endif return u2_me_boxto(box_u); + } } } } } } - /* u2_me_malloc(): allocate storage measured in bytes. */ void* @@ -343,7 +357,7 @@ u2_me_malloc(c3_w len_w) /* u2_me_free(): free storage. */ void -u2_me_free(void* tox_v); +u2_me_free(void* tox_v) { u2_me_box* box_u = u2_me_botox(tox_v); c3_w* box_w = (c3_w *)(void *)box_u; @@ -363,10 +377,7 @@ u2_me_free(void* tox_v); } if ( u2_yes == u2_me_is_north ) { - c3_w* bot_w = u2R->rut_w; - c3_w* top_w = u2R->hat_w; - - /* Try to coalesce with the previous block. + /* Try to coalesce with the block below. */ if ( box_w != u2R->rut_w ) { c3_w laz_w = *(box_w - 1); @@ -377,124 +388,440 @@ u2_me_free(void* tox_v); _me_box_make(pox_u, (laz_w + box_u->siz_w), 0); box_u = pox_u; - box_w = (c3_w*)(void *)box_u; + box_w = (c3_w*)(void *)pox_u; } } - /* Try to coalesce with the next block, or the wilderness. + /* Try to coalesce with the block above, or the wilderness. */ - if ( (box_w + siz_w) == u2R->hat_w ) { + if ( (box_w + box_u->siz_w) == u2R->hat_w ) { u2R->hat_w = box_w; } else { u2_me_box* nox_u = (u2_me_box*)(void *)(box_w + box_u->siz_w); if ( 0 == nox_u->use_w ) { - _me_nox_detach(nox_u); - _me_box_make(box_u, (nox_u->siz_w + box_u->siz_w)); + _me_box_detach(nox_u); + _me_box_make(box_u, (box_u->siz_w + nox_u->siz_w), 0); } _me_box_attach(box_u); } } else { - if ( - } + /* Try to coalesce with the block above. + */ + if ( (box_w + box_u->siz_w) != u2R->rut_w ) { + u2_me_box* nox_u = (u2_me_box*)(void *)(box_w + box_u->siz_w); - if ( ((c3_w*) tox_v) == u2 - if ( box_r != beg_r ) { - c3_w las_w = *u2_at_ray(box_r - 1); - u2_ray tod_r = (box_r - las_w); + if ( 0 == nox_u->use_w ) { + _me_box_detach(nox_u); + _me_box_make(box_u, (box_u->siz_w + nox_u->siz_w), 0); - if ( 0 == u2_rail_hut_use(tod_r) ) { - _rl_bloq_detach(ral_r, tod_r); - _rl_bloq_make(ral_r, tod_r, (las_w + u2_rail_hut_siz(box_r)), 0); - box_r = tod_r; + box_u = nox_u; + box_w = (c3_w*)(void *)nox_u; + } } - } - /* Try to coalesce with the next block, or with the wilderness. - */ - { - c3_w siz_w = u2_rail_hut_siz(box_r); - - if ( (box_r + siz_w == hat_r) ) { - u2_rail_hat_r(ral_r) = box_r; + /* Try to coalesce with the block below, or with the wilderness. + */ + if ( box_w == u2R->hat_w ) { + u2R->hat_w = (box_w + box_u->siz_w); } else { - u2_ray hob_r = (box_r + siz_w); + c3_w laz_w = *(box_w - 1); + u2_me_box* pox_u = (u2_me_box*)(void *)(box_w - laz_w); - if ( 0 == u2_rail_hut_use(hob_r) ) { - _rl_bloq_detach(ral_r, hob_r); - _rl_bloq_make(ral_r, box_r, (siz_w + u2_rail_hut_siz(hob_r)), 0); + if ( 0 == pox_u->use_w ) { + _me_box_detach(pox_u); + _me_box_make(pox_u, (laz_w + box_u->siz_w), 0); } - - /* Add to the appropriate free list. - */ - _rl_bloq_attach(ral_r, box_r); + _me_box_attach(box_u); } } - } -//////// Atoms from proto-atoms. - - /* Basic allocation. - */ - /* u2_me_walloc(): allocate storage measured in words. - */ - void* - u2_me_walloc(c3_w len_w); - - /* u2_me_malloc(): allocate storage measured in bytes. - */ - void* - u2_me_malloc(c3_w len_w); - - /* u2_me_free(): free storage. - */ - void - u2_me_free(void* lag_v); - - - -/* u2_me_slab(): create a length-bounded proto-atom. +/* _me_north_senior(): yes iff only in the senior region. */ -c3_w* -u2_me_slab(c3_w len_w) +static u2_bean +_me_north_senior(u2_noun dog) { - u2_ray nov_r = u2_rl_ralloc(ral_r, (len_w + c3_wiseof(u2_loom_atom))); - u2_atom nov = u2_pug_of(nov_r, 0); + c3_w* dog_w = u2_me_to_ptr(dog); - *u2_at_dog_mug(nov) = 0; - *u2_at_pug_len(nov) = len_w; + return u2_say((dog_w < u2R->rut_w) || (dog_w >= u2R->mat_w)); +} - /* Clear teh slab. - */ +/* _me_north_junior(): yes iff only in the junior section. +*/ +static u2_bean +_me_north_junior(u2_noun dog) +{ + c3_w* dog_w = u2_me_to_ptr(dog); + + return u2_say((dog_w >= u2R->cap_w) && (dog_w < u2R->mat_w)); +} +/* _me_north_normal(): yes iff only in the normal heap. +*/ +static u2_bean +_me_north_normal(u2_noun dog) +{ + return u2_and(u2_not(_me_north_senior(dog)), + u2_not(_me_north_junior(dog))); +} + +/* _me_south_senior(): yes iff only in the senior region. +*/ +static u2_bean +_me_south_senior(u2_noun dog) +{ + c3_w* dog_w = u2_me_to_ptr(dog); + + return u2_say((dog_w >= u2R->mat_w) || (dog_w < u2R->cap_w)); +} +/* _me_south_junior(): yes iff only in the junior section. +*/ +static u2_bean +_me_south_junior(u2_noun dog) +{ + c3_w* dog_w = u2_me_to_ptr(dog); + + return u2_say((dog_w >= u2R->cap_w) && (dog_w < u2R->mat_w)); +} +/* _me_south_normal(): yes iff only in the normal heap. +*/ +static u2_bean +_me_south_normal(u2_noun dog) +{ + return u2_and(u2_not(_me_south_senior(dog)), + u2_not(_me_south_junior(dog))); +} + +/* _me_wash_north(): clean up mug slots after copy. +*/ +static void _me_wash_north(u2_noun dog); +static void +_me_wash_north_in(u2_noun som) +{ + if ( u2_so(u2_me_is_cat(som)) ) return; + if ( u2_ne(_me_north_junior(som)) ) return; + + _me_wash_north(som); +} +static void +_me_wash_north(u2_noun dog) +{ + c3_assert(u2_me_is_dog(dog)); + c3_assert(u2_yes == _me_north_junior(dog)); { - c3_w i_w; + u2_me_noun* dog_u = u2_me_to_ptr(dog); - for ( i_w=0; i_w < len_w; i_w++ ) { - *u2_at_pug_buf(nov, i_w) = 0; + if ( dog_u->mug_w >> 31 ) { dog_u->mug_w = 0; } + + if ( u2_so(u2_me_is_pom(dog)) ) { + u2_me_cell* god_u = (u2_me_cell *)(void *)dog_u; + + _me_wash_north_in(god_u->hed); + _me_wash_north_in(god_u->tel); + } + } +} + +/* _me_wash_south(): clean up mug slots after copy. +*/ +static void _me_wash_south(u2_noun dog); +static void +_me_wash_south_in(u2_noun som) +{ + if ( u2_so(u2_me_is_cat(som)) ) return; + if ( u2_ne(_me_south_junior(som)) ) return; + + _me_wash_south(som); +} +static void +_me_wash_south(u2_noun dog) +{ + c3_assert(u2_me_is_dog(dog)); + c3_assert(u2_yes == _me_south_junior(dog)); + { + u2_me_noun* dog_u = u2_me_to_ptr(dog); + + if ( dog_u->mug_w >> 31 ) { dog_u->mug_w = 0; } + + if ( u2_so(u2_me_is_pom(dog)) ) { + u2_me_cell* god_u = (u2_me_cell *)(void *)dog_u; + + _me_wash_south_in(god_u->hed); + _me_wash_south_in(god_u->tel); + } + } +} + +/* _me_gain_use(): increment use count. +*/ +static void +_me_gain_use(u2_noun dog) +{ + c3_w* dog_w = u2_me_to_ptr(dog); + u2_me_box* box_u = u2_me_botox(dog_w); + + box_u = u2_me_botox(dog_w); + if ( 0xffffffff == box_u->use_w ) { + u2_me_bail(c3__fail); + } + else { + box_u->use_w += 1; + } +} + +/* _me_copy_north_in(): copy subjuniors on a north road. +*/ +static u2_noun _me_copy_north(u2_noun); +static u2_noun +_me_copy_north_in(u2_noun som) +{ + c3_assert(u2_none != som); + if ( u2_so(u2_me_is_cat(som)) ) { + return som; + } + else { + u2_noun dog = som; + + if ( u2_so(_me_north_senior(dog)) ) { + return dog; + } + else if ( u2_so(_me_north_junior(dog)) ) { + return _me_copy_north(dog); + } + else { + _me_gain_use(dog); + return dog; } } - return (nov_r + c3_wiseof(u2_loom_atom)); - -/* u2_me_slaq(): u2_me_slaq() with a defined blocksize. +} +/* _me_copy_north(): copy juniors on a north road. */ -c3_w* -u2_me_slaq(c3_g met_g, c3_w len_w); +static u2_noun +_me_copy_north(u2_noun dog) +{ + c3_assert(u2_yes == _me_north_junior(dog)); -/* u2_me_malt(): measure and finish a proto-atom. + if ( u2_ne(_me_north_junior(dog)) ) { + if ( u2_ne(_me_north_senior(dog)) ) { + _me_gain_use(dog); + } + return dog; + } + else { + u2_me_noun* dog_u = u2_me_to_ptr(dog); + + /* Borrow mug slot to record new destination. + */ + if ( dog_u->mug_w >> 31 ) { + u2_noun nov = (u2_noun) dog_u->mug_w; + + c3_assert(u2_so(_me_north_normal(nov))); + _me_gain_use(nov); + + return nov; + } + else { + if ( u2_yes == u2_me_is_pom(dog) ) { + u2_me_cell* old_u = u2_me_to_ptr(dog); + c3_w* new_w = u2_me_walloc(c3_wiseof(u2_me_cell)); + u2_noun new = u2_me_de_twin(dog, new_w); + u2_me_cell* new_u = (u2_me_cell*)(void *)new_w; + + new_u->mug_w = old_u->mug_w; + new_u->hed = _me_copy_north_in(old_u->hed); + new_u->tel = _me_copy_north_in(old_u->tel); + + /* Borrow mug slot to record new destination. + */ + old_u->mug_w = new; + return new; + } + else { + u2_me_atom* old_u = u2_me_to_ptr(dog); + c3_w* new_w = u2_me_walloc(old_u->len_w + c3_wiseof(u2_me_atom)); + u2_noun new = u2_me_de_twin(dog, new_w); + u2_me_atom* new_u = (u2_me_atom*)(void *)new_w; + + new_u->mug_w = old_u->mug_w; + new_u->len_w = old_u->len_w; + { + c3_w i_w; + + for ( i_w=0; i_w < old_u->len_w; i_w++ ) { + new_u->buf_w[i_w] = old_u->buf_w[i_w]; + } + } + + /* Borrow mug slot to record new destination. + */ + old_u->mug_w = new; + return new; + } + } + } +} + +/* _me_copy_south_in(): copy subjuniors on a south road. +*/ +static u2_noun _me_copy_south(u2_noun); +static u2_noun +_me_copy_south_in(u2_noun som) +{ + c3_assert(u2_none != som); + if ( u2_so(u2_me_is_cat(som)) ) { + return som; + } + else { + u2_noun dog = som; + + if ( u2_so(_me_south_senior(dog)) ) { + return dog; + } + else if ( u2_so(_me_south_junior(dog)) ) { + return _me_copy_south(dog); + } + else { + _me_gain_use(dog); + return dog; + } + } +} +/* _me_copy_south(): copy juniors on a south road. +*/ +static u2_noun +_me_copy_south(u2_noun dog) +{ + c3_assert(u2_yes == _me_south_junior(dog)); + + if ( u2_ne(_me_south_junior(dog)) ) { + if ( u2_ne(_me_south_senior(dog)) ) { + _me_gain_use(dog); + } + return dog; + } + else { + u2_me_noun* dog_u = u2_me_to_ptr(dog); + + /* Borrow mug slot to record new destination. + */ + if ( dog_u->mug_w >> 31 ) { + u2_noun nov = (u2_noun) dog_u->mug_w; + + c3_assert(u2_so(_me_south_normal(nov))); + _me_gain_use(nov); + + return nov; + } + else { + if ( u2_yes == u2_me_is_pom(dog) ) { + u2_me_cell* old_u = u2_me_to_ptr(dog); + c3_w* new_w = u2_me_walloc(c3_wiseof(u2_me_cell)); + u2_noun new = u2_me_de_twin(dog, new_w); + u2_me_cell* new_u = (u2_me_cell*)(void *)new_w; + + new_u->mug_w = old_u->mug_w; + new_u->hed = _me_copy_south_in(old_u->hed); + new_u->tel = _me_copy_south_in(old_u->tel); + + /* Borrow mug slot to record new destination. + */ + old_u->mug_w = new; + return new; + } + else { + u2_me_atom* old_u = u2_me_to_ptr(dog); + c3_w* new_w = u2_me_walloc(old_u->len_w + c3_wiseof(u2_me_atom)); + u2_noun new = u2_me_de_twin(dog, new_w); + u2_me_atom* new_u = (u2_me_atom*)(void *)new_w; + + new_u->mug_w = old_u->mug_w; + new_u->len_w = old_u->len_w; + { + c3_w i_w; + + for ( i_w=0; i_w < old_u->len_w; i_w++ ) { + new_u->buf_w[i_w] = old_u->buf_w[i_w]; + } + } + + /* Borrow mug slot to record new destination. + */ + old_u->mug_w = new; + return new; + } + } + } +} + +/* _me_gain_north(): gain on a north road. +*/ +static u2_noun +_me_gain_north(u2_noun dog) +{ + c3_assert(u2_none != dog); + if ( u2_yes == _me_north_senior(dog) ) { + /* senior pointers are not refcounted + */ + return dog; + } + else if ( u2_yes == _me_north_junior(dog) ) { + /* junior pointers are copied + */ + u2_noun mos = _me_copy_north(dog); + + _me_wash_north(dog); + return mos; + } + else { + /* normal pointers are refcounted + */ + _me_gain_use(dog); + return dog; + } +} + +/* _me_gain_south(): gain on a south road. +*/ +static u2_noun +_me_gain_south(u2_noun dog) +{ + if ( u2_yes == _me_south_senior(dog) ) { + /* senior pointers are not refcounted + */ + return dog; + } + else if ( u2_yes == _me_south_junior(dog) ) { + /* junior pointers are copied + */ + u2_noun mos = _me_copy_south(dog); + + _me_wash_south(dog); + return mos; + } + else { + /* normal pointers are refcounted + */ + _me_gain_use(dog); + return dog; + } +} + +/* u2_me_gain(): gain and/or copy juniors. */ u2_noun -u2_me_malt(c3_w* sal_w); +u2_me_gain(u2_noun som) +{ + c3_assert(u2_none != som); -/* u2_me_moot(): finish a pre-measured proto-atom; dangerous. -*/ -u2_noun -u2_me_moot(c3_w* sal_w); - -/* u2_me_mint(): finish a measured proto-atom. -*/ -u2_noun -u2_me_mint(c3_w* sal_w, c3_w len_w); + if ( u2_so(u2_me_is_cat(som)) ) { + return som; + } + else { + return u2_so(u2_me_is_north) + ? _me_gain_north(som) + : _me_gain_south(som); + } +} diff --git a/include/c/motes.h b/include/c/motes.h index f5b1f90577..062faca3db 100644 --- a/include/c/motes.h +++ b/include/c/motes.h @@ -647,6 +647,7 @@ # define c3__meh c3_s3('m','e','h') # define c3__meld c3_s4('m','e','l','d') # define c3__melt c3_s4('m','e','l','t') +# define c3__meme c3_s4('m','e','m','e') # define c3__memo c3_s4('m','e','m','o') # define c3__menu c3_s4('m','e','n','u') # define c3__mesh c3_s4('m','e','s','h') diff --git a/include/f/loom.h b/include/f/loom.h index 69f818b7d1..03f6191639 100644 --- a/include/f/loom.h +++ b/include/f/loom.h @@ -387,6 +387,7 @@ /* Tools for Martian booleans. */ +# define u2_na(x) (u2_no == (x)) # define u2_so(x) (u2_yes == (x)) # define u2_say(x) ( (x) ? u2_yes : u2_no ) # define u2_not(x) ( (x == u2_yes) ? u2_no : u2_yes ) diff --git a/include/f/meme.h b/include/f/meme.h index 28af3171d4..cd797e13e6 100644 --- a/include/f/meme.h +++ b/include/f/meme.h @@ -2,9 +2,21 @@ ** ** This file is in the public domain. */ + /** Subordinate includes. + **/ + /** c3: the C layer. + **/ +# include "c/portable.h" +# include "c/tune.h" +# include "c/types.h" +# include "c/defs.h" +# include "c/motes.h" +# include "c/comd.h" + + /** Tuning and configuration. **/ -# define u2_me_free_no 28 +# define u2_me_fbox_no 28 # undef U2_MEMORY_DEBUG # ifdef U2_MEMORY_DEBUG @@ -16,6 +28,84 @@ /** Data structures. **/ + /* u2_noun: tagged pointer. + ** + ** If bit 31 is 0, a u2_noun is a direct 31-bit atom ("cat"). + ** If bit 31 is 1 and bit 30 0, an indirect atom ("pug"). + ** If bit 31 is 1 and bit 30 1, an indirect cell ("pom"). + ** + ** Bits 0-29 are a word offset against u2_Loom. + */ + typedef c3_w u2_noun; + + /* u2_none - out-of-band noun. + */ +# define u2_none (u2_noun)0xffffffff + + /* u2_atom, u2_cell: logical atom and cell structures. + */ + typedef struct { + c3_w mug_w; + } u2_me_noun; + + typedef struct { + c3_w mug_w; + c3_w len_w; + c3_w buf_w[0]; + } u2_me_atom; + + typedef struct _u2_loom_cell { + c3_w mug_w; + u2_noun hed; + u2_noun tel; + } u2_me_cell; + + /* u2_yes, u2_no, u2_nul; + ** + ** Our Martian booleans and list terminator; empty string; not a nonu. + */ +# define u2_yes 0 +# define u2_no 1 +# define u2_nul 0 +# define u2_blip 0 + + /* Tools for Martian booleans. + */ +# define u2_so(x) (u2_yes == (x)) +# define u2_ne(x) (u2_no == (x)) +# define u2_say(x) ( (x) ? u2_yes : u2_no ) +# define u2_not(x) ( (x == u2_yes) ? u2_no : u2_yes ) +# define u2_and(x, y) ( (u2_so(x) && u2_so(y)) ? u2_yes : u2_no ) +# define u2_or(x, y) ( (u2_so(x) || u2_so(y)) ? u2_yes : u2_no ) + + /* Inside a noun. + */ +# define u2_me_is_cat(som) (((som) >> 31) ? u2_no : u2_yes) +# define u2_me_is_dog(som) (((som) >> 31) ? u2_yes : u2_no) + +# define u2_me_is_pug(som) (2 == (som >> 30)) +# define u2_me_is_pom(som) (3 == (som >> 30)) +# define u2_me_to_ptr(som) ((void *)(u2_me_into(som & 0x3fffffff))) + +# define u2_me_is_atom(som) u2_or(u2_noun_is_cat(som), \ + u2_noun_is_pug(som)) +# define u2_me_is_cell(som) u2_noun_is_pom(som) +# define u2_me_de_twin(dog, dog_w) ((dog & 0xc0000000) | u2_me_outa(dog_w)) + + + /* More typedefs. + */ + typedef u2_noun u2_atom; // must be atom + typedef u2_noun u2_term; // @tas + typedef u2_noun u2_mote; // @tas + typedef u2_noun u2_cell; // must be cell + typedef u2_noun u2_trel; // must be triple + typedef u2_noun u2_qual; // must be quadruple + typedef u2_noun u2_quin; // must be quintuple + typedef u2_noun u2_bean; // loobean: 0 == u2_yes, 1 == u2_no + typedef u2_noun u2_weak; // may be u2_none + + /* u2_me_box: classic allocation box. ** ** The box size is also stored at the end of the box in classic @@ -40,7 +130,6 @@ } u2_me_box; # define u2_me_boxed(len_w) (len_w + c3_wiseof(u2_me_box) + 1) -# define u2_me_boxof(box_v) ( (void *) \ # define u2_me_boxto(box_v) ( (void *) \ ( ((c3_w *)(void*)(box_v)) + \ c3_wiseof(u2_me_box) ) ) @@ -49,18 +138,16 @@ ( ((c3_w *)(void*)(tox_v)) - \ c3_wiseof(u2_me_box) ) ) -((box_w) + c3_wiseof(u2_me_box)) - - /* u2_me_free: free node in heap. Sets minimum node size. + /* u2_me_fbox: free node in heap. Sets minimum node size. ** */ - typedef struct _u2_me_free { + typedef struct _u2_me_fbox { u2_me_box box_u; - struct _u2_me_free* pre_u; - struct _u2_me_free* nex_u; - } u2_me_free; + struct _u2_me_fbox* pre_u; + struct _u2_me_fbox* nex_u; + } u2_me_fbox; -# define u2_me_minimum (c3_wiseof(u2_me_free)) +# define u2_me_minimum (c3_wiseof(u2_me_fbox)) /* u2_me_road: contiguous allocation and execution context. ** @@ -103,17 +190,16 @@ struct _u2_me_road* kid_u; // child road list struct _u2_me_road* nex_u; // sibling road - struct { // layout information - c3_w* cap_w; // top of transient region - c3_w* hat_w; // top of durable region - c3_w* mat_w; // bottom of transient region - c3_w* rut_w; // bottom of durable region - + c3_w* cap_w; // top of transient region + c3_w* hat_w; // top of durable region + c3_w* mat_w; // bottom of transient region + c3_w* rut_w; // bottom of durable region +#if 0 c3_w* gar_w; // bottom of guard region (future) c3_w* rag_w; // top of guard region (future) c3_w pad_w[4]; // future interesting info - } lay; +#endif struct { // escape buffer union { @@ -123,7 +209,7 @@ } esc; struct { // allocation pools - u2_me_free* fre_u[u2_me_free_no]; // heap by node size log + u2_me_fbox* fre_u[u2_me_fbox_no]; // heap by node size log # ifdef U2_MEMORY_DEBUG c3_w liv_w; // number of live words # endif @@ -175,15 +261,15 @@ /** Macros. **/ -# define u2_me_is_north ((u2R->cap > u2R->hat) ? u2_yes : u2_no) +# define u2_me_is_north ((u2R->cap_w > u2R->hat_w) ? u2_yes : u2_no) # define u2_me_is_south ((u2_yes == u2_me_is_north) ? u2_no : u2_yes) # define u2_me_open ( (u2_yes == u2_me_is_north) \ - ? (c3_w)(u2R->cap - u2R->hat) \ - : (c3_w)(u2R->hat - u2R->cap) ) + ? (c3_w)(u2R->cap_w - u2R->hat_w) \ + : (c3_w)(u2R->hat_w - u2R->cap_w) ) -# define u2_me_into(x) (((c3_w*)(void*)u2H) + (x)) -# define u2_me_outa(p) (((c3_w*)(void*)(p)) - (c3w*)(void*)u2H) +# define u2_me_into(x) (u2_Loom + (x)) +# define u2_me_outa(p) (((c3_w*)(void*)(p)) - u2_Loom) /** Functions. @@ -196,10 +282,10 @@ /* u2_me_trap(): setjmp within road. */ #if 0 - u2_noun + u2_bean u2_me_trap(void); #else -# define u2_me_trap() (u2_noun)(setjmp(u2R->esc.buf)) +# define u2_me_trap() (u2_bean)(setjmp(u2R->esc.buf)) #endif /* u2_me_bail(): bail out. Does not return. @@ -228,7 +314,7 @@ /* u2_me_fall(): return to parent road. */ void - u2_me_fall(void): + u2_me_fall(void); /* u2_me_leap(): advance to inner road. */ @@ -249,18 +335,19 @@ ** // allocate some inner stuff... ** u2_me_fall(); ** // inner stuff is still valid, but on cap - ** u2_me_ + ** u2_me_flog(gof_w); ** ** u2_me_flog(0) simply clears the cap. */ void - u2_me_flog(void); + u2_me_flog(c3_w gof_w); /* u2_me_water(): produce high and low watermarks. Asserts u2R == u2H. */ void u2_me_water(c3_w *low_w, c3_w *hig_w); + /** Allocation. **/ /* Basic allocation. @@ -283,11 +370,6 @@ /* Reference and arena control. */ - /* u2_me_open(): u2_yes iff a free block is available. - */ - u2_bean - u2_me_open(c3_w len_w); - /* u2_me_gain(): gain and/or copy juniors. */ u2_weak @@ -415,436 +497,3 @@ u2_weak u2_me_uniq(u2_noun som); - /* u2_rl_find(): - ** - ** Cache search for function (0 means nock) and sample. - */ - u2_weak // transfer - u2_rl_find(u2_ray ral_r, - u2_mote fun_m, - u2_noun sam); // retain - - /* u2_rl_save(): - ** - ** Cache store for function (0 means nock), sample and product. - */ - u2_weak // transfer - u2_rl_save(u2_ray ral_r, - u2_mote fun_m, // retain - u2_noun sam, // retain - u2_noun pro); // transfer - - /* u2_rl_uniq(): - ** - ** Use cache to render object unique. - */ - u2_noun // produce - u2_rl_uniq(u2_ray ral_r, - u2_noun som); // submit - - /* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`. - ** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`. - ** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`. - ** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`. - ** - ** Extend as needed... - */ - u2_weak // transfer - u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - - /* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`. - ** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`. - ** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`. - ** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`. - ** - ** Extended - */ - u2_weak // transfer - u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - - /** Abbreviations. - **/ -# define u2_rc(ral_r, a, b) u2_rl_cell(ral_r, a, b) -# define u2_rt(ral_r, a, b, c) u2_rl_trel(ral_r, a, b, c) -# define u2_rq(ral_r, a, b, c, d) u2_rl_qual(ral_r, a, b, c, d) -# define u2_ri(ral_r, a, b, c, d, e) u2_rl_quil(ral_r, a, b, c, d, e) -# define u2_ro(ral_r, a) u2_rl_lone(ral_r, a) -# define u2_ru(ral_r, a) u2_rl_unit(ral_r, a) -# define u2_rx(ral_r, a) u2_rl_take(ral_r, a) -# define u2_rz(ral_r, a) u2_rl_lose(ral_r, a) -# define u2_rl u2_rl_list -# define u2_rk u2_rl_rack - - - /** Functions. - **/ - - /* u2_rl_malloc(): - ** - ** Allocate `sib_w` *bytes* of raw C storage. - */ - void* - u2_rl_malloc(u2_ray ral_r, - c3_w sib_w); - - /* u2_rl_open(): - ** - ** Yes iff [a] more words remain in the pad. - */ - u2_bean - u2_rl_open(u2_ray ral_r, - c3_w a_w); - - /* u2_rl_ralloc(): - ** - ** Allocate `siz_w` words of raw ray storage. - */ - u2_ray - u2_rl_ralloc(u2_ray ral_r, - c3_w siz_w); - - /* u2_rl_rfree(): - ** - ** Free raw ray storage allocated by `u2_rl_ralloc()`. - */ - void - u2_rl_rfree(u2_ray ral_r, - u2_ray nov_r); - - /* u2_rl_senior(): - ** - ** Yes iff `dus` is senior in `ral` - ie, does not - ** require reference counting. - */ - u2_bean - u2_rl_senior(u2_ray ral_r, - u2_noun dus); // retain - - /* u2_rl_refs(): - ** - ** Return the reference count of (som). For debugging, etc. - */ - c3_w - u2_rl_refs(u2_ray ral_r, - u2_noun som); - - /* u2_rl_copy(): - ** - ** Copy indirect noun `fiz` into main storage, preserving dags. - ** Must be followed by `rl_wash(fiz)` if `fiz` is to be preserved. - */ - u2_weak // transfer - u2_rl_copy(u2_ray ral_r, - u2_dog fiz); // retain - - /* u2_rl_take(): - ** - ** Produce `a`, as eligible result. Copy juniors; reference peers. - */ - u2_weak // transfer - u2_rl_take(u2_ray ral_r, - u2_weak a); // retain -# define u2_rl_ice(ral_r, a) \ - u2_rl_take(ral_r, a) - - /* u2_rl_tamp(): - ** - ** Tamp, eliding the segment from `net` up to `bat`, - ** preserving the root `lef`. - ** - ** Assumes u2_rl_clear() with the same arguments. - */ - u2_noun - u2_rl_tamp(u2_ray ral_r, - u2_noun lef, - u2_ray net_r, - u2_ray bat_r); - - /* u2_rl_valid(): - ** - ** Validate rail for memory bugs. - */ - void - u2_rl_valid(u2_ray ral_r); - - /* u2_rl_water(): - ** - ** Return east and west watermarks, respectively. - */ - void - u2_rl_water(u2_ray ral_r, - c3_w* maz_w, - c3_w* buc_w); - - /** Basic noun fabrication. - **/ - /* u2_rl_bytes(): - ** - ** Copy `a` bytes from `b` to an LSB first atom. - */ - u2_weak // transfer - u2_rl_bytes(u2_ray ral_r, - c3_w a_w, - const c3_y* b_y); - - /* u2_rl_cell(): - ** - ** Produce the cell `[a b]`. - */ - u2_weak // transfer - u2_rl_cell(u2_ray ral_r, - u2_weak a, // transfer - u2_weak b); // transfer - - /* u2_rl_list(): - ** - ** Produce a null-terminated list, terminating `...` with `u2_none`. - */ - u2_weak // transfer - u2_rl_list(u2_rail ral_r, - ...); // transfer - - /* u2_rl_lone(): - ** - ** Create the unit `[0 a]`. - */ -#if 0 - u2_weak // transfer - u2_rl_lone(u2_rail ral_r, - u2_weak a); // transfer -#else -# define u2_rl_lone(ral_r, a) \ - u2_rc(ral_r, a, u2_nul) -#endif - - /* u2_rl_molt(): - ** - ** Mutate `som` with a 0-terminated list of axis, noun pairs. - ** Axes must be cats (31 bit). - */ - u2_weak // transfer - u2_rl_molt(u2_rail ral_r, - u2_weak som, // retain - ...); // transfer - - /* u2_rl_molv(): - ** - ** As u2_rl_molt(), by argument pointer. - */ - u2_weak // transfer - u2_rl_molv(u2_rail ral_r, - u2_weak som, // retain - va_list vap); // transfer - - /* u2_rl_mp(): - ** - ** Copy the GMP integer [a] into an atom. - */ - u2_weak // transfer - u2_rl_mp(u2_ray ral_r, - mpz_t a_mp); // transfer - - /* u2_rl_qual(): - ** - ** Produce the triple `[a b c d]`. - */ -#if 0 - u2_weak // transfer - u2_rl_qual(u2_rail ral_r, - u2_weak a, // transfer - u2_weak b, // transfer - u2_weak c, // transfer - u2_weak d); // transfer -#else -# define u2_rl_qual(ral_r, a, b, c, d) \ - u2_rc(ral_r, a, u2_rt(ral_r, b, c, d)) -#endif - - /* u2_rl_rack(): - ** - ** Produce an n-tuple, terminating `...` with `u2_none`. - */ - u2_weak // transfer - u2_rl_rack(u2_rail ral_r, - ...); // transfer - - /* u2_rl_string(): - ** - ** Produce an LSB-first atom from the C string `a`. - */ - u2_weak // transfer - u2_rl_string(u2_ray ral_r, - const c3_c* a_c); - - /* u2_rl_trel(): - ** - ** Create the triple `[a b c]`. - */ -#if 0 - u2_weak // transfer - u2_rl_trel(u2_rail ral_r, - u2_weak a, // transfer - u2_weak b, // transfer - u2_weak c); // transfer -#else -# define u2_rl_trel(ral_r, a, b, c) \ - u2_rc(ral_r, a, u2_rc(ral_r, b, c)) -#endif - - /* u2_rl_unit(): - ** - ** Create the unit `[0 a]`. - */ -#if 0 - u2_weak // transfer - u2_rl_unit(u2_rail ral_r, - u2_weak a); // transfer -#else -# define u2_rl_unit(ral_r, a) \ - u2_rc(ral_r, u2_nul, a) -#endif - - /* u2_rl_vint(): - ** - ** Create `a + 1`. - */ - u2_weak // transfer - u2_rl_vint(u2_rail ral_r, - u2_weak a); // transfer - - /* u2_rl_words(): - ** - ** Copy [a] words from [b] into an atom. - */ - u2_weak // transfer - u2_rl_words(u2_ray ral_r, - c3_w a_w, - const c3_w* b_w); - - /** Caching. - **/ - /* u2_rl_find(): - ** - ** Cache search for function (0 means nock) and sample. - */ - u2_weak // transfer - u2_rl_find(u2_ray ral_r, - u2_mote fun_m, - u2_noun sam); // retain - - /* u2_rl_save(): - ** - ** Cache store for function (0 means nock), sample and product. - */ - u2_weak // transfer - u2_rl_save(u2_ray ral_r, - u2_mote fun_m, // retain - u2_noun sam, // retain - u2_noun pro); // transfer - - /* u2_rl_uniq(): - ** - ** Use cache to render object unique. - */ - u2_noun // produce - u2_rl_uniq(u2_ray ral_r, - u2_noun som); // submit - - /* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`. - ** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`. - ** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`. - ** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`. - ** - ** Extend as needed... - */ - u2_weak // transfer - u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - u2_weak // transfer - u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // retain - - /* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`. - ** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`. - ** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`. - ** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`. - ** - ** Extended - */ - u2_weak // transfer - u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer - - u2_weak // transfer - u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun, // retain - u2_noun); // transfer diff --git a/v/cttp.c b/v/cttp.c index 0adfd1b05b..cfa7928fe7 100644 --- a/v/cttp.c +++ b/v/cttp.c @@ -32,6 +32,8 @@ # pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif +#define CTTP_NO_PIPELINE + /* Forward declarations. */ static void _cttp_ccon_kick(u2_ccon* coc_u); @@ -638,6 +640,7 @@ _cttp_message_complete(http_parser* par_u) if ( u2_yes == coc_u->sec ) { SSL_shutdown(coc_u->ssl.ssl_u); _cttp_ccon_cryp_rout(coc_u); + uL(fprintf(uH, "cttp: close b: %p\n", coc_u)); uv_close((uv_handle_t*)&coc_u->wax_u, _cttp_ccon_fail_cb); } return 0; @@ -806,6 +809,7 @@ _cttp_ccon_reboot(u2_ccon* coc_u) /* Begin again. */ + uL(fprintf(uH, "ccon: rekick\r\n")); _cttp_ccon_kick(coc_u); } break; @@ -836,6 +840,7 @@ _cttp_ccon_fail(u2_ccon* coc_u, u2_bean say) _cttp_ccon_reboot(coc_u); } else { + uL(fprintf(uH, "cttp: close: %p\n", coc_u)); uv_close((uv_handle_t*)&coc_u->wax_u, _cttp_ccon_fail_cb); } } @@ -1319,6 +1324,7 @@ _cttp_ccon_new(u2_bean sec, c3_s por_s, c3_c* hot_c) return coc_u; } +#ifndef CTTP_NO_PIPELINE /* _cttp_ccon_find(): find existing connection for remote server. */ static u2_ccon* @@ -1335,19 +1341,23 @@ _cttp_ccon_find(u2_bean sec, c3_s por_s, c3_c* hot_c) } return 0; } +#endif /* _cttp_ccon(): create or find persistent client connection. */ static u2_ccon* _cttp_ccon(u2_bean sec, c3_s por_s, c3_c* hot_c) { +#ifndef CTTP_NO_PIPELINE u2_ccon* coc_c = _cttp_ccon_find(sec, por_s, hot_c); if ( 0 != coc_c ) { free(hot_c); return coc_c; } - else return _cttp_ccon_new(sec, por_s, hot_c); + else +#endif + return _cttp_ccon_new(sec, por_s, hot_c); } /* _cttp_creq(): cttp request from noun.