From 03763e48177b0098961130f6d0e30aa174fc601c Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Mon, 2 Apr 2018 14:08:28 -0700 Subject: [PATCH] fix profiling leaks --- include/noun/hashtable.h | 10 ++++++++- noun/hashtable.c | 39 +++++++++++++++++++++++++--------- noun/nock.c | 46 ++++++++++++++++++++++++++-------------- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/include/noun/hashtable.h b/include/noun/hashtable.h index 93c34f4871..127514afd3 100644 --- a/include/noun/hashtable.h +++ b/include/noun/hashtable.h @@ -141,7 +141,15 @@ c3_w u3h_mark(u3p(u3h_root) har_p); - /* u3h_walk(): traverse hashtable with key, value fn; RETAINS. + /* u3h_walk_with(): traverse hashtable with key, value fn and data + * argument; RETAINS. + */ + void + u3h_walk_with(u3p(u3h_root) har_p, + void (*fun_f)(u3_noun, void*), + void* wit); + + /* u3h_walk(): u3h_walk_with, but with no data argument */ void u3h_walk(u3p(u3h_root) har_p, void (*fun_f)(u3_noun)); diff --git a/noun/hashtable.c b/noun/hashtable.c index 410119f7f0..c54dc31365 100644 --- a/noun/hashtable.c +++ b/noun/hashtable.c @@ -767,19 +767,19 @@ u3h_free(u3p(u3h_root) har_p) /* _ch_walk_buck(): walk bucket for gc. */ static void -_ch_walk_buck(u3h_buck* hab_u, void (*fun_f)(u3_noun)) +_ch_walk_buck(u3h_buck* hab_u, void (*fun_f)(u3_noun, void*), void* wit) { c3_w i_w; for ( i_w = 0; i_w < hab_u->len_w; i_w++ ) { - fun_f(u3h_slot_to_noun(hab_u->sot_w[i_w])); + fun_f(u3h_slot_to_noun(hab_u->sot_w[i_w]), wit); } } /* _ch_walk_node(): walk node for gc. */ static void -_ch_walk_node(u3h_node* han_u, c3_w lef_w, void (*fun_f)(u3_noun)) +_ch_walk_node(u3h_node* han_u, c3_w lef_w, void (*fun_f)(u3_noun, void*), void* wit) { c3_w len_w = _ch_popcount(han_u->map_w); c3_w i_w; @@ -792,24 +792,27 @@ _ch_walk_node(u3h_node* han_u, c3_w lef_w, void (*fun_f)(u3_noun)) if ( _(u3h_slot_is_noun(sot_w)) ) { u3_noun kev = u3h_slot_to_noun(sot_w); - fun_f(kev); + fun_f(kev, wit); } else { void* hav_v = u3h_slot_to_node(sot_w); if ( 0 == lef_w ) { - _ch_walk_buck(hav_v, fun_f); + _ch_walk_buck(hav_v, fun_f, wit); } else { - _ch_walk_node(hav_v, lef_w, fun_f); + _ch_walk_node(hav_v, lef_w, fun_f, wit); } } } } -/* u3h_walk(): walk hashtable for gc. +/* u3h_walk_with(): traverse hashtable with key, value fn and data + * argument; RETAINS. */ void -u3h_walk(u3p(u3h_root) har_p, void (*fun_f)(u3_noun)) +u3h_walk_with(u3p(u3h_root) har_p, + void (*fun_f)(u3_noun, void*), + void* wit) { u3h_root* har_u = u3to(u3h_root, har_p); c3_w i_w; @@ -820,16 +823,32 @@ u3h_walk(u3p(u3h_root) har_p, void (*fun_f)(u3_noun)) if ( _(u3h_slot_is_noun(sot_w)) ) { u3_noun kev = u3h_slot_to_noun(sot_w); - fun_f(kev); + fun_f(kev, wit); } else if ( _(u3h_slot_is_node(sot_w)) ) { u3h_node* han_u = u3h_slot_to_node(sot_w); - _ch_walk_node(han_u, 25, fun_f); + _ch_walk_node(han_u, 25, fun_f, wit); } } } +/* _ch_walk_plain(): use plain u3_noun fun_f for each node + */ +static void +_ch_walk_plain(u3_noun kev, void* wit) +{ + void (*fun_f)(u3_noun) = wit; + fun_f(kev); +} + +/* u3h_walk(): u3h_walk_with, but with no data argument +*/ +void +u3h_walk(u3p(u3h_root) har_p, void (*fun_f)(u3_noun)) +{ + u3h_walk_with(har_p, _ch_walk_plain, fun_f); +} /* _ch_mark_buck(): mark bucket for gc. */ diff --git a/noun/nock.c b/noun/nock.c index ac562baf15..d083f7f786 100644 --- a/noun/nock.c +++ b/noun/nock.c @@ -1153,13 +1153,23 @@ _n_bite(u3_noun fol) static inline c3_y* _n_find(u3_noun fol) { + /* check on the home road first. not only is this likely to be faster, it + * protects us from things which compile bytecode on the home road + * mid-computation (like u3t_samp()) + */ u3a_road* rod_u = u3R; + u3a_road* hom_u = &(u3H->rod_u); + u3_weak byc = u3h_gut(hom_u->byc.har_p, fol); - while ( 1 ) { - u3_weak jaw = u3h_gut(rod_u->byc.har_p, fol); + if ( u3_none != byc ) { + return u3a_into(byc); + } - if ( u3_none != jaw ) { - return u3a_into(jaw); + while ( rod_u != hom_u ) { + byc = u3h_gut(rod_u->byc.har_p, fol); + + if ( u3_none != byc ) { + return u3a_into(byc); } if ( rod_u->par_p ) { @@ -1894,10 +1904,15 @@ _n_reap(u3_noun kev) u3_noun fol = u3h(kev); u3_noun got = u3t(kev); u3_noun lof = u3a_take(fol); - c3_y* pog = u3a_into(got); - c3_y* gop = _n_take_byc(pog); - u3_noun tog = u3a_outa(gop); - u3h_put(u3R->byc.har_p, lof, tog); + u3_weak con = u3h_get(u3R->byc.har_p, lof); + // u3t_samp() etc. can interrupt us while we're compiling + // so we need to avoid leaking any parent bytecode + if ( u3_none == con ) { + c3_y* pog = u3a_into(got); + c3_y* gop = _n_take_byc(pog); + u3_noun tog = u3a_outa(gop); + u3h_put(u3R->byc.har_p, lof, tog); + } u3z(lof); } @@ -1950,15 +1965,14 @@ _n_mark_byc(c3_y* pog) return tot_w; } -static c3_w bam_w; - -/* _n_bam(): u3h_walk helper for u3n_bark +/* _n_bam(): u3h_walk_with helper for u3n_bark */ static void -_n_bam(u3_noun kev) +_n_bam(u3_noun kev, void* dat) { - c3_y* pog = u3a_into(u3t(kev)); - bam_w += _n_mark_byc(pog); + c3_w* bam_w = dat; + c3_y* pog = u3a_into(u3t(kev)); + *bam_w += _n_mark_byc(pog); } /* u3n_bark(): mark the bytecode cache for gc. @@ -1966,9 +1980,9 @@ _n_bam(u3_noun kev) c3_w u3n_bark() { + c3_w bam_w = 0; u3p(u3h_root) har_p = u3R->byc.har_p; - bam_w = 0; - u3h_walk(har_p, _n_bam); + u3h_walk_with(har_p, _n_bam, &bam_w); return bam_w + u3h_mark(har_p); }