diff --git a/g/a.c b/g/a.c index c7f7e587aa..fc1ccd281d 100644 --- a/g/a.c +++ b/g/a.c @@ -54,7 +54,7 @@ _box_attach(u3_cs_box* box_u) { c3_assert(box_u->siz_w >= (1 + c3_wiseof(u3_cs_fbox))); - u3R->fre_w += box_u->siz_w; + u3R->all.fre_w += box_u->siz_w; { c3_w sel_w = _box_slot(box_u->siz_w); u3_cs_fbox* fre_u = (void *)box_u; @@ -79,7 +79,7 @@ _box_detach(u3_cs_box* box_u) u3_cs_fbox* pre_u = fre_u->pre_u; u3_cs_fbox* nex_u = fre_u->nex_u; - u3R->fre_w -= box_u->siz_w; + u3R->all.fre_w -= box_u->siz_w; if ( nex_u ) { c3_assert(nex_u->pre_u == fre_u); @@ -97,7 +97,7 @@ _box_detach(u3_cs_box* box_u) } } -/* _me_road_all_hat(): in u3R, allocate directly on the hat_w. +/* _me_road_all_hat(): in u3R, allocate directly on the hat. */ static c3_w* _me_road_all_hat(c3_w len_w) @@ -652,10 +652,10 @@ _me_copy_south(u3_noun dog) } } -/* _me_gain_north(): gain on a north road. +/* _me_take_north(): take on a north road. */ static u3_noun -_me_gain_north(u3_noun dog) +_me_take_north(u3_noun dog) { if ( u3_yes == u3_co_north_is_senior(dog) ) { /* senior pointers are not refcounted @@ -678,10 +678,32 @@ _me_gain_north(u3_noun dog) } } -/* _me_gain_south(): gain on a south road. +/* _me_gain_north(): gain on a north road. */ static u3_noun -_me_gain_south(u3_noun dog) +_me_gain_north(u3_noun dog) +{ + if ( u3_yes == u3_co_north_is_senior(dog) ) { + /* senior pointers are not refcounted + */ + return dog; + } + else { + /* junior nouns are disallowed + */ + c3_assert(u3_ne(u3_co_north_is_junior(dog))); + + /* normal pointers are refcounted + */ + _me_gain_use(dog); + return dog; + } +} + +/* _me_take_south(): take on a south road. +*/ +static u3_noun +_me_take_south(u3_noun dog) { if ( u3_yes == u3_co_south_is_senior(dog) ) { /* senior pointers are not refcounted @@ -704,6 +726,28 @@ _me_gain_south(u3_noun dog) } } +/* _me_gain_south(): gain on a south road. +*/ +static u3_noun +_me_gain_south(u3_noun dog) +{ + if ( u3_yes == u3_co_south_is_senior(dog) ) { + /* senior pointers are not refcounted + */ + return dog; + } + else { + /* junior nouns are disallowed + */ + c3_assert(u3_ne(u3_co_south_is_junior(dog))); + + /* normal nouns are refcounted + */ + _me_gain_use(dog); + return dog; + } +} + /* _me_lose_north(): lose on a north road. */ static void @@ -784,7 +828,24 @@ top: } } -/* u3_ca_gain(): gain a reference count, and/or copy juniors. +/* u3_ca_take(): gain, copying juniors. +*/ +u3_noun +u3_ca_take(u3_noun som) +{ + c3_assert(u3_none != som); + + if ( u3_so(u3_co_is_cat(som)) ) { + return som; + } + else { + return u3_so(u3_co_is_north) + ? _me_take_north(som) + : _me_take_south(som); + } +} + +/* u3_ca_gain(): gain a reference count in normal space. */ u3_noun u3_ca_gain(u3_noun som) diff --git a/g/m.c b/g/m.c index 8ddbe7e784..214d63d55b 100644 --- a/g/m.c +++ b/g/m.c @@ -49,6 +49,7 @@ _find_north(c3_w* mem_w, c3_w siz_w, c3_w len_w) return (void *) ((mem_w + len_w) - siz_w); } +#if 0 /* _find_south(): in restored image, point to a south home. */ static u3_road* @@ -56,6 +57,7 @@ _find_south(c3_w* mem_w, c3_w siz_w, c3_w len_w) { return (void *)(mem_w + siz_w); } +#endif static u3_road* _boot_north(c3_w* mem_w, c3_w siz_w, c3_w len_w) @@ -174,6 +176,7 @@ u3_cm_dump(void) } } +#if 0 /* _cm_punt(): crudely print trace. */ static void @@ -185,6 +188,7 @@ _cm_punt(void) u3_cm_p("&", u3h(xat)); } } +#endif /* u3_cm_bail(): bail out. Does not return. ** @@ -207,7 +211,7 @@ _cm_punt(void) ** == */ c3_i -u3_cm_bail(u2_noun how) +u3_cm_bail(u3_noun how) { /* Printf some metadata. */ @@ -215,10 +219,10 @@ u3_cm_bail(u2_noun how) if ( u3_so(u3ud(how)) ) { c3_c str_c[5]; - str_c[0] = ((how_m >> 0) & 0xff); - str_c[1] = ((how_m >> 8) & 0xff); - str_c[2] = ((how_m >> 16) & 0xff); - str_c[3] = ((how_m >> 24) & 0xff); + 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; printf("bail: %s (at %llu)\r\n", str_c, u3N); } @@ -251,7 +255,7 @@ u3_cm_bail(u2_noun how) /* Longjmp, with an underscore. */ - _longjmp(u3R->esc.buf, how_m); + _longjmp(u3R->esc.buf, how); return 0; } @@ -269,27 +273,68 @@ u3_cm_error(c3_c* str_c) /* u3_cm_leap(): in u3R, create a new road within the existing one. */ void -u3_cm_leap() +u3_cm_leap(c3_w pad_w) { + c3_w len_w; u3_road* rod_u; - if ( u3_yes == u3_co_is_north ) { - rod_u = _boot_south(u3R->hat_w, - c3_wiseof(u3_cs_road), - (u3R->cap_w - u3R->hat_w)); - } - else { - rod_u = _boot_north(u3R->cap_w, - c3_wiseof(u3_cs_road), - (u3R->hat_w - u3R->cap_w)); + /* Measure the pad - we'll need it. + */ + { + if ( pad_w < u3R->all.fre_w ) { + pad_w = 0; + } + else { + pad_w -= u3R->all.fre_w; + } + if ( (pad_w + c3_wiseof(u3_cs_road)) <= u3_co_open ) { + u3_cm_bail(c3__meme); + } + len_w = u3_co_open - (pad_w + c3_wiseof(u3_cs_road)); } - c3_assert(0 == u3R->kid_u); - rod_u->par_u = u3R; - u3R->kid_u = rod_u; + /* Allocate a region on the cap. + */ + { + c3_w* bot_w; - u3R = rod_u; - _boot_parts(); + if ( u3_yes == u3_co_is_north ) { + bot_w = (u3R->cap_w - len_w); + u3R->cap_w -= len_w; + + rod_u = _boot_south(bot_w, c3_wiseof(u3_cs_road), len_w); + printf("leap: from north %p (cap %p), to south %p\r\n", + u3R, + u3R->cap_w + len_w, + rod_u); + } + else { + bot_w = u3R->cap_w; + u3R->cap_w += len_w; + + rod_u = _boot_north(bot_w, c3_wiseof(u3_cs_road), len_w); + + printf("leap: from north %p (cap %p), to south %p\r\n", + u3R, + u3R->cap_w - len_w, + rod_u); + } + } + + /* Attach the new road to its parents. + */ + { + c3_assert(0 == u3R->kid_u); + rod_u->par_u = u3R; + u3R->kid_u = rod_u; + } + + /* Set up the new road. + */ + { + u3R = rod_u; + _boot_parts(); + } } /* u3_cm_fall(): in u3R, return an inner road to its parent. @@ -299,8 +344,22 @@ u3_cm_fall() { c3_assert(0 != u3R->par_u); + printf("leap: from %s %p, to %s %p (cap %p, was %p)\r\n", + u3_so(u3_co_is_north) ? "north" : "south", + u3R, + u3_so(u3_co_is_north) ? "north" : "south", + u3R->par_u, + u3R->hat_w, + u3R->rut_w); + + /* The new cap is the old hat - it's as simple as that. + */ u3R->par_u->cap_w = u3R->hat_w; + + /* And, we're back home. + */ u3R = u3R->par_u; + u3R->kid_u = 0; } /* u3_cm_golf(): record cap_w length for u3_flog(). @@ -339,7 +398,7 @@ u3_cm_water(c3_w* low_w, c3_w* hig_w) *hig_w = (u3H->rod_u.mat_w - u3H->rod_u.cap_w) + c3_wiseof(u3_cs_home); } -/* u3_cm_soft_top(): top-level wrapper. +/* u3_cm_soft_top(): top-level safety wrapper. */ u3_noun u3_cm_soft_top(c3_w pad_w, @@ -387,7 +446,7 @@ u3_cm_soft_top(c3_w pad_w, /* Produce success, on the old road. */ - pro = u3nc(0, u3k(pro)); + pro = u3nc(0, u3_ca_take(pro)); } else { /* Test stack correctness assertions, and restore. @@ -405,11 +464,11 @@ u3_cm_soft_top(c3_w pad_w, /* Produce the error result. */ - pro = u3k(why); + pro = u3_ca_take(why); } /* Clean up temporary memory. */ - u3_cm_golf(gof_w); + u3_cm_flog(gof_w); /* Return the product. */ @@ -424,20 +483,9 @@ u3_cm_soft_run(u3_noun fly, u3_noun aga, u3_noun agb) { - u3_noun why, don, flu, tax, pro; + u3_noun why, pro; c3_w gof_w; - /* Record all stacks; clear the trace; push the fly. - */ - { - don = u3R->pro.don; - flu = u3R->ski.flu; - tax = u3R->bug.tax; - - u3R->bug.tax = 0; - u3R->ski.flu = u3nc(fly, u3k(flu)); - } - /* Record the cap, and leap. */ { @@ -445,43 +493,28 @@ u3_cm_soft_run(u3_noun fly, u3_cm_leap(32768); } + /* Configure the new road. + */ + { + u3R->ski.flu = u3nc(fly, u3R->par_u->ski.flu); + u3R->pro.don = u3R->par_u->pro.don; + u3R->bug.tax = 0; + } + /* Trap for exceptions. */ if ( 0 == (why = u3_cm_trap()) ) { u3_noun pro = fun_f(aga, agb); - /* Test stack correctness assertions, and restore. - */ - { - c3_assert(0 == u3R->bug.tax); // trace is clean - c3_assert(flu == u3t(u3R->ski.flu)); // namespaces are clean - c3_assert(don == u3R->pro.don); // profile is clean - - u3R->bug.tax = tax; // restore trace - u3z(u3R->ski.flu); // free namespace stack - u3R->ski.flu = flu; // reset namespaces - } - /* Fall back to the old road, leaving temporary memory intact. */ u3_cm_fall(); /* Produce success, on the old road. */ - pro = u3nc(0, u3k(pro)); + pro = u3nc(0, u3_ca_take(pro)); } else { - /* Test stack correctness assertions, and restore. - */ - { - c3_assert(flu == u3t(u3R->ski.flu)); // namespaces are clean - - u3R->pro.don = don; // restore profile - u3R->bug.tax = tax; // restore trace - u3z(u3R->ski.flu); // free namespace stack - u3R->ski.flu = flu; // reset namespaces - } - /* Fall back to the old road, leaving temporary memory intact. */ u3_cm_fall(); @@ -494,57 +527,62 @@ u3_cm_soft_run(u3_noun fly, default: c3_assert(0); return 0; case 0: { // unusual: bail with success. - pro = u3k(why); + pro = u3_ca_take(why); } break; case 1: { // blocking request - pro = u3k(why); + pro = u3_ca_take(why); } break; case 2: { // true exit - pro = u3k(why); + pro = u3_ca_take(why); } break; - case 3: { // super-exit; rebail + case 3: { // failure; rebail w/trace u3_cm_bail (u3nt(3, - u3h(u3t(why)), - u3_ckb_weld(u3t(u3t(why)), u3k(tax))); + u3_ca_take(u3h(u3t(why))), + u3_ckb_weld(u3_ca_take(u3t(u3t(why))), + u3k(u3R->bug.tax)))); } break; case 4: { // meta-bail - u3_cm_bail(u3t(why)); + u3_cm_bail(u3_ca_take(u3t(why))); } break; } } } + /* Clean up temporary memory. */ - u3_cm_golf(gof_w); + u3_cm_flog(gof_w); + + /* Release the arguments. + */ + { + u3z(fly); + u3z(aga); + u3z(agb); + } /* Return the product. */ return pro; } -/* u3_cm_nock_soft_esc(): compute with fly. +/* u3_cm_soft_esc(): namespace lookup. Produces direct result. */ u3_noun -u3_cm_nock_soft_esc(u3_noun sam) +u3_cm_soft_esc(u3_noun sam) { - u3_noun why, don, flu, tax, pro; + u3_noun why, fly, pro; c3_w gof_w; - /* Record all stacks; clear the trace; pop the fly. + /* Assert preconditions. */ - c3_assert(0 != u3R->ski.flu); { - don = u3R->pro.don; - flu = u3R->ski.flu; - tax = u3R->bug.tax; - - u3R->bug.tax = 0; - u3R->ski.flu = u3k(u3t(flu)); + c3_assert(0 != u3R->ski.flu); + fly = u3h(u3R->ski.flu); } /* Record the cap, and leap. @@ -554,22 +592,18 @@ u3_cm_nock_soft_esc(u3_noun sam) u3_cm_leap(32768); } + /* Configure the new road. + */ + { + u3R->ski.flu = u3t(u3R->par_u->ski.flu); + u3R->pro.don = u3R->par_u->pro.don; + u3R->bug.tax = 0; + } + /* Trap for exceptions. */ if ( 0 == (why = u3_cm_trap()) ) { - u3_noun pro = fun_f(aga, agb); - - /* Test stack correctness assertions, and restore. - */ - { - c3_assert(0 == u3R->bug.tax); // trace is clean - c3_assert(u3t(flu) == u3R->ski.flu); // namespaces are clean - c3_assert(don == u3R->pro.don); // profile is clean - - u3R->bug.tax = tax; // restore trace - u3z(u3R->ski.flu); // free namespace stack - u3R->ski.flu = flu; // reset namespaces - } + pro = u3_cn_slam_on(fly, sam); /* Fall back to the old road, leaving temporary memory intact. */ @@ -577,39 +611,51 @@ u3_cm_nock_soft_esc(u3_noun sam) /* Produce success, on the old road. */ - pro = u3nc(0, u3k(pro)); + pro = u3_ca_take(pro); } else { - /* Test stack correctness assertions, and restore. - */ - { - c3_assert(flu == u3t(u3R->ski.flu)); // namespaces are clean - - u3R->pro.don = don; // restore profile - u3R->bug.tax = tax; // restore trace - u3z(u3R->ski.flu); // free namespace stack - u3R->ski.flu = flu; // reset namespaces - } - /* Fall back to the old road, leaving temporary memory intact. */ u3_cm_fall(); /* Push the error back up to the calling context - not the run we - ** are in, but the caller of the run. + ** are in, but the caller of the run, matching pure nock semantics. */ - return u3_cm_bail(u3nc(4, u3k(why))); + return u3_cm_bail(u3nc(4, u3_ca_take(why))); } /* Clean up temporary memory. */ - u3_cm_golf(gof_w); + u3_cm_flog(gof_w); + + /* Release the sample. + */ + u3z(sam); /* Return the product. */ return pro; } +/* u3_cm_soft(): wrapper for old calls. +*/ +u3_noun +u3_cm_soft(c3_w sec_w, + u3_funk fun_f, + u3_noun arg) +{ + u3_noun why = u3_cm_soft_top(0, fun_f, arg); + u3_noun pro; + + switch ( u3h(why) ) { + default: c3_assert(0); break; + case 0: pro = why; break; + case 2: pro = u3nc(c3__exit, u3k(u3t(why))); u3z(why); break; + case 3: pro = u3k(u3t(why)); u3z(why); break; + } + return pro; +} + /* _cm_is_tas(): yes iff som (RETAIN) is @tas. */ static c3_o diff --git a/g/n.c b/g/n.c index a7b5a21b00..d4b8c7f7d2 100644 --- a/g/n.c +++ b/g/n.c @@ -297,8 +297,22 @@ u3_cn_nock_on(u3_noun bus, u3_noun fol) } case 11: { - c3_assert(!"11 remains stubbed out"); - } + u3_noun gof = u3_cn_nock_on(bus, u3k(gal)); + u3_noun val = u3_cm_soft_esc(u3nc(u3k(gof), 0)); + + if ( u3_ne(u3du(val)) ) { + u3_cm_bail(u3nt(1, gof, 0)); + } + else { + u3_noun pro; + + u3z(fol); + pro = u3k(u3t(val)); + u3z(val); + + return pro; + } + } c3_assert(!"not reached"); } } @@ -323,78 +337,14 @@ u3_cn_slam_on(u3_noun gat, u3_noun sam) return u3_cn_kick_on(cor); } -/* u3_cn_nock_it_top(): full virtualization, no fly, set pad. -** -** Produces [0 result], [1 paths] == wait, [2 trace] == exit, -** or [term trace] for an internal error. -*/ -u3_noun -u3_cn_nock_it_flat(c3_w pad_w, - u3_noun bus, - u3_noun fol) -{ - c3_w gof_w; - c3_l why_l; - - gof_w = u3_cm_golf(); - u3_cm_leap(pad_w); - - if ( u3_blip != (why_l = u3_cm_trap()) ) { - /* Collect information to be preserved. - */ - if ( (why_l == c3__need) || (why_l == c3__exit) ) { - u3_noun ton; - - if ( 0 != u3R->net.nyd ) { - c3_assert(c3__need == why_l); - ton = u3nc(1, u3R->net.nyd); - } - } - u3_cm_fall(); - - /* Collect infora - if ( 0 != u3R->net.nyd ) { - c3_assert(c3__need == why_l); - } - } - else { - -} - /* u3_cn_nock_un(): produce .*(bus fol), as ++toon. */ u3_noun u3_cn_nock_un(u3_noun bus, u3_noun fol) { - u3_noun why_l; - c3_w gof_w; - u3_noun ton; + u3_noun fly = u3nt(u3nt(11, 0, 6), 0, 0); // |=(a=* .^(a)) - // u3_cm_leap(); - if ( u3_blip != (why_l = u3_cm_trap()) ) { - - u3_noun ton; - - if ( 0 != u3R->net.nyd ) { - ton = u3nc(1, u3R->net.nyd); - u3R->net.nyd = 0; - } - else { - ton = u3nc(2, u3R->bug.tax); - u3R->bug.tax = 0; - } - // u3_cm_fall(); - ton = u3_ca_gain(ton); - // u3_cm_flog(0); - } - else { - u3_noun pro = u3_cn_nock_on(bus, fol); - - // u3_cm_fall(); - ton = u3nc(0, u3_ca_gain(pro)); - } - // u3z(bus); u3z(fol); return ton; - return ton; + return u3_cn_nock_in(fly, bus, fol); } /* u3_cn_slam_un(): produce (gat sam), as ++toon. @@ -402,31 +352,9 @@ u3_cn_nock_un(u3_noun bus, u3_noun fol) u3_noun u3_cn_slam_un(u3_noun gat, u3_noun sam) { - u3_noun ton; + u3_noun fly = u3nt(u3nt(11, 0, 6), 0, 0); // |=(a=* .^(a)) - // u3_cm_leap(); - if ( u3_blip != u3_cm_trap() ) { - u3_noun ton; - - if ( 0 != u3R->net.nyd ) { - ton = u3nc(1, u3R->net.nyd); - u3R->net.nyd = 0; - } else { - ton = u3nc(2, u3R->bug.tax); - u3R->bug.tax = 0; - } - // u3_cm_fall(); - ton = u3_ca_gain(ton); - // u3_cm_flog(0); - } - else { - u3_noun pro = u3_cn_slam_on(gat, sam); - - // u3_cm_fall(); - ton = u3nc(0, u3_ca_gain(pro)); - } - // u3z(gat); u3z(sam); return ton; - return ton; + return u3_cn_slam_in(fly, gat, sam); } /* u3_cn_nock_in(): produce .*(bus fol), as ++toon, in namespace. @@ -434,9 +362,7 @@ u3_cn_slam_un(u3_noun gat, u3_noun sam) u3_noun u3_cn_nock_in(u3_noun fly, u3_noun bus, u3_noun fol) { - // XX implement 11 - // - u3z(fly); return u3_cn_nock_un(bus, fol); + return u3_cm_soft_run(fly, u3_cn_nock_on, bus, fol); } /* u3_cn_slam_in(): produce (gat sam), as ++toon, in namespace. @@ -444,9 +370,7 @@ u3_cn_nock_in(u3_noun fly, u3_noun bus, u3_noun fol) u3_noun u3_cn_slam_in(u3_noun fly, u3_noun gat, u3_noun sam) { - // XX implement 11 - // - u3z(fly); return u3_cn_slam_un(gat, sam); + return u3_cm_soft_run(fly, u3_cn_slam_on, gat, sam); } /* u3_cn_nock_an(): as slam_in(), but with empty fly. @@ -454,5 +378,7 @@ u3_cn_slam_in(u3_noun fly, u3_noun gat, u3_noun sam) u3_noun u3_cn_nock_an(u3_noun bus, u3_noun fol) { - return u3_cn_nock_un(bus, fol); + u3_noun fly = u3nt(u3nc(1, 0), 0, 0); // |=(a=* ~) + + return u3_cn_nock_in(fly, bus, fol); } diff --git a/include/g/a.h b/include/g/a.h index d11fe95a2a..f55a75f074 100644 --- a/include/g/a.h +++ b/include/g/a.h @@ -35,11 +35,16 @@ /* Reference and arena control. */ - /* u3_ca_gain(): gain and/or copy juniors. + /* u3_ca_gain(): gain a reference count in normal space. */ u3_weak u3_ca_gain(u3_weak som); + /* u3_ca_take(): gain, copying juniors. + */ + u3_noun + u3_ca_take(u3_noun som); + /* u3_ca_lose(): lose a reference. */ void diff --git a/include/g/m.h b/include/g/m.h index 355822f7b6..628dcb36a0 100644 --- a/include/g/m.h +++ b/include/g/m.h @@ -68,10 +68,10 @@ void u3_cm_fall(void); - /* u3_cm_leap(): advance to inner road. + /* u3_cm_leap(): in u3R, create a new road within the existing one. */ void - u3_cm_leap(void); + u3_cm_leap(c3_w pad_w); /* u3_cm_wash(): wash all lazy mugs. RETAIN. */ @@ -106,6 +106,26 @@ u3_noun u3_cm_soft(c3_w sec_w, u3_funk fun_f, u3_noun arg); + /* u3_cm_soft_top(): top-level safety wrapper. + */ + u3_noun + u3_cm_soft_top(c3_w pad_w, + u3_funk fun_f, + u3_noun arg); + + /* u3_cm_soft_run(): descend into virtualization context. + */ + u3_noun + u3_cm_soft_run(u3_noun fly, + u3_funq fun_f, + u3_noun aga, + u3_noun agb); + + /* u3_cm_soft_esc(): namespace lookup. Produces direct result. + */ + u3_noun + u3_cm_soft_esc(u3_noun sam); + /* u3_cm_water(): produce high and low watermarks. Asserts u3R == u3H. */ void diff --git a/include/n/road.h b/include/n/road.h index 234cd2e9c1..b46ec67c9b 100644 --- a/include/n/road.h +++ b/include/n/road.h @@ -149,7 +149,7 @@ } coy; struct { // jet dashboard - u3_ch_root* har_u; // jet index by + u3_ch_root* har_u; // jet index } jed; struct { // namespace