diff --git a/pkg/noun/allocate.c b/pkg/noun/allocate.c index 44f7175879..b905ce5912 100644 --- a/pkg/noun/allocate.c +++ b/pkg/noun/allocate.c @@ -2131,7 +2131,8 @@ u3a_mark_road(FILE* fil_u) tot_w += u3a_maid(fil_u, " profile batteries", u3a_mark_noun(u3R->pro.don)); tot_w += u3a_maid(fil_u, " profile doss", u3a_mark_noun(u3R->pro.day)); tot_w += u3a_maid(fil_u, " new profile trace", u3a_mark_noun(u3R->pro.trace)); - tot_w += u3a_maid(fil_u, " memoization cache", u3h_mark(u3R->cax.har_p)); + tot_w += u3a_maid(fil_u, " transient memoization cache", u3h_mark(u3R->cax.har_p)); + tot_w += u3a_maid(fil_u, " persistent memoization cache", u3h_mark(u3R->cax.per_p)); return u3a_maid(fil_u, "total road stuff", tot_w); } @@ -2158,6 +2159,7 @@ u3a_rewrite_compact(void) u3a_rewrite_noun(u3R->pro.day); u3a_rewrite_noun(u3R->pro.trace); u3h_rewrite(u3R->cax.har_p); + u3h_rewrite(u3R->cax.per_p); u3R->ski.gul = u3a_rewritten_noun(u3R->ski.gul); u3R->bug.tax = u3a_rewritten_noun(u3R->bug.tax); @@ -2166,6 +2168,7 @@ u3a_rewrite_compact(void) u3R->pro.day = u3a_rewritten_noun(u3R->pro.day); u3R->pro.trace = u3a_rewritten_noun(u3R->pro.trace); u3R->cax.har_p = u3a_rewritten(u3R->cax.har_p); + u3R->cax.per_p = u3a_rewritten(u3R->cax.per_p); } /* _ca_print_box(): heuristically print the contents of an allocation box. diff --git a/pkg/noun/allocate.h b/pkg/noun/allocate.h index be50793002..a31488642c 100644 --- a/pkg/noun/allocate.h +++ b/pkg/noun/allocate.h @@ -154,11 +154,11 @@ u3a_jets jed; // jet dashboard - struct { // bytecode state - u3p(u3h_root) har_p; // formula->post of bytecode + struct { // bytecode state + u3p(u3h_root) har_p; // formula->post of bytecode } byc; - struct { // namespace + struct { // scry namespace u3_noun gul; // (list $+(* (unit (unit)))) now } ski; @@ -175,8 +175,11 @@ u3_noun day; // doss, only in u3H (moveme) } pro; - struct { // memoization - u3p(u3h_root) har_p; // (map (pair term noun) noun) + struct { // memoization caches + u3p(u3h_root) har_p; // transient + u3p(u3h_root) per_p; // persistent + u3p(u3h_root) fod_p; // ford NB: not used + u3p(u3h_root) sam_p; // ames NB: not used } cax; } u3a_road; typedef u3a_road u3_road; @@ -232,7 +235,7 @@ /* u3a_is_atom(): yes if noun [som] is direct atom or indirect atom. */ # define u3a_is_atom(som) c3o(u3a_is_cat(som), \ - u3a_is_pug(som)) + u3a_is_pug(som)) # define u3ud(som) u3a_is_atom(som) /* u3a_is_cell: yes if noun [som] is cell. diff --git a/pkg/noun/hashtable.h b/pkg/noun/hashtable.h index a117f50011..291ef28a0c 100644 --- a/pkg/noun/hashtable.h +++ b/pkg/noun/hashtable.h @@ -16,9 +16,8 @@ *** corresponding to the 32-slot nodes for everything under *** the root node. *** - *** We store an extra "freshly warm" bit for a simple - *** clock-algorithm reclamation policy, not yet implemented. - *** Search "clock algorithm" to figure it out. + *** We store an extra "freshly warm" bit and use it for a simple + *** clock-algorithm reclamation policy. **/ /* u3h_slot: map slot. ** diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index dcabcdb559..13e417dab6 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -18,15 +18,6 @@ #include "vortex.h" #include "xtract.h" -/** Data structures. -**/ - -/* _cj_hank: cached hook information. - */ -typedef struct { - u3_weak hax; // axis of hooked inner core - u3j_site sit_u; // call-site data -} _cj_hank; /** Functions. **/ @@ -1069,7 +1060,7 @@ _cj_prog(u3_weak loc, u3_noun fol) /* cj_hank_find(): find cached hook information, keyed by arbitrary * prefix and term cords. RETAIN. */ -static _cj_hank* +static u3j_hank* _cj_hank_find(u3_noun pre, u3_noun tam) { u3_noun key = u3nc(u3k(pre), u3k(tam)); @@ -1077,10 +1068,10 @@ _cj_hank_find(u3_noun pre, u3_noun tam) if ( u3_none != got ) { u3z(key); - return u3to(_cj_hank, got); + return u3to(u3j_hank, got); } else { - _cj_hank* new_u = u3a_walloc(c3_wiseof(_cj_hank)); + u3j_hank* new_u = u3a_walloc(c3_wiseof(u3j_hank)); u3a_road* rod_u = u3R; while ( rod_u->par_p && u3_none == got ) { @@ -1092,7 +1083,7 @@ _cj_hank_find(u3_noun pre, u3_noun tam) new_u->hax = u3_none; } else { - _cj_hank* old_u = u3to(_cj_hank, got); + u3j_hank* old_u = u3to(u3j_hank, got); if ( u3_none != (new_u->hax = old_u->hax) ) { // it's unusual but safe to "take" here, because // u3a_take will no-op on senior nouns (just as u3k would) @@ -1101,7 +1092,7 @@ _cj_hank_find(u3_noun pre, u3_noun tam) } } - u3h_put(u3R->jed.han_p, key, u3of(_cj_hank, new_u)); + u3h_put(u3R->jed.han_p, key, u3of(u3j_hank, new_u)); u3z(key); return new_u; } @@ -1112,7 +1103,7 @@ _cj_hank_find(u3_noun pre, u3_noun tam) * core on return if valid. RETAIN. */ static c3_o -_cj_hank_fine(_cj_hank* han_u, u3_noun cor, u3_noun *inn) +_cj_hank_fine(u3j_hank* han_u, u3_noun cor, u3_noun *inn) { u3_noun hax = han_u->hax; if ( u3_none == hax ) { @@ -1134,7 +1125,7 @@ _cj_hank_fine(_cj_hank* han_u, u3_noun cor, u3_noun *inn) /* _cj_hank_lose(): release memory maintained in a hook cache. */ static void -_cj_hank_lose(_cj_hank* han_u) +_cj_hank_lose(u3j_hank* han_u) { if ( u3_none != han_u->hax ) { u3z(han_u->hax); @@ -1145,7 +1136,7 @@ _cj_hank_lose(_cj_hank* han_u) /* _cj_hank_fill(): slow path, populate han_u. */ static u3_noun -_cj_hank_fill(_cj_hank* han_u, u3_noun tam, u3_noun cor) +_cj_hank_fill(u3j_hank* han_u, u3_noun tam, u3_noun cor) { u3_weak loc, col; u3_noun got, pat, nam, huc; @@ -1642,7 +1633,7 @@ u3j_cook(const c3_c* key_c, const c3_c* tam_c) { u3_noun pro, key, tam, inn; - _cj_hank* han_u; + u3j_hank* han_u; u3t_on(glu_o); key = u3i_string(key_c); @@ -1992,11 +1983,11 @@ u3j_rite_mine(u3j_rite* rit_u, u3_noun clu, u3_noun cor) /* _cj_take_hank_cb(): u3h_take_with cb for taking hanks */ -static u3p(_cj_hank) -_cj_take_hank_cb(u3p(_cj_hank) nah_p) +static u3p(u3j_hank) +_cj_take_hank_cb(u3p(u3j_hank) nah_p) { - _cj_hank* nah_u = u3to(_cj_hank, nah_p); - _cj_hank* han_u = u3a_walloc(c3_wiseof(_cj_hank)); + u3j_hank* nah_u = u3to(u3j_hank, nah_p); + u3j_hank* han_u = u3a_walloc(c3_wiseof(u3j_hank)); if ( u3_none == nah_u->hax ) { han_u->hax = u3_none; @@ -2007,7 +1998,7 @@ _cj_take_hank_cb(u3p(_cj_hank) nah_p) u3j_site_take(&(han_u->sit_u), &(nah_u->sit_u)); } - return u3of(_cj_hank, han_u); + return u3of(u3j_hank, han_u); } /* u3j_take(): copy junior jet state. @@ -2029,25 +2020,25 @@ static void _cj_merge_hank_cb(u3_noun kev, void* wit) { u3p(u3h_root) han_p = *(u3p(u3h_root)*)wit; - _cj_hank* nah_u; + u3j_hank* nah_u; u3_noun key; - u3p(_cj_hank) nah_p; + u3p(u3j_hank) nah_p; u3x_cell(kev, &key, &nah_p); - nah_u = u3to(_cj_hank, nah_p); + nah_u = u3to(u3j_hank, nah_p); if ( u3_none == nah_u->hax ) { u3a_wfree(nah_u); } else { - _cj_hank* han_u; + u3j_hank* han_u; u3_weak got = u3h_git(u3R->jed.han_p, key); if ( u3_none == got ) { han_u = nah_u; } else { - han_u = u3to(_cj_hank, got); + han_u = u3to(u3j_hank, got); if ( u3_none != han_u->hax ) { u3z(han_u->hax); @@ -2058,7 +2049,7 @@ _cj_merge_hank_cb(u3_noun kev, void* wit) u3a_wfree(nah_u); } - u3h_put(han_p, key, u3of(_cj_hank, han_u)); + u3h_put(han_p, key, u3of(u3j_hank, han_u)); } } @@ -2170,7 +2161,7 @@ _cj_warm_tap(u3_noun kev, void* wit) static void _cj_ream_hank(u3_noun kev) { - u3j_site_ream(&(u3to(_cj_hank, u3t(kev))->sit_u)); + u3j_site_ream(&(u3to(u3j_hank, u3t(kev))->sit_u)); } /* u3j_ream(): rebuild warm state @@ -2304,7 +2295,7 @@ static void _cj_mark_hank(u3_noun kev, void* dat) { c3_w* tot_w = (c3_w*) dat; - _cj_hank* han_u = u3to(_cj_hank, u3t(kev)); + u3j_hank* han_u = u3to(u3j_hank, u3t(kev)); *tot_w += u3a_mark_ptr(han_u); if ( u3_none != han_u->hax ) { *tot_w += u3a_mark_noun(han_u->hax); @@ -2337,12 +2328,12 @@ u3j_mark(FILE* fil_u) return u3a_maid(fil_u, "total jet stuff", tot_w); } -/* _cj_free_hank(): free an entry from the hank cache. +/* u3j_free_hank(): free an entry from the hank cache. */ -static void -_cj_free_hank(u3_noun kev) +void +u3j_free_hank(u3_noun kev) { - _cj_hank* han_u = u3to(_cj_hank, u3t(kev)); + u3j_hank* han_u = u3to(u3j_hank, u3t(kev)); if ( u3_none != han_u->hax ) { u3z(han_u->hax); u3j_site_lose(&(han_u->sit_u)); @@ -2355,7 +2346,7 @@ _cj_free_hank(u3_noun kev) void u3j_free(void) { - u3h_walk(u3R->jed.han_p, _cj_free_hank); + u3h_walk(u3R->jed.han_p, u3j_free_hank); u3h_free(u3R->jed.war_p); u3h_free(u3R->jed.cod_p); u3h_free(u3R->jed.han_p); @@ -2379,7 +2370,7 @@ u3j_reclaim(void) // } // clear the jet hank cache // - u3h_walk(u3R->jed.han_p, _cj_free_hank); + u3h_walk(u3R->jed.han_p, u3j_free_hank); u3h_free(u3R->jed.han_p); u3R->jed.han_p = u3h_new(); } diff --git a/pkg/noun/jets.h b/pkg/noun/jets.h index 9c5241c5db..1440f7558a 100644 --- a/pkg/noun/jets.h +++ b/pkg/noun/jets.h @@ -126,6 +126,13 @@ u3p(u3j_fink) fin_p; // fine check } u3j_site; + /* u3j_hank: cached hook information. + */ + typedef struct { + u3_weak hax; // axis of hooked inner core + u3j_site sit_u; // call-site data + } u3j_hank; + /** Globals. **/ /* u3_Dash: jet dashboard. @@ -297,6 +304,11 @@ void u3j_free(void); + /* u3j_free_hank(): free an entry from the hank cache. + */ + void + u3j_free_hank(u3_noun kev); + /* u3j_reclaim(): clear ad-hoc persistent caches to reclaim memory. */ void diff --git a/pkg/noun/jets/f/ut_crop.c b/pkg/noun/jets/f/ut_crop.c index 1969a13a3d..189564d0c3 100644 --- a/pkg/noun/jets/f/ut_crop.c +++ b/pkg/noun/jets/f/ut_crop.c @@ -20,7 +20,7 @@ u3wfu_crop(u3_noun cor) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__crop + ((!!vet) << 8); u3_noun key = u3z_key_3(fun_m, sut, ref, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -28,7 +28,7 @@ u3wfu_crop(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/jets/f/ut_fish.c b/pkg/noun/jets/f/ut_fish.c index e7505b9345..e8acbd43cf 100644 --- a/pkg/noun/jets/f/ut_fish.c +++ b/pkg/noun/jets/f/ut_fish.c @@ -21,7 +21,7 @@ u3wfu_fish(u3_noun cor) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__fish + ((!!vet) << 8); u3_noun key = u3z_key_3(fun_m, sut, axe, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -29,7 +29,7 @@ u3wfu_fish(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/jets/f/ut_fuse.c b/pkg/noun/jets/f/ut_fuse.c index f9fac33a4d..8e4e1a6135 100644 --- a/pkg/noun/jets/f/ut_fuse.c +++ b/pkg/noun/jets/f/ut_fuse.c @@ -20,7 +20,7 @@ u3wfu_fuse(u3_noun cor) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__fuse + ((!!vet) << 8); u3_noun key = u3z_key_3(fun_m, sut, ref, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -28,7 +28,7 @@ u3wfu_fuse(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/jets/f/ut_mint.c b/pkg/noun/jets/f/ut_mint.c index fc8424854a..618e7291fd 100644 --- a/pkg/noun/jets/f/ut_mint.c +++ b/pkg/noun/jets/f/ut_mint.c @@ -22,7 +22,7 @@ u3wfu_mint(u3_noun cor) c3_m fun_m = 141 + c3__mint; u3_noun vet = u3r_at(u3qfu_van_vet, van); u3_noun key = u3z_key_5(fun_m, vet, sut, gol, gen, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -30,7 +30,7 @@ u3wfu_mint(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/jets/f/ut_mull.c b/pkg/noun/jets/f/ut_mull.c index 98e62ca57e..767ab3c51a 100644 --- a/pkg/noun/jets/f/ut_mull.c +++ b/pkg/noun/jets/f/ut_mull.c @@ -23,7 +23,7 @@ u3wfu_mull(u3_noun cor) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__mull + ((!!vet) << 8); u3_noun key = u3z_key_5(fun_m, sut, gol, dox, gen, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -31,7 +31,7 @@ u3wfu_mull(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/jets/f/ut_nest.c b/pkg/noun/jets/f/ut_nest.c index 765081a5cb..9bc53bf0f9 100644 --- a/pkg/noun/jets/f/ut_nest.c +++ b/pkg/noun/jets/f/ut_nest.c @@ -27,7 +27,7 @@ u3wfu_nest_dext(u3_noun dext_core) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__dext + ((!!vet) << 8); u3_noun key = u3z_key_3(fun_m, sut, ref, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -39,7 +39,7 @@ u3wfu_nest_dext(u3_noun dext_core) if ( ((c3y == pro) && (u3_nul == reg)) || ((c3n == pro) && (u3_nul == seg)) ) { - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } else { u3z(key); diff --git a/pkg/noun/jets/f/ut_rest.c b/pkg/noun/jets/f/ut_rest.c index 3fdbed23b0..87ff60fa68 100644 --- a/pkg/noun/jets/f/ut_rest.c +++ b/pkg/noun/jets/f/ut_rest.c @@ -20,7 +20,7 @@ u3wfu_rest(u3_noun cor) u3_weak vet = u3r_at(u3qfu_van_vet, van); c3_m fun_m = 141 + c3__rest + ((!!vet) << 8); u3_noun key = u3z_key_3(fun_m, sut, leg, bat); - u3_weak pro = u3z_find(key); + u3_weak pro = u3z_find(u3z_memo_toss, key); if ( u3_none != pro ) { u3z(key); @@ -28,7 +28,7 @@ u3wfu_rest(u3_noun cor) } else { pro = u3n_nock_on(u3k(cor), u3k(u3x_at(u3x_bat, cor))); - return u3z_save(key, pro); + return u3z_save(u3z_memo_toss, key, pro); } } } diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index 60787bde34..ec1f32524b 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -1,6 +1,8 @@ /// @file -#include "manage.h" +#include "pkg/noun/manage.h" +#include "pkg/noun/v2/manage.h" +#include "pkg/noun/v3/manage.h" #include #include @@ -473,9 +475,8 @@ u3m_mark(FILE* fil_u) static void _pave_parts(void) { - // TODO: pass `u3_Host.ops_u.hap_w` into `noun` library as an argument and use - // as size of memo cache. - u3R->cax.har_p = u3h_new_cache(50000); + u3R->cax.har_p = u3h_new_cache(u3C.hap_w); // transient + u3R->cax.per_p = u3h_new_cache(u3C.per_w); // persistent u3R->jed.war_p = u3h_new(); u3R->jed.cod_p = u3h_new(); u3R->jed.han_p = u3h_new(); @@ -597,7 +598,8 @@ _find_home(void) switch ( ver_w ) { case 1: u3m_v2_migrate(); - case 2: break; + case 2: u3m_v3_migrate(); + case 3: break; default: { fprintf(stderr, "loom: checkpoint version mismatch: " "have %u, need %u\r\n", @@ -991,6 +993,7 @@ u3m_love(u3_noun pro) // u3p(u3h_root) byc_p = u3R->byc.har_p; u3a_jets jed_u = u3R->jed; + u3p(u3h_root) per_p = u3R->cax.per_p; // fallback to parent road (child heap on parent's stack) // @@ -1001,6 +1004,7 @@ u3m_love(u3_noun pro) pro = u3a_take(pro); jed_u = u3j_take(jed_u); byc_p = u3n_take(byc_p); + per_p = u3h_take(per_p); // pop the stack // @@ -1011,6 +1015,7 @@ u3m_love(u3_noun pro) // u3j_reap(jed_u); u3n_reap(byc_p); + u3z_reap(u3z_memo_keep, per_p); return pro; } diff --git a/pkg/noun/nock.c b/pkg/noun/nock.c index 6ac08779ef..452b04c309 100644 --- a/pkg/noun/nock.c +++ b/pkg/noun/nock.c @@ -619,7 +619,7 @@ _n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, case SKIB: case SLIB: { c3_l tot_l = 0, - sip_l = u3h(u3t(op)); + sip_l = u3h(u3t(u3t(op))); c3_w j_w, k_w = i_w; for ( j_w = 0; j_w < sip_l; ++j_w ) { tot_l += siz_y[++k_w]; @@ -830,7 +830,9 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) _n_prog_asm_inx(buf_y, &i_w, mem_s, cod); mem_u = &(pog_u->mem_u.sot_u[mem_s++]); mem_u->sip_l = sip_l; - mem_u->key = u3k(u3t(u3t(op))); + // [op_y, cid, mem_w, nef] + mem_u->key = u3k(u3t(u3t(u3t(op)))); + mem_u->cid = u3h(u3t(op)); break; } @@ -1117,16 +1119,21 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) c3_w mem_w = 0; c3_y op_y; - // we just throw away the hint (why is this not a static hint?) tot_w += _n_comp(ops, hod, c3n, c3n); ++tot_w; _n_emit(ops, TOSS); - // memoizing code always loses TOS because SAVE needs [pro key] mem_w += _n_comp(&mem, nef, c3y, c3n); ++mem_w; _n_emit(&mem, SAVE); op_y = (c3y == los_o) ? SLIB : SKIB; // overflows to SLIS / SKIS - ++tot_w; _n_emit(ops, u3nt(op_y, mem_w, u3k(nef))); + 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; } @@ -2610,9 +2617,9 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) skim_out: o = u3k(mem_u->key); x = u3nc(x, o); - o = u3z_find_m(144 + c3__nock, x); + o = u3z_find_m(mem_u->cid, 144 + c3__nock, x); if ( u3_none == o ) { - _n_push(mov, off, x); + _n_push(mov, off, u3nc(mem_u->cid, x)); _n_push(mov, off, u3k(u3h(x))); } else { @@ -2623,11 +2630,16 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) BURN(); do_save: - x = _n_pep(mov, off); + x = _n_pep(mov, off); // product top = _n_peek(off); o = *top; - if ( &(u3H->rod_u) != u3R ) { - u3z_save_m(144 + c3__nock, o, x); + if ( ( u3z_memo_toss == u3h(o) ) + ? ( &(u3H->rod_u) != u3R ) + : ( 0 == u3R->ski.gul ) ) { // prevents userspace from persistence + u3z_save_m(u3h(o), 144 + c3__nock, u3t(o), x); + } + else if ( u3z_memo_keep == u3h(o) ) { + fprintf(stderr, "\r\nnock: userspace can't save to persistent cache\r\n"); } *top = x; u3z(o); @@ -2853,6 +2865,7 @@ _cn_take_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) u3n_memo* ome_u = &(dst_u->mem_u.sot_u[i_w]); ome_u->sip_l = emo_u->sip_l; ome_u->key = u3a_take(emo_u->key); + ome_u->cid = emo_u->cid; } for ( i_w = 0; i_w < src_u->cal_u.len_w; ++i_w ) { @@ -2918,6 +2931,7 @@ _cn_merge_prog_dat(u3n_prog* dst_u, u3n_prog* src_u) u3z(emo_u->key); emo_u->sip_l = ome_u->sip_l; emo_u->key = ome_u->key; + emo_u->cid = ome_u->cid; } for ( i_w = 0; i_w < src_u->cal_u.len_w; ++i_w ) { diff --git a/pkg/noun/nock.h b/pkg/noun/nock.h index 7dded22058..7baf7351d8 100644 --- a/pkg/noun/nock.h +++ b/pkg/noun/nock.h @@ -8,6 +8,7 @@ #include "c3.h" #include "jets.h" #include "types.h" +#include "zave.h" /** Data structures. *** @@ -18,6 +19,7 @@ typedef struct { c3_l sip_l; u3_noun key; + u3z_cid cid; } u3n_memo; /* u3n_prog: program compiled from nock diff --git a/pkg/noun/options.h b/pkg/noun/options.h index 52732d2655..29ca6ce9d9 100644 --- a/pkg/noun/options.h +++ b/pkg/noun/options.h @@ -17,6 +17,8 @@ c3_w wag_w; // flags (both ways) size_t wor_i; // loom word-length (<= u3a_words) c3_w tos_w; // loom toss skip-length + c3_w hap_w; // transient memoization cache size + c3_w per_w; // persistent memoization cache size void (*stderr_log_f)(c3_c*); // errors from c code void (*slog_f)(u3_noun); // function pointer for slog void (*sign_hold_f)(void); // suspend system signal regime diff --git a/pkg/noun/retrieve.c b/pkg/noun/retrieve.c index d1790c7320..cc1add4c9c 100644 --- a/pkg/noun/retrieve.c +++ b/pkg/noun/retrieve.c @@ -1903,3 +1903,28 @@ u3r_mug(u3_noun veb) return mug_l; } + +/* u3r_skip(): +** +** Extract a constant from a formula, ignoring +** safe/static hints, doing no computation. +*/ +u3_weak +u3r_skip(u3_noun fol) { + while ( c3y == u3du(fol) ) { + switch ( u3h(fol) ) { + default: return u3_none; + case 1: return u3t(fol); + case 11: { + u3_noun arg = u3t(fol), + hod = u3h(arg); + + if ( (c3y == u3du(hod)) && (u3_none == u3r_skip(u3t(hod))) ) { + return u3_none; + } + fol = u3t(arg); + } + } + } + return u3_none; +} diff --git a/pkg/noun/retrieve.h b/pkg/noun/retrieve.h index a98a5e4697..f382ff6db0 100644 --- a/pkg/noun/retrieve.h +++ b/pkg/noun/retrieve.h @@ -486,4 +486,11 @@ c3_y* u3r_tape(u3_noun a); + /* u3r_skip(): + ** + ** Extract a constant from a formula, ignoring + ** safe/static hints, doing no computation. + */ + u3_weak u3r_skip(u3_noun fol); + #endif /* ifndef U3_RETRIEVE_H */ diff --git a/pkg/noun/v1/allocate.c b/pkg/noun/v1/allocate.c index 226aa33f00..29a1f5de77 100644 --- a/pkg/noun/v1/allocate.c +++ b/pkg/noun/v1/allocate.c @@ -210,10 +210,10 @@ u3a_v1_reclaim(void) u3h_v1_free_nodes(u3R_v1->cax.har_p); } -/* _me_lose_north(): lose on a north road. +/* _me_v1_lose_north(): lose on a north road. */ static void -_me_lose_north(u3_noun dog) +_me_v1_lose_north(u3_noun dog) { top: { @@ -234,7 +234,7 @@ _me_lose_north(u3_noun dog) u3_noun t_dog = dog_u->tel; if ( !_(u3a_v1_is_cat(h_dog)) ) { - _me_lose_north(h_dog); + _me_v1_lose_north(h_dog); } u3a_v1_wfree(dog_w); if ( !_(u3a_v1_is_cat(t_dog)) ) { @@ -256,6 +256,6 @@ void u3a_v1_lose(u3_noun som) { if ( !_(u3a_v1_is_cat(som)) ) { - _me_lose_north(som); + _me_v1_lose_north(som); } } diff --git a/pkg/noun/v1/jets.c b/pkg/noun/v1/jets.c index be13a63d49..272930e11d 100644 --- a/pkg/noun/v1/jets.c +++ b/pkg/noun/v1/jets.c @@ -9,19 +9,6 @@ #include "pkg/noun/v1/allocate.h" #include "pkg/noun/v1/hashtable.h" -/** Data structures. -**/ - -/* _cj_v1_hank: cached hook information. -** NB: copy of _cj_hank from pkg/noun/jets.c - */ -typedef struct { - u3_weak hax; // axis of hooked inner core - u3j_v1_site sit_u; // call-site data -} _cj_v1_hank; - -/** Functions. -**/ /* _cj_fink_free(): lose and free everything in a u3j_v1_fink. */ @@ -75,13 +62,12 @@ u3j_v1_site_lose(u3j_v1_site* sit_u) } /* _cj_v1_free_hank(): free an entry from the hank cache. -** NB: copy of _cj_v1_free_hank() from pkg/noun/jets.c */ static void _cj_v1_free_hank(u3_noun kev) { u3a_v1_cell* cel_u = (u3a_v1_cell*) u3a_v1_to_ptr(kev); - _cj_v1_hank* han_u = u3to(_cj_v1_hank, cel_u->tel); + u3j_v1_hank* han_u = u3to(u3j_v1_hank, cel_u->tel); if ( u3_none != han_u->hax ) { u3a_v1_lose(han_u->hax); u3j_v1_site_lose(&(han_u->sit_u)); diff --git a/pkg/noun/v1/jets.h b/pkg/noun/v1/jets.h index 1711a0e675..bf3dfe6afe 100644 --- a/pkg/noun/v1/jets.h +++ b/pkg/noun/v1/jets.h @@ -10,6 +10,7 @@ **/ # define u3j_v1_fink u3j_v2_fink # define u3j_v1_fist u3j_v2_fist +# define u3j_v1_hank u3j_v2_hank # define u3j_v1_rite u3j_v2_rite # define u3j_v1_site u3j_v2_site @@ -23,11 +24,11 @@ /* u3j_v1_rite_lose(): lose references of u3j_rite (but do not free). */ void - u3j_v1_rite_lose(u3j_rite* rit_u); + u3j_v1_rite_lose(u3j_v1_rite* rit_u); /* u3j_v1_site_lose(): lose references of u3j_site (but do not free). */ void - u3j_v1_site_lose(u3j_site* sit_u); + u3j_v1_site_lose(u3j_v1_site* sit_u); #endif /* ifndef U3_JETS_V1_H */ diff --git a/pkg/noun/v1/nock.c b/pkg/noun/v1/nock.c index 4e0de27dc2..cce00b28b6 100644 --- a/pkg/noun/v1/nock.c +++ b/pkg/noun/v1/nock.c @@ -22,17 +22,10 @@ u3n_v1_reclaim(void) } /* _cn_v1_prog_free(): free memory retained by program pog_u -** NB: copy of _cn_v1_prog_free in pkg/noun/nock.c */ static void _cn_v1_prog_free(u3n_v1_prog* pog_u) { - // fix up pointers for loom portability - // pog_u->byc_u.ops_y = (c3_y*) ((void*) pog_u) + sizeof(u3n_v1_prog); - // pog_u->lit_u.non = (u3_noun*) (pog_u->byc_u.ops_y + pog_u->byc_u.len_w); - // pog_u->mem_u.sot_u = (u3n_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w); - // pog_u->cal_u.sit_u = (u3j_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w); - // pog_u->reg_u.rit_u = (u3j_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); c3_w dex_w; for (dex_w = 0; dex_w < pog_u->lit_u.len_w; ++dex_w) { @@ -47,13 +40,21 @@ _cn_v1_prog_free(u3n_v1_prog* pog_u) for (dex_w = 0; dex_w < pog_u->reg_u.len_w; ++dex_w) { u3j_v1_rite_lose(&(pog_u->reg_u.rit_u[dex_w])); } + + // fix up pointers for loom portability + pog_u->byc_u.ops_y = (c3_y*) ((void*) pog_u) + sizeof(u3n_v1_prog); + pog_u->lit_u.non = (u3_noun*) (pog_u->byc_u.ops_y + pog_u->byc_u.len_w); + pog_u->mem_u.sot_u = (u3n_v1_memo*) (pog_u->lit_u.non + pog_u->lit_u.len_w); + pog_u->cal_u.sit_u = (u3j_v1_site*) (pog_u->mem_u.sot_u + pog_u->mem_u.len_w); + pog_u->reg_u.rit_u = (u3j_rite*) (pog_u->cal_u.sit_u + pog_u->cal_u.len_w); + u3a_v1_free(pog_u); } -/* _n_feb(): u3h_v1_walk helper for u3n_v1_free +/* _n_v1_feb(): u3h_v1_walk helper for u3n_v1_free */ static void -_n_feb(u3_noun kev) +_n_v1_feb(u3_noun kev) { u3a_v1_cell *cel_u = (u3a_v1_cell*) u3a_v1_to_ptr(kev); _cn_v1_prog_free(u3to(u3n_v1_prog, cel_u->tel)); @@ -65,6 +66,6 @@ void u3n_v1_free() { u3p(u3h_v1_root) har_p = u3R_v1->byc.har_p; - u3h_v1_walk(har_p, _n_feb); + u3h_v1_walk(har_p, _n_v1_feb); u3h_v1_free_nodes(har_p); } diff --git a/pkg/noun/v1/nock.h b/pkg/noun/v1/nock.h index 08a7a5959a..5320307b6b 100644 --- a/pkg/noun/v1/nock.h +++ b/pkg/noun/v1/nock.h @@ -7,6 +7,7 @@ /** Aliases. **/ +# define u3n_v1_memo u3n_v2_memo # define u3n_v1_prog u3n_v2_prog /** Functions. diff --git a/pkg/noun/v2/allocate.h b/pkg/noun/v2/allocate.h index 82b1826adb..b08ffd9c69 100644 --- a/pkg/noun/v2/allocate.h +++ b/pkg/noun/v2/allocate.h @@ -21,6 +21,7 @@ # define u3a_v2_is_north u3a_is_north # define u3a_v2_is_pom u3a_is_pom # define u3a_v2_is_pug u3a_is_pug +# define u3a_v2_lose u3a_lose # define u3a_v2_malloc u3a_malloc # define u3a_v2_minimum u3a_minimum # define u3a_v2_outa u3a_outa diff --git a/pkg/noun/v2/hashtable.h b/pkg/noun/v2/hashtable.h index be6ab9587c..09025fc19f 100644 --- a/pkg/noun/v2/hashtable.h +++ b/pkg/noun/v2/hashtable.h @@ -3,6 +3,7 @@ #define u3h_v2_buck u3h_buck #define u3h_v2_free u3h_free +#define u3h_v2_new u3h_new #define u3h_v2_node u3h_node #define u3h_v2_noun_to_slot u3h_noun_to_slot #define u3h_v2_root u3h_root diff --git a/pkg/noun/v2/jets.c b/pkg/noun/v2/jets.c index e70ef46abe..4b25c0e9d5 100644 --- a/pkg/noun/v2/jets.c +++ b/pkg/noun/v2/jets.c @@ -9,6 +9,18 @@ #include "pkg/noun/v2/hashtable.h" #include "pkg/noun/v2/vortex.h" +/* u3j_v2_reclaim(): clear ad-hoc persistent caches to reclaim memory. +*/ +void +u3j_v2_reclaim(void) +{ + // clear the jet hank cache + // + u3h_v2_walk(u3R_v2->jed.han_p, u3j_v2_free_hank); + u3h_v2_free(u3R_v2->jed.han_p); + u3R_v2->jed.han_p = u3h_v2_new(); +} + /* u3j_v2_rewrite_compact(): rewrite jet state for compaction. * * NB: u3R_v2->jed.han_p *must* be cleared (currently via u3j_v2_reclaim above) diff --git a/pkg/noun/v2/jets.h b/pkg/noun/v2/jets.h index a596170f60..281c5d62be 100644 --- a/pkg/noun/v2/jets.h +++ b/pkg/noun/v2/jets.h @@ -3,17 +3,30 @@ #ifndef U3_JETS_V2_H #define U3_JETS_V2_H +#include "pkg/noun/allocate.h" +#include "pkg/noun/jets.h" + + /** Aliases. **/ +# define u3j_v2_core u3j_core # define u3j_v2_fink u3j_fink # define u3j_v2_fist u3j_fist +# define u3j_v2_hank u3j_hank +# define u3j_v2_free_hank u3j_free_hank +# define u3j_v2_harm u3j_harm # define u3j_v2_rite u3j_rite -# define u3j_v2_rite_lose u3j_rite_lose # define u3j_v2_site u3j_site +# define u3j_v2_rite_lose u3j_rite_lose # define u3j_v2_site_lose u3j_site_lose /** Functions. **/ + /* u3j_v2_reclaim(): clear ad-hoc persistent caches to reclaim memory. + */ + void + u3j_v2_reclaim(void); + /* u3j_v2_rewrite_compact(): rewrite jet state for compaction. */ void diff --git a/pkg/noun/v2/manage.h b/pkg/noun/v2/manage.h index 998a37cc65..1d03b97809 100644 --- a/pkg/noun/v2/manage.h +++ b/pkg/noun/v2/manage.h @@ -3,10 +3,9 @@ #ifndef U3_MANAGE_V2_H #define U3_MANAGE_V2_H - /** System management. + /** System management. **/ /* u3m_v2_migrate: perform pointer compression loom migration if necessary. - ver_w - target version */ void u3m_v2_migrate(); diff --git a/pkg/noun/v2/nock.c b/pkg/noun/v2/nock.c index 95a011e005..d8e447a417 100644 --- a/pkg/noun/v2/nock.c +++ b/pkg/noun/v2/nock.c @@ -1,11 +1,9 @@ /// @file -#include "pkg/noun/nock.h" #include "pkg/noun/v2/nock.h" #include "pkg/noun/v2/allocate.h" #include "pkg/noun/v2/hashtable.h" -#include "pkg/noun/v2/vortex.h" /* u3n_v2_rewrite_compact(): rewrite the bytecode cache for compaction. * diff --git a/pkg/noun/v2/nock.h b/pkg/noun/v2/nock.h index eddc3d2074..13432f384b 100644 --- a/pkg/noun/v2/nock.h +++ b/pkg/noun/v2/nock.h @@ -3,13 +3,16 @@ #ifndef U3_NOCK_V2_H #define U3_NOCK_V2_H +#include "pkg/noun/nock.h" + +#include "types.h" + /** Aliases. **/ -#define u3n_v2_free u3n_free -#define u3n_v2_prog u3n_prog +# define u3n_v2_memo u3n_memo +# define u3n_v2_prog u3n_prog +# define u3n_v2_reclaim u3n_reclaim - /** Functions. - **/ /* u3n_v2_rewrite_compact(): rewrite bytecode cache for compaction. */ void diff --git a/pkg/noun/v3/allocate.h b/pkg/noun/v3/allocate.h new file mode 100644 index 0000000000..fb9fa73015 --- /dev/null +++ b/pkg/noun/v3/allocate.h @@ -0,0 +1,16 @@ +#ifndef U3_ALLOCATE_V3_H +#define U3_ALLOCATE_V3_H + +#include "pkg/noun/allocate.h" + +#include "pkg/noun/v3/manage.h" +#include "options.h" + + /** Aliases. + **/ +# define u3R_v3 u3a_Road +# define u3a_v3_balign u3a_balign +# define u3a_v3_road u3a_road +# define u3a_v3_walign u3a_walign + +#endif /* ifndef U3_ALLOCATE_V3_H */ diff --git a/pkg/noun/v3/hashtable.h b/pkg/noun/v3/hashtable.h new file mode 100644 index 0000000000..7ad854b91c --- /dev/null +++ b/pkg/noun/v3/hashtable.h @@ -0,0 +1,8 @@ +#ifndef U3_HASHTABLE_V3_H +#define U3_HASHTABLE_V3_H + +#define u3h_v3_new_cache u3h_new_cache + +#include "pkg/noun/hashtable.h" + +#endif /* U3_HASHTABLE_V3_H */ diff --git a/pkg/noun/v3/manage.c b/pkg/noun/v3/manage.c new file mode 100644 index 0000000000..a9236ffa80 --- /dev/null +++ b/pkg/noun/v3/manage.c @@ -0,0 +1,111 @@ +/// @file + +#include "pkg/noun/v3/manage.h" + +#include "pkg/noun/v2/jets.h" +#include "pkg/noun/v2/nock.h" +#include "pkg/noun/v2/vortex.h" + +#include "pkg/noun/v3/allocate.h" +#include "pkg/noun/v3/hashtable.h" +#include "pkg/noun/version.h" +#include "pkg/noun/v3/vortex.h" +#include + +/* u3m_v3_migrate: perform loom migration if necessary. +*/ +void +u3m_v3_migrate() +{ + fprintf(stderr, "loom: memoization migration running...\r\n"); + + + c3_w ver_w = *(u3_Loom + u3C.wor_i - 1); + c3_w *mem_w = u3_Loom + u3a_v3_walign; + c3_w len_w = u3C.wor_i - u3a_v3_walign; + c3_w suz_w = c3_wiseof(u3v_v2_home); + c3_w *mut_w = c3_align(mem_w + len_w - suz_w, u3a_v3_balign, C3_ALGLO); + + // old road + u3v_v2_home* hum_u = (u3v_v2_home*)mut_w; + u3a_v2_road* rud_u = &hum_u->rod_u; + size_t ruz_t = sizeof(u3a_v2_road); + + // set v2 globals + u3H_v2 = (void *)mut_w; + u3R_v2 = &u3H_v2->rod_u; + u3R_v2->cap_p = u3R_v2->mat_p = u3a_v2_outa(u3H_v2); + u3H = (u3v_home*)u3H_v2; + u3R = (u3a_road*)u3R_v2; + + // free bytecode caches in old road + u3j_v2_reclaim(); + u3n_v2_reclaim(); + + // new home, new road + u3v_v3_home hom_u = {0}; + u3a_v3_road rod_u = {0}; + + // copy members, one-by-one, from old road to new road + rod_u.par_p = rud_u->par_p; + rod_u.kid_p = rud_u->kid_p; + rod_u.nex_p = rud_u->nex_p; + + rod_u.cap_p = rud_u->cap_p; + rod_u.hat_p = rud_u->hat_p; + rod_u.mat_p = rud_u->mat_p; + rod_u.rut_p = rud_u->rut_p; + rod_u.ear_p = rud_u->ear_p; + + // no need to zero-out fut_w + // no need to do anything with esc + + rod_u.how.fag_w = rud_u->how.fag_w; + + memcpy(rod_u.all.fre_p, rud_u->all.fre_p, sizeof(rud_u->all.fre_p)); + rod_u.all.cel_p = rud_u->all.cel_p; + rod_u.all.fre_w = rud_u->all.fre_w; + rod_u.all.max_w = rud_u->all.max_w; + + rod_u.jed.hot_p = rud_u->jed.hot_p; + rod_u.jed.war_p = rud_u->jed.war_p; + rod_u.jed.cod_p = rud_u->jed.cod_p; + rod_u.jed.han_p = rud_u->jed.han_p; + rod_u.jed.bas_p = rud_u->jed.bas_p; + + rod_u.byc.har_p = rud_u->byc.har_p; + + rod_u.ski.gul = rud_u->ski.gul; + + rod_u.bug.tax = rud_u->bug.tax; + rod_u.bug.mer = rud_u->bug.mer; + + rod_u.pro.nox_d = rud_u->pro.nox_d; + rod_u.pro.cel_d = rud_u->pro.cel_d; + rod_u.pro.don = rud_u->pro.don; + rod_u.pro.trace = rud_u->pro.trace; + rod_u.pro.day = rud_u->pro.day; + + rod_u.cax.har_p = rud_u->cax.har_p; + + // prepare the new home, update the version + hom_u.arv_u = hum_u->arv_u; + hom_u.rod_u = rod_u; + hom_u.ver_w = U3V_VER3; + + // place the new home over the old one + c3_w siz_w = c3_wiseof(u3v_v3_home); + c3_w *mat_w = c3_align(mem_w + len_w - siz_w, u3a_v3_balign, C3_ALGLO); + memcpy(mat_w, &hom_u, sizeof(u3v_v3_home)); + + // set globals + u3H_v3 = (void*)mat_w; + u3R_v3 = &u3H_v3->rod_u; + u3H = (u3v_home*)u3H_v3; + u3R = (u3a_road*)u3R_v3; + + // initialize persistent cache + u3R_v3->cax.per_p = u3h_v3_new_cache(u3C.per_w); + + fprintf(stderr, "loom: memoization migration done\r\n"); +} diff --git a/pkg/noun/v3/manage.h b/pkg/noun/v3/manage.h new file mode 100644 index 0000000000..5745a6316b --- /dev/null +++ b/pkg/noun/v3/manage.h @@ -0,0 +1,13 @@ +/// @file + +#ifndef U3_MANAGE_V3_H +#define U3_MANAGE_V3_H + + /** System management. + **/ + /* u3m_v3_migrate: perform memoization loom migration if necessary. + */ + void + u3m_v3_migrate(); + +#endif /* ifndef U3_MANAGE_V3_H */ diff --git a/pkg/noun/v3/vortex.c b/pkg/noun/v3/vortex.c new file mode 100644 index 0000000000..7f2a9e6569 --- /dev/null +++ b/pkg/noun/v3/vortex.c @@ -0,0 +1,5 @@ +/// @file + +#include "pkg/noun/v3/vortex.h" + +u3v_v3_home* u3v_v3_Home; diff --git a/pkg/noun/v3/vortex.h b/pkg/noun/v3/vortex.h new file mode 100644 index 0000000000..58443a79a3 --- /dev/null +++ b/pkg/noun/v3/vortex.h @@ -0,0 +1,35 @@ +/// @file + +#ifndef U3_VORTEX_V3_H +#define U3_VORTEX_V3_H + +#include "pkg/noun/vortex.h" + +#include "pkg/noun/v3/allocate.h" +#include "pkg/noun/version.h" + + /** Aliases. + **/ +# define u3v_v3_arvo u3v_arvo +# define u3H_v3 u3v_Home +# define u3A_v3 (&(u3H_v3)->arv_u) + + /** Data structures. + **/ + /* u3v_v3_home: all internal (within image) state. + ** NB: version must be last for discriminability in north road + */ + typedef struct _u3v_v3_home { + u3a_v3_road rod_u; // storage state + u3v_v3_arvo arv_u; // arvo state + u3v_version ver_w; // version number + } u3v_v3_home; + + /** Functions. + **/ + /* u3v_v3_rewrite_compact(): rewrite arvo kernel for compaction. + */ + void + u3v_v3_rewrite_compact(); + +#endif /* ifndef U3_VORTEX_V3_H */ diff --git a/pkg/noun/version.h b/pkg/noun/version.h index f64d0a398e..bc81c83f5a 100644 --- a/pkg/noun/version.h +++ b/pkg/noun/version.h @@ -8,7 +8,8 @@ typedef c3_w u3v_version; #define U3V_VER1 1 #define U3V_VER2 2 -#define U3V_VERLAT U3V_VER2 +#define U3V_VER3 3 +#define U3V_VERLAT U3V_VER3 /* EVENTS */ diff --git a/pkg/noun/zave.c b/pkg/noun/zave.c index 0955af906c..596200f887 100644 --- a/pkg/noun/zave.c +++ b/pkg/noun/zave.c @@ -5,6 +5,7 @@ #include "allocate.h" #include "hashtable.h" #include "imprison.h" +#include "vortex.h" /* u3z_key(): construct a memo cache-key. Arguments retained. */ @@ -34,30 +35,60 @@ u3z_key_5(c3_m fun, u3_noun one, u3_noun two, u3_noun tri, u3_noun qua, u3_noun return u3nc(fun, u3nq(u3k(one), u3k(two), u3k(tri), u3nc(u3k(qua), u3k(qin)))); } +/* _har(): get the memo cache for the given cid. +*/ +static u3p(u3h_root) +_har(u3a_road* rod_u, u3z_cid cid) +{ + switch ( cid ) { + case u3z_memo_toss: + return rod_u->cax.har_p; + case u3z_memo_keep: + return rod_u->cax.per_p; + } + u3_assert(0); +} + /* u3z_find(): find in memo cache. Arguments retained. */ u3_weak -u3z_find(u3_noun key) +u3z_find(u3z_cid cid, u3_noun key) { - return u3h_get(u3R->cax.har_p, key); + if ( u3z_memo_toss == cid ) { + return u3h_get(_har(u3R, cid), key); + } + else { + // XX needs to be benchmarked (up vs. down search) + u3a_road* rod_u = &(u3H->rod_u); + while ( 1 ) { + u3_weak got = u3h_get(_har(rod_u, cid), key); + if ( u3_none != got ) { + return got; + } + if ( 0 == rod_u->kid_p ) { + return u3_none; + } + rod_u = u3to(u3a_road, rod_u->kid_p); + }; + } } u3_weak -u3z_find_m(c3_m fun, u3_noun one) +u3z_find_m(u3z_cid cid, c3_m fun, u3_noun one) { u3_noun key = u3nc(fun, u3k(one)); u3_weak val; - - val = u3h_get(u3R->cax.har_p, key); + val = u3z_find(cid, key); u3z(key); + return val; } /* u3z_save(): save in memo cache. TRANSFER key; RETAIN val */ u3_noun -u3z_save(u3_noun key, u3_noun val) +u3z_save(u3z_cid cid, u3_noun key, u3_noun val) { - u3h_put(u3R->cax.har_p, key, u3k(val)); + u3h_put(_har(u3R, cid), key, u3k(val)); u3z(key); return val; } @@ -65,28 +96,39 @@ u3z_save(u3_noun key, u3_noun val) /* u3z_save_m(): save in memo cache. Arguments retained. */ u3_noun -u3z_save_m(c3_m fun, u3_noun one, u3_noun val) +u3z_save_m(u3z_cid cid, c3_m fun, u3_noun one, u3_noun val) { u3_noun key = u3nc(fun, u3k(one)); - u3h_put(u3R->cax.har_p, key, u3k(val)); + u3h_put(_har(u3R, cid), key, u3k(val)); u3z(key); return val; } -/* u3z_uniq(): uniquify with memo cache. +/* u3z_uniq(): uniquify with memo cache. XX not used. */ u3_noun -u3z_uniq(u3_noun som) +u3z_uniq(u3z_cid cid, u3_noun som) { u3_noun key = u3nc(c3__uniq, u3k(som)); - u3_noun val = u3h_get(u3R->cax.har_p, key); + u3_noun val = u3h_get(_har(u3R, cid), key); if ( u3_none != val ) { u3z(key); u3z(som); return val; } else { - u3h_put(u3R->cax.har_p, key, u3k(som)); + u3h_put(_har(u3R, cid), key, u3k(som)); return som; } } + +/* u3z_reap(): promote memoization cache state. +*/ +void +u3z_reap(u3z_cid cid, u3p(u3h_root) har_p) +{ + u3_assert(u3z_memo_toss != cid); + + u3h_uni(_har(u3R, cid), har_p); + u3h_free(har_p); +} diff --git a/pkg/noun/zave.h b/pkg/noun/zave.h index 44f272da7c..feff83f664 100644 --- a/pkg/noun/zave.h +++ b/pkg/noun/zave.h @@ -12,10 +12,18 @@ *** and a noun argument to that (logical) function. Functions *** are predefined by C-level callers, but 0 means nock. *** - *** The memo cache is within its road and dies when it falls. - *** *** Memo functions RETAIN keys and transfer values. **/ + /* u3z_cid: cache id + */ + typedef enum { + u3z_memo_toss = 0, + u3z_memo_keep = 1, + // u3z_memo_ford = 2, + // u3z_memo_ames = 3, + // ... + } u3z_cid; + /* u3z_key*(): construct a memo cache-key. Arguments retained. */ u3_noun u3z_key(c3_m, u3_noun); @@ -26,20 +34,35 @@ /* u3z_find*(): find in memo cache. Arguments retained */ - u3_weak u3z_find(u3_noun key); - u3_weak u3z_find_m(c3_m fun_m, u3_noun one); + u3_weak u3z_find(u3z_cid cid, u3_noun key); + u3_weak u3z_find_m(u3z_cid cid, c3_m fun_m, u3_noun one); /* u3z_save(): save in memo cache. TRANSFER key; RETAIN val; */ - u3_noun u3z_save(u3_noun key, u3_noun val); + u3_noun u3z_save(u3z_cid cid, u3_noun key, u3_noun val); /* u3z_save_m(): save in memo cache. Arguments retained */ - u3_noun u3z_save_m(c3_m fun_m, u3_noun one, u3_noun val); + u3_noun u3z_save_m(u3z_cid cid, c3_m fun_m, u3_noun one, u3_noun val); /* u3z_uniq(): uniquify with memo cache. */ u3_noun - u3z_uniq(u3_noun som); + u3z_uniq(u3z_cid cid, u3_noun som); + + /* u3z_reap(): promote memoization cache state. + */ + void + u3z_reap(u3z_cid cid, u3p(u3h_root) har_p); + + /* u3z_free(): free memoization cache. + */ + void + u3z_free(u3z_cid cid); + + /* u3z_ream(): refresh after restoring from checkpoint. + */ + void + u3z_ream(u3z_cid cid); #endif /* ifndef U3_ZAVE_H */ diff --git a/pkg/vere/BUILD.bazel b/pkg/vere/BUILD.bazel index 76f8b47eca..f856ce0047 100644 --- a/pkg/vere/BUILD.bazel +++ b/pkg/vere/BUILD.bazel @@ -301,7 +301,7 @@ genrule( if check && sleep 10 && check; then echo "boot success" - lensa hood "+hood/exit" + lensa hood '+hood/exit' while [ -f ./pier/.vere.lock ]; do echo "waiting for pier to shut down" sleep 5 diff --git a/pkg/vere/lord.c b/pkg/vere/lord.c index cf1dfcfba9..a63824ae9b 100644 --- a/pkg/vere/lord.c +++ b/pkg/vere/lord.c @@ -1160,10 +1160,11 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) // spawn new process and connect to it // { - c3_c* arg_c[11]; + c3_c* arg_c[12]; c3_c key_c[256]; c3_c wag_c[11]; c3_c hap_c[11]; + c3_c per_c[11]; c3_c cev_c[11]; c3_c lom_c[11]; c3_c tos_c[11]; @@ -1179,6 +1180,8 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) sprintf(hap_c, "%u", u3_Host.ops_u.hap_w); + sprintf(per_c, "%u", u3_Host.ops_u.per_w); + sprintf(lom_c, "%u", u3_Host.ops_u.lom_y); sprintf(tos_c, "%u", u3C.tos_w); @@ -1208,7 +1211,8 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) } arg_c[9] = tos_c; - arg_c[10] = NULL; + arg_c[10] = per_c; + arg_c[11] = NULL; uv_pipe_init(u3L, &god_u->inn_u.pyp_u, 0); uv_timer_init(u3L, &god_u->out_u.tim_u); diff --git a/pkg/vere/main.c b/pkg/vere/main.c index f83d656e98..c35b7ff2e4 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -183,6 +183,9 @@ _main_init(void) u3_Host.ops_u.veb = c3n; u3_Host.ops_u.puf_c = "jam"; u3_Host.ops_u.hap_w = 50000; + u3C.hap_w = u3_Host.ops_u.hap_w; + u3_Host.ops_u.per_w = 50000; + u3C.per_w = u3_Host.ops_u.per_w; u3_Host.ops_u.kno_w = DefaultKernel; u3_Host.ops_u.sap_w = 120; /* aka 2 minutes */ @@ -247,6 +250,7 @@ _main_getopt(c3_i argc, c3_c** argv) { "loom", required_argument, NULL, c3__loom }, { "local", no_argument, NULL, 'L' }, { "lite-boot", no_argument, NULL, 'l' }, + { "keep-cache-limit", required_argument, NULL, 'M' }, { "replay-to", required_argument, NULL, 'n' }, { "profile", no_argument, NULL, 'P' }, { "ames-port", required_argument, NULL, 'p' }, @@ -279,7 +283,7 @@ _main_getopt(c3_i argc, c3_c** argv) }; while ( -1 != (ch_i=getopt_long(argc, argv, - "A:B:C:DF:G:H:I:J:K:LPRSX:Y:Z:ab:c:de:gi:jk:ln:p:qr:stu:vw:x", + "A:B:C:DF:G:H:I:J:K:LM:PRSX:Y:Z:ab:c:de:gi:jk:ln:p:qr:stu:vw:x", lop_u, &lid_i)) ) { switch ( ch_i ) { @@ -342,7 +346,7 @@ _main_getopt(c3_i argc, c3_c** argv) return c3n; } else { u3_Host.ops_u.sap_w = arg_w * 60; - if ( 0 == u3_Host.ops_u.sap_w) + if ( 0 == u3_Host.ops_u.sap_w ) return c3n; } break; @@ -365,6 +369,7 @@ _main_getopt(c3_i argc, c3_c** argv) if ( c3n == _main_readw(optarg, 1000000000, &u3_Host.ops_u.hap_w) ) { return c3n; } + u3C.hap_w = u3_Host.ops_u.hap_w; break; } case 'c': { @@ -412,6 +417,13 @@ _main_getopt(c3_i argc, c3_c** argv) u3_Host.ops_u.key_c = _main_repath(optarg); break; } + case 'M': { + if ( c3n == _main_readw(optarg, 1000000000, &u3_Host.ops_u.per_w) ) { + return c3n; + } + u3C.per_w = u3_Host.ops_u.per_w; + break; + } case 'n': { u3_Host.ops_u.til_c = strdup(optarg); break; @@ -764,6 +776,7 @@ u3_ve_usage(c3_i argc, c3_c** argv) "-L, --local Local networking only\n", " --loom Set loom to binary exponent (31 == 2GB)\n" "-l, --lite-boot Most-minimal startup\n", + "-M, --keep-cache-limit LIMIT Set persistent memo cache max size; 0 means default\n", "-n, --replay-to NUMBER Replay up to event\n", "-P, --profile Profiling\n", "-p, --ames-port PORT Set the ames port to bind to\n", @@ -1075,6 +1088,8 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) exit(1); } + // XX use named arguments and getopt + c3_d eve_d = 0; uv_loop_t* lup_u = u3_Host.lup_u = uv_default_loop(); c3_c* dir_c = argv[2]; @@ -1086,6 +1101,7 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) c3_c* eve_c = argv[7]; c3_c* eph_c = argv[8]; c3_c* tos_c = argv[9]; + c3_c* per_c = argv[10]; c3_w tos_w; _cw_init_io(lup_u); @@ -1110,7 +1126,8 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) // XX check return // sscanf(wag_c, "%" SCNu32, &u3C.wag_w); - sscanf(hap_c, "%" SCNu32, &u3_Host.ops_u.hap_w); + sscanf(hap_c, "%" SCNu32, &u3C.hap_w); + sscanf(per_c, "%" SCNu32, &u3C.per_w); sscanf(lom_c, "%" SCNu32, &lom_w); if ( 1 != sscanf(tos_c, "%" SCNu32, &u3C.tos_w) ) { diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 1e39d14ef4..8e54dbb37e 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -675,8 +675,8 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 412 -#define VERE_LULL 323 +#define VERE_ZUSE 411 +#define VERE_LULL 322 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index cef16810b6..2bf976c1dd 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -263,7 +263,7 @@ c3_o abo; // -a, abort aggressively c3_c* pil_c; // -B, bootstrap from c3_c* bin_c; // -b, http server bind ip - c3_w hap_w; // -C, cap memo cache + c3_w hap_w; // -C, cap transient memo cache c3_o dry; // -D, dry compute, no checkpoint c3_o dem; // -d, daemon c3_c* eth_c; // -e, ethereum node url @@ -281,6 +281,7 @@ c3_o lit; // -l, lite mode c3_y lom_y; // loom bex c3_y lut_y; // urth-loom bex + c3_w per_w; // -M, cap persistent memo cache c3_c* til_c; // -n, play till eve_d c3_o pro; // -P, profile c3_s per_s; // http port