diff --git a/pkg/arvo/ted/test.hoon b/pkg/arvo/ted/test.hoon index a25496fc2..43a81700c 100644 --- a/pkg/arvo/ted/test.hoon +++ b/pkg/arvo/ted/test.hoon @@ -66,7 +66,7 @@ =/ fire-arm=nock ~| [%failed-to-compile-test-arm name] q:(~(mint ut typ) p:!>(*tang) [%limb name]) - [name |.(;;(tang .*(cor fire-arm)))] + [name |.(;;(tang ~>(%bout.[1 name] .*(cor fire-arm))))] :: +has-test-prefix: does the arm define a test we should run? :: ++ has-test-prefix diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index cbb4850b2..807c80f78 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -112,6 +112,7 @@ # define c3__boot c3_s4('b','o','o','t') # define c3__born c3_s4('b','o','r','n') # define c3__both c3_s4('b','o','t','h') +# define c3__bout c3_s4('b','o','u','t') # define c3__box c3_s3('b','o','x') # define c3__br c3_s2('b','r') # define c3__bran c3_s4('b','r','a','n') diff --git a/pkg/urbit/include/noun/trace.h b/pkg/urbit/include/noun/trace.h index 80b7bc1e5..28b42151d 100644 --- a/pkg/urbit/include/noun/trace.h +++ b/pkg/urbit/include/noun/trace.h @@ -93,6 +93,12 @@ void u3t_trace_close(); + /* u3t_trace_time(): returns current time since system epoc, + * whatever it is per system, in microseconds. + */ + c3_d + u3t_trace_time(); + /* u3t_nock_trace_push(): pushes a frame onto the trace stack; * return yes if active push. */ diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index bc41e5ddd..f2ec04e64 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1004,8 +1004,8 @@ _n_emit(u3_noun *ops, u3_noun op) static c3_w _n_comp(u3_noun*, u3_noun, c3_o, c3_o); /* _n_bint(): hint-processing helper for _n_comp. - * hif: hint-formula (first part of 10). RETAIN. - * nef: next-formula (second part of 10). RETAIN. + * hif: hint-formula (first part of 11). RETAIN. + * nef: next-formula (second part of 11). RETAIN. */ static c3_w _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) @@ -1021,18 +1021,22 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) return _n_comp(ops, nef, los_o, tel_o); } - // no currently recognized static hints - // - case u3_none: { + case c3__bout: { u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HILL : HILK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + // call hilt_fore // HILB overflows to HILS - // ++tot_w; _n_emit(ops, u3nc(HILB, u3nc(u3k(hif), u3k(nef)))); - ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w + 1)); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); tot_w += nef_w; _n_apen(ops, fen); - ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HILL : HILK); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); } break; } } @@ -1052,19 +1056,24 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) tot_w += _n_comp(ops, nef, los_o, tel_o); } break; - // no currently recognized dynamic hints - // - case u3_none: { + case c3__bout: { u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HINL : HINK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + // push clue tot_w += _n_comp(ops, hod, c3n, c3n); + // call hint_fore // HINB overflows to HINS - // ++tot_w; _n_emit(ops, u3nc(HINB, u3nc(u3k(zep), u3k(nef)))); - ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w + 1)); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); tot_w += nef_w; _n_apen(ops, fen); - ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HINL : HINK); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); } break; } } break; @@ -1677,18 +1686,25 @@ u3n_find(u3_noun key, u3_noun fol) } /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. -** lit: hint atom. TRANSFER +** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN -** out: token for _n_hilt_hind(); -** conventionally, [lit] or [lit data]. ~ if unused. +** out: token for _n_hilt_hind(); convention: +** [hint-atom] or [hint-atom data], ~ if unused. ** ** any hints herein must be whitelisted in _n_burn(). */ static c3_o -_n_hilt_fore(u3_atom lit, u3_noun bus, u3_noun* out) // transfer, retain, n/a +_n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { - u3z(lit); - *out = u3_nul; + if ( c3__bout == u3h(hin) ) { + u3_atom now = u3i_chub(u3t_trace_time()); + *out = u3i_cell(u3h(hin), now); + } + else { + *out = u3_nul; + } + + u3z(hin); return c3y; } @@ -1697,9 +1713,20 @@ _n_hilt_fore(u3_atom lit, u3_noun bus, u3_noun* out) // transfer, retain, n/a ** pro: product of formula evaluation. RETAIN */ static void -_n_hilt_hind(u3_noun tok, u3_noun pro) // transfer, retain +_n_hilt_hind(u3_noun tok, u3_noun pro) { - c3_assert( u3_nul == tok ); + u3_noun p_tok, q_tok; + if ( (c3y == u3r_cell(tok, &p_tok, &q_tok)) && (c3__bout == p_tok) ) { + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(q_tok)); + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + u3t_slog(u3nc(0, u3i_string(str_c))); + u3z(delta); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } @@ -1707,16 +1734,24 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) // transfer, retain ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN ** clu: product of the hint-formula. TRANSFER -** also, token for _n_hint_hind(); -** conventionally, [hint-atom] or [hint-atom data]. ~ if unused. +** also, token for _n_hilt_hind(); convention: +** [hint-atom] or [hint-atom data], ~ if unused. ** ** any hints herein must be whitelisted in _n_burn(). */ static c3_o _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) { - u3z(hin); u3z(*clu); - *clu = u3_nul; + if ( c3__bout == u3h(hin) ) { + u3_atom now = u3i_chub(u3t_trace_time()); + *clu = u3i_trel(u3h(hin), *clu, now); + } + else { + u3z(*clu); + *clu = u3_nul; + } + + u3z(hin); return c3y; } @@ -1727,7 +1762,43 @@ _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) static void _n_hint_hind(u3_noun tok, u3_noun pro) { - c3_assert( u3_nul == tok ); + u3_noun p_tok, q_tok, r_tok; + if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok)) + && (c3__bout == p_tok) ) + { + // get the microseconds elapsed + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok)); + + // unpack q_tok to get the priority integer and the tank + // p_q_tok is the priority, q_q_tok is the tank we will work with + u3_noun p_q_tok, q_q_tok; + c3_assert(c3y == u3r_cell(q_tok, &p_q_tok, &q_q_tok)); + + // format the timing report + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + + // join the timing report with the original tank from q_q_tok like so: + // "q_q_tok: report" + // prepend the priority to form a cell of the same shape q_tok + // send this to ut3_slog so that it can be logged out + u3t_slog( + u3nc( + u3k(p_q_tok), + u3nt( + c3__rose, + u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul), + u3nt(u3k(q_q_tok), u3i_string(str_c), u3_nul) + ) + ) + ); + + u3z(delta); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } diff --git a/pkg/urbit/ur/hashcons.c b/pkg/urbit/ur/hashcons.c index 4863ef6b7..a2dd691d7 100644 --- a/pkg/urbit/ur/hashcons.c +++ b/pkg/urbit/ur/hashcons.c @@ -937,7 +937,6 @@ struct ur_walk_fore_s { ur_root_t *r; uint32_t prev; uint32_t size; - uint32_t fill; ur_nref *top; }; @@ -950,7 +949,6 @@ ur_walk_fore_init_with(ur_root_t *r, w->top = _oom("walk_fore", malloc(s_size * sizeof(*w->top))); w->prev = s_prev; w->size = s_size; - w->fill = 0; w->r = r; return w; @@ -969,45 +967,42 @@ ur_walk_fore_with(ur_walk_fore_t *w, void (*atom)(ur_root_t*, ur_nref, void*), ur_bool_t (*cell)(ur_root_t*, ur_nref, void*)) { - ur_root_t *r = w->r; - ur_nref *don = w->top; + ur_root_t *r = w->r; + uint32_t fill = 1; - w->top += ++w->fill; *w->top = ref; - while ( w->top != don ) { + do { // visit atom, pop stack // if ( !ur_deep(ref) ) { atom(r, ref, v); - w->top--; w->fill--; + fill--; } // visit cell, pop stack if false // else if ( !cell(r, ref, v) ) { - w->top--; w->fill--; + fill--; } // push the tail, continue into the head // else { - *w->top = ur_tail(r, ref); + w->top[fill++] = ur_tail(r, ref); // reallocate "stack" if full // - if ( w->size == w->fill ) { + if ( w->size == fill ) { uint32_t next = w->prev + w->size; - don = _oom("walk_fore", realloc(don, next * sizeof(*don))); - w->top = don + w->fill; + w->top = _oom("walk_fore", realloc(w->top, next * sizeof(*w->top))); w->prev = w->size; w->size = next; } - w->top++; w->fill++; - *w->top = ur_head(r, ref); + w->top[fill] = ur_head(r, ref); } - ref = *w->top; - } + ref = w->top[fill]; + } while ( fill ); } void diff --git a/pkg/urbit/ur/serial.c b/pkg/urbit/ur/serial.c index 61eeca39c..2bdfa2f4b 100644 --- a/pkg/urbit/ur/serial.c +++ b/pkg/urbit/ur/serial.c @@ -134,7 +134,7 @@ void ur_jam_done(ur_jam_t *j) { ur_dict_free((ur_dict_t*)&j->dict); - free(j->w); + ur_walk_fore_done(j->w); free(j); } diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index db072f641..17be5776e 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -1114,7 +1114,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // dispose successful // - while ( tac_u->eve_d < eve_d ) { + while ( tac_u->eve_d <= eve_d ) { nex_u = tac_u->nex_u; las_l = tac_u->mug_l; u3_fact_free(tac_u); diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 3e005a750..55cb3ad7d 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -751,16 +751,12 @@ _serf_play_list(u3_serf* sef_u, u3_noun eve) eve = u3t(eve); } - // event succeeded, save and continue + // event failed, stop and send trace // else { - u3_noun dud = u3k(u3t(gon)); - // reset sent event counter // - sef_u->sen_d = sef_u->dun_d; - - u3z(gon); + sef_u->sen_d = sef_u->dun_d; // XX reclaim on meme ? // @@ -770,7 +766,7 @@ _serf_play_list(u3_serf* sef_u, u3_noun eve) u3z(vev); return u3nc(c3__bail, u3nt(u3i_chubs(1, &sef_u->dun_d), sef_u->mug_l, - dud)); + gon)); } }