diff --git a/doc/spec/nock/10.txt b/doc/spec/nock/10.txt new file mode 100644 index 0000000000..27d1e8c730 --- /dev/null +++ b/doc/spec/nock/10.txt @@ -0,0 +1,70 @@ +Author: Mencius Moldbug [moldbug@gmail.com] +Date: 9/15/2008 +Version: 10K + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Brackets enclose cells. [a b c] is [a [b c]]. + +5. Definition + +5.1 Transformations + + *[a [b c] d] => [*[a b c] *[a d]] + *[a 0 b] => /[b a] + *[a 1 b] => [b] + *[a 2 b c d] => *[a 3 [0 1] 3 [1 c d] [1 0] 3 [1 2 3] [1 0] 5 5 b] + *[a 3 b] => **[a b] + *[a 4 b] => &*[a b] + *[a 5 b] => ^*[a b] + *[a 6 b] => =*[a b] + *[a] => *[a] + +5.2 Operators + +5.2.1 Goto [*] + + *[a] -> nock[a] + +5.2.2 Deep [&] + + &[a b] -> 0 + &[a] -> 1 + +5.2.4 Bump [^] + + ^[a b] -> ^[a b] + ^[a] -> (a + 1) + +5.2.5 Like [=] + + =[a a] -> 0 + =[a b] -> 1 + =[a] -> =[a] + +5.2.6 Snip [/] + + /[1 a] -> a + /[2 a b] -> a + /[3 a b] -> b + /[(a + a) b] -> /[2 /[a b]] + /[(a + a + 1) b] -> /[3 /[a b]] + /[a] -> /[a] diff --git a/doc/spec/nock/11.txt b/doc/spec/nock/11.txt new file mode 100644 index 0000000000..da9dafb91b --- /dev/null +++ b/doc/spec/nock/11.txt @@ -0,0 +1,74 @@ +Author: Mencius Moldbug (moldbug@gmail.com) +Date: 5/25/2008 +Version: 11K + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Parentheses enclose cells. (a b c) is (a (b c)). + +5. Definition + +5.1 Transformations + + *(a (b c) d) => (*(a b c) *(a d)) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b c d) => *(a 3 (0 1) 3 (1 c d) (1 0) 3 (1 2 3) (1 0) 5 5 b) + *(a 3 b) => **(a b) + *(a 4 b) => &*(a b) + *(a 5 b) => ^*(a b) + *(a 6 b) => =*(a b) + + *(a 7 b c) => *(a 3 (((1 0) b) c) 1 0 3) + *(a 8 b c) => *(a c) + + *(a) => *(a) + +5.2 Operators + +5.2.1 Goto (*) + + *(a) -> nock(a) + +5.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +5.2.4 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +5.2.5 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +5.2.6 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/12.txt b/doc/spec/nock/12.txt new file mode 100644 index 0000000000..d3762e8557 --- /dev/null +++ b/doc/spec/nock/12.txt @@ -0,0 +1,75 @@ +Author: Curtis Yarvin (curtis.yarvin@gmail.com) +Date: 3/28/2008 +Version: 0.12 + +1. Introduction + + This file defines one function, "nock." + + nock is in the public domain. + +2. Data + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Semantics + + nock maps one noun to another. It doesn't always terminate. + +4. Pseudocode + + nock is defined in a pattern-matching pseudocode, below. + + Parentheses enclose cells. (a b c) is (a (b c)). + +5. Definition + +5.1 Transformations + + *(a (b c) d) => (*(a b c) *(a d)) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b c) => *(*(a b) c) + *(a 3 b) => **(a b) + *(a 4 b) => &*(a b) + *(a 5 b) => ^*(a b) + *(a 6 b) => =*(a b) + + *(a 7 b c d) => *(a 3 (0 1) 3 (1 c d) (1 0) 3 (1 2 3) (1 0) 5 5 b) + *(a 8 b c) => *(a 2 (((1 0) b) c) 0 3) + *(a 9 b c) => *(a c) + + *(a) => *(a) + +5.2 Operators + +5.2.1 Goto (*) + + *(a) -> nock(a) + +5.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +5.2.4 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +5.2.5 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +5.2.6 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/13.txt b/doc/spec/nock/13.txt new file mode 100644 index 0000000000..2295e5ead5 --- /dev/null +++ b/doc/spec/nock/13.txt @@ -0,0 +1,71 @@ +Author: Curtis Yarvin (curtis.yarvin@gmail.com) +Date: 3/8/2008 +Version: 0.13 + +1. Manifest + + This file defines one Turing-complete function, "nock." + + nock is in the public domain. So far as I know, it is + neither patentable nor patented. Use it at your own risk. + +2. Data + + Both the domain and range of nock are "nouns." + + A "noun" is either an "atom" or a "cell." An "atom" is an unsigned + integer of any size. A "cell" is an ordered pair of any two nouns, + the "head" and "tail." + +3. Pseudocode + + nock is defined in a pattern-matching pseudocode. + + Match precedence is top-down. Operators are prefix. Parens + denote cells, and group right: (a b c) is (a (b c)). + +4. Definition + +4.1 Transformations + + *(a 0 b c) => *(*(a b) c) + *(a 0 b) => /(b a) + *(a 1 b) => (b) + *(a 2 b) => **(a b) + *(a 3 b) => &*(a b) + *(a 4 b) => ^*(a b) + *(a 5 b) => =*(a b) + *(a 6 b c d) => *(a 2 (0 1) 2 (1 c d) (1 0) 2 (1 2 3) (1 0) 4 4 b) + *(a b c) => (*(a b) *(a c)) + *(a) => *(a) + +4.2 Operators + +4.2.1 Goto (*) + + *(a) -> nock(a) + +4.2.2 Deep (&) + + &(a b) -> 0 + &(a) -> 1 + +4.2.3 Bump (^) + + ^(a b) -> ^(a b) + ^(a) -> a + 1 + +4.2.4 Same (=) + + =(a a) -> 0 + =(a b) -> 1 + =(a) -> =(a) + +4.2.5 Snip (/) + + /(1 a) -> a + /(2 a b) -> a + /(3 a b) -> b + /((a + a) b) -> /(2 /(a b)) + /((a + a + 1) b) -> /(3 /(a b)) + /(a) -> /(a) diff --git a/doc/spec/nock/6.txt b/doc/spec/nock/6.txt new file mode 100644 index 0000000000..1dbd599583 --- /dev/null +++ b/doc/spec/nock/6.txt @@ -0,0 +1,42 @@ +1 Structures + + A noun is an atom or a cell. An atom is any natural number. + A cell is an ordered pair of nouns. + +2 Reductions + + nock(a) *a + [a b c] [a [b c]] + + ?[a b] 0 + ?a 1 + +a 1 + a + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] +*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [[0 1] b] c] + *[a 9 b c] *[a 7 c 0 b] + *[a 10 b c] *[a c] + *[a 10 [b c] d] *[a 8 c 7 [0 2] d] + + +[a b] +[a b] + =a =a + /a /a + *a *a diff --git a/doc/spec/nock/7.txt b/doc/spec/nock/7.txt new file mode 100644 index 0000000000..bd3e295083 --- /dev/null +++ b/doc/spec/nock/7.txt @@ -0,0 +1,42 @@ +1 Structures + + A noun is an atom or a cell. An atom is any natural number. + A cell is any ordered pair of nouns. + +2 Pseudocode + + [a b c] [a [b c]] + nock(a) *a + + ?[a b] 0 + ?a 1 + ^a 1 + a + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] ^*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c] + *[a 9 b c] *[a 7 c 0 b] + *[a 10 b c] *[a c] + *[a 10 [b c] d] *[a 8 c 7 [0 3] d] + + ^[a b] ^[a b] + =a =a + /a /a + *a *a diff --git a/doc/spec/nock/8.txt b/doc/spec/nock/8.txt new file mode 100644 index 0000000000..2981d6c5f7 --- /dev/null +++ b/doc/spec/nock/8.txt @@ -0,0 +1,45 @@ +1 Structures + + A noun is an atom or a cell. An atom is any unsigned integer. + A cell is an ordered pair of nouns. + +2 Pseudocode + + [a b c] is [a [b c]]; *a is nock(a). Reductions match top-down. + +3 Reductions + + ?[a b] 0 + ?a 1 + ^a (a + 1) + =[a a] 0 + =[a b] 1 + + /[1 a] a + /[2 a b] a + /[3 a b] b + /[(a + a) b] /[2 /[a b]] + /[(a + a + 1) b] /[3 /[a b]] + + *[a [b c] d] [*[a b c] *[a d]] + *[a 0 b] /[b a] + *[a 1 b] b + *[a 2 b c] *[*[a b] *[a c]] + *[a 3 b] ?*[a b] + *[a 4 b] ^*[a b] + *[a 5 b] =*[a b] + + *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] + *[a 7 b c] *[a 2 b 1 c] + *[a 8 b c] *[a 7 [7 b [0 1]] c] + *[a 9 b c] *[a 8 b 2 [[7 [0 3] d] [0 5]] 0 5] + *[a 10 b c] *[a 8 b 8 [7 [0 3] c] 0 2] + *[a 11 b c] *[a 8 b 7 [0 3] c] + *[a 12 b c] *[a [1 0] 1 c] + + ^[a b] ^[a b] + =a =a + /a /a + *a *a + + diff --git a/doc/spec/nock/9.txt b/doc/spec/nock/9.txt new file mode 100644 index 0000000000..b6aabad768 --- /dev/null +++ b/doc/spec/nock/9.txt @@ -0,0 +1,43 @@ +1 Context + + This spec defines one function, Nock. + +2 Structures + + A noun is an atom or a cell. An atom is any unsigned integer. + A cell is an ordered pair of any two nouns. + +3 Pseudocode + + Brackets enclose cells. [a b c] is [a [b c]]. + + *a is Nock(a). Reductions match top-down. + +4 Reductions + + ?[a b] => 0 + ?a => 1 + + ^[a b] => ^[a b] + ^a => (a + 1) + + =[a a] => 0 + =[a b] => 1 + =a => =a + + /[1 a] => a + /[2 a b] => a + /[3 a b] => b + /[(a + a) b] => /[2 /[a b]] + /[(a + a + 1) b] => /[3 /[a b]] + /a => /a + + *[a 0 b] => /[b a] + *[a 1 b] => b + *[a 2 b c d] => *[a 3 [0 1] 3 [1 c d] [1 0] 3 [1 2 3] [1 0] 5 5 b] + *[a 3 b] => **[a b] + *[a 4 b] => ?*[a b] + *[a 5 b] => ^*[a b] + *[a 6 b] => =*[a b] + *[a [b c] d] => [*[a b c] *[a d]] + *a => *a diff --git a/pkg/arvo/sys/arvo.hoon b/pkg/arvo/sys/arvo.hoon index 7dbbb0a239..c308777ebc 100644 --- a/pkg/arvo/sys/arvo.hoon +++ b/pkg/arvo/sys/arvo.hoon @@ -415,7 +415,7 @@ == -- :: -:: |de: axal engine +:: |of: axal engine :: ++ of =| fat=(axal) diff --git a/pkg/arvo/tests/run/hints.hoon b/pkg/arvo/tests/run/hints.hoon index 7481b105bd..ac382497fc 100644 --- a/pkg/arvo/tests/run/hints.hoon +++ b/pkg/arvo/tests/run/hints.hoon @@ -1,21 +1,33 @@ :: Test that these hints do not crash the runtime -:: there is no need to include the hints for dynamic %bout +:: there is no need to include a test for dynamic %bout :: since all hoon tests exersize dynamic %bout |% -:: these test that the hilt-trace hints +:: test that these trace hints :: are safe to run or ignore -++ test-hela-hilt +++ test-hilt-hela ~> %hela ~ -++ test-nara-hilt +++ test-hint-hela + ~> %hela.[1 leaf+"test-hint-hela ~"] + ~ +++ test-hilt-nara ~> %nara ~ -:: these test that the hint-trace hints -:: are safe to run or ignore -++ test-hela-hint - ~> %hela.[1 leaf+"test-hela-trace-hint"] +++ test-hint-nara + ~> %nara.[1 leaf+"test-hint-nara ~"] ~ -++ test-nara-hint - ~> %nara.[1 leaf+"test-nara-trace-hint"] +:: test that theses bytecode-report hints +:: are safe to run or ignore +++ test-hilt-xray + ~> %xray + ~ +++ test-hint-xray + ~> %xray.[1 leaf+"test-hint-xray ~"] + ~ +:: test that the hilt bout hint +:: is safe to run or ignore +++ test-hilt-bout + ~> %bout ~ -- + diff --git a/pkg/urbit/bench/ur_bench.c b/pkg/urbit/bench/ur_bench.c index 40a4e518c6..4c01513576 100644 --- a/pkg/urbit/bench/ur_bench.c +++ b/pkg/urbit/bench/ur_bench.c @@ -7,8 +7,9 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 24); u3m_pave(c3y); + u3e_init(); } /* _ames_writ_ex(): |hi packet from fake ~zod to fake ~nec diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index fffb762623..1853ed8710 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -4,6 +4,8 @@ #define U3_GLOBAL #define C3_GLOBAL #include "all.h" +#include "vere/ivory.h" +#include "ur/ur.h" #include "rsignal.h" #include #include "vere/vere.h" @@ -164,6 +166,9 @@ _main_init(void) u3_Host.ops_u.puf_c = "jam"; u3_Host.ops_u.hap_w = 50000; u3_Host.ops_u.kno_w = DefaultKernel; + + u3_Host.ops_u.lut_y = u3a_bits + 1; + u3_Host.ops_u.lom_y = u3a_bits + 1; } /* _main_pier_run(): get pier from binary path (argv[0]), if appropriate @@ -216,6 +221,7 @@ _main_getopt(c3_i argc, c3_c** argv) { "json-trace", no_argument, NULL, 'j' }, { "kernel-stage", required_argument, NULL, 'K' }, { "key-file", required_argument, NULL, 'k' }, + { "loom", required_argument, NULL, c3__loom }, { "local", no_argument, NULL, 'L' }, { "lite-boot", no_argument, NULL, 'l' }, { "replay-to", required_argument, NULL, 'n' }, @@ -238,6 +244,9 @@ _main_getopt(c3_i argc, c3_c** argv) { "exit", no_argument, NULL, 'x' }, { "scry-into", required_argument, NULL, 'Y' }, { "scry-format", required_argument, NULL, 'Z' }, + // + { "urth-loom", required_argument, NULL, 5 }, + // { NULL, 0, NULL, 0 }, }; @@ -246,6 +255,17 @@ _main_getopt(c3_i argc, c3_c** argv) lop_u, &lid_i)) ) { switch ( ch_i ) { + case 5: { // urth-loom + c3_w lut_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lut_w); + if ( (c3n == res_o) || (lut_w < 20) ) { + fprintf(stderr, "error: --urth-loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + return c3n; + } + + u3_Host.ops_u.lut_y = lut_w; + break; + } case 'X': { u3_Host.ops_u.pek_c = strdup(optarg); break; @@ -346,6 +366,16 @@ _main_getopt(c3_i argc, c3_c** argv) } else u3_Host.ops_u.pes_s = arg_w; break; } + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + return c3n; + } + u3_Host.ops_u.lom_y = lom_w; + break; + } case c3__noco: { u3_Host.ops_u.con = c3n; break; @@ -660,6 +690,7 @@ u3_ve_usage(c3_i argc, c3_c** argv) "-K, --kernel-stage STAGE Start at Hoon kernel version stage\n", "-k, --key-file KEYS Private key file (see also -G)\n", "-L, --local Local networking only\n", + " --loom Set loom to binary exponent (31 == 2GB)\n" "-l, --lite-boot Most-minimal startup\n", "-n, --replay-to NUMBER Replay up to event\n", "-P, --profile Profiling\n", @@ -997,9 +1028,9 @@ static void _cw_serf_commence(c3_i argc, c3_c* argv[]) { #ifdef U3_OS_mingw - if ( 8 > argc ) { + if ( 9 > argc ) { #else - if ( 7 > argc ) { + if ( 8 > argc ) { #endif fprintf(stderr, "serf: missing args\n"); exit(1); @@ -1011,9 +1042,11 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) c3_c* key_c = argv[3]; // XX use passkey c3_c* wag_c = argv[4]; c3_c* hap_c = argv[5]; - c3_c* eve_c = argv[6]; + c3_c* lom_c = argv[6]; + c3_w lom_w; + c3_c* eve_c = argv[7]; #ifdef U3_OS_mingw - c3_c* han_c = argv[7]; + c3_c* han_c = argv[8]; _cw_intr_win(han_c); #endif @@ -1039,6 +1072,7 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) { sscanf(wag_c, "%" SCNu32, &u3C.wag_w); sscanf(hap_c, "%" SCNu32, &u3_Host.ops_u.hap_w); + sscanf(lom_c, "%" SCNu32, &lom_w); if ( 1 != sscanf(eve_c, "%" PRIu64, &eve_d) ) { fprintf(stderr, "serf: rock: invalid number '%s'\r\n", argv[4]); @@ -1062,7 +1096,7 @@ _cw_serf_commence(c3_i argc, c3_c* argv[]) // { u3V.dir_c = strdup(dir_c); - u3V.sen_d = u3V.dun_d = u3m_boot(dir_c); + u3V.sen_d = u3V.dun_d = u3m_boot(dir_c, (size_t)1 << lom_w); if ( eve_d ) { // XX need not be fatal, need a u3m_reboot equivalent @@ -1152,6 +1186,117 @@ _cw_dock(c3_i argc, c3_c* argv[]) u3_king_dock(U3_VERE_PACE); } +/* _cw_eval_get_input(): read file til EOF and return a malloc'd string +*/ +c3_c* +_cw_eval_get_input(FILE* fil_u, size_t siz_i) +{ + c3_i car_i; + size_t len_i = 0; + c3_c* str_c = c3_realloc(NULL, siz_i);//size is start size + + while( EOF != (car_i = fgetc(fil_u)) ){ + str_c[len_i++] = car_i; + if( len_i == siz_i ){ + siz_i += 16; + str_c = c3_realloc(str_c, siz_i); + } + } + + str_c[len_i++]='\0'; + + return c3_realloc(str_c, len_i); +} + +/* _cw_eval(): initialize and run the hoon evaluator +*/ +static void +_cw_eval(c3_i argc, c3_c* argv[]) +{ + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "eval" + // + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + c3_c* evl_c = _cw_eval_get_input(stdin, 10); + + // initialize the Loom and load the Ivory Pill + // + { + c3_d len_d = u3_Ivory_pill_len; + c3_y* byt_y = u3_Ivory_pill; + u3_cue_xeno* sil_u; + u3_weak pil; + + u3C.wag_w |= u3o_hashless; + u3m_boot_lite((size_t)1 << u3_Host.ops_u.lom_y); + sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { + printf("lite: unable to cue ivory pill\r\n"); + exit(1); + } + u3s_cue_xeno_done(sil_u); + if ( c3n == u3v_boot_lite(pil) ) { + u3l_log("lite: boot failed\r\n"); + exit(1); + } + } + + printf("eval:\n"); + + // +wish for an eval gate (virtualized twice for pretty-printing) + // + u3_noun gat = u3v_wish("|=(a=@t (sell (slap !>(+>.$) (rain /eval a))))"); + u3_noun res; + { + u3_noun sam = u3i_string(evl_c); + u3_noun cor = u3nc(u3k(u3h(gat)), u3nc(sam, u3k(u3t(u3t(gat))))); + res = u3m_soft(0, u3n_kick_on, cor); + } + + + if ( 0 == u3h(res) ) { // successful execution, print output + u3_pier_tank(0, 0, u3k(u3t(res))); + } + else { // error, print stack trace + u3_pier_punt_goof("eval", u3k(res)); + } + + u3z(res); + u3z(gat); + free(evl_c); +} + /* _cw_info(): print pier info */ static void @@ -1175,7 +1320,7 @@ _cw_info(c3_i argc, c3_c* argv[]) } break; } - c3_d eve_d = u3m_boot(u3_Host.dir_c); + c3_d eve_d = u3m_boot(u3_Host.dir_c, u3a_bytes); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); fprintf(stderr, "\r\nurbit: %s at event %" PRIu64 "\r\n", @@ -1212,7 +1357,7 @@ _cw_grab(c3_i argc, c3_c* argv[]) } break; } - u3m_boot(u3_Host.dir_c); + u3m_boot(u3_Host.dir_c, u3a_bytes); u3C.wag_w |= u3o_hashless; u3_serf_grab(); u3m_stop(); @@ -1223,25 +1368,56 @@ _cw_grab(c3_i argc, c3_c* argv[]) static void _cw_cram(c3_i argc, c3_c* argv[]) { - switch ( argc ) { - case 2: { - if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { - fprintf(stderr, "unable to find pier\r\n"); - exit (1); - } - } break; + c3_i ch_i, lid_i; + c3_w arg_w; - case 3: { - u3_Host.dir_c = argv[2]; - } break; + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; - default: { - fprintf(stderr, "invalid command\r\n"); - exit(1); - } break; + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } } - c3_d eve_d = u3m_boot(u3_Host.dir_c); + // argv[optind] is always "cram" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); + exit(1); + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + c3_d eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_o ret_o; @@ -1271,29 +1447,58 @@ _cw_cram(c3_i argc, c3_c* argv[]) static void _cw_queu(c3_i argc, c3_c* argv[]) { + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; + + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "queu" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); + exit(1); + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + c3_c* eve_c; c3_d eve_d; - switch ( argc ) { - case 3: { - if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { - fprintf(stderr, "unable to find pier\r\n"); - exit (1); - } - eve_c = argv[2]; - } break; - - case 4: { - u3_Host.dir_c = argv[2]; - eve_c = argv[3]; - } break; - - default: { - fprintf(stderr, "invalid command\r\n"); - exit(1); - } break; - } - if ( 1 != sscanf(eve_c, "%" PRIu64 "", &eve_d) ) { fprintf(stderr, "urbit: queu: invalid number '%s'\r\n", eve_c); exit(1); @@ -1303,7 +1508,7 @@ _cw_queu(c3_i argc, c3_c* argv[]) fprintf(stderr, "urbit: queu: preparing\r\n"); - u3m_boot(u3_Host.dir_c); + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); // XX can spuriously fail do to corrupt memory-image checkpoint, // need a u3m_half_boot equivalent @@ -1327,29 +1532,60 @@ _cw_queu(c3_i argc, c3_c* argv[]) static void _cw_meld(c3_i argc, c3_c* argv[]) { - switch ( argc ) { - case 2: { - if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { - fprintf(stderr, "unable to find pier\r\n"); - exit (1); - } - } break; + c3_i ch_i, lid_i; + c3_w arg_w; - case 3: { - u3_Host.dir_c = argv[2]; - } break; + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; - default: { - fprintf(stderr, "invalid command\r\n"); + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "meld" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); exit(1); - } break; + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); } u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock c3_w pre_w; u3C.wag_w |= u3o_hashless; - u3m_boot(u3_Host.dir_c); + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); pre_w = u3a_open(u3R); u3u_meld(); @@ -1369,7 +1605,8 @@ _cw_next(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "arch", required_argument, NULL, 'a' }, + { "arch", required_argument, NULL, 'a' }, + { "loom", required_argument, NULL, c3__loom }, { NULL, 0, NULL, 0 } }; @@ -1381,7 +1618,18 @@ _cw_next(c3_i argc, c3_c* argv[]) u3_Host.arc_c = strdup(optarg); } break; + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + case '?': { + fprintf(stderr, "invalid argument\r\n"); exit(1); } break; } @@ -1409,6 +1657,7 @@ _cw_next(c3_i argc, c3_c* argv[]) u3_Host.pep_o = c3y; u3_Host.nex_o = c3y; + u3_Host.ops_u.tem = c3y; } /* _cw_pack(): compact memory, save, and exit. @@ -1416,27 +1665,58 @@ _cw_next(c3_i argc, c3_c* argv[]) static void _cw_pack(c3_i argc, c3_c* argv[]) { - switch ( argc ) { - case 2: { - if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { - fprintf(stderr, "unable to find pier\r\n"); - exit (1); - } - } break; + c3_i ch_i, lid_i; + c3_w arg_w; - case 3: { - u3_Host.dir_c = argv[2]; - } break; + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; - default: { - fprintf(stderr, "invalid command\r\n"); + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "pack" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); exit(1); - } break; + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); } u3_disk* log_u = _cw_disk_init(u3_Host.dir_c); // XX s/b try_aquire lock - u3m_boot(u3_Host.dir_c); + u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); u3a_print_memory(stderr, "urbit: pack: gained", u3m_pack()); u3e_save(); @@ -1449,25 +1729,57 @@ _cw_pack(c3_i argc, c3_c* argv[]) static void _cw_prep(c3_i argc, c3_c* argv[]) { - switch ( argc ) { - case 2: { - if ( !(u3_Host.dir_c = _main_pier_run(argv[0])) ) { - fprintf(stderr, "unable to find pier\r\n"); - exit (1); - } - } break; + c3_i ch_i, lid_i; + c3_w arg_w; - case 3: { - u3_Host.dir_c = argv[2]; - } break; + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; - default: { - fprintf(stderr, "invalid command\r\n"); + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "prep" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); exit(1); - } break; + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); } u3_Host.pep_o = c3y; + u3_Host.ops_u.tem = c3y; } /* _cw_vere(): download vere @@ -1484,9 +1796,9 @@ _cw_vere(c3_i argc, c3_c* argv[]) c3_w arg_w; static struct option lop_u[] = { - { "arch", required_argument, NULL, 'a' }, - { "pace", required_argument, NULL, 'p' }, - { "version", required_argument, NULL, 'v' }, + { "arch", required_argument, NULL, 'a' }, + { "pace", required_argument, NULL, 'p' }, + { "version", required_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; @@ -1583,6 +1895,100 @@ _cw_vere(c3_i argc, c3_c* argv[]) u3l_log("vere: download succeeded\r\n"); } +/* _cw_vile(): generatoe/print keyfile +*/ +static void +_cw_vile(c3_i argc, c3_c* argv[]) +{ + c3_i ch_i, lid_i; + c3_w arg_w; + + static struct option lop_u[] = { + { "loom", required_argument, NULL, c3__loom }, + { NULL, 0, NULL, 0 } + }; + + u3_Host.dir_c = _main_pier_run(argv[0]); + + while ( -1 != (ch_i=getopt_long(argc, argv, "", lop_u, &lid_i)) ) { + switch ( ch_i ) { + case c3__loom: { + c3_w lom_w; + c3_o res_o = _main_readw(optarg, u3a_bits + 3, &lom_w); + if ( (c3n == res_o) || (lom_w < 20) ) { + fprintf(stderr, "error: --loom must be >= 20 and <= %u\r\n", u3a_bits + 2); + exit(1); + } + u3_Host.ops_u.lom_y = lom_w; + } break; + + case '?': { + fprintf(stderr, "invalid argument\r\n"); + exit(1); + } break; + } + } + + // argv[optind] is always "vile" + // + + if ( !u3_Host.dir_c ) { + if ( optind + 1 < argc ) { + u3_Host.dir_c = argv[optind + 1]; + } + else { + fprintf(stderr, "invalid command, pier required\r\n"); + exit(1); + } + + optind++; + } + + if ( optind + 1 != argc ) { + fprintf(stderr, "invalid command\r\n"); + exit(1); + } + + // XX check if snapshot is stale? + // + c3_d eve_d = u3m_boot(u3_Host.dir_c, (size_t)1 << u3_Host.ops_u.lom_y); + u3_noun sam = u3nc(u3nc(u3_nul, u3_nul), + u3nc(c3n, u3nq(c3__once, 'j', c3__vile, u3_nul))); + u3_noun res = u3v_soft_peek(0, sam); + + + switch ( u3h(res) ) { + default: c3_assert(0); + + case c3n: { + fprintf(stderr, "vile: unable to retrieve key file\r\n"); + u3_pier_punt_goof("foo", u3k(u3t(res))); + } + case c3y: { + u3_noun dat, vil, out; + c3_c* out_c; + + if ( (u3_nul != u3h(u3t(res))) + || (c3n == u3r_pq(u3t(u3t(res)), c3__omen, 0, &dat)) + || (c3n == u3r_p(dat, c3__atom, &vil)) + || (c3n == u3a_is_atom(vil)) ) + { + fprintf(stderr, "vile: unable to extract key file\r\n"); + u3m_p("vil", res); + } + else { + out = u3dc("scot", c3__uw, u3k(vil)); + out_c = u3r_string(out); + puts(out_c); + c3_free(out_c); + u3z(out); + } + } + } + + u3z(res); +} + /* _cw_utils(): "worker" utilities and "serf" entrypoint */ static c3_i @@ -1601,9 +2007,12 @@ _cw_utils(c3_i argc, c3_c* argv[]) // [%prep dir=@t] :: prep upgrade // [%queu dir=@t eve=@ud] :: cue state // [?(%vere %fetch-vere) dir=@t] :: download vere + // [%vile dir=@t] :: extract keys // :: :: ipc: - // [%serf dir=@t key=@t wag=@t hap=@ud eve=@ud] :: compute - // == + // $: %serf :: compute + // dir=@t key=@t wag=@t hap=@ud :: + // lom=@ud eve=@ud :: + // == == :: // // NB: don't print to anything other than stderr; // other streams may be used for ipc. @@ -1626,6 +2035,7 @@ _cw_utils(c3_i argc, c3_c* argv[]) switch ( mot_m ) { case c3__cram: _cw_cram(argc, argv); return 1; case c3__dock: _cw_dock(argc, argv); return 1; + case c3__eval: _cw_eval(argc, argv); return 1; case c3__mass: case c3__grab: _cw_grab(argc, argv); return 1; @@ -1637,6 +2047,7 @@ _cw_utils(c3_i argc, c3_c* argv[]) case c3__prep: _cw_prep(argc, argv); return 2; // continue on case c3__queu: _cw_queu(argc, argv); return 1; case c3__vere: _cw_vere(argc, argv); return 1; + case c3__vile: _cw_vile(argc, argv); return 1; case c3__serf: _cw_serf_commence(argc, argv); return 1; } @@ -1828,7 +2239,7 @@ main(c3_i argc, // starting u3m configures OpenSSL memory functions, so we must do it // before any OpenSSL allocations // - u3m_boot_lite(); + u3m_boot_lite((size_t)1 << u3_Host.ops_u.lut_y); // Initialize OpenSSL for client and server // diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index e8b944394d..f67a50f4ed 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -387,6 +387,7 @@ # define c3__ergo c3_s4('e','r','g','o') # define c3__esh c3_s3('e','s','h') # define c3__etch c3_s4('e','t','c','h') +# define c3__eval c3_s4('e','v','a','l') # define c3__evil c3_s4('e','v','i','l') # define c3__ex c3_s2('e','x') # define c3__exit c3_s4('e','x','i','t') @@ -698,6 +699,7 @@ # define c3__lond c3_s4('l','o','n','d') # define c3__lonk c3_s4('l','o','n','k') # define c3__look c3_s4('l','o','o','k') +# define c3__loom c3_s4('l','o','o','m') # define c3__loop c3_s4('l','o','o','p') # define c3__lorb c3_s4('l','o','r','b') # define c3__lord c3_s4('l','o','r','d') @@ -1239,6 +1241,7 @@ # define c3__vern c3_s4('v','e','r','n') # define c3__very c3_s4('v','e','r','y') # define c3__view c3_s4('v','i','e','w') +# define c3__vile c3_s4('v','i','l', 'e') # define c3__vint c3_s4('v','i','n','t') # define c3__void c3_s4('v','o','i','d') # define c3__vorp c3_s4('v','o','r','p') @@ -1296,6 +1299,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') diff --git a/pkg/urbit/include/c/portable.h b/pkg/urbit/include/c/portable.h index 83871d32f9..671db4d069 100644 --- a/pkg/urbit/include/c/portable.h +++ b/pkg/urbit/include/c/portable.h @@ -157,24 +157,24 @@ # else # define U3_OS_LoomBase 0x36000000 # endif -# define U3_OS_LoomBits 29 +# define U3_OS_LoomBits 30 # elif defined(U3_OS_mingw) # define U3_OS_LoomBase 0x28000000000 -# define U3_OS_LoomBits 29 +# define U3_OS_LoomBits 30 # elif defined(U3_OS_osx) # ifdef __LP64__ # define U3_OS_LoomBase 0x28000000000 # else # define U3_OS_LoomBase 0x4000000 # endif -# define U3_OS_LoomBits 29 +# define U3_OS_LoomBits 30 # elif defined(U3_OS_bsd) # ifdef __LP64__ # define U3_OS_LoomBase 0x200000000 # else # define U3_OS_LoomBase 0x4000000 # endif -# define U3_OS_LoomBits 29 +# define U3_OS_LoomBits 30 # else # error "port: LoomBase" # endif diff --git a/pkg/urbit/include/noun/allocate.h b/pkg/urbit/include/noun/allocate.h index 529ad6fb60..964de538be 100644 --- a/pkg/urbit/include/noun/allocate.h +++ b/pkg/urbit/include/noun/allocate.h @@ -1,8 +1,6 @@ #ifndef U3_ALLOCATE_H #define U3_ALLOCATE_H -#include - #include "manage.h" /** Constants. @@ -15,15 +13,15 @@ */ # define u3a_page 12 - /* u3a_pages: number of pages in memory. + /* u3a_pages: maximum number of pages in memory. */ # define u3a_pages (1 << (u3a_bits - u3a_page)) - /* u3a_words: number of words in memory. + /* u3a_words: maximum number of words in memory. */ # define u3a_words (1 << u3a_bits) - /* u3a_bytes: number of bytes in memory. + /* u3a_bytes: maximum number of bytes in memory. */ # define u3a_bytes (sizeof(c3_w) * u3a_words) @@ -477,15 +475,6 @@ void* u3a_malloc(size_t len_i); - /* u3a_malloc_ssl(): openssl-shaped malloc - */ - void* - u3a_malloc_ssl(size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* u3a_calloc(): aligned storage measured in bytes. */ void* @@ -496,39 +485,11 @@ void* u3a_realloc(void* lag_v, size_t len_i); - /* u3a_realloc2(): gmp-shaped realloc. - */ - void* - u3a_realloc2(void* lag_v, size_t old_i, size_t new_i); - - /* u3a_realloc_ssl(): openssl-shaped realloc. - */ - void* - u3a_realloc_ssl(void* lag_v, size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* u3a_free(): free for aligned malloc. */ void u3a_free(void* tox_v); - /* u3a_free2(): gmp-shaped free. - */ - void - u3a_free2(void* tox_v, size_t siz_i); - - /* u3a_free_ssl(): openssl-shaped free. - */ - void - u3a_free_ssl(void* tox_v -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* Reference and arena control. */ /* u3a_gain(): gain a reference count in normal space. diff --git a/pkg/urbit/include/noun/events.h b/pkg/urbit/include/noun/events.h index 7edf44a2f9..c1b95cde83 100644 --- a/pkg/urbit/include/noun/events.h +++ b/pkg/urbit/include/noun/events.h @@ -41,6 +41,7 @@ typedef struct _u3e_pool { c3_c* dir_c; // path to c3_w dit_w[u3a_pages >> 5]; // touched since last save + c3_w pag_w; // number of pages (<= u3a_pages) u3e_image nor_u; // north segment u3e_image sou_u; // south segment } u3e_pool; diff --git a/pkg/urbit/include/noun/manage.h b/pkg/urbit/include/noun/manage.h index 89f50d6037..72e29f5330 100644 --- a/pkg/urbit/include/noun/manage.h +++ b/pkg/urbit/include/noun/manage.h @@ -6,12 +6,12 @@ /* u3m_boot(): start the u3 system. return next event, starting from 1. */ c3_d - u3m_boot(c3_c* dir_c); + u3m_boot(c3_c* dir_c, size_t len_i); /* u3m_boot_lite(): start without checkpointing. */ c3_d - u3m_boot_lite(void); + u3m_boot_lite(size_t len_i); /* u3m_stop(): graceful shutdown cleanup. */ void @@ -37,7 +37,7 @@ /* u3m_init(): start the environment. */ void - u3m_init(); + u3m_init(size_t len_i); /* u3m_pave(): instantiate or activate image. */ diff --git a/pkg/urbit/include/noun/options.h b/pkg/urbit/include/noun/options.h index f73dba264d..c1fd58c408 100644 --- a/pkg/urbit/include/noun/options.h +++ b/pkg/urbit/include/noun/options.h @@ -9,6 +9,7 @@ u3_noun who; // single identity c3_c* dir_c; // execution directory (pier) c3_w wag_w; // flags (both ways) + size_t wor_i; // loom word-length (<= u3a_words) void (*stderr_log_f)(c3_c*); // errors from c code void (*slog_f)(u3_noun); // function pointer for slog void (*sign_hold_f)(void); // suspend system signal regime diff --git a/pkg/urbit/include/noun/retrieve.h b/pkg/urbit/include/noun/retrieve.h index edd2275bfa..b6e96e3804 100644 --- a/pkg/urbit/include/noun/retrieve.h +++ b/pkg/urbit/include/noun/retrieve.h @@ -304,6 +304,7 @@ ** (1 << a_y). ** ** For example, (a_y == 3) returns the size in bytes. + ** NB: (a_y) must be < 37. */ c3_w u3r_met(c3_y a_y, @@ -362,18 +363,50 @@ u3r_bytes_all(c3_w* len_w, u3_atom a); + /* u3r_chop_bits(): + ** + ** XOR `wid_d` bits from`src_w` at `bif_g` to `dst_w` at `bif_g` + ** + ** NB: [dst_w] must have space for [bit_g + wid_d] bits + */ + void + u3r_chop_bits(c3_g bif_g, + c3_d wid_d, + c3_g bit_g, + c3_w* dst_w, + const c3_w* src_w); + + /* u3r_chop_words(): + ** + ** Into the bloq space of `met`, from position `fum` for a + ** span of `wid`, to position `tou`, XOR from `src_w` + ** into `dst_w`. + ** + ** NB: [dst_w] must have space for [tou_w + wid_w] bloqs + */ + void + u3r_chop_words(c3_g met_g, + c3_w fum_w, + c3_w wid_w, + c3_w tou_w, + c3_w* dst_w, + c3_w len_w, + const c3_w* src_w); + /* u3r_chop(): ** ** Into the bloq space of `met`, from position `fum` for a ** span of `wid`, to position `tou`, XOR from atom `src` - ** into ray `dst`. + ** into `dst_w`. + ** + ** NB: [dst_w] must have space for [tou_w + wid_w] bloqs */ void - u3r_chop(c3_g met_g, - c3_w fum_w, - c3_w wid_w, - c3_w tou_w, - c3_w* dst_w, + u3r_chop(c3_g met_g, + c3_w fum_w, + c3_w wid_w, + c3_w tou_w, + c3_w* dst_w, u3_atom src); /* u3r_mp(): diff --git a/pkg/urbit/include/noun/vortex.h b/pkg/urbit/include/noun/vortex.h index 3e8f014840..92320620a7 100644 --- a/pkg/urbit/include/noun/vortex.h +++ b/pkg/urbit/include/noun/vortex.h @@ -77,6 +77,11 @@ u3_noun u3v_peek(u3_noun hap); + /* u3v_soft_peek(): softly query the reck namespace. + */ + u3_noun + u3v_soft_peek(c3_w mil_w, u3_noun sam); + /* u3v_poke(): insert and apply an input ovum (protected). */ u3_noun diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index d33d1ff84e..d02771343f 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -291,6 +291,8 @@ c3_c* key_c; // -k, private key file c3_o net; // -L, local-only networking c3_o lit; // -l, lite mode + c3_y lom_y; // loom bex + c3_y lut_y; // urth-loom bex c3_c* til_c; // -n, play till eve_d c3_o pro; // -P, profile c3_s per_s; // http port diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index 2a92e64903..f7ce679584 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -692,18 +692,6 @@ u3a_malloc(size_t len_i) return out_w; } -/* u3a_malloc_ssl(): openssl-shaped malloc -*/ -void* -u3a_malloc_ssl(size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_malloc(len_i); -} - /* u3a_cellblock(): allocate a block of cells on the hat. */ static c3_o @@ -885,26 +873,6 @@ u3a_realloc(void* lag_v, size_t len_i) return u3a_wealloc(lag_v, (len_w + 3) >> 2); } -/* u3a_realloc2(): gmp-shaped realloc. -*/ -void* -u3a_realloc2(void* lag_v, size_t old_i, size_t new_i) -{ - return u3a_realloc(lag_v, new_i); -} - -/* u3a_realloc_ssl(): openssl-shaped realloc. -*/ -void* -u3a_realloc_ssl(void* lag_v, size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_realloc(lag_v, len_i); -} - /* u3a_free(): free for aligned malloc. */ void @@ -921,26 +889,6 @@ u3a_free(void* tox_v) u3a_wfree(org_w); } -/* u3a_free2(): gmp-shaped free. -*/ -void -u3a_free2(void* tox_v, size_t siz_i) -{ - return u3a_free(tox_v); -} - -/* u3a_free_ssl(): openssl-shaped free. -*/ -void -u3a_free_ssl(void* tox_v -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_free(tox_v); -} - /* _me_wash_north(): clean up mug slots after copy. */ static void _me_wash_north(u3_noun dog); diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 551149cb65..ceec1bd411 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -136,9 +136,9 @@ u3e_check(c3_c* cap_c) sum_w += mug_w; } for ( i_w = 0; i_w < sou_w; i_w++ ) { - mug_w = _ce_check_page((u3a_pages - (i_w + 1))); + mug_w = _ce_check_page((u3P.pag_w - (i_w + 1))); if ( strcmp(cap_c, "boot") ) { - c3_assert(mug_w == u3K.mug_w[(u3a_pages - (i_w + 1))]); + c3_assert(mug_w == u3K.mug_w[(u3P.pag_w - (i_w + 1))]); } sum_w += mug_w; } @@ -195,7 +195,7 @@ _ce_center_guard_page(void) { u3p(c3_w) bot_p, top_p; if ( !u3R ) { - top_p = u3a_outa(u3_Loom + u3a_words); + top_p = u3a_outa(u3_Loom + u3C.wor_i); bot_p = u3a_outa(u3_Loom); } else if ( c3y == u3a_is_north(u3R) ) { @@ -256,9 +256,9 @@ u3e_fault(void* adr_v, c3_i ser_i) c3_w* adr_w = (c3_w*) adr_v; - if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3a_words)) ) { + if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) { fprintf(stderr, "address %p out of loom!\r\n", adr_w); - fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3a_words); + fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3C.wor_i); c3_assert(0); return 0; } @@ -668,7 +668,7 @@ _ce_patch_compose(void) pgs_w = _ce_patch_count_page(i_w, pgs_w); } for ( i_w = 0; i_w < sou_w; i_w++ ) { - pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w); + pgs_w = _ce_patch_count_page((u3P.pag_w - (i_w + 1)), pgs_w); } } @@ -688,7 +688,7 @@ _ce_patch_compose(void) pgc_w = _ce_patch_save_page(pat_u, i_w, pgc_w); } for ( i_w = 0; i_w < sou_w; i_w++ ) { - pgc_w = _ce_patch_save_page(pat_u, (u3a_pages - (i_w + 1)), pgc_w); + pgc_w = _ce_patch_save_page(pat_u, (u3P.pag_w - (i_w + 1)), pgc_w); } pat_u->con_u->nor_w = nor_w; @@ -738,7 +738,7 @@ _ce_image_resize(u3e_image* img_u, c3_w pgs_w) { if ( img_u->pgs_w > pgs_w ) { if ( ftruncate(img_u->fid_i, pgs_w << (u3a_page + 2)) ) { - fprintf(stderr, "loom: image truncate %s: %s\r\n", + fprintf(stderr, "loom: image (%s) truncate: %s\r\n", img_u->nam_c, strerror(errno)); c3_assert(0); @@ -785,7 +785,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } else { fid_i = u3P.sou_u.fid_i; - off_w = (u3a_pages - (pag_w + 1)); + off_w = (u3P.pag_w - (pag_w + 1)); } if ( pag_siz_i != (ret_i = read(pat_u->mem_i, mem_w, pag_siz_i)) ) { @@ -836,18 +836,20 @@ _ce_image_blit(u3e_image* img_u, c3_w siz_w = pag_siz_i; if ( -1 == lseek(img_u->fid_i, 0, SEEK_SET) ) { - fprintf(stderr, "loom: image blit seek 0: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) blit seek 0: %s\r\n", + img_u->nam_c, strerror(errno)); c3_assert(0); } for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) { if ( siz_w != (ret_i = read(img_u->fid_i, ptr_w, siz_w)) ) { if ( 0 < ret_i ) { - fprintf(stderr, "loom: image blit partial read: %zu\r\n", - (size_t)ret_i); + fprintf(stderr, "loom: image (%s) blit partial read: %zu\r\n", + img_u->nam_c, (size_t)ret_i); } else { - fprintf(stderr, "loom: image blit read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) blit read: %s\r\n", + img_u->nam_c, strerror(errno)); } c3_assert(0); } @@ -888,10 +890,12 @@ _ce_image_fine(u3e_image* img_u, if ( pag_siz_i != (ret_i = read(img_u->fid_i, buf_w, pag_siz_i)) ) { if ( 0 < ret_i ) { - fprintf(stderr, "loom: image fine partial read: %zu\r\n", (size_t)ret_i); + fprintf(stderr, "loom: image (%s) fine partial read: %zu\r\n", + img_u->nam_c, (size_t)ret_i); } else { - fprintf(stderr, "loom: image fine read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) fine read: %s\r\n", + img_u->nam_c, strerror(errno)); } c3_assert(0); } @@ -901,11 +905,13 @@ _ce_image_fine(u3e_image* img_u, if ( mem_w != fil_w ) { c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page; - fprintf(stderr, "mismatch: page %d, mem_w %x, fil_w %x, K %x\r\n", - pag_w, - mem_w, - fil_w, - u3K.mug_w[pag_w]); + fprintf(stderr, "loom: image (%s) mismatch: " + "page %d, mem_w %x, fil_w %x, K %x\r\n", + img_u->nam_c, + pag_w, + mem_w, + fil_w, + u3K.mug_w[pag_w]); abort(); } ptr_w += stp_ws; @@ -930,7 +936,9 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) if ( (-1 == lseek(fom_u->fid_i, 0, SEEK_SET)) || (-1 == lseek(tou_u->fid_i, 0, SEEK_SET)) ) { - fprintf(stderr, "loom: image copy seek 0: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", + fom_u->nam_c, + strerror(errno)); return c3n; } @@ -942,26 +950,29 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) if ( pag_siz_i != (ret_i = read(fom_u->fid_i, mem_w, pag_siz_i)) ) { if ( 0 < ret_i ) { - fprintf(stderr, "loom: image copy partial read: %zu\r\n", - (size_t)ret_i); + fprintf(stderr, "loom: image (%s) copy partial read: %zu\r\n", + fom_u->nam_c, (size_t)ret_i); } else { - fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy read: %s\r\n", + fom_u->nam_c, strerror(errno)); } return c3n; } else { if ( -1 == lseek(tou_u->fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) { - fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", + tou_u->nam_c, strerror(errno)); return c3n; } if ( pag_siz_i != (ret_i = write(tou_u->fid_i, mem_w, pag_siz_i)) ) { if ( 0 < ret_i ) { - fprintf(stderr, "loom: image copy partial write: %zu\r\n", - (size_t)ret_i); + fprintf(stderr, "loom: image (%s) copy partial write: %zu\r\n", + tou_u->nam_c, (size_t)ret_i); } else { - fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy write: %s\r\n", + tou_u->nam_c, strerror(errno)); } return c3n; } @@ -1069,7 +1080,7 @@ u3e_save(void) pag_wiz_i); _ce_image_fine(&u3P.sou_u, - (u3_Loom + (1 << u3a_bits) - pag_wiz_i), + (u3_Loom + u3C.wor_i) - pag_wiz_i, -(ssize_t)pag_wiz_i); c3_assert(u3P.nor_u.pgs_w == u3K.nor_w); @@ -1105,6 +1116,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) u3P.dir_c = dir_c; u3P.nor_u.nam_c = "north"; u3P.sou_u.nam_c = "south"; + u3P.pag_w = u3C.wor_i >> u3a_page; // XX review dryrun requirements, enable or remove // @@ -1154,7 +1166,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) pag_wiz_i); _ce_image_blit(&u3P.sou_u, - (u3_Loom + (1 << u3a_bits) - pag_wiz_i), + (u3_Loom + u3C.wor_i) - pag_wiz_i, -(ssize_t)pag_wiz_i); u3l_log("boot: protected loom\r\n"); @@ -1181,9 +1193,12 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) c3_o u3e_yolo(void) { - // NB: u3e_save() will reinstate protection flags + // NB: u3e_save() will reinstate protection flags // - if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, (PROT_READ | PROT_WRITE)) ) { + if ( 0 != mprotect((void *)u3_Loom, + u3C.wor_i << 2, + (PROT_READ | PROT_WRITE)) ) + { // XX confirm recoverable errors // fprintf(stderr, "loom: yolo: %s\r\n", strerror(errno)); @@ -1212,6 +1227,8 @@ u3e_foul(void) void u3e_init(void) { + u3P.pag_w = u3C.wor_i >> u3a_page; + #ifdef U3_GUARD_PAGE _ce_center_guard_page(); #endif diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index e5648a6ab4..aa33b03287 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -553,7 +553,7 @@ _pave_home(void) { c3_w* mem_w = u3_Loom + 1; c3_w siz_w = c3_wiseof(u3v_home); - c3_w len_w = u3a_words - 1; + c3_w len_w = u3C.wor_i - 1; u3H = (void *)_pave_north(mem_w, siz_w, len_w); u3H->ver_w = u3v_version; @@ -574,7 +574,7 @@ _find_home(void) // c3_w* mem_w = u3_Loom + 1; c3_w siz_w = c3_wiseof(u3v_home); - c3_w len_w = u3a_words - 1; + c3_w len_w = u3C.wor_i - 1; { c3_w ver_w = *((mem_w + len_w) - 1); @@ -594,7 +594,7 @@ _find_home(void) // this looks risky, but there are no legitimate scenarios // where it's wrong // - u3R->cap_p = u3R->mat_p = u3a_words - c3_wiseof(*u3H); + u3R->cap_p = u3R->mat_p = u3C.wor_i - c3_wiseof(*u3H); } /* u3m_pave(): instantiate or activate image. @@ -695,22 +695,27 @@ u3m_bail(u3_noun how) abort(); } - /* Printf some metadata. - */ - if ( c3__exit != how && (_(u3ud(how)) || 1 != u3h(how)) ) { - if ( _(u3ud(how)) ) { - c3_c str_c[5]; + // printf some metadata + // + switch ( how ) { + case c3__evil: + case c3__exit: break; - str_c[0] = ((how >> 0) & 0xff); - str_c[1] = ((how >> 8) & 0xff); - str_c[2] = ((how >> 16) & 0xff); - str_c[3] = ((how >> 24) & 0xff); - str_c[4] = 0; - fprintf(stderr, "\r\nbail: %s\r\n", str_c); - } - else { - c3_assert(_(u3ud(u3h(how)))); - fprintf(stderr, "\r\nbail: %d\r\n", u3h(how)); + default: { + if ( _(u3ud(how)) ) { + c3_c str_c[5]; + + str_c[0] = ((how >> 0) & 0xff); + str_c[1] = ((how >> 8) & 0xff); + str_c[2] = ((how >> 16) & 0xff); + str_c[3] = ((how >> 24) & 0xff); + str_c[4] = 0; + fprintf(stderr, "\r\nbail: %s\r\n", str_c); + } + else if ( 1 != u3h(how) ) { + c3_assert(_(u3ud(u3h(how)))); + fprintf(stderr, "\r\nbail: %d\r\n", u3h(how)); + } } } @@ -1720,16 +1725,53 @@ _cm_signals(void) # endif } -extern void u3je_secp_init(void); -extern void u3je_secp_stop(void); +/* _cm_malloc_ssl(): openssl-shaped malloc +*/ +static void* +_cm_malloc_ssl(size_t len_i +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_malloc(len_i); +} +/* _cm_realloc_ssl(): openssl-shaped realloc. +*/ +static void* +_cm_realloc_ssl(void* lag_v, size_t len_i +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_realloc(lag_v, len_i); +} + +/* _cm_free_ssl(): openssl-shaped free. +*/ +static void +_cm_free_ssl(void* tox_v +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_free(tox_v); +} + +extern void u3je_secp_init(void); + +/* _cm_crypto(): initialize openssl and crypto jets. +*/ static void _cm_crypto() { /* Initialize OpenSSL with loom allocation functions. */ - if ( 0 == CRYPTO_set_mem_functions(&u3a_malloc_ssl, - &u3a_realloc_ssl, - &u3a_free_ssl) ) { + if ( 0 == CRYPTO_set_mem_functions(&_cm_malloc_ssl, + &_cm_realloc_ssl, + &_cm_free_ssl) ) { u3l_log("%s\r\n", "openssl initialization failed"); abort(); } @@ -1737,53 +1779,81 @@ _cm_crypto() u3je_secp_init(); } +/* _cm_realloc2(): gmp-shaped realloc. +*/ +static void* +_cm_realloc2(void* lag_v, size_t old_i, size_t new_i) +{ + return u3a_realloc(lag_v, new_i); +} + +/* _cm_free2(): gmp-shaped free. +*/ +static void +_cm_free2(void* tox_v, size_t siz_i) +{ + return u3a_free(tox_v); +} + /* u3m_init(): start the environment. */ void -u3m_init(void) +u3m_init(size_t len_i) { _cm_limits(); _cm_signals(); _cm_crypto(); - /* Make sure GMP uses our malloc. - */ - mp_set_memory_functions(u3a_malloc, u3a_realloc2, u3a_free2); + // make sure GMP uses our malloc. + // + mp_set_memory_functions(u3a_malloc, _cm_realloc2, _cm_free2); - /* Map at fixed address. - */ + // make sure that [len_i] is a fully-addressible non-zero power of two. + // + if ( !len_i + || (len_i & (len_i - 1)) + || (len_i < (1 << (u3a_page + 2))) + || (len_i > u3a_bytes) ) { - c3_w len_w = u3a_bytes; - void* map_v; + u3l_log("loom: bad size: %zu\r\n", len_i); + exit(1); + } - map_v = mmap((void *)u3_Loom, - len_w, - (PROT_READ | PROT_WRITE), - (MAP_ANON | MAP_FIXED | MAP_PRIVATE), - -1, 0); + // map at fixed address. + // + { + void* map_v = mmap((void *)u3_Loom, + len_i, + (PROT_READ | PROT_WRITE), + (MAP_ANON | MAP_FIXED | MAP_PRIVATE), + -1, 0); if ( -1 == (c3_ps)map_v ) { - void* dyn_v = mmap((void *)0, - len_w, - PROT_READ, - MAP_ANON | MAP_PRIVATE, - -1, 0); + map_v = mmap((void *)0, + len_i, + (PROT_READ | PROT_WRITE), + (MAP_ANON | MAP_PRIVATE), + -1, 0); - u3l_log("boot: mapping %dMB failed\r\n", (len_w / (1024 * 1024))); + u3l_log("boot: mapping %zuMB failed\r\n", len_i >> 20); u3l_log("see urbit.org/using/install/#about-swap-space" " for adding swap space\r\n"); - if ( -1 != (c3_ps)dyn_v ) { + if ( -1 != (c3_ps)map_v ) { u3l_log("if porting to a new platform, try U3_OS_LoomBase %p\r\n", - dyn_v); + map_v); } exit(1); } - u3l_log("loom: mapped %dMB\r\n", len_w >> 20); + u3C.wor_i = len_i >> 2; + u3l_log("loom: mapped %zuMB\r\n", len_i >> 20); } } -/* u3m_stop(): graceful shutdown cleanup. */ +extern void u3je_secp_stop(void); + +/* u3m_stop(): graceful shutdown cleanup. +*/ void u3m_stop() { @@ -1793,13 +1863,13 @@ u3m_stop() /* u3m_boot(): start the u3 system. return next event, starting from 1. */ c3_d -u3m_boot(c3_c* dir_c) +u3m_boot(c3_c* dir_c, size_t len_i) { c3_o nuu_o; /* Activate the loom. */ - u3m_init(); + u3m_init(len_i); /* Activate the storage system. */ @@ -1832,7 +1902,6 @@ u3m_boot(c3_c* dir_c) if ( c3n == nuu_o ) { u3j_ream(); u3n_ream(); - return u3A->eve_d; } else { @@ -1846,11 +1915,11 @@ u3m_boot(c3_c* dir_c) /* u3m_boot_lite(): start without checkpointing. */ c3_d -u3m_boot_lite(void) +u3m_boot_lite(size_t len_i) { /* Activate the loom. */ - u3m_init(); + u3m_init(len_i); /* Activate tracing. */ diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index 3722f1d619..dda8a4921a 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -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,14 +500,14 @@ _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 */ \ + 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 */ \ X(LAST, NULL, NULL), /* 95 */ // Opcodes. Define X to select the enum name from OPCODES. @@ -522,6 +527,7 @@ _n_arg(c3_y cod_y) case SLIB: case SKIB: case KICB: case TICB: case BUSH: case BAST: case BALT: case MUTB: case KUTB: case MITB: case KITB: + case HILB: case HINB: return sizeof(c3_y); case FASK: case FASL: case FISL: case FISK: @@ -530,6 +536,7 @@ _n_arg(c3_y cod_y) case SLIS: case SKIS: case KICS: case TICS: case SUSH: case SAST: case SALT: case MUTS: case KUTS: case MITS: case KITS: + case HILS: case HINS: return sizeof(c3_s); case SWIP: case SWIN: @@ -779,7 +786,7 @@ _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); + buf_y[i_w] = (c3_y) op; break; /* registration site index args */ @@ -956,12 +963,10 @@ static void _n_print_stack(u3p(u3_noun) empty) { } #endif -#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 /* _n_apen(): emit the instructions contained in src to dst */ @@ -998,6 +1003,7 @@ _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); } + case c3__xray: case c3__nara: case c3__hela: case c3__bout: { @@ -1034,6 +1040,7 @@ _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; + case c3__xray: case c3__nara: case c3__hela: case c3__bout: { @@ -1665,6 +1672,144 @@ u3n_find(u3_noun key, u3_noun fol) return pog_p; } +/* _cn_prog_free(): free memory retained by program pog_u +*/ +static void +_cn_prog_free(u3n_prog* pog_u) +{ + c3_w dex_w; + for (dex_w = 0; dex_w < pog_u->lit_u.len_w; ++dex_w) { + u3z(pog_u->lit_u.non[dex_w]); + } + for (dex_w = 0; dex_w < pog_u->mem_u.len_w; ++dex_w) { + u3z(pog_u->mem_u.sot_u[dex_w].key); + } + for (dex_w = 0; dex_w < pog_u->cal_u.len_w; ++dex_w) { + u3j_site_lose(&(pog_u->cal_u.sit_u[dex_w])); + } + for (dex_w = 0; dex_w < pog_u->reg_u.len_w; ++dex_w) { + u3j_rite_lose(&(pog_u->reg_u.rit_u[dex_w])); + } + u3a_free(pog_u); +} + +/* _cn_intlen(): find the number of characters num_w would take to print. +** num_w: an int we want to later serialize to a string +*/ +c3_w +_cn_intlen(c3_w num_w) +{ + c3_w len_w=0; + while(num_w){ + num_w/=10; + len_w++; + } + return len_w; +} + +/* _cn_is_indexed(): return true if bop_w is an opcodes that uses pog_u->lit_u.non +** bop_w: opcode (assumed 0-94) +*/ +c3_b +_cn_is_indexed(c3_w bop_w) +{ + switch (bop_w) { + case FIBK: case FISK: + case FIBL: case FISL: + case LIBK: case LISK: + case LIBL: case LISL: + case BUSH: case SUSH: + case SANB: case SANS: + case KITB: case KITS: + case MITB: case MITS: + case HILB: case HILS: + case HINB: case HINS: + return 1; + default: + return 0; + } +} + +/* _cn_pog_to_num(): read a bytecode from the steam and advance the index +** par_w: c3_w: can be 0, 2, 4 +** pog_y: c3_y*: a bytecode stream +** ip_w: c3_w: an index into pog +*/ +#define _cn_pog_to_num(par_w, pog_y, ip_w) (\ + par_w == 4 ? _n_rewo(pog_y, &ip_w): \ + par_w == 2 ? _n_resh(pog_y, &ip_w): \ + pog_y[ip_w++]) + +/* _cn_etch_bytecode(): render a nock program as string of bytecodes +** fol: a nock formula to compile and render +** returns: a u3i_string noun of the rendered bytecode +*/ +u3_noun +_cn_etch_bytecode(u3_noun fol) { + u3n_prog* pog_u = _n_bite(fol); + c3_y* pog_y = pog_u->byc_u.ops_y; + c3_w len_w = pog_u->byc_u.len_w; + c3_w ip_w=0, num_w=0, bop_w=0, dex_w=0; + c3_w len_c = 1; // opening "{" + // set par_w (parameter flag) to an invalid value, + // so we can break imeadately if needed + c3_w par_w = 5; + // lets count the chars in this string + while ( ip_w < len_w ) { + par_w = _n_arg(pog_y[ip_w]); + bop_w = pog_y[ip_w++]; // move ip_w for reading a opcode name + dex_w = _cn_is_indexed(bop_w); // is this an indexed bytecode argument + len_c += 5; // a leading space, and opcode name + if (par_w > 0) { // if pair: "[bytecode arg]" else "bytecode" + len_c += 3; // "[", space between opcode & arg, "]" + if ( dex_w ) len_c += 2; // 'i:' + len_c += _cn_intlen( // length of the bytecode argument + _cn_pog_to_num(par_w, pog_y, ip_w) + ); + } + } + // reset so we can loop again + ip_w=0, num_w=0, bop_w=0, dex_w=0, par_w=5; + // init our string, and give it a trailing null + c3_c str_c[len_c]; + str_c[0] = 0; + // lets print this string + while ( ip_w < len_w ) { + par_w = _n_arg(pog_y[ip_w]); + bop_w = pog_y[ip_w++]; // move ip_w for reading a opcode name + dex_w = _cn_is_indexed(bop_w); // is this an indexed bytecode argument + strcat(str_c, " "); // leading space + if (par_w > 0) strcat(str_c, "["); // add "[" if the opcode pairs + strncat(str_c, opcode_names[bop_w], 4); // add the opcode name + if (par_w > 0) { // finish the pair + strcat(str_c, " "); // add the space between byt and arg + if ( dex_w ) strcat(str_c, "i:"); // indexed args are labeled as "index of arg" + num_w = _cn_pog_to_num(par_w, pog_y, ip_w); // the bytecode argument + if (num_w == 0) { // + strcat(str_c, "0"); // handle a literal zero + } // + else { // + c3_w x = 0; // + for (x = _cn_intlen(num_w); x > 0; x--) { // + strcat(str_c, "_"); // prefill the buffer + } // + c3_w f = strlen(str_c)-1; // get the index of the last prefill + while (num_w > 0) { // stringify number in LSB order + str_c[f--] = (num_w%10)+'0'; // .. stringify the tail of num into tail of buf + num_w /= 10; // .. turncate num by one digit + } // + } // + strcat(str_c, "]"); // add the closing brace + } + } + // replace the first leading space and append the last char to the string + str_c[0] = '{'; + strcat(str_c, "}"); + _cn_prog_free(pog_u); + return u3i_string(str_c); +} + + /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN @@ -1695,6 +1840,11 @@ _n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) *out = u3_nul; } break; + case c3__xray : { + u3t_slog(u3nc(0, _cn_etch_bytecode(fol))); + *out = u3_nul; + } break; + default: { *out = u3_nul; } break; @@ -1769,6 +1919,16 @@ _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* 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, u3k(tan), _cn_etch_bytecode(fol)); + } + u3z(*clu); + *clu = u3_nul; + } break; + default: { u3z(*clu); *clu = u3_nul; @@ -2646,32 +2806,6 @@ u3n_nock_on(u3_noun bus, u3_noun fol) return pro; } -/* _n_prog_free(): free memory retained by program -*/ -static void -_n_prog_free(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); -} - /* _cn_take_prog_dat(): take references from junior u3n_prog. */ static void @@ -2920,7 +3054,7 @@ u3n_rewrite_compact() static void _n_feb(u3_noun kev) { - _n_prog_free(u3to(u3n_prog, u3t(kev))); + _cn_prog_free(u3to(u3n_prog, u3t(kev))); } /* u3n_free(): free bytecode cache diff --git a/pkg/urbit/noun/retrieve.c b/pkg/urbit/noun/retrieve.c index c207c7f47f..06a9fb2fe0 100644 --- a/pkg/urbit/noun/retrieve.c +++ b/pkg/urbit/noun/retrieve.c @@ -1023,10 +1023,11 @@ u3r_hext(u3_noun a, ** (1 << a_y). ** ** For example, (a_y == 3) returns the size in bytes. +** NB: (a_y) must be < 37. */ c3_w -u3r_met(c3_y a_y, - u3_atom b) +u3r_met(c3_y a_y, + u3_atom b) { c3_assert(u3_none != b); c3_assert(_(u3a_is_atom(b))); @@ -1061,19 +1062,23 @@ u3r_met(c3_y a_y, */ c3_w bif_w, col_w; + if ( gal_w > ((UINT32_MAX - 35) >> 5) ) { + return u3m_bail(c3__fail); + } + col_w = c3_bits_word(daz_w); bif_w = col_w + (gal_w << 5); return (bif_w + ((1 << a_y) - 1)) >> a_y; } - case 3: { - return (gal_w << 2) - + ((daz_w >> 24) ? 4 : (daz_w >> 16) ? 3 : (daz_w >> 8) ? 2 : 1); - } - case 4: { - return (gal_w << 1) - + ((daz_w >> 16) ? 2 : 1); - } + + STATIC_ASSERT((UINT32_MAX > ((c3_d)u3a_maximum << 2)), + "met overflow"); + + case 3: return (gal_w << 2) + ((c3_bits_word(daz_w) + 7) >> 3); + + case 4: return (gal_w << 1) + ((c3_bits_word(daz_w) + 15) >> 4); + default: { c3_y gow_y = (a_y - 5); @@ -1448,79 +1453,201 @@ u3r_safe_chub(u3_noun dat, c3_d* out_d) return c3y; } +/* u3r_chop_bits(): +** +** XOR `wid_d` bits from`src_w` at `bif_g` to `dst_w` at `bif_g` +** +** NB: [dst_w] must have space for [bit_g + wid_d] bits +*/ +void +u3r_chop_bits(c3_g bif_g, + c3_d wid_d, + c3_g bit_g, + c3_w* dst_w, + const c3_w* src_w) +{ + c3_y fib_y = 32 - bif_g; + c3_y tib_y = 32 - bit_g; + + // we need to chop words + // + if ( wid_d >= tib_y ) { + // align *dst_w + // + if ( bit_g ) { + c3_w low_w = src_w[0] >> bif_g; + + if ( bif_g > bit_g ) { + low_w ^= src_w[1] << fib_y; + } + + *dst_w++ ^= low_w << bit_g; + + wid_d -= tib_y; + bif_g += tib_y; + src_w += !!(bif_g >> 5); + bif_g &= 31; + fib_y = 32 - bif_g; + } + + { + size_t i_i, byt_i = wid_d >> 5; + + if ( !bif_g ) { + for ( i_i = 0; i_i < byt_i; i_i++ ) { + dst_w[i_i] ^= src_w[i_i]; + } + } + else { + for ( i_i = 0; i_i < byt_i; i_i++ ) { + dst_w[i_i] ^= (src_w[i_i] >> bif_g) ^ (src_w[i_i + 1] << fib_y); + } + } + + src_w += byt_i; + dst_w += byt_i; + wid_d &= 31; + bit_g = 0; + } + } + + // we need to chop (more) bits + // + if ( wid_d ) { + c3_w hig_w = src_w[0] >> bif_g; + + if ( wid_d > fib_y ) { + hig_w ^= src_w[1] << fib_y; + } + + *dst_w ^= (hig_w & ((1 << wid_d) - 1)) << bit_g; + } +} + +/* u3r_chop_words(): +** +** Into the bloq space of `met`, from position `fum` for a +** span of `wid`, to position `tou`, XOR from `src_w` +** into `dst_w`. +** +** NB: [dst_w] must have space for [tou_w + wid_w] bloqs +*/ +void +u3r_chop_words(c3_g met_g, + c3_w fum_w, + c3_w wid_w, + c3_w tou_w, + c3_w* dst_w, + c3_w len_w, + const c3_w* src_w) +{ + // operate on words + // + if ( met_g >= 5 ) { + size_t i_i, wid_i; + + { + c3_g hut_g = met_g - 5; + size_t fum_i = (size_t)fum_w << hut_g; + size_t tou_i = (size_t)tou_w << hut_g; + size_t tot_i; + + wid_i = (size_t)wid_w << hut_g; + tot_i = fum_i + wid_i; + + // since [dst_w] must have space for (tou_w + wid_w) bloqs, + // neither conversion can overflow + // + if ( (fum_i >> hut_g != fum_w) || (tot_i - wid_i != fum_i) ) { + u3m_bail(c3__fail); + return; + } + else if ( fum_i >= len_w ) { + return; + } + + if ( tot_i > len_w ) { + wid_i -= tot_i - len_w; + } + + src_w += fum_i; + dst_w += tou_i; + } + + for ( i_i = 0; i_i < wid_i; i_i++ ) { + dst_w[i_i] ^= src_w[i_i]; + } + } + // operate on bits + // + else { + c3_d wid_d = (c3_d)wid_w << met_g; + c3_g bif_g, bit_g; + + { + c3_d len_d = (c3_d)len_w << 5; + c3_d fum_d = (c3_d)fum_w << met_g; + c3_d tou_d = (c3_d)tou_w << met_g; + c3_d tot_d = fum_d + wid_d; + + // see above + // + if ( (fum_d >> met_g != fum_w) || (tot_d - wid_d != fum_d) ) { + u3m_bail(c3__fail); + return; + } + else if ( fum_d > len_d ) { + return; + } + + if ( tot_d > len_d ) { + wid_d -= tot_d - len_d; + } + + src_w += fum_d >> 5; + dst_w += tou_d >> 5; + bif_g = fum_d & 31; + bit_g = tou_d & 31; + } + + u3r_chop_bits(bif_g, wid_d, bit_g, dst_w, src_w); + } +} + /* u3r_chop(): ** ** Into the bloq space of `met`, from position `fum` for a ** span of `wid`, to position `tou`, XOR from atom `src` ** into `dst_w`. +** +** NB: [dst_w] must have space for [tou_w + wid_w] bloqs */ void -u3r_chop(c3_g met_g, - c3_w fum_w, - c3_w wid_w, - c3_w tou_w, - c3_w* dst_w, - u3_atom src) +u3r_chop(c3_g met_g, + c3_w fum_w, + c3_w wid_w, + c3_w tou_w, + c3_w* dst_w, + u3_atom src) { - c3_w i_w; + c3_w* src_w; c3_w len_w; - c3_w* buf_w; - - c3_assert(u3_none != src); - c3_assert(_(u3a_is_atom(src))); if ( _(u3a_is_cat(src)) ) { len_w = src ? 1 : 0; - buf_w = &src; + src_w = &src; } else { u3a_atom* src_u = u3a_to_ptr(src); + c3_assert(u3_none != src); + c3_assert(_(u3a_is_atom(src))); + len_w = src_u->len_w; - buf_w = src_u->buf_w; + src_w = src_u->buf_w; } - if ( met_g < 5 ) { - c3_w san_w = (1 << met_g); - c3_w mek_w = ((1 << san_w) - 1); - c3_w baf_w = (fum_w << met_g); - c3_w bat_w = (tou_w << met_g); - - // XX: efficiency: poor. Iterate by words. - // - for ( i_w = 0; i_w < wid_w; i_w++ ) { - c3_w waf_w = (baf_w >> 5); - c3_g raf_g = (baf_w & 31); - c3_w wat_w = (bat_w >> 5); - c3_g rat_g = (bat_w & 31); - c3_w hop_w; - - hop_w = (waf_w >= len_w) ? 0 : buf_w[waf_w]; - hop_w = (hop_w >> raf_g) & mek_w; - - dst_w[wat_w] ^= (hop_w << rat_g); - - baf_w += san_w; - bat_w += san_w; - } - } - else { - c3_g hut_g = (met_g - 5); - c3_w san_w = (1 << hut_g); - c3_w j_w; - - for ( i_w = 0; i_w < wid_w; i_w++ ) { - c3_w wuf_w = (fum_w + i_w) << hut_g; - c3_w wut_w = (tou_w + i_w) << hut_g; - - for ( j_w = 0; j_w < san_w; j_w++ ) { - dst_w[wut_w + j_w] ^= - ((wuf_w + j_w) >= len_w) - ? 0 - : buf_w[wuf_w + j_w]; - } - } - } + u3r_chop_words(met_g, fum_w, wid_w, tou_w, dst_w, len_w, src_w); } /* u3r_string(): `a` as malloced C string. @@ -1676,9 +1803,7 @@ u3r_mug_words(const c3_w* key_w, c3_w len_w) c3_w gal_w = len_w - 1; c3_w daz_w = key_w[gal_w]; - byt_w = (gal_w << 2) - + ((daz_w >> 24) ? 4 : (daz_w >> 16) ? 3 : (daz_w >> 8) ? 2 : 1); - + byt_w = (gal_w << 2) + ((c3_bits_word(daz_w) + 7) >> 3); } // XX: assumes little-endian diff --git a/pkg/urbit/noun/vortex.c b/pkg/urbit/noun/vortex.c index 03d174e1fc..016588ea86 100644 --- a/pkg/urbit/noun/vortex.c +++ b/pkg/urbit/noun/vortex.c @@ -216,6 +216,32 @@ u3v_peek(u3_noun sam) return u3n_slam_on(fun, sam); } +/* u3v_soft_peek(): softly query the reck namespace. +*/ +u3_noun +u3v_soft_peek(c3_w mil_w, u3_noun sam) +{ + u3_noun gon = u3m_soft(mil_w, u3v_peek, sam); + u3_noun tag, dat; + u3x_cell(gon, &tag, &dat); + + // read failed, produce trace + // + // NB, reads *should not* fail deterministically + // + if ( u3_blip != tag ) { + return u3nc(c3n, gon); + } + + // read succeeded, produce result + // + { + u3_noun pro = u3nc(c3y, u3k(dat)); + u3z(gon); + return pro; + } +} + /* u3v_poke(): insert and apply an input ovum (protected). */ u3_noun diff --git a/pkg/urbit/tests/ames_tests.c b/pkg/urbit/tests/ames_tests.c index 69ed7b9b98..0907898d41 100644 --- a/pkg/urbit/tests/ames_tests.c +++ b/pkg/urbit/tests/ames_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 22); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/boot_tests.c b/pkg/urbit/tests/boot_tests.c new file mode 100644 index 0000000000..1897bbe937 --- /dev/null +++ b/pkg/urbit/tests/boot_tests.c @@ -0,0 +1,68 @@ +#include "all.h" +#include "ur/ur.h" +#include "vere/ivory.h" +#include "vere/vere.h" + +/* _setup(): prepare for tests. +*/ +static void +_setup(void) +{ + c3_d len_d = u3_Ivory_pill_len; + c3_y* byt_y = u3_Ivory_pill; + u3_cue_xeno* sil_u; + u3_weak pil; + + u3C.wag_w |= u3o_hashless; + u3m_boot_lite(1 << 26); + sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { + printf("*** fail _setup 1\n"); + exit(1); + } + u3s_cue_xeno_done(sil_u); + if ( c3n == u3v_boot_lite(pil) ) { + printf("*** fail _setup 2\n"); + exit(1); + } +} + +/* _test_lily(): test small noun parsing. +*/ +static void +_test_lily() +{ + c3_l lit_l; + c3_w big_w[] = {0, 0, 1}; + u3_noun big = u3i_words(3, big_w); + u3_noun cod = u3dc("scot", c3__uv, big); + + if ( c3y == u3v_lily(c3__uv, cod, &lit_l) ) { + printf("*** fail _test_lily-1\n"); + exit(1); + } + cod = u3dc("scot", c3__ud, 0x7fffffff); + if ( (c3n == u3v_lily(c3__ud, cod, &lit_l)) || + (0x7fffffff != lit_l) ) { + printf("*** fail _test_lily-2a\n"); + exit(1); + } + cod = u3dc("scot", c3__ux, u3i_word(0x80000000)); + if ( c3y == u3v_lily(c3__ux, cod, &lit_l) ) { + printf("*** fail _test_lily-2b\n"); + exit(1); + } +} + +/* main(): run all test cases. +*/ +int +main(int argc, char* argv[]) +{ + _setup(); + + _test_lily(); + + fprintf(stderr, "test boot: ok\n"); + return 0; +} diff --git a/pkg/urbit/tests/hashtable_tests.c b/pkg/urbit/tests/hashtable_tests.c index 6322a331cc..3b36dc8876 100644 --- a/pkg/urbit/tests/hashtable_tests.c +++ b/pkg/urbit/tests/hashtable_tests.c @@ -9,7 +9,7 @@ c3_w _ch_skip_slot(c3_w mug_w, c3_w lef_w); static void _setup(void) { - u3m_init(); + u3m_init(1 << 26); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/jam_tests.c b/pkg/urbit/tests/jam_tests.c index 55a83009b1..fd416945d6 100644 --- a/pkg/urbit/tests/jam_tests.c +++ b/pkg/urbit/tests/jam_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 24); u3m_pave(c3y); u3e_init(); } diff --git a/pkg/urbit/tests/jet_tests.c b/pkg/urbit/tests/jet_tests.c index 2e96f2305f..4904a959da 100644 --- a/pkg/urbit/tests/jet_tests.c +++ b/pkg/urbit/tests/jet_tests.c @@ -5,7 +5,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/mug_tests.c b/pkg/urbit/tests/mug_tests.c index 7ac9783d26..ffd0516747 100644 --- a/pkg/urbit/tests/mug_tests.c +++ b/pkg/urbit/tests/mug_tests.c @@ -5,7 +5,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/newt_tests.c b/pkg/urbit/tests/newt_tests.c index 043151784b..6fdbdb759e 100644 --- a/pkg/urbit/tests/newt_tests.c +++ b/pkg/urbit/tests/newt_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/nock_tests.c b/pkg/urbit/tests/nock_tests.c index 19c7ef200d..a96ed09bd1 100644 --- a/pkg/urbit/tests/nock_tests.c +++ b/pkg/urbit/tests/nock_tests.c @@ -5,7 +5,10 @@ static void _setup(void) { - u3m_init(); + // XX at 1<<24, this succeeds on mac, but bail:exit's on linux. + // investigate possible u3n_prog corruption + // + u3m_init(1 << 25); u3m_pave(c3y); u3e_init(); } diff --git a/pkg/urbit/tests/noun_tests.c b/pkg/urbit/tests/noun_tests.c index b84b618652..af54cd2894 100644 --- a/pkg/urbit/tests/noun_tests.c +++ b/pkg/urbit/tests/noun_tests.c @@ -1,7 +1,4 @@ #include "all.h" -#include "ur/ur.h" -#include "vere/ivory.h" -#include "vere/vere.h" #define TRUE 1 #define FALSE 0 @@ -11,23 +8,358 @@ static void _setup(void) { - c3_d len_d = u3_Ivory_pill_len; - c3_y* byt_y = u3_Ivory_pill; - u3_cue_xeno* sil_u; - u3_weak pil; + u3m_init(1 << 20); + u3m_pave(c3y); +} - u3C.wag_w |= u3o_hashless; - u3m_boot_lite(); - sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); - if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { - printf("*** fail _setup 1\n"); - exit(1); +/* _test_u3r_chop: "extract bit slices from atom" +*/ +static c3_i +_test_u3r_chop() +{ + c3_i ret_i = 1; + c3_w dst_w = 0; + u3_atom src = 0b11011; + + // bloq 0 + // + { + // read 1 bit from pos=0 (far right) + // + dst_w = 0; + u3r_chop(0, 0, 1, 0, &dst_w, src); + if ( 0x1 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 0, 0\r\n"); + ret_i = 0; + } + + // read 1 bit from pos=1 + // + dst_w = 0; + u3r_chop(0, 1, 1, 0, &dst_w, src); + if ( 0x1 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 0, 1\r\n"); + ret_i = 0; + } + + // read 1 bit from pos=2 + // + dst_w = 0; + u3r_chop(0, 2, 1, 0, &dst_w, src); + if ( 0x0 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 0, 2\r\n"); + ret_i = 0; + } + + // read 4 x 1 bit bloq from pos=0 + // + dst_w = 0; + u3r_chop(0, 0, 4, 0, &dst_w, src); + if ( 0b1011 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 0, 3\r\n"); + ret_i = 0; + } + + // read 4 x 1 bit bloq from pos=0 into offset 1 + // + dst_w = 0; + u3r_chop(0, 0, 4, 1, &dst_w, src); + if ( 0b10110 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 0, 4\r\n"); + ret_i = 0; + } } - u3s_cue_xeno_done(sil_u); - if ( c3n == u3v_boot_lite(pil) ) { - printf("*** fail _setup 2\n"); - exit(1); + + // bloq 1 + // + { + // read 2 bit from pos=0 (far right) + // + dst_w = 0; + u3r_chop(1, 0, 1, 0, &dst_w, src); + if ( 0b11 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 1, 0\r\n"); + ret_i = 0; + } + + // read 2 bit from pos=1 + // + dst_w = 0; + u3r_chop(1, 1, 1, 0, &dst_w, src); + if ( 0b10 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 1, 1\r\n"); + ret_i = 0; + } + + // read 2 bit from pos=2 (2 bloq over) + dst_w = 0; + u3r_chop(1, 2, 1, 0, &dst_w, src); + if ( 0b01 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 1, 2\r\n"); + ret_i = 0; + } } + + // bloq 3 + { + dst_w = 0; + u3r_chop(3, 0, 1, 0, &dst_w, src); + if ( 0b11011 != dst_w ) { + fprintf(stderr, "test: u3r_chop: bloq 3, 0\r\n"); + ret_i = 0; + } + } + + // read 1,8,16 bit bloqs from an indirect atom + // + { + src = u3i_string("abcdefghij"); + + // 1 bit pos=0 (far right) + // + dst_w = 0; + u3r_chop(0, 0, 1, 0, &dst_w, src); + if ( 0b1 != dst_w ) { + fprintf(stderr, "test: u3r_chop: indirect 0\r\n"); + ret_i = 0; + } + + // 8 bits pos=0 + // + dst_w = 0; + u3r_chop(0, 0, 8, 0, &dst_w, src); + if ( 0b1100001 != dst_w ) { + fprintf(stderr, "test: u3r_chop: indirect 1\r\n"); + ret_i = 0; + } + + // 1 byte pos=0 + // + dst_w = 0; + u3r_chop(3, 0, 1, 0, &dst_w, src); + if ( 0b1100001 != dst_w ) { + fprintf(stderr, "test: u3r_chop: indirect 2\r\n"); + ret_i = 0; + } + + // 1 short pos=0 + // + dst_w = 0; + u3r_chop(4, 0, 1, 0, &dst_w, src); + if ( 0b0110001001100001 != dst_w ) { + fprintf(stderr, "test: u3r_chop: indirect 3\r\n"); + ret_i = 0; + } + + u3z(src); + } + + // read lots of bits from a direct noun which holds 64 bits of data + // makes sure that we handle top 32 / bottom 32 correctly + { + c3_y inp_y[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }; + src = u3i_bytes(8, inp_y); + + c3_w dst_w[2] = {0}; + u3r_chop(0, 0, 63, 0, dst_w, src); + if ( (0x3020100 != dst_w[0]) || (0x7060504 != dst_w[1]) ) { + fprintf(stderr, "test: u3r_chop: indirect 4\r\n"); + ret_i = 0; + } + + u3z(src); + } + + // as above (read lots of bits from a direct noun which holds 64 bits of data + // makes sure that we handle top 32 / bottom 32 correctly) + // but with a bit more nuance + { + c3_y inp_y[8] = { 0x0, 0x0, 0x0, 0xaa, 0xff, 0x0, 0x0, 0x0 }; + src = u3i_bytes(8, (c3_y*)inp_y); + + dst_w = 0; + u3r_chop(0, 24, 16, 0, &dst_w, src); + if ( 0b1111111110101010 != dst_w ) { + fprintf(stderr, "test: u3r_chop: indirect 5\r\n"); + ret_i = 0; + } + + u3z(src); + } + + return ret_i; +} + +/* _test_chop_slow(): "golden master" for chop tests (formerly u3r_chop()) +*/ +void +_test_chop_slow(c3_g met_g, + c3_w fum_w, + c3_w wid_w, + c3_w tou_w, + c3_w* dst_w, + c3_w len_w, + c3_w* buf_w) +{ + c3_w i_w; + + if ( met_g < 5 ) { + c3_w san_w = (1 << met_g); + c3_w mek_w = ((1 << san_w) - 1); + c3_w baf_w = (fum_w << met_g); + c3_w bat_w = (tou_w << met_g); + + // XX: efficiency: poor. Iterate by words. + // + for ( i_w = 0; i_w < wid_w; i_w++ ) { + c3_w waf_w = (baf_w >> 5); + c3_g raf_g = (baf_w & 31); + c3_w wat_w = (bat_w >> 5); + c3_g rat_g = (bat_w & 31); + c3_w hop_w; + + hop_w = (waf_w >= len_w) ? 0 : buf_w[waf_w]; + hop_w = (hop_w >> raf_g) & mek_w; + + dst_w[wat_w] ^= (hop_w << rat_g); + + baf_w += san_w; + bat_w += san_w; + } + } + else { + c3_g hut_g = (met_g - 5); + c3_w san_w = (1 << hut_g); + c3_w j_w; + + for ( i_w = 0; i_w < wid_w; i_w++ ) { + c3_w wuf_w = (fum_w + i_w) << hut_g; + c3_w wut_w = (tou_w + i_w) << hut_g; + + for ( j_w = 0; j_w < san_w; j_w++ ) { + dst_w[wut_w + j_w] ^= + ((wuf_w + j_w) >= len_w) + ? 0 + : buf_w[wuf_w + j_w]; + } + } + } +} + +/* _test_chop_smol(): test permuations of chop from bloq 0-4 +*/ +static c3_i +_test_chop_smol(c3_c* cap_c, c3_y val_y) +{ + c3_i ret_i = 1; + c3_g met_g; + c3_w fum_w, wid_w, tou_w; + c3_w len_w = 34; // (rsh [0 5] (mul 2 (mul 34 (bex 4)))) + c3_w src_w[len_w]; + c3_w a_w[len_w]; + c3_w b_w[len_w]; + + memset(src_w, val_y, len_w << 2); + + for ( met_g = 0; met_g < 5; met_g++ ) { + for ( fum_w = 0; fum_w <= len_w; fum_w++ ) { + for ( wid_w = 0; wid_w <= len_w; wid_w++ ) { + for ( tou_w = 0; tou_w <= len_w; tou_w++ ) { + memset(a_w, 0, len_w << 2); + memset(b_w, 0, len_w << 2); + u3r_chop_words(met_g, fum_w, wid_w, tou_w, a_w, len_w, src_w); + _test_chop_slow(met_g, fum_w, wid_w, tou_w, b_w, len_w, src_w); + + if ( 0 != memcmp(a_w, b_w, len_w << 2) ) { + c3_g sif_g = 5 - met_g; + c3_w mas_w = (1 << met_g) - 1; + c3_w out_w = tou_w >> sif_g; + c3_w max_w = out_w + !!(fum_w & mas_w) + + (wid_w >> sif_g) + !!(wid_w & mas_w); + + fprintf(stderr, "%s (0x%x): met_g=%u fum_w=%u wid_w=%u tou_w=%u\r\n", + cap_c, val_y, + met_g, fum_w, wid_w, tou_w); + + + fprintf(stderr, "%u-%u: ", out_w, max_w - 1); + for ( ; out_w < max_w; out_w++ ) { + fprintf(stderr, "[0x%x 0x%x] ", a_w[out_w], b_w[out_w]); + } + fprintf(stderr, "\r\n"); + } + } + } + } + } + + return ret_i; +} + +/* _test_chop_huge(): test permuations of chop from bloq 5+ +*/ +static c3_i +_test_chop_huge(c3_c* cap_c, c3_y val_y) +{ + c3_i ret_i = 1; + c3_g met_g; + c3_w fum_w, wid_w, tou_w; + c3_w len_w = 192; // (rsh [0 5] (mul 2 (mul 3 (bex 10)))) + c3_w src_w[len_w]; + c3_w a_w[len_w]; + c3_w b_w[len_w]; + + memset(src_w, val_y, len_w << 2); + + for ( met_g = 5; met_g <= 10; met_g++ ) { + for ( fum_w = 0; fum_w <= 3; fum_w++ ) { + for ( wid_w = 0; wid_w <= 2; wid_w++ ) { + for ( tou_w = 0; tou_w <= 1; tou_w++ ) { + memset(a_w, 0, len_w << 2); + memset(b_w, 0, len_w << 2); + u3r_chop_words(met_g, fum_w, wid_w, tou_w, a_w, len_w, src_w); + _test_chop_slow(met_g, fum_w, wid_w, tou_w, b_w, len_w, src_w); + + if ( 0 != memcmp(a_w, b_w, len_w << 2) ) { + c3_g sif_g = met_g - 5; + c3_w mas_w = (1 << met_g) - 1; + c3_w out_w = tou_w << sif_g; + c3_w max_w = out_w + !!(fum_w & mas_w) + + (wid_w << sif_g) + !!(wid_w & mas_w); + + fprintf(stderr, "%s (0x%x): met_g=%u fum_w=%u wid_w=%u tou_w=%u\r\n", + cap_c, val_y, + met_g, fum_w, wid_w, tou_w); + + + fprintf(stderr, "%u-%u: ", out_w, max_w - 1); + for ( ; out_w < max_w; out_w++ ) { + fprintf(stderr, "[0x%x 0x%x] ", a_w[out_w], b_w[out_w]); + } + fprintf(stderr, "\r\n"); + } + } + } + } + } + + return ret_i; +} + +/* _test_u3r_chop(): bit slice XOR +*/ +static c3_i +_test_chop() +{ + return _test_u3r_chop() + & _test_chop_smol("chop smol zeros", 0x0) + & _test_chop_smol("chop smol ones", 0xff) + & _test_chop_smol("chop smol alt 1", 0xaa) + & _test_chop_smol("chop smol alt 2", 0x55) + & _test_chop_huge("chop huge zeros", 0x0) + & _test_chop_huge("chop huge ones", 0xff) + & _test_chop_huge("chop huge alt 1", 0xaa) + & _test_chop_huge("chop huge alt 2", 0x55); } /* _util_rand_string(): dynamically allocated len_w random string @@ -1265,256 +1597,6 @@ _test_u3r_at() if (bignum != ret) { printf("*** u3r_at \n"); } } -/* _test_u3r_chop: "extract bit slices from atom" -*/ -static void -_test_u3r_chop() -{ - c3_w dst_w = 0; - - // read 1 bit bloq - { - // read 1 bit from pos=0 (far right) - u3_atom src = 0b11011; - - c3_g bloqsize_g = 0; - - - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0x1 != dst_w) { printf("*** test_u3r_chop \n"); } - - - // read 1 bit from pos=1 - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 1, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0x1 != dst_w) { printf("*** test_u3r_chop 2\n"); } - - // read 1 bit from pos=2 - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 2, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0x0 != dst_w) { printf("*** test_u3r_chop 3\n"); } - - // read 4 x 1 bit bloq from pos=0 - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 4, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b1011 != dst_w) { printf("*** test_u3r_chop 4\n"); } - - - // read 1 x 1 bit bloq from pos=0 into offset 1 - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 4, // count of bloqs - 1, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b10110 != dst_w) { printf("*** test_u3r_chop 5\n"); } - - - - } - - // read 2 bit bloq - { - u3_atom src = 0b11011; - - c3_g bloqsize_g = 1; - - // read 2 bit from pos=0 (far right) - - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b11 != dst_w) { printf("*** test_u3r_chop 2.1\n"); } - - - // read 2 bit from pos=1 (1 bloq over ) - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 1, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b10 != dst_w) { printf("*** test_u3r_chop 2.2\n"); } - - // read 2 bit from pos=2 (2 bloq over) - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 2, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b01 != dst_w) { printf("*** test_u3r_chop 2.3\n"); } - - } - - // read 8 bit bloq - { - u3_atom src = 0b11011; - - c3_g bloqsize_g = 3; // 2^3 = 8 bits - - // pos=0 (far right) - - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b11011 != dst_w) { printf("*** test_u3r_chop 8.1\n"); } - } - - // read 1,8,16 bit bloqs from an indirect atom - { - // build an indirect noun 'src' - - c3_c* input_c = "abcdefghij"; - u3_noun src = u3i_bytes(10, (c3_y*)input_c); - - - c3_g bloqsize_g = 0; // 2^0 = 1 bit - - // 1 x 1 bit pos=0 (far right) - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b1 != dst_w) { - printf("*** test_u3r_chop indirect.1\n"); - } - - // 8 x 1 bit pos=0 (far right) - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 8, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b1100001 != dst_w) { - printf("*** test_u3r_chop indirect.2\n"); - } - - // 1 x 1 byte = 8 bit, pos=0 (far right) - bloqsize_g = 3; // 2^3 = 1 byte - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b1100001 != dst_w) { - printf("*** test_u3r_chop indirect.3\n"); - } - - // 1 x 16 bit bloq, pos = 0 - bloqsize_g = 4; // 2^4 = 2 bytes - - dst_w = 0; - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 1, // count of bloqs - 0, // end index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b0110001001100001 != dst_w) { - printf("*** test_u3r_chop indirect.4\n"); - } - } - - // read lots of bits from a direct noun which holds 64 bits of data - // makes sure that we handle top 32 / bottom 32 correctly - { - // build an indirect noun 'src' - - c3_c input_c[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }; - u3_noun src = u3i_bytes(8, (c3_y*)input_c); - - c3_g bloqsize_g = 0; // 2^0 = 1 bit - - c3_w dst_w[2]; - memset(dst_w, 0, 2 * sizeof(c3_w)); - - u3r_chop(bloqsize_g, /// bloq size - 0, // start index - 63, // count of bloqs - 0, // offset on out index - dst_w, // where bytes go to - src); // where bytes come from - - } - - // as above (read lots of bits from a direct noun which holds 64 bits of data - // makes sure that we handle top 32 / bottom 32 correctly) - // but with a bit more nuance - { - // least significant most - c3_c input_c[8] = { 0x0, 0x0, 0x0, 0xaa, 0xff, 0x0, 0x0, 0x0 }; - u3_noun src = u3i_bytes(8, (c3_y*)input_c); - - c3_g bloqsize_g = 0; // 2^0 = 1 bit - - c3_w dst_w = 0; - - u3r_chop(bloqsize_g, /// bloq size - 24, // start index - 16, // count of bloqs - 0, // offset on out index - & dst_w, // where bytes go to - src); // where bytes come from - - if (0b1111111110101010 != dst_w) { - printf("*** test_u3r_chop indirect. 6\n"); - } - } -} - // XX disabled, static functions // #if 0 @@ -1652,31 +1734,17 @@ _test_nvm_stack() #endif } -/* _test_lily(): test small noun parsing. -*/ -static void -_test_lily() +static c3_i +_test_noun(void) { - c3_l lit_l; - c3_w big_w[] = {0, 0, 1}; - u3_noun big = u3i_words(3, big_w); - u3_noun cod = u3dc("scot", c3__uv, big); + c3_i ret_i = 1; - if ( c3y == u3v_lily(c3__uv, cod, &lit_l) ) { - printf("*** fail _test_lily-1\n"); - exit(1); - } - cod = u3dc("scot", c3__ud, 0x7fffffff); - if ( (c3n == u3v_lily(c3__ud, cod, &lit_l)) || - (0x7fffffff != lit_l) ) { - printf("*** fail _test_lily-2a\n"); - exit(1); - } - cod = u3dc("scot", c3__ux, u3i_word(0x80000000)); - if ( c3y == u3v_lily(c3__ux, cod, &lit_l) ) { - printf("*** fail _test_lily-2b\n"); - exit(1); + if ( !_test_chop() ) { + fprintf(stderr, "test noun: chop failed\r\n"); + ret_i = 0; } + + return ret_i; } /* main(): run all test cases. @@ -1686,9 +1754,20 @@ main(int argc, char* argv[]) { _setup(); + if ( !_test_noun() ) { + fprintf(stderr, "test noun: failed\r\n"); + exit(1); + } + + // GC + // + u3m_grab(u3_none); + + // XX the following tests leak memory + // fix and move to _test_noun() + // _test_noun_bits_set(); _test_noun_bits_read(); - _test_u3r_chop(); _test_imprison(); _test_imprison_complex(); _test_sing(); @@ -1698,7 +1777,6 @@ main(int argc, char* argv[]) _test_cells_complex(); _test_u3r_at(); _test_nvm_stack(); - _test_lily(); fprintf(stderr, "test_noun: ok\n"); diff --git a/pkg/urbit/ur/bitstream.c b/pkg/urbit/ur/bitstream.c index dfc42393b7..5d69e3f9e7 100644 --- a/pkg/urbit/ur/bitstream.c +++ b/pkg/urbit/ur/bitstream.c @@ -411,25 +411,21 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out) // else { uint8_t rest = 8 - off; - uint8_t mask = (1 << off) - 1; - uint8_t byt, l, m = *b >> off; uint64_t last = left - 1; + uint64_t max = ur_min(last, len_byt); + uint8_t m, l; // loop over all the bytes we need (or all that remain) // - // [l] holds [off] bits - // [m] holds [rest] bits - // { - uint64_t max = ur_min(last, len_byt); uint64_t i; for ( i = 0; i < max; i++ ) { - byt = *++b; - l = byt & mask; - out[i] = m ^ (l << rest); - m = byt >> off; + out[i] = (b[i] >> off) ^ (b[i + 1] << rest); } + + b += max; + m = *b >> off; } // we're reading into or beyond the last byte [bsr] @@ -441,13 +437,13 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out) uint8_t bits = len - (last << 3); if ( bits < rest ) { - out[last] = m & ((1 << bits) - 1); + out[max] = m & ((1 << len_bit) - 1); bsr->bytes = b; left = 1; off += len_bit; } else { - out[last] = m; + out[max] = m; bsr->bytes = 0; left = 0; off = 0; @@ -465,11 +461,11 @@ ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out) if ( len_bit ) { if ( len_bit <= rest ) { - out[len_byt] = m & ((1 << len_bit) - 1); + out[max] = m & ((1 << len_bit) - 1); } else { l = *++b & ((1 << off) - 1); - out[len_byt] = m ^ (l << rest); + out[max] = (m ^ (l << rest)) & ((1 << len_bit) - 1); } } } @@ -1035,67 +1031,60 @@ ur_bsw64(ur_bsw_t *bsw, uint8_t len, uint64_t val) } static inline void -_bsw_bytes_unsafe(ur_bsw_t *bsw, uint64_t len, uint8_t *byt) +_bsw_bytes_unsafe(ur_bsw_t *bsw, const uint64_t len, const uint8_t* src) { - uint64_t len_byt = len >> 3; - uint8_t len_bit = ur_mask_3(len); - uint64_t fill = bsw->fill; - uint8_t off = bsw->off; + uint64_t fill = bsw->fill; + uint8_t off = bsw->off; + uint8_t *dst = bsw->bytes + fill; if ( !off ) { - memcpy(bsw->bytes + fill, byt, len_byt); - fill += len_byt; - off = len_bit; + const uint64_t len_byt = len >> 3; + const uint8_t len_bit = ur_mask_3(len); - if ( off ) { - bsw->bytes[fill] = byt[len_byt] & ((1 << off) - 1); + memcpy(dst, src, len_byt); + bsw->fill = fill + len_byt; + + if ( len_bit ) { + dst[len_byt] = src[len_byt] & ((1 << len_bit) - 1); + bsw->off = len_bit; } } - // the least-significant bits of the input become the - // most-significant bits of a byte in the output stream, and vice-versa - // - else { - uint8_t rest = 8 - off; - uint8_t mask = (1 << rest) - 1; - uint8_t l, m = bsw->bytes[fill]; - uint64_t i; + else { + const uint8_t rest = 8 - off; - for ( i = 0; i < len_byt; i++ ) { - l = byt[i] & mask; - bsw->bytes[fill++] = m ^ (l << off); - m = byt[i] >> rest; - } + if ( rest >= len ) { + uint16_t ful = off + len; - // no trailing bits; we need only write the rest of the last byte. - // - // NB: while semantically equivalent to the subsequent block, - // this case must be separate to avoid reading off the end of [byt] - // - if ( !len_bit ) { - bsw->bytes[fill] = m; + *dst ^= (*src & ((1 << len) - 1)) << off; + + if ( ful >> 3 ) { + bsw->fill = fill + 1; + } + + bsw->off = ur_mask_3(ful); } - // trailing bits fit into the current output byte. - // - else if ( len_bit < rest ) { - l = byt[len_byt] & ((1 << len_bit) - 1); - bsw->bytes[fill] = m ^ (l << off); - off += len_bit; - } - // trailing bits extend into the next output byte. - // else { - l = byt[len_byt] & mask; - bsw->bytes[fill++] = m ^ (l << off); + const uint64_t nel = len - rest; + const uint64_t len_byt = nel >> 3; + const uint8_t len_bit = ur_mask_3(nel); - m = byt[len_byt] >> rest; + *dst++ ^= *src << off; - off = len_bit - rest; - bsw->bytes[fill] = m & ((1 << off) - 1); + for ( uint64_t i = 0; i < len_byt; i++ ) { + dst[i] = (src[i] >> rest) ^ (src[i + 1] << off); + } + + { + uint8_t tal = (src[len_byt] >> rest) + ^ (( off > len_bit ) ? 0 : (src[len_byt + 1] << off)); + dst[len_byt] = tal & ((1 << len_bit) - 1); + } + + bsw->fill = fill + len_byt + 1; + bsw->off = len_bit; } } - bsw->off = off; - bsw->fill = fill; bsw->bits += len; } diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index 730d5da82b..eb4a275339 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -617,7 +617,15 @@ u3_disk_acquire(c3_c* pax_c) else if (pid_w != getpid()) { c3_w i_w; - if ( -1 != kill(pid_w, SIGTERM) ) { + int ret = kill(pid_w, SIGTERM); + + if ( -1 == ret && errno == EPERM ) { + u3l_log("disk: permission denied when trying to kill process %d!\n", pid_w); + kill(getpid(), SIGTERM); + sleep(1); c3_assert(0); + } + + if ( -1 != ret ) { u3l_log("disk: stopping process %d, live in %s...\n", pid_w, pax_c); diff --git a/pkg/urbit/vere/lord.c b/pkg/urbit/vere/lord.c index cc7af14f6b..2051908485 100644 --- a/pkg/urbit/vere/lord.c +++ b/pkg/urbit/vere/lord.c @@ -1157,11 +1157,12 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) // spawn new process and connect to it // { - c3_c* arg_c[8]; + c3_c* arg_c[10]; c3_c key_c[256]; c3_c wag_c[11]; c3_c hap_c[11]; c3_c cev_c[11]; + c3_c lom_c[11]; c3_i err_i; sprintf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64 "", @@ -1174,30 +1175,34 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) sprintf(hap_c, "%u", u3_Host.ops_u.hap_w); + sprintf(lom_c, "%u", u3_Host.ops_u.lom_y); + arg_c[0] = god_u->bin_c; // executable arg_c[1] = "serf"; // protocol arg_c[2] = god_u->pax_c; // path to checkpoint directory arg_c[3] = key_c; // disk key arg_c[4] = wag_c; // runtime config arg_c[5] = hap_c; // hash table size + arg_c[6] = lom_c; // loom bex if ( u3_Host.ops_u.roc_c ) { // XX validate // - arg_c[6] = u3_Host.ops_u.roc_c; + arg_c[7] = u3_Host.ops_u.roc_c; } else { - arg_c[6] = "0"; + arg_c[7] = "0"; } #ifdef U3_OS_mingw sprintf(cev_c, "%" PRIu64, u3_Host.cev_u); - arg_c[7] = cev_c; - arg_c[8] = 0; + arg_c[8] = cev_c; #else - arg_c[7] = 0; + arg_c[8] = 0; #endif + arg_c[9] = 0; + uv_pipe_init(u3L, &god_u->inn_u.pyp_u, 0); uv_timer_init(u3L, &god_u->out_u.tim_u); uv_pipe_init(u3L, &god_u->out_u.pyp_u, 0); diff --git a/pkg/urbit/version b/pkg/urbit/version index 35d51f33b3..9f76d37b71 100644 --- a/pkg/urbit/version +++ b/pkg/urbit/version @@ -1 +1 @@ -1.12 \ No newline at end of file +1.13 \ No newline at end of file