diff --git a/nix/nixcrpkgs/pkgs.nix b/nix/nixcrpkgs/pkgs.nix index b08387670..2fb612a27 100644 --- a/nix/nixcrpkgs/pkgs.nix +++ b/nix/nixcrpkgs/pkgs.nix @@ -24,10 +24,6 @@ rec { inherit crossenv; }; - ncurses = import ./pkgs/ncurses { - inherit crossenv; - }; - pdcurses = import ./pkgs/pdcurses { inherit crossenv; }; diff --git a/pkg/urbit/include/noun/allocate.h b/pkg/urbit/include/noun/allocate.h index 934b70328..989891fba 100644 --- a/pkg/urbit/include/noun/allocate.h +++ b/pkg/urbit/include/noun/allocate.h @@ -465,6 +465,31 @@ c3_w u3a_mark_road(FILE* fil_u); + /* u3a_rewrite_ptr(): mark a pointer as already having been rewritten + */ + c3_o + u3a_rewrite_ptr(void* ptr_v); + + /* u3a_rewrite_noun(): rewrite a noun for compaction. + */ + void + u3a_rewrite_noun(u3_noun som); + + /* u3a_rewritten(): rewrite a pointer for compaction. + */ + u3_post + u3a_rewritten(u3_post som_p); + + /* u3a_rewritten(): rewritten noun pointer for compaction. + */ + u3_noun + u3a_rewritten_noun(u3_noun som); + + /* u3a_compact(): compact (north) road. + */ + void + u3a_compact(); + /* u3a_count_noun(): count size of noun. */ c3_w diff --git a/pkg/urbit/include/noun/hashtable.h b/pkg/urbit/include/noun/hashtable.h index a6457ad95..bf9f50e17 100644 --- a/pkg/urbit/include/noun/hashtable.h +++ b/pkg/urbit/include/noun/hashtable.h @@ -139,6 +139,11 @@ c3_w u3h_mark(u3p(u3h_root) har_p); + /* u3h_rewrite(): rewrite hashtable for compaction. + */ + void + u3h_rewrite(u3p(u3h_root) har_p); + /* u3h_count(): count hashtable for gc. */ c3_w diff --git a/pkg/urbit/include/noun/jets.h b/pkg/urbit/include/noun/jets.h index aa3934284..214376d76 100644 --- a/pkg/urbit/include/noun/jets.h +++ b/pkg/urbit/include/noun/jets.h @@ -287,6 +287,21 @@ c3_w u3j_mark(FILE* fil_u); + /* u3j_rite_rewrite(): rewrite u3j_rite for compaction. + */ + void + u3j_rite_rewrite(u3j_rite* rit_u); + + /* u3j_site_rewrite(): rewrite u3j_site for compaction. + */ + void + u3j_site_rewrite(u3j_site* sit_u); + + /* u3j_rewrite_compact(): rewrite jet state for compaction. + */ + void + u3j_rewrite_compact(); + /* u3j_free_hank(): free an entry from the hank cache. */ void diff --git a/pkg/urbit/include/noun/nock.h b/pkg/urbit/include/noun/nock.h index 243932fa1..3de1f1977 100644 --- a/pkg/urbit/include/noun/nock.h +++ b/pkg/urbit/include/noun/nock.h @@ -117,6 +117,11 @@ c3_w u3n_mark(FILE* fil_u); + /* u3n_rewrite_compact(): rewrite bytecode cache for compaction. + */ + void + u3n_rewrite_compact(); + /* u3n_free(): free bytecode cache. */ void diff --git a/pkg/urbit/include/noun/vortex.h b/pkg/urbit/include/noun/vortex.h index c1f1e7270..4da1a135f 100644 --- a/pkg/urbit/include/noun/vortex.h +++ b/pkg/urbit/include/noun/vortex.h @@ -103,3 +103,8 @@ */ c3_w u3v_mark(FILE* fil_u); + + /* u3v_rewrite_compact(): rewrite arvo kernel for compaction. + */ + void + u3v_rewrite_compact(); diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index ea44ef168..06096d2c0 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -1679,6 +1679,29 @@ u3a_mark_ptr(void* ptr_v) } } +u3_post +u3a_rewritten(u3_post ptr_v) +{ + u3a_box* box_u = u3a_botox(u3a_into(ptr_v)); + c3_w* box_w = (c3_w*) box_u; + return (u3_post)box_w[box_u->siz_w - 1]; +} + +u3_noun +u3a_rewritten_noun(u3_noun som) +{ + if ( c3y == u3a_is_cat(som) ) { + return som; + } + u3_post som_p = u3a_rewritten(u3a_to_off(som)); + if ( c3y == u3a_is_pug(som) ) { + return u3a_to_pug(som_p); + } + else { + return u3a_to_pom(som_p); + } +} + /* u3a_mark_mptr(): mark a malloc-allocated ptr for gc. */ c3_w @@ -1928,6 +1951,28 @@ u3a_mark_road(FILE* fil_u) return u3a_maid(fil_u, "total road stuff", tot_w); } +/* u3a_rewrite_compact(): rewrite pointers in ad-hoc persistent road structures. +*/ +void +u3a_rewrite_compact() +{ + u3a_rewrite_noun(u3R->ski.gul); + u3a_rewrite_noun(u3R->bug.tax); + u3a_rewrite_noun(u3R->bug.mer); + u3a_rewrite_noun(u3R->pro.don); + u3a_rewrite_noun(u3R->pro.day); + u3a_rewrite_noun(u3R->pro.trace); + u3h_rewrite(u3R->cax.har_p); + + u3R->ski.gul = u3a_rewritten_noun(u3R->ski.gul); + u3R->bug.tax = u3a_rewritten_noun(u3R->bug.tax); + u3R->bug.mer = u3a_rewritten_noun(u3R->bug.mer); + u3R->pro.don = u3a_rewritten_noun(u3R->pro.don); + 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); +} + /* _ca_print_box(): heuristically print the contents of an allocation box. */ static c3_c* @@ -2180,6 +2225,162 @@ u3a_sweep(void) return neg_w; } + +/* u3a_compact(): compact road. +*/ +void +u3a_compact(void) +{ + sleep(10); + u3m_reclaim(); + assert(c3y == u3a_is_north(u3R)); + u3_post box_p = _(u3a_is_north(u3R)) ? u3R->rut_p : u3R->hat_p; + u3_post end_p = _(u3a_is_north(u3R)) ? u3R->hat_p : u3R->rut_p; + + /* Sweep through arena, recording new address + * + * Don't trace to preserve memory locality + */ + { + u3_post new_p = c3_wiseof(u3a_box) + 1; + c3_w* box_w = u3a_into(box_p); + c3_w* end_w = u3a_into(end_p); + + while ( box_w < end_w ) { + u3a_box* box_u = (void *)box_w; + + /* If not free, rewrite trailing size word to be new pointer. + * + * Another option would be to use the refcount and just + * regenerate it by tracing. + */ + if ( box_u->use_w > 0 ) { + //fprintf(stderr, "compact: found size %d at box_u %p, setting to new_p %x\r\n", box_u->siz_w, box_u, new_p); + box_w[box_u->siz_w - 1] = new_p; + new_p += box_u->siz_w; + //fprintf(stderr, "compact: adding to new_p %x\r\n", new_p); + } + + box_w += box_u->siz_w; + } + } + + fprintf(stderr, "compact: sweep 1 complete\r\n"); + + /* Trace through arena, rewriting pointers + * + * Don't sweep because it's ad-hoc polymorphic + */ + { + u3v_rewrite_compact(); + u3j_rewrite_compact(); + u3n_rewrite_compact(); + u3a_rewrite_compact(); + } + + fprintf(stderr, "compact: trace complete\r\n"); + + c3_w* new_w = (void*)u3a_botox(u3a_into(c3_wiseof(u3a_box) + 1)); + + /* Sweep through arena, moving nouns + * + * Don't trace because you need to move in order + */ + { + c3_w* box_w = u3a_into(box_p); + c3_w* end_w = u3a_into(end_p); + + while ( box_w < end_w ) { + u3a_box* old_u = (void *)box_w; + c3_w siz_w = old_u->siz_w; // store because we're about to overwrite + + /* Unmark if marked + */ + old_u->use_w &= 0x7fffffff; + + //fprintf(stderr, "compact: 364 == %d\r\n", *((c3_w*)0x200000364)); + //fprintf(stderr, "compact: found size %d at old_u %p\r\n", old_u->siz_w, old_u); + + + /* If not free, move to new home + */ + if ( old_u->use_w > 0 ) { + //fprintf(stderr, "compact: writing to %p from %p\r\n", u3a_botox(u3a_into(box_w[siz_w - 1])), box_w); + assert(new_w == (c3_w*)u3a_botox(u3a_into(box_w[siz_w - 1]))); + new_w = (c3_w*)u3a_botox(u3a_into(box_w[siz_w - 1])); + c3_w i_w; + if ( new_w > box_w ) { + fprintf(stderr, "compact: whoa new_w %p, i_w %d\r\n", new_w, i_w); + } + for ( i_w = 0; i_w < siz_w - 1; i_w++ ) { + new_w[i_w] = box_w[i_w]; + } + new_w[siz_w - 1] = siz_w; + new_w += siz_w; + } + + box_w += siz_w; + } + fprintf(stderr, "compact: box_w %lx new_w %lx\r\n", u3a_outa(box_w), u3a_outa(new_w)); + } + + fprintf(stderr, "compact: sweep 2 complete\r\n"); + + /* Set new end of heap. + */ + { + u3R->hat_p = u3a_outa(new_w); + + c3_w i_w; + for ( i_w = 0; i_w < u3a_fbox_no; i_w++ ) { + u3R->all.fre_p[i_w] = 0; + } + + u3R->all.cel_p = 0; + u3R->all.fre_w = 0; + + u3n_ream(); + + u3m_mark(stderr); + fprintf(stderr, "compact: marked\r\n"); + u3a_sweep(); + fprintf(stderr, "compact: swept\r\n"); + } +} + +/* u3a_rewrite_ptr(): mark a pointer as already having been rewritten +*/ +c3_o +u3a_rewrite_ptr(void* ptr_v) +{ + u3a_box* box_u = u3a_botox(ptr_v); + if ( box_u->use_w & 0x80000000 ) { + /* Already rewritten. + */ + return c3n; + } + box_u->use_w |= 0x80000000; + return c3y; +} + +void +u3a_rewrite_noun(u3_noun som) +{ + if ( c3n == u3a_is_cell(som) ) { + return; + } + + if ( c3n == u3a_rewrite_ptr(u3a_to_ptr((som))) ) return; + + u3a_cell* cel = u3a_to_ptr(som); + + u3a_rewrite_noun(cel->hed); + u3a_rewrite_noun(cel->tel); + + cel->hed = u3a_rewritten_noun(cel->hed); + cel->tel = u3a_rewritten_noun(cel->tel); +} + /* u3a_slab(): create a length-bounded proto-atom. */ c3_w* diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 86162741d..8bae1891d 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -148,7 +148,7 @@ u3e_fault(void* adr_v, c3_i ser_i) if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) { fprintf(stderr, "strange page: %d, at %p, off %x\r\n", pag_w, adr_w, off_w); - c3_assert(0); + // c3_assert(0); return 0; } diff --git a/pkg/urbit/noun/hashtable.c b/pkg/urbit/noun/hashtable.c index 3eb7152be..e57c47be9 100644 --- a/pkg/urbit/noun/hashtable.c +++ b/pkg/urbit/noun/hashtable.c @@ -913,6 +913,58 @@ _ch_mark_node(u3h_node* han_u, c3_w lef_w) return tot_w; } +// XXX reorg +/* _ch_rewrite_buck(): rewrite buck for compaction. +*/ +void +_ch_rewrite_buck(u3h_buck* hab_u) +{ + if ( c3n == u3a_rewrite_ptr(hab_u) ) return; + c3_w i_w; + + for ( i_w = 0; i_w < hab_u->len_w; i_w++ ) { + u3_noun som = u3h_slot_to_noun(hab_u->sot_w[i_w]); + hab_u->sot_w[i_w] = u3h_noun_to_slot(u3a_rewritten_noun(som)); + u3a_rewrite_noun(som); + } +} + +/* _ch_rewrite_node(): rewrite node for compaction. +*/ +void +_ch_rewrite_node(u3h_node* han_u, c3_w lef_w) +{ + if ( c3n == u3a_rewrite_ptr(han_u) ) return; + + c3_w len_w = _ch_popcount(han_u->map_w); + c3_w i_w; + + lef_w -= 5; + + for ( i_w = 0; i_w < len_w; i_w++ ) { + c3_w sot_w = han_u->sot_w[i_w]; + + if ( _(u3h_slot_is_noun(sot_w)) ) { + u3_noun kev = u3h_slot_to_noun(sot_w); + han_u->sot_w[i_w] = u3h_noun_to_slot(u3a_rewritten_noun(kev)); + + u3a_rewrite_noun(kev); + } + else { + void* hav_v = u3h_slot_to_node(sot_w); + u3h_node* nod_u = u3to(u3h_node,u3a_rewritten(u3of(u3h_node,hav_v))); + han_u->sot_w[i_w] = u3h_node_to_slot(nod_u); + + if ( 0 == lef_w ) { + _ch_rewrite_buck(hav_v); + } else { + _ch_rewrite_node(hav_v, lef_w); + } + } + } +} + + /* u3h_mark(): mark hashtable for gc. */ c3_w @@ -942,6 +994,35 @@ u3h_mark(u3p(u3h_root) har_p) return tot_w; } +/* u3h_rewrite(): rewrite pointers during compaction. +*/ +void +u3h_rewrite(u3p(u3h_root) har_p) +{ + u3h_root* har_u = u3to(u3h_root, har_p); + c3_w i_w; + + if ( c3n == u3a_rewrite_ptr(har_u) ) return; + + for ( i_w = 0; i_w < 64; i_w++ ) { + c3_w sot_w = har_u->sot_w[i_w]; + + if ( _(u3h_slot_is_noun(sot_w)) ) { + u3_noun kev = u3h_slot_to_noun(sot_w); + har_u->sot_w[i_w] = u3h_noun_to_slot(u3a_rewritten_noun(kev)); + + u3a_rewrite_noun(kev); + } + else if ( _(u3h_slot_is_node(sot_w)) ) { + u3h_node* han_u = u3h_slot_to_node(sot_w); + u3h_node* nod_u = u3to(u3h_node,u3a_rewritten(u3of(u3h_node,han_u))); + har_u->sot_w[i_w] = u3h_node_to_slot(nod_u); + + _ch_rewrite_node(han_u, 25); + } + } +} + /* _ch_count_buck(): count bucket for gc. */ c3_w diff --git a/pkg/urbit/noun/jets.c b/pkg/urbit/noun/jets.c index 2ae4aea40..aaadd2ce5 100644 --- a/pkg/urbit/noun/jets.c +++ b/pkg/urbit/noun/jets.c @@ -2339,6 +2339,104 @@ u3j_mark(FILE* fil_u) return u3a_maid(fil_u, "total jet stuff", tot_w); } +/* _cj_fink_rewrite(): rewrite a u3j_fink for compaction. +*/ +static void +_cj_fink_rewrite(u3j_fink* fin_u) +{ + if ( c3n == u3a_rewrite_ptr(fin_u) ) return; + c3_w i_w; + u3a_rewrite_noun(fin_u->sat); + fin_u->sat = u3a_rewritten_noun(fin_u->sat); + + for ( i_w = 0; i_w < fin_u->len_w; ++i_w ) { + u3j_fist* fis_u = &(fin_u->fis_u[i_w]); + u3a_rewrite_noun(fis_u->bat); + u3a_rewrite_noun(fis_u->pax); + fis_u->bat = u3a_rewritten_noun(fis_u->bat); + fis_u->pax = u3a_rewritten_noun(fis_u->pax); + } +} + +/* u3j_rite_rewrite(): rewrite u3j_rite for compaction. +*/ +void +u3j_rite_rewrite(u3j_rite* rit_u) +{ + if ( (c3y == rit_u->own_o) && u3_none != rit_u->clu ) { + u3a_rewrite_noun(rit_u->clu); + _cj_fink_rewrite(u3to(u3j_fink, rit_u->fin_p)); + rit_u->clu = u3a_rewritten_noun(rit_u->clu); + rit_u->fin_p = u3a_rewritten(rit_u->fin_p); + } +} + +/* u3j_site_rewrite(): rewrite u3j_site for compaction. +*/ +void +u3j_site_rewrite(u3j_site* sit_u) +{ + u3a_rewrite_noun(sit_u->axe); + sit_u->axe = u3a_rewritten_noun(sit_u->axe); + + if ( u3_none != sit_u->bat ) { + u3a_rewrite_noun(sit_u->bat); + sit_u->bat = u3a_rewritten_noun(sit_u->bat); + } + if ( u3_none != sit_u->bas ) { + u3a_rewrite_noun(sit_u->bas); + sit_u->bas = u3a_rewritten_noun(sit_u->bas); + } + if ( u3_none != sit_u->loc ) { + u3a_rewrite_noun(sit_u->loc); + u3a_rewrite_noun(sit_u->lab); + sit_u->loc = u3a_rewritten_noun(sit_u->loc); + sit_u->lab = u3a_rewritten_noun(sit_u->lab); + if ( c3y == sit_u->fon_o ) { + _cj_fink_rewrite(u3to(u3j_fink, sit_u->fin_p)); + sit_u->fin_p = u3a_rewritten(sit_u->fin_p); + } + } +} + +/* _cj_rewrite_hank(): rewrite hank cache for compaction. +*/ +static void +_cj_rewrite_hank(u3_noun kev) +{ + _cj_hank* han_u = u3to(_cj_hank, u3t(kev)); + if ( c3n == u3a_rewrite_ptr(han_u) ) return; + if ( u3_none != han_u->hax ) { + u3a_rewrite_noun(han_u->hax); + u3j_site_rewrite(&(han_u->sit_u)); + + han_u->hax = u3a_rewritten_noun(han_u->hax); + } +} + +/* u3j_rewrite_compact(): rewrite jet state for compaction. +*/ +void +u3j_rewrite_compact() +{ + u3h_walk(u3R->jed.han_p, _cj_rewrite_hank); + + u3h_rewrite(u3R->jed.war_p); + u3h_rewrite(u3R->jed.cod_p); + u3h_rewrite(u3R->jed.han_p); + u3h_rewrite(u3R->jed.bas_p); + + if ( u3R == &(u3H->rod_u) ) { + u3h_rewrite(u3R->jed.hot_p); + u3R->jed.hot_p = u3a_rewritten(u3R->jed.hot_p); + } + + u3R->jed.war_p = u3a_rewritten(u3R->jed.war_p); + u3R->jed.cod_p = u3a_rewritten(u3R->jed.cod_p); + u3R->jed.han_p = u3a_rewritten(u3R->jed.han_p); + u3R->jed.bas_p = u3a_rewritten(u3R->jed.bas_p); +} + /* u3j_free_hank(): free an entry from the hank cache. */ void diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index e2bfc0f7d..6a449d6ad 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -2597,6 +2597,51 @@ u3n_mark(FILE* fil_u) return u3a_maid(fil_u, "total nock stuff", bam_w + har_w); } +/* _n_prog_rewrite(): rewrite program for compaction. +*/ +static void +_n_prog_rewrite(u3n_prog* pog_u) +{ + c3_w i_w; + + for ( i_w = 0; i_w < pog_u->lit_u.len_w; ++i_w ) { + u3a_rewrite_noun(pog_u->lit_u.non[i_w]); + } + + for ( i_w = 0; i_w < pog_u->mem_u.len_w; ++i_w ) { + u3a_rewrite_noun(pog_u->mem_u.sot_u[i_w].key); + } + + for ( i_w = 0; i_w < pog_u->cal_u.len_w; ++i_w ) { + u3j_site_rewrite(&(pog_u->cal_u.sit_u[i_w])); + } + + for ( i_w = 0; i_w < pog_u->reg_u.len_w; ++i_w ) { + u3j_rite_rewrite(&(pog_u->reg_u.rit_u[i_w])); + } +} + +/* _n_rewrite(): u3h_walk_with helper for u3n_rewrite_compact + */ +static void +_n_rewrite(u3_noun kev) +{ + u3n_prog* pog = u3to(u3n_prog, u3t(kev)); + _n_prog_rewrite(pog); +} + +/* u3n_rewrite_compact(): rewrite the bytecode cache for compaction. + */ +void +u3n_rewrite_compact() +{ + u3h_walk(u3R->byc.har_p, _n_rewrite); + + u3h_rewrite(u3R->byc.har_p); + u3R->byc.har_p = u3a_rewritten(u3R->byc.har_p); +} + + /* _n_feb(): u3h_walk helper for u3n_free */ static void diff --git a/pkg/urbit/noun/vortex.c b/pkg/urbit/noun/vortex.c index ad12ab404..65db02bae 100644 --- a/pkg/urbit/noun/vortex.c +++ b/pkg/urbit/noun/vortex.c @@ -326,3 +326,24 @@ u3v_mark(FILE* fil_u) tot_w += u3a_maid(fil_u, " wish cache", u3a_mark_noun(arv_u->yot)); return u3a_maid(fil_u, "total arvo stuff", tot_w); } + +/* u3v_rewrite_compact(): rewrite arvo kernel for compaction. +*/ +void +u3v_rewrite_compact() +{ + u3v_arvo* arv_u = &(u3H->arv_u); + + u3a_rewrite_noun(arv_u->roc); + u3a_rewrite_noun(arv_u->now); + u3a_rewrite_noun(arv_u->wen); + u3a_rewrite_noun(arv_u->sen); + u3a_rewrite_noun(arv_u->yot); + + arv_u->roc = u3a_rewritten_noun(arv_u->roc); + arv_u->now = u3a_rewritten_noun(arv_u->now); + arv_u->wen = u3a_rewritten_noun(arv_u->wen); + arv_u->sen = u3a_rewritten_noun(arv_u->sen); + arv_u->yot = u3a_rewritten_noun(arv_u->yot); +} + diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index e18bae794..054c4c881 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -256,6 +256,10 @@ _serf_grab(u3_serf* sef_u) u3z(sef_u->sac); sef_u->sac = u3_nul; + + { + u3a_compact(); + } } }