From 73469e3383e2f335cc8a382101ac5c727f619a76 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Fri, 9 Mar 2018 10:42:04 -0800 Subject: [PATCH 1/8] remove well-intentioned equality profile breakage process sampling already takes care to turn off cpu profiling during its sampling. this "fix" for mid-equality sampling was masking another bug at an earlier point in the debugging process for the unifying equality changes. I realized upon reflection that it was incorrect. --- noun/trace.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/noun/trace.c b/noun/trace.c index ddb7410c5..1464d719b 100644 --- a/noun/trace.c +++ b/noun/trace.c @@ -361,12 +361,7 @@ u3t_damp(void) void _ct_sigaction(c3_i x_i) { // fprintf(stderr, "itimer!\r\n"); abort(); - - // sampling mid-equality can break without this - c3_o meq_o = u3T.euq_o; - u3T.euq_o = c3n; u3t_samp(); - u3T.euq_o = meq_o; } /* u3t_init(): initialize tracing layer. From 1d1593274c089306f7057180da52b62b7c7bd2f7 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Wed, 14 Mar 2018 17:53:12 -0700 Subject: [PATCH 2/8] tightening up jam jet --- jets/e/jam.c | 190 +++++++++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 80 deletions(-) diff --git a/jets/e/jam.c b/jets/e/jam.c index ec2a7c6ca..f310154d7 100644 --- a/jets/e/jam.c +++ b/jets/e/jam.c @@ -61,101 +61,131 @@ return z; } + #define JAM_NONE 0 + #define JAM_HEAD 1 + #define JAM_TAIL 2 + typedef struct { - u3_noun a; - u3_noun b; - u3_noun l; - u3_noun* r; + c3_y sat_y; + u3_noun nun; + u3_noun len; + u3_noun lis; u3_noun hed; - u3_noun tel; } jamframe; - static inline void - _jam_push(u3_noun a, u3_noun b, u3_noun l, u3_noun *r) + static inline jamframe* + _jam_push(c3_ys mov, c3_ys off) { - jamframe* fam = u3a_push(sizeof(jamframe)); - fam->a = a; - fam->b = b; - fam->l = l; - fam->r = r; - fam->hed = u3_none; - fam->tel = u3_none; - } - - static inline void - _jam_pop() - { - u3a_pop(sizeof(jamframe)); + u3R->cap_p += mov; + return u3to(jamframe, u3R->cap_p + off); } static inline jamframe* - _jam_peek() + _jam_pop(c3_ys mov, c3_ys off) { - return (jamframe*) u3a_peek(sizeof(jamframe)); + u3R->cap_p -= mov; + return u3to(jamframe, u3R->cap_p + off); } + static u3_noun + _jam_cap(u3_atom a) + { + u3p(u3h_root) har_p = u3h_new(); + c3_o nor_o = u3a_is_north(u3R); + c3_y wis_y = c3_wiseof(jamframe); + c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); + c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); + jamframe* fam = _jam_push(mov, off); + + fam->sat_y = JAM_NONE; + fam->nun = a; + fam->len = 0; + fam->lis = u3_nul; + + u3_noun q, r = u3_none; + c3_w dep_w; + + for ( dep_w = 1; dep_w > 0; ) { + switch ( fam->sat_y ) { + case JAM_NONE: { + u3_noun nun = fam->nun; + u3_noun len = fam->len; + u3_noun lis = fam->lis; + u3_weak got = u3h_get(har_p, nun); + + if ( u3_none == got ) { + u3h_put(har_p, nun, u3k(len)); + if ( c3n == u3du(nun) ) { + r = _jam_flat(nun, lis); + fam = _jam_pop(mov, off); + --dep_w; + u3z(len); + } + else { + fam->sat_y = JAM_HEAD; + fam = _jam_push(mov, off); + fam->sat_y = JAM_NONE; + fam->nun = u3h(nun); + fam->len = u3qa_add(2, len); + fam->lis = u3nc(u3nc(2, 1), lis); + ++dep_w; + } + } + else { + if ( c3y == u3ud(nun) && (u3r_met(0, nun) <= u3r_met(0, got)) ) { + r = _jam_flat(nun, lis); + } + else { + r = _jam_ptr(got, lis); + } + fam = _jam_pop(mov, off); + --dep_w; + u3z(len); + } + break; + } + case JAM_HEAD: { + u3_noun p_r, q_r, r_r; + u3x_trel(r, &p_r, &q_r, &r_r); + u3_noun nun = fam->nun; + fam->sat_y = JAM_TAIL; + fam->hed = r; + u3_noun z = u3qa_add(2, fam->len); + fam = _jam_push(mov, off); + fam->sat_y = JAM_NONE; + fam->nun = u3t(nun); + fam->len = u3qa_add(z, p_r); + fam->lis = u3k(q_r); + u3z(z); + ++dep_w; + break; + } + case JAM_TAIL: { + u3_noun len = fam->len; + r = _jam_pair(u3qa_add(2, len), fam->hed, r); + fam = _jam_pop(mov, off); + --dep_w; + u3z(len); + break; + } + default: + c3_assert(0); + return u3_none; + } + } + + q = u3qb_flop(u3h(u3t(r))); + u3z(r); + r = u3qc_can(0, q); + u3z(q); + u3h_free(har_p); + return r; + } u3_noun u3qe_jam(u3_atom a) { - u3p(u3h_root) har_p = u3h_new(); - u3p(jamframe) empty = u3R->cap_p; - jamframe* fam; - u3_noun out, c, x, q, r; - - _jam_push(a, 0, u3_nul, &out); - while ( empty != u3R->cap_p ) { - fam = _jam_peek(); - if ( u3_none != fam->tel ) { - u3_noun z = u3qa_add(2, fam->b); - x = _jam_pair(z, fam->hed, fam->tel); - } - else if ( u3_none != fam->hed ) { - u3_noun p_d, q_d, r_d; - u3x_trel(fam->hed, &p_d, &q_d, &r_d); - { - u3_noun z = u3qa_add(2, fam->b); - u3_noun y = u3qa_add(z, p_d); - _jam_push(u3t(fam->a), y, u3k(q_d), &(fam->tel)); - u3z(z); - continue; - } - } - else { - a = fam->a; - c = u3h_get(har_p, a); - if ( u3_none != c ) { - if ( (c3y == u3ud(a)) && u3r_met(0, a) <= u3r_met(0, c) ) { - x = _jam_flat(a, fam->l); - } - else { - x = _jam_ptr(c, fam->l); - } - } - else { - u3h_put(har_p, a, u3k(fam->b)); - if ( c3y == u3ud(a) ) { - x = _jam_flat(a, fam->l); - } - else { - u3_noun z = u3qa_add(2, fam->b); - u3_noun w = u3nc(u3nc(2, 1), fam->l); - _jam_push(u3h(a), z, w, &(fam->hed)); - continue; - } - } - } - *(fam->r) = x; - u3z(fam->b); - _jam_pop(); - } - - q = u3qb_flop(u3h(u3t(out))); - r = u3qc_can(0, q); - u3z(out); - u3z(q); - u3h_free(har_p); - return r; + return _jam_cap(a); } u3_noun u3we_jam(u3_noun cor) From 3c54440c82d7f12eefcb8ced08fbd43802b39660 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Thu, 15 Mar 2018 13:07:22 -0700 Subject: [PATCH 3/8] mov/off optimization for unifying equality --- noun/retrieve.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/noun/retrieve.c b/noun/retrieve.c index ea94ecf80..9d4d825fd 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -509,24 +509,21 @@ typedef struct { } eqframe; static inline eqframe* -_eq_peek() +_eq_push(c3_ys mov, c3_ys off, u3_noun a, u3_noun b) { - return (eqframe*) u3a_peek(sizeof(eqframe)); + u3R->cap_p += mov; + eqframe* cur = u3to(eqframe, u3R->cap_p + off); + cur->a = a; + cur->b = b; + cur->sat_y = 0; + return cur; } -static inline void -_eq_push(u3_noun a, u3_noun b) +static inline eqframe* +_eq_pop(c3_ys mov, c3_ys off) { - eqframe* cur = (eqframe*) u3a_push(sizeof(eqframe)); - cur->a = a; - cur->b = b; - cur->sat_y = 0; -} - -static inline void -_eq_pop() -{ - u3a_pop(sizeof(eqframe)); + u3R->cap_p -= mov; + return u3to(eqframe, u3R->cap_p + off); } /* _sing_one(): do not pick a unified pointer for identical (a) and (b). @@ -671,19 +668,22 @@ _song_atom(u3_atom a, u3_atom b) static c3_o _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) { - eqframe* fam; - u3p(eqframe) empty = u3R->cap_p; - c3_w wis_w = 0; - c3_o r_o = c3n; + u3p(eqframe) empty = u3R->cap_p; u3p(u3h_root) har_p = 0; - _eq_push(a, b); + c3_y wis_y = c3_wiseof(eqframe); + c3_o nor_o = u3a_is_north(u3R); + c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); + c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); + c3_w wis_w = 0; + c3_o r_o = c3n; + eqframe* fam = _eq_push(mov, off, a, b); + /* there's a while and a switch here. continues all mean "do the loop again" ** and breaks all mean "fall through this switch case". There are no breaks ** that early terminate the loop. */ while ( empty != u3R->cap_p ) { - fam = _eq_peek(); if ( (a = fam->a) == (b = fam->b) ) { r_o = c3y; } @@ -705,8 +705,8 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) case 1: uni(&(a_u->hed), &(b_u->hed)); - _eq_push(a_u->tel, b_u->tel); fam->sat_y = 2; + fam = _eq_push(mov, off, a_u->tel, b_u->tel); continue; case 0: { @@ -724,12 +724,12 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) u3t_on(euq_o); u3z(key); if ( u3_none != got ) { - _eq_pop(); + fam = _eq_pop(mov, off); continue; } } - _eq_push(a_u->hed, b_u->hed); fam->sat_y = 1; + fam = _eq_push(mov, off, a_u->hed, b_u->hed); continue; } } @@ -756,7 +756,7 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) u3t_on(euq_o); u3z(key); } - _eq_pop(); + fam = _eq_pop(mov, off); } } From 93d54041a9ffcfc73cc4243b7a476f7fd02db6e6 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Thu, 15 Mar 2018 15:06:53 -0700 Subject: [PATCH 4/8] tightening up unifying equality in several small ways --- noun/retrieve.c | 102 ++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/noun/retrieve.c b/noun/retrieve.c index 9d4d825fd..59eaaf09b 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -502,10 +502,14 @@ _sang_one(u3_noun* a, u3_noun* b) } } +#define SONG_NONE 0 +#define SONG_HEAD 1 +#define SONG_TAIL 2 + typedef struct { + c3_y sat_y; u3_noun a; u3_noun b; - c3_y sat_y; } eqframe; static inline eqframe* @@ -513,9 +517,9 @@ _eq_push(c3_ys mov, c3_ys off, u3_noun a, u3_noun b) { u3R->cap_p += mov; eqframe* cur = u3to(eqframe, u3R->cap_p + off); - cur->a = a; - cur->b = b; - cur->sat_y = 0; + cur->sat_y = SONG_NONE; + cur->a = a; + cur->b = b; return cur; } @@ -659,10 +663,6 @@ _song_atom(u3_atom a, u3_atom b) return c3y; } -/* knob: set lower to get more/earlier memoize-by-pointer, - * higher to avoid allocating the u3h as often */ -#define EQ_WHISTLE 1024 - /* _song_x(): yes if a and b are the same noun, use uni to unify */ static c3_o @@ -671,50 +671,39 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) u3p(eqframe) empty = u3R->cap_p; u3p(u3h_root) har_p = 0; - c3_y wis_y = c3_wiseof(eqframe); - c3_o nor_o = u3a_is_north(u3R); - c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); - c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); - c3_w wis_w = 0; - c3_o r_o = c3n; + c3_y wis_y = c3_wiseof(eqframe); + c3_o nor_o = u3a_is_north(u3R); + c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); + c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); + c3_o r_o = c3n; + c3_w ovr_w = 0; eqframe* fam = _eq_push(mov, off, a, b); + eqframe* don = u3to(eqframe, empty + off); /* there's a while and a switch here. continues all mean "do the loop again" - ** and breaks all mean "fall through this switch case". There are no breaks - ** that early terminate the loop. + ** and breaks all mean jump to end of switch. There are no breaks + ** that terminate the loop. */ - while ( empty != u3R->cap_p ) { - if ( (a = fam->a) == (b = fam->b) ) { - r_o = c3y; - } - else if ( c3y == u3a_is_atom(a) ) { - r_o = _song_atom(a, b); - } - else if ( c3y == u3a_is_atom(b) ) { - r_o = c3n; - } - else { - u3a_cell* a_u = u3a_to_ptr(a); - u3a_cell* b_u = u3a_to_ptr(b); - - switch ( fam->sat_y ) { - case 2: - uni(&(a_u->tel), &(b_u->tel)); + while ( don != fam ) { + switch ( fam->sat_y ) { + case SONG_NONE: + if ( (a = fam->a) == (b = fam->b) ) { r_o = c3y; - break; + } + else if ( c3y == u3a_is_atom(a) ) { + r_o = _song_atom(a, b); + } + else if ( c3y == u3a_is_atom(b) ) { + r_o = c3n; + } + else { + u3a_cell* a_u = u3a_to_ptr(a); + u3a_cell* b_u = u3a_to_ptr(b); - case 1: - uni(&(a_u->hed), &(b_u->hed)); - fam->sat_y = 2; - fam = _eq_push(mov, off, a_u->tel, b_u->tel); - continue; - - case 0: { if ( a_u->mug_w && b_u->mug_w && (a_u->mug_w != b_u->mug_w) ) { r_o = c3n; - break; } else { if ( har_p != 0 ) { @@ -728,14 +717,33 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) continue; } } - fam->sat_y = 1; + fam->sat_y = SONG_HEAD; fam = _eq_push(mov, off, a_u->hed, b_u->hed); continue; } } - default: - c3_assert(0); + break; + + case SONG_HEAD: { + u3a_cell* a_u = u3a_to_ptr(fam->a); + u3a_cell* b_u = u3a_to_ptr(fam->b); + uni(&(a_u->hed), &(b_u->hed)); + fam->sat_y = SONG_TAIL; + fam = _eq_push(mov, off, a_u->tel, b_u->tel); + continue; } + + case SONG_TAIL: { + u3a_cell* a_u = u3a_to_ptr(fam->a); + u3a_cell* b_u = u3a_to_ptr(fam->b); + uni(&(a_u->tel), &(b_u->tel)); + r_o = c3y; + break; + } + + default: + c3_assert(0); + break; } if ( c3n == r_o ) { @@ -746,7 +754,9 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) return c3n; } else { - if ( 0 == har_p && (wis_w++ > EQ_WHISTLE) ) { + // ovr_w counts iterations. when it overflows, we know we've hit a + // pathological case and MUST start de-duplicating comparisons. + if ( 0 == har_p && 0 == ++ovr_w ) { har_p = u3h_new(); } if ( 0 != har_p ) { From e1d724e084954fe61d3c92b7141d351d948b993d Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Thu, 15 Mar 2018 15:51:35 -0700 Subject: [PATCH 5/8] tightening down song_x even further, offloading book-keeping to a seperate helper function --- noun/retrieve.c | 197 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 67 deletions(-) diff --git a/noun/retrieve.c b/noun/retrieve.c index 59eaaf09b..028c88c30 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -663,38 +663,38 @@ _song_atom(u3_atom a, u3_atom b) return c3y; } -/* _song_x(): yes if a and b are the same noun, use uni to unify -*/ +/* _song_x_cape(): unifying equality with comparison deduplication + * (tightly coupled to _song_x) + */ static c3_o -_song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) +_song_x_cape(c3_ys mov, c3_ys off, + eqframe* fam, eqframe* don, + u3p(u3h_root) har_p, + void (*uni)(u3_noun*, u3_noun*)) { - u3p(eqframe) empty = u3R->cap_p; - u3p(u3h_root) har_p = 0; + u3_noun a, b, key; + u3_weak got; + u3a_cell* a_u; + u3a_cell* b_u; - c3_y wis_y = c3_wiseof(eqframe); - c3_o nor_o = u3a_is_north(u3R); - c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); - c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); - c3_o r_o = c3n; - c3_w ovr_w = 0; - eqframe* fam = _eq_push(mov, off, a, b); - eqframe* don = u3to(eqframe, empty + off); - - /* there's a while and a switch here. continues all mean "do the loop again" - ** and breaks all mean jump to end of switch. There are no breaks - ** that terminate the loop. - */ while ( don != fam ) { + a = fam->a; + b = fam->b; switch ( fam->sat_y ) { case SONG_NONE: - if ( (a = fam->a) == (b = fam->b) ) { - r_o = c3y; + if ( a == b ) { + break; } else if ( c3y == u3a_is_atom(a) ) { - r_o = _song_atom(a, b); + if ( c3n == _song_atom(a, b) ) { + return c3n; + } + else { + break; + } } else if ( c3y == u3a_is_atom(b) ) { - r_o = c3n; + return c3n; } else { u3a_cell* a_u = u3a_to_ptr(a); @@ -703,76 +703,139 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) if ( a_u->mug_w && b_u->mug_w && (a_u->mug_w != b_u->mug_w) ) { - r_o = c3n; + return c3n; } else { - if ( har_p != 0 ) { - u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b)); - u3t_off(euq_o); - u3_noun got = u3h_get(har_p, key); - u3t_on(euq_o); - u3z(key); - if ( u3_none != got ) { - fam = _eq_pop(mov, off); - continue; - } + key = u3nc(u3a_to_off(a), u3a_to_off(b)); + u3t_off(euq_o); + got = u3h_get(har_p, key); + u3t_on(euq_o); + u3z(key); + if ( u3_none != got ) { + fam = _eq_pop(mov, off); + continue; } fam->sat_y = SONG_HEAD; fam = _eq_push(mov, off, a_u->hed, b_u->hed); continue; } } - break; - case SONG_HEAD: { - u3a_cell* a_u = u3a_to_ptr(fam->a); - u3a_cell* b_u = u3a_to_ptr(fam->b); + case SONG_HEAD: + a_u = u3a_to_ptr(a); + b_u = u3a_to_ptr(b); uni(&(a_u->hed), &(b_u->hed)); fam->sat_y = SONG_TAIL; fam = _eq_push(mov, off, a_u->tel, b_u->tel); continue; - } - case SONG_TAIL: { - u3a_cell* a_u = u3a_to_ptr(fam->a); - u3a_cell* b_u = u3a_to_ptr(fam->b); + case SONG_TAIL: + a_u = u3a_to_ptr(a); + b_u = u3a_to_ptr(b); uni(&(a_u->tel), &(b_u->tel)); - r_o = c3y; break; - } default: c3_assert(0); break; } - if ( c3n == r_o ) { - if ( 0 != har_p ) { - u3h_free(har_p); - } - u3R->cap_p = empty; - return c3n; - } - else { - // ovr_w counts iterations. when it overflows, we know we've hit a - // pathological case and MUST start de-duplicating comparisons. - if ( 0 == har_p && 0 == ++ovr_w ) { - har_p = u3h_new(); - } - if ( 0 != har_p ) { - u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b)); - u3t_off(euq_o); - u3h_put(har_p, key, c3y); - u3t_on(euq_o); - u3z(key); - } - fam = _eq_pop(mov, off); - } + key = u3nc(u3a_to_off(a), u3a_to_off(b)); + u3t_off(euq_o); + u3h_put(har_p, key, c3y); + u3t_on(euq_o); + u3z(key); + fam = _eq_pop(mov, off); } - if ( 0 != har_p ) { - u3h_free(har_p); + return c3y; +} + +/* _song_x(): yes if a and b are the same noun, use uni to unify +*/ +static c3_o +_song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) +{ + u3p(eqframe) empty = u3R->cap_p; + + c3_y wis_y = c3_wiseof(eqframe); + c3_o nor_o = u3a_is_north(u3R); + c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); + c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); + c3_w ovr_w = 0; + eqframe* fam = _eq_push(mov, off, a, b); + eqframe* don = u3to(eqframe, empty + off); + + u3a_cell* a_u; + u3a_cell* b_u; + + while ( don != fam ) { + a = fam->a; + b = fam->b; + switch ( fam->sat_y ) { + case SONG_NONE: + if ( a == b ) { + break; + } + else if ( c3y == u3a_is_atom(a) ) { + if ( c3n == _song_atom(a, b) ) { + u3R->cap_p = empty; + return c3n; + } + else { + break; + } + } + else if ( c3y == u3a_is_atom(b) ) { + u3R->cap_p = empty; + return c3n; + } + else { + a_u = u3a_to_ptr(a); + b_u = u3a_to_ptr(b); + + if ( a_u->mug_w && + b_u->mug_w && + (a_u->mug_w != b_u->mug_w) ) { + u3R->cap_p = empty; + return c3n; + } + else { + fam->sat_y = SONG_HEAD; + fam = _eq_push(mov, off, a_u->hed, b_u->hed); + continue; + } + } + + case SONG_HEAD: + a_u = u3a_to_ptr(a); + b_u = u3a_to_ptr(b); + uni(&(a_u->hed), &(b_u->hed)); + fam->sat_y = SONG_TAIL; + fam = _eq_push(mov, off, a_u->tel, b_u->tel); + continue; + + case SONG_TAIL: + a_u = u3a_to_ptr(a); + b_u = u3a_to_ptr(b); + uni(&(a_u->tel), &(b_u->tel)); + break; + + default: + c3_assert(0); + break; + } + + if ( 0 == ++ovr_w ) { + u3p(u3h_root) har_p = u3h_new(); + c3_o ret_o = _song_x_cape(mov, off, fam, don, har_p, uni); + u3h_free(har_p); + u3R->cap_p = empty; + return ret_o; + } + fam = _eq_pop(mov, off); } + return c3y; } From 0883264aa1f8d83bf1cc2c45398ef7a73fcd44ae Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Thu, 15 Mar 2018 15:58:20 -0700 Subject: [PATCH 6/8] do the don trick for jam --- jets/e/jam.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/jets/e/jam.c b/jets/e/jam.c index f310154d7..0886dad5a 100644 --- a/jets/e/jam.c +++ b/jets/e/jam.c @@ -90,12 +90,14 @@ static u3_noun _jam_cap(u3_atom a) { + u3p(jamframe) empty = u3R->cap_p; u3p(u3h_root) har_p = u3h_new(); c3_o nor_o = u3a_is_north(u3R); c3_y wis_y = c3_wiseof(jamframe); c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); jamframe* fam = _jam_push(mov, off); + jamframe* don = u3to(jamframe, empty + off); fam->sat_y = JAM_NONE; fam->nun = a; @@ -103,9 +105,8 @@ fam->lis = u3_nul; u3_noun q, r = u3_none; - c3_w dep_w; - for ( dep_w = 1; dep_w > 0; ) { + while ( don != fam ) { switch ( fam->sat_y ) { case JAM_NONE: { u3_noun nun = fam->nun; @@ -118,7 +119,6 @@ if ( c3n == u3du(nun) ) { r = _jam_flat(nun, lis); fam = _jam_pop(mov, off); - --dep_w; u3z(len); } else { @@ -128,7 +128,6 @@ fam->nun = u3h(nun); fam->len = u3qa_add(2, len); fam->lis = u3nc(u3nc(2, 1), lis); - ++dep_w; } } else { @@ -139,7 +138,6 @@ r = _jam_ptr(got, lis); } fam = _jam_pop(mov, off); - --dep_w; u3z(len); } break; @@ -157,14 +155,12 @@ fam->len = u3qa_add(z, p_r); fam->lis = u3k(q_r); u3z(z); - ++dep_w; break; } case JAM_TAIL: { u3_noun len = fam->len; r = _jam_pair(u3qa_add(2, len), fam->hed, r); fam = _jam_pop(mov, off); - --dep_w; u3z(len); break; } From c1f4c7fcb34ebe6f0569e9c0d3aa968bd20fe19c Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Thu, 15 Mar 2018 16:58:04 -0700 Subject: [PATCH 7/8] change overflow check to short --- noun/retrieve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noun/retrieve.c b/noun/retrieve.c index 028c88c30..3a3b9e25c 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -762,7 +762,7 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) c3_o nor_o = u3a_is_north(u3R); c3_ys mov = ( c3y == nor_o ? -wis_y : wis_y ); c3_ys off = ( c3y == nor_o ? 0 : -wis_y ); - c3_w ovr_w = 0; + c3_s ovr_s = 0; eqframe* fam = _eq_push(mov, off, a, b); eqframe* don = u3to(eqframe, empty + off); @@ -826,7 +826,7 @@ _song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) break; } - if ( 0 == ++ovr_w ) { + if ( 0 == ++ovr_s ) { u3p(u3h_root) har_p = u3h_new(); c3_o ret_o = _song_x_cape(mov, off, fam, don, har_p, uni); u3h_free(har_p); From 087b674a377e5f720bf1e79e28550d4738799eea Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Mon, 19 Mar 2018 09:12:39 -0700 Subject: [PATCH 8/8] Revert "Revert "Merge pull request #941 from frodwith/runtime-overflows"" This reverts commit 074a29325763273c6edf32d241876df1a02d5c89. --- include/noun/allocate.h | 16 ++ jets/e/jam.c | 150 ++++++++++------ noun/allocate.c | 52 ++++++ noun/retrieve.c | 371 +++++++++++++++++----------------------- noun/trace.c | 5 + 5 files changed, 319 insertions(+), 275 deletions(-) diff --git a/include/noun/allocate.h b/include/noun/allocate.h index 1549948f8..075b12d2f 100644 --- a/include/noun/allocate.h +++ b/include/noun/allocate.h @@ -291,6 +291,22 @@ void* u3a_wealloc(void* lag_v, c3_w len_w); + /* u3a_push(): allocate space on the road stack + */ + void* + u3a_push(c3_w len_w); + + /* u3a_pop(): deallocate space on the road stack + */ + void + u3a_pop(c3_w len_w); + + /* u3a_peek(): examine the top of the road stack + */ + void* + u3a_peek(c3_w len_w); + + /* C-style aligned allocation - *not* compatible with above. */ /* u3a_malloc(): aligned storage measured in bytes. diff --git a/jets/e/jam.c b/jets/e/jam.c index 7751aa05c..ec2a7c6ca 100644 --- a/jets/e/jam.c +++ b/jets/e/jam.c @@ -3,32 +3,19 @@ */ #include "all.h" - /* functions */ - static u3_noun - _jam_in(u3p(u3h_root) har_p, u3_atom, u3_atom, u3_noun); static u3_noun - _jam_in_pair(u3p(u3h_root) har_p, - u3_atom h_a, - u3_atom t_a, - u3_atom b, - u3_noun l) + _jam_pair(u3_noun x, u3_noun d, u3_noun e) { - u3_noun w = u3nc(u3nc(2, 1), u3k(l)); - u3_noun x = u3qa_add(2, b); - u3_noun d = _jam_in(har_p, h_a, x, w); - u3_noun p_d, q_d, r_d; - u3_noun r; - - u3r_trel(d, &p_d, &q_d, &r_d); + u3_noun r, p_d, q_d, r_d; + u3x_trel(d, &p_d, &q_d, &r_d); { u3_noun y = u3qa_add(x, p_d); - u3_noun e = _jam_in(har_p, t_a, y, q_d); u3_noun p_e, q_e, r_e; - u3r_trel(e, &p_e, &q_e, &r_e); + u3x_trel(e, &p_e, &q_e, &r_e); { u3_noun z = u3qa_add(p_d, p_e); @@ -36,20 +23,16 @@ u3z(z); } - u3z(e); u3z(y); } - u3z(d); u3z(x); - u3z(w); - + u3z(d); + u3z(e); return r; } static u3_noun - _jam_in_flat(u3p(u3h_root) har_p, - u3_atom a, - u3_noun l) + _jam_flat(u3_atom a, u3_noun l) { u3_noun d = u3qe_mat(a); u3_noun x = u3qa_add(1, u3h(d)); @@ -57,14 +40,13 @@ (u3k(x), u3nc(u3nc(x, u3qc_lsh(0, 1, u3t(d))), u3k(l)), 0); u3z(d); + u3z(l); return y; } static u3_noun - _jam_in_ptr(u3p(u3h_root) har_p, - u3_atom u_c, - u3_noun l) + _jam_ptr(u3_atom u_c, u3_noun l) { u3_noun d = u3qe_mat(u_c); u3_atom x = u3qc_lsh(0, 2, u3t(d)); @@ -74,49 +56,103 @@ u3z(d); u3z(x); + u3z(l); return z; } - static u3_noun - _jam_in(u3p(u3h_root) har_p, - u3_noun a, - u3_atom b, - u3_noun l) + typedef struct { + u3_noun a; + u3_noun b; + u3_noun l; + u3_noun* r; + u3_noun hed; + u3_noun tel; + } jamframe; + + static inline void + _jam_push(u3_noun a, u3_noun b, u3_noun l, u3_noun *r) { - u3_noun c = u3h_get(har_p, a); - u3_noun x; - - if ( u3_none == c ) { - u3h_put(har_p, a, u3k(b)); - - if ( c3y == u3ud(a) ) { - x = _jam_in_flat(har_p, a, l); - } else { - x = _jam_in_pair(har_p, u3h(a), u3t(a), b, l); - } - } - else { - if ( c3y == u3ud(a) && u3r_met(0, a) <= u3r_met(0, c) ) { - x = _jam_in_flat(har_p, a, l); - } - else { - x = _jam_in_ptr(har_p, c, l); - } - } - return x; + jamframe* fam = u3a_push(sizeof(jamframe)); + fam->a = a; + fam->b = b; + fam->l = l; + fam->r = r; + fam->hed = u3_none; + fam->tel = u3_none; } + static inline void + _jam_pop() + { + u3a_pop(sizeof(jamframe)); + } + + static inline jamframe* + _jam_peek() + { + return (jamframe*) u3a_peek(sizeof(jamframe)); + } + + u3_noun u3qe_jam(u3_atom a) { u3p(u3h_root) har_p = u3h_new(); + u3p(jamframe) empty = u3R->cap_p; + jamframe* fam; + u3_noun out, c, x, q, r; - u3_noun x = _jam_in(har_p, a, 0, u3_nul); - u3_noun q = u3qb_flop(u3h(u3t(x))); - u3_noun r = u3qc_can(0, q); + _jam_push(a, 0, u3_nul, &out); + while ( empty != u3R->cap_p ) { + fam = _jam_peek(); + if ( u3_none != fam->tel ) { + u3_noun z = u3qa_add(2, fam->b); + x = _jam_pair(z, fam->hed, fam->tel); + } + else if ( u3_none != fam->hed ) { + u3_noun p_d, q_d, r_d; + u3x_trel(fam->hed, &p_d, &q_d, &r_d); + { + u3_noun z = u3qa_add(2, fam->b); + u3_noun y = u3qa_add(z, p_d); + _jam_push(u3t(fam->a), y, u3k(q_d), &(fam->tel)); + u3z(z); + continue; + } + } + else { + a = fam->a; + c = u3h_get(har_p, a); + if ( u3_none != c ) { + if ( (c3y == u3ud(a)) && u3r_met(0, a) <= u3r_met(0, c) ) { + x = _jam_flat(a, fam->l); + } + else { + x = _jam_ptr(c, fam->l); + } + } + else { + u3h_put(har_p, a, u3k(fam->b)); + if ( c3y == u3ud(a) ) { + x = _jam_flat(a, fam->l); + } + else { + u3_noun z = u3qa_add(2, fam->b); + u3_noun w = u3nc(u3nc(2, 1), fam->l); + _jam_push(u3h(a), z, w, &(fam->hed)); + continue; + } + } + } + *(fam->r) = x; + u3z(fam->b); + _jam_pop(); + } - u3z(x); + q = u3qb_flop(u3h(u3t(out))); + r = u3qc_can(0, q); + u3z(out); u3z(q); u3h_free(har_p); return r; diff --git a/noun/allocate.c b/noun/allocate.c index f8dd50f31..92af40851 100644 --- a/noun/allocate.c +++ b/noun/allocate.c @@ -576,6 +576,58 @@ u3a_wealloc(void* lag_v, c3_w len_w) } } } +/* u3a_push(): allocate space on the road stack +*/ +void* +u3a_push(c3_w len_w) +{ + void *cur, *top = u3to(void, u3R->cap_p); + if ( c3y == u3a_is_north(u3R) ) { + top -= len_w; + cur = top; + u3p(void) cap_p = u3R->cap_p = u3of(void, top); + c3_assert(cap_p < u3R->mat_p); + c3_assert(cap_p > u3R->hat_p); + return cur; + } + else { + cur = top; + top += len_w; + u3R->cap_p = u3of(void, top); + u3p(void) cap_p = u3R->cap_p = u3of(void, top); + c3_assert(cap_p > u3R->mat_p); + c3_assert(cap_p < u3R->hat_p); + return cur; + } +} + +/* u3a_pop(): deallocate space on the road stack +*/ +void +u3a_pop(c3_w len_w) +{ + void* top = u3to(void, u3R->cap_p); + if ( c3y == u3a_is_north(u3R) ) { + top += len_w; + u3p(void) cap_p = u3R->cap_p = u3of(void, top); + c3_assert(cap_p <= u3R->mat_p); + c3_assert(cap_p > u3R->hat_p); + } + else { + top -= len_w; + u3p(void) cap_p = u3R->cap_p = u3of(void, top); + c3_assert(cap_p >= u3R->mat_p); + c3_assert(cap_p < u3R->hat_p); + } +} + +/* u3a_peek(): examine the top of the road stack +*/ +void* +u3a_peek(c3_w len_w) +{ + return u3to(void, u3R->cap_p) - (c3y == u3a_is_north(u3R) ? 0 : len_w); +} /* u3a_wfree(): free storage. */ diff --git a/noun/retrieve.c b/noun/retrieve.c index 400007489..ea94ecf80 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -502,87 +502,39 @@ _sang_one(u3_noun* a, u3_noun* b) } } -/* _sang_x(): yes if a and b are the same noun, unifying but leaking. -*/ -static c3_o -_sang_x(u3_noun a, u3_noun b) +typedef struct { + u3_noun a; + u3_noun b; + c3_y sat_y; +} eqframe; + +static inline eqframe* +_eq_peek() { - if ( a == b ) { - return c3y; - } - else { - if ( _(u3a_is_atom(a)) ) { - u3a_atom* a_u = u3a_to_ptr(a); + return (eqframe*) u3a_peek(sizeof(eqframe)); +} - if ( !_(u3a_is_atom(b)) || - _(u3a_is_cat(a)) || - _(u3a_is_cat(b)) ) - { - return c3n; - } - else { - u3a_atom* b_u = u3a_to_ptr(b); +static inline void +_eq_push(u3_noun a, u3_noun b) +{ + eqframe* cur = (eqframe*) u3a_push(sizeof(eqframe)); + cur->a = a; + cur->b = b; + cur->sat_y = 0; +} - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - c3_w w_rez = a_u->len_w; - c3_w w_mox = b_u->len_w; +static inline void +_eq_pop() +{ + u3a_pop(sizeof(eqframe)); +} - if ( w_rez != w_mox ) { - return c3n; - } - else { - c3_w i_w; - - for ( i_w = 0; i_w < w_rez; i_w++ ) { - if ( a_u->buf_w[i_w] != b_u->buf_w[i_w] ) { - return c3n; - } - } - return c3y; - } - } - } - } - else { - if ( _(u3a_is_atom(b)) ) { - return c3n; - } - else { - u3a_cell* a_u = u3a_to_ptr(a); - u3a_cell* b_u = u3a_to_ptr(b); - - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - if ( c3n == _sang_x(a_u->hed, b_u->hed) ) { - return c3n; - } - else { - _sang_one(&a_u->hed, &b_u->hed); - - if ( c3n == _sang_x(a_u->tel, b_u->tel) ) { - return c3n; - } - else { - _sang_one(&a_u->tel, &b_u->tel); - - return c3y; - } - } - } - } - } - } +/* _sing_one(): do not pick a unified pointer for identical (a) and (b). +*/ +static void +_sing_one(u3_noun* a, u3_noun* b) +{ + // this space left intentionally blank } /* _sung_one(): pick a unified pointer for identical (a) and (b). @@ -669,168 +621,149 @@ _sung_one(u3_noun* a, u3_noun* b) } } -/* _sung_x(): yes if a and b are the same noun, unifying. -*/ -static c3_o -_sung_x(u3_noun a, u3_noun b) +static inline c3_o +_song_atom(u3_atom a, u3_atom b) { - if ( a == b ) { - return c3y; + u3a_atom* a_u = u3a_to_ptr(a); + + if ( !_(u3a_is_atom(b)) || + _(u3a_is_cat(a)) || + _(u3a_is_cat(b)) ) + { + return c3n; } else { - if ( _(u3a_is_atom(a)) ) { - u3a_atom* a_u = u3a_to_ptr(a); + u3a_atom* b_u = u3a_to_ptr(b); - if ( !_(u3a_is_atom(b)) || - _(u3a_is_cat(a)) || - _(u3a_is_cat(b)) ) - { - return c3n; - } - else { - u3a_atom* b_u = u3a_to_ptr(b); - - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - c3_w w_rez = a_u->len_w; - c3_w w_mox = b_u->len_w; - - if ( w_rez != w_mox ) { - return c3n; - } - else { - c3_w i_w; - - for ( i_w = 0; i_w < w_rez; i_w++ ) { - if ( a_u->buf_w[i_w] != b_u->buf_w[i_w] ) { - return c3n; - } - } - return c3y; - } - } - } + if ( a_u->mug_w && + b_u->mug_w && + (a_u->mug_w != b_u->mug_w) ) + { + return c3n; } else { - if ( _(u3a_is_atom(b)) ) { + c3_w w_rez = a_u->len_w; + c3_w w_mox = b_u->len_w; + + if ( w_rez != w_mox ) { return c3n; } else { - u3a_cell* a_u = u3a_to_ptr(a); - u3a_cell* b_u = u3a_to_ptr(b); + c3_w i_w; - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - if ( c3n == _sung_x(a_u->hed, b_u->hed) ) { + for ( i_w = 0; i_w < w_rez; i_w++ ) { + if ( a_u->buf_w[i_w] != b_u->buf_w[i_w] ) { return c3n; } - else { - _sung_one(&a_u->hed, &b_u->hed); - - if ( c3n == _sung_x(a_u->tel, b_u->tel) ) { - return c3n; - } - else { - _sung_one(&a_u->tel, &b_u->tel); - - return c3y; - } - } } } } } + return c3y; } -/* _sing_x(): -** -** Yes iff (a) and (b) are the same noun. +/* knob: set lower to get more/earlier memoize-by-pointer, + * higher to avoid allocating the u3h as often */ +#define EQ_WHISTLE 1024 + +/* _song_x(): yes if a and b are the same noun, use uni to unify */ static c3_o -_sing_x(u3_noun a, - u3_noun b) +_song_x(u3_noun a, u3_noun b, void (*uni)(u3_noun*, u3_noun*)) { - c3_assert(u3_none != a); - c3_assert(u3_none != b); + eqframe* fam; + u3p(eqframe) empty = u3R->cap_p; + c3_w wis_w = 0; + c3_o r_o = c3n; + u3p(u3h_root) har_p = 0; - if ( a == b ) { - return c3y; - } - else { - if ( _(u3a_is_atom(a)) ) { - u3a_atom* a_u = u3a_to_ptr(a); - - if ( !_(u3a_is_atom(b)) || - _(u3a_is_cat(a)) || - _(u3a_is_cat(b)) ) - { - return c3n; - } - else { - u3a_atom* b_u = u3a_to_ptr(b); - - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - c3_w w_rez = a_u->len_w; - c3_w w_mox = b_u->len_w; - - if ( w_rez != w_mox ) { - return c3n; - } - else { - c3_w i_w; - - for ( i_w = 0; i_w < w_rez; i_w++ ) { - if ( a_u->buf_w[i_w] != b_u->buf_w[i_w] ) { - return c3n; - } - } - return c3y; - } - } - } + _eq_push(a, b); + /* there's a while and a switch here. continues all mean "do the loop again" + ** and breaks all mean "fall through this switch case". There are no breaks + ** that early terminate the loop. + */ + while ( empty != u3R->cap_p ) { + fam = _eq_peek(); + if ( (a = fam->a) == (b = fam->b) ) { + r_o = c3y; + } + else if ( c3y == u3a_is_atom(a) ) { + r_o = _song_atom(a, b); + } + else if ( c3y == u3a_is_atom(b) ) { + r_o = c3n; } else { - if ( _(u3a_is_atom(b)) ) { - return c3n; - } - else { - u3a_cell* a_u = u3a_to_ptr(a); - u3a_cell* b_u = u3a_to_ptr(b); + u3a_cell* a_u = u3a_to_ptr(a); + u3a_cell* b_u = u3a_to_ptr(b); - if ( a_u->mug_w && - b_u->mug_w && - (a_u->mug_w != b_u->mug_w) ) - { - return c3n; - } - else { - if ( c3n == _sing_x(u3a_h(a), u3a_h(b)) ) { - return c3n; + switch ( fam->sat_y ) { + case 2: + uni(&(a_u->tel), &(b_u->tel)); + r_o = c3y; + break; + + case 1: + uni(&(a_u->hed), &(b_u->hed)); + _eq_push(a_u->tel, b_u->tel); + fam->sat_y = 2; + continue; + + case 0: { + if ( a_u->mug_w && + b_u->mug_w && + (a_u->mug_w != b_u->mug_w) ) { + r_o = c3n; + break; } - else if ( c3n == _sing_x(u3a_t(a), u3a_t(b)) ) { - return c3n; + else { + if ( har_p != 0 ) { + u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b)); + u3t_off(euq_o); + u3_noun got = u3h_get(har_p, key); + u3t_on(euq_o); + u3z(key); + if ( u3_none != got ) { + _eq_pop(); + continue; + } + } + _eq_push(a_u->hed, b_u->hed); + fam->sat_y = 1; + continue; } - return c3y; } + default: + c3_assert(0); } } + + if ( c3n == r_o ) { + if ( 0 != har_p ) { + u3h_free(har_p); + } + u3R->cap_p = empty; + return c3n; + } + else { + if ( 0 == har_p && (wis_w++ > EQ_WHISTLE) ) { + har_p = u3h_new(); + } + if ( 0 != har_p ) { + u3_noun key = u3nc(u3a_to_off(a), u3a_to_off(b)); + u3t_off(euq_o); + u3h_put(har_p, key, c3y); + u3t_on(euq_o); + u3z(key); + } + _eq_pop(); + } } + + if ( 0 != har_p ) { + u3h_free(har_p); + } + return c3y; } /* u3r_sang(): yes iff (a) and (b) are the same noun, unifying equals. @@ -838,7 +771,11 @@ _sing_x(u3_noun a, c3_o u3r_sang(u3_noun a, u3_noun b) { - return _sang_x(a, b); + c3_o ret_o; + u3t_on(euq_o); + ret_o = _song_x(a, b, &_sang_one); + u3t_off(euq_o); + return ret_o; } /* u3r_sing(): @@ -850,20 +787,14 @@ u3r_sing(u3_noun a, u3_noun b) { #ifndef U3_MEMORY_DEBUG if ( u3R->par_p ) { - c3_o ret_o; - - u3t_on(euq_o); - ret_o = u3r_sang(a, b); - u3t_off(euq_o); - - return ret_o; + return u3r_sang(a, b); } #endif { c3_o ret_o; u3t_on(euq_o); - ret_o = _sing_x(a, b); + ret_o = _song_x(a, b, &_sing_one); u3t_off(euq_o); return ret_o; @@ -875,7 +806,11 @@ u3r_sing(u3_noun a, u3_noun b) c3_o u3r_sung(u3_noun a, u3_noun b) { - return _sung_x(a, b); + c3_o ret_o; + u3t_on(euq_o); + ret_o = _song_x(a, b, &_sung_one); + u3t_off(euq_o); + return ret_o; } c3_o diff --git a/noun/trace.c b/noun/trace.c index 1464d719b..ddb7410c5 100644 --- a/noun/trace.c +++ b/noun/trace.c @@ -361,7 +361,12 @@ u3t_damp(void) void _ct_sigaction(c3_i x_i) { // fprintf(stderr, "itimer!\r\n"); abort(); + + // sampling mid-equality can break without this + c3_o meq_o = u3T.euq_o; + u3T.euq_o = c3n; u3t_samp(); + u3T.euq_o = meq_o; } /* u3t_init(): initialize tracing layer.