Adds %meme and %xray hints.

%meme reports mem usage at callsite.
%xray prints the vere bytecode of the hoon tree wrapped by the hint.
This commit is contained in:
DaneBettis 2022-03-18 09:10:57 +00:00
parent 460e7c8800
commit 2dfde98b0f
6 changed files with 812 additions and 102 deletions

View File

@ -2,7 +2,7 @@
:: there is no need to include the hints for dynamic %bout
:: since all hoon tests exersize dynamic %bout
|%
:: these test that the hilt-trace hints
:: these test that the hilt trace hints
:: are safe to run or ignore
++ test-hela-hilt
~> %hela
@ -10,7 +10,12 @@
++ test-nara-hilt
~> %nara
~
:: these test that the hint-trace hints
:: test that the hilt memory-report hint
:: is safe to run or ignore
++ test-meme-hilt
~> %meme
~
:: these test that the hint trace hints
:: are safe to run or ignore
++ test-hela-hint
~> %hela.[1 leaf+"test-hela-trace-hint"]
@ -18,4 +23,9 @@
++ test-nara-hint
~> %nara.[1 leaf+"test-nara-trace-hint"]
~
:: test that the hilt memory-report hint
:: is safe to run or ignore
++ test-meme-hint
~> %meme.[1 leaf+"test-meme-hint"]
~
--

View File

@ -1296,6 +1296,7 @@
# define c3__wtts c3_s4('w','t','t','s')
# define c3__wtzp c3_s4('w','t','z','p')
# define c3__wyrd c3_s4('w','y','r','d')
# define c3__xray c3_s4('x','r','a','y')
# define c3__yell c3_s4('y','e','l','l')
# define c3__yelp c3_s4('y','e','l','p')
# define c3__z c3_s1('z')

View File

@ -154,8 +154,37 @@
void
u3t_slog_hela(c3_l pri_l);
/** Globals.
**/
/* u3t_meme(): report memory stats at call time
*/
void
u3t_slog_meme(c3_l pri_l);
/* u3t_xray(): collect the bytecode data
** for the expression wrapped in the 'calling' hint
** and print it to the terminal
*/
void
u3t_slog_xray(c3_l pri_l, u3_noun inf);
/* u3t_slog_xray_raw(): this is for me to hack on
** it must be replace with u3t_xray() before release.
*/
void
u3t_slog_xray_raw(c3_l pri_l, u3_noun fol, c3_w ip_w);
/* u3t_slog_memory():
*/
void
u3t_slog_memory(c3_l pri_l, c3_c* cap_c, float percent, c3_w wor_w);
/* u3t_slog_steps():
*/
void
u3t_slog_steps(c3_l pri_l, c3_c* cap_c, c3_d sep_d);
/* Globals.
*/
/* u3_Trace / u3C: global memory control.
*/
c3_global u3t_trace u3t_Trace;

View File

