Skip to content

Commit

Permalink
UIP-0103: Persistent Nock Caching + Loom Migration Framework + Pointe…
Browse files Browse the repository at this point in the history
…r Compression Migration Refactor (#508)

Implements
[UIP-0103](https://github.com/urbit/UIPs/blob/main/UIPS/UIP-0103.md),
establishes a pattern for implementing loom migrations, and refactors
the pointer compression as a compile-time feature instead of a runtime
one.

See #496 for original work on UIP-0103.

TODO:
- [x] Loom migration
- [x] Affordance for future specialized caches in `u3a_road` struct
- [x] PRs for use cases ready in Arvo
  - [x] urbit/urbit#6770
  - [x] urbit/urbit#6773
  - [x] ~~Ford Lightning~~
- [x] Manage new persistent state like we manage the rest of our
persistent state (`|mass` breaks before we do this)
- [x] Update command-line args for cache sizes
- [x] Determine why `bazel build //pkg/vere:test-fake-ship` seems to
hang indefinitely (I ran it for ~16h on my own dedicated box and it
still didn't finish)

Tested working in all vanes I tested (Iris, etc. are a little more
cumbersome):
- [x] Ames
- [x] Arvo
- [x] Behn
- [x] Clay
- [x] Dill
- [x] Eyre
- [x] Gall
  • Loading branch information
matthew-levan authored Nov 8, 2023
2 parents 936a61a + 0269cf7 commit 87783a9
Show file tree
Hide file tree
Showing 63 changed files with 2,309 additions and 417 deletions.
5 changes: 2 additions & 3 deletions pkg/noun/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ vere_library(
name = "noun",
srcs = glob(
[
"*.c",
"*.h",
"jets/tree.c",
"**/*.c",
"**/*.h",
"jets/*.h",
"jets/**/*.c",
],
Expand Down
56 changes: 19 additions & 37 deletions pkg/noun/allocate.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ u3_road* u3a_Road;
c3_w u3_Code;
#endif

// declarations of inline functions
//

void u3a_config_loom(c3_w ver_w);
void *u3a_into(c3_w x);
c3_w u3a_outa(void *p);
c3_w u3a_to_off(c3_w som);
void *u3a_to_ptr(c3_w som);
c3_w *u3a_to_wtr(c3_w som);
c3_w u3a_to_pug(c3_w off);
c3_w u3a_to_pom(c3_w off);

Expand Down Expand Up @@ -67,12 +58,12 @@ _box_count(c3_ws siz_ws) { }
_box_count, (others?) should have perhaps its own header and certainly its
own prefix. having to remind yourself that _box_count doesn't actually do
anything unless U3_CPU_DEBUG is defined is annoying. */
#define _box_vaal(box_u) \
do { \
c3_dessert(((uintptr_t)u3a_boxto(box_u) \
& u3C.balign_d-1) == 0); \
c3_dessert((((u3a_box*)(box_u))->siz_w \
& u3C.walign_w-1) == 0); \
#define _box_vaal(box_u) \
do { \
c3_dessert(((uintptr_t)u3a_boxto(box_u) \
& u3a_balign-1) == 0); \
c3_dessert((((u3a_box*)(box_u))->siz_w \
& u3a_walign-1) == 0); \
} while(0)

/* _box_slot(): select the right free list to search for a block.
Expand Down Expand Up @@ -302,7 +293,7 @@ _ca_box_make_hat(c3_w len_w, c3_w ald_w, c3_w off_w, c3_w use_w)
all_p += c3_wiseof(u3a_box) + off_w;
pad_w = c3_align(all_p, ald_w, C3_ALGHI)
- all_p;
siz_w = c3_align(len_w + pad_w, u3C.walign_w, C3_ALGHI);
siz_w = c3_align(len_w + pad_w, u3a_walign, C3_ALGHI);

// hand-inlined: siz_w >= u3a_open(u3R)
//
Expand All @@ -316,7 +307,7 @@ _ca_box_make_hat(c3_w len_w, c3_w ald_w, c3_w off_w, c3_w use_w)
all_p += c3_wiseof(u3a_box) + off_w;
pad_w = all_p
- c3_align(all_p, ald_w, C3_ALGLO);
siz_w = c3_align(len_w + pad_w, u3C.walign_w, C3_ALGHI);
siz_w = c3_align(len_w + pad_w, u3a_walign, C3_ALGHI);

// hand-inlined: siz_w >= u3a_open(u3R)
//
Expand Down Expand Up @@ -508,7 +499,7 @@ _ca_willoc(c3_w len_w, c3_w ald_w, c3_w off_w)
box_p = all_p = *pfr_p;
all_p += c3_wiseof(u3a_box) + off_w;
c3_w pad_w = c3_align(all_p, ald_w, C3_ALGHI) - all_p;
c3_w des_w = c3_align(siz_w + pad_w, u3C.walign_w, C3_ALGHI);
c3_w des_w = c3_align(siz_w + pad_w, u3a_walign, C3_ALGHI);

/* calls maximally requesting DWORD alignment of returned pointer
shouldn't require padding. */
Expand Down Expand Up @@ -711,17 +702,17 @@ u3a_wtrim(void* tox_v, c3_w old_w, c3_w len_w)
c3_w* box_w = (void*)u3a_botox(nov_w);

c3_w* end_w = c3_align(nov_w + len_w + 1, /* +1 for trailing allocation size */
u3C.balign_d,
u3a_balign,
C3_ALGHI);

c3_w asz_w = (end_w - box_w); /* total size in words of new allocation */
if (box_u->siz_w <= asz_w) return;
c3_w bsz_w = box_u->siz_w - asz_w; /* size diff in words between old and new */

c3_dessert(asz_w && ((asz_w & u3C.walign_w-1) == 0)); /* new allocation size must be non-zero and DWORD multiple */
c3_dessert(asz_w && ((asz_w & u3a_walign-1) == 0)); /* new allocation size must be non-zero and DWORD multiple */
c3_dessert(end_w < (box_w + box_u->siz_w)); /* desired alloc end must not exceed existing boundaries */
c3_dessert(((uintptr_t)end_w & u3C.balign_d-1) == 0); /* address of box getting freed must be DWORD aligned */
c3_dessert((bsz_w & u3C.walign_w-1) == 0); /* size of box getting freed must be DWORD multiple */
c3_dessert(((uintptr_t)end_w & u3a_balign-1) == 0); /* address of box getting freed must be DWORD aligned */
c3_dessert((bsz_w & u3a_walign-1) == 0); /* size of box getting freed must be DWORD multiple */

_box_attach(_box_make(end_w, bsz_w, 0)); /* free the unneeded space */

Expand Down Expand Up @@ -1747,24 +1738,12 @@ u3a_rewritten_noun(u3_noun som)
return som;
}
u3_post som_p = u3a_rewritten(u3a_to_off(som));

/* If this is being called during a migration, one-bit pointer compression
needs to be temporarily enabled so the rewritten reference is compressed */
if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 1;

if ( c3y == u3a_is_pug(som) ) {
som_p = u3a_to_pug(som_p);
return u3a_to_pug(som_p);
}
else {
som_p = u3a_to_pom(som_p);
return u3a_to_pom(som_p);
}

/* likewise, pointer compression is disabled until migration is complete */
if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 0;

return som_p;
}

/* u3a_mark_mptr(): mark a malloc-allocated ptr for gc.
Expand Down Expand Up @@ -2152,7 +2131,8 @@ u3a_mark_road(FILE* fil_u)
tot_w += u3a_maid(fil_u, " profile batteries", u3a_mark_noun(u3R->pro.don));
tot_w += u3a_maid(fil_u, " profile doss", u3a_mark_noun(u3R->pro.day));
tot_w += u3a_maid(fil_u, " new profile trace", u3a_mark_noun(u3R->pro.trace));
tot_w += u3a_maid(fil_u, " memoization cache", u3h_mark(u3R->cax.har_p));
tot_w += u3a_maid(fil_u, " transient memoization cache", u3h_mark(u3R->cax.har_p));
tot_w += u3a_maid(fil_u, " persistent memoization cache", u3h_mark(u3R->cax.per_p));
return u3a_maid(fil_u, "total road stuff", tot_w);
}

Expand All @@ -2179,6 +2159,7 @@ u3a_rewrite_compact(void)
u3a_rewrite_noun(u3R->pro.day);
u3a_rewrite_noun(u3R->pro.trace);
u3h_rewrite(u3R->cax.har_p);
u3h_rewrite(u3R->cax.per_p);

u3R->ski.gul = u3a_rewritten_noun(u3R->ski.gul);
u3R->bug.tax = u3a_rewritten_noun(u3R->bug.tax);
Expand All @@ -2187,6 +2168,7 @@ u3a_rewrite_compact(void)
u3R->pro.day = u3a_rewritten_noun(u3R->pro.day);
u3R->pro.trace = u3a_rewritten_noun(u3R->pro.trace);
u3R->cax.har_p = u3a_rewritten(u3R->cax.har_p);
u3R->cax.per_p = u3a_rewritten(u3R->cax.per_p);
}

/* _ca_print_box(): heuristically print the contents of an allocation box.
Expand Down
85 changes: 32 additions & 53 deletions pkg/noun/allocate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,40 @@

#include "error.h"
#include "manage.h"
#include "options.h"

/** Constants.
**/
/* u3a_bits: number of bits in word-addressed pointer. 29 == 2GB.
*/
# define u3a_bits U3_OS_LoomBits /* 30 */

/* u3a_vits_max: number of virtual bits in a reference gained via pointer
compression
/* u3a_vits: number of virtual bits in a noun reference gained via shifting
*/
# define u3a_vits_max 1
# define u3a_vits 1

/* u3a_walign: references into the loom are guaranteed to be word-aligned to:
*/
# define u3a_walign (1 << u3a_vits)

/* u3a_balign: u3a_walign in bytes
*/
# define u3a_balign (sizeof(c3_w)*u3a_walign)

/* u3a_bits_max: max loom bex
*/
# define u3a_bits_max (8 * sizeof(c3_w) + u3a_vits_max)
# define u3a_bits_max (8 * sizeof(c3_w) + u3a_vits)

/* u3a_page: number of bits in word-addressed page. 12 == 16K page
*/
# define u3a_page 12ULL

/* u3a_pages: maximum number of pages in memory.
*/
# define u3a_pages (1ULL << (u3a_bits + u3a_vits_max - u3a_page) )
# define u3a_pages (1ULL << (u3a_bits + u3a_vits - u3a_page) )

/* u3a_words: maximum number of words in memory.
*/
# define u3a_words ( 1ULL << (u3a_bits + u3a_vits_max ))
# define u3a_words ( 1ULL << (u3a_bits + u3a_vits))

/* u3a_bytes: maximum number of bytes in memory.
*/
Expand Down Expand Up @@ -148,11 +154,11 @@

u3a_jets jed; // jet dashboard

struct { // bytecode state
u3p(u3h_root) har_p; // formula->post of bytecode
struct { // bytecode state
u3p(u3h_root) har_p; // formula->post of bytecode
} byc;

struct { // namespace
struct { // scry namespace
u3_noun gul; // (list $+(* (unit (unit)))) now
} ski;

Expand All @@ -169,8 +175,9 @@
u3_noun day; // doss, only in u3H (moveme)
} pro;

struct { // memoization
u3p(u3h_root) har_p; // (map (pair term noun) noun)
struct { // memoization caches
u3p(u3h_root) har_p; // transient
u3p(u3h_root) per_p; // persistent
} cax;
} u3a_road;
typedef u3a_road u3_road;
Expand Down Expand Up @@ -226,7 +233,7 @@
/* u3a_is_atom(): yes if noun [som] is direct atom or indirect atom.
*/
# define u3a_is_atom(som) c3o(u3a_is_cat(som), \
u3a_is_pug(som))
u3a_is_pug(som))
# define u3ud(som) u3a_is_atom(som)

/* u3a_is_cell: yes if noun [som] is cell.
Expand Down Expand Up @@ -355,7 +362,7 @@
# define _rod_vaal(rod_u) \
do { \
c3_dessert(((uintptr_t)((u3a_road*)(rod_u))->hat_p \
& u3C.walign_w-1) == 0); \
& u3a_walign-1) == 0); \
} while(0)


Expand All @@ -374,68 +381,40 @@

# define u3_Loom ((c3_w *)(void *)U3_OS_LoomBase)

/** inline functions.
**/
/* u3a_config_loom(): configure loom information by u3v version
*/
inline void u3a_config_loom(c3_w ver_w) {
switch (ver_w) {
case U3V_VER1:
u3C.vits_w = 0;
break;
case U3V_VER2:
u3C.vits_w = 1;
break;
default:
u3_assert(0);
}

u3C.walign_w = 1 << u3C.vits_w;
u3C.balign_d = sizeof(c3_w) * u3C.walign_w;
}

/* u3a_into(): convert loom offset [x] into generic pointer.
*/
inline void *u3a_into(c3_w x) {
return u3_Loom + x;
}
# define u3a_into(x) ((void *)(u3_Loom + (x)))

/* u3a_outa(): convert pointer [p] into word offset into loom.
*/
inline c3_w u3a_outa(void *p) {
return ((c3_w *)p) - u3_Loom;
}
# define u3a_outa(p) ((c3_w *)(void *)(p) - u3_Loom)

/* u3a_to_off(): mask off bits 30 and 31 from noun [som].
*/
inline c3_w u3a_to_off(c3_w som) {
return (som & 0x3fffffff) << u3C.vits_w;
}
# define u3a_to_off(som) (((som) & 0x3fffffff) << u3a_vits)

/* u3a_to_ptr(): convert noun [som] into generic pointer into loom.
*/
inline void *u3a_to_ptr(c3_w som) {
return u3a_into(u3a_to_off(som));
}
# define u3a_to_ptr(som) (u3a_into(u3a_to_off(som)))

/* u3a_to_wtr(): convert noun [som] into word pointer into loom.
*/
inline c3_w *u3a_to_wtr(c3_w som) {
return (c3_w *)u3a_to_ptr(som);
}
# define u3a_to_wtr(som) ((c3_w *)u3a_to_ptr(som))

/** Inline functions.
**/
/* u3a_to_pug(): set bit 31 of [off].
*/
inline c3_w u3a_to_pug(c3_w off) {
c3_dessert((off & u3C.walign_w-1) == 0);
return (off >> u3C.vits_w) | 0x80000000;
c3_dessert((off & u3a_walign-1) == 0);
return (off >> u3a_vits) | 0x80000000;
}

/* u3a_to_pom(): set bits 30 and 31 of [off].
*/
inline c3_w u3a_to_pom(c3_w off) {
c3_dessert((off & u3C.walign_w-1) == 0);
return (off >> u3C.vits_w) | 0xc0000000;
c3_dessert((off & u3a_walign-1) == 0);
return (off >> u3a_vits) | 0xc0000000;
}

/** road stack.
Expand Down
14 changes: 0 additions & 14 deletions pkg/noun/hashtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,15 +1017,8 @@ _ch_rewrite_node(u3h_node* han_u, c3_w lef_w)
else {
void* hav_v = u3h_slot_to_node(sot_w);
u3h_node* nod_u = u3to(u3h_node,u3a_rewritten(u3of(u3h_node,hav_v)));

if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 1;

han_u->sot_w[i_w] = u3h_node_to_slot(nod_u);

if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 0;

if ( 0 == lef_w ) {
_ch_rewrite_buck(hav_v);
} else {
Expand Down Expand Up @@ -1057,15 +1050,8 @@ u3h_rewrite(u3p(u3h_root) har_p)
else if ( _(u3h_slot_is_node(sot_w)) ) {
u3h_node* han_u = u3h_slot_to_node(sot_w);
u3h_node* nod_u = u3to(u3h_node,u3a_rewritten(u3of(u3h_node,han_u)));

if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 1;

har_u->sot_w[i_w] = u3h_node_to_slot(nod_u);

if (u3C.migration_state == MIG_REWRITE_COMPRESSED)
u3C.vits_w = 0;

_ch_rewrite_node(han_u, 25);
}
}
Expand Down
9 changes: 4 additions & 5 deletions pkg/noun/hashtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
*** corresponding to the 32-slot nodes for everything under
*** the root node.
***
*** We store an extra "freshly warm" bit for a simple
*** clock-algorithm reclamation policy, not yet implemented.
*** Search "clock algorithm" to figure it out.
*** We store an extra "freshly warm" bit and use it for a simple
*** clock-algorithm reclamation policy.
**/
/* u3h_slot: map slot.
**
Expand Down Expand Up @@ -79,8 +78,8 @@
# define u3h_slot_is_node(sot) ((1 == ((sot) >> 30)) ? c3y : c3n)
# define u3h_slot_is_noun(sot) ((1 == ((sot) >> 31)) ? c3y : c3n)
# define u3h_slot_is_warm(sot) (((sot) & 0x40000000) ? c3y : c3n)
# define u3h_slot_to_node(sot) (u3a_into(((sot) & 0x3fffffff) << u3C.vits_w))
# define u3h_node_to_slot(ptr) ((u3a_outa((ptr)) >> u3C.vits_w) | 0x40000000)
# define u3h_slot_to_node(sot) (u3a_into(((sot) & 0x3fffffff) << u3a_vits))
# define u3h_node_to_slot(ptr) ((u3a_outa((ptr)) >> u3a_vits) | 0x40000000)
# define u3h_noun_be_warm(sot) ((sot) | 0x40000000)
# define u3h_noun_be_cold(sot) ((sot) & ~0x40000000)
# define u3h_slot_to_noun(sot) (0x40000000 | (sot))
Expand Down
Loading

0 comments on commit 87783a9

Please sign in to comment.