From e09139b1321658a923483f06a2eed8eb099fc7dc Mon Sep 17 00:00:00 2001 From: Quodss Date: Tue, 23 Sep 2025 18:20:56 +0200 Subject: [PATCH 01/27] ska: integration wip --- pkg/c3/motes.h | 1 + pkg/noun/allocate.c | 1 + pkg/noun/ska_core.c | 3 +++ pkg/noun/ska_core.h | 5 +++++ 4 files changed, 10 insertions(+) create mode 100644 pkg/noun/ska_core.c create mode 100644 pkg/noun/ska_core.h diff --git a/pkg/c3/motes.h b/pkg/c3/motes.h index 3ba8a700ed..84b0f26ce6 100644 --- a/pkg/c3/motes.h +++ b/pkg/c3/motes.h @@ -1089,6 +1089,7 @@ # define c3__site c3_s4('s','i','t','e') # define c3__sith c3_s4('s','i','t','h') # define c3__size c3_s4('s','i','z','e') +# define c3__ska c3_s3('s','k','a') # define c3__slam c3_s4('s','l','a','m') # define c3__slap c3_s4('s','l','a','p') # define c3__slat c3_s4('s','l','a','t') diff --git a/pkg/noun/allocate.c b/pkg/noun/allocate.c index 96a09b26d8..e36989a20f 100644 --- a/pkg/noun/allocate.c +++ b/pkg/noun/allocate.c @@ -1784,6 +1784,7 @@ u3a_rewrite_compact(void) u3a_relocate_noun(&(u3R->pro.don)); u3a_relocate_noun(&(u3R->pro.day)); u3a_relocate_noun(&(u3R->pro.trace)); + u3a_relocate_noun(&(u3R->dir.ka)); u3h_relocate(&(u3R->cax.har_p)); u3h_relocate(&(u3R->cax.per_p)); } diff --git a/pkg/noun/ska_core.c b/pkg/noun/ska_core.c new file mode 100644 index 0000000000..075434bb27 --- /dev/null +++ b/pkg/noun/ska_core.c @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28c29bba907b5e380808cd90cb122b4ca50b7fa73525740fab704c3acaa172d7 +size 937831 diff --git a/pkg/noun/ska_core.h b/pkg/noun/ska_core.h new file mode 100644 index 0000000000..a7ee4bee5a --- /dev/null +++ b/pkg/noun/ska_core.h @@ -0,0 +1,5 @@ +#ifndef u3_ska_core_H +#define u3_ska_core_H +extern unsigned char u3_Ka_core[]; +extern unsigned int u3_Ka_core_len; +#endif From 4e80d77f02517faf3fbe05dda31a577035b71735 Mon Sep 17 00:00:00 2001 From: Quodss Date: Tue, 23 Sep 2025 18:21:06 +0200 Subject: [PATCH 02/27] ska: integration wip --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..4fecd208b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +pkg/noun/ska_core.c filter=lfs diff=lfs merge=lfs -text From a8a1bec0d6540160e8a7a2d86fe20343d3a7cc4e Mon Sep 17 00:00:00 2001 From: Quodss Date: Tue, 23 Sep 2025 19:57:24 +0200 Subject: [PATCH 03/27] ska: rest of integration --- pkg/noun/allocate.h | 8 + pkg/noun/build.zig | 6 +- pkg/noun/direct.c | 222 +++++++++++ pkg/noun/direct.h | 23 ++ pkg/noun/hashtable.c | 17 + pkg/noun/hashtable.h | 12 + pkg/noun/jets.c | 92 ++++- pkg/noun/jets.h | 7 + pkg/noun/manage.c | 17 +- pkg/noun/nock.c | 921 ++++++++++++++++++++++++++++++++++++++++--- pkg/noun/nock.h | 57 ++- pkg/vere/melt.c | 4 + 12 files changed, 1285 insertions(+), 101 deletions(-) create mode 100644 pkg/noun/direct.c create mode 100644 pkg/noun/direct.h diff --git a/pkg/noun/allocate.h b/pkg/noun/allocate.h index 418db1a7ba..0b88b9294c 100644 --- a/pkg/noun/allocate.h +++ b/pkg/noun/allocate.h @@ -127,6 +127,7 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, u3p(u3h_root) cod_p; // cold state u3p(u3h_root) han_p; // hank cache u3p(u3h_root) bas_p; // battery hashes + u3p(u3h_root) pax_p; // [path axis] -> arm jet (home road only) } u3a_jets; /* u3a_road: contiguous allocation and execution context. @@ -186,6 +187,9 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, struct { // bytecode state u3p(u3h_root) har_p; // formula->post of bytecode + /* Direct calls */ + u3p(u3h_root) dar_p; // [less fol]->post of bytecode + u3p(u3h_root) lar_p; // fol->(list [less post]) of bytecode } byc; struct { // scry namespace @@ -209,6 +213,10 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, u3p(u3h_root) har_p; // transient u3p(u3h_root) per_p; // persistent } cax; + + struct { // direct calls + u3_noun ka; // ~ | +ka core vase XX raw noun + } dir; } u3a_road; typedef u3a_road u3_road; diff --git a/pkg/noun/build.zig b/pkg/noun/build.zig index f0d353597a..1b130450cc 100644 --- a/pkg/noun/build.zig +++ b/pkg/noun/build.zig @@ -179,6 +179,7 @@ pub fn build(b: *std.Build) !void { const c_source_files = [_][]const u8{ "allocate.c", + "direct.c", "events.c", "hashtable.c", "imprison.c", @@ -376,8 +377,9 @@ const c_source_files = [_][]const u8{ "nock.c", "options.c", "retrieve.c", - "ship.c", "serial.c", + "ship.c", + "ska_core.c", "trace.c", "urth.c", "vortex.c", @@ -387,6 +389,7 @@ const c_source_files = [_][]const u8{ const install_headers = [_][]const u8{ "allocate.h", + "direct.h", "error.h", "events.h", "hashtable.h", @@ -403,6 +406,7 @@ const install_headers = [_][]const u8{ "retrieve.h", "serial.h", "ship.h", + "ska_core.h", "trace.h", "types.h", "urth.h", diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c new file mode 100644 index 0000000000..34e1329be9 --- /dev/null +++ b/pkg/noun/direct.c @@ -0,0 +1,222 @@ +/// @file + +#include "direct.h" + +static inline c3_w +_cn_of_prog(u3n_prog *pog_u) +{ + u3_post pog_p = u3of(u3n_prog, pog_u); + return pog_p >> u3a_vits; +} + +static inline u3n_prog* +_cn_to_prog(c3_w pog_w) +{ + u3_post pog_p = pog_w << u3a_vits; + return u3to(u3n_prog, pog_p); +} + +// RETAINS +// +static void +_ca_rip(u3_noun cape, u3_noun* l, u3_noun* r) +{ + if ( c3y == u3ud(cape) ) + { + *l = *r = u3x_loob(cape); // debug assert + } + else + { + u3r_cell(cape, l, r); + } +} + +// RETAINS arguments +// (here it is ok since deduplication will always happen on each iteration, so +// inductive argument of validity of uncounted refs applies) +// +static c3_o +_so_huge(u3_noun cape_one, + u3_noun data_one, + u3_noun cape_two, + u3_noun data_two) +{ + if ( c3y == u3r_sing(cape_one, cape_two) + && c3y == u3r_sing(data_one, data_two) ) + { + return c3y; + } + + if ( c3y == u3ud(data_one) ) + { + if ( c3n == u3x_loob(cape_one) ) return c3y; + return c3a(u3ud(cape_two), + c3a(u3x_loob(cape_two), + u3r_sing(data_one, data_two))); + } + + if ( c3y == u3ud(data_two) ) + { + u3x_loob(cape_two); + if ( c3n == cape_one ) return u3m_bail(c3__exit); // normalization assert + return c3n; + } + + u3_noun lope, rope, loop, roop; + u3_noun l_data_one, r_data_one; + u3_noun l_data_two, r_data_two; + + u3r_cell(data_one, &l_data_one, &r_data_one); + u3r_cell(data_two, &l_data_two, &r_data_two); + + _ca_rip(cape_one, &lope, &rope); + _ca_rip(cape_two, &loop, &roop); + + return c3a(_so_huge(lope, l_data_one, loop, l_data_two), + _so_huge(rope, r_data_one, roop, r_data_two)); +} + +void +u3d_prep_ka() +{ + if ( u3R->dir.ka ) { + return; + } + // [sock=hoon soak=hoon noir=hoon skan=hoon] + // + u3_noun hoons = u3s_cue_bytes((c3_d)u3_Ka_core_len, u3_Ka_core); + u3_noun sock, soak, noir, skan; + if ( c3n == u3r_mean(hoons, + 2, &sock, + 6, &soak, + 14, &noir, + 15, &skan, 0) ) { + u3m_bail(c3__fail); + } + + u3_noun bild = u3v_wish("!>(..zuse)"); + u3_noun slap = u3v_wish("slap"); + + bild = u3n_slam_on(u3k(slap), u3nc(bild, u3k(sock))); + bild = u3n_slam_on(u3k(slap), u3nc(bild, u3k(soak))); + bild = u3n_slam_on(u3k(slap), u3nc(bild, u3k(noir))); + bild = u3n_slam_on(u3k(slap), u3nc(bild, u3k(skan))); + + u3_noun ka = u3n_slam_on(slap, + u3nc(bild, u3nt(c3__wing, c3_s2('k', 'a'), u3_nul))); + + u3z(hoons); + u3R->dir.ka = ka; +} + +// XX: reentrance? +// +void +u3d_rout(u3_noun sub, u3_noun fol) +{ + u3d_prep_ka(); + // ( [%wing p=~[%rout]] ) + // + u3_noun gen = u3nt(c3__wing, c3_s4('r','o','u','t'), u3_nul), + rout = u3dc("slap", u3R->dir.ka, gen); + + u3_noun typ = u3nt(c3__cell, c3__noun, c3__noun); + u3_noun sam = u3nt(typ, sub, fol); // !>([sub=* fol=*]) + + u3_noun slam = u3v_wish("slam"); + u3_noun gul = u3nt(u3nc(1, 0), u3nc(0, 0), 0); // |~(^ ~) + + u3_noun pro = u3n_slam_et(gul, slam, u3nc(rout, sam)); + + u3_assert(_(u3du(pro))); + if ( 0 != u3h(pro) ) + { + u3m_bail(c3__fail); + } + u3R->dir.ka = u3k(u3t(pro)); + u3z(pro); +} + +// RETAINS +// `list` is (list pro=[sock *]) +// +u3_weak +u3d_match_sock(u3_noun cape, u3_noun data, u3_noun list) +{ + u3_weak pro = u3_none; + u3_noun cape_max, data_max; + u3_noun i, cape_i, data_i; + while ( u3_nul != list ) + { + u3x_cell(list, &i, &list); + u3x_mean(i, 4, &cape_i, + 5, &data_i, + 0); + if ( c3n == _so_huge(cape_i, data_i, cape, data) ) continue; + // first match or better match + // + if ( (u3_none == pro) + || (c3y == _so_huge(cape_max, data_max, cape_i, data_i)) ) + { + pro = i; + cape_max = cape_i; + data_max = data_i; + } + } + return pro; +} + +// RETAINS arguments +// XX remove u3dc, use hard-coded axes +// +u3n_prog* +u3d_search(u3_noun sub, u3_noun fol) +{ + u3n_prog* pog_u = NULL; + u3_weak lit = u3h_git(u3R->byc.lar_p, fol); + if ( u3_none != lit ) + { + u3_weak less_pog = u3d_match_sock(c3y, sub, lit); + pog_u = ( u3_none != less_pog ) + ? _cn_to_prog(u3t(less_pog)) + : NULL; + } + if ( pog_u ) return pog_u; + + u3d_rout(u3k(sub), u3k(fol)); + u3_noun slap = u3v_wish("slap"); + u3_noun gul = u3nt(u3nc(1, 0), u3nc(0, 0), 0); // |~(^ ~) + + // ( [%wing p=~[%lon]] ) + // + u3_noun gen = u3nt(c3__wing, c3_s3('l','o','n'), u3_nul); + u3_noun vax = u3n_slam_on(u3k(slap), u3nc(u3k(u3R->dir.ka), gen)); + u3_noun lon = u3k(u3t(vax)); + u3z(vax); + + // ( [%wing p=~[%cook]] ) + // + gen = u3nt(c3__wing, c3__cook, u3_nul); + vax = u3n_slam_on(slap, u3nc(u3k(u3R->dir.ka), gen)); + u3_noun gat = u3k(u3t(vax)); + u3z(vax); + + u3_noun pro = u3n_slam_et(gul, gat, lon); + u3_assert(_(u3du(pro))); + if ( 0 != u3h(pro) ) + { + u3m_bail(c3__fail); + } + u3_noun boil = u3t(pro); + + u3_noun cole, code, fols; + if ( c3n == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ) + { + u3m_bail(c3__fail); + return 0; + } + + pog_u = u3n_build_direct(sub, fol, cole, code, fols); + u3z(pro); + return pog_u; +} \ No newline at end of file diff --git a/pkg/noun/direct.h b/pkg/noun/direct.h new file mode 100644 index 0000000000..a5fc87abb6 --- /dev/null +++ b/pkg/noun/direct.h @@ -0,0 +1,23 @@ +#ifndef U3_DIRECT_H +#define U3_DIRECT_H + +#include "error.h" +#include "hashtable.h" +#include "manage.h" +#include "nock.h" +#include "retrieve.h" +#include "serial.h" +#include "ska_core.h" +#include "vortex.h" +#include "xtract.h" + +void +u3d_rout(u3_noun sub, u3_noun fol); + +u3n_prog* +u3d_search(u3_noun sub, u3_noun fol); + +u3_weak +u3d_match_sock(u3_noun cape, u3_noun data, u3_noun list); + +#endif /* ifndef U3_DIRECT_H */ diff --git a/pkg/noun/hashtable.c b/pkg/noun/hashtable.c index 6b1fb39f87..890f4f4eba 100644 --- a/pkg/noun/hashtable.c +++ b/pkg/noun/hashtable.c @@ -296,6 +296,23 @@ u3h_put(u3p(u3h_root) har_p, u3_noun key, u3_noun val) } } +/* u3h_jib(): update a hashtable value +** +** `key` is RETAINED +** `fun_f` must transfer the noun argument +** XX make it in-place? +*/ +void +u3h_jib(u3p(u3h_root) har_p, + u3_noun key, + u3_noun(*fun_f)(u3_weak, void*), + void* ptr_v) +{ + u3h_put(har_p, + key, + fun_f(u3h_get(har_p, key), ptr_v)); +} + /* _ch_buck_del(): delete from bucket */ static c3_o diff --git a/pkg/noun/hashtable.h b/pkg/noun/hashtable.h index f263dd8a05..c8334e6a41 100644 --- a/pkg/noun/hashtable.h +++ b/pkg/noun/hashtable.h @@ -105,6 +105,18 @@ */ void u3h_put(u3p(u3h_root) har_p, u3_noun key, u3_noun val); + + /* u3h_jib(): update a hashtable value or insert `val` + ** + ** `key` is RETAINED + ** `fun_f` must transfer the noun argument + ** XX make it in-place? + */ + void + u3h_jib(u3p(u3h_root) har_p, + u3_noun key, + u3_noun(*fun_f)(u3_weak, void*), + void* ptr_v); /* u3h_put_get(): insert in caching hashtable, returning deleted entry ** diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index 3598364b1a..c22f20516f 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -258,6 +258,30 @@ _cj_axis(u3_noun fol) } } +/* read 31-bit integer for an arm axis from a dot-prefixed C string +* returns 0 on failure +*/ +static c3_l +_cj_read_axe(c3_c* str_c, c3_c* who_c) +{ + // ".2" common case shortcut + // + if ( '2' == str_c[1] && 0 == str_c[2] ) return 2; + + c3_d axe_d = 0; + c3_l axe_l = 0; + if ( (1 != sscanf(str_c + 1, "%" SCNu64, &axe_d)) + || axe_d >> 32ULL + || (((c3_w)1 << 31) & (axe_l = (c3_w)axe_d)) + || (axe_l < 2) ) + { + u3l_log("jets: %s: bad fcs %s", who_c, str_c); + return 0; + } + + return axe_l; +} + /* _cj_warm_hump(): generate axis-to-arm map. RETAIN. */ static u3_noun @@ -276,15 +300,7 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc) c3_l axe_l = 0; if ( '.' == *(jet_u->fcs_c) ) { - c3_d axe_d = 0; - - if ( (1 != sscanf(jet_u->fcs_c+1, "%" SCNu64, &axe_d)) || - axe_d >> 32ULL || - (((c3_w)1 << 31) & (axe_l = (c3_w)axe_d)) || - (axe_l < 2) ) - { - u3l_log("jets: activate: bad fcs %s", jet_u->fcs_c); - } + axe_l = _cj_read_axe(jet_u->fcs_c, "activate"); } else { u3_noun nam = u3i_string(jet_u->fcs_c); @@ -309,7 +325,12 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc) /* _cj_install(): install dashboard entries. */ static c3_w -_cj_install(u3j_core* ray_u, c3_w jax_l, u3_noun pel, u3_noun lab, u3j_core* dev_u) +_cj_install(u3j_core* ray_u, + c3_w jax_l, + u3_noun pel, + u3_noun lab, + u3j_core* dev_u, + u3_noun pax) { c3_w i_w; u3_assert(u3R == &(u3H->rod_u)); @@ -318,7 +339,8 @@ _cj_install(u3j_core* ray_u, c3_w jax_l, u3_noun pel, u3_noun lab, u3j_core* dev for ( i_w = 0; 0 != dev_u[i_w].cos_c; i_w++ ) { u3j_core* kid_u = &dev_u[i_w]; u3_noun loc = _cj_core_loc(u3k(pel), kid_u), - bal = u3nc(u3k(u3h(u3t(loc))), u3k(lab)); + bal = u3nc(u3k(u3h(u3t(loc))), u3k(lab)), + xap = u3nc(u3i_string(kid_u->cos_c), u3k(pax)); kid_u->jax_l = jax_l; ray_u[jax_l] = *kid_u; @@ -339,11 +361,23 @@ _cj_install(u3j_core* ray_u, c3_w jax_l, u3_noun pel, u3_noun lab, u3j_core* dev } } - jax_l = _cj_install(ray_u, ++jax_l, loc, bal, kid_u->dev_u); + if ( kid_u->arm_u ) { + for (u3j_harm* jet_u = kid_u->arm_u; jet_u->fcs_c; jet_u++ ) { + if ( '.' != jet_u->fcs_c[0] ) continue; + c3_l axe_l = _cj_read_axe(jet_u->fcs_c, "_cj_install"); + if ( !axe_l ) continue; + u3_noun key = u3nc(u3k(xap), axe_l); + u3h_put(u3R->jed.pax_p, key, u3i_chub((c3_d)(c3_p)jet_u)); + u3z(key); + } + } + + jax_l = _cj_install(ray_u, ++jax_l, loc, bal, kid_u->dev_u, xap); } } u3z(pel); u3z(lab); + u3z(pax); return jax_l; } @@ -814,13 +848,16 @@ u3j_boot(c3_o nuu_o) if ( c3n == nuu_o ) { u3h_free(u3R->jed.hot_p); + u3h_free(u3R->jed.pax_p); } u3R->jed.hot_p = u3h_new(); + u3R->jed.pax_p = u3h_new(); return _cj_install(u3D.ray_u, 1, (c3_l) (long long) u3D.dev_u[0].par_u, u3_nul, - u3D.dev_u); + u3D.dev_u, + u3_nul); } /* _cj_soft(): kick softly by arm axis. @@ -846,6 +883,7 @@ _cj_soft(u3_noun cor, u3_noun axe) static u3_weak _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) { + c3_c* cos_c = ( cop_u ) ? cop_u->cos_c : "????"; if ( 0 == ham_u->fun_f ) { return u3_none; } @@ -861,7 +899,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) char soc_c[5]; memset(soc_c, 0, 5); - strncpy(soc_c, cop_u->cos_c, 4); + strncpy(soc_c, cos_c, 4); soc_c[4] = 0; cod_w = u3i_string(soc_c); cod_w = u3a_lush(cod_w); @@ -899,7 +937,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) if ( c3n == u3r_sing(ame, pro) ) { u3l_log("test: %s %s: mismatch: good %x, bad %x", - cop_u->cos_c, + cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c, u3r_mug(ame), u3r_mug(pro)); @@ -911,7 +949,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) #if 0 u3l_log("test: %s %s", - cop_u->cos_c, + cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c); #endif u3z(ame); @@ -922,6 +960,16 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) } } +/* u3j_call_direct(): try to kick by jet, no validation. No ice test. +** Return u3_none if no kick. +** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. +*/ +u3_weak +u3j_call_direct(u3_noun cor, u3j_harm* ham_u, c3_l axe_l) +{ + return _cj_kick_z(cor, NULL, ham_u, axe_l); +} + /* _cj_hook_in(): execute hook from core, or fail. */ static u3_noun @@ -2322,7 +2370,7 @@ _cj_mark_hank(u3_noun kev, void* dat) u3m_quac* u3j_mark() { - u3m_quac** qua_u = c3_malloc(sizeof(*qua_u) * 7); + u3m_quac** qua_u = c3_malloc(sizeof(*qua_u) * 8); qua_u[0] = c3_calloc(sizeof(*qua_u[0])); qua_u[0]->nam_c = strdup("warm jet state"); @@ -2360,7 +2408,13 @@ u3j_mark() sum_w += qua_u[5]->siz_w; - qua_u[6] = NULL; + qua_u[6] = c3_calloc(sizeof(*qua_u[6])); + qua_u[6]->nam_c = strdup("path/axis -> jet driver map"); + qua_u[6]->siz_w = u3h_mark(u3R->jed.pax_p) * 4; + + sum_w += qua_u[6]->siz_w; + + qua_u[7] = NULL; tot_u->siz_w = sum_w; tot_u->qua_u = qua_u; @@ -2401,6 +2455,7 @@ u3j_free(void) u3h_free(u3R->jed.bas_p); if ( u3R == &(u3H->rod_u) ) { u3h_free(u3R->jed.hot_p); + u3h_free(u3R->jed.pax_p); } } @@ -2441,5 +2496,6 @@ u3j_rewrite_compact(void) if ( u3R == &(u3H->rod_u) ) { u3h_relocate(&(u3R->jed.hot_p)); + u3h_relocate(&(u3R->jed.pax_p)); } } diff --git a/pkg/noun/jets.h b/pkg/noun/jets.h index c81ab18318..8b24b859a3 100644 --- a/pkg/noun/jets.h +++ b/pkg/noun/jets.h @@ -169,6 +169,13 @@ u3j_hook(u3_noun cor, const c3_c* tam_c); + /* u3j_call_direct(): try to kick by jet, no validation. No ice test. + ** Return u3_none if no kick. + ** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. + */ + u3_weak + u3j_call_direct(u3_noun cor, u3j_harm* ham_u, c3_l axe_l); + /* u3j_soft(): ** ** Execute hook from core, without jet. diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index bcccd8aebf..f6839672ca 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -530,6 +530,8 @@ _pave_parts(void) u3R->jed.han_p = u3h_new(); u3R->jed.bas_p = u3h_new(); u3R->byc.har_p = u3h_new(); + u3R->byc.dar_p = u3h_new(); + u3R->byc.lar_p = u3h_new(); } static c3_d @@ -567,6 +569,7 @@ _pave_home(void) u3R->mat_p = u3R->cap_p = top_p; _pave_parts(); + u3R->dir.ka = u3_nul; } STATIC_ASSERT( (c3_wiseof(u3v_home) <= (1U << u3a_page)), @@ -1144,6 +1147,7 @@ u3m_leap(c3_w pad_w) { u3R = rod_u; _pave_parts(); + u3R->dir.ka = u3to(u3_road, u3R->par_p)->dir.ka; } #ifdef U3_MEMORY_DEBUG rod_u->all.fre_w = 0; @@ -1229,9 +1233,14 @@ u3m_love(u3_noun pro) { // save cache pointers from current road // - u3p(u3h_root) byc_p = u3R->byc.har_p; + u3p(u3h_root) byc_har_p = u3R->byc.har_p; + // XX integrate junior direct call tables + // + u3n_free_table(u3R->byc.dar_p); + u3h_free(u3R->byc.lar_p); u3a_jets jed_u = u3R->jed; u3p(u3h_root) per_p = u3R->cax.per_p; + u3_noun ka = u3R->dir.ka; // fallback to parent road (child heap on parent's stack) // @@ -1240,8 +1249,9 @@ u3m_love(u3_noun pro) // copy product and caches off our stack // pro = u3a_take(pro); + ka = u3a_take(ka); jed_u = u3j_take(jed_u); - byc_p = u3n_take(byc_p); + byc_har_p = u3n_take(byc_har_p); per_p = u3h_take(per_p); // pop the stack @@ -1253,8 +1263,9 @@ u3m_love(u3_noun pro) // integrate junior caches // u3j_reap(jed_u); - u3n_reap(byc_p); + u3n_reap(byc_har_p); u3z_reap(u3z_memo_keep, per_p); + u3z(u3R->dir.ka), u3R->dir.ka = ka; return pro; } diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index f7bc22c7ed..e6a49a8f09 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -3,6 +3,7 @@ #include "nock.h" #include "allocate.h" +#include "direct.h" #include "hashtable.h" #include "imprison.h" #include "jets.h" @@ -522,7 +523,25 @@ _n_nock_on(u3_noun bus, u3_noun fol) X(KUTS, "kuts", &&do_kuts), /* 92: c3_s */ \ X(KITB, "kitb", &&do_kitb), /* 93: c3_b */ \ X(KITS, "kits", &&do_kits), /* 94: c3_s */ \ - X(LAST, NULL, NULL), /* 95 */ + /* SKA-specific output */ \ + /* Search for a program with direct calls and execute it */ \ + /* Head position, keep */ \ + X(DISB, "disb", &&do_disb), /* 95: c3_y */ \ + X(DISS, "diss", &&do_diss), /* 96: c3_s */ \ + /* Head position, lose */ \ + X(LISB, "lisb", &&do_lisb), /* 97: c3_y */ \ + X(LISS, "liss", &&do_liss), /* 98: c3_s */ \ + /* Tail position */ \ + X(TISB, "tisb", &&do_tisb), /* 99: c3_y */ \ + X(TISS, "tiss", &&do_tiss), /* 100: c3_s */ \ + /* Direct calls to a program */ \ + /* Head position */ \ + X(DIRB, "dirb", &&do_dirb), /* 101: c3_y */ \ + X(DIRS, "dirs", &&do_dirs), /* 102: c3_s */ \ + /* Tail position */ \ + X(TIRB, "tirb", &&do_tirb), /* 103: c3_y */ \ + X(TIRS, "tirs", &&do_tirs), /* 104: c3_s */ \ + X(LAST, NULL, NULL), /* 105 */ // Opcodes. Define X to select the enum name from OPCODES. #define X(opcode, name, indirect_jump) opcode @@ -542,6 +561,8 @@ _n_arg(c3_y cod_y) case BUSH: case BAST: case BALT: case MUTB: case KUTB: case MITB: case KITB: case HILB: case HINB: + case DISB: case LISB: case TISB: + case DIRB: case TIRB: return sizeof(c3_y); case FASK: case FASL: case FISL: case FISK: @@ -551,6 +572,8 @@ _n_arg(c3_y cod_y) case SUSH: case SAST: case SALT: case MUTS: case KUTS: case MITS: case KITS: case HILS: case HINS: + case DISS: case LISS: case TISS: + case DIRS: case TIRS: return sizeof(c3_s); case SWIP: case SWIN: @@ -565,8 +588,8 @@ _n_arg(c3_y cod_y) /* _n_melt(): measure space for list of ops (from _n_comp) */ static u3_noun -_n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, - c3_w* reg_w, c3_w* lit_w, c3_w* mem_w) +_n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, c3_w* reg_w, + c3_w* lit_w, c3_w* mem_w, c3_w* dir_w) { c3_w len_w = u3qb_lent(ops), i_w = len_w - 1, @@ -645,6 +668,8 @@ _n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, case FISK: case FISL: case SUSH: case SANS: case LISL: case LISK: case SKIS: case SLIS: case HILS: case HINS: + case DISS: case LISS: case TISS: + case DIRS: case TIRS: u3_assert(0); //overflows break; @@ -666,6 +691,7 @@ _n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, case SANB: case LIBL: case LIBK: case KITB: case MITB: case HILB: case HINB: + case DISB: case LISB: case TISB: a_w = (*lit_w)++; if ( a_w <= 0xFF ) { siz_y[i_w] = 2; @@ -678,6 +704,20 @@ _n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, u3_assert(0); } break; + + case DIRB: case TIRB: + a_w = (*dir_w)++; + if ( a_w <= 0xFF ) { + siz_y[i_w] = 2; + } + else if ( a_w <= 0xFFFF ) { + siz_y[i_w] = 3; + } + else { + fprintf(stderr, "_n_melt(): over 2^16 direct call sites.\r\n"); + u3_assert(0); + } + break; } } @@ -700,35 +740,60 @@ _n_prog_dat(u3n_prog* pog_u) /* _n_prog_new(): allocate and set up pointers for u3n_prog */ static u3n_prog* -_n_prog_new(c3_w byc_w, c3_w cal_w, - c3_w reg_w, c3_w lit_w, c3_w mem_w) -{ - c3_w cab_w = (sizeof(u3j_site) * cal_w), - reb_w = (sizeof(u3j_rite) * reg_w), - lib_w = (sizeof(u3_noun) * lit_w), - meb_w = (sizeof(u3n_memo) * mem_w), - pad_w = (8 - byc_w % 8) % 8, - pod_w = lit_w % 2, - ped_w = mem_w % 2, - dat_w = byc_w + cab_w + reb_w + lib_w + meb_w + pad_w + - (pod_w * sizeof(u3_noun)) + (ped_w * sizeof(u3n_memo)); - - u3n_prog* pog_u = u3a_malloc(sizeof(u3n_prog) + dat_w); +_n_prog_new(c3_w byc_w, c3_w cal_w, c3_w reg_w, + c3_w lit_w, c3_w mem_w, c3_w dir_w) +{ + // program data segment already has alignment of 8 + // also ops_y does not require padding + // + c3_w len_w = byc_w; + + // for each array: + // align the byte offset; + // record current byte offset for the array pointer; + // advance the offset by the size of the array. + // + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w let_w = len_w; + len_w += (sizeof(u3_noun) * lit_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w mim_w = len_w; + len_w += (sizeof(u3n_memo) * mem_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w cel_w = len_w; + len_w += (sizeof(u3j_site) * cal_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w rig_w = len_w; + len_w += (sizeof(u3j_rite) * reg_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w der_w = len_w; + len_w += (sizeof(u3n_dire) * dir_w); + + u3n_prog* pog_u = u3a_malloc(sizeof(u3n_prog) + len_w); + c3_y* dat_y = _n_prog_dat(pog_u); + pog_u->byc_u.own_o = c3y; pog_u->byc_u.len_w = byc_w; - pog_u->byc_u.ops_y = (c3_y*) _n_prog_dat(pog_u); + pog_u->byc_u.ops_y = dat_y; pog_u->lit_u.len_w = lit_w; - pog_u->lit_u.non = (u3_noun*) (pog_u->byc_u.ops_y + pog_u->byc_u.len_w + pad_w); + pog_u->lit_u.non = (u3_noun*) (dat_y + let_w); pog_u->mem_u.len_w = mem_w; - pog_u->mem_u.sot_u = (u3n_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w + pod_w); + pog_u->mem_u.sot_u = (u3n_memo*) (dat_y + mim_w); pog_u->cal_u.len_w = cal_w; - pog_u->cal_u.sit_u = (u3j_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w + ped_w); + pog_u->cal_u.sit_u = (u3j_site*) (dat_y + cel_w); pog_u->reg_u.len_w = reg_w; - pog_u->reg_u.rit_u = (u3j_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); + pog_u->reg_u.rit_u = (u3j_rite*) (dat_y + rig_w); + + pog_u->dir_u.len_w = dir_w; + pog_u->dir_u.dat_u = (u3n_dire*) (dat_y + der_w); return pog_u; } @@ -739,33 +804,50 @@ _n_prog_new(c3_w byc_w, c3_w cal_w, static u3n_prog* _n_prog_old(u3n_prog* sep_u) { - c3_w cab_w = sizeof(u3j_site) * sep_u->cal_u.len_w, - reb_w = sizeof(u3j_rite) * sep_u->reg_u.len_w, - lib_w = sizeof(u3_noun) * sep_u->lit_u.len_w, - meb_w = sizeof(u3n_memo) * sep_u->mem_u.len_w, - pod_w = sep_u->lit_u.len_w % 2, - ped_w = sep_u->mem_u.len_w % 2, - dat_w = cab_w + reb_w + lib_w + meb_w + - (pod_w * sizeof(u3_noun)) + (ped_w * sizeof(u3n_memo)); + // program data segment already has alignment of 8 + // + c3_w len_w = (sizeof(u3_noun) * sep_u->lit_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w mim_w = len_w; + len_w += (sizeof(u3n_memo) * sep_u->mem_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w cel_w = len_w; + len_w += (sizeof(u3j_site) * sep_u->cal_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w rig_w = len_w; + len_w += (sizeof(u3j_rite) * sep_u->reg_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w der_w = len_w; + len_w += (sizeof(u3n_dire) * sep_u->dir_u.len_w); + + u3n_prog* pog_u = u3a_malloc(sizeof(u3n_prog) + len_w); + c3_y* dat_y = _n_prog_dat(pog_u); - u3n_prog* pog_u = u3a_malloc(sizeof(u3n_prog) + dat_w); pog_u->byc_u.own_o = c3n; pog_u->byc_u.len_w = sep_u->byc_u.len_w; pog_u->byc_u.ops_y = sep_u->byc_u.ops_y; pog_u->lit_u.len_w = sep_u->lit_u.len_w; - pog_u->lit_u.non = (u3_noun*) _n_prog_dat(pog_u); + pog_u->lit_u.non = (u3_noun*) dat_y; pog_u->mem_u.len_w = sep_u->mem_u.len_w; - pog_u->mem_u.sot_u = (u3n_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w + pod_w); + pog_u->mem_u.sot_u = (u3n_memo*) (dat_y + mim_w); pog_u->cal_u.len_w = sep_u->cal_u.len_w; - pog_u->cal_u.sit_u = (u3j_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w + ped_w); + pog_u->cal_u.sit_u = (u3j_site*) (dat_y + cel_w); pog_u->reg_u.len_w = sep_u->reg_u.len_w; - pog_u->reg_u.rit_u = (u3j_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); + pog_u->reg_u.rit_u = (u3j_rite*) (dat_y + rig_w); + + pog_u->dir_u.len_w = sep_u->dir_u.len_w; + pog_u->dir_u.dat_u = (u3n_dire*) (dat_y + der_w); + + memcpy(pog_u->lit_u.non, sep_u->lit_u.non, len_w); - memcpy(pog_u->lit_u.non, sep_u->lit_u.non, dat_w); return pog_u; } @@ -787,6 +869,24 @@ _n_prog_asm_inx(c3_y* buf_y, c3_w* i_w, c3_s inx_s, c3_y cod) } } +// RETAINS +// `bell` is (unit (pair path axis)) +// +static void +_direct_match_bell(u3n_dire* dir_u, u3_noun bell) +{ + u3_weak harm; + if ( u3_nul == bell + || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, u3t(bell))) + ) { + dir_u->ham_u = NULL; + } + else { + dir_u->ham_u = (u3j_harm*)(c3_p)u3r_chub(0, u3x_atom(harm)); + dir_u->axe_l = u3t(u3t(bell)); + } +} + /* _n_prog_asm(): assemble list of ops (from _n_comp) into u3n_prog */ static void @@ -797,7 +897,8 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) c3_s lit_s = 0, cal_s = 0, mem_s = 0, - reg_s = 0; + reg_s = 0, + dir_s = 0; c3_w i_w = pog_u->byc_u.len_w-1; buf_y[i_w] = HALT; @@ -907,6 +1008,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) case BUSH: case SANB: case KITB: case MITB: case HILB: case HINB: + case DISB: case LISB: case TISB: _n_prog_asm_inx(buf_y, &i_w, lit_s, cod); pog_u->lit_u.non[lit_s++] = u3k(u3t(op)); break; @@ -928,6 +1030,15 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) sit_u->fin_p = 0; break; } + + /* direct call site index args */ + case DIRB: case TIRB: { + _n_prog_asm_inx(buf_y, &i_w, dir_s, cod); + u3n_dire* dir_u = &(pog_u->dir_u.dat_u[dir_s++]); + dir_u->pog_p = u3k(u3h(u3t(op))); // [sock fol] pair, to be rewritten + _direct_match_bell(dir_u, u3t(u3t(op))); + break; + } } } ops = u3t(ops); @@ -950,10 +1061,11 @@ _n_prog_from_ops(u3_noun ops) cal_w = 0, reg_w = 0, lit_w = 0, - mem_w = 0; + mem_w = 0, + dir_w = 0; - sip = _n_melt(ops, &byc_w, &cal_w, ®_w, &lit_w, &mem_w); - pog_u = _n_prog_new(byc_w, cal_w, reg_w, lit_w, mem_w); + sip = _n_melt(ops, &byc_w, &cal_w, ®_w, &lit_w, &mem_w, &dir_w); + pog_u = _n_prog_new(byc_w, cal_w, reg_w, lit_w, mem_w, dir_w); _n_prog_asm(ops, pog_u, sip); return pog_u; } @@ -1008,6 +1120,8 @@ _n_emit(u3_noun *ops, u3_noun op) } static c3_w _n_comp(u3_noun*, u3_noun, c3_o, c3_o); +static c3_w _n_comp_direct(u3_noun*, u3_noun, c3_o, c3_o, + u3_noun*, u3_noun, u3_noun); /* _n_bint(): hint-processing helper for _n_comp. * hif: hint-formula (first part of 11). RETAIN. @@ -1048,6 +1162,15 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) // post-skip cleanup opcode ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); } break; + + // entry point into SKA computation: defer `nef` compilation + // + case c3__ska: { + c3_y op = _(tel_o) ? TISB + : _(los_o) ? LISB : DISB; + ++tot_w; _n_emit(ops, u3nc(op, u3k(nef))); + } + break; } } else { @@ -1153,6 +1276,150 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) return tot_w; } +static c3_w +_n_bint_direct(u3_noun* ops, + u3_noun hif, + u3_noun nef, + c3_o los_o, + c3_o tel_o, + u3_noun* queu, + u3_noun cole, + u3_noun code) +{ + c3_w tot_w = 0; + + if ( c3n == u3du(hif) ) { + switch ( hif ) { + // compile whitelisted atomic hints to dispatch protocol; + // %xray is ignored + // + case c3__cash: + case c3__meme: + case c3__nara: + case c3__hela: + case c3__bout: { + u3_noun fen = u3_nul; + c3_w nef_w = _n_comp_direct(&fen, nef, los_o, c3n, queu, cole, code); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HILL : HILK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + + // call hilt_fore + // HILB overflows to HILS + ++tot_w; _n_emit(ops, u3nc(HILB, u3nc(u3k(hif), u3k(nef)))); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); + tot_w += nef_w; _n_apen(ops, fen); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); + } break; + + // compute and drop all others; %ska case is ignored + // + default: { + return _n_comp_direct(ops, nef, los_o, tel_o, queu, cole, code); + } + } + } + else { + u3_noun zep, hod; + u3x_cell(hif, &zep, &hod); + + switch ( zep ) { + default: { + // compile whitelisted dynamic hints to dispatch protocol; + // compute and drop all others; + // + switch ( zep ) { + default: { + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, TOSS); + tot_w += _n_comp_direct(ops, nef, los_o, tel_o, queu, cole, code); + } break; + // %xray is ignored + // + case c3__meme: + case c3__nara: + case c3__hela: + case c3__spin: + case c3__bout: { + u3_noun fen = u3_nul; + c3_w nef_w = _n_comp_direct(&fen, nef, los_o, c3n, + queu, cole, code); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HINL : HINK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + + // push clue + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + // call hint_fore + // HINB overflows to HINS + ++tot_w; _n_emit(ops, u3nc(HINB, u3nc(u3k(zep), u3k(nef)))); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); + tot_w += nef_w; _n_apen(ops, fen); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); + } break; + } + } break; + + case c3__hunk: + case c3__lose: + case c3__mean: + case c3__spot: + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, u3nc(BUSH, zep)); // overflows to SUSH + tot_w += _n_comp_direct(ops, nef, los_o, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, DROP); + break; + + case c3__live: + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, HECK); + tot_w += _n_comp_direct(ops, nef, los_o, tel_o, queu, cole, code); + break; + + case c3__slog: + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SLOG); + tot_w += _n_comp_direct(ops, nef, los_o, tel_o, queu, cole, code); + break; + + // germ and sole are unused... + // fast was treated during analysis + + case c3__memo: { + u3_noun mem = u3_nul; + c3_w mem_w = 0; + c3_y op_y; + + tot_w += _n_comp_direct(ops, hod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, TOSS); + + mem_w += _n_comp_direct(&mem, nef, c3y, c3n, queu, cole, code); + ++mem_w; _n_emit(&mem, SAVE); + + op_y = (c3y == los_o) ? SLIB : SKIB; // overflows to SLIS / SKIS + u3z_cid cid = u3z_memo_toss; + { + u3_weak con = u3r_skip(hod); + if ( (u3_none != con) && (c3y == u3du(con)) ) { + cid = u3z_memo_keep; + } + } + ++tot_w; _n_emit(ops, u3nq(op_y, cid, mem_w, u3k(nef))); + tot_w += mem_w; _n_apen(ops, mem); + break; + } + } + } + + return tot_w; +} + static c3_t _n_formulaic(u3_noun fol) { @@ -1595,7 +1862,7 @@ _n_resh(c3_y* buf, c3_w* ip_w) static inline c3_w _n_rewo(c3_y* buf, c3_w* ip_w) { - c3_y one = buf[(*ip_w)++], + c3_w one = buf[(*ip_w)++], two = buf[(*ip_w)++], tre = buf[(*ip_w)++], qua = buf[(*ip_w)++]; @@ -1690,6 +1957,387 @@ _cn_to_prog(c3_w pog_w) return u3to(u3n_prog, pog_p); } +// RETAINS +// +static c3_w +_n_comp_direct(u3_noun* ops, + u3_noun nomm, + c3_o los_o, + c3_o tel_o, + u3_noun* queu, + u3_noun cole, + u3_noun code) +{ + c3_y op_y; + c3_w tot_w = 0; + u3_noun cod, arg, hed, tel, info, boot; + u3x_cell(nomm, &cod, &arg); + if ( c3y == u3du(cod) ) { + tot_w += _n_comp_direct(ops, cod, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp_direct(ops, arg, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, (c3y == los_o) ? AULT : AUTO); + } + else switch ( cod ) { + case 0: + if ( c3n == u3ud(arg) ) { + u3m_bail(c3__fail); + return 0; + } + switch ( arg ) { + case 0: + ++tot_w; _n_emit(ops, BAIL); + break; + case 1: + if ( c3n == los_o ) { + ++tot_w; _n_emit(ops, COPY); + } + break; + case 2: + ++tot_w; _n_emit(ops, (c3y == los_o) ? HELD : HEAD); + break; + case 3: + ++tot_w; _n_emit(ops, (c3y == los_o) ? TALL : TAIL); + break; + default: + op_y = (c3y == los_o) + ? (arg <= 0xFF ? FABL : arg <= 0xFFFF ? FASL : FIBL) // overflows to FISL + : (arg <= 0xFF ? FABK : arg <= 0xFFFF ? FASK : FIBK); // overflows to FISK + ++tot_w; _n_emit(ops, u3nc(op_y, u3k(arg))); + break; + } + break; + + case 1: + switch ( arg ) { + case 0: + ++tot_w; _n_emit(ops, (c3y == los_o) ? LIL0 : LIT0); + break; + case 1: + ++tot_w; _n_emit(ops, (c3y == los_o) ? LIL1 : LIT1); + break; + default: + op_y = (c3y == los_o) + ? (arg <= 0xFF ? LILB : arg <= 0xFFFF ? LILS : LIBL) // overflows to LISL + : (arg <= 0xFF ? LITB : arg <= 0xFFFF ? LITS : LIBK); // overflows to LISK + ++tot_w; _n_emit(ops, u3nc(op_y, u3k(arg))); + break; + } + break; + + case 2: + u3x_trel(arg, &hed, &tel, &info); + if ( u3_nul == info ) { + // indirect call: fall back to regular interpreter + // XX TODO reanalysis + // + tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); + op_y = (c3y == tel_o) ? NOCT + : (c3y == los_o) ? NOLK : NOCK; + ++tot_w; _n_emit(ops, op_y); + } + else { + // don't compile the formula for the formula, we already know the + // result and it won't ever crash + // + tot_w += _n_comp_direct(ops, hed, los_o, c3n, queu, cole, code); + boot = u3t(info); + op_y = (c3y == tel_o) ? TIRB : DIRB; // overflows to TIRS/DIRS + ++tot_w; _n_emit(ops, u3nt(op_y, u3k(boot), u3qdb_get(cole, boot))); + *queu = u3nc(u3k(boot), *queu); + } + break; + + case 3: + tot_w += _n_comp_direct(ops, arg, los_o, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, DEEP); + break; + + case 4: + tot_w += _n_comp_direct(ops, arg, los_o, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, BUMP); + break; + + case 5: { + u3x_cell(arg, &hed, &tel); + + if ( c3n == u3du(hed) ) { + u3m_bail(c3__fail); + return 0; + } + else { + c3_t hec_t, tec_t; + hec_t = (1 == u3h(hed)); + if ( c3n == u3du(tel) ) { + u3m_bail(c3__fail); + break; + } + else { + tec_t = (1 == u3h(tel)); + } + if ( hec_t && tec_t ) { + if ( c3y == u3r_sing(u3t(hed), u3t(tel)) ) { + ++tot_w; _n_emit(ops, (c3y == los_o) ? LIL0 : LIT0); + } + else { + ++tot_w; _n_emit(ops, (c3y == los_o) ? LIL1 : LIT1); + } + } + else if ( !hec_t && !tec_t ) { + tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, (c3y == los_o) ? SALM : SAME); + } + else { + tot_w += _n_comp_direct(ops, + (hec_t ? tel : hed), los_o, c3n, queu, cole, code); + + u3_noun lit = u3t(hec_t ? hed : tel); + switch ( lit ) { + case 0: + ++tot_w; _n_emit(ops, SAM0); + break; + case 1: + ++tot_w; _n_emit(ops, SAM1); + break; + default: + // overflows to SANS + op_y = lit <= 0xFF ? SAMB : lit <= 0xFFFF ? SAMS : SANB; + ++tot_w; _n_emit(ops, u3nc(op_y, u3k(lit))); + } + } + } + break; + } + + case 6: { + u3_noun mid, lit; + u3x_trel(arg, &hed, &mid, &tel); + // u3r_safe works for nomm + // + if ( c3y == u3r_safe(hed, &lit) && u3_none != lit ) { + switch ( lit ) { + case 0: + tot_w += _n_comp_direct(ops, mid, los_o, tel_o, queu, cole, code); + break; + + case 1: + tot_w += _n_comp_direct(ops, tel, los_o, tel_o, queu, cole, code); + break; + + default: + ++tot_w; _n_emit(ops, BAIL); + break; + } + } + else { + u3_noun yep = u3_nul, + nop = u3_nul; + c3_w yep_w, nop_w; + // nomm is always valid + // + tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); + yep_w = _n_comp_direct(&yep, mid, los_o, tel_o, queu, cole, code); + nop_w = _n_comp_direct(&nop, tel, los_o, tel_o, queu, cole, code); + + // SBIP and SBIN get sized during assembly + ++yep_w; _n_emit(&yep, u3nc(SBIP, nop_w)); + ++tot_w; _n_emit(ops, u3nc(SBIN, yep_w)); + tot_w += yep_w; _n_apen(ops, yep); + tot_w += nop_w; _n_apen(ops, nop); + } + break; + } + + case 7: + u3x_cell(arg, &hed, &tel); + tot_w += _n_comp_direct(ops, hed, los_o, c3n, queu, cole, code); + tot_w += _n_comp_direct(ops, tel, c3y, tel_o, queu, cole, code); + break; + + case 10: { + u3_noun axe, nef; + u3x_cell(arg, &hed, &tel); + u3x_cell(hed, &axe, &nef); + tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp_direct(ops, nef, c3n, c3n, queu, cole, code); + + ++tot_w; + switch ( axe ) { + case 2: + _n_emit(ops, (c3y == los_o) ? MUTH : KUTH); + break; + + case 3: + _n_emit(ops, (c3y == los_o) ? MUTT : KUTT); + break; + + case u3x_sam: + _n_emit(ops, (c3y == los_o) ? MUSM : KUSM); + break; + + default: + op_y = (c3y == los_o) + ? (axe <= 0xFF) ? MUTB : (axe <= 0xFFFF) ? MUTS : MITB // overflows to MITS + : (axe <= 0xFF) ? KUTB : (axe <= 0xFFFF) ? KUTS : KITB; // overflows to KITS + _n_emit(ops, u3nc(op_y, u3k(axe))); + break; + } + break; + } + + case 11: + u3x_cell(arg, &hed, &tel); + tot_w += _n_bint_direct(ops, hed, tel, los_o, tel_o, queu, cole, code); + break; + + case 12: + // XX TODO scry, persistence of byc.dar_p/lar_p, check 12 treatment in +ka + // + u3m_bail(c3__fail); + break; + + default: + u3m_bail(c3__fail); + return 0; + } + return tot_w; +} + +// RETAINS +static u3n_prog* +_n_bite_direct(u3_noun nomm, + u3_noun* queu, + u3_noun cole, + u3_noun code) +{ + u3_noun ops = u3_nul; + _n_comp_direct(&ops, nomm, c3y, c3y, queu, cole, code); + return _n_prog_from_ops(ops); +} + +static u3_noun +_cb_jib_cons(u3_weak list, void* ptr_v) +{ + return u3nc(*(u3_noun*)ptr_v, ( u3_none == list ) ? u3_nul : list); +} + +// yes iff produced fresh code that requires a rewrite +// RETAINS +static c3_o +_n_find_direct(u3_noun less_fol, + u3_noun* queu, + u3_noun cole, + u3_noun code, + u3n_prog** pog_o_u) +{ + u3_weak pog = u3h_git(u3R->byc.dar_p, less_fol); + if ( u3_none != pog ) { + *pog_o_u = _cn_to_prog(pog); + return c3n; + } + + u3_noun u_nomm = u3qdb_get(code, less_fol); + u3_assert(u3_nul != u_nomm); + *pog_o_u = _n_bite_direct(u3t(u_nomm), queu, cole, code); + pog = _cn_of_prog(*pog_o_u); + u3_noun i_larp = u3nc(u3k(u3h(less_fol)), pog); + u3h_put(u3R->byc.dar_p, less_fol, pog); + u3h_jib(u3R->byc.lar_p, u3t(less_fol), _cb_jib_cons, &i_larp); + + u3z(u_nomm); + return c3y; +} + +static void +_cb_fresh_rewrite(u3_noun kev) +{ + u3_noun pog = u3t(kev); + u3p(u3h_root) dar_p = u3R->byc.dar_p; + u3n_prog* pog_u = _cn_to_prog(pog); + u3n_dire* dir_u = pog_u->dir_u.dat_u; + c3_w len_w = pog_u->dir_u.len_w; + u3_noun less_fol; + + for (c3_w i_w = 0; i_w < len_w; i_w++) { + less_fol = dir_u[i_w].pog_p; + pog = u3x_good(u3h_git(dar_p, less_fol)); + // uncompress loom offset + // + dir_u[i_w].pog_p = pog << u3a_vits; + u3z(less_fol); + } +} + +// [&+sub fol] pair must be findable in fols +// RETAINS +// +// cole: [sock formula] -> [path axis]; cold state +// code: [sock formula] -> nomm-1; code objects for direct calls +// fols: formula -> (list [sock nomm-1]): code objects for lookups +// +u3n_prog* +u3n_build_direct(u3_noun sub, + u3_noun fol, + u3_noun cole, + u3_noun code, + u3_noun fols) +{ + u3_noun lit = u3x_good(u3kdb_got(u3k(fols), u3k(fol))), + less_nomm = u3x_good(u3d_match_sock(c3y, sub, lit)); + u3z(lit); + // As we compile new code with direct calls, we might not have a post + // of a directly called program yet. We will instead put a pair + // [sock formula] in u3n_dire.pog_p, and rewrite it once we are done with + // compiling. u3R->byc.dar_p provides [sock formula] -> u3_post(u3n_prog) + // mapping. + // + // fresh_p is a map [sock formula] -> u3_post(u3n_prog) of programs that + // a) need to be rewritten, + // b) are already compiled, so they can be skipped. + // + u3p(u3h_root) fresh_p = u3h_new(); + // queu is a worklist [sock *] for our breadth-first compilation order + // + u3_noun queu = u3_nul; + u3_noun less, nomm, less_fol; + u3r_cell(less_nomm, &less, &nomm); + less_fol = u3nc(u3k(less), u3k(fol)); + // if we are here then this nomm was not compiled, no need to search + // + u3n_prog* out_u = _n_bite_direct(nomm, &queu, cole, code); + u3_noun pog = _cn_of_prog(out_u); + u3_noun i_larp = u3nc(u3k(less), pog); + u3h_put(u3R->byc.dar_p, less_fol, pog); + u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); + u3h_put(fresh_p, less_fol, pog); + u3z(less_fol); + + u3n_prog* pog_u; + u3_noun t; + while (u3_nul != queu) { + u3r_cell(queu, &less_fol, &t); + u3k(less_fol); + u3k(t), u3z(queu), queu = t; + + if ( u3_none == u3h_git(fresh_p, less_fol) + && c3y == _n_find_direct(less_fol, &queu, cole, code, &pog_u) ) { + u3h_put(fresh_p, less_fol, _cn_of_prog(pog_u)); + } + + u3z(less_fol); + } + + u3h_walk(fresh_p, _cb_fresh_rewrite); + u3h_free(fresh_p); + + return out_u; +} + /* _n_find(): return prog for given formula with prefix (u3_nul for none). * RETAIN. */ @@ -2150,6 +2798,7 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) u3j_site* sit_u; u3j_rite* rit_u; u3n_memo* mem_u; + u3n_dire* dir_u; c3_y *pog = pog_u->byc_u.ops_y; c3_w sip_w, ip_w = 0; u3_noun* top; @@ -2880,6 +3529,98 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) edit_in: *top = u3i_edit(*top, x, o); BURN(); + + do_tiss: + x = pog_u->lit_u.non[_n_resh(pog, &ip_w)]; + goto tis_in; + + do_tisb: + x = pog_u->lit_u.non[pog[ip_w++]]; + tis_in: + top = _n_peek(off); + o = *top; + goto dis_out; + + do_liss: + x = pog_u->lit_u.non[_n_resh(pog, &ip_w)]; + goto lis_in; + + do_lisb: + x = pog_u->lit_u.non[pog[ip_w++]]; + lis_in: + o = _n_pep(mov, off); + goto dis_frame; + + do_diss: + x = pog_u->lit_u.non[_n_resh(pog, &ip_w)]; + goto dis_in; + + do_disb: + x = pog_u->lit_u.non[pog[ip_w++]]; + dis_in: + top = _n_peek(off); + o = u3k(*top); + dis_frame: + fam = u3to(burnframe, u3R->cap_p) + off + mov; + u3R->cap_p = u3of(burnframe, fam - off); + fam->ip_w = ip_w; + fam->pog_u = pog_u; + _n_push(mov, off, o); + dis_out: + pog_u = u3d_search(o, x); + pog = pog_u->byc_u.ops_y; + ip_w = 0; + BURN(); + + do_dirs: + x = _n_resh(pog, &ip_w); + goto dir_in; + + do_dirb: + x = pog[ip_w++]; + dir_in: + top = _n_peek(off); + o = *top; + dir_u = &(pog_u->dir_u.dat_u[x]); + if ( !dir_u->ham_u + || u3_none == (*top = u3j_call_direct(o, dir_u->ham_u, dir_u->axe_l)) + ) + { + _n_pop(mov); + + fam = u3to(burnframe, u3R->cap_p) + off + mov; + u3R->cap_p = u3of(burnframe, fam - off); + fam->ip_w = ip_w; + fam->pog_u = pog_u; + _n_push(mov, off, o); + + pog_u = u3to(u3n_prog, dir_u->pog_p); + pog = pog_u->byc_u.ops_y; + ip_w = 0; + } + BURN(); + + do_tirs: + x = _n_resh(pog, &ip_w); + goto tir_in; + + do_tirb: + x = pog[ip_w++]; + tir_in: + top = _n_peek(off); + o = *top; + dir_u = &(pog_u->dir_u.dat_u[x]); + if ( !dir_u->ham_u + || u3_none == (*top = u3j_call_direct(o, dir_u->ham_u, dir_u->axe_l)) + ) + { + *top = o; + + pog_u = u3to(u3n_prog, dir_u->pog_p); + pog = pog_u->byc_u.ops_y; + ip_w = 0; + } + BURN(); } } @@ -2969,6 +3710,7 @@ _cn_take_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) u3j_rite_take(&(dst_u->reg_u.rit_u[i_w]), &(src_u->reg_u.rit_u[i_w])); } + // XX take dir_u } /* _cn_take_prog_cb(): u3h_take_with cb for taking junior u3n_prog's. @@ -2980,13 +3722,14 @@ _cn_take_prog_cb(c3_w pog_w) u3n_prog* gop_u; if ( c3y == pog_u->byc_u.own_o ) { - c3_w pad_w = (8 - pog_u->byc_u.len_w % 8) % 8; + c3_w byc_w = c3_align(pog_u->byc_u.len_w, 8, C3_ALGHI); gop_u = _n_prog_new(pog_u->byc_u.len_w, pog_u->cal_u.len_w, pog_u->reg_u.len_w, pog_u->lit_u.len_w, - pog_u->mem_u.len_w); - memcpy(gop_u->byc_u.ops_y, pog_u->byc_u.ops_y, pog_u->byc_u.len_w + pad_w); + pog_u->mem_u.len_w, + pog_u->dir_u.len_w); + memcpy(gop_u->byc_u.ops_y, pog_u->byc_u.ops_y, byc_w); } else { gop_u = _n_prog_old(pog_u); @@ -3065,6 +3808,7 @@ _cn_merge_prog_cb(u3_noun kev, void* wit) /* u3n_reap(): promote bytecode state. */ +// XX add dar_p, lar_p in args void u3n_reap(u3p(u3h_root) har_p) { @@ -3080,15 +3824,35 @@ _n_ream(u3_noun kev) { u3n_prog* pog_u = _cn_to_prog(u3t(kev)); - c3_w pad_w = (8 - pog_u->byc_u.len_w % 8) % 8; - c3_w pod_w = pog_u->lit_u.len_w % 2; - c3_w ped_w = pog_u->mem_u.len_w % 2; + c3_y* dat_y = _n_prog_dat(pog_u); + c3_w len_w = pog_u->byc_u.len_w; + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w let_w = len_w; + len_w += (sizeof(u3_noun) * pog_u->lit_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w mim_w = len_w; + len_w += (sizeof(u3n_memo) * pog_u->mem_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w cel_w = len_w; + len_w += (sizeof(u3j_site) * pog_u->cal_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w rig_w = len_w; + len_w += (sizeof(u3j_rite) * pog_u->reg_u.len_w); + + len_w = c3_align(len_w, 8, C3_ALGHI); + c3_w der_w = len_w; + // fix up pointers for loom portability - pog_u->byc_u.ops_y = (c3_y*) _n_prog_dat(pog_u); - pog_u->lit_u.non = (u3_noun*) (pog_u->byc_u.ops_y + pog_u->byc_u.len_w + pad_w); - pog_u->mem_u.sot_u = (u3n_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w + pod_w); - pog_u->cal_u.sit_u = (u3j_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w + ped_w); - pog_u->reg_u.rit_u = (u3j_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); + pog_u->byc_u.ops_y = dat_y; + pog_u->lit_u.non = (u3_noun*) (dat_y + let_w); + pog_u->mem_u.sot_u = (u3n_memo*) (dat_y + mim_w); + pog_u->cal_u.sit_u = (u3j_site*) (dat_y + cel_w); + pog_u->reg_u.rit_u = (u3j_rite*) (dat_y + rig_w); + pog_u->dir_u.dat_u = (u3n_dire*) (dat_y + der_w); for ( c3_w i_w = 0; i_w < pog_u->cal_u.len_w; ++i_w ) { u3j_site_ream(&(pog_u->cal_u.sit_u[i_w])); @@ -3102,6 +3866,7 @@ u3n_ream() { u3_assert(u3R == &(u3H->rod_u)); u3h_walk(u3R->byc.har_p, _n_ream); + u3h_walk(u3R->byc.dar_p, _n_ream); } /* _n_prog_mark(): mark program for gc. @@ -3146,7 +3911,8 @@ _n_bam(u3_noun kev, void* dat) u3m_quac* u3n_mark() { - u3m_quac** qua_u = c3_malloc(sizeof(*qua_u) * 3); + u3m_quac** qua_u = c3_malloc(sizeof(*qua_u) * 7); + c3_w siz_w = 0; qua_u[0] = c3_calloc(sizeof(*qua_u[0])); qua_u[0]->nam_c = strdup("bytecode programs"); @@ -3154,16 +3920,39 @@ u3n_mark() u3p(u3h_root) har_p = u3R->byc.har_p; u3h_walk_with(har_p, _n_bam, &qua_u[0]->siz_w); qua_u[0]->siz_w = qua_u[0]->siz_w * 4; + siz_w += qua_u[0]->siz_w; qua_u[1] = c3_calloc(sizeof(*qua_u[1])); qua_u[1]->nam_c = strdup("bytecode cache"); qua_u[1]->siz_w = u3h_mark(har_p) * 4; + siz_w += qua_u[1]->siz_w; + + qua_u[2] = c3_calloc(sizeof(*qua_u[2])); + qua_u[2]->nam_c = strdup("direct bytecode programs"); + u3h_walk_with(u3R->byc.dar_p, _n_bam, &qua_u[2]->siz_w); + qua_u[2]->siz_w = qua_u[2]->siz_w * 4; + siz_w += qua_u[2]->siz_w; - qua_u[2] = NULL; + qua_u[3] = c3_calloc(sizeof(*qua_u[3])); + qua_u[3]->nam_c = strdup("direct bytecode cache"); + qua_u[3]->siz_w = u3h_mark(u3R->byc.dar_p) * 4; + siz_w += qua_u[3]->siz_w; + + qua_u[4] = c3_calloc(sizeof(*qua_u[4])); + qua_u[4]->nam_c = strdup("direct bytecode jar"); + qua_u[4]->siz_w = u3h_mark(u3R->byc.lar_p) * 4; + siz_w += qua_u[4]->siz_w; + + qua_u[5] = c3_calloc(sizeof(*qua_u[5])); + qua_u[5]->nam_c = strdup("+ka SKA core"); + qua_u[5]->siz_w = u3a_mark_noun(u3R->dir.ka) * 4; + siz_w += qua_u[5]->siz_w; + + qua_u[6] = NULL; u3m_quac* tot_u = c3_malloc(sizeof(*tot_u)); tot_u->nam_c = strdup("total nock stuff"); - tot_u->siz_w = qua_u[0]->siz_w + qua_u[1]->siz_w; + tot_u->siz_w = siz_w; tot_u->qua_u = qua_u; return tot_u; @@ -3171,6 +3960,7 @@ u3n_mark() /* u3n_reclaim(): clear ad-hoc persistent caches to reclaim memory. */ +// XX don't clear dar_p/lar_p? void u3n_reclaim(void) { @@ -3181,6 +3971,8 @@ u3n_reclaim(void) // u3n_free(); u3R->byc.har_p = u3h_new(); + u3R->byc.dar_p = u3h_new(); + u3R->byc.lar_p = u3h_new(); } /* u3n_rewrite_compact(): rewrite the bytecode cache for compaction. @@ -3200,6 +3992,8 @@ void u3n_rewrite_compact() { u3h_relocate(&(u3R->byc.har_p)); + u3h_relocate(&(u3R->byc.dar_p)); + u3h_relocate(&(u3R->byc.lar_p)); } @@ -3211,16 +4005,27 @@ _n_feb(u3_noun kev) _cn_prog_free(_cn_to_prog(u3t(kev))); } -/* u3n_free(): free bytecode cache +/* u3n_free_table(): free bytecode table */ void -u3n_free() +u3n_free_table(u3p(u3h_root) har_p) { - u3p(u3h_root) har_p = u3R->byc.har_p; u3h_walk(har_p, _n_feb); u3h_free(har_p); } +/* u3n_free(): free bytecode cache + */ +void +u3n_free() +{ + u3n_free_table(u3R->byc.har_p); + u3n_free_table(u3R->byc.dar_p); + // programs in lar_p are owned by the already freed dar_p + // + u3h_free(u3R->byc.lar_p); +} + /* u3n_kick_on(): fire `gat` without changing the sample. */ u3_noun diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index 5c34515a02..85fc604097 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -10,6 +10,13 @@ #include "types.h" #include "zave.h" +#if 0 + |% + +$ cape $~(| $@(? (pair cape cape))) + +$ sock $~(|+~ (pair cape *)) + -- +#endif + /** Data structures. *** **/ @@ -22,6 +29,15 @@ u3z_cid cid; } u3n_memo; + /* u3n_dire: direct call information + */ + struct _u3n_prog; + typedef struct { + u3p(_u3n_prog) pog_p; // called program post or [less formula] during compilation + u3j_harm* ham_u; // jet arm, nullable + c3_l axe_l; // jet arm axis + } u3n_dire; + /* u3n_prog: program compiled from nock */ typedef struct _u3n_prog { @@ -46,6 +62,10 @@ c3_w len_w; // number of registration sites u3j_rite* rit_u; // array of sites } reg_u; // registration site data + struct { + c3_w len_w; // number of direct calls + u3n_dire* dat_u; // array of call info + } dir_u; // direct call data } u3n_prog; /** Functions. @@ -76,35 +96,15 @@ u3_noun u3n_kick_on(u3_noun gat); - /* u3n_nock_in(): produce .*(bus fol), as ++toon, in namespace. - */ - u3_noun - u3n_nock_in(u3_noun fly, u3_noun bus, u3_noun fol); - - /* u3n_nock_it(): produce .*(bus fol), as ++toon, in namespace. - */ - u3_noun - u3n_nock_it(u3_noun sea, u3_noun bus, u3_noun fol); - /* u3n_nock_et(): produce .*(bus fol), as ++toon, in namespace. */ u3_noun u3n_nock_et(u3_noun gul, u3_noun bus, u3_noun fol); - /* u3n_slam_in(): produce (gat sam), as ++toon, in namespace. - */ - u3_noun - u3n_slam_in(u3_noun fly, u3_noun gat, u3_noun sam); - - /* u3n_slam_it(): produce (gat sam), as ++toon, in namespace. - */ - u3_noun - u3n_slam_it(u3_noun sea, u3_noun gat, u3_noun sam); - /* u3n_slam_et(): produce (gat sam), as ++toon, in namespace. */ u3_noun - u3n_slam_it(u3_noun gul, u3_noun gat, u3_noun sam); + u3n_slam_et(u3_noun gul, u3_noun gat, u3_noun sam); /* u3n_nock_an(): as slam_in(), but with empty fly. */ @@ -141,9 +141,24 @@ void u3n_free(void); + /* u3n_free_table(): free bytecode table + */ + void + u3n_free_table(u3p(u3h_root) har_p); + /* u3n_ream(): refresh after restoring from checkpoint. */ void u3n_ream(void); + /* u3n_build_direct(): Compile [sub fol] pair with direct calls and + * its callees recursively + */ + u3n_prog* + u3n_build_direct(u3_noun sub, + u3_noun fol, + u3_noun cole, + u3_noun code, + u3_noun fols); + #endif /* ifndef U3_NOCK_H */ diff --git a/pkg/vere/melt.c b/pkg/vere/melt.c index 01b9208cec..2bce9b4e95 100644 --- a/pkg/vere/melt.c +++ b/pkg/vere/melt.c @@ -174,6 +174,7 @@ u3_melt_all(FILE *fil_u) u3m_reclaim(); _melt_canon_ptr(&can_u, &(u3A->roc)); + _melt_canon_ptr(&can_u, &(u3R->dir.ka)); u3h_walk_with(u3R->jed.cod_p, _melt_walk_hamt, &can_u); u3h_walk_with(u3R->cax.per_p, _melt_walk_hamt, &can_u); @@ -203,6 +204,9 @@ u3_meld_all(FILE *fil_u) u3h_free(u3R->cax.per_p); u3R->cax.per_p = u3h_new_cache(u3C.per_w); + + u3z(u3R->dir.ka); + u3R->dir.ka = u3_nul; (void)u3_melt_all(fil_u); (void)u3m_pack(); From 2e91f0e3b3ef135c517bfe29b9fb043ed81787ee Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 22 Oct 2025 12:18:12 +0200 Subject: [PATCH 04/27] update ska_core --- pkg/noun/ska_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/noun/ska_core.c b/pkg/noun/ska_core.c index 075434bb27..120495807c 100644 --- a/pkg/noun/ska_core.c +++ b/pkg/noun/ska_core.c @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28c29bba907b5e380808cd90cb122b4ca50b7fa73525740fab704c3acaa172d7 -size 937831 +oid sha256:ca84191da697c3e80197a50b7aad5043f124951e5688bfe57d01e581130dbd1d +size 870553 From 859d61183d22853c330d5d7b0fef00cbd43c1605 Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 22 Oct 2025 13:01:25 +0200 Subject: [PATCH 05/27] verbose ska core --- .gitattributes | 1 + pkg/noun/build.zig | 2 ++ pkg/noun/direct.c | 3 ++- pkg/noun/direct.h | 1 + pkg/noun/ska_core_verb.c | 3 +++ pkg/noun/ska_core_verb.h | 5 +++++ 6 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 pkg/noun/ska_core_verb.c create mode 100644 pkg/noun/ska_core_verb.h diff --git a/.gitattributes b/.gitattributes index 4fecd208b7..95b731f03c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ pkg/noun/ska_core.c filter=lfs diff=lfs merge=lfs -text +pkg/noun/ska_core_verb.c filter=lfs diff=lfs merge=lfs -text diff --git a/pkg/noun/build.zig b/pkg/noun/build.zig index 0aa5ca9e2a..4d890d21dc 100644 --- a/pkg/noun/build.zig +++ b/pkg/noun/build.zig @@ -405,6 +405,7 @@ const c_source_files = [_][]const u8{ "serial.c", "ship.c", "ska_core.c", + "ska_core_verb.c", "trace.c", "urth.c", "vortex.c", @@ -432,6 +433,7 @@ const install_headers = [_][]const u8{ "serial.h", "ship.h", "ska_core.h", + "ska_core_verb.h", "trace.h", "types.h", "urth.h", diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index 34e1329be9..f51862cd6b 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -84,7 +84,8 @@ u3d_prep_ka() } // [sock=hoon soak=hoon noir=hoon skan=hoon] // - u3_noun hoons = u3s_cue_bytes((c3_d)u3_Ka_core_len, u3_Ka_core); + // u3_noun hoons = u3s_cue_bytes((c3_d)u3_Ka_core_len, u3_Ka_core); + u3_noun hoons = u3s_cue_bytes((c3_d)u3_Ka_core_verb_len, u3_Ka_core_verb); u3_noun sock, soak, noir, skan; if ( c3n == u3r_mean(hoons, 2, &sock, diff --git a/pkg/noun/direct.h b/pkg/noun/direct.h index a5fc87abb6..468c458fd9 100644 --- a/pkg/noun/direct.h +++ b/pkg/noun/direct.h @@ -8,6 +8,7 @@ #include "retrieve.h" #include "serial.h" #include "ska_core.h" +#include "ska_core_verb.h" #include "vortex.h" #include "xtract.h" diff --git a/pkg/noun/ska_core_verb.c b/pkg/noun/ska_core_verb.c new file mode 100644 index 0000000000..b9d9896215 --- /dev/null +++ b/pkg/noun/ska_core_verb.c @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:555b3288bc0ec8444c6b80a3cee5f56962f819171f0a2ce3049df8563aba1c15 +size 870741 diff --git a/pkg/noun/ska_core_verb.h b/pkg/noun/ska_core_verb.h new file mode 100644 index 0000000000..3f247dd558 --- /dev/null +++ b/pkg/noun/ska_core_verb.h @@ -0,0 +1,5 @@ +#ifndef u3_ska_core_verb_H +#define u3_ska_core_verb_H +extern unsigned char u3_Ka_core_verb[]; +extern unsigned int u3_Ka_core_verb_len; +#endif From 5995d182f6814823d6d9e63fd31907d4b5e94d52 Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 22 Oct 2025 13:02:55 +0200 Subject: [PATCH 06/27] check is sub/fol is present in boil before analysis --- pkg/noun/direct.c | 80 +++++++++++++++++++++++++++++++++-------------- pkg/noun/direct.h | 4 +-- pkg/noun/nock.c | 2 +- 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index f51862cd6b..a5c597724d 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -112,10 +112,9 @@ u3d_prep_ka() // XX: reentrance? // -void -u3d_rout(u3_noun sub, u3_noun fol) +static void +_d_rout(u3_noun sub, u3_noun fol) { - u3d_prep_ka(); // ( [%wing p=~[%rout]] ) // u3_noun gen = u3nt(c3__wing, c3_s4('r','o','u','t'), u3_nul), @@ -167,26 +166,11 @@ u3d_match_sock(u3_noun cape, u3_noun data, u3_noun list) return pro; } -// RETAINS arguments -// XX remove u3dc, use hard-coded axes -// -u3n_prog* -u3d_search(u3_noun sub, u3_noun fol) +static u3_noun +_d_get_boil() { - u3n_prog* pog_u = NULL; - u3_weak lit = u3h_git(u3R->byc.lar_p, fol); - if ( u3_none != lit ) - { - u3_weak less_pog = u3d_match_sock(c3y, sub, lit); - pog_u = ( u3_none != less_pog ) - ? _cn_to_prog(u3t(less_pog)) - : NULL; - } - if ( pog_u ) return pog_u; - - u3d_rout(u3k(sub), u3k(fol)); - u3_noun slap = u3v_wish("slap"); u3_noun gul = u3nt(u3nc(1, 0), u3nc(0, 0), 0); // |~(^ ~) + u3_noun slap = u3v_wish("slap"); // ( [%wing p=~[%lon]] ) // @@ -208,9 +192,59 @@ u3d_search(u3_noun sub, u3_noun fol) { u3m_bail(c3__fail); } - u3_noun boil = u3t(pro); + u3_noun boil = u3k(u3t(pro)); + u3z(pro); + return boil; +} + +// RETAINS arguments +// XX remove u3dc, use hard-coded axes +// +u3n_prog* +u3d_search(u3_noun sub, u3_noun fol) +{ + u3d_prep_ka(); + + u3n_prog* pog_u = NULL; + u3_weak lit = u3h_git(u3R->byc.lar_p, fol); + if ( u3_none != lit ) + { + u3_weak less_pog = u3d_match_sock(c3y, sub, lit); + pog_u = ( u3_none != less_pog ) + ? _cn_to_prog(u3t(less_pog)) + : NULL; + } + if ( pog_u ) return pog_u; + + u3_noun boil = _d_get_boil(); u3_noun cole, code, fols; + if ( c3n == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ) + { + u3m_bail(c3__fail); + return 0; + } + lit = u3kdb_get(u3k(fols), u3k(fol)); + u3_weak less_nomm; + if (u3_none != lit + && u3_none != (less_nomm = u3d_match_sock(c3y, sub, lit))) + { + pog_u = u3n_build_direct(sub, fol, cole, code, fols); + u3z(lit); + u3z(boil); + return pog_u; + } + + // may be u3_none + // + u3z(lit); + + u3z(boil); + + _d_rout(u3k(sub), u3k(fol)); + + boil = _d_get_boil(); + if ( c3n == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ) { u3m_bail(c3__fail); @@ -218,6 +252,6 @@ u3d_search(u3_noun sub, u3_noun fol) } pog_u = u3n_build_direct(sub, fol, cole, code, fols); - u3z(pro); + u3z(boil); return pog_u; } \ No newline at end of file diff --git a/pkg/noun/direct.h b/pkg/noun/direct.h index 468c458fd9..4446e740d1 100644 --- a/pkg/noun/direct.h +++ b/pkg/noun/direct.h @@ -11,9 +11,7 @@ #include "ska_core_verb.h" #include "vortex.h" #include "xtract.h" - -void -u3d_rout(u3_noun sub, u3_noun fol); +#include "jets/k.h" u3n_prog* u3d_search(u3_noun sub, u3_noun fol); diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 753d103e40..2a279833de 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2287,7 +2287,7 @@ u3n_build_direct(u3_noun sub, u3_noun code, u3_noun fols) { - u3_noun lit = u3x_good(u3kdb_got(u3k(fols), u3k(fol))), + u3_noun lit = u3kdb_got(u3k(fols), u3k(fol)), less_nomm = u3x_good(u3d_match_sock(c3y, sub, lit)); u3z(lit); // As we compile new code with direct calls, we might not have a post From 9bedb87dfa7c6a4d5272f5d1dfd9fcb4b4cb2c57 Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 22 Oct 2025 13:25:47 +0200 Subject: [PATCH 07/27] make _n_comp_direct use same stack protocol as _n_comp (eager subject loss PR) --- pkg/noun/nock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 2a279833de..b973b72e95 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -1975,7 +1975,7 @@ _n_comp_direct(u3_noun* ops, if ( c3y == u3du(cod) ) { tot_w += _n_comp_direct(ops, cod, c3n, c3n, queu, cole, code); ++tot_w; _n_emit(ops, SWAP); - tot_w += _n_comp_direct(ops, arg, c3n, c3n, queu, cole, code); + tot_w += _n_comp_direct(ops, arg, los_o, c3n, queu, cole, code); ++tot_w; _n_emit(ops, (c3y == los_o) ? AULT : AUTO); } else switch ( cod ) { @@ -2033,7 +2033,7 @@ _n_comp_direct(u3_noun* ops, // tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); ++tot_w; _n_emit(ops, SWAP); - tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); + tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); op_y = (c3y == tel_o) ? NOCT : (c3y == los_o) ? NOLK : NOCK; ++tot_w; _n_emit(ops, op_y); @@ -2088,7 +2088,7 @@ _n_comp_direct(u3_noun* ops, else if ( !hec_t && !tec_t ) { tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); ++tot_w; _n_emit(ops, SWAP); - tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); + tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); ++tot_w; _n_emit(ops, (c3y == los_o) ? SALM : SAME); } else { @@ -2164,7 +2164,7 @@ _n_comp_direct(u3_noun* ops, u3x_cell(hed, &axe, &nef); tot_w += _n_comp_direct(ops, tel, c3n, c3n, queu, cole, code); ++tot_w; _n_emit(ops, SWAP); - tot_w += _n_comp_direct(ops, nef, c3n, c3n, queu, cole, code); + tot_w += _n_comp_direct(ops, nef, los_o, c3n, queu, cole, code); ++tot_w; switch ( axe ) { From 4b7cabd1e0d7dd2ac74f6fbe27e476ae55e88cd1 Mon Sep 17 00:00:00 2001 From: Quodss Date: Tue, 4 Nov 2025 21:41:27 +0100 Subject: [PATCH 08/27] ska: direct programs road promotion WIP --- pkg/noun/direct.c | 2 +- pkg/noun/manage.c | 7 ++--- pkg/noun/nock.c | 73 +++++++++++++++++++++++++++++++++++++++++++---- pkg/noun/nock.h | 6 ++++ 4 files changed, 77 insertions(+), 11 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index a5c597724d..44c2671ca2 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -207,7 +207,7 @@ u3d_search(u3_noun sub, u3_noun fol) u3d_prep_ka(); u3n_prog* pog_u = NULL; - u3_weak lit = u3h_git(u3R->byc.lar_p, fol); + u3_weak lit = u3h_git(u3R->byc.lar_p, fol); // XX search on parent roads too if ( u3_none != lit ) { u3_weak less_pog = u3d_match_sock(c3y, sub, lit); diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index eb6a8f8768..b77358d070 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1236,10 +1236,7 @@ u3m_love(u3_noun pro) // save cache pointers from current road // u3p(u3h_root) byc_har_p = u3R->byc.har_p; - // XX integrate junior direct call tables - // - u3n_free_table(u3R->byc.dar_p); - u3h_free(u3R->byc.lar_p); + u3p(u3h_root) byc_dar_p = u3R->byc.dar_p; u3a_jets jed_u = u3R->jed; u3p(u3h_root) per_p = u3R->cax.per_p; u3_noun ka = u3R->dir.ka; @@ -1254,6 +1251,7 @@ u3m_love(u3_noun pro) ka = u3a_take(ka); jed_u = u3j_take(jed_u); byc_har_p = u3n_take(byc_har_p); + byc_dar_p = u3n_take(byc_dar_p); per_p = u3h_take(per_p); // pop the stack @@ -1266,6 +1264,7 @@ u3m_love(u3_noun pro) // u3j_reap(jed_u); u3n_reap(byc_har_p); + u3n_reap_direct(byc_dar_p); u3z_reap(u3z_memo_keep, per_p); u3z(u3R->dir.ka), u3R->dir.ka = ka; diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index b973b72e95..7b3244bd61 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2261,15 +2261,12 @@ _cb_fresh_rewrite(u3_noun kev) u3n_prog* pog_u = _cn_to_prog(pog); u3n_dire* dir_u = pog_u->dir_u.dat_u; c3_w len_w = pog_u->dir_u.len_w; - u3_noun less_fol; for (c3_w i_w = 0; i_w < len_w; i_w++) { - less_fol = dir_u[i_w].pog_p; - pog = u3x_good(u3h_git(dar_p, less_fol)); + pog = u3x_good(u3h_git(dar_p, dir_u[i_w].bell)); // uncompress loom offset // dir_u[i_w].pog_p = pog << u3a_vits; - u3z(less_fol); } } @@ -3700,7 +3697,10 @@ _cn_take_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) u3j_rite_take(&(dst_u->reg_u.rit_u[i_w]), &(src_u->reg_u.rit_u[i_w])); } - // XX take dir_u + + for ( i_w = 0; i_w < src_u->dir_u.len_w; ++i_w ) { + dst_u->dir_u.dat_u[i_w].bell = u3a_take(src_u->dir_u.dat_u[i_w].bell); + } } /* _cn_take_prog_cb(): u3h_take_with cb for taking junior u3n_prog's. @@ -3769,6 +3769,11 @@ _cn_merge_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) u3j_rite_merge(&(dst_u->reg_u.rit_u[i_w]), &(src_u->reg_u.rit_u[i_w])); } + + for ( i_w = 0; i_w < src_u->dir_u.len_w; ++i_w ) { + u3z(dst_u->dir_u.dat_u[i_w].bell); + dst_u->dir_u.dat_u[i_w].bell = src_u->dir_u.dat_u[i_w].bell; + } } /* _cn_merge_prog_cb(): u3h_walk_with cb for integrating taken u3n_prog's. @@ -3798,7 +3803,6 @@ _cn_merge_prog_cb(u3_noun kev, void* wit) /* u3n_reap(): promote bytecode state. */ -// XX add dar_p, lar_p in args void u3n_reap(u3p(u3h_root) har_p) { @@ -3807,6 +3811,59 @@ u3n_reap(u3p(u3h_root) har_p) u3h_free(har_p); } +static void +_cn_larp_put_cb(u3_noun kev) +{ + u3_noun sock, fol, key; + c3_w pog_w; + u3x_cell(kev, &key, &pog_w); + u3x_cell(key, &sock, &fol); + + u3_noun i_larp = u3nc(u3k(sock), pog_w); + u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); +} + +static void +_cn_rebuild_larp(void) +{ + u3h_free(u3R->byc.lar_p); + u3R->byc.lar_p = u3h_new(); + u3h_walk(u3R->byc.dar_p, _cn_larp_put_cb); +} + +static void +_cb_merge_rewrite(u3_noun kev) +{ + u3_noun key = u3h(kev); + c3_w pog_w = u3x_good(u3h_git(u3R->byc.dar_p, key)); + + u3p(u3h_root) dar_p = u3R->byc.dar_p; + u3n_prog* pog_u = _cn_to_prog(pog_w); + u3n_dire* dir_u = pog_u->dir_u.dat_u; + c3_w len_w = pog_u->dir_u.len_w; + + for (c3_w i_w = 0; i_w < len_w; i_w++) { + pog_w = u3x_good(u3h_git(dar_p, dir_u[i_w].bell)); + // uncompress loom offset + // + dir_u[i_w].pog_p = pog_w << u3a_vits; + } +} + +/* u3n_reap_direct(): promote state of bytecode with direct calls +*/ +void +u3n_reap_direct(u3p(u3h_root) dar_p) +{ + if ( !u3h_wyt(dar_p) ) return; + + u3h_walk_with(dar_p, _cn_merge_prog_cb, &u3R->byc.dar_p); + u3h_walk(dar_p, _cb_merge_rewrite); + _cn_rebuild_larp(); + + u3h_free(dar_p); +} + /* _n_ream(): ream program call sites */ void @@ -3882,6 +3939,10 @@ _n_prog_mark(u3n_prog* pog_u) tot_w += u3j_rite_mark(&(pog_u->reg_u.rit_u[i_w])); } + for ( i_w = 0; i_w < pog_u->dir_u.len_w; ++i_w ) { + tot_w += u3a_mark_noun(pog_u->dir_u.dat_u[i_w].bell); + } + return tot_w; } diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index 85fc604097..c38dbd3673 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -33,6 +33,7 @@ */ struct _u3n_prog; typedef struct { + u3_noun bell; // [sock formula] u3p(_u3n_prog) pog_p; // called program post or [less formula] during compilation u3j_harm* ham_u; // jet arm, nullable c3_l axe_l; // jet arm axis @@ -116,6 +117,11 @@ void u3n_reap(u3p(u3h_root) har_p); + /* u3n_reap_direct(): promote state of bytecode with direct calls + */ + void + u3n_reap_direct(u3p(u3h_root) dar_p); + /* u3n_take(): copy junior bytecode state. */ u3p(u3h_root) From 5a1e4775fa9b53af222ffb7d3a7f23199a2dd84f Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 12 Nov 2025 15:34:09 +0100 Subject: [PATCH 09/27] ska: check formula-formula for crashing --- pkg/noun/nock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 7b3244bd61..8843244817 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2039,10 +2039,17 @@ _n_comp_direct(u3_noun* ops, ++tot_w; _n_emit(ops, op_y); } else { - // don't compile the formula for the formula, we already know the - // result and it won't ever crash + tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); + // evaluate the formula for the formula and drop the result as we + // already know it // - tot_w += _n_comp_direct(ops, hed, los_o, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); + ++tot_w; _n_emit(ops, DROP); + if ( c3n == los_o ) { + // [old bus] -> [bus old] + ++tot_w; _n_emit(ops, SWAP); + } boot = u3t(info); op_y = (c3y == tel_o) ? TIRB : DIRB; // overflows to TIRS/DIRS ++tot_w; _n_emit(ops, u3nt(op_y, u3k(boot), u3qdb_get(cole, boot))); From add83be62c4303ed9cc999effc301974b24faa06 Mon Sep 17 00:00:00 2001 From: Quodss Date: Wed, 12 Nov 2025 16:03:51 +0100 Subject: [PATCH 10/27] ska: bugfixes --- pkg/noun/nock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 8843244817..43100967cd 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -1035,7 +1035,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) case DIRB: case TIRB: { _n_prog_asm_inx(buf_y, &i_w, dir_s, cod); u3n_dire* dir_u = &(pog_u->dir_u.dat_u[dir_s++]); - dir_u->pog_p = u3k(u3h(u3t(op))); // [sock fol] pair, to be rewritten + dir_u->bell = u3k(u3h(u3t(op))); _direct_match_bell(dir_u, u3t(u3t(op))); break; } @@ -2040,12 +2040,12 @@ _n_comp_direct(u3_noun* ops, } else { tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); - // evaluate the formula for the formula and drop the result as we + // evaluate the formula for the formula and toss the result as we // already know it // ++tot_w; _n_emit(ops, SWAP); tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); - ++tot_w; _n_emit(ops, DROP); + ++tot_w; _n_emit(ops, TOSS); if ( c3n == los_o ) { // [old bus] -> [bus old] ++tot_w; _n_emit(ops, SWAP); From 96c40a90fccf0bf364c129beeee85459fb88211e Mon Sep 17 00:00:00 2001 From: Quodss Date: Thu, 13 Nov 2025 15:44:55 +0100 Subject: [PATCH 11/27] ska: skip %2 formula-formula compilation/execution if it is safe to do so --- pkg/noun/nock.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 43100967cd..d4ec50a72b 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -1957,6 +1957,20 @@ _cn_to_prog(c3_w pog_w) return u3to(u3n_prog, pog_p); } +// check that nomm is safe to skip, assuming its product is known and is used +// as a Nock formula +// +static c3_t +_nomm_fol_fol_safe(u3_noun nomm) +{ + switch ( u3h(nomm) ) { + default: return false; + case 0: + case 1: + return true; + } +} + // RETAINS // static c3_w @@ -2039,16 +2053,22 @@ _n_comp_direct(u3_noun* ops, ++tot_w; _n_emit(ops, op_y); } else { - tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); - // evaluate the formula for the formula and toss the result as we - // already know it - // - ++tot_w; _n_emit(ops, SWAP); - tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); - ++tot_w; _n_emit(ops, TOSS); - if ( c3n == los_o ) { - // [old bus] -> [bus old] - ++tot_w; _n_emit(ops, SWAP); + if ( _nomm_fol_fol_safe(tel) ) { + // skip evaluating formula-formula as we know its result and it won't + // crash + tot_w += _n_comp_direct(ops, hed, los_o, c3n, queu, cole, code); + } + else { + // eval and toss the product of formula-formula to preserve crashes + // + tot_w += _n_comp_direct(ops, hed, c3n, c3n, queu, cole, code); // [bus old] + ++tot_w; _n_emit(ops, SWAP); // [old bus] + tot_w += _n_comp_direct(ops, tel, los_o, c3n, queu, cole, code); // [fol ...] + ++tot_w; _n_emit(ops, TOSS); + if ( c3n == los_o ) { + // [old bus] -> [bus old] + ++tot_w; _n_emit(ops, SWAP); + } } boot = u3t(info); op_y = (c3y == tel_o) ? TIRB : DIRB; // overflows to TIRS/DIRS From 32de749cf8aa9fa0c68b1c47ac281b1368eeb82a Mon Sep 17 00:00:00 2001 From: Quodss Date: Thu, 13 Nov 2025 16:41:38 +0100 Subject: [PATCH 12/27] ska: search parent roads for code (not tested) --- pkg/noun/direct.c | 12 ++------ pkg/noun/nock.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ pkg/noun/nock.h | 3 ++ 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index 44c2671ca2..4027332b7e 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -206,15 +206,7 @@ u3d_search(u3_noun sub, u3_noun fol) { u3d_prep_ka(); - u3n_prog* pog_u = NULL; - u3_weak lit = u3h_git(u3R->byc.lar_p, fol); // XX search on parent roads too - if ( u3_none != lit ) - { - u3_weak less_pog = u3d_match_sock(c3y, sub, lit); - pog_u = ( u3_none != less_pog ) - ? _cn_to_prog(u3t(less_pog)) - : NULL; - } + u3n_prog* pog_u = u3n_look_direct(sub, fol); if ( pog_u ) return pog_u; u3_noun boil = _d_get_boil(); @@ -224,7 +216,7 @@ u3d_search(u3_noun sub, u3_noun fol) u3m_bail(c3__fail); return 0; } - lit = u3kdb_get(u3k(fols), u3k(fol)); + u3_noun lit = u3kdb_get(u3k(fols), u3k(fol)); u3_weak less_nomm; if (u3_none != lit && u3_none != (less_nomm = u3d_match_sock(c3y, sub, lit))) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 27bb5aac38..9df786e667 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2255,6 +2255,56 @@ _cb_jib_cons(u3_weak list, void* ptr_v) return u3nc(*(u3_noun*)ptr_v, ( u3_none == list ) ? u3_nul : list); } +// RETAINS +// +u3n_prog* +u3n_look_direct(u3_noun sub, u3_noun fol) +{ + u3n_prog* pog_u = NULL; + u3_weak lit = u3h_git(u3R->byc.lar_p, fol); + if ( u3_none != lit ) { + u3_weak less_pog = u3d_match_sock(c3y, sub, lit); + pog_u = ( u3_none != less_pog ) + ? _cn_to_prog(u3t(less_pog)) + : NULL; + } + if ( pog_u ) return pog_u; + + if (u3R == &u3H->rod_u ) return NULL; + u3a_road* rod_u = u3R; + + while ( rod_u->par_p ) { + rod_u = u3to(u3a_road, rod_u->par_p); + lit = u3h_git(rod_u->byc.lar_p, fol); + if ( u3_none == lit ) continue; + u3_weak less_pog = u3d_match_sock(c3y, sub, lit); + if ( u3_none == less_pog ) continue; + c3_w i_w; + u3n_prog* old = _n_prog_old(_cn_to_prog(u3t(less_pog))); + for ( i_w = 0; i_w < old->reg_u.len_w; ++i_w ) { + u3j_rite* rit_u = &(old->reg_u.rit_u[i_w]); + rit_u->own_o = c3n; + } + for ( i_w = 0; i_w < old->cal_u.len_w; ++i_w ) { + u3j_site* sit_u = &(old->cal_u.sit_u[i_w]); + sit_u->bat = u3_none; + sit_u->pog_p = 0; + sit_u->fon_o = c3n; + } + + u3_noun pog = _cn_of_prog(old); + u3_noun less_fol = u3nc(u3k(u3h(less_pog)), u3k(fol)); + u3h_put(u3R->byc.dar_p, less_fol, pog); + u3z(less_fol); + + u3_noun i_larp = u3nc(u3k(u3h(less_pog)), pog); + u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); + return old; + } + + return NULL; +} + // yes iff produced fresh code that requires a rewrite // RETAINS static c3_o @@ -2270,6 +2320,33 @@ _n_find_direct(u3_noun less_fol, return c3n; } + if (u3R != &u3H->rod_u ) { + u3a_road* rod_u = u3R; + while ( rod_u->par_p ) { + rod_u = u3to(u3a_road, rod_u->par_p); + pog = u3h_git(rod_u->byc.dar_p, less_fol); + if ( u3_none == pog ) continue; + c3_w i_w; + u3n_prog* old = _n_prog_old(_cn_to_prog(pog)); + for ( i_w = 0; i_w < old->reg_u.len_w; ++i_w ) { + u3j_rite* rit_u = &(old->reg_u.rit_u[i_w]); + rit_u->own_o = c3n; + } + for ( i_w = 0; i_w < old->cal_u.len_w; ++i_w ) { + u3j_site* sit_u = &(old->cal_u.sit_u[i_w]); + sit_u->bat = u3_none; + sit_u->pog_p = 0; + sit_u->fon_o = c3n; + } + *pog_o_u = old; + pog = _cn_of_prog(*pog_o_u); + u3h_put(u3R->byc.dar_p, less_fol, pog); + u3_noun i_larp = u3nc(u3k(u3h(less_fol)), pog); + u3h_jib(u3R->byc.lar_p, u3t(less_fol), _cb_jib_cons, &i_larp); + return c3n; + } + } + u3_noun u_nomm = u3qdb_get(code, less_fol); u3_assert(u3_nul != u_nomm); *pog_o_u = _n_bite_direct(u3t(u_nomm), queu, cole, code); diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index c38dbd3673..46d006d172 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -167,4 +167,7 @@ u3_noun code, u3_noun fols); + u3n_prog* + u3n_look_direct(u3_noun sub, u3_noun fol); + #endif /* ifndef U3_NOCK_H */ From bb01d2fd3159ab3a7d1efb9e005de1cbf3c481d2 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sat, 15 Nov 2025 17:56:42 +0100 Subject: [PATCH 13/27] ska: bail harder --- pkg/noun/direct.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index 4027332b7e..fa916ac8a1 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -23,7 +23,8 @@ _ca_rip(u3_noun cape, u3_noun* l, u3_noun* r) { if ( c3y == u3ud(cape) ) { - *l = *r = u3x_loob(cape); // debug assert + u3_assert(cape <= 1); + *l = *r = cape; } else { @@ -58,7 +59,7 @@ _so_huge(u3_noun cape_one, if ( c3y == u3ud(data_two) ) { u3x_loob(cape_two); - if ( c3n == cape_one ) return u3m_bail(c3__exit); // normalization assert + if ( c3n == cape_one ) return u3m_bail(c3__fail); // normalization assert return c3n; } From 340a59f9591bbb61706dcc90e25cf5bb6c1b70ac Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 12:08:15 +0100 Subject: [PATCH 14/27] jets: preserve old map if put:by nooped --- pkg/noun/jets/d/by_put.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/noun/jets/d/by_put.c b/pkg/noun/jets/d/by_put.c index ad0e7ecad2..f1380db0f0 100644 --- a/pkg/noun/jets/d/by_put.c +++ b/pkg/noun/jets/d/by_put.c @@ -38,6 +38,11 @@ u3qdb_put(u3_noun a, if ( c3y == u3qc_gor(b, pn_a) ) { d = u3qdb_put(l_a, b, c); + if ( d == l_a ) { + u3z(d); + return u3k(a); + } + if ( c3y == u3qc_mor(pn_a, u3h(u3h(d))) ) { return u3nt(u3k(n_a), d, @@ -59,6 +64,11 @@ u3qdb_put(u3_noun a, else { d = u3qdb_put(r_a, b, c); + if ( d == r_a ) { + u3z(d); + return u3k(a); + } + if ( c3y == u3qc_mor(pn_a, u3h(u3h(d))) ) { return u3nt(u3k(n_a), u3k(l_a), From dafec28a4e546ebcab48fab3c810119ca77e23c9 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:03:47 +0100 Subject: [PATCH 15/27] ska: refactor direct.c, assert harder --- pkg/noun/direct.c | 53 +++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index fa916ac8a1..0bf2994930 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -16,6 +16,13 @@ _cn_to_prog(c3_w pog_w) return u3to(u3n_prog, pog_p); } +static inline c3_o +_assert_loob(u3_noun som) +{ + u3_assert(som <= 1); + return som; +} + // RETAINS // static void @@ -23,8 +30,7 @@ _ca_rip(u3_noun cape, u3_noun* l, u3_noun* r) { if ( c3y == u3ud(cape) ) { - u3_assert(cape <= 1); - *l = *r = cape; + *l = *r = _assert_loob(cape); } else { @@ -50,16 +56,17 @@ _so_huge(u3_noun cape_one, if ( c3y == u3ud(data_one) ) { - if ( c3n == u3x_loob(cape_one) ) return c3y; + if ( c3n == _assert_loob(cape_one) ) return c3y; return c3a(u3ud(cape_two), - c3a(u3x_loob(cape_two), + c3a(_assert_loob(cape_two), u3r_sing(data_one, data_two))); } + + u3_assert(c3n != cape_one); if ( c3y == u3ud(data_two) ) { - u3x_loob(cape_two); - if ( c3n == cape_one ) return u3m_bail(c3__fail); // normalization assert + _assert_loob(cape_two); return c3n; } @@ -210,40 +217,22 @@ u3d_search(u3_noun sub, u3_noun fol) u3n_prog* pog_u = u3n_look_direct(sub, fol); if ( pog_u ) return pog_u; - u3_noun boil = _d_get_boil(); u3_noun cole, code, fols; - if ( c3n == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ) - { - u3m_bail(c3__fail); - return 0; - } + u3_noun boil = _d_get_boil(); + u3_assert( c3y == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ); + u3_noun lit = u3kdb_get(u3k(fols), u3k(fol)); - u3_weak less_nomm; - if (u3_none != lit - && u3_none != (less_nomm = u3d_match_sock(c3y, sub, lit))) + if (u3_none == lit || u3_none == u3d_match_sock(c3y, sub, lit)) { - pog_u = u3n_build_direct(sub, fol, cole, code, fols); - u3z(lit); u3z(boil); - return pog_u; - } + _d_rout(u3k(sub), u3k(fol)); + boil = _d_get_boil(); + u3_assert( c3y == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ); + } // may be u3_none // u3z(lit); - - u3z(boil); - - _d_rout(u3k(sub), u3k(fol)); - - boil = _d_get_boil(); - - if ( c3n == u3r_mean(boil, 2, &cole, 6, &code, 7, &fols, 0) ) - { - u3m_bail(c3__fail); - return 0; - } - pog_u = u3n_build_direct(sub, fol, cole, code, fols); u3z(boil); return pog_u; From bf7516a6f1ff53fbb2ff506d677efb2f69470293 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:04:59 +0100 Subject: [PATCH 16/27] jets: cleanup, assertion --- pkg/noun/jets.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index c22f20516f..7a465b5107 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -264,6 +264,7 @@ _cj_axis(u3_noun fol) static c3_l _cj_read_axe(c3_c* str_c, c3_c* who_c) { + u3_assert(0 != str_c[0]); // ".2" common case shortcut // if ( '2' == str_c[1] && 0 == str_c[2] ) return 2; @@ -960,7 +961,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) } } -/* u3j_call_direct(): try to kick by jet, no validation. No ice test. +/* u3j_call_direct(): try to kick by jet, no validation. ** Return u3_none if no kick. ** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. */ From 13aa1c63a994eee492ef3fbd775f071323462791 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:12:13 +0100 Subject: [PATCH 17/27] ska: don't forget to free bells --- pkg/noun/nock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 9df786e667..dfc786b03c 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2517,6 +2517,9 @@ _cn_prog_free(u3n_prog* pog_u) for (dex_w = 0; dex_w < pog_u->reg_u.len_w; ++dex_w) { u3j_rite_lose(&(pog_u->reg_u.rit_u[dex_w])); } + for (dex_w = 0; dex_w < pog_u->dir_u.len_w; ++dex_w) { + u3z(pog_u->dir_u.dat_u[dex_w].bell); + } u3a_free(pog_u); } From a0da1e9df72e5c2d4f0ad58d2f6c74fcd9cf6b00 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:18:24 +0100 Subject: [PATCH 18/27] ska: assert & use read-only nature of SKA programs --- pkg/noun/nock.c | 172 ++++++++++++++++++++++-------------------------- pkg/noun/nock.h | 9 ++- 2 files changed, 86 insertions(+), 95 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index dfc786b03c..1b0491f2ce 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -2246,7 +2246,13 @@ _n_bite_direct(u3_noun nomm, { u3_noun ops = u3_nul; _n_comp_direct(&ops, nomm, c3y, c3y, queu, cole, code); - return _n_prog_from_ops(ops); + u3n_prog* pog_u = _n_prog_from_ops(ops); + + // read-only assertion for programs with direct calls + // + u3_assert(0 == pog_u->cal_u.len_w && 0 == pog_u->reg_u.len_w); + + return pog_u; } static u3_noun @@ -2256,50 +2262,21 @@ _cb_jib_cons(u3_weak list, void* ptr_v) } // RETAINS +// NB: this can produce a pointer into senior memory. +// This is fine though, as direct programs are read-only // u3n_prog* u3n_look_direct(u3_noun sub, u3_noun fol) { - u3n_prog* pog_u = NULL; - u3_weak lit = u3h_git(u3R->byc.lar_p, fol); - if ( u3_none != lit ) { - u3_weak less_pog = u3d_match_sock(c3y, sub, lit); - pog_u = ( u3_none != less_pog ) - ? _cn_to_prog(u3t(less_pog)) - : NULL; - } - if ( pog_u ) return pog_u; - - if (u3R == &u3H->rod_u ) return NULL; + u3_weak lit, less_pog; u3a_road* rod_u = u3R; - - while ( rod_u->par_p ) { - rod_u = u3to(u3a_road, rod_u->par_p); - lit = u3h_git(rod_u->byc.lar_p, fol); - if ( u3_none == lit ) continue; - u3_weak less_pog = u3d_match_sock(c3y, sub, lit); - if ( u3_none == less_pog ) continue; - c3_w i_w; - u3n_prog* old = _n_prog_old(_cn_to_prog(u3t(less_pog))); - for ( i_w = 0; i_w < old->reg_u.len_w; ++i_w ) { - u3j_rite* rit_u = &(old->reg_u.rit_u[i_w]); - rit_u->own_o = c3n; - } - for ( i_w = 0; i_w < old->cal_u.len_w; ++i_w ) { - u3j_site* sit_u = &(old->cal_u.sit_u[i_w]); - sit_u->bat = u3_none; - sit_u->pog_p = 0; - sit_u->fon_o = c3n; + while ( 1 ) { + if ( u3_none != (lit = u3h_git(rod_u->byc.lar_p, fol)) + && u3_none != (less_pog = u3d_match_sock(c3y, sub, lit))) { + return _cn_to_prog(u3t(less_pog)); } - - u3_noun pog = _cn_of_prog(old); - u3_noun less_fol = u3nc(u3k(u3h(less_pog)), u3k(fol)); - u3h_put(u3R->byc.dar_p, less_fol, pog); - u3z(less_fol); - - u3_noun i_larp = u3nc(u3k(u3h(less_pog)), pog); - u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); - return old; + if ( !rod_u->par_p ) break; + rod_u = u3to(u3a_road, rod_u->par_p); } return NULL; @@ -2307,6 +2284,9 @@ u3n_look_direct(u3_noun sub, u3_noun fol) // yes iff produced fresh code that requires a rewrite // RETAINS +// NB: this can produce a pointer into senior memory. +// This is fine though, as direct programs are read-only +// static c3_o _n_find_direct(u3_noun less_fol, u3_noun* queu, @@ -2314,37 +2294,15 @@ _n_find_direct(u3_noun less_fol, u3_noun code, u3n_prog** pog_o_u) { - u3_weak pog = u3h_git(u3R->byc.dar_p, less_fol); - if ( u3_none != pog ) { - *pog_o_u = _cn_to_prog(pog); - return c3n; - } - - if (u3R != &u3H->rod_u ) { - u3a_road* rod_u = u3R; - while ( rod_u->par_p ) { - rod_u = u3to(u3a_road, rod_u->par_p); - pog = u3h_git(rod_u->byc.dar_p, less_fol); - if ( u3_none == pog ) continue; - c3_w i_w; - u3n_prog* old = _n_prog_old(_cn_to_prog(pog)); - for ( i_w = 0; i_w < old->reg_u.len_w; ++i_w ) { - u3j_rite* rit_u = &(old->reg_u.rit_u[i_w]); - rit_u->own_o = c3n; - } - for ( i_w = 0; i_w < old->cal_u.len_w; ++i_w ) { - u3j_site* sit_u = &(old->cal_u.sit_u[i_w]); - sit_u->bat = u3_none; - sit_u->pog_p = 0; - sit_u->fon_o = c3n; - } - *pog_o_u = old; - pog = _cn_of_prog(*pog_o_u); - u3h_put(u3R->byc.dar_p, less_fol, pog); - u3_noun i_larp = u3nc(u3k(u3h(less_fol)), pog); - u3h_jib(u3R->byc.lar_p, u3t(less_fol), _cb_jib_cons, &i_larp); + u3a_road* rod_u = u3R; + u3_weak pog; + while ( 1 ) { + if ( u3_none != (pog = u3h_git(rod_u->byc.dar_p, less_fol)) ) { + *pog_o_u = _cn_to_prog(pog); return c3n; } + if ( !rod_u->par_p ) break; + rod_u = u3to(u3a_road, rod_u->par_p); } u3_noun u_nomm = u3qdb_get(code, less_fol); @@ -2359,23 +2317,41 @@ _n_find_direct(u3_noun less_fol, return c3y; } +/* set up program offsets for direct calls +*/ static void -_cb_fresh_rewrite(u3_noun kev) +_direct_rewrite(u3n_prog* pog_u) { - u3_noun pog = u3t(kev); - u3p(u3h_root) dar_p = u3R->byc.dar_p; - u3n_prog* pog_u = _cn_to_prog(pog); u3n_dire* dir_u = pog_u->dir_u.dat_u; c3_w len_w = pog_u->dir_u.len_w; + u3_noun less_fol; + u3_weak gop = u3_none; + u3a_road* rod_u; for (c3_w i_w = 0; i_w < len_w; i_w++) { - pog = u3x_good(u3h_git(dar_p, dir_u[i_w].bell)); - // uncompress loom offset - // - dir_u[i_w].pog_p = pog << u3a_vits; + less_fol = dir_u[i_w].bell; + rod_u = u3R; + while ( 1 ) { + if ( u3_none != (gop = u3h_git(rod_u->byc.dar_p, less_fol)) ) { + // uncompress loom offset + // + dir_u[i_w].pog_p = gop << u3a_vits; + break; + } + if ( !rod_u->par_p ) break; + rod_u = u3to(u3a_road, rod_u->par_p); + } + + u3_assert( u3_none != gop ); } } +static void +_cb_fresh_rewrite(u3_noun kev) +{ + _direct_rewrite(_cn_to_prog(u3t(kev))); +} + // [&+sub fol] pair must be findable in fols // RETAINS // @@ -3904,10 +3880,9 @@ _cn_merge_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) &(src_u->reg_u.rit_u[i_w])); } - for ( i_w = 0; i_w < src_u->dir_u.len_w; ++i_w ) { - u3z(dst_u->dir_u.dat_u[i_w].bell); - dst_u->dir_u.dat_u[i_w].bell = src_u->dir_u.dat_u[i_w].bell; - } + // this function is meant for regular programs only + // + u3_assert( 0 == src_u->dir_u.len_w ); } /* _cn_merge_prog_cb(): u3h_walk_with cb for integrating taken u3n_prog's. @@ -3935,6 +3910,25 @@ _cn_merge_prog_cb(u3_noun kev, void* wit) u3h_put(har_p, key, _cn_of_prog(pog_u)); } +static void +_cn_merge_prog_direct_cb(u3_noun kev, void* wit) +{ + u3p(u3h_root) dar_p = *(u3p(u3h_root)*)wit; + u3_weak got; + u3_noun key; + c3_w pog_w; + u3x_cell(kev, &key, &pog_w); + + got = u3h_git(dar_p, key); + + if ( u3_none != got ) { + u3n_prog* sep_u = _cn_to_prog(got); + _cn_prog_free(sep_u); + } + + u3h_put(dar_p, key, pog_w); +} + /* u3n_reap(): promote bytecode state. */ void @@ -3969,19 +3963,9 @@ static void _cb_merge_rewrite(u3_noun kev) { u3_noun key = u3h(kev); - c3_w pog_w = u3x_good(u3h_git(u3R->byc.dar_p, key)); - - u3p(u3h_root) dar_p = u3R->byc.dar_p; - u3n_prog* pog_u = _cn_to_prog(pog_w); - u3n_dire* dir_u = pog_u->dir_u.dat_u; - c3_w len_w = pog_u->dir_u.len_w; - - for (c3_w i_w = 0; i_w < len_w; i_w++) { - pog_w = u3x_good(u3h_git(dar_p, dir_u[i_w].bell)); - // uncompress loom offset - // - dir_u[i_w].pog_p = pog_w << u3a_vits; - } + u3_weak pog = u3h_git(u3R->byc.dar_p, key); + u3_assert(u3_none != pog); + _direct_rewrite(_cn_to_prog(pog)); } /* u3n_reap_direct(): promote state of bytecode with direct calls @@ -3991,7 +3975,7 @@ u3n_reap_direct(u3p(u3h_root) dar_p) { if ( !u3h_wyt(dar_p) ) return; - u3h_walk_with(dar_p, _cn_merge_prog_cb, &u3R->byc.dar_p); + u3h_walk_with(dar_p, _cn_merge_prog_direct_cb, &u3R->byc.dar_p); u3h_walk(dar_p, _cb_merge_rewrite); _cn_rebuild_larp(); diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index 46d006d172..057fbedf19 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -40,7 +40,14 @@ } u3n_dire; /* u3n_prog: program compiled from nock - */ + ** u3n_prog is read/write if it is a regular program + ** and it is READ-ONLY if it is a program with direct calls + ** the read/write portions are cal_u and reg_u, they MUST be + ** empty if dir_u is not empty + ** + ** Regular programs have to be copied onto the current road to + ** execute them, read-only programs don't need to be copied. + */ typedef struct _u3n_prog { struct { c3_o own_o; // program owns ops_y? From da8c87e5b38c012dbe74894a2eae3e39bab1a3a9 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:23:08 +0100 Subject: [PATCH 19/27] ska: cleanup --- pkg/noun/direct.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index 0bf2994930..a69f9a887c 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -2,20 +2,6 @@ #include "direct.h" -static inline c3_w -_cn_of_prog(u3n_prog *pog_u) -{ - u3_post pog_p = u3of(u3n_prog, pog_u); - return pog_p >> u3a_vits; -} - -static inline u3n_prog* -_cn_to_prog(c3_w pog_w) -{ - u3_post pog_p = pog_w << u3a_vits; - return u3to(u3n_prog, pog_p); -} - static inline c3_o _assert_loob(u3_noun som) { From e9cab1d29789f8b7896c552d1b9fbe41d96aeeb8 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:33:13 +0100 Subject: [PATCH 20/27] ska: EOF --- pkg/noun/direct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index a69f9a887c..591602bd93 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -222,4 +222,4 @@ u3d_search(u3_noun sub, u3_noun fol) pog_u = u3n_build_direct(sub, fol, cole, code, fols); u3z(boil); return pog_u; -} \ No newline at end of file +} From 83f3171b589497d4fe18ef64b10ebf4a511b07e7 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 16:34:50 +0100 Subject: [PATCH 21/27] jets: comment --- pkg/noun/jets.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/noun/jets.h b/pkg/noun/jets.h index 8b24b859a3..81c4395fff 100644 --- a/pkg/noun/jets.h +++ b/pkg/noun/jets.h @@ -169,7 +169,7 @@ u3j_hook(u3_noun cor, const c3_c* tam_c); - /* u3j_call_direct(): try to kick by jet, no validation. No ice test. + /* u3j_call_direct(): try to kick by jet, no validation. ** Return u3_none if no kick. ** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. */ From ebb29681fc835af482fb2681bd8f91d8958b6576 Mon Sep 17 00:00:00 2001 From: Quodss Date: Sun, 16 Nov 2025 17:00:00 +0100 Subject: [PATCH 22/27] ci: use LFS --- .github/workflows/shared.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/shared.yml b/.github/workflows/shared.yml index e13506e239..c72a89cf5d 100644 --- a/.github/workflows/shared.yml +++ b/.github/workflows/shared.yml @@ -45,6 +45,8 @@ jobs: # BUILD AND TEST # - uses: actions/checkout@v3 + with: + lfs: true - name: Set swap space run: | From 4810044be92df439ded2c03728342af845e21c8c Mon Sep 17 00:00:00 2001 From: Quodss Date: Mon, 17 Nov 2025 16:18:56 +0100 Subject: [PATCH 23/27] ska: ream pointers in u3n_dire, don't forget to take stuff --- pkg/noun/nock.c | 42 +++++++++++++++++++++++++++++++++++------- pkg/noun/nock.h | 1 + 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 1b0491f2ce..daf2285b66 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -870,20 +870,23 @@ _n_prog_asm_inx(c3_y* buf_y, c3_w* i_w, c3_s inx_s, c3_y cod) } // RETAINS -// `bell` is (unit (pair path axis)) +// `ring` is (unit (pair path axis)) // static void -_direct_match_bell(u3n_dire* dir_u, u3_noun bell) +_direct_match_ring(u3n_dire* dir_u, u3_noun ring) { u3_weak harm; - if ( u3_nul == bell - || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, u3t(bell))) + if ( u3_nul == ring + || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, u3t(ring))) ) { dir_u->ham_u = NULL; + dir_u->ring = u3_nul; } else { + dir_u->ring = u3k(u3t(ring)); dir_u->ham_u = (u3j_harm*)(c3_p)u3r_chub(0, u3x_atom(harm)); - dir_u->axe_l = u3t(u3t(bell)); + dir_u->axe_l = u3t(u3t(ring)); + u3_assert( c3y == u3a_is_cat(dir_u->axe_l) ); } } @@ -1036,7 +1039,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) _n_prog_asm_inx(buf_y, &i_w, dir_s, cod); u3n_dire* dir_u = &(pog_u->dir_u.dat_u[dir_s++]); dir_u->bell = u3k(u3h(u3t(op))); - _direct_match_bell(dir_u, u3t(u3t(op))); + _direct_match_ring(dir_u, u3t(u3t(op))); break; } } @@ -2495,6 +2498,7 @@ _cn_prog_free(u3n_prog* pog_u) } for (dex_w = 0; dex_w < pog_u->dir_u.len_w; ++dex_w) { u3z(pog_u->dir_u.dat_u[dex_w].bell); + u3z(pog_u->dir_u.dat_u[dex_w].ring); } u3a_free(pog_u); } @@ -3810,6 +3814,11 @@ _cn_take_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) for ( i_w = 0; i_w < src_u->dir_u.len_w; ++i_w ) { dst_u->dir_u.dat_u[i_w].bell = u3a_take(src_u->dir_u.dat_u[i_w].bell); + // skip pog_p as it is going to be rewritten anyway + // + dst_u->dir_u.dat_u[i_w].ring = u3a_take(src_u->dir_u.dat_u[i_w].ring); + dst_u->dir_u.dat_u[i_w].ham_u = src_u->dir_u.dat_u[i_w].ham_u; + dst_u->dir_u.dat_u[i_w].axe_l = src_u->dir_u.dat_u[i_w].axe_l; } } @@ -3982,9 +3991,24 @@ u3n_reap_direct(u3p(u3h_root) dar_p) u3h_free(dar_p); } +static void +_n_dire_ream(u3n_dire* dir_u) +{ + u3_weak harm; + if ( u3_nul == dir_u->ring + || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, dir_u->ring)) ) { + dir_u->ham_u = NULL; + } + else { + dir_u->ham_u = (u3j_harm*)(c3_p)u3r_chub(0, u3x_atom(harm)); + dir_u->axe_l = u3t(dir_u->ring); + u3_assert( c3y == u3a_is_cat(dir_u->axe_l) ); + } +} + /* _n_ream(): ream program call sites */ -void +static void _n_ream(u3_noun kev) { u3n_prog* pog_u = _cn_to_prog(u3t(kev)); @@ -4022,6 +4046,9 @@ _n_ream(u3_noun kev) for ( c3_w i_w = 0; i_w < pog_u->cal_u.len_w; ++i_w ) { u3j_site_ream(&(pog_u->cal_u.sit_u[i_w])); } + for ( c3_w i_w = 0; i_w < pog_u->dir_u.len_w; ++i_w ) { + _n_dire_ream(&(pog_u->dir_u.dat_u[i_w])); + } } /* u3n_ream(): refresh after restoring from checkpoint. @@ -4059,6 +4086,7 @@ _n_prog_mark(u3n_prog* pog_u) for ( i_w = 0; i_w < pog_u->dir_u.len_w; ++i_w ) { tot_w += u3a_mark_noun(pog_u->dir_u.dat_u[i_w].bell); + tot_w += u3a_mark_noun(pog_u->dir_u.dat_u[i_w].ring); } return tot_w; diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index 057fbedf19..565d0d23f1 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -35,6 +35,7 @@ typedef struct { u3_noun bell; // [sock formula] u3p(_u3n_prog) pog_p; // called program post or [less formula] during compilation + u3_noun ring; // ~ or [path axis] u3j_harm* ham_u; // jet arm, nullable c3_l axe_l; // jet arm axis } u3n_dire; From 724c2cf04864246ffaa4c8ca95eed6f2b8c44088 Mon Sep 17 00:00:00 2001 From: Quodss Date: Mon, 17 Nov 2025 18:54:05 +0100 Subject: [PATCH 24/27] ska: simple migration --- pkg/noun/allocate.c | 2 +- pkg/noun/allocate.h | 18 +++++++-------- pkg/noun/direct.c | 12 +++++----- pkg/noun/jets.c | 12 +++++----- pkg/noun/manage.c | 25 ++++++++++---------- pkg/noun/nock.c | 56 ++++++++++++++++++++++----------------------- pkg/noun/version.h | 7 +++--- pkg/vere/melt.c | 6 ++--- 8 files changed, 70 insertions(+), 68 deletions(-) diff --git a/pkg/noun/allocate.c b/pkg/noun/allocate.c index 282cf8b61c..d38e4b58e9 100644 --- a/pkg/noun/allocate.c +++ b/pkg/noun/allocate.c @@ -1791,7 +1791,7 @@ u3a_rewrite_compact(void) u3a_relocate_noun(&(u3R->pro.don)); u3a_relocate_noun(&(u3R->pro.day)); u3a_relocate_noun(&(u3R->pro.trace)); - u3a_relocate_noun(&(u3R->dir.ka)); + u3a_relocate_noun(&(u3R->dir_ka)); u3h_relocate(&(u3R->cax.har_p)); u3h_relocate(&(u3R->cax.per_p)); u3h_relocate(&(u3R->lop_p)); diff --git a/pkg/noun/allocate.h b/pkg/noun/allocate.h index 297859e183..ec34ed870e 100644 --- a/pkg/noun/allocate.h +++ b/pkg/noun/allocate.h @@ -128,7 +128,6 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, u3p(u3h_root) cod_p; // cold state u3p(u3h_root) han_p; // hank cache u3p(u3h_root) bas_p; // battery hashes - u3p(u3h_root) pax_p; // [path axis] -> arm jet (home road only) } u3a_jets; /* u3a_road: contiguous allocation and execution context. @@ -148,7 +147,15 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, c3_w fow_w; // spin stack overflow count u3p(u3h_root) lop_p; // %loop hint set - c3_w fut_w[29]; // futureproof buffer + /* ska-related things + ** XX move to appropriate places with an actual migration + */ + u3p(u3h_root) jed_pax_p; // [path axis] -> arm jet (home road only) + u3p(u3h_root) byc_dar_p; // [less fol]->post of bytecode + u3p(u3h_root) byc_lar_p; // fol->(list [less post]) of bytecode + u3_noun dir_ka; // ~ | +ka core vase XX raw noun + + c3_w fut_w[25]; // futureproof buffer struct { // escape buffer union { @@ -189,9 +196,6 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, struct { // bytecode state u3p(u3h_root) har_p; // formula->post of bytecode - /* Direct calls */ - u3p(u3h_root) dar_p; // [less fol]->post of bytecode - u3p(u3h_root) lar_p; // fol->(list [less post]) of bytecode } byc; struct { // scry namespace @@ -215,10 +219,6 @@ STATIC_ASSERT( u3a_vits <= u3a_min_log, u3p(u3h_root) har_p; // transient u3p(u3h_root) per_p; // persistent } cax; - - struct { // direct calls - u3_noun ka; // ~ | +ka core vase XX raw noun - } dir; } u3a_road; typedef u3a_road u3_road; diff --git a/pkg/noun/direct.c b/pkg/noun/direct.c index 591602bd93..1cb39e37c5 100644 --- a/pkg/noun/direct.c +++ b/pkg/noun/direct.c @@ -73,7 +73,7 @@ _so_huge(u3_noun cape_one, void u3d_prep_ka() { - if ( u3R->dir.ka ) { + if ( u3R->dir_ka ) { return; } // [sock=hoon soak=hoon noir=hoon skan=hoon] @@ -101,7 +101,7 @@ u3d_prep_ka() u3nc(bild, u3nt(c3__wing, c3_s2('k', 'a'), u3_nul))); u3z(hoons); - u3R->dir.ka = ka; + u3R->dir_ka = ka; } // XX: reentrance? @@ -112,7 +112,7 @@ _d_rout(u3_noun sub, u3_noun fol) // ( [%wing p=~[%rout]] ) // u3_noun gen = u3nt(c3__wing, c3_s4('r','o','u','t'), u3_nul), - rout = u3dc("slap", u3R->dir.ka, gen); + rout = u3dc("slap", u3R->dir_ka, gen); u3_noun typ = u3nt(c3__cell, c3__noun, c3__noun); u3_noun sam = u3nt(typ, sub, fol); // !>([sub=* fol=*]) @@ -127,7 +127,7 @@ _d_rout(u3_noun sub, u3_noun fol) { u3m_bail(c3__fail); } - u3R->dir.ka = u3k(u3t(pro)); + u3R->dir_ka = u3k(u3t(pro)); u3z(pro); } @@ -169,14 +169,14 @@ _d_get_boil() // ( [%wing p=~[%lon]] ) // u3_noun gen = u3nt(c3__wing, c3_s3('l','o','n'), u3_nul); - u3_noun vax = u3n_slam_on(u3k(slap), u3nc(u3k(u3R->dir.ka), gen)); + u3_noun vax = u3n_slam_on(u3k(slap), u3nc(u3k(u3R->dir_ka), gen)); u3_noun lon = u3k(u3t(vax)); u3z(vax); // ( [%wing p=~[%cook]] ) // gen = u3nt(c3__wing, c3__cook, u3_nul); - vax = u3n_slam_on(slap, u3nc(u3k(u3R->dir.ka), gen)); + vax = u3n_slam_on(slap, u3nc(u3k(u3R->dir_ka), gen)); u3_noun gat = u3k(u3t(vax)); u3z(vax); diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index 7a465b5107..747a684514 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -368,7 +368,7 @@ _cj_install(u3j_core* ray_u, c3_l axe_l = _cj_read_axe(jet_u->fcs_c, "_cj_install"); if ( !axe_l ) continue; u3_noun key = u3nc(u3k(xap), axe_l); - u3h_put(u3R->jed.pax_p, key, u3i_chub((c3_d)(c3_p)jet_u)); + u3h_put(u3R->jed_pax_p, key, u3i_chub((c3_d)(c3_p)jet_u)); u3z(key); } } @@ -849,10 +849,10 @@ u3j_boot(c3_o nuu_o) if ( c3n == nuu_o ) { u3h_free(u3R->jed.hot_p); - u3h_free(u3R->jed.pax_p); + u3h_free(u3R->jed_pax_p); } u3R->jed.hot_p = u3h_new(); - u3R->jed.pax_p = u3h_new(); + u3R->jed_pax_p = u3h_new(); return _cj_install(u3D.ray_u, 1, (c3_l) (long long) u3D.dev_u[0].par_u, @@ -2411,7 +2411,7 @@ u3j_mark() qua_u[6] = c3_calloc(sizeof(*qua_u[6])); qua_u[6]->nam_c = strdup("path/axis -> jet driver map"); - qua_u[6]->siz_w = u3h_mark(u3R->jed.pax_p) * 4; + qua_u[6]->siz_w = u3h_mark(u3R->jed_pax_p) * 4; sum_w += qua_u[6]->siz_w; @@ -2456,7 +2456,7 @@ u3j_free(void) u3h_free(u3R->jed.bas_p); if ( u3R == &(u3H->rod_u) ) { u3h_free(u3R->jed.hot_p); - u3h_free(u3R->jed.pax_p); + u3h_free(u3R->jed_pax_p); } } @@ -2497,6 +2497,6 @@ u3j_rewrite_compact(void) if ( u3R == &(u3H->rod_u) ) { u3h_relocate(&(u3R->jed.hot_p)); - u3h_relocate(&(u3R->jed.pax_p)); + u3h_relocate(&(u3R->jed_pax_p)); } } diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 211defa5ae..32184d9aae 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -532,8 +532,8 @@ _pave_parts(void) u3R->byc.har_p = u3h_new(); u3R->lop_p = u3h_new(); u3R->how.fag_w = 0; - u3R->byc.dar_p = u3h_new(); - u3R->byc.lar_p = u3h_new(); + u3R->byc_dar_p = u3h_new(); + u3R->byc_lar_p = u3h_new(); } static c3_d @@ -571,7 +571,7 @@ _pave_home(void) u3R->mat_p = u3R->cap_p = top_p; _pave_parts(); - u3R->dir.ka = u3_nul; + u3R->dir_ka = u3_nul; } STATIC_ASSERT( (c3_wiseof(u3v_home) <= (1U << u3a_page)), @@ -669,12 +669,13 @@ _find_home(void) u3H->pam_d = _pave_params(); } - // if lop_p is zero than it is an old pier pre %loop hint, initialize the - // HAMT + // Simple migration for zero-initialized u3a_road members + // from futureproof buffer // - if (!u3R->lop_p) { - u3R->lop_p = u3h_new(); - } + if ( !u3R->lop_p ) u3R->lop_p = u3h_new(); + if ( !u3R->jed_pax_p ) u3R->jed_pax_p = u3h_new(); + if ( !u3R->byc_dar_p ) u3R->byc_dar_p = u3h_new(); + if ( !u3R->byc_lar_p ) u3R->byc_lar_p = u3h_new(); } /* u3m_pave(): instantiate or activate image. @@ -1155,7 +1156,7 @@ u3m_leap(c3_w pad_w) { u3R = rod_u; _pave_parts(); - u3R->dir.ka = u3to(u3_road, u3R->par_p)->dir.ka; + u3R->dir_ka = u3to(u3_road, u3R->par_p)->dir_ka; } #ifdef U3_MEMORY_DEBUG rod_u->all.fre_w = 0; @@ -1242,10 +1243,10 @@ u3m_love(u3_noun pro) // save cache pointers from current road // u3p(u3h_root) byc_har_p = u3R->byc.har_p; - u3p(u3h_root) byc_dar_p = u3R->byc.dar_p; + u3p(u3h_root) byc_dar_p = u3R->byc_dar_p; u3a_jets jed_u = u3R->jed; u3p(u3h_root) per_p = u3R->cax.per_p; - u3_noun ka = u3R->dir.ka; + u3_noun ka = u3R->dir_ka; // fallback to parent road (child heap on parent's stack) // @@ -1272,7 +1273,7 @@ u3m_love(u3_noun pro) u3n_reap(byc_har_p); u3n_reap_direct(byc_dar_p); u3z_reap(u3z_memo_keep, per_p); - u3z(u3R->dir.ka), u3R->dir.ka = ka; + u3z(u3R->dir_ka), u3R->dir_ka = ka; return pro; } diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index daf2285b66..8b46445425 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -877,7 +877,7 @@ _direct_match_ring(u3n_dire* dir_u, u3_noun ring) { u3_weak harm; if ( u3_nul == ring - || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, u3t(ring))) + || u3_none == (harm = u3h_git(u3H->rod_u.jed_pax_p, u3t(ring))) ) { dir_u->ham_u = NULL; dir_u->ring = u3_nul; @@ -2228,7 +2228,7 @@ _n_comp_direct(u3_noun* ops, break; case 12: - // XX TODO scry, persistence of byc.dar_p/lar_p, check 12 treatment in +ka + // XX TODO scry, persistence of byc_dar_p/lar_p, check 12 treatment in +ka // u3m_bail(c3__fail); break; @@ -2274,7 +2274,7 @@ u3n_look_direct(u3_noun sub, u3_noun fol) u3_weak lit, less_pog; u3a_road* rod_u = u3R; while ( 1 ) { - if ( u3_none != (lit = u3h_git(rod_u->byc.lar_p, fol)) + if ( u3_none != (lit = u3h_git(rod_u->byc_lar_p, fol)) && u3_none != (less_pog = u3d_match_sock(c3y, sub, lit))) { return _cn_to_prog(u3t(less_pog)); } @@ -2300,7 +2300,7 @@ _n_find_direct(u3_noun less_fol, u3a_road* rod_u = u3R; u3_weak pog; while ( 1 ) { - if ( u3_none != (pog = u3h_git(rod_u->byc.dar_p, less_fol)) ) { + if ( u3_none != (pog = u3h_git(rod_u->byc_dar_p, less_fol)) ) { *pog_o_u = _cn_to_prog(pog); return c3n; } @@ -2313,8 +2313,8 @@ _n_find_direct(u3_noun less_fol, *pog_o_u = _n_bite_direct(u3t(u_nomm), queu, cole, code); pog = _cn_of_prog(*pog_o_u); u3_noun i_larp = u3nc(u3k(u3h(less_fol)), pog); - u3h_put(u3R->byc.dar_p, less_fol, pog); - u3h_jib(u3R->byc.lar_p, u3t(less_fol), _cb_jib_cons, &i_larp); + u3h_put(u3R->byc_dar_p, less_fol, pog); + u3h_jib(u3R->byc_lar_p, u3t(less_fol), _cb_jib_cons, &i_larp); u3z(u_nomm); return c3y; @@ -2335,7 +2335,7 @@ _direct_rewrite(u3n_prog* pog_u) less_fol = dir_u[i_w].bell; rod_u = u3R; while ( 1 ) { - if ( u3_none != (gop = u3h_git(rod_u->byc.dar_p, less_fol)) ) { + if ( u3_none != (gop = u3h_git(rod_u->byc_dar_p, less_fol)) ) { // uncompress loom offset // dir_u[i_w].pog_p = gop << u3a_vits; @@ -2375,7 +2375,7 @@ u3n_build_direct(u3_noun sub, // As we compile new code with direct calls, we might not have a post // of a directly called program yet. We will instead put a pair // [sock formula] in u3n_dire.pog_p, and rewrite it once we are done with - // compiling. u3R->byc.dar_p provides [sock formula] -> u3_post(u3n_prog) + // compiling. u3R->byc_dar_p provides [sock formula] -> u3_post(u3n_prog) // mapping. // // fresh_p is a map [sock formula] -> u3_post(u3n_prog) of programs that @@ -2394,8 +2394,8 @@ u3n_build_direct(u3_noun sub, u3n_prog* out_u = _n_bite_direct(nomm, &queu, cole, code); u3_noun pog = _cn_of_prog(out_u); u3_noun i_larp = u3nc(u3k(less), pog); - u3h_put(u3R->byc.dar_p, less_fol, pog); - u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); + u3h_put(u3R->byc_dar_p, less_fol, pog); + u3h_jib(u3R->byc_lar_p, fol, _cb_jib_cons, &i_larp); u3h_put(fresh_p, less_fol, pog); u3z(less_fol); @@ -3957,22 +3957,22 @@ _cn_larp_put_cb(u3_noun kev) u3x_cell(key, &sock, &fol); u3_noun i_larp = u3nc(u3k(sock), pog_w); - u3h_jib(u3R->byc.lar_p, fol, _cb_jib_cons, &i_larp); + u3h_jib(u3R->byc_lar_p, fol, _cb_jib_cons, &i_larp); } static void _cn_rebuild_larp(void) { - u3h_free(u3R->byc.lar_p); - u3R->byc.lar_p = u3h_new(); - u3h_walk(u3R->byc.dar_p, _cn_larp_put_cb); + u3h_free(u3R->byc_lar_p); + u3R->byc_lar_p = u3h_new(); + u3h_walk(u3R->byc_dar_p, _cn_larp_put_cb); } static void _cb_merge_rewrite(u3_noun kev) { u3_noun key = u3h(kev); - u3_weak pog = u3h_git(u3R->byc.dar_p, key); + u3_weak pog = u3h_git(u3R->byc_dar_p, key); u3_assert(u3_none != pog); _direct_rewrite(_cn_to_prog(pog)); } @@ -3984,7 +3984,7 @@ u3n_reap_direct(u3p(u3h_root) dar_p) { if ( !u3h_wyt(dar_p) ) return; - u3h_walk_with(dar_p, _cn_merge_prog_direct_cb, &u3R->byc.dar_p); + u3h_walk_with(dar_p, _cn_merge_prog_direct_cb, &u3R->byc_dar_p); u3h_walk(dar_p, _cb_merge_rewrite); _cn_rebuild_larp(); @@ -3996,7 +3996,7 @@ _n_dire_ream(u3n_dire* dir_u) { u3_weak harm; if ( u3_nul == dir_u->ring - || u3_none == (harm = u3h_git(u3H->rod_u.jed.pax_p, dir_u->ring)) ) { + || u3_none == (harm = u3h_git(u3H->rod_u.jed_pax_p, dir_u->ring)) ) { dir_u->ham_u = NULL; } else { @@ -4058,7 +4058,7 @@ u3n_ream() { u3_assert(u3R == &(u3H->rod_u)); u3h_walk(u3R->byc.har_p, _n_ream); - u3h_walk(u3R->byc.dar_p, _n_ream); + u3h_walk(u3R->byc_dar_p, _n_ream); } /* _n_prog_mark(): mark program for gc. @@ -4126,23 +4126,23 @@ u3n_mark() qua_u[2] = c3_calloc(sizeof(*qua_u[2])); qua_u[2]->nam_c = strdup("direct bytecode programs"); - u3h_walk_with(u3R->byc.dar_p, _n_bam, &qua_u[2]->siz_w); + u3h_walk_with(u3R->byc_dar_p, _n_bam, &qua_u[2]->siz_w); qua_u[2]->siz_w = qua_u[2]->siz_w * 4; siz_w += qua_u[2]->siz_w; qua_u[3] = c3_calloc(sizeof(*qua_u[3])); qua_u[3]->nam_c = strdup("direct bytecode cache"); - qua_u[3]->siz_w = u3h_mark(u3R->byc.dar_p) * 4; + qua_u[3]->siz_w = u3h_mark(u3R->byc_dar_p) * 4; siz_w += qua_u[3]->siz_w; qua_u[4] = c3_calloc(sizeof(*qua_u[4])); qua_u[4]->nam_c = strdup("direct bytecode jar"); - qua_u[4]->siz_w = u3h_mark(u3R->byc.lar_p) * 4; + qua_u[4]->siz_w = u3h_mark(u3R->byc_lar_p) * 4; siz_w += qua_u[4]->siz_w; qua_u[5] = c3_calloc(sizeof(*qua_u[5])); qua_u[5]->nam_c = strdup("+ka SKA core"); - qua_u[5]->siz_w = u3a_mark_noun(u3R->dir.ka) * 4; + qua_u[5]->siz_w = u3a_mark_noun(u3R->dir_ka) * 4; siz_w += qua_u[5]->siz_w; qua_u[6] = NULL; @@ -4168,8 +4168,8 @@ u3n_reclaim(void) // u3n_free(); u3R->byc.har_p = u3h_new(); - u3R->byc.dar_p = u3h_new(); - u3R->byc.lar_p = u3h_new(); + u3R->byc_dar_p = u3h_new(); + u3R->byc_lar_p = u3h_new(); } /* u3n_rewrite_compact(): rewrite the bytecode cache for compaction. @@ -4189,8 +4189,8 @@ void u3n_rewrite_compact() { u3h_relocate(&(u3R->byc.har_p)); - u3h_relocate(&(u3R->byc.dar_p)); - u3h_relocate(&(u3R->byc.lar_p)); + u3h_relocate(&(u3R->byc_dar_p)); + u3h_relocate(&(u3R->byc_lar_p)); } @@ -4217,10 +4217,10 @@ void u3n_free() { u3n_free_table(u3R->byc.har_p); - u3n_free_table(u3R->byc.dar_p); + u3n_free_table(u3R->byc_dar_p); // programs in lar_p are owned by the already freed dar_p // - u3h_free(u3R->byc.lar_p); + u3h_free(u3R->byc_lar_p); } /* u3n_kick_on(): fire `gat` without changing the sample. diff --git a/pkg/noun/version.h b/pkg/noun/version.h index 88c6ac400a..3580e2003b 100644 --- a/pkg/noun/version.h +++ b/pkg/noun/version.h @@ -16,9 +16,10 @@ typedef c3_d u3v_version; */ typedef c3_w u3n_version; -#define U3N_VER1 (u3n_version)0 // zero-indexedfor backcompat -#define U3N_VER2 (u3n_version)1 -#define U3N_VERLAT U3N_VER2 +#define U3N_VER1 (u3n_version)0 // zero-indexedfor backcompat +#define U3N_VER2 (u3n_version)1 // lose subject more eagerly +#define U3N_VER3 (u3n_version)2 // ska +#define U3N_VERLAT U3N_VER3 /* snapshot patch format */ diff --git a/pkg/vere/melt.c b/pkg/vere/melt.c index 2bce9b4e95..c2e4aa16cb 100644 --- a/pkg/vere/melt.c +++ b/pkg/vere/melt.c @@ -174,7 +174,7 @@ u3_melt_all(FILE *fil_u) u3m_reclaim(); _melt_canon_ptr(&can_u, &(u3A->roc)); - _melt_canon_ptr(&can_u, &(u3R->dir.ka)); + _melt_canon_ptr(&can_u, &(u3R->dir_ka)); u3h_walk_with(u3R->jed.cod_p, _melt_walk_hamt, &can_u); u3h_walk_with(u3R->cax.per_p, _melt_walk_hamt, &can_u); @@ -205,8 +205,8 @@ u3_meld_all(FILE *fil_u) u3h_free(u3R->cax.per_p); u3R->cax.per_p = u3h_new_cache(u3C.per_w); - u3z(u3R->dir.ka); - u3R->dir.ka = u3_nul; + u3z(u3R->dir_ka); + u3R->dir_ka = u3_nul; (void)u3_melt_all(fil_u); (void)u3m_pack(); From 5a527bb6ae4113e4e8eb5304bcdf05ff6e89860c Mon Sep 17 00:00:00 2001 From: Quodss Date: Mon, 17 Nov 2025 20:26:04 +0100 Subject: [PATCH 25/27] ska: free bytecode properly during nock bytecode migration --- pkg/noun/build.zig | 3 ++ pkg/noun/manage.c | 24 +++++++---- pkg/noun/nock_migrate.h | 6 +++ pkg/noun/nock_migrate/v2.c | 85 ++++++++++++++++++++++++++++++++++++++ pkg/noun/nock_migrate/v2.h | 58 ++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 pkg/noun/nock_migrate.h create mode 100644 pkg/noun/nock_migrate/v2.c create mode 100644 pkg/noun/nock_migrate/v2.h diff --git a/pkg/noun/build.zig b/pkg/noun/build.zig index 4cec5661fa..4399f16ae0 100644 --- a/pkg/noun/build.zig +++ b/pkg/noun/build.zig @@ -400,6 +400,7 @@ const c_source_files = [_][]const u8{ "manage.c", "palloc.c", "nock.c", + "nock_migrate/v2.c", "options.c", "retrieve.c", "serial.c", @@ -427,6 +428,8 @@ const install_headers = [_][]const u8{ "log.h", "manage.h", "nock.h", + "nock_migrate.h", + "nock_migrate/v2.h", "noun.h", "options.h", "retrieve.h", diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 32184d9aae..a03aafd3a0 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -28,6 +28,7 @@ #include "jets/q.h" #include "log.h" #include "nock.h" +#include "nock_migrate.h" #include "openssl/crypto.h" #include "options.h" #include "rsignal.h" @@ -660,13 +661,22 @@ _find_home(void) _rod_vaal(u3R); - if ( ((pam_d >> 6) & 31) != U3N_VERLAT ) { - fprintf(stderr, "loom: discarding stale bytecode programs\r\n"); - u3j_ream(); - u3n_ream(); - u3n_reclaim(); - u3j_reclaim(); - u3H->pam_d = _pave_params(); + u3n_version nock_ver_w = ((pam_d >> 6) & 31); + if ( nock_ver_w != U3N_VERLAT ) { + switch ( nock_ver_w ) { + default: u3_assert(!"unrecognized bytecode version"); + case U3N_VER1: + case U3N_VER2: { + fprintf(stderr, "loom: discarding stale bytecode programs\r\n"); + u3j_nv2_ream(); + u3n_nv2_ream(); + u3n_nv2_reclaim(); + u3j_nv2_reclaim(); + u3H->pam_d = _pave_params(); + } break; + + case U3N_VER3: break; + } } // Simple migration for zero-initialized u3a_road members diff --git a/pkg/noun/nock_migrate.h b/pkg/noun/nock_migrate.h new file mode 100644 index 0000000000..2cf9282f27 --- /dev/null +++ b/pkg/noun/nock_migrate.h @@ -0,0 +1,6 @@ +#ifndef U3_NOCK_MIGRATE_H +#define U3_NOCK_MIGRATE_H + +#include "nock_migrate/v2.h" + +#endif /* #ifndef U3_NOCK_MIGRATE_H */ \ No newline at end of file diff --git a/pkg/noun/nock_migrate/v2.c b/pkg/noun/nock_migrate/v2.c new file mode 100644 index 0000000000..7404265069 --- /dev/null +++ b/pkg/noun/nock_migrate/v2.c @@ -0,0 +1,85 @@ +/// @file + +#include "v2.h" + +#include "allocate.h" + +static void +_cn_prog_free(u3n_nv2_prog* pog_u) +{ + c3_w dex_w; + for (dex_w = 0; dex_w < pog_u->lit_u.len_w; ++dex_w) { + u3z_nv2(pog_u->lit_u.non[dex_w]); + } + for (dex_w = 0; dex_w < pog_u->mem_u.len_w; ++dex_w) { + u3z_nv2(pog_u->mem_u.sot_u[dex_w].key); + } + for (dex_w = 0; dex_w < pog_u->cal_u.len_w; ++dex_w) { + u3j_nv2_site_lose(&(pog_u->cal_u.sit_u[dex_w])); + } + for (dex_w = 0; dex_w < pog_u->reg_u.len_w; ++dex_w) { + u3j_nv2_rite_lose(&(pog_u->reg_u.rit_u[dex_w])); + } + u3a_nv2_free(pog_u); +} + +static inline u3n_nv2_prog* +_cn_to_prog(c3_w pog_w) +{ + u3_post pog_p = pog_w << u3a_vits; + return u3to_nv2(u3n_nv2_prog, pog_p); +} + +static void +_n_feb(u3_nv2_noun kev) +{ + _cn_prog_free(_cn_to_prog(u3t_nv2(kev))); +} + +void +u3n_nv2_free() +{ + u3h_nv2_walk(u3R->byc.har_p, _n_feb); + u3h_nv2_free(u3R->byc.har_p); +} + +void +u3n_nv2_reclaim(void) +{ + u3n_nv2_free(); + u3R->byc.har_p = u3h_nv2_new(); +} + +static void* +_n_prog_dat_nv2(u3n_nv2_prog* pog_u) +{ + return ((void*) pog_u) + sizeof(u3n_nv2_prog); +} + +static void +_n_ream(u3_nv2_noun kev) +{ + u3n_nv2_prog* pog_u = _cn_to_prog(u3t_nv2(kev)); + + c3_w pad_w = (8 - pog_u->byc_u.len_w % 8) % 8; + c3_w pod_w = pog_u->lit_u.len_w % 2; + c3_w ped_w = pog_u->mem_u.len_w % 2; + // fix up pointers for loom portability + pog_u->byc_u.ops_y = (c3_y*) _n_prog_dat_nv2(pog_u); + pog_u->lit_u.non = (u3_nv2_noun*) (pog_u->byc_u.ops_y + pog_u->byc_u.len_w + pad_w); + pog_u->mem_u.sot_u = (u3n_nv2_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w + pod_w); + pog_u->cal_u.sit_u = (u3j_nv2_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w + ped_w); + pog_u->reg_u.rit_u = (u3j_nv2_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); + + for ( c3_w i_w = 0; i_w < pog_u->cal_u.len_w; ++i_w ) { + u3j_nv2_site_ream(&(pog_u->cal_u.sit_u[i_w])); + } +} + + +void +u3n_nv2_ream(void) +{ + u3_assert(u3R == &(u3H->rod_u)); + u3h_nv2_walk(u3R->byc.har_p, _n_ream); +} \ No newline at end of file diff --git a/pkg/noun/nock_migrate/v2.h b/pkg/noun/nock_migrate/v2.h new file mode 100644 index 0000000000..7008ab2c99 --- /dev/null +++ b/pkg/noun/nock_migrate/v2.h @@ -0,0 +1,58 @@ +#ifndef U3_NOCK_MIGRATE_V2_H +#define U3_NOCK_MIGRATE_V2_H + +#include "allocate.h" +#include "hashtable.h" +#include "jets.h" +#include "nock.h" +#include "vortex.h" + +#define u3h_nv2_new u3h_new +#define u3h_nv2_walk u3h_walk +#define u3h_nv2_free u3h_free +#define u3t_nv2 u3t +#define u3z_nv2 u3z +#define u3to_nv2 u3to +#define u3j_nv2_site_lose u3j_site_lose +#define u3j_nv2_rite_lose u3j_rite_lose +#define u3a_nv2_free u3a_free +#define u3j_nv2_site_ream u3j_site_ream +#define u3j_nv2_ream u3j_ream +#define u3j_nv2_reclaim u3j_reclaim + +#define u3_nv2_noun u3_noun +#define u3n_nv2_memo u3n_memo +#define u3j_nv2_site u3j_site +#define u3j_nv2_rite u3j_rite + +typedef struct _u3n_nv2_prog { + struct { + c3_o own_o; // program owns ops_y? + c3_w len_w; // length of bytecode (bytes) + c3_y* ops_y; // actual array of bytes + } byc_u; // bytecode + struct { + c3_w len_w; // number of literals + u3_nv2_noun* non; // array of literals + } lit_u; // literals + struct { + c3_w len_w; // number of memo slots + u3n_nv2_memo* sot_u; // array of memo slots + } mem_u; // memo slot data + struct { + c3_w len_w; // number of calls sites + u3j_nv2_site* sit_u; // array of sites + } cal_u; // call site data + struct { + c3_w len_w; // number of registration sites + u3j_nv2_rite* rit_u; // array of sites + } reg_u; // registration site data + } u3n_nv2_prog; + +void +u3n_nv2_reclaim(void); + +void +u3n_nv2_ream(void); + +#endif /* #ifndef U3_NOCK_MIGRATE_V2_H */ \ No newline at end of file From 66d476f0df22b09c27258f421ba97f235d3435dc Mon Sep 17 00:00:00 2001 From: Quodss Date: Mon, 17 Nov 2025 20:42:02 +0100 Subject: [PATCH 26/27] ska: EOF --- pkg/noun/nock_migrate.h | 2 +- pkg/noun/nock_migrate/v2.c | 2 +- pkg/noun/nock_migrate/v2.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/noun/nock_migrate.h b/pkg/noun/nock_migrate.h index 2cf9282f27..347678c2a4 100644 --- a/pkg/noun/nock_migrate.h +++ b/pkg/noun/nock_migrate.h @@ -3,4 +3,4 @@ #include "nock_migrate/v2.h" -#endif /* #ifndef U3_NOCK_MIGRATE_H */ \ No newline at end of file +#endif /* #ifndef U3_NOCK_MIGRATE_H */ diff --git a/pkg/noun/nock_migrate/v2.c b/pkg/noun/nock_migrate/v2.c index 7404265069..495799fcfb 100644 --- a/pkg/noun/nock_migrate/v2.c +++ b/pkg/noun/nock_migrate/v2.c @@ -82,4 +82,4 @@ u3n_nv2_ream(void) { u3_assert(u3R == &(u3H->rod_u)); u3h_nv2_walk(u3R->byc.har_p, _n_ream); -} \ No newline at end of file +} diff --git a/pkg/noun/nock_migrate/v2.h b/pkg/noun/nock_migrate/v2.h index 7008ab2c99..3ff67cc01d 100644 --- a/pkg/noun/nock_migrate/v2.h +++ b/pkg/noun/nock_migrate/v2.h @@ -55,4 +55,4 @@ u3n_nv2_reclaim(void); void u3n_nv2_ream(void); -#endif /* #ifndef U3_NOCK_MIGRATE_V2_H */ \ No newline at end of file +#endif /* #ifndef U3_NOCK_MIGRATE_V2_H */ From 8df1f92463a226a311cbc79672edd0d022aa6677 Mon Sep 17 00:00:00 2001 From: Quodss Date: Mon, 24 Nov 2025 18:02:22 +0100 Subject: [PATCH 27/27] cleanup --- pkg/noun/jets/a/max.c | 25 +------------------------ pkg/noun/jets/a/min.c | 27 +-------------------------- pkg/noun/manage.c | 2 +- pkg/noun/retrieve.c | 34 +--------------------------------- 4 files changed, 4 insertions(+), 84 deletions(-) diff --git a/pkg/noun/jets/a/max.c b/pkg/noun/jets/a/max.c index 2646ec7e04..d1047281b6 100644 --- a/pkg/noun/jets/a/max.c +++ b/pkg/noun/jets/a/max.c @@ -9,30 +9,7 @@ u3_noun u3qa_max(u3_atom a, u3_atom b) { - if ( _(u3a_is_cat(a)) || _(u3a_is_cat(b)) ) - { - return u3k(c3_max(a, b)); - } - - if (a == b) return u3k(a); - - u3a_atom* a_u = u3a_to_ptr(a); - u3a_atom* b_u = u3a_to_ptr(b); - - if (a_u->len_w != b_u->len_w) - { - return (a_u->len_w > b_u->len_w) ? u3k(a) : u3k(b); - } - - c3_w* a_w = a_u->buf_w; - c3_w* b_w = b_u->buf_w; - for (c3_w i_w = a_u->len_w; i_w--;) - { - if (a_w[i_w] > b_w[i_w]) return u3k(a); - if (a_w[i_w] < b_w[i_w]) return u3k(b); - } - - return u3k(a); + return ( 1 == u3r_comp(a, b) ) ? u3k(a) : u3k(b); } u3_noun diff --git a/pkg/noun/jets/a/min.c b/pkg/noun/jets/a/min.c index 00a75e6117..f52531ca20 100644 --- a/pkg/noun/jets/a/min.c +++ b/pkg/noun/jets/a/min.c @@ -9,32 +9,7 @@ u3_noun u3qa_min(u3_atom a, u3_atom b) { - if ( _(u3a_is_cat(a)) || _(u3a_is_cat(b)) ) - { - // this will always return a direct atom, no refcount gain necessary - // - return c3_min(a, b); - } - - if (a == b) return u3k(a); - - u3a_atom* a_u = u3a_to_ptr(a); - u3a_atom* b_u = u3a_to_ptr(b); - - if (a_u->len_w != b_u->len_w) - { - return (a_u->len_w < b_u->len_w) ? u3k(a) : u3k(b); - } - - c3_w* a_w = a_u->buf_w; - c3_w* b_w = b_u->buf_w; - for (c3_w i_w = a_u->len_w; i_w--;) - { - if (a_w[i_w] < b_w[i_w]) return u3k(a); - if (a_w[i_w] > b_w[i_w]) return u3k(b); - } - - return u3k(a); + return ( -1 == u3r_comp(a, b) ) ? u3k(a) : u3k(b); } u3_noun diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 8f4fd0dc1a..740dc1f23e 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -668,7 +668,7 @@ _find_home(void) // Simple migration for zero-initialized u3a_road members // from futureproof buffer // - if ( !u3R->lop_p ) u3R->lop_p = u3h_new(); + if ( !u3R->lop_p ) u3R->lop_p = u3h_new(); if ( !u3R->jed_pax_p ) u3R->jed_pax_p = u3h_new(); if ( !u3R->byc_dar_p ) u3R->byc_dar_p = u3h_new(); if ( !u3R->byc_lar_p ) u3R->byc_lar_p = u3h_new(); diff --git a/pkg/noun/retrieve.c b/pkg/noun/retrieve.c index 9bf554cb99..c4de00ee33 100644 --- a/pkg/noun/retrieve.c +++ b/pkg/noun/retrieve.c @@ -747,39 +747,7 @@ u3r_nord(u3_noun a, if ( !_(u3a_is_atom(b)) ) { return 0; } else { - if ( _(u3a_is_cat(a)) ) { - if ( _(u3a_is_cat(b)) ) { - return (a < b) ? 0 : 2; - } - else return 0; - } - else if ( _(u3a_is_cat(b)) ) { - return 2; - } - else { - u3a_atom* a_u = u3a_to_ptr(a); - u3a_atom* b_u = u3a_to_ptr(b); - - c3_w w_rez = a_u->len_w; - c3_w w_mox = b_u->len_w; - - if ( w_rez != w_mox ) { - return (w_rez < w_mox) ? 0 : 2; - } - else { - c3_w i_w; - - for ( i_w = 0; i_w < w_rez; i_w++ ) { - c3_w ai_w = a_u->buf_w[i_w]; - c3_w bi_w = b_u->buf_w[i_w]; - - if ( ai_w != bi_w ) { - return (ai_w < bi_w) ? 0 : 2; - } - } - return 1; - } - } + return u3r_comp(a, b) + 1; } } else { if ( _(u3a_is_atom(b)) ) {