mirror of
https://github.com/urbit/vere.git
synced 2024-09-11 11:55:31 +03:00
loom migration to support compressed pointers
This commit is contained in:
parent
0966fb0195
commit
48e326ff03
@ -18,7 +18,9 @@ c3_w u3_Code;
|
||||
|
||||
// declarations of inline functions
|
||||
//
|
||||
c3_w c3_align_w(c3_w x, c3_w al, align_dir hilo);
|
||||
|
||||
void u3a_config_loom(c3_w ver_w);
|
||||
c3_w c3_align_w(c3_w x, c3_w al, align_dir hilo); /* ;;: after rebasing on /vere, these should be declared somewhere else (the align functions) */
|
||||
c3_d c3_align_d(c3_d x, c3_d al, align_dir hilo);
|
||||
void *c3_align_p(void const * p, size_t al, align_dir hilo);
|
||||
void *u3a_into(c3_w x);
|
||||
@ -71,9 +73,9 @@ _box_count(c3_ws siz_ws) { }
|
||||
#define _box_vaal(box_u) \
|
||||
do { \
|
||||
c3_dessert(((uintptr_t)u3a_boxto(box_u) \
|
||||
& u3a_balign-1) == 0); \
|
||||
& u3C.balign_d-1) == 0); \
|
||||
c3_dessert((((u3a_box*)(box_u))->siz_w \
|
||||
& u3a_walign-1) == 0); \
|
||||
& u3C.walign_w-1) == 0); \
|
||||
} while(0)
|
||||
|
||||
/* _box_slot(): select the right free list to search for a block.
|
||||
@ -325,7 +327,7 @@ _ca_box_make_hat(c3_w len_w, c3_w ald_w, c3_w alp_w, c3_w use_w)
|
||||
if ( c3y == u3a_is_north(u3R) ) {
|
||||
all_p = u3R->hat_p;
|
||||
pad_w = c3_align(all_p, ald_w, ALHI) - all_p;
|
||||
siz_w = c3_align(len_w + pad_w, u3a_walign, ALHI);
|
||||
siz_w = c3_align(len_w + pad_w, u3C.walign_w, ALHI);
|
||||
|
||||
// hand-inlined: siz_w >= u3a_open(u3R)
|
||||
//
|
||||
@ -337,7 +339,7 @@ _ca_box_make_hat(c3_w len_w, c3_w ald_w, c3_w alp_w, c3_w use_w)
|
||||
else {
|
||||
all_p = u3R->hat_p - len_w;
|
||||
pad_w = all_p - c3_align(all_p, ald_w, ALLO);
|
||||
siz_w = c3_align(len_w + pad_w, u3a_walign, ALHI);
|
||||
siz_w = c3_align(len_w + pad_w, u3C.walign_w, ALHI);
|
||||
|
||||
// hand-inlined: siz_w >= u3a_open(u3R)
|
||||
//
|
||||
@ -526,7 +528,7 @@ _ca_willoc(c3_w len_w, c3_w ald_w, c3_w alp_w)
|
||||
}
|
||||
else { /* we got a non-null freelist */
|
||||
c3_w pad_w = _me_align_pad(*pfr_p, ald_w, alp_w);
|
||||
c3_w des_w = c3_align(siz_w + pad_w, u3a_walign, ALHI);
|
||||
c3_w des_w = c3_align(siz_w + pad_w, u3C.walign_w, ALHI);
|
||||
|
||||
if ( 1 == ald_w ) c3_assert(0 == pad_w);
|
||||
|
||||
@ -624,8 +626,8 @@ _ca_walloc(c3_w len_w, c3_w ald_w, c3_w alp_w)
|
||||
*/
|
||||
req_w = len_w
|
||||
+ (c3_wiseof(u3a_box) + 1)
|
||||
+ u3a_walign
|
||||
& ~(u3a_walign - 1)
|
||||
+ u3C.walign_w
|
||||
& ~(u3C.walign_w - 1)
|
||||
- (c3_wiseof(u3a_box) + 1);
|
||||
for (;;) {
|
||||
ptr_v = _ca_willoc(req_w, ald_w, alp_w);
|
||||
@ -675,8 +677,8 @@ u3a_wealloc(void* lag_v, c3_w len_w)
|
||||
/* N.B: see related note in _ca_walloc */
|
||||
req_w = len_w
|
||||
+ (c3_wiseof(u3a_box) + 1)
|
||||
+ u3a_walign
|
||||
& ~(u3a_walign - 1)
|
||||
+ u3C.walign_w
|
||||
& ~(u3C.walign_w - 1)
|
||||
- (c3_wiseof(u3a_box) + 1);
|
||||
|
||||
if ( !lag_v ) {
|
||||
@ -743,17 +745,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 */
|
||||
u3a_balign,
|
||||
u3C.balign_d,
|
||||
ALHI);
|
||||
|
||||
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 & u3a_walign-1) == 0)); /* new allocation size must be non-zero and DWORD multiple */
|
||||
c3_dessert(asz_w && ((asz_w & u3C.walign_w-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 & 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 */
|
||||
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 */
|
||||
|
||||
_box_attach(_box_make(end_w, bsz_w, 0)); /* free the unneeded space */
|
||||
|
||||
@ -1783,12 +1785,24 @@ 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) ) {
|
||||
return u3a_to_pug(som_p);
|
||||
som_p = u3a_to_pug(som_p);
|
||||
}
|
||||
else {
|
||||
return u3a_to_pom(som_p);
|
||||
som_p = 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.
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define U3_ALLOCATE_H
|
||||
|
||||
#include "manage.h"
|
||||
#include "options.h"
|
||||
|
||||
/** Constants.
|
||||
**/
|
||||
@ -9,17 +10,10 @@
|
||||
*/
|
||||
# define u3a_bits U3_OS_LoomBits /* 30 */
|
||||
|
||||
/* u3a_vits: number of virtual bits in a noun reference gained via shifting
|
||||
/* u3a_vits_max: number of virtual bits in a reference gained via pointer
|
||||
compression
|
||||
*/
|
||||
# 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)
|
||||
# define u3a_vits_max 1
|
||||
|
||||
/* u3a_bits_max: max loom bex
|
||||
*/
|
||||
@ -31,11 +25,11 @@
|
||||
|
||||
/* u3a_pages: maximum number of pages in memory.
|
||||
*/
|
||||
# define u3a_pages (1ULL << (u3a_bits + u3a_vits - u3a_page) )
|
||||
# define u3a_pages (1ULL << (u3a_bits + u3a_vits_max - u3a_page) )
|
||||
|
||||
/* u3a_words: maximum number of words in memory.
|
||||
*/
|
||||
# define u3a_words ( 1ULL << (u3a_bits + u3a_vits))
|
||||
# define u3a_words ( 1ULL << (u3a_bits + u3a_vits_max ))
|
||||
|
||||
/* u3a_bytes: maximum number of bytes in memory.
|
||||
*/
|
||||
@ -360,7 +354,7 @@
|
||||
# define _rod_vaal(rod_u) \
|
||||
do { \
|
||||
c3_dessert(((uintptr_t)((u3a_road*)(rod_u))->hat_p \
|
||||
& u3a_walign-1) == 0); \
|
||||
& u3C.walign_w-1) == 0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
@ -381,6 +375,23 @@
|
||||
|
||||
/** 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 */ 1:
|
||||
u3C.vits_w = 0;
|
||||
break;
|
||||
case /* U3V_VER2 */ 2:
|
||||
u3C.vits_w = 1;
|
||||
break;
|
||||
default:
|
||||
c3_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.
|
||||
*/
|
||||
@ -397,7 +408,7 @@
|
||||
/* u3a_to_off(): mask off bits 30 and 31 from noun [som].
|
||||
*/
|
||||
inline c3_w u3a_to_off(c3_w som) {
|
||||
return (som & 0x3fffffff) << u3a_vits;
|
||||
return (som & 0x3fffffff) << u3C.vits_w;
|
||||
}
|
||||
|
||||
/* u3a_to_ptr(): convert noun [som] into generic pointer into loom.
|
||||
@ -415,15 +426,15 @@
|
||||
/* u3a_to_pug(): set bit 31 of [off].
|
||||
*/
|
||||
inline c3_w u3a_to_pug(c3_w off) {
|
||||
c3_dessert((off & u3a_walign-1) == 0);
|
||||
return (off >> u3a_vits) | 0x80000000;
|
||||
c3_dessert((off & u3C.walign_w-1) == 0);
|
||||
return (off >> u3C.vits_w) | 0x80000000;
|
||||
}
|
||||
|
||||
/* u3a_to_pom(): set bits 30 and 31 of [off].
|
||||
*/
|
||||
inline c3_w u3a_to_pom(c3_w off) {
|
||||
c3_dessert((off & u3a_walign-1) == 0);
|
||||
return (off >> u3a_vits) | 0xc0000000;
|
||||
c3_dessert((off & u3C.walign_w-1) == 0);
|
||||
return (off >> u3C.vits_w) | 0xc0000000;
|
||||
}
|
||||
|
||||
/** road stack.
|
||||
|
@ -1017,8 +1017,15 @@ _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 {
|
||||
@ -1050,8 +1057,15 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -79,8 +79,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) << u3a_vits))
|
||||
# define u3h_node_to_slot(ptr) ((u3a_outa((ptr)) >> u3a_vits) | 0x40000000)
|
||||
# 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_noun_be_warm(sot) ((sot) | 0x40000000)
|
||||
# define u3h_noun_be_cold(sot) ((sot) & ~0x40000000)
|
||||
# define u3h_slot_to_noun(sot) (0x40000000 | (sot))
|
||||
|
@ -488,7 +488,7 @@ _pave_parts(void)
|
||||
static u3_road*
|
||||
_pave_road(c3_w* rut_w, c3_w* mat_w, c3_w* cap_w, c3_w siz_w)
|
||||
{
|
||||
c3_dessert(((uintptr_t)rut_w & u3a_balign-1) == 0);
|
||||
c3_dessert(((uintptr_t)rut_w & u3C.balign_d-1) == 0);
|
||||
u3_road* rod_u = (void*) mat_w;
|
||||
|
||||
// enable in case of corruption
|
||||
@ -529,8 +529,8 @@ _pave_north(c3_w* mem_w, c3_w siz_w, c3_w len_w)
|
||||
// 00~~~|R|---|H|######|C|+++|M|~~~FF
|
||||
// ^--u3R which _pave_road returns (u3H for home road)
|
||||
//
|
||||
c3_w* mat_w = c3_align(mem_w + len_w - siz_w, u3a_balign, ALLO);
|
||||
c3_w* rut_w = c3_align(mem_w, u3a_balign, ALHI);
|
||||
c3_w* mat_w = c3_align(mem_w + len_w - siz_w, u3C.balign_d, ALLO);
|
||||
c3_w* rut_w = c3_align(mem_w, u3C.balign_d, ALHI);
|
||||
c3_w* cap_w = mat_w;
|
||||
|
||||
return _pave_road(rut_w, mat_w, cap_w, siz_w);
|
||||
@ -555,8 +555,8 @@ _pave_south(c3_w* mem_w, c3_w siz_w, c3_w len_w)
|
||||
//
|
||||
// 00~~~|M|+++|C|######|H|---|R|~~~FFF
|
||||
// ^---u3R which _pave_road returns
|
||||
c3_w* mat_w = c3_align(mem_w, u3a_balign, ALHI);
|
||||
c3_w* rut_w = c3_align(mem_w + len_w, u3a_balign, ALLO);
|
||||
c3_w* mat_w = c3_align(mem_w, u3C.balign_d, ALHI);
|
||||
c3_w* rut_w = c3_align(mem_w + len_w, u3C.balign_d, ALLO);
|
||||
c3_w* cap_w = mat_w + siz_w;
|
||||
|
||||
return _pave_road(rut_w, mat_w, cap_w, siz_w);
|
||||
@ -567,9 +567,12 @@ _pave_south(c3_w* mem_w, c3_w siz_w, c3_w len_w)
|
||||
static void
|
||||
_pave_home(void)
|
||||
{
|
||||
c3_w* mem_w = u3_Loom + u3a_walign;
|
||||
/* a pristine home road will always have compressed references */
|
||||
u3a_config_loom(/* U3V_LATEST */ 2);
|
||||
|
||||
c3_w* mem_w = u3_Loom + u3C.walign_w;
|
||||
c3_w siz_w = c3_wiseof(u3v_home);
|
||||
c3_w len_w = u3C.wor_i - u3a_walign;
|
||||
c3_w len_w = u3C.wor_i - u3C.walign_w;
|
||||
|
||||
u3H = (void *)_pave_north(mem_w, siz_w, len_w);
|
||||
u3H->ver_w = u3v_version;
|
||||
@ -586,34 +589,34 @@ STATIC_ASSERT( ((c3_wiseof(u3v_home) * 4) == sizeof(u3v_home)),
|
||||
static void
|
||||
_find_home(void)
|
||||
{
|
||||
c3_w ver_w = *(u3_Loom + u3C.wor_i - 1);
|
||||
u3a_config_loom(ver_w);
|
||||
|
||||
// NB: the home road is always north
|
||||
//
|
||||
c3_w* mem_w = u3_Loom + u3a_walign;
|
||||
c3_w* mem_w = u3_Loom + u3C.walign_w;
|
||||
c3_w siz_w = c3_wiseof(u3v_home);
|
||||
c3_w len_w = u3C.wor_i - u3a_walign;
|
||||
c3_w* mat_w;
|
||||
c3_w len_w = u3C.wor_i - u3C.walign_w;
|
||||
c3_w* mat_w = c3_align(mem_w + len_w - siz_w, u3C.balign_d, ALLO);
|
||||
|
||||
{
|
||||
c3_w ver_w = *((mem_w + len_w) - 1);
|
||||
|
||||
if ( u3v_version != ver_w ) {
|
||||
fprintf(stderr, "loom: checkpoint version mismatch: "
|
||||
"have %u, need %u\r\n",
|
||||
ver_w,
|
||||
u3v_version);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
mat_w = c3_align(mem_w + len_w - siz_w, u3a_balign, ALLO);
|
||||
u3H = (void *)mat_w;
|
||||
u3R = &u3H->rod_u;
|
||||
|
||||
// this looks risky, but there are no legitimate scenarios
|
||||
// where it's wrong
|
||||
//
|
||||
// this looks risky, but there are no legitimate scenarios where it's wrong
|
||||
u3R->cap_p = u3R->mat_p = u3C.wor_i - c3_wiseof(*u3H);
|
||||
|
||||
if (u3v_version > ver_w) {
|
||||
u3m_migrate(u3v_version);
|
||||
u3a_config_loom(u3v_version);
|
||||
}
|
||||
else if ( u3v_version < ver_w ) {
|
||||
fprintf(stderr, "loom: checkpoint version mismatch: "
|
||||
"have %u, need %u\r\n",
|
||||
ver_w,
|
||||
u3v_version);
|
||||
abort();
|
||||
}
|
||||
|
||||
_rod_vaal(u3R);
|
||||
}
|
||||
|
||||
@ -825,7 +828,7 @@ u3m_leap(c3_w pad_w)
|
||||
}
|
||||
pad_w += c3_wiseof(u3a_road);
|
||||
len_w = u3a_open(u3R) - pad_w;
|
||||
c3_align(len_w, u3a_walign, ALHI);
|
||||
c3_align(len_w, u3C.walign_w, ALHI);
|
||||
}
|
||||
|
||||
/* Allocate a region on the cap.
|
||||
@ -2008,3 +2011,155 @@ u3m_pack(void)
|
||||
|
||||
return (u3a_open(u3R) - pre_w);
|
||||
}
|
||||
|
||||
static void
|
||||
_migrate_reclaim()
|
||||
{
|
||||
fprintf(stderr, "loom: migration reclaim\r\n");
|
||||
u3m_reclaim();
|
||||
}
|
||||
|
||||
static void
|
||||
_migrate_seek(const u3a_road *rod_u)
|
||||
{
|
||||
/*
|
||||
very much like u3a_pack_seek with the following changes:
|
||||
- there is no need to account for free space as |pack is performed before
|
||||
the migration
|
||||
- odd sized boxes will be padded by one word to achieve an even size
|
||||
- rut will be moved from one word ahead of u3_Loom to two words ahead
|
||||
*/
|
||||
c3_w * box_w = u3a_into(rod_u->rut_p);
|
||||
c3_w * end_w = u3a_into(rod_u->hat_p);
|
||||
u3_post new_p = (rod_u->rut_p + 1 + c3_wiseof(u3a_box));
|
||||
u3a_box * box_u = (void *)box_w;
|
||||
|
||||
fprintf(stderr, "loom: migration seek\r\n");
|
||||
|
||||
for (; box_w < end_w
|
||||
; box_w += box_u->siz_w
|
||||
, box_u = (void*)box_w)
|
||||
{
|
||||
if (!box_u->use_w)
|
||||
continue;
|
||||
c3_assert(box_u->siz_w);
|
||||
c3_assert(box_u->use_w);
|
||||
box_w[box_u->siz_w - 1] = new_p;
|
||||
new_p = c3_align(new_p + box_u->siz_w, 2, ALHI);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_migrate_rewrite()
|
||||
{
|
||||
fprintf(stderr, "loom: migration rewrite\r\n");
|
||||
|
||||
/* So that rewritten pointers are compressed, this flag is set */
|
||||
u3C.migration_state = MIG_REWRITE_COMPRESSED;
|
||||
_cm_pack_rewrite();
|
||||
u3C.migration_state = MIG_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
_migrate_move(u3a_road *rod_u)
|
||||
{
|
||||
fprintf(stderr, "loom: migration move\r\n");
|
||||
|
||||
c3_z hiz_z = u3a_heap(rod_u) * sizeof(c3_w);
|
||||
|
||||
/* calculate required shift distance to prevent write head overlapping read head */
|
||||
c3_w off_w = 1; /* at least 1 word because u3R->rut_p migrates from 1 to 2 */
|
||||
for (u3a_box *box_u = u3a_into(rod_u->rut_p)
|
||||
; (void *)box_u < u3a_into(rod_u->hat_p)
|
||||
; box_u = (void *)((c3_w *)box_u + box_u->siz_w))
|
||||
off_w += box_u->siz_w & 1; /* odd-sized boxes are padded by one word */
|
||||
|
||||
/* shift */
|
||||
memmove(u3a_into(u3H->rod_u.rut_p + off_w),
|
||||
u3a_into(u3H->rod_u.rut_p),
|
||||
hiz_z);
|
||||
/* manually zero the former rut */
|
||||
*(c3_w *)u3a_into(rod_u->rut_p) = 0;
|
||||
|
||||
/* relocate boxes to DWORD-aligned addresses stored in trailing size word */
|
||||
c3_w *box_w = u3a_into(rod_u->rut_p + off_w);
|
||||
c3_w *end_w = u3a_into(rod_u->hat_p + off_w);
|
||||
u3a_box *old_u = (void *)box_w;
|
||||
c3_w siz_w = old_u->siz_w;
|
||||
u3p(c3_w) new_p = rod_u->rut_p + 1 + c3_wiseof(u3a_box);
|
||||
c3_w *new_w;
|
||||
|
||||
for (; box_w < end_w
|
||||
; box_w += siz_w
|
||||
, old_u = (void *)box_w
|
||||
, siz_w = old_u->siz_w) {
|
||||
old_u->use_w &= 0x7fffffff;
|
||||
|
||||
if (!old_u->use_w)
|
||||
continue;
|
||||
|
||||
new_w = (void *)u3a_botox(u3a_into(new_p));
|
||||
c3_assert(box_w[siz_w - 1] == new_p);
|
||||
c3_assert(new_w <= box_w);
|
||||
|
||||
c3_w i_w;
|
||||
for (i_w = 0; i_w < siz_w - 1; i_w++)
|
||||
new_w[i_w] = box_w[i_w];
|
||||
|
||||
if (siz_w & 1) {
|
||||
new_w[i_w++] = 0; /* pad odd sized boxes */
|
||||
new_w[i_w++] = siz_w + 1; /* restore trailing size word */
|
||||
new_w[0] = siz_w + 1; /* and the leading size word */
|
||||
}
|
||||
else {
|
||||
new_w[i_w++] = siz_w;
|
||||
}
|
||||
|
||||
new_p += i_w;
|
||||
}
|
||||
|
||||
/* restore proper heap state */
|
||||
rod_u->rut_p = 2;
|
||||
rod_u->hat_p = new_p - c3_wiseof(u3a_box);
|
||||
|
||||
/* like |pack, clear the free lists and cell allocator */
|
||||
for (c3_w i_w = 0; i_w < u3a_fbox_no; i_w++)
|
||||
u3R->all.fre_p[i_w] = 0;
|
||||
|
||||
u3R->all.fre_w = 0;
|
||||
u3R->all.cel_p = 0;
|
||||
}
|
||||
|
||||
|
||||
/* u3m_migrate: perform loom migration if necessary.
|
||||
ver_w - target version
|
||||
*/
|
||||
void
|
||||
u3m_migrate(c3_w ver_w)
|
||||
{
|
||||
if (u3H->ver_w == ver_w)
|
||||
return;
|
||||
|
||||
/* 1 -> 2 is all that is currently supported */
|
||||
c3_dessert(u3H->ver_w == 1 &&
|
||||
ver_w == 2);
|
||||
/* only home road migration is supported */
|
||||
c3_dessert((uintptr_t)u3H == (uintptr_t)u3R);
|
||||
|
||||
fprintf(stderr, "loom: migration running. This may take several minutes to perform\r\n");
|
||||
fprintf(stderr, "loom: have version: %" PRIc3_w " migrating to version: %" PRIc3_w "\r\n",
|
||||
u3H->ver_w, ver_w);
|
||||
|
||||
/* packing first simplifies migration logic and minimizes required buffer space */
|
||||
u3m_pack();
|
||||
|
||||
/* perform the migration in a pattern similar to |pack */
|
||||
_migrate_reclaim();
|
||||
_migrate_seek(&u3H->rod_u);
|
||||
_migrate_rewrite();
|
||||
_migrate_move(&u3H->rod_u);
|
||||
|
||||
/* finally update the version and commit to disk */
|
||||
u3H->ver_w = ver_w;
|
||||
u3e_save();
|
||||
}
|
||||
|
@ -159,4 +159,10 @@
|
||||
c3_w
|
||||
u3m_pack(void);
|
||||
|
||||
/* u3m_migrate: perform loom migration if necessary.
|
||||
ver_w - target version
|
||||
*/
|
||||
void
|
||||
u3m_migrate(c3_w ver_w);
|
||||
|
||||
#endif /* ifndef U3_MANAGE_H */
|
||||
|
@ -14,6 +14,14 @@
|
||||
u3_noun who; // single identity
|
||||
c3_c* dir_c; // execution directory (pier)
|
||||
c3_w wag_w; // flags (both ways)
|
||||
c3_w vits_w; // number of virtual bits in reference
|
||||
c3_w walign_w; // word alignment
|
||||
c3_d balign_d; // byte alignment
|
||||
enum {
|
||||
MIG_NONE,
|
||||
MIG_REWRITE_COMPRESSED,
|
||||
} migration_state;
|
||||
|
||||
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
|
||||
@ -45,5 +53,4 @@
|
||||
extern u3o_config u3o_Config;
|
||||
# define u3C u3o_Config
|
||||
|
||||
|
||||
#endif /* ifndef U3_OPTIONS_H */
|
||||
|
@ -37,7 +37,17 @@
|
||||
|
||||
/** Constants.
|
||||
**/
|
||||
# define u3v_version 1
|
||||
/*
|
||||
version change log:
|
||||
1 -> 2:
|
||||
- 1 bit pointer compression to enable 8G loom
|
||||
*/
|
||||
|
||||
/* ;;: TODO: refactor so that this is possible -- dependency loop if used in options.h */
|
||||
/* # define U3V_VER1 1 */
|
||||
/* # define U3V_VER2 2 */
|
||||
/* # define u3v_version U3V_VER2 */
|
||||
# define u3v_version 2
|
||||
|
||||
/** Functions.
|
||||
**/
|
||||
|
Loading…
Reference in New Issue
Block a user