@ -1136,11 +1136,17 @@ u3m_soft_run(u3_noun gul,
u3t_off(coy_o);
pro = fun_f(aga, agb);
/*
#ifdef U3_CPU_DEBUG
// TODO: maybe this should just go away since the %meme hint reports this better
if ( u3R->all.max_w > 1000000 ) {
// the old interupting way
u3a_print_memory(stderr, "execute: run", u3R->all.max_w);
// the new well behaved way
u3t_slog_memory(2, "execute: run", 0.0, u3R->all.max_w*4);
}
#endif
*/
/* Today you can't run -g without memory debug, but you should be
* able to.
@ -1830,7 +1836,8 @@ u3m_boot(c3_c* dir_c)
if ( c3n == nuu_o ) {
u3j_ream();
u3n_ream();
// TODO: remove me before PR
u3m_reclaim();
return u3A->eve_d;
}
else {

View File

@ -388,102 +388,107 @@ _n_nock_on(u3_noun bus, u3_noun fol)
// the opcode's enum name, string representation, and computed goto into a
// single structure.
#define OPCODES \
/* general purpose */ \
X(HALT, "halt", &&do_halt), /* 0 */ \
X(BAIL, "bail", &&do_bail), /* 1 */ \
/* non-nock bytecodes */ \
X(HALT, "halt", &&do_halt), /* 0: terminator, end of bytcode program */ \
X(BAIL, "bail", &&do_bail), /* 1: deterministic crash */ \
/* stack manipulation */ \
X(COPY, "copy", &&do_copy), /* 2 */ \
X(SWAP, "swap", &&do_swap), /* 3 */ \
X(TOSS, "toss", &&do_toss), /* 4 */ \
X(AUTO, "auto", &&do_auto), /* 5 */ \
X(AULT, "ault", &&do_ault), /* 6 */ \
X(SNOC, "snoc", &&do_snoc), /* 7 */ \
X(SNOL, "snol", &&do_snol), /* 8 */ \
X(HEAD, "head", &&do_head), /* 9 */ \
X(HELD, "held", &&do_held), /* 10 */ \
X(TAIL, "tail", &&do_tail), /* 11 */ \
X(TALL, "tall", &&do_tall), /* 12 */ \
/* fragment (keep) */ \
X(FABK, "fabk", &&do_fabk), /* 13 */ \
X(FASK, "fask", &&do_fask), /* 14 */ \
X(FIBK, "fibk", &&do_fibk), /* 15 */ \
X(FISK, "fisk", &&do_fisk), /* 16 */ \
/* fragment (lose) */ \
X(FABL, "fabl", &&do_fabl), /* 17 */ \
X(FASL, "fasl", &&do_fasl), /* 18 */ \
X(FIBL, "fibl", &&do_fibl), /* 19 */ \
X(FISL, "fisl", &&do_fisl), /* 20 */ \
/* literal (keep) */ \
X(LIT0, "lit0", &&do_lit0), /* 21 */ \
X(LIT1, "lit1", &&do_lit1), /* 22 */ \
X(LITB, "litb", &&do_litb), /* 23 */ \
X(LITS, "lits", &&do_lits), /* 24 */ \
X(LIBK, "libk", &&do_libk), /* 25 */ \
X(LISK, "lisk", &&do_lisk), /* 26 */ \
/* literal (lose) */ \
X(LIL0, "lil0", &&do_lil0), /* 27 */ \
X(LIL1, "lil1", &&do_lil1), /* 28 */ \
X(LILB, "lilb", &&do_lilb), /* 29 */ \
X(LILS, "lils", &&do_lils), /* 30 */ \
X(LIBL, "libl", &&do_libl), /* 31 */ \
X(LISL, "lisl", &&do_lisl), /* 32 */ \
/* nock */ \
/* auto-cons */ \
X(AUTO, "auto", &&do_auto), /* 5: keep */ \
X(AULT, "ault", &&do_ault), /* 6: lose */ \
/* general purposes */ \
X(SNOC, "snoc", &&do_snoc), /* 7: keep */ \
X(SNOL, "snol", &&do_snol), /* 8: lose */ \
/* nock 0: head */ \
X(HEAD, "head", &&do_head), /* 9: keep */ \
X(HELD, "held", &&do_held), /* 10: lose */ \
/* nock 0: tail */ \
X(TAIL, "tail", &&do_tail), /* 11: keep */ \
X(TALL, "tall", &&do_tall), /* 12: lose */ \
/* nock 0: fragment (keep) */ \
X(FABK, "fabk", &&do_fabk), /* 13: c3_y */ \
X(FASK, "fask", &&do_fask), /* 14: c3_s */ \
X(FIBK, "fibk", &&do_fibk), /* 15: c3_y */ \
X(FISK, "fisk", &&do_fisk), /* 16: c3_s */ \
/* nock 0: fragment (lose) */ \
X(FABL, "fabl", &&do_fabl), /* 17: c3_y */ \
X(FASL, "fasl", &&do_fasl), /* 18: c3_s */ \
X(FIBL, "fibl", &&do_fibl), /* 19: c3_y */ \
X(FISL, "fisl", &&do_fisl), /* 20: c3_s */ \
/* nock 1: literal (keep) */ \
X(LIT0, "lit0", &&do_lit0), /* 21: a literal 0 */ \
X(LIT1, "lit1", &&do_lit1), /* 22: a literal 1 */ \
X(LITB, "litb", &&do_litb), /* 23: c3_y */ \
X(LITS, "lits", &&do_lits), /* 24: c3_s */ \
X(LIBK, "libk", &&do_libk), /* 25: c3_y */ \
X(LISK, "lisk", &&do_lisk), /* 26: c3_s */ \
/* nock 1: literal (lose) */ \
X(LIL0, "lil0", &&do_lil0), /* 27: a literal 0 */ \
X(LIL1, "lil1", &&do_lil1), /* 28: a literal 1 */ \
X(LILB, "lilb", &&do_lilb), /* 29: c3_y */ \
X(LILS, "lils", &&do_lils), /* 30: c3_s */ \
X(LIBL, "libl", &&do_libl), /* 31: c3_y */ \
X(LISL, "lisl", &&do_lisl), /* 32: c3_s */ \
/* nock 2: nock (lose) */ \
X(NOLK, "nolk", &&do_nolk), /* 33 */ \
X(NOCT, "noct", &&do_noct), /* 34 */ \
X(NOCK, "nock", &&do_nock), /* 35 */ \
/* 3 & 4 */ \
/* nock 3 & 4 */ \
X(DEEP, "deep", &&do_deep), /* 36 */ \
X(BUMP, "bump", &&do_bump), /* 37 */ \
/* equality */ \
X(SAM0, "sam0", &&do_sam0), /* 38 */ \
X(SAM1, "sam1", &&do_sam1), /* 39 */ \
X(SAMB, "samb", &&do_samb), /* 40 */ \
X(SAMS, "sams", &&do_sams), /* 41 */ \
X(SANB, "sanb", &&do_sanb), /* 42 */ \
X(SANS, "sans", &&do_sans), /* 43 */ \
/* nock 5: equality */ \
X(SAM0, "sam0", &&do_sam0), /* 38: test that it is equal to 0 */ \
X(SAM1, "sam1", &&do_sam1), /* 39: test that it is equal to 1 */ \
X(SAMB, "samb", &&do_samb), /* 40: test equality for vars size c3_b */ \
X(SAMS, "sams", &&do_sams), /* 41: test equality for vars size c3_s */ \
X(SANB, "sanb", &&do_sanb), /* 42: test equality for vars size c3_b */ \
X(SANS, "sans", &&do_sans), /* 43: test equality for vars size c3_s */ \
X(SAME, "same", &&do_same), /* 44 */ \
X(SALM, "salm", &&do_salm), /* 45 */ \
X(SAMC, "samc", &&do_samc), /* 46 */ \
/* unconditional skips */ \
X(SBIP, "sbip", &&do_sbip), /* 47 */ \
X(SIPS, "sips", &&do_sips), /* 48 */ \
X(SWIP, "swip", &&do_swip), /* 49 */ \
/* conditional skips */ \
X(SBIN, "sbin", &&do_sbin), /* 50 */ \
X(SINS, "sins", &&do_sins), /* 51 */ \
X(SWIN, "swin", &&do_swin), /* 52 */ \
/* related to nock 6: unconditional skips */ \
X(SBIP, "sbip", &&do_sbip), /* 47: c3_b */ \
X(SIPS, "sips", &&do_sips), /* 48: c3_s */ \
X(SWIP, "swip", &&do_swip), /* 49: c3_l */ \
/* related to nock 6: conditional skips */ \
X(SBIN, "sbin", &&do_sbin), /* 50: c3_b */ \
X(SINS, "sins", &&do_sins), /* 51: c3_s */ \
X(SWIN, "swin", &&do_swin), /* 52: c3_l */ \
/* nock 9 */ \
X(KICB, "kicb", &&do_kicb), /* 53 */ \
X(KICS, "kics", &&do_kics), /* 54 */ \
X(TICB, "ticb", &&do_ticb), /* 55 */ \
X(TICS, "tics", &&do_tics), /* 56 */ \
/* nock 12 */ \
X(KICB, "kicb", &&do_kicb), /* 53: c3_b */ \
X(KICS, "kics", &&do_kics), /* 54: c3_s */ \
X(TICB, "ticb", &&do_ticb), /* 55: c3_b */ \
X(TICS, "tics", &&do_tics), /* 56: c3_s */ \
/* nock 12: scry (only defined in arvo, not in base nock spec) */ \
X(WILS, "wils", &&do_wils), /* 57 */ \
X(WISH, "wish", &&do_wish), /* 58 */ \
/* hint processing */ \
X(BUSH, "bush", &&do_bush), /* 59 */ \
X(SUSH, "sush", &&do_sush), /* 60 */ \
/* nock 11: hint processing */ \
X(BUSH, "bush", &&do_bush), /* 59: c3_b */ \
X(SUSH, "sush", &&do_sush), /* 60: c3_s */ \
X(DROP, "drop", &&do_drop), /* 61 */ \
X(HECK, "heck", &&do_heck), /* 62 */ \
X(SLOG, "slog", &&do_slog), /* 63 */ \
/* fast (keep) */ \
X(BAST, "bast", &&do_bast), /* 64 */ \
X(SAST, "sast", &&do_sast), /* 65 */ \
/* fast (lose) */ \
X(BALT, "balt", &&do_balt), /* 66 */ \
X(SALT, "salt", &&do_salt), /* 67 */ \
/* memo (keep) */ \
X(SKIB, "skib", &&do_skib), /* 68 */ \
X(SKIS, "skis", &&do_skis), /* 69 */ \
/* memo (lose) */ \
X(SLIB, "slib", &&do_slib), /* 70 */ \
X(SLIS, "slis", &&do_slis), /* 71 */ \
/* nock 11: fast (keep) */ \
X(BAST, "bast", &&do_bast), /* 64: c3_b */ \
X(SAST, "sast", &&do_sast), /* 65: c3_s */ \
/* nock 11: fast (lose) */ \
X(BALT, "balt", &&do_balt), /* 66: c3_b */ \
X(SALT, "salt", &&do_salt), /* 67: c3_s */ \
/* nock 11: memo (keep) */ \
X(SKIB, "skib", &&do_skib), /* 68: c3_b */ \
X(SKIS, "skis", &&do_skis), /* 69: c3_s */ \
/* nock 11: memo (lose) */ \
X(SLIB, "slib", &&do_slib), /* 70: c3_b */ \
X(SLIS, "slis", &&do_slis), /* 71: c3_s */ \
X(SAVE, "save", &&do_save), /* 72 */ \
/* before formula */ \
/* nock 11: before formula */ \
X(HILB, "hilb", &&do_hilb), /* 73: atomic, byte */ \
X(HILS, "hils", &&do_hils), /* 74: atomic, short */ \
X(HINB, "hinb", &&do_hinb), /* 75: arbitrary, byte */ \
X(HINS, "hins", &&do_hins), /* 76: arbitrary, short */ \
/* after formula */ \
/* nock 11: after formula */ \
X(HILK, "hilk", &&do_hilk), /* 77: atomic, keep */ \
X(HILL, "hill", &&do_hill), /* 78: atomic, lose */ \
X(HINK, "hink", &&do_hink), /* 79: arbitrary, keep */ \
@ -495,20 +500,20 @@ _n_nock_on(u3_noun bus, u3_noun fol)
X(KUTT, "kutt", &&do_kutt), /* 84 */ \
X(MUSM, "musm", &&do_musm), /* 85 */ \
X(KUSM, "kusm", &&do_kusm), /* 86 */ \
X(MUTB, "mutb", &&do_mutb), /* 87 */ \
X(MUTS, "muts", &&do_muts), /* 88 */ \
X(MITB, "mitb", &&do_mitb), /* 89 */ \
X(MITS, "mits", &&do_mits), /* 90 */ \
X(KUTB, "kutb", &&do_kutb), /* 91 */ \
X(KUTS, "kuts", &&do_kuts), /* 92 */ \
X(KITB, "kitb", &&do_kitb), /* 93 */ \
X(KITS, "kits", &&do_kits), /* 94 */ \
X(MUTB, "mutb", &&do_mutb), /* 87: c3_b */ \
X(MUTS, "muts", &&do_muts), /* 88: c3_s */ \
X(MITB, "mitb", &&do_mitb), /* 89: c3_b */ \
X(MITS, "mits", &&do_mits), /* 90: c3_s, seems unused in codebase */ \
X(KUTB, "kutb", &&do_kutb), /* 91: c3_b */ \
X(KUTS, "kuts", &&do_kuts), /* 92: c3_s */ \
X(KITB, "kitb", &&do_kitb), /* 93: c3_b */ \
X(KITS, "kits", &&do_kits), /* 94: c3_s, seems unused in codebase */ \
X(LAST, NULL, NULL), /* 95 */
// Opcodes. Define X to select the enum name from OPCODES.
#define X(opcode, name, indirect_jump) opcode
enum { OPCODES };
#undef X
/* TODO: opcodes for nock 7 & 8 seem to be missing */
/* _n_arg(): return the size (in bytes) of an opcode's argument
*/
@ -779,7 +784,8 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip)
if ( c3y == u3ud(op) ) {
switch ( op ) {
default:
buf_y[i_w] = (c3_y) u3h(ops);
// just reuse op
buf_y[i_w] = (c3_y) op;
break;
/* registration site index args */
@ -877,6 +883,49 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip)
case BUSH: case SANB:
case KITB: case MITB:
case HILB: case HINB:
/* TODO:
** check tail of op for being xray
** if so call a rendering and cons to tail of op
** like sip list in melt?
** take interpret buffy upto nef_w
*/
// check tail of op for being xray
/*if ( c3__xray == u3k(u3t(op)) ) {
// TODO: render everything called until this point
// ie take whatever the analog of fol is, and run it through
// something like _slog_bytecode without sloging it, to convert
// it to a u3i_string, then store that to the tail of op
// TODO: cons the rendered data to tail of op
// TODO: slog out info on what is compiling right now
u3_noun op_string = u3i_string("xray");
switch ( cod ) {
default: break;
case FIBK: u3t_slog_cap(1, u3i_string("FIBK"), op_string); break;
case FIBL: u3t_slog_cap(1, u3i_string("FIBL"), op_string); break;
case LIBK: u3t_slog_cap(1, u3i_string("LIBK"), op_string); break;
case LIBL: u3t_slog_cap(1, u3i_string("LIBL"), op_string); break;
case BUSH: u3t_slog_cap(1, u3i_string("BUSH"), op_string); break;
case SANB: u3t_slog_cap(1, u3i_string("SANB"), op_string); break;
case KITB: u3t_slog_cap(1, u3i_string("KITB"), op_string); break;
case MITB: u3t_slog_cap(1, u3i_string("MITB"), op_string); break;
case HILB: u3t_slog_cap(1, u3i_string("HILB"), op_string); break;
case HINB: u3t_slog_cap(1, u3i_string("HINB"), op_string); break;
}
_n_prog_asm_inx(buf_y, &i_w, lit_s, cod);
pog_u->lit_u.non[lit_s++] = u3k(u3t(op));
// NOTE: buf_y is pog_u->byc_u.ops_y ie it is arg #1 for render bytecode
// NOTE: ___ is arg #2 for render_bytecode (aka c3_w her_w)
// i_W
_slog_bytecode(1, buf_y, 0);
_slog_bytecode(1, pog_u->byc_u.ops_y, 0);
}
else {
_n_prog_asm_inx(buf_y, &i_w, lit_s, cod);
pog_u->lit_u.non[lit_s++] = u3k(u3t(op));
}*/
_n_prog_asm_inx(buf_y, &i_w, lit_s, cod);
pog_u->lit_u.non[lit_s++] = u3k(u3t(op));
break;
@ -956,12 +1005,12 @@ static void _n_print_stack(u3p(u3_noun) empty) {
}
#endif
#ifdef VERBOSE_BYTECODE
//#ifdef VERBOSE_BYTECODE
// Define X to select the opcode string representation from OPCODES.
# define X(opcode, name, indirect_jump) name
static c3_c* opcode_names[] = { OPCODES };
# undef X
#endif
//#endif
/* _n_apen(): emit the instructions contained in src to dst
*/
@ -998,6 +1047,12 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
default: {
return _n_comp(ops, nef, los_o, tel_o);
}
/* TODO:
** for case xray pack more info into HILB
** place nef_w into HILB trel
*/
case c3__xray:
case c3__meme:
case c3__nara:
case c3__hela:
case c3__bout: {
@ -1009,7 +1064,7 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
++nef_w; _n_emit(&fen, u3nc(SBIP, 1));
// call hilt_fore
// HILB overflows to HILS
// HILB overflows to HILS - NOTE: this becomes hin
++tot_w; _n_emit(ops, u3nc(HILB, u3nc(u3k(hif), u3k(nef))));
// if fore return c3n, skip fen
++tot_w; _n_emit(ops, u3nc(SBIN, nef_w));
@ -1034,6 +1089,12 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
++tot_w; _n_emit(ops, TOSS);
tot_w += _n_comp(ops, nef, los_o, tel_o);
} break;
/* TODO:
** for case xray pack more info into HILB
** place nef_w into HINB trel
*/
case c3__xray:
case c3__meme:
case c3__nara:
case c3__hela:
case c3__bout: {
@ -1047,7 +1108,7 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o)
// push clue
tot_w += _n_comp(ops, hod, c3n, c3n);
// call hint_fore
// HINB overflows to HINS
// HINB overflows to HINS - NOTE: does this also becom hin?
++tot_w; _n_emit(ops, u3nc(HINB, u3nc(u3k(zep), u3k(nef))));
// if fore return c3n, skip fen
++tot_w; _n_emit(ops, u3nc(SBIN, nef_w));
@ -1192,11 +1253,11 @@ _n_comp(u3_noun* ops, u3_noun fol, c3_o los_o, c3_o tel_o)
u3_noun cod, arg, hed, tel;
u3x_cell(fol, &cod, &arg);
if ( c3y == u3du(cod) ) {
tot_w += _n_comp(ops, cod, c3n, c3n);
++tot_w; _n_emit(ops, SWAP);
tot_w += _n_comp(ops, arg, c3n, c3n);
++tot_w; _n_emit(ops, (c3y == los_o ) ? AULT : AUTO);
}
tot_w += _n_comp(ops, cod, c3n, c3n); // [hed bus ..] // compute head: don't lose, not in tail
++tot_w; _n_emit(ops, SWAP); // [bus hed ..]
tot_w += _n_comp(ops, arg, c3n, c3n); // [tel bus hed ..] // compute tail: don't lose, not in tail
++tot_w; _n_emit(ops, (c3y == los_o ) ? AULT : AUTO); // [[hed tel] ..]
} // [[hed tel] bus ..]
else switch ( cod ) {
case 0:
if ( c3n == u3ud(arg) ) {
@ -1230,12 +1291,12 @@ _n_comp(u3_noun* ops, u3_noun fol, c3_o los_o, c3_o tel_o)
case 1:
switch ( arg ) {
case 0:
++tot_w; _n_emit(ops, (c3y == los_o) ? LIL0 : LIT0);
++tot_w; _n_emit(ops, (c3y == los_o) ? LIL0 : LIT0); // an actual value of 0
break;
case 1:
++tot_w; _n_emit(ops, (c3y == los_o) ? LIL1 : LIT1);
++tot_w; _n_emit(ops, (c3y == los_o) ? LIL1 : LIT1); // an actual value of 1
break;
default:
default: // these are all indexes
op_y = (c3y == los_o)
? (arg <= 0xFF ? LILB : arg <= 0xFFFF ? LILS : LIBL) // overflows to LISL
: (arg <= 0xFF ? LITB : arg <= 0xFFFF ? LITS : LIBK); // overflows to LISK
@ -1665,6 +1726,139 @@ u3n_find(u3_noun key, u3_noun fol)
return pog_p;
}
//-------------------DANE------
/* _n_prog_free(): free memory retained by program
*/
static void
_n_prog_free_willy(u3n_prog* pog_u)
{
c3_w i_w;
for ( i_w = 0; i_w < pog_u->lit_u.len_w; ++i_w ) {
u3z(pog_u->lit_u.non[i_w]);
}
for ( i_w = 0; i_w < pog_u->mem_u.len_w; ++i_w ) {
u3z(pog_u->mem_u.sot_u[i_w].key);
}
for ( i_w = 0; i_w < pog_u->cal_u.len_w; ++i_w ) {
u3j_site_lose(&(pog_u->cal_u.sit_u[i_w]));
}
for ( i_w = 0; i_w < pog_u->reg_u.len_w; ++i_w ) {
u3j_rite_lose(&(pog_u->reg_u.rit_u[i_w]));
}
u3a_free(pog_u);
}
int
_intlen (int value)
{
int x=!value;
while(value){
value/=10;
x++;
}
return x;
}
int _is_valid_op(int go) {
return (go == 0 || go == 1 || go == 2 | go == 4);
}
int _is_pair_op(int go) {
return (go == 1 || go == 2 | go == 4);
}
void
_slog_bytecode(c3_l pri_l, c3_y* pog, c3_w her_w) {
c3_w ip_w = 0;
// NOTE: if we change the main loop, we should c/p
// it back up here to replace this loop,
// then replace all string ops with increments
// thats how I did it in the first place.
// lets count the chars in this string
unsigned int s_ln = 1; // opening "{"
// set go to an invalid value, so we can break imeadately if needed
unsigned int go = 5;
while ( pog[ip_w] ) {
go = _n_arg(pog[ip_w]);
// no need to stay here if we cant print it
if (!_is_valid_op(go)) break;
ip_w++; // move ip_w for reading a opcode name
s_ln += 4; // opcode name, which is always 4 char long
if (_is_pair_op(go)) {
// add the len of the number
s_ln += _intlen(
go == 4 ? _n_rewo(pog, &ip_w):
go == 2 ? _n_resh(pog, &ip_w):
pog[ip_w++]);
s_ln+= 3; // "[", the space between the opcode and number, "]"
}
s_ln++; // add trailing space before next word in string
if (ip_w == her_w) s_ln +=3; // add "[*]" before next word
}
s_ln += 5; //add "halt}" to end of the bytecode
// reset ip_w so we can loop again
ip_w = 0;
c3_c str_c[s_ln];
str_c[0] = 0;
strcat(str_c, "{");
go = 5;
while ( pog[ip_w] ) {
go = _n_arg(pog[ip_w]);
// no need to stay here if we cant print it
if (!_is_valid_op(go)) break;
// add open brace if the opcode pairs with a number
if (_is_pair_op(go)) strcat(str_c, "[");
// add the opcode name
strncat(str_c, opcode_names[pog[ip_w++]], 4);
// finish the pair
if (_is_pair_op(go)) {
// add the space
strcat(str_c, " ");
// get the number
int num =
go == 4 ? _n_rewo(pog, &ip_w):
go == 2 ? _n_resh(pog, &ip_w):
pog[ip_w++];
if (num == 0) {
// handle a litteral zero
strcat(str_c, "0");
}
else {
// add underscores to the buffer for the number
for (int x = _intlen(num); x > 0; x--) strcat(str_c, "_");
// get the index of the last underscore we added
int f = strlen(str_c)-1;
// add num to the string by decrementing into str_c,
// stuffing the tail of num into each slot
while (num > 0) {
str_c[f--] = (num%10)+'0';
num /= 10;
}
}
// add the closing brace
strcat(str_c, "]");
}
strcat(str_c, " ");
if (ip_w == her_w) strcat(str_c, "[*]");
}
strcat(str_c, "halt}");
u3t_slog_cap(pri_l, u3i_string("bytecode"), u3i_string(str_c));
}
void
_xray(c3_l pri_l, u3_noun fol) {
u3n_prog* pog_u = _n_bite(fol);
c3_y* pog = pog_u->byc_u.ops_y;
_slog_bytecode(pri_l, pog, pog_u->byc_u.len_w-1);
_n_prog_free_willy(pog_u);
}
// ---------------END DANEs EDIT -----
/* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation.
** hin: [hint-atom, formula]. TRANSFER
** bus: subject. RETAIN
@ -1695,6 +1889,16 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out)
*out = u3_nul;
} break;
case c3__meme : {
u3t_slog_meme(0);
*out = u3_nul;
} break;
case c3__xray : {
_xray(0, fol);
*out = u3_nul;
} break;
default: {
*out = u3_nul;
} break;
@ -1769,6 +1973,28 @@ _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu)
*clu = u3_nul;
} break;
case c3__meme : {
u3_noun pri, tan;
if ( c3y == u3r_cell(*clu, &pri, &tan) ) {
c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0;
u3t_slog_cap(pri_l, u3i_string("memeory profile at"), u3k(tan));
u3t_slog_meme(pri_l);
}
u3z(*clu);
*clu = u3_nul;
} break;
case c3__xray : {
u3_noun pri, tan;
if ( c3y == u3r_cell(*clu, &pri, &tan) ) {
c3_l pri_l = c3y == u3a_is_cat(pri) ? pri : 0;
u3t_slog_cap(pri_l, u3i_string("bytecode of"), u3k(tan));
_xray(pri_l, fol);
}
u3z(*clu);
*clu = u3_nul;
} break;
default: {
u3z(*clu);
*clu = u3_nul;
@ -2987,3 +3213,4 @@ u3n_nock_an(u3_noun bus, u3_noun fol)
return u3n_nock_et(gul, bus, fol);
}

View File

@ -609,6 +609,24 @@ u3t_slog_cap(c3_l pri_l, u3_noun cap, u3_noun tan)
);
}
/* _slog_blank(): slog out a blank line with
** a given priority c3_l (assumed 0-3).
*/
void
_slog_blank(c3_l pri_l)
{
u3t_slog(
u3nc(
pri_l,
u3nt(
c3__rose,
u3nt(u3nt(' ', ' ', u3_nul), u3_nul, u3_nul),
u3nt(u3i_string(" "), u3i_string(" "), u3_nul)
)
)
);
}
/* u3t_slog_trace(): given a c3_l priority pri and a raw stack tax
** flop the order into start-to-end, render, and slog each item
@ -620,7 +638,7 @@ u3t_slog_trace(c3_l pri_l, u3_noun tax)
// render the stack
// Note: ton is a reference to a data struct
// we have just allocated
// lit is a used as a moving cursor pointer through
// lit is used as a moving cursor pointer through
// that allocated struct
// once we finish lit will be null, but ton will still
// point to the whole valid allocated data structure
@ -673,3 +691,421 @@ u3t_slog_hela(c3_l pri_l)
u3t_slog_trace(pri_l, tax);
}
/* _roundf(): truncate a float to preciscon
** equivalant to %.2f
*/
float
_roundf(float percent)
{
// scale the percentage so that all siginificant digits
// would be retained when truncted to an int, then add 0.5
// to account for rounding without using round or roundf
float percent_big_f = (percent*10000)+0.5;
// truncate to int
int percent_big_i = (int) percent_big_f;
// convert to float and scale down such that
// our last to digits are right of the decimal
float percent_truncated_f = (float) percent_big_i/100.0;
return percent_truncated_f;
}
float
_meme_percent(unsigned int small, unsigned int large)
{
// get the percentage of our inputs as a float
float percent_raw_f = (float) small/large;
return _roundf(percent_raw_f);
}
/*
void
_slog_free_discrepancy( )
{
c3_w fre_w = u3a_idle(u3R);
if ( fre_w != u3R->all.fre_w ) {
char* s;
int result = asprintf(&s,
"%x\n\t\t\tfre_w: %x\n\t\t all.fre_w: %x\n\t\t\t diff: %x",
u3R->par_p,
fre_w,
u3R->all.fre_w,
(u3R->all.fre_w - fre_w)
);
if (0 <= result) {
u3t_slog_cap(2, u3i_string(" free discrepancy at par_p"), u3i_string(s));
free(s);
}
}
}
*/
void _slog_road_depth(c3_l pri_l, u3_road* r, int i) {
if (r == &(u3H->rod_u)) {
// slog the info
unsigned int x = 0;
char s[8] = " 0";
while (i > 0 && x < 8) {
s[6-x] = (i%10)+'0';
i /= 10;
x++;
}
u3t_slog_cap(pri_l, u3i_string(" road depth"), u3i_string(s));
} else {
// recurse
_slog_road_depth(pri_l, u3tn(u3_road, r->par_p), ++i);
}
}
int _all_heap_size(u3_road* r) {
if (r == &(u3H->rod_u)) {
return u3a_heap(r)*4;
} else {
// recurse
return (u3a_heap(r)*4) + _all_heap_size(u3tn(u3_road, r->par_p));
}
}
struct
_report_bar {
char s[105];
};
struct
bar_item {
unsigned int index;
unsigned int lower;
float og;
float dif;
};
struct
bar_items {
struct bar_item s[6];
};
float
_boost_small(float x)
{
return
// we want zero to be zero,
// and anything between zero and one to be one
// all else goes as normal
0.0 >= x ? 0.0:
1.0 > x ? 1.0:
x;
}
int
_global_difference(struct bar_items item)
{
unsigned int lower_sum = 0;
for (unsigned int i=0; i < 6; i++) lower_sum += item.s[i].lower;
return 100 - lower_sum;
}
struct bar_items
_get_roundoff_error(struct bar_items item)
{
for (unsigned int i=0; i < 6; i++) {
item.s[i].dif = item.s[i].og - item.s[i].lower;
}
return item;
}
struct bar_items
_sort_by_roundoff_error(struct bar_items item)
{
struct bar_item temp;
for (unsigned int i=1; i < 6; i++) {
for (unsigned int j=0; j < 6-i; j++) {
if (item.s[j+1].dif > item.s[j].dif) {
temp = item.s[j];
item.s[j] = item.s[j+1];
item.s[j+1] = temp;
}
}
}
return item;
}
struct bar_items
_sort_by_index(struct bar_items item)
{
struct bar_item temp;
for (unsigned int i=1; i < 6; i++) {
for (unsigned int j=0; j < 6-i; j++) {
if (item.s[j+1].index < item.s[j].index) {
temp = item.s[j];
item.s[j] = item.s[j+1];
item.s[j+1] = temp;
}
}
}
return item;
}
void
_print_bar_items(struct bar_items item)
{
const char symbol[6] = "=-%#+~";
for (int i=0; i < 6; i++) printf(
"item:%c,%2u, %6.2f,%6.2f, %2u\n",
symbol[i],
item.s[i].index,
item.s[i].og,
item.s[i].dif,
item.s[i].lower
);
}
struct bar_items
_reduce_error(struct bar_items item, int difference)
{
for (unsigned int i=0; i < 6; i++) {
if (item.s[i].lower == 0) continue;
if (item.s[i].lower == 1) continue;
if (difference > 0) {
item.s[i].lower++;
difference--;
}
if (difference < 0) {
item.s[i].lower--;
difference++;
}
}
return item;
}
struct _report_bar
_report_bargraph(float ih, float sh, float fh, float op, float sk, float ik)
{
float in[6];
in[0] = _boost_small(ih);
in[1] = _boost_small(sh);
in[2] = _boost_small(fh);
in[3] = _boost_small(op);
in[4] = _boost_small(sk);
in[5] = _boost_small(ik);
const char symbol[6] = "=-%#+~";
// init the list of structs
struct bar_items item;
for (unsigned int i=0; i < 6; i++) {
item.s[i].index = i;
item.s[i].og = in[i];
item.s[i].lower = (int) item.s[i].og;
}
int difference = 0;
for (int x=0; x<100; x++) {
item = _get_roundoff_error(item);
difference = _global_difference(item);
if (difference == 0) break;
item = _sort_by_roundoff_error(item);
item = _reduce_error(item, difference);
}
item = _sort_by_index(item);
struct _report_bar bar = {
.s = "[ ]"
};
// create our bar chart
int x = 0, y = 0;
for (int i=0; i < 6; i++) {
x++;
for (int j=0; j < item.s[i].lower; j++) {
bar.s[x+j] = symbol[i];
y = x+j;
}
if (y > 0) x = y;
}
return bar;
}
/* u3t_meme(): report memory stats at call time */
void
u3t_slog_meme(c3_l pri_l)
{
c3_w low = 0,
top = u3a_bytes,
full = u3a_full(u3R)*4,
fred = u3a_idle(u3R)*4,
temp = u3a_temp(u3R)*4,
heap = u3a_heap(u3R)*4,
open = u3a_open(u3R)*4;
c3_w imut = top-full;
c3_w solid = heap-fred;
float imut_p = _meme_percent(imut, top),
heap_p = _meme_percent(solid, top),
free_p = _meme_percent(fred, top),
open_p = _meme_percent(open, top),
stak_p = _meme_percent(temp, top);
float full_p = heap_p + free_p + open_p + stak_p;
// TODO: replace all calls of free() with calls of u3a_free() or its alias.
c3_w imut_heap = _all_heap_size(u3R) - heap;
c3_w imut_stak = imut - imut_heap;
float imut_heap_p = _meme_percent(imut_heap, top),
imut_stak_p = _meme_percent(imut_stak, top);
u3t_slog_cap(pri_l, u3i_string("Legend | Report"), u3i_string(" "));
u3t_slog_memory(pri_l, " loom", 100.0, top);
u3t_slog_memory(pri_l, " road", full_p, full);
_slog_blank(pri_l);
u3t_slog_memory(pri_l, " = immutable heap", imut_heap_p, imut_heap);
u3t_slog_memory(pri_l, " - solid heap", heap_p, solid);
u3t_slog_memory(pri_l," \% freed heap", free_p, fred);
u3t_slog_memory(pri_l, " # open space", open_p, open);
u3t_slog_memory(pri_l, " + stack", stak_p, temp);
u3t_slog_memory(pri_l, " ~ immutable stack", imut_stak_p, imut_stak);
_slog_blank(pri_l);
u3t_slog_memory(pri_l, " $ allocation frame", imut_heap_p, imut_heap);
#ifdef U3_CPU_DEBUG
/* iff we are using CPU_DEBUG env var
** we can report more facts:
** max_w: max allocated on the current road (not global, not including child roads)
** cel_d: max cells allocated in current road (inc closed kids, but not parents)
** nox_d: nock steps performed in current road, less caching
*/
c3_w max = (u3R->all.max_w*4)+imut;
float max_p = _meme_percent(max, top);
c3_d cells = u3R->pro.cel_d;
c3_d nox = u3R->pro.nox_d;
u3t_slog_memory(pri_l, " | road max memory", max_p, max);
_slog_blank(pri_l);
u3t_slog_steps(pri_l, " road cells made", cells);
u3t_slog_steps(pri_l, " road nocks made", nox);
#endif
if ( u3a_is_north(u3R) == c3y ) {
u3t_slog_cap(pri_l, u3i_string(" road direction"), u3i_string(" North"));
} else {
u3t_slog_cap(pri_l, u3i_string(" road direction"), u3i_string(" South"));
}
_slog_road_depth(pri_l, u3R, 1);
_slog_blank(pri_l);
// warn if any sanity checks have failed
if (full_p != (100.0 - imut_p))
u3t_slog_cap(3, u3i_string("error"), u3i_string("road != (loom - immutable)"));
if (100.0 < (imut_heap_p + heap_p + free_p + open_p + stak_p + imut_stak_p))
u3t_slog_cap(3, u3i_string("error"), u3i_string("loom sums over 100%"));
struct _report_bar bar = _report_bargraph(
imut_heap_p,
heap_p,
free_p,
open_p,
stak_p,
imut_stak_p
);
int dol = (int) _roundf(imut_heap_p/100);
bar.s[dol] = '$';
#ifdef U3_CPU_DEBUG
// iff we have a max_p we will render it into the bar graph
// in other words iff we have max_p it will always replace something
c3_w inc_max = (max_p > imut_heap_p+1.0) ? (c3_w) max_p+0.5 : (c3_w) imut_heap_p+1.5;
if (max_p > 0.0) bar.s[inc_max] = '|';
#endif
// TODO: not sure we really need _slog_free_discrepancy()
//_slog_free_discrepancy();
u3t_slog_cap(pri_l, u3i_string("Loom"), u3i_string(bar.s));
}
int
_size_prefix(unsigned int wor_w)
{
return
(wor_w / 1000000000) ? 'G':
(wor_w % 1000000000) / 1000000 ? 'M':
(wor_w % 1000000) / 1000 ? 'K':
(wor_w % 1000) ? ' ':
'X';
}
// create a struct to allow passing around a fixed size string
struct _report {
char s[32];
};
struct _report
report_string(unsigned int wor_w)
{
struct _report r = {
.s = " "
};
// add the G/M/K prefix
r.s[24] = _size_prefix(wor_w);
// consume wor_w into a string one base-10 digit at a time
// including dot formatting
unsigned int i = 0, j = 0;
while (wor_w > 0) {
if (j == 3) {
r.s[22-i] = '.';
i++;
j = 0;
} else {
r.s[22-i] = (wor_w%10)+'0';
wor_w /= 10;
i++;
j++;
}
}
// return our fixed size string within a struct
return r;
}
void
u3t_slog_memory(c3_l pri_l, c3_c* cap_c, float percent, c3_w wor_w)
{
// create the report string and apply it to our char array s
struct _report r = report_string(wor_w);
// add the Bytes postfix to the size report
r.s[25] = 'B';
// add the space-percentage into the report
r.s[2] = '0', r.s[3] = '.', r.s[4] = '0', r.s[5] = '0';
int per_int = (int) (percent*100);
unsigned int i = 0;
while (per_int > 0 && i < 6) {
if (i == 2) {
r.s[5-i] = '.';
} else {
r.s[5-i] = (per_int%10)+'0';
per_int /= 10;
}
i++;
}
// add the percent sign
r.s[6] = '%';
// slog it and go home
u3t_slog_cap(pri_l, u3i_string(cap_c), u3i_string(r.s));
}
void
u3t_slog_steps(c3_l pri_l, c3_c* cap_c, c3_d sep_d)
{
struct _report r = report_string(sep_d);
u3t_slog_cap(pri_l, u3i_string(cap_c), u3i_string(r.s));
}
/* u3t_render_bytecode(): collect the bytecode data
** for the expression wrapped in the calling hint
** and
*
u3_noun
u3t_render_bytecode(c3_y* pog, c3_w her_w)
{
//NOTE: this is basically the slog_byecode() function in nock.c
}
*/