Skip to content

Commit

Permalink
sysimg relocation lists now use LEB128 format (#47204)
Browse files Browse the repository at this point in the history
Appears to reduce the data size from about 165MB to 147MB!
  • Loading branch information
apaz-cli authored Oct 18, 2022
1 parent bc7500b commit 94736a4
Showing 1 changed file with 71 additions and 30 deletions.
101 changes: 71 additions & 30 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,12 @@ typedef enum {
} jl_callingconv_t;


//#ifdef _P64
//#define RELOC_TAG_OFFSET 61
//#else
#ifdef _P64
#define RELOC_TAG_OFFSET 61
#else
// this supports up to 8 RefTags, 512MB of pointer data, and 4/2 (64/32-bit) GB of constant data.
#define RELOC_TAG_OFFSET 29
//#endif
#endif

#if RELOC_TAG_OFFSET <= 32
typedef uint32_t reloc_t;
Expand Down Expand Up @@ -1133,7 +1133,7 @@ static void jl_write_values(jl_serializer_state *s)
assert(invokeptr_id > 0);
ios_ensureroom(s->fptr_record, invokeptr_id * sizeof(void*));
ios_seek(s->fptr_record, (invokeptr_id - 1) * sizeof(void*));
write_reloc_t(s->fptr_record, (uint32_t)~reloc_offset);
write_reloc_t(s->fptr_record, (reloc_t)~reloc_offset);
#ifdef _P64
if (sizeof(reloc_t) < 8)
write_padding(s->fptr_record, 8 - sizeof(reloc_t));
Expand Down Expand Up @@ -1409,41 +1409,71 @@ static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t bas
}


static void jl_write_skiplist(ios_t *s, char *base, size_t size, arraylist_t *list)
static void jl_write_reloclist(ios_t *s, char *base, size_t size, arraylist_t *list)
{
size_t i;
for (i = 0; i < list->len; i += 2) {
for (size_t i = 0; i < list->len; i += 2) {
size_t last_pos = i ? (size_t)list->items[i - 2] : 0;
size_t pos = (size_t)list->items[i];
size_t item = (size_t)list->items[i + 1];
uintptr_t *pv = (uintptr_t*)(base + pos);
assert(pos < size && pos != 0);
*pv = get_reloc_for_item(item, *pv);
// record pos in relocations list
// TODO: save space by using delta-compression
write_reloc_t(s, pos);

// write pos as compressed difference.
size_t pos_diff = pos - last_pos;
while (pos_diff) {
assert(pos_diff >= 0);
if (pos_diff <= 127) {
write_int8(s, pos_diff);
break;
}
else {
// Extract the next 7 bits
int8_t ns = pos_diff & (int8_t)0x7F;
pos_diff >>= 7;
// Set the high bit if there's still more
ns |= (!!pos_diff) << 7;
write_int8(s, ns);
}
}
}
write_reloc_t(s, 0);
write_int8(s, 0);
}


static void jl_write_relocations(jl_serializer_state *s)
{
char *base = &s->s->buf[0];
jl_write_skiplist(s->relocs, base, s->s->size, &s->gctags_list);
jl_write_skiplist(s->relocs, base, s->s->size, &s->relocs_list);
jl_write_reloclist(s->relocs, base, s->s->size, &s->gctags_list);
jl_write_reloclist(s->relocs, base, s->s->size, &s->relocs_list);
}


static void jl_read_relocations(jl_serializer_state *s, uint8_t bits)
static void jl_read_reloclist(jl_serializer_state *s, uint8_t bits)
{
uintptr_t base = (uintptr_t)&s->s->buf[0];
uintptr_t base = (uintptr_t)s->s->buf;
size_t size = s->s->size;
uintptr_t last_pos = 0;
uint8_t *current = (uint8_t *)(s->relocs->buf + s->relocs->bpos);
while (1) {
uintptr_t offset = *(reloc_t*)&s->relocs->buf[(uintptr_t)s->relocs->bpos];
s->relocs->bpos += sizeof(reloc_t);
if (offset == 0)
// Read the offset of the next object
size_t pos_diff = 0;
size_t cnt = 0;
while (1) {
assert(s->relocs->bpos <= s->relocs->size);
assert((char *)current <= (char *)(s->relocs->buf + s->relocs->size));
int8_t c = *current++;
s->relocs->bpos += 1;

pos_diff |= ((size_t)c & 0x7F) << (7 * cnt++);
if ((c >> 7) == 0)
break;
}
if (pos_diff == 0)
break;
uintptr_t *pv = (uintptr_t*)(base + offset);

uintptr_t pos = last_pos + pos_diff;
last_pos = pos;
uintptr_t *pv = (uintptr_t *)(base + pos);
uintptr_t v = *pv;
v = get_item_for_reloc(s, base, size, v);
*pv = v | bits;
Expand All @@ -1454,16 +1484,27 @@ static char *sysimg_base;
static char *sysimg_relocs;
void gc_sweep_sysimg(void)
{
char *base = sysimg_base;
reloc_t *relocs = (reloc_t*)sysimg_relocs;
if (relocs == NULL)
if (!sysimg_relocs)
return;
uintptr_t base = (uintptr_t)sysimg_base;
uintptr_t last_pos = 0;
uint8_t *current = (uint8_t *)sysimg_relocs;
while (1) {
uintptr_t offset = *relocs;
relocs++;
if (offset == 0)
// Read the offset of the next object
size_t pos_diff = 0;
size_t cnt = 0;
while (1) {
int8_t c = *current++;
pos_diff |= ((size_t)c & 0x7F) << (7 * cnt++);
if ((c >> 7) == 0)
break;
}
if (pos_diff == 0)
break;
jl_taggedvalue_t *o = (jl_taggedvalue_t*)(base + offset);

uintptr_t pos = last_pos + pos_diff;
last_pos = pos;
jl_taggedvalue_t *o = (jl_taggedvalue_t *)(base + pos);
o->bits.gc = GC_OLD;
}
}
Expand Down Expand Up @@ -2220,10 +2261,10 @@ static void jl_restore_system_image_from_stream(ios_t *f) JL_GC_DISABLED
jl_gc_set_permalloc_region((void*)sysimg_base, (void*)(sysimg_base + sysimg.size));

s.s = &sysimg;
jl_read_relocations(&s, GC_OLD); // gctags
jl_read_reloclist(&s, GC_OLD); // gctags
size_t sizeof_tags = ios_pos(&relocs);
(void)sizeof_tags;
jl_read_relocations(&s, 0); // general relocs
jl_read_reloclist(&s, 0); // general relocs
ios_close(&relocs);
ios_close(&const_data);
jl_update_all_gvars(&s); // gvars relocs
Expand Down

0 comments on commit 94736a4

Please sign in to comment.