From a90c34f68d5b9d60c45df900e04636efdcc38ddb Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 11 Aug 2021 16:31:29 -0400 Subject: [PATCH 01/13] u3: corrects dynamic hint protocol signatures/comments --- pkg/urbit/noun/nock.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index aca031030..6e01ae326 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) @@ -1677,17 +1677,17 @@ 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); + u3z(hin); *out = u3_nul; return c3y; } @@ -1697,7 +1697,7 @@ _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 ); u3z(tok); @@ -1707,8 +1707,8 @@ _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(). */ From 57a53792c1cb6ded4c8413f4d0577b0c1464f72a Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 11 Aug 2021 16:04:58 -0400 Subject: [PATCH 02/13] u3: reclaim on restart (clear caches) REMOVE ME --- pkg/urbit/noun/manage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index 4833228ff..522a2dcd4 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -1725,6 +1725,8 @@ u3m_boot(c3_c* dir_c) u3j_ream(); u3n_ream(); + u3m_reclaim(); + return u3A->eve_d; } else { From c75b9d6f48f632aa3d78f01ed479c38130f1da3f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 11 Aug 2021 16:32:58 -0400 Subject: [PATCH 03/13] u3: adds dynamic hint (literal) callback example %clep --- pkg/urbit/noun/nock.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index 6e01ae326..195eb3463 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1023,7 +1023,8 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) // no currently recognized static hints // - case u3_none: { + case c3__clep: { + fprintf(stderr, "compiling clep\r\n"); u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); @@ -1687,6 +1688,12 @@ u3n_find(u3_noun key, u3_noun fol) static c3_o _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { + if ( c3__clep == u3h(hin) ) { + fprintf(stderr, "fore: got clep\r\n"); + *out = c3__clep; + return c3y; + } + u3z(hin); *out = u3_nul; return c3y; @@ -1699,7 +1706,13 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) static void _n_hilt_hind(u3_noun tok, u3_noun pro) { - c3_assert( u3_nul == tok ); + if ( c3__clep == tok ) { + fprintf(stderr, "hind: got clep\r\n"); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } From 53942552f8121033826051c7085fff58d72d3ca5 Mon Sep 17 00:00:00 2001 From: Dane Bettis Date: Fri, 27 Aug 2021 16:44:43 +0200 Subject: [PATCH 04/13] Adds clep hint to time an expression and clet to print the stack trace at expression --- pkg/urbit/noun/nock.c | 433 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 429 insertions(+), 4 deletions(-) diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index 195eb3463..3d3b55ecb 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1024,10 +1024,24 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) // no currently recognized static hints // case c3__clep: { + fprintf(stderr," \r\n"); fprintf(stderr, "compiling clep\r\n"); u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // 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)); + tot_w += nef_w; _n_apen(ops, fen); + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HILL : HILK); + } break; + case c3__clet: { + fprintf(stderr," \r\n"); + fprintf(stderr, "compiling clet\r\n"); + u3_noun fen = u3_nul; + c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // HILB overflows to HILS // ++tot_w; _n_emit(ops, u3nc(HILB, u3nc(u3k(hif), u3k(nef)))); @@ -1677,6 +1691,295 @@ u3n_find(u3_noun key, u3_noun fol) return pog_p; } +//----------------------------------------------------- +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +static u3_cell +current_epoc_time_ms_as_cell (void) +{ + long ms; // Milliseconds + time_t s; // Seconds + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + s = spec.tv_sec; + // Convert nanoseconds to milliseconds + ms = round(spec.tv_nsec / 1.0e6); + if (ms > 999) { + s++; + ms = 0; + } + return u3i_cell(s, ms); +} + +/*TODO: move time functions + so that noun does not + cycle-depend upon vere + */ +#include <../include/vere/vere.h> +static u3_atom +urbit_epocnow_atom (void) +{ + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return u3_time_in_ts(&spec); +} + +#ifdef WIN32 +#include +#elif _POSIX_C_SOURCE >= 199309L +#include // for nanosleep +#else +#include // for usleep +#endif + +void +sleep_ms(int milliseconds) +{ // cross-platform sleep function +#ifdef WIN32 + Sleep(milliseconds); +#elif _POSIX_C_SOURCE >= 199309L + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&ts, NULL); +#else + if (milliseconds >= 1000) + sleep(milliseconds / 1000); + usleep((milliseconds % 1000) * 1000); +#endif +} +//----------------------------------------------------- +/* urbit dev process notes 2021-08-11: + project setup: + install nix + install git + install git-lfs + git clone urbit + cd urbit + git config credential.helper store + git config pull.rebase true + git lfs install + git lfs pull + cd pkg/urbit + nix-shell + ./configure && make -j 6 + + pills: + - brass: formal bootstrap + - solid: fast boot for development (logically, partially-evaluated brass) + - ivory: runtime support + my pill locations: + urbit/bin/brass.pill + urbit/bin/ivory.pill + urbit/bin/solid.pill + urbit/pkg/hs/urbit-king/test/gold/hoontree.pill + + boot a fake ship: + build/urbit -F name-of-any-ship-except-comets + - + + these are all the same: + build/urbit -F zod + build/urbit -F zod -c zod + build/urbit -F zod -u bootstrap.urbit.org/$URBIT_VERSION.pill + + this is the standard local dev command: + build/urbit -l -F zod -B path/to/pill -A path/to/arvo -c name-of-fake-ship + my version: + # create a fake ship zod with a peir named fakezod, lite boot using fast boot pill and the local arvo path + build/urbit -c ../../fakezod -F zod -l -B ../../bin/solid.pill -A ../arvo + + to restart: + build/urbit name-of-fake-ship + my version: + # this should resume the above ship with all the settings + build/urbit fakezod + + notable urbit binary flags: + * -L: local-only networking (automatically set for fake ships) + * -u: download pill from url + * -B: boot from local pill at path + * -l: lite-boot (faster, limited userspace) + * -A: load filesystem from local arvo directory + + to test clep: + # in the fake zod dojo type and enter this: + ~> %clep (add 2 2) + + bootstrap formula (see media.urbit.org/whitepaper.pdf): + [%2 [%0 3] %0 2] + - + + >>>>> commands to use during main dev cycle: + [urbit git root]$ cd pkg/urbit/ && nix-shell && cd ../.. + [nix-shell urbit/pkg/urbit]$ ./configure && make -j 6 && build/urbit ../../fakezod + ~zod:dojo> !: ~> %clep (add 1 2) + ~zod:dojo> !: ~> %clet (add 4 1) + + dynamic hint protocol: + commonly used hints are directly represented in the u3 bytecode for performance, and adding new opcodes is an involved task. + + in urbit-v1.0, we introduced a protocol for implementing dynamic hint handlers. hints must be whitelisted in the nock->bytecode compiler, and handlers are implemented in before/after callback functions: + + https://github.com/urbit/urbit/pull/3979 + + there are two kinds of dynamic hint handlers, mirroring the two hint reduction rules (opcode 11) in the nock spec. the first is an atomic hint, which is merely a label; the second is a labeled nock formula, which can convey arbitrary data to the runtime. these are compiled into different bytecodes, and handled in different callbacks. + + hints are whitelisted in _n_bint() (the "hint-processing helper" for the bytecode compiler in _n_comp()). there are separate case statements for the separate hint types, and whitelisting a given hint merely involves adding a fallthru case (the default case discards the hint while preserving nock semantics). to simplify memory management, hint labels should be "motes" -- compile-time constants of up to 4 letters, defined in motes.h. + + atomic hint handlers are added to _n_hilt_fore()/_n_hilt_hind(), arbitrary hint handlers in _n_hint_fore()/_n_hint_hind() + */ + +/* urbit grant notes 2021-08-18: + Here's a quick rundown of u3's stack trace production mechanism: + + - the bytecode interpreter maintains a trace stack via + u3t_push()/u3t_mean() and u3t_drop() + + - the frames in that stack are unrendered + Many frames are just data, like the %spot hints that record source locations. But some contain code, like the %mean hints from ~|. + + - the stack is stored in the current road, at u3R->bug.tax + + - traces are currently only produced for failed/interrupted virtual computations + + - Virtualization is performed by u3m_soft() and related variants. + It involves a setjmp() call to trap for "exceptions", and a new inner road (u3m_leap()) to establish an isolated memory arena. + "Exceptions" are "thrown" via longjmp(), in u3m_bail() or a signal handler. + + In some more detail: + - Every event is run virtualized via u3m_soft. see _serf_poke() in worker/serf.c + - Inside an event, further levels of virtualization are established via the +mink jet, which eventually calls u3m_soft_run() + - Successful computations, namespace blocks, and deterministic bails, such as u3m_bail(c3__exit), are all returned directly to the parent context + - Non-deterministic bails cannot be trapped, and unwind the entire execution context by re-bailing at each layer. + - In the case of a deterministic bail, the product of +mink / u3m_soft_run() is a proto-stack trace + - To render that to (list tank), ie $tang, we call `+mook`, which formats each entry in urbit's print format ($tank), and evaluates any lazy/deferred frames + - There's no C implementation, so we just make a dynamic call into nock + - A representative call-site is in u3m_soft() + ------- + - At any point time, the logical current trace stack may be spread across many roads, if we're deeply nested in virtual contexts + - There is not currently any code that combines those traces directly; they're currently combined by unwinding/re-bailing + - For an initial implementation, I would only print the trace from the current road. + - Eventually, we'll want to gather the trace stack from all roads, and probably virtualize the call to +mook. + + */ + +/* urbit grant todo/notes 2021-08-25: + - u3t_init()/u3t_boot() are called on loom/inner-road init + - u3t_on()/u3t_off() establishing modes/labels for -P sampling profiler (and no-op without the compile-time MEMORY_DEBUG option) + + >>>> Brad jump to THIS! <<<<<< + 1. be able to session drive next time + 2. DONE: poc of print traces without crashing + 3. look into concating parent stacks into my trace + - trace is most recent at top + - (weld a b) / u3ck_weld + - u3kc_weld() + - u3kb_weld() + - best bet (zing a) + - u3kb_zing() + - nock.hoon: _n_find() + - trace.c: _t_samp_process() + - post is an offset into loom: u3to / u3of + - rod_u = u3tn(u3_road, rod_u->par_p); + + correct code example: + u3_noun lit = u3t(u3dc("mook", 2, u3k(u3R->bug.tax))); + while ( u3_nul != lit ) { + u3t_slog(u3nc(0,u3k(u3h(lit)))); + lit = u3t(lit); + } + + notes: + print the trace during 'fore' + spot hints + src code locations + assumed to be paths to hoon file in clay + wraps expressions (or tries to) + :startend + the parser handles them + dojo dissables %spots by default + we potentially can parse these against clay files + to render code in the form of + : + aka what perl, python, and everything else does + mean hints + also push/pop per expression + not locations, these are data (to pretty print?) + ~| and ~! will push a %mean hint in hoon or dojo + an example: + [ %gall-call-failed + ~[/gall/use/hood/0w2.ihwUB/out/~zod/dojo/drum/phat/~zod/dojo /dill //term/1] + [ %deal + p=[p=~zod q=~zod] + q=%dojo + r + [ %poke + cage + [ p=%sole-action + q + [ #t/ + [ id=@ta + dat + ?( + [%clr %~] + [ %det + ler=[own=@ud his=@ud] + haw=@uvH + ted + ^#2 + ?( + [%del p=@ud] + [%ins p=@ud q=@c] + [%mor p=it(#2)] + [%nop %~] + [%set p=it(@c)] + ) + ] + [%ret %~] + [%tab pos=@ud] + ) + ] + q=[1.852.707.279.204.647.268.964 7.628.146 0] + ] + ] + ] + ] + ] + to re-enable dojo spot hints do this (without the backticks): + turn on hints `!: ` + turn off hints `!. ` + + this should push %mean hint before clet or add + ~| %clet ~> %clet (add 1 1) + + ~! is a hint for compile time crashes + ~| is for runtime crash hints + + tall: + ~| %foo ~% %clet (add 2 2) + wide: + ~|(%foo ~%(%clet (add 2 2))) + + tall can contain wide but not the other way. + + road ref counts: + (expect more info from Joe on this soon) + read only access to roads above me + on road exit we copy out our data + usually some big tree + as we copy things out we inc ref count on stuff that is already in parent road + walk up the parent roads to find the + stacks to join together + + event:(timestamp, ovom:(wire, card:(tree of cells))) + */ +//----------------------------------------------------- + + /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN @@ -1689,8 +1992,54 @@ static c3_o _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { if ( c3__clep == u3h(hin) ) { - fprintf(stderr, "fore: got clep\r\n"); - *out = c3__clep; + u3_cell now = current_epoc_time_ms_as_cell(); + *out = u3i_cell(u3h(hin), now); + //// TODO: this should work, but does not + //u3_atom now = urbit_epocnow_atom(); + //*out = u3i_cell(u3h(hin), now); + sleep_ms(512); + return c3y; + } + else if ( c3__clet == u3h(hin) ) { + u3_cell now = current_epoc_time_ms_as_cell(); + *out = u3i_cell(u3h(hin), now); + //// TODO: this should work, but does not + //u3_atom now = urbit_epocnow_atom(); + //*out = u3i_cell(u3h(hin), now); + + u3_road* road = u3R; + u3_noun tax = road->bug.tax; + + /*TODO: something in this loop causes u3t_slog to fail + perhaps its the zero at the end of one of the tax lists + perhaps its on of the tax refs that IS zero + perhaps its a pointer/noun mismatch + the result is that I get what seems to be a stacktrace-on-fail + when I just want a printout of the stack... + */ + // while there is a parent road ref ... + while ( &(u3H->rod_u) != road ) { + // ... point at the next road and append its stack to tax + road = u3tn(u3_road, road->par_p); + //if (0 == road->bug.tax) { + // continue; + //} + //if (0 == tax) { + // tax = road->bug.tax; + // continue; + //} + tax = u3qb_weld(tax, road->bug.tax); + } + // render and print the stack + u3_noun lit = u3t(u3dc("mook", 2, u3k(tax))); + while ( u3_nul != lit ) { + u3t_slog(u3nc(1,u3k(u3th(lit)))); + lit = u3t(lit); + } + + //u3_noun mok = u3dc("mook", 2, tax); + //u3v_punt(blu, tab_l, u3k(u3h(mok))); + return c3y; } @@ -1706,8 +2055,83 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) static void _n_hilt_hind(u3_noun tok, u3_noun pro) { - if ( c3__clep == tok ) { - fprintf(stderr, "hind: got clep\r\n"); + /* TODO: first attempt to unpack tok + so that we can test for clep-ness + */ + u3_noun h_tok, t_tok; + u3r_cell(tok, &h_tok, &t_tok); + if ( c3__clep == h_tok ) { + // get and unpack current time + u3_noun h_now, t_now; + u3_cell timenow = current_epoc_time_ms_as_cell(); + u3r_cell(timenow, &h_now, &t_now); + + // unpack old time + u3_noun h_then, t_then; + u3r_cell(t_tok, &h_then, &t_then); + + // subtract seconds + u3_atom s = h_now - h_then; + + // subtract milliseconds + u3_atom ms; + if ( s != 0 ) { + ms = (1000+t_now) - t_then; + s -= 1; + } + else { + ms = t_now - t_then; + } + fprintf(stderr, " \r\n"); + fprintf(stderr, "clep: took sec.ms %u.%u\r\n", s, ms); + /* TODO: we need to fix this; + both u3_time_gap_double and u3_time_gap_ms crash when mem managing + and yeild wrong results when I comment out the u3z calls + */ + //u3_atom now = urbit_epocnow_atom(); + //u3_atom wen = t_tok; + //c3_c* lab_a = u3m_pretty(now); + //c3_c* lab_b = u3m_pretty(wen); + //fprintf(stderr, " \r\n"); + //fprintf(stderr, "clep: result is now:%s wen:%s\r\n", lab_a, lab_b); + //c3_d delta_time = u3_time_gap_double(u3k(now), u3k(wen)); + //fprintf(stderr, "clep: took %lu microseconds\r\n", delta_time); + } + else if ( c3__clet == h_tok ) { + // get and unpack current time + u3_noun h_now, t_now; + u3_cell timenow = current_epoc_time_ms_as_cell(); + u3r_cell(timenow, &h_now, &t_now); + + // unpack old time + u3_noun h_then, t_then; + u3r_cell(t_tok, &h_then, &t_then); + + // subtract seconds + u3_atom s = h_now - h_then; + + // subtract milliseconds + u3_atom ms; + if ( s != 0 ) { + ms = (1000+t_now) - t_then; + s -= 1; + } + else { + ms = t_now - t_then; + } + fprintf(stderr, " \r\n"); + fprintf(stderr, "clet: took sec.ms %u.%u\r\n", s, ms); + /* TODO: we need to fix this; + both u3_time_gap_double and u3_time_gap_ms crash when mem managing + and yeild wrong results when I comment out the u3z calls + */ + //u3_atom now = urbit_epocnow_atom(); + //u3_atom wen = t_tok; + //c3_c* lab_a = u3m_pretty(now); + //c3_c* lab_b = u3m_pretty(wen); + //fprintf(stderr, "clet: result is now:%s wen:%s\r\n", lab_a, lab_b); + //c3_d delta_time = u3_time_gap_double(u3k(now), u3k(wen)); + //fprintf(stderr, "clet: took %lu microseconds\r\n", delta_time); } else { c3_assert( u3_nul == tok ); @@ -1715,6 +2139,7 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) u3z(tok); } +//----------------------------------------------------- /* _n_hint_fore(): arbitrary dynamic hint, before formula evaluation ** hin: [hint-atom, formula]. TRANSFER From 48ebb1a37517f5e9a3bbc8f66ab08bc7b9820446 Mon Sep 17 00:00:00 2001 From: DaneBettis Date: Tue, 28 Sep 2021 08:54:35 +0000 Subject: [PATCH 05/13] vere: adds %bout hint, reports nanoseconds spent on the given hoon expression --- pkg/urbit/include/c/motes.h | 3 + pkg/urbit/noun/nock.c | 499 +++++------------------------------- 2 files changed, 71 insertions(+), 431 deletions(-) diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index 240086ec9..485ba9d44 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') @@ -291,6 +292,7 @@ # define c3__dago c3_s4('d','a','g','o') # define c3__dant c3_s4('d','a','n','t') # define c3__dast c3_s4('d','a','s','t') +# define c3__darg c3_s4('d','a','r','g') # define c3__data c3_s4('d','a','t','a') # define c3__dawn c3_s4('d','a','w','n') # define c3__dbug c3_s4('d','b','u','g') @@ -1050,6 +1052,7 @@ # define c3__some c3_s4('s','o','m','e') # define c3__sort c3_s4('s','o','r','t') # define c3__spal c3_s4('s','p','a','l') +# define c3__span c3_s4('s','p','a','n') # define c3__spar c3_s4('s','p','a','r') # define c3__spig c3_s4('s','p','i','g') # define c3__spil c3_s4('s','p','i','l') diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index 3d3b55ecb..a620c71de 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1021,24 +1021,9 @@ _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 c3__clep: { + case c3__bout: { fprintf(stderr," \r\n"); - fprintf(stderr, "compiling clep\r\n"); - u3_noun fen = u3_nul; - c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); - - // 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)); - tot_w += nef_w; _n_apen(ops, fen); - ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HILL : HILK); - } break; - case c3__clet: { - fprintf(stderr," \r\n"); - fprintf(stderr, "compiling clet\r\n"); + fprintf(stderr, "compiling bout\r\n"); u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); @@ -1067,9 +1052,7 @@ _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); @@ -1691,295 +1674,24 @@ u3n_find(u3_noun key, u3_noun fol) return pog_p; } -//----------------------------------------------------- -#define _POSIX_C_SOURCE 200809L -#include -#include -#include +/* TODO: this function should probably not live in nock.c + * let's put it somewhere more appropriate + */ + +/* current_epoc_time_ns(): returns milliseconds since epoc at call time +** as a 64-bit wide atom. +*/ #include -static u3_cell -current_epoc_time_ms_as_cell (void) -{ - long ms; // Milliseconds - time_t s; // Seconds - struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - s = spec.tv_sec; - // Convert nanoseconds to milliseconds - ms = round(spec.tv_nsec / 1.0e6); - if (ms > 999) { - s++; - ms = 0; - } - return u3i_cell(s, ms); -} - -/*TODO: move time functions - so that noun does not - cycle-depend upon vere - */ -#include <../include/vere/vere.h> static u3_atom -urbit_epocnow_atom (void) +current_epoc_time_ns (void) { struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - return u3_time_in_ts(&spec); + clock_gettime(CLOCK_MONOTONIC, &spec); + return u3i_chub( + (spec.tv_sec * 1000000000ULL) + spec.tv_nsec + ); } -#ifdef WIN32 -#include -#elif _POSIX_C_SOURCE >= 199309L -#include // for nanosleep -#else -#include // for usleep -#endif - -void -sleep_ms(int milliseconds) -{ // cross-platform sleep function -#ifdef WIN32 - Sleep(milliseconds); -#elif _POSIX_C_SOURCE >= 199309L - struct timespec ts; - ts.tv_sec = milliseconds / 1000; - ts.tv_nsec = (milliseconds % 1000) * 1000000; - nanosleep(&ts, NULL); -#else - if (milliseconds >= 1000) - sleep(milliseconds / 1000); - usleep((milliseconds % 1000) * 1000); -#endif -} -//----------------------------------------------------- -/* urbit dev process notes 2021-08-11: - project setup: - install nix - install git - install git-lfs - git clone urbit - cd urbit - git config credential.helper store - git config pull.rebase true - git lfs install - git lfs pull - cd pkg/urbit - nix-shell - ./configure && make -j 6 - - pills: - - brass: formal bootstrap - - solid: fast boot for development (logically, partially-evaluated brass) - - ivory: runtime support - my pill locations: - urbit/bin/brass.pill - urbit/bin/ivory.pill - urbit/bin/solid.pill - urbit/pkg/hs/urbit-king/test/gold/hoontree.pill - - boot a fake ship: - build/urbit -F name-of-any-ship-except-comets - - - - these are all the same: - build/urbit -F zod - build/urbit -F zod -c zod - build/urbit -F zod -u bootstrap.urbit.org/$URBIT_VERSION.pill - - this is the standard local dev command: - build/urbit -l -F zod -B path/to/pill -A path/to/arvo -c name-of-fake-ship - my version: - # create a fake ship zod with a peir named fakezod, lite boot using fast boot pill and the local arvo path - build/urbit -c ../../fakezod -F zod -l -B ../../bin/solid.pill -A ../arvo - - to restart: - build/urbit name-of-fake-ship - my version: - # this should resume the above ship with all the settings - build/urbit fakezod - - notable urbit binary flags: - * -L: local-only networking (automatically set for fake ships) - * -u: download pill from url - * -B: boot from local pill at path - * -l: lite-boot (faster, limited userspace) - * -A: load filesystem from local arvo directory - - to test clep: - # in the fake zod dojo type and enter this: - ~> %clep (add 2 2) - - bootstrap formula (see media.urbit.org/whitepaper.pdf): - [%2 [%0 3] %0 2] - - - - >>>>> commands to use during main dev cycle: - [urbit git root]$ cd pkg/urbit/ && nix-shell && cd ../.. - [nix-shell urbit/pkg/urbit]$ ./configure && make -j 6 && build/urbit ../../fakezod - ~zod:dojo> !: ~> %clep (add 1 2) - ~zod:dojo> !: ~> %clet (add 4 1) - - dynamic hint protocol: - commonly used hints are directly represented in the u3 bytecode for performance, and adding new opcodes is an involved task. - - in urbit-v1.0, we introduced a protocol for implementing dynamic hint handlers. hints must be whitelisted in the nock->bytecode compiler, and handlers are implemented in before/after callback functions: - - https://github.com/urbit/urbit/pull/3979 - - there are two kinds of dynamic hint handlers, mirroring the two hint reduction rules (opcode 11) in the nock spec. the first is an atomic hint, which is merely a label; the second is a labeled nock formula, which can convey arbitrary data to the runtime. these are compiled into different bytecodes, and handled in different callbacks. - - hints are whitelisted in _n_bint() (the "hint-processing helper" for the bytecode compiler in _n_comp()). there are separate case statements for the separate hint types, and whitelisting a given hint merely involves adding a fallthru case (the default case discards the hint while preserving nock semantics). to simplify memory management, hint labels should be "motes" -- compile-time constants of up to 4 letters, defined in motes.h. - - atomic hint handlers are added to _n_hilt_fore()/_n_hilt_hind(), arbitrary hint handlers in _n_hint_fore()/_n_hint_hind() - */ - -/* urbit grant notes 2021-08-18: - Here's a quick rundown of u3's stack trace production mechanism: - - - the bytecode interpreter maintains a trace stack via - u3t_push()/u3t_mean() and u3t_drop() - - - the frames in that stack are unrendered - Many frames are just data, like the %spot hints that record source locations. But some contain code, like the %mean hints from ~|. - - - the stack is stored in the current road, at u3R->bug.tax - - - traces are currently only produced for failed/interrupted virtual computations - - - Virtualization is performed by u3m_soft() and related variants. - It involves a setjmp() call to trap for "exceptions", and a new inner road (u3m_leap()) to establish an isolated memory arena. - "Exceptions" are "thrown" via longjmp(), in u3m_bail() or a signal handler. - - In some more detail: - - Every event is run virtualized via u3m_soft. see _serf_poke() in worker/serf.c - - Inside an event, further levels of virtualization are established via the +mink jet, which eventually calls u3m_soft_run() - - Successful computations, namespace blocks, and deterministic bails, such as u3m_bail(c3__exit), are all returned directly to the parent context - - Non-deterministic bails cannot be trapped, and unwind the entire execution context by re-bailing at each layer. - - In the case of a deterministic bail, the product of +mink / u3m_soft_run() is a proto-stack trace - - To render that to (list tank), ie $tang, we call `+mook`, which formats each entry in urbit's print format ($tank), and evaluates any lazy/deferred frames - - There's no C implementation, so we just make a dynamic call into nock - - A representative call-site is in u3m_soft() - ------- - - At any point time, the logical current trace stack may be spread across many roads, if we're deeply nested in virtual contexts - - There is not currently any code that combines those traces directly; they're currently combined by unwinding/re-bailing - - For an initial implementation, I would only print the trace from the current road. - - Eventually, we'll want to gather the trace stack from all roads, and probably virtualize the call to +mook. - - */ - -/* urbit grant todo/notes 2021-08-25: - - u3t_init()/u3t_boot() are called on loom/inner-road init - - u3t_on()/u3t_off() establishing modes/labels for -P sampling profiler (and no-op without the compile-time MEMORY_DEBUG option) - - >>>> Brad jump to THIS! <<<<<< - 1. be able to session drive next time - 2. DONE: poc of print traces without crashing - 3. look into concating parent stacks into my trace - - trace is most recent at top - - (weld a b) / u3ck_weld - - u3kc_weld() - - u3kb_weld() - - best bet (zing a) - - u3kb_zing() - - nock.hoon: _n_find() - - trace.c: _t_samp_process() - - post is an offset into loom: u3to / u3of - - rod_u = u3tn(u3_road, rod_u->par_p); - - correct code example: - u3_noun lit = u3t(u3dc("mook", 2, u3k(u3R->bug.tax))); - while ( u3_nul != lit ) { - u3t_slog(u3nc(0,u3k(u3h(lit)))); - lit = u3t(lit); - } - - notes: - print the trace during 'fore' - spot hints - src code locations - assumed to be paths to hoon file in clay - wraps expressions (or tries to) - :startend - the parser handles them - dojo dissables %spots by default - we potentially can parse these against clay files - to render code in the form of - : - aka what perl, python, and everything else does - mean hints - also push/pop per expression - not locations, these are data (to pretty print?) - ~| and ~! will push a %mean hint in hoon or dojo - an example: - [ %gall-call-failed - ~[/gall/use/hood/0w2.ihwUB/out/~zod/dojo/drum/phat/~zod/dojo /dill //term/1] - [ %deal - p=[p=~zod q=~zod] - q=%dojo - r - [ %poke - cage - [ p=%sole-action - q - [ #t/ - [ id=@ta - dat - ?( - [%clr %~] - [ %det - ler=[own=@ud his=@ud] - haw=@uvH - ted - ^#2 - ?( - [%del p=@ud] - [%ins p=@ud q=@c] - [%mor p=it(#2)] - [%nop %~] - [%set p=it(@c)] - ) - ] - [%ret %~] - [%tab pos=@ud] - ) - ] - q=[1.852.707.279.204.647.268.964 7.628.146 0] - ] - ] - ] - ] - ] - to re-enable dojo spot hints do this (without the backticks): - turn on hints `!: ` - turn off hints `!. ` - - this should push %mean hint before clet or add - ~| %clet ~> %clet (add 1 1) - - ~! is a hint for compile time crashes - ~| is for runtime crash hints - - tall: - ~| %foo ~% %clet (add 2 2) - wide: - ~|(%foo ~%(%clet (add 2 2))) - - tall can contain wide but not the other way. - - road ref counts: - (expect more info from Joe on this soon) - read only access to roads above me - on road exit we copy out our data - usually some big tree - as we copy things out we inc ref count on stuff that is already in parent road - walk up the parent roads to find the - stacks to join together - - event:(timestamp, ovom:(wire, card:(tree of cells))) - */ -//----------------------------------------------------- - - /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN @@ -1991,60 +1703,15 @@ sleep_ms(int milliseconds) static c3_o _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { - if ( c3__clep == u3h(hin) ) { - u3_cell now = current_epoc_time_ms_as_cell(); + if ( c3__bout == u3h(hin) ) { + u3_atom now = current_epoc_time_ns(); *out = u3i_cell(u3h(hin), now); - //// TODO: this should work, but does not - //u3_atom now = urbit_epocnow_atom(); - //*out = u3i_cell(u3h(hin), now); - sleep_ms(512); - return c3y; - } - else if ( c3__clet == u3h(hin) ) { - u3_cell now = current_epoc_time_ms_as_cell(); - *out = u3i_cell(u3h(hin), now); - //// TODO: this should work, but does not - //u3_atom now = urbit_epocnow_atom(); - //*out = u3i_cell(u3h(hin), now); - - u3_road* road = u3R; - u3_noun tax = road->bug.tax; - - /*TODO: something in this loop causes u3t_slog to fail - perhaps its the zero at the end of one of the tax lists - perhaps its on of the tax refs that IS zero - perhaps its a pointer/noun mismatch - the result is that I get what seems to be a stacktrace-on-fail - when I just want a printout of the stack... - */ - // while there is a parent road ref ... - while ( &(u3H->rod_u) != road ) { - // ... point at the next road and append its stack to tax - road = u3tn(u3_road, road->par_p); - //if (0 == road->bug.tax) { - // continue; - //} - //if (0 == tax) { - // tax = road->bug.tax; - // continue; - //} - tax = u3qb_weld(tax, road->bug.tax); - } - // render and print the stack - u3_noun lit = u3t(u3dc("mook", 2, u3k(tax))); - while ( u3_nul != lit ) { - u3t_slog(u3nc(1,u3k(u3th(lit)))); - lit = u3t(lit); - } - - //u3_noun mok = u3dc("mook", 2, tax); - //u3v_punt(blu, tab_l, u3k(u3h(mok))); - - return c3y; } + else { + *out = u3_nul; + } u3z(hin); - *out = u3_nul; return c3y; } @@ -2055,83 +1722,15 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) static void _n_hilt_hind(u3_noun tok, u3_noun pro) { - /* TODO: first attempt to unpack tok - so that we can test for clep-ness - */ u3_noun h_tok, t_tok; u3r_cell(tok, &h_tok, &t_tok); - if ( c3__clep == h_tok ) { - // get and unpack current time - u3_noun h_now, t_now; - u3_cell timenow = current_epoc_time_ms_as_cell(); - u3r_cell(timenow, &h_now, &t_now); - - // unpack old time - u3_noun h_then, t_then; - u3r_cell(t_tok, &h_then, &t_then); - - // subtract seconds - u3_atom s = h_now - h_then; - - // subtract milliseconds - u3_atom ms; - if ( s != 0 ) { - ms = (1000+t_now) - t_then; - s -= 1; - } - else { - ms = t_now - t_then; - } - fprintf(stderr, " \r\n"); - fprintf(stderr, "clep: took sec.ms %u.%u\r\n", s, ms); - /* TODO: we need to fix this; - both u3_time_gap_double and u3_time_gap_ms crash when mem managing - and yeild wrong results when I comment out the u3z calls - */ - //u3_atom now = urbit_epocnow_atom(); - //u3_atom wen = t_tok; - //c3_c* lab_a = u3m_pretty(now); - //c3_c* lab_b = u3m_pretty(wen); - //fprintf(stderr, " \r\n"); - //fprintf(stderr, "clep: result is now:%s wen:%s\r\n", lab_a, lab_b); - //c3_d delta_time = u3_time_gap_double(u3k(now), u3k(wen)); - //fprintf(stderr, "clep: took %lu microseconds\r\n", delta_time); - } - else if ( c3__clet == h_tok ) { - // get and unpack current time - u3_noun h_now, t_now; - u3_cell timenow = current_epoc_time_ms_as_cell(); - u3r_cell(timenow, &h_now, &t_now); - - // unpack old time - u3_noun h_then, t_then; - u3r_cell(t_tok, &h_then, &t_then); - - // subtract seconds - u3_atom s = h_now - h_then; - - // subtract milliseconds - u3_atom ms; - if ( s != 0 ) { - ms = (1000+t_now) - t_then; - s -= 1; - } - else { - ms = t_now - t_then; - } - fprintf(stderr, " \r\n"); - fprintf(stderr, "clet: took sec.ms %u.%u\r\n", s, ms); - /* TODO: we need to fix this; - both u3_time_gap_double and u3_time_gap_ms crash when mem managing - and yeild wrong results when I comment out the u3z calls - */ - //u3_atom now = urbit_epocnow_atom(); - //u3_atom wen = t_tok; - //c3_c* lab_a = u3m_pretty(now); - //c3_c* lab_b = u3m_pretty(wen); - //fprintf(stderr, "clet: result is now:%s wen:%s\r\n", lab_a, lab_b); - //c3_d delta_time = u3_time_gap_double(u3k(now), u3k(wen)); - //fprintf(stderr, "clet: took %lu microseconds\r\n", delta_time); + if ( c3__bout == h_tok ) { + u3_atom delta = u3ka_sub(current_epoc_time_ns(), u3k(t_tok) ); + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 " nanoseconds", u3r_chub(0, delta) ); + // TODO: can we make our statement show up AFTER the echo of the hoon cmd in dojo? + u3t_slog(u3nc(0, u3i_string(str_c))); + u3z(delta); } else { c3_assert( u3_nul == tok ); @@ -2153,8 +1752,16 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) 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 = current_epoc_time_ns(); + *clu = u3i_trel(u3h(hin), *clu, now); + } + else { + u3z(*clu); + *clu = u3_nul; + } + + u3z(hin); return c3y; } @@ -2165,7 +1772,34 @@ _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; + u3r_trel(tok, &p_tok, &q_tok, &r_tok); + if ( c3__bout == p_tok ) { + // get the nanoseconds elapsed + u3_atom delta = u3ka_sub(current_epoc_time_ns(), u3k(r_tok) ); + + // unpack q_tok to get the C string from the tank + u3_noun q_tok_h, q_tok_t; + u3r_cell(q_tok, &q_tok_h, &q_tok_t); + c3_y* str_b = u3r_tape(q_tok_t); + + // format the timing report and the clu sting from q_tok together + c3_c str_c[64]; + snprintf(str_c, 63, "%s: took %" PRIu64 " nanoseconds", str_b, u3r_chub(0, delta) ); + + // TODO: can we make our statements show up AFTER the echo of the hoon cmd in dojo? + + // send the head of the tank (severity) and the report string to the terminal + // to handle it as it wants, when it wants + u3t_slog(u3nc(q_tok_h, u3i_string(str_c))); + + // TODO: do I need to u3z any of the local vars I've defined? + u3z(delta); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } @@ -2202,6 +1836,9 @@ typedef struct { * mov: -1 north, 1 south * off: 0 north, -1 south */ +// thats telekinesis Kyle! +// this is where I can steal u3t_heck calls and other +// profile printing goodness from! static u3_noun _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) { From 9cb53597fbe6caf0916a96631e39da8a59137ffe Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 12 Oct 2021 11:33:12 -0400 Subject: [PATCH 06/13] ur: fixes "stack" overflow in preorder traversal, simplifies "stack" --- pkg/urbit/ur/hashcons.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) 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 From 94878e695e50dd07c3395b457861fd93faa77af9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 12 Oct 2021 11:34:09 -0400 Subject: [PATCH 07/13] ur: fixes preorder handle destructor in jam handle destructor --- pkg/urbit/ur/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From ef6251c87ca10042267dc2e089ea5dec60f8d026 Mon Sep 17 00:00:00 2001 From: DaneBettis Date: Wed, 13 Oct 2021 19:14:56 +0000 Subject: [PATCH 08/13] vere: altered %bout, now reports microseconds --- pkg/urbit/include/c/motes.h | 2 - pkg/urbit/include/noun/trace.h | 6 +++ pkg/urbit/noun/manage.c | 2 - pkg/urbit/noun/nock.c | 90 +++++++++++++--------------------- 4 files changed, 41 insertions(+), 59 deletions(-) diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index 485ba9d44..520f7fc35 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -292,7 +292,6 @@ # define c3__dago c3_s4('d','a','g','o') # define c3__dant c3_s4('d','a','n','t') # define c3__dast c3_s4('d','a','s','t') -# define c3__darg c3_s4('d','a','r','g') # define c3__data c3_s4('d','a','t','a') # define c3__dawn c3_s4('d','a','w','n') # define c3__dbug c3_s4('d','b','u','g') @@ -1052,7 +1051,6 @@ # define c3__some c3_s4('s','o','m','e') # define c3__sort c3_s4('s','o','r','t') # define c3__spal c3_s4('s','p','a','l') -# define c3__span c3_s4('s','p','a','n') # define c3__spar c3_s4('s','p','a','r') # define c3__spig c3_s4('s','p','i','g') # define c3__spil c3_s4('s','p','i','l') 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/manage.c b/pkg/urbit/noun/manage.c index 522a2dcd4..4833228ff 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -1725,8 +1725,6 @@ u3m_boot(c3_c* dir_c) u3j_ream(); u3n_ream(); - u3m_reclaim(); - return u3A->eve_d; } else { diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index a620c71de..b4eaeddca 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1,7 +1,7 @@ /* g/n.c ** */ -#include "all.h" +#include "../include/all.h" // define to have each opcode printed as it executes, // along with some other debugging info @@ -1022,8 +1022,6 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) } case c3__bout: { - fprintf(stderr," \r\n"); - fprintf(stderr, "compiling bout\r\n"); u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); @@ -1052,7 +1050,7 @@ _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; - case c3__bout: { + case c3__bout: { u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); @@ -1674,24 +1672,6 @@ u3n_find(u3_noun key, u3_noun fol) return pog_p; } -/* TODO: this function should probably not live in nock.c - * let's put it somewhere more appropriate - */ - -/* current_epoc_time_ns(): returns milliseconds since epoc at call time -** as a 64-bit wide atom. -*/ -#include -static u3_atom -current_epoc_time_ns (void) -{ - struct timespec spec; - clock_gettime(CLOCK_MONOTONIC, &spec); - return u3i_chub( - (spec.tv_sec * 1000000000ULL) + spec.tv_nsec - ); -} - /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN @@ -1704,12 +1684,12 @@ static c3_o _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { if ( c3__bout == u3h(hin) ) { - u3_atom now = current_epoc_time_ns(); + u3_atom now = u3i_chub(u3t_trace_time()); *out = u3i_cell(u3h(hin), now); } - else { - *out = u3_nul; - } + else { + *out = u3_nul; + } u3z(hin); return c3y; @@ -1725,10 +1705,9 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) u3_noun h_tok, t_tok; u3r_cell(tok, &h_tok, &t_tok); if ( c3__bout == h_tok ) { - u3_atom delta = u3ka_sub(current_epoc_time_ns(), u3k(t_tok) ); - c3_c str_c[64]; - snprintf(str_c, 63, "took %" PRIu64 " nanoseconds", u3r_chub(0, delta) ); - // TODO: can we make our statement show up AFTER the echo of the hoon cmd in dojo? + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(t_tok)); + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 " microseconds", u3r_chub(0, delta) ); u3t_slog(u3nc(0, u3i_string(str_c))); u3z(delta); } @@ -1738,7 +1717,6 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) u3z(tok); } -//----------------------------------------------------- /* _n_hint_fore(): arbitrary dynamic hint, before formula evaluation ** hin: [hint-atom, formula]. TRANSFER @@ -1753,15 +1731,15 @@ static c3_o _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) { if ( c3__bout == u3h(hin) ) { - u3_atom now = current_epoc_time_ns(); + u3_atom now = u3i_chub(u3t_trace_time()); *clu = u3i_trel(u3h(hin), *clu, now); } - else { - u3z(*clu); - *clu = u3_nul; - } + else { + u3z(*clu); + *clu = u3_nul; + } - u3z(hin); + u3z(hin); return c3y; } @@ -1775,25 +1753,30 @@ _n_hint_hind(u3_noun tok, u3_noun pro) u3_noun p_tok, q_tok, r_tok; u3r_trel(tok, &p_tok, &q_tok, &r_tok); if ( c3__bout == p_tok ) { - // get the nanoseconds elapsed - u3_atom delta = u3ka_sub(current_epoc_time_ns(), u3k(r_tok) ); + // get the microseconds elapsed + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok)); - // unpack q_tok to get the C string from the tank - u3_noun q_tok_h, q_tok_t; - u3r_cell(q_tok, &q_tok_h, &q_tok_t); - c3_y* str_b = u3r_tape(q_tok_t); + // unpack q_tok to get the C string from the tank + u3_noun q_tok_h, q_tok_t; + u3r_cell(q_tok, &q_tok_h, &q_tok_t); - // format the timing report and the clu sting from q_tok together - c3_c str_c[64]; - snprintf(str_c, 63, "%s: took %" PRIu64 " nanoseconds", str_b, u3r_chub(0, delta) ); - - // TODO: can we make our statements show up AFTER the echo of the hoon cmd in dojo? + // format the timing report and the clu sting from q_tok together + c3_c str_c[64]; + snprintf(str_c, 63, " took %" PRIu64 " microseconds", u3r_chub(0, delta) ); - // send the head of the tank (severity) and the report string to the terminal - // to handle it as it wants, when it wants - u3t_slog(u3nc(q_tok_h, u3i_string(str_c))); + // send the head of the tank (severity) and the report string to the terminal + // to handle it as it wants, when it wants + u3t_slog( + u3nc( + u3k(q_tok_h), + u3nt( + c3__rose, + u3nt(u3nc(':', u3_nul), u3_nul, u3_nul), + u3nt(u3k(q_tok_t), u3i_string(str_c), u3_nul) + ) + ) + ); - // TODO: do I need to u3z any of the local vars I've defined? u3z(delta); } else { @@ -1836,9 +1819,6 @@ typedef struct { * mov: -1 north, 1 south * off: 0 north, -1 south */ -// thats telekinesis Kyle! -// this is where I can steal u3t_heck calls and other -// profile printing goodness from! static u3_noun _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) { From 6dcbb82f54c6fd9fd75ec6e5da9df16d31f753d0 Mon Sep 17 00:00:00 2001 From: DaneBettis Date: Wed, 20 Oct 2021 19:07:41 +0000 Subject: [PATCH 09/13] vere: altered %bout to use micro symbol, fixed comments --- pkg/arvo/ted/test.hoon | 4 +++- pkg/urbit/noun/nock.c | 27 +++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pkg/arvo/ted/test.hoon b/pkg/arvo/ted/test.hoon index a25496fc2..1a43a53d2 100644 --- a/pkg/arvo/ted/test.hoon +++ b/pkg/arvo/ted/test.hoon @@ -14,11 +14,12 @@ => |% :: +run-test: execute an individual test -:: +:: see photo ++ run-test |= [pax=path test=test-func] ^- [ok=? =tang] =+ name=(spud pax) + ~> %bout =+ run=(mule test) ?- -.run %| |+(welp p.run leaf+"CRASHED {name}" ~) @@ -67,6 +68,7 @@ ~| [%failed-to-compile-test-arm name] q:(~(mint ut typ) p:!>(*tang) [%limb name]) [name |.(;;(tang .*(cor fire-arm)))] +:: see photo :: +has-test-prefix: does the arm define a test we should run? :: ++ has-test-prefix diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index b4eaeddca..eaf1ca098 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1,7 +1,7 @@ /* g/n.c ** */ -#include "../include/all.h" +#include "all.h" // define to have each opcode printed as it executes, // along with some other debugging info @@ -1707,7 +1707,7 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) if ( c3__bout == h_tok ) { u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(t_tok)); c3_c str_c[64]; - snprintf(str_c, 63, "took %" PRIu64 " microseconds", u3r_chub(0, delta) ); + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); u3t_slog(u3nc(0, u3i_string(str_c))); u3z(delta); } @@ -1756,23 +1756,26 @@ _n_hint_hind(u3_noun tok, u3_noun pro) // get the microseconds elapsed u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok)); - // unpack q_tok to get the C string from the tank - u3_noun q_tok_h, q_tok_t; - u3r_cell(q_tok, &q_tok_h, &q_tok_t); + // 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; + u3r_cell(q_tok, &p_q_tok, &q_q_tok); - // format the timing report and the clu sting from q_tok together + // format the timing report c3_c str_c[64]; - snprintf(str_c, 63, " took %" PRIu64 " microseconds", u3r_chub(0, delta) ); + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); - // send the head of the tank (severity) and the report string to the terminal - // to handle it as it wants, when it wants + // 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(q_tok_h), + u3k(p_q_tok), u3nt( c3__rose, - u3nt(u3nc(':', u3_nul), u3_nul, u3_nul), - u3nt(u3k(q_tok_t), u3i_string(str_c), u3_nul) + u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul), + u3nt(u3k(q_q_tok), u3i_string(str_c), u3_nul) ) ) ); From 66f8a893a65ff9186b89ba69a74644bfa9d6121b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 13 Oct 2021 00:35:07 -0400 Subject: [PATCH 10/13] serf: fix replay %bail response $plea construction --- pkg/urbit/worker/serf.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) 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)); } } From c28aace72f36a6dba964021431cc35a6ff656c07 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 13 Oct 2021 00:37:30 -0400 Subject: [PATCH 11/13] vere: fix off-by-one in mug check on replay %bail --- pkg/urbit/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 9dce9359e548d1dc74e4e1731ba2ff338363bfc7 Mon Sep 17 00:00:00 2001 From: DaneBettis Date: Wed, 27 Oct 2021 18:49:55 +0000 Subject: [PATCH 12/13] vere: added %bout sanity checks, added bout call in test.hoon --- pkg/arvo/ted/test.hoon | 6 ++---- pkg/urbit/noun/nock.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/arvo/ted/test.hoon b/pkg/arvo/ted/test.hoon index 1a43a53d2..43a81700c 100644 --- a/pkg/arvo/ted/test.hoon +++ b/pkg/arvo/ted/test.hoon @@ -14,12 +14,11 @@ => |% :: +run-test: execute an individual test -:: see photo +:: ++ run-test |= [pax=path test=test-func] ^- [ok=? =tang] =+ name=(spud pax) - ~> %bout =+ run=(mule test) ?- -.run %| |+(welp p.run leaf+"CRASHED {name}" ~) @@ -67,8 +66,7 @@ =/ fire-arm=nock ~| [%failed-to-compile-test-arm name] q:(~(mint ut typ) p:!>(*tang) [%limb name]) - [name |.(;;(tang .*(cor fire-arm)))] -:: see photo + [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/noun/nock.c b/pkg/urbit/noun/nock.c index eaf1ca098..1a77f4873 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1702,11 +1702,10 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) static void _n_hilt_hind(u3_noun tok, u3_noun pro) { - u3_noun h_tok, t_tok; - u3r_cell(tok, &h_tok, &t_tok); - if ( c3__bout == h_tok ) { - u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(t_tok)); - c3_c str_c[64]; + 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); @@ -1751,15 +1750,16 @@ static void _n_hint_hind(u3_noun tok, u3_noun pro) { u3_noun p_tok, q_tok, r_tok; - u3r_trel(tok, &p_tok, &q_tok, &r_tok); - if ( c3__bout == p_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; - u3r_cell(q_tok, &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]; From 524ca6f81b95ed65c44df3d68c3b8ee588942798 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Wed, 17 Mar 2021 12:18:28 -0700 Subject: [PATCH 13/13] add stack cleanup for computation-skipping dynamic hints --- pkg/urbit/noun/nock.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index bc41e5ddd..1c03e35df 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1026,13 +1026,19 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) case u3_none: { 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; } } @@ -1057,14 +1063,21 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) case u3_none: { 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;