Merge ../ChezScheme-vfasl

original commit: dbe15d6cae6f23c4e218974ac83f36a935292ad2
This commit is contained in:
Matthew Flatt 2018-12-21 14:35:49 -07:00
commit 545a465cf4
8 changed files with 460 additions and 156 deletions

View File

@ -109,6 +109,7 @@ extern int S_fasl_intern_rtd(ptr *x);
extern ptr S_to_vfasl PROTO((ptr v)); extern ptr S_to_vfasl PROTO((ptr v));
extern ptr S_vfasl PROTO((ptr bv, void *stream, iptr len)); extern ptr S_vfasl PROTO((ptr bv, void *stream, iptr len));
extern ptr S_vfasl_to PROTO((ptr v)); extern ptr S_vfasl_to PROTO((ptr v));
extern IBOOL S_vfasl_can_combinep(ptr v);
/* flushcache.c */ /* flushcache.c */
extern void S_record_code_mod PROTO((ptr tc, uptr addr, uptr bytes)); extern void S_record_code_mod PROTO((ptr tc, uptr addr, uptr bytes));

View File

@ -237,7 +237,7 @@ static void ppc32_set_jump PROTO((void *address, uptr item, IBOOL callp));
static uptr ppc32_get_jump PROTO((void *address)); static uptr ppc32_get_jump PROTO((void *address));
#endif /* PPC32 */ #endif /* PPC32 */
#ifdef X86_64 #ifdef X86_64
static void x86_64_set_jump PROTO((void *address, uptr item, IBOOL callp, IBOOL force_abs)); static void x86_64_set_jump PROTO((void *address, uptr item, IBOOL callp));
static uptr x86_64_get_jump PROTO((void *address)); static uptr x86_64_get_jump PROTO((void *address));
#endif /* X86_64 */ #endif /* X86_64 */
#ifdef SPARC64 #ifdef SPARC64
@ -463,6 +463,12 @@ static ptr fasl_entry(ptr tc, unbufFaslFile uf) {
ffo.size = uf_uptrin(uf); ffo.size = uf_uptrin(uf);
if (ty == fasl_type_vfasl_size) { if (ty == fasl_type_vfasl_size) {
if (S_vfasl_boot_mode == -1) {
ptr pre = S_cputime();
Scompact_heap();
S_vfasl_boot_mode = 1;
printf("pre compact %ld\n", UNFIX(S_cputime()) - UNFIX(pre));
}
x = S_vfasl((ptr)0, uf, ffo.size); x = S_vfasl((ptr)0, uf, ffo.size);
} else { } else {
ffo.buf = buf; ffo.buf = buf;
@ -1192,7 +1198,7 @@ void S_set_code_obj(who, typ, p, n, x, o) char *who; IFASLCODE typ; iptr n, o; p
address = (void *)((uptr)p + n); address = (void *)((uptr)p + n);
item = (uptr)x + o; item = (uptr)x + o;
switch (typ & ~reloc_force_abs) { switch (typ) {
case reloc_abs: case reloc_abs:
*(uptr *)address = item; *(uptr *)address = item;
break; break;
@ -1226,10 +1232,10 @@ void S_set_code_obj(who, typ, p, n, x, o) char *who; IFASLCODE typ; iptr n, o; p
#endif /* I386 */ #endif /* I386 */
#ifdef X86_64 #ifdef X86_64
case reloc_x86_64_jump: case reloc_x86_64_jump:
x86_64_set_jump(address, item, 0, typ & reloc_force_abs); x86_64_set_jump(address, item, 0);
break; break;
case reloc_x86_64_call: case reloc_x86_64_call:
x86_64_set_jump(address, item, 1, typ & reloc_force_abs); x86_64_set_jump(address, item, 1);
break; break;
#endif /* X86_64 */ #endif /* X86_64 */
#ifdef SPARC64 #ifdef SPARC64
@ -1269,7 +1275,7 @@ ptr S_get_code_obj(typ, p, n, o) IFASLCODE typ; iptr n, o; ptr p; {
void *address; uptr item; void *address; uptr item;
address = (void *)((uptr)p + n); address = (void *)((uptr)p + n);
switch (typ & ~reloc_force_abs) { switch (typ) {
case reloc_abs: case reloc_abs:
item = *(uptr *)address; item = *(uptr *)address;
break; break;
@ -1447,9 +1453,9 @@ static uptr ppc32_get_jump(void *address) {
#endif /* PPC32 */ #endif /* PPC32 */
#ifdef X86_64 #ifdef X86_64
static void x86_64_set_jump(void *address, uptr item, IBOOL callp, IBOOL force_abs) { static void x86_64_set_jump(void *address, uptr item, IBOOL callp) {
I64 disp = (I64)item - ((I64)address + 5); /* 5 = size of call instruction */ I64 disp = (I64)item - ((I64)address + 5); /* 5 = size of call instruction */
if ((I32)disp == disp && !force_abs) { if ((I32)disp == disp) {
*(octet *)address = callp ? 0xE8 : 0xE9; /* call or jmp disp32 opcode */ *(octet *)address = callp ? 0xE8 : 0xE9; /* call or jmp disp32 opcode */
*(I32 *)((uptr)address + 1) = (I32)disp; *(I32 *)((uptr)address + 1) = (I32)disp;
*((octet *)address + 5) = 0x90; /* nop */ *((octet *)address + 5) = 0x90; /* nop */

View File

@ -26,6 +26,7 @@ EXTERN ptr S_child_processes[static_generation+1];
/* scheme.c */ /* scheme.c */
EXTERN IBOOL S_boot_time; EXTERN IBOOL S_boot_time;
EXTERN int S_vfasl_boot_mode;
EXTERN IBOOL S_errors_to_console; EXTERN IBOOL S_errors_to_console;
EXTERN ptr S_threads; EXTERN ptr S_threads;
EXTERN uptr S_nthreads; EXTERN uptr S_nthreads;

View File

@ -1548,6 +1548,7 @@ void S_prim5_init() {
Sforeign_symbol("(cs)bv_fasl_read", (void *)S_bv_fasl_read); Sforeign_symbol("(cs)bv_fasl_read", (void *)S_bv_fasl_read);
Sforeign_symbol("(cs)to_vfasl", (void *)S_to_vfasl); Sforeign_symbol("(cs)to_vfasl", (void *)S_to_vfasl);
Sforeign_symbol("(cs)vfasl_to", (void *)S_vfasl_to); Sforeign_symbol("(cs)vfasl_to", (void *)S_vfasl_to);
Sforeign_symbol("(cs)vfasl_can_combinep", (void *)S_vfasl_can_combinep);
Sforeign_symbol("(cs)s_decode_float", (void *)s_decode_float); Sforeign_symbol("(cs)s_decode_float", (void *)s_decode_float);
Sforeign_symbol("(cs)new_open_input_fd", (void *)S_new_open_input_fd); Sforeign_symbol("(cs)new_open_input_fd", (void *)S_new_open_input_fd);

View File

@ -25,6 +25,10 @@
#endif #endif
#include <stddef.h> #include <stddef.h>
extern iptr vfasl_load_time;
extern iptr vfasl_fix_time;
extern iptr vfasl_relocs;
static INT boot_count; static INT boot_count;
static IBOOL verbose; static IBOOL verbose;
@ -884,7 +888,11 @@ static void load(tc, n, base) ptr tc; iptr n; IBOOL base; {
i = 0; i = 0;
while (i++ < LOADSKIP && S_boot_read(bd[n].file, bd[n].path) != Seof_object); while (i++ < LOADSKIP && S_boot_read(bd[n].file, bd[n].path) != Seof_object);
ptr pre = S_cputime();
uptr reading = 0;
while ((x = S_boot_read(bd[n].file, bd[n].path)) != Seof_object) { while ((x = S_boot_read(bd[n].file, bd[n].path)) != Seof_object) {
reading += UNFIX(S_cputime()) - UNFIX(pre);
if (loadecho) { if (loadecho) {
printf("%ld: ", (long)i); printf("%ld: ", (long)i);
fflush(stdout); fflush(stdout);
@ -917,8 +925,11 @@ static void load(tc, n, base) ptr tc; iptr n; IBOOL base; {
fflush(stdout); fflush(stdout);
} }
i += 1; i += 1;
pre = S_cputime();
} }
printf("load %ld\n", reading);
S_G.load_binary = Sfalse; S_G.load_binary = Sfalse;
gzclose(bd[n].file); gzclose(bd[n].file);
} }
@ -1116,6 +1127,8 @@ extern void Sbuild_heap(kernel, custom_init) const char *kernel; void (*custom_i
} }
} }
S_vfasl_boot_mode = -1; /* to static generation after compacting initial */
if (boot_count != 0) { if (boot_count != 0) {
INT i = 0; INT i = 0;
@ -1142,8 +1155,16 @@ extern void Sbuild_heap(kernel, custom_init) const char *kernel; void (*custom_i
while (i < boot_count) load(tc, i++, 0); while (i < boot_count) load(tc, i++, 0);
} }
S_vfasl_boot_mode = 0;
printf("vfasl %ld %ld / %ld\n", vfasl_load_time, vfasl_fix_time, vfasl_relocs);
ptr pre = S_cputime();
if (boot_count != 0) Scompact_heap(); if (boot_count != 0) Scompact_heap();
printf("compact %ld\n", UNFIX(S_cputime()) - UNFIX(pre));
/* complete the initialization on the Scheme side */ /* complete the initialization on the Scheme side */
p = S_symbol_value(S_intern((const unsigned char *)"$scheme-init")); p = S_symbol_value(S_intern((const unsigned char *)"$scheme-init"));
if (!Sprocedurep(p)) { if (!Sprocedurep(p)) {

537
c/vfasl.c
View File

@ -16,6 +16,47 @@
#include "system.h" #include "system.h"
iptr vfasl_load_time;
iptr vfasl_fix_time;
iptr vfasl_relocs;
/*
vfasl ("very fast load") format, where "data" corresponds to an
image to load into memory, "table" is metadata to relocate that
data, and the fixed-size header determines the overall size. The
data can be loaded directly to the static generation on boot, since
it's organized into pieces that should reside in a particular
space.
[vfasl_header]
_
/ [symbol] ... -> space_symbol
/ [rtd] ... -> space_pure
d | [closure] ... -> space_pure
a | [impure] ... -> space_impure
t | [pure_typed] ... -> space_pure_typed
a | [impure_record] ... -> space_impure_record
| [code] ... -> space_code
\ [data] ... -> space_data
\_ [reloc] ... -> (not kept for direct-to-static)
_
t / [symbol reference offset] ...
a / [rtd reference offset] ...
b | [singleton reference offset] ...
l \
e \_ [bitmap of pointers to relocate]
The bitmap at the end has one bit for each pointer-sized word in
the data, but it's shorter than the "data" size (divided by the
pointer size then divided by 8 bits per byte) because the trailing
zeros for data are omitted. The bitmap doesn't include some fixups
that are handled more directly, such as for code and its
relocations.
*/
typedef uptr vfoff; typedef uptr vfoff;
typedef struct vfasl_header { typedef struct vfasl_header {
@ -29,37 +70,59 @@ typedef struct vfasl_header {
vfoff rtd_offset; vfoff rtd_offset;
# define rtd_end_offset closure_offset # define rtd_end_offset closure_offset
vfoff closure_offset; vfoff closure_offset;
# define closure_end_offset code_offset # define closure_end_offset impure_offset
vfoff impure_offset;
# define impure_end_offset pure_typed_offset
vfoff pure_typed_offset;
# define pure_typed_object_end_offset impure_record_offset
vfoff impure_record_offset;
# define impure_record_end_offset code_offset
vfoff code_offset; vfoff code_offset;
# define code_end_offset other_offset # define code_end_offset data_offset
vfoff other_offset; vfoff data_offset;
# define data_end_offset reloc_offset
vfoff reloc_offset;
# define reloc_end_offset data_size
vfoff symref_count; vfoff symref_count;
vfoff rtdref_count; vfoff rtdref_count;
vfoff singletonref_count; vfoff singletonref_count;
} vfasl_header; } vfasl_header;
/* vfasl format, where the fixed-size header determines the rest of the enum {
size: /* The order of these spaces needs to match vfasl_header: */
vspace_symbol,
vspace_rtd,
vspace_closure,
vspace_impure,
vspace_pure_typed,
vspace_impure_record,
/* rest rest are at then end to make the pointer bitmap
end with zeros (that can be dropped): */
vspace_code,
vspace_data,
vspace_reloc, /* can be dropped after direct to static generation */
vspaces_count
};
[vfasl_header] /* Needs to match order above: */
_ static ISPC vspace_spaces[] = {
d / [symbol] ... space_symbol,
a / [rtd] ... space_pure, /* rtd */
t | [closure] ... space_pure, /* closure */
a \ [code] ... space_impure,
\_ [other] ... space_pure_typed_object,
space_impure_record,
space_code,
space_data,
space_data /* reloc --- but not really, since relocs are never in static */
};
t / [vfoff: symbol reference offset] ... /************************************************************/
a / [vfoff: rtd reference offset] ... /* Encode-time data structures */
b | [vfoff: singleton reference offset] ...
l \
e \_ [bitmap of pointer offsets]
*/
/* Many chunks per vspace on first pass, one per vspace on second /* During encoding, we use many chunks per vspace on first pass, one
pass: */ per vspace on second pass: */
typedef struct vfasl_chunk { typedef struct vfasl_chunk {
ptr bytes; ptr bytes;
uptr length; uptr length;
@ -74,20 +137,6 @@ struct vfasl_count_and_chunk {
vfasl_chunk *first; vfasl_chunk *first;
}; };
enum {
/* The order of these spaces matters: */
vspace_symbol,
vspace_rtd,
vspace_closure,
vspace_code,
/* The rest of the spaces are "other" */
vspace_array,
vspace_typed,
vspace_reloc,
vspace_data, /* at end, so pointer bitmap ends with zeros */
vspaces_count
};
typedef struct vfasl_info { typedef struct vfasl_info {
ptr base_addr; /* address to make relocations relative to */ ptr base_addr; /* address to make relocations relative to */
@ -109,6 +158,8 @@ typedef struct vfasl_info {
octet *ptr_bitmap; octet *ptr_bitmap;
struct vfasl_hash_table *graph; struct vfasl_hash_table *graph;
IBOOL installs_library_entry; /* to determine whether vfasls can be combined */
} vfasl_info; } vfasl_info;
#define ptr_add(p, n) ((ptr)((uptr)(p) + (n))) #define ptr_add(p, n) ((ptr)((uptr)(p) + (n)))
@ -126,7 +177,8 @@ static uptr sweep_code_object(vfasl_info *vfi, ptr co);
static uptr sweep_record(vfasl_info *vfi, ptr co); static uptr sweep_record(vfasl_info *vfi, ptr co);
static uptr sweep(vfasl_info *vfi, ptr p); static uptr sweep(vfasl_info *vfi, ptr p);
static void relink_code(ptr co, ptr sym_base, ptr dest_base); static void relink_code(ptr co, ptr sym_base, ptr *vspaces, uptr *vspace_offsets, IBOOL to_static);
static ptr find_pointer_from_offset(uptr p_off, ptr *vspaces, uptr *vspace_offsets);
static void vfasl_relocate(vfasl_info *vfi, ptr *ppp); static void vfasl_relocate(vfasl_info *vfi, ptr *ppp);
static ptr vfasl_relocate_help(vfasl_info *vfi, ptr pp); static ptr vfasl_relocate_help(vfasl_info *vfi, ptr pp);
@ -138,6 +190,7 @@ static void vfasl_register_forward(vfasl_info *vfi, ptr pp, ptr p);
static ptr vfasl_lookup_forward(vfasl_info *vfi, ptr p); static ptr vfasl_lookup_forward(vfasl_info *vfi, ptr p);
static void fasl_init_entry_tables(); static void fasl_init_entry_tables();
static void vfasl_check_install_library_entry(vfasl_info *vfi, ptr name);
static int detect_singleton(ptr p); static int detect_singleton(ptr p);
static ptr lookup_singleton(int which); static ptr lookup_singleton(int which);
@ -152,17 +205,24 @@ static void sort_offsets(vfoff *p, vfoff len);
#define vfasl_fail(vfi, what) S_error("vfasl", "cannot encode " what) #define vfasl_fail(vfi, what) S_error("vfasl", "cannot encode " what)
#define print_stats(args) /* printf args */ /************************************************************/
/* Loading */
ptr S_vfasl(ptr bv, void *stream, iptr input_len) ptr S_vfasl(ptr bv, void *stream, iptr input_len)
{ {
ptr tc = get_thread_context(); ptr tc = get_thread_context();
vfasl_header header; vfasl_header header;
ptr vspaces[vspaces_count];
uptr vspace_offsets[vspaces_count+1], vspace_deltas[vspaces_count];
ptr data, table; ptr data, table;
vfoff *symrefs, *rtdrefs, *singletonrefs; vfoff *symrefs, *rtdrefs, *singletonrefs;
octet *bm, *bm_end; octet *bm, *bm_end;
iptr used_len; iptr used_len;
int s;
IBOOL to_static = 0;
ptr pre = S_cputime();
used_len = sizeof(header); used_len = sizeof(header);
if (used_len > input_len) if (used_len > input_len)
S_error("fasl-read", "input length mismatch"); S_error("fasl-read", "input length mismatch");
@ -178,21 +238,68 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
if (used_len > input_len) if (used_len > input_len)
S_error("fasl-read", "input length mismatch"); S_error("fasl-read", "input length mismatch");
vspace_offsets[vspace_symbol] = 0;
vspace_offsets[vspace_rtd] = header.rtd_offset;
vspace_offsets[vspace_closure] = header.closure_offset;
vspace_offsets[vspace_impure] = header.impure_offset;
vspace_offsets[vspace_pure_typed] = header.pure_typed_offset;
vspace_offsets[vspace_impure_record] = header.impure_record_offset;
vspace_offsets[vspace_code] = header.code_offset;
vspace_offsets[vspace_data] = header.data_offset;
vspace_offsets[vspace_reloc] = header.reloc_offset;
vspace_offsets[vspaces_count] = header.data_size;
if (bv) { if (bv) {
ptr base_addr = &BVIT(bv, sizeof(vfasl_header)); ptr base_addr = &BVIT(bv, sizeof(vfasl_header));
thread_find_room(tc, typemod, header.data_size, data); thread_find_room(tc, typemod, header.data_size, data);
memcpy(data, base_addr, header.data_size); memcpy(data, base_addr, header.data_size);
table = ptr_add(base_addr, header.data_size); table = ptr_add(base_addr, header.data_size);
} else { } else {
thread_find_room(tc, typemod, header.data_size, data); if (S_vfasl_boot_mode > 0) {
if (S_fasl_stream_read(stream, data, header.data_size) < 0) for (s = 0; s < vspaces_count; s++) {
S_error("fasl-read", "input truncated"); uptr sz = vspace_offsets[s+1] - vspace_offsets[s];
if (sz > 0) {
if (s == vspace_reloc) {
thread_find_room(tc, typemod, sz, vspaces[s]);
} else {
find_room(vspace_spaces[s], static_generation, typemod, sz, vspaces[s]);
}
if (S_fasl_stream_read(stream, vspaces[s], sz) < 0)
S_error("fasl-read", "input truncated");
} else
vspaces[s] = (ptr)0;
}
for (s = vspaces_count - 1; s--; ) {
if (!vspaces[s])
vspaces[s] = vspaces[s+1];
}
data = (ptr)0; /* => initialize below */
to_static = 1;
} else {
thread_find_room(tc, typemod, header.data_size, data);
if (S_fasl_stream_read(stream, data, header.data_size) < 0)
S_error("fasl-read", "input truncated");
}
thread_find_room(tc, typemod, ptr_align(header.table_size), table); thread_find_room(tc, typemod, ptr_align(header.table_size), table);
if (S_fasl_stream_read(stream, table, header.table_size) < 0) if (S_fasl_stream_read(stream, table, header.table_size) < 0)
S_error("fasl-read", "input truncated"); S_error("fasl-read", "input truncated");
} }
if (data) {
for (s = 0; s < vspaces_count; s++) {
vspaces[s] = ptr_add(data, vspace_offsets[s]);
vspace_deltas[s] = (uptr)data;
}
} else {
data = vspaces[0];
for (s = 0; s < vspaces_count; s++)
vspace_deltas[s] = (uptr)ptr_subtract(vspaces[s], vspace_offsets[s]);
}
vfasl_load_time += UNFIX(S_cputime()) - UNFIX(pre);
pre = S_cputime();
symrefs = table; symrefs = table;
rtdrefs = ptr_add(symrefs, header.symref_count * sizeof(vfoff)); rtdrefs = ptr_add(symrefs, header.symref_count * sizeof(vfoff));
singletonrefs = ptr_add(rtdrefs, header.rtdref_count * sizeof(vfoff)); singletonrefs = ptr_add(rtdrefs, header.rtdref_count * sizeof(vfoff));
@ -213,21 +320,50 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
header.rtd_end_offset - header.rtd_offset, header.rtd_end_offset - header.rtd_offset,
header.closure_end_offset - header.closure_offset, header.closure_end_offset - header.closure_offset,
header.code_end_offset - header.code_offset, header.code_end_offset - header.code_offset,
header.data_size - header.other_offset, ((header.code_offset - header.closure_end_offset)
+ (header.data_size - header.code_end_offset)),
header.table_size, header.table_size,
header.symref_count * sizeof(vfoff), header.symref_count * sizeof(vfoff),
header.rtdref_count * sizeof(vfoff), header.rtdref_count * sizeof(vfoff),
header.singletonref_count * sizeof(vfoff)); header.singletonref_count * sizeof(vfoff));
/* Fix up pointers. The content `data` initially has all pointers /* We have to convert an offset relative to the start of data in the
relative to the start of the data, so add the `data` address vfasl format to an offset relative to an individual space, at
to all pointers. */ least for target generations other than 0. Rely on the fact that
the spaces and the references are both sorted. */
#define SPACE_OFFSET_DECLS \
int s2 = 0; \
uptr offset2 = vspace_offsets[s2]; \
uptr next_offset2 = vspace_offsets[s2+1]
#define INC_SPACE_OFFSET(off) \
do { \
while ((off) >= next_offset2) { \
s2++; \
offset2 = next_offset2; \
next_offset2 = vspace_offsets[s2+1]; \
} \
} while (0)
#define SPACE_PTR(off) ptr_add(vspaces[s2], (off) - offset2)
/* Fix up pointers. The initial content has all pointers relative to
the start of the data. If the data were all still contiguous,
we'd add the `data` address to all pointers. Since the spaces may
be disconnected, though, add `vspace_deltas[s]` for the right
`s`. */
{ {
ptr *p = data; SPACE_OFFSET_DECLS;
uptr p_off = 0;
while (bm != bm_end) { while (bm != bm_end) {
octet m; octet m = *bm;
m = *bm; # define MAYBE_FIXUP(i) \
# define MAYBE_FIXUP(i) if (m & (1 << i)) ((uptr *)p)[i] += (uptr)data if (m & (1 << i)) { \
ptr *p3; \
INC_SPACE_OFFSET(p_off); \
p3 = SPACE_PTR(p_off); \
*p3 = find_pointer_from_offset((uptr)*p3, vspaces, vspace_offsets); \
} \
p_off += sizeof(uptr);
MAYBE_FIXUP(0); MAYBE_FIXUP(0);
MAYBE_FIXUP(1); MAYBE_FIXUP(1);
MAYBE_FIXUP(2); MAYBE_FIXUP(2);
@ -236,8 +372,8 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
MAYBE_FIXUP(5); MAYBE_FIXUP(5);
MAYBE_FIXUP(6); MAYBE_FIXUP(6);
MAYBE_FIXUP(7); MAYBE_FIXUP(7);
# undef MAYBE_FIXUP # undef MAYBE_FIXUP
p += byte_bits;
bm++; bm++;
} }
} }
@ -246,18 +382,22 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
This needs to be before interning symbols, in case "" This needs to be before interning symbols, in case ""
is a symbol name. */ is a symbol name. */
{ {
SPACE_OFFSET_DECLS;
vfoff i; vfoff i;
for (i = 0; i < header.singletonref_count; i++) { for (i = 0; i < header.singletonref_count; i++) {
uptr r_off;
ptr *ref; ptr *ref;
ref = ptr_add(data, singletonrefs[i]); r_off = singletonrefs[i];
INC_SPACE_OFFSET(r_off);
ref = SPACE_PTR(r_off);
*ref = lookup_singleton(UNFIX(*ref)); *ref = lookup_singleton(UNFIX(*ref));
} }
} }
/* Intern symbols */ /* Intern symbols */
{ {
ptr sym = TYPE(data, type_symbol); ptr sym = TYPE(vspaces[vspace_symbol], type_symbol);
ptr end_syms = TYPE(ptr_add(data, header.sym_end_offset), type_symbol); ptr end_syms = TYPE(ptr_add(vspaces[vspace_symbol], header.sym_end_offset), type_symbol);
if (sym != end_syms) { if (sym != end_syms) {
tc_mutex_acquire() tc_mutex_acquire()
@ -283,12 +423,15 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
/* Replace symbol references with interned references */ /* Replace symbol references with interned references */
{ {
ptr syms = data; SPACE_OFFSET_DECLS;
ptr syms = vspaces[vspace_symbol];
vfoff i; vfoff i;
for (i = 0; i < header.symref_count; i++) { for (i = 0; i < header.symref_count; i++) {
uptr sym_pos; uptr p2_off, sym_pos;
ptr p2, sym, val; ptr p2, sym, val;
p2 = ptr_add(data, symrefs[i]); p2_off = symrefs[i];
INC_SPACE_OFFSET(p2_off);
p2 = SPACE_PTR(p2_off);
sym_pos = UNFIX(*(ptr **)p2); sym_pos = UNFIX(*(ptr **)p2);
sym = TYPE(ptr_add(syms, sym_pos * size_symbol), type_symbol); sym = TYPE(ptr_add(syms, sym_pos * size_symbol), type_symbol);
if ((val = SYMVAL(sym)) != sunbound) if ((val = SYMVAL(sym)) != sunbound)
@ -299,9 +442,10 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
/* Intern rtds */ /* Intern rtds */
if (header.rtd_offset < header.rtd_end_offset) { if (header.rtd_offset < header.rtd_end_offset) {
ptr rtd = TYPE(ptr_add(data, header.rtd_offset), type_typed_object); ptr rtd = TYPE(ptr_add(vspaces[vspace_rtd], header.rtd_offset - vspace_offsets[vspace_rtd]),
ptr rtd_end = TYPE(ptr_add(data, header.rtd_end_offset), type_typed_object); type_typed_object);
ptr rtd_end = ptr_add(rtd, header.rtd_end_offset - header.rtd_offset);
/* first one corresponds to base_rtd */ /* first one corresponds to base_rtd */
RECORDINSTTYPE(rtd) = S_G.base_rtd; RECORDINSTTYPE(rtd) = S_G.base_rtd;
RECORDDESCUID(rtd) = S_G.base_rtd; RECORDDESCUID(rtd) = S_G.base_rtd;
@ -315,7 +459,7 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
RECORDINSTTYPE(rtd) = S_G.base_rtd; RECORDINSTTYPE(rtd) = S_G.base_rtd;
/* fixup type and parent before continuing, relying on parents being earlier in `rtd`s */ /* fixup parent before continuing, relying on parents being earlier in `rtd`s */
parent_rtd = RECORDDESCPARENT(rtd); parent_rtd = RECORDDESCPARENT(rtd);
if (parent_rtd != Sfalse) { if (parent_rtd != Sfalse) {
ptr parent_uid = RECORDDESCUID(parent_rtd); ptr parent_uid = RECORDDESCUID(parent_rtd);
@ -337,10 +481,14 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
/* Replace rtd references to interned references */ /* Replace rtd references to interned references */
{ {
SPACE_OFFSET_DECLS;
vfoff i; vfoff i;
for (i = 0; i < header.rtdref_count; i++) { for (i = 0; i < header.rtdref_count; i++) {
uptr r_off;
ptr *ref, rtd, uid; ptr *ref, rtd, uid;
ref = ptr_add(data, rtdrefs[i]); r_off = rtdrefs[i];
INC_SPACE_OFFSET(r_off);
ref = SPACE_PTR(r_off);
rtd = *ref; rtd = *ref;
uid = RECORDDESCUID(rtd); uid = RECORDDESCUID(rtd);
if (!Ssymbolp(uid)) { if (!Ssymbolp(uid)) {
@ -352,35 +500,38 @@ ptr S_vfasl(ptr bv, void *stream, iptr input_len)
/* Fix code pointers on closures */ /* Fix code pointers on closures */
{ {
ptr cl = TYPE(ptr_add(data, header.closure_offset), type_closure); ptr cl = TYPE(ptr_add(vspaces[vspace_closure], header.closure_offset - vspace_offsets[vspace_closure]),
ptr end_closures = TYPE(ptr_add(data, header.closure_end_offset), type_closure); type_closure);
ptr end_closures = ptr_add(cl, header.closure_end_offset - header.closure_offset);
uptr code_delta = vspace_deltas[vspace_code];
while (cl != end_closures) { while (cl != end_closures) {
ptr code = CLOSCODE(cl); ptr code = CLOSCODE(cl);
code = ptr_add(code, (uptr)data); code = ptr_add(code, code_delta);
SETCLOSCODE(cl,code); SETCLOSCODE(cl,code);
cl = ptr_add(cl, size_closure(CLOSLEN(cl))); cl = ptr_add(cl, size_closure(CLOSLEN(cl)));
} }
} }
/* Fix code via relocations */ /* Fix code via relocations */
{ {
ptr sym_base = vspaces[vspace_symbol];
ptr sym_base = data; ptr code = TYPE(vspaces[vspace_code], type_typed_object);
ptr code = TYPE(ptr_add(data, header.code_offset), type_typed_object); ptr code_end = ptr_add(code, header.code_end_offset - header.code_offset);
ptr code_end = TYPE(ptr_add(data, header.code_end_offset), type_typed_object);
while (code != code_end) { while (code != code_end) {
relink_code(code, sym_base, data); relink_code(code, sym_base, vspaces, vspace_offsets, to_static);
code = ptr_add(code, size_code(CODELEN(code))); code = ptr_add(code, size_code(CODELEN(code)));
} }
} }
vfasl_fix_time += UNFIX(S_cputime()) - UNFIX(pre);
/* Turn result offset into a value, unboxing if it's a box (which /* Turn result offset into a value, unboxing if it's a box (which
supports a symbol result, for example). */ supports a symbol result, for example). */
{ {
ptr v; ptr v;
ITYPE t; ITYPE t;
v = ptr_add(data, header.result_offset); v = find_pointer_from_offset(header.result_offset, vspaces, vspace_offsets);
if (((t = TYPEBITS(v)) == type_typed_object) if (((t = TYPEBITS(v)) == type_typed_object)
&& TYPEP(TYPEFIELD(v), mask_box, type_box)) && TYPEP(TYPEFIELD(v), mask_box, type_box))
v = Sunbox(v); v = Sunbox(v);
@ -394,6 +545,53 @@ ptr S_vfasl_to(ptr bv)
return S_vfasl(bv, (ptr)0, Sbytevector_length(bv)); return S_vfasl(bv, (ptr)0, Sbytevector_length(bv));
} }
/************************************************************/
/* Saving */
static void vfasl_init(vfasl_info *vfi) {
int s;
vfi->base_addr = (ptr)0;
vfi->sym_count = 0;
vfi->symref_count = 0;
vfi->symrefs = (ptr)0;
vfi->base_rtd = S_G.base_rtd;
vfi->rtdref_count = 0;
vfi->rtdrefs = (ptr)0;
vfi->singletonref_count = 0;
vfi->singletonrefs = (ptr)0;
vfi->graph = make_vfasl_hash_table();
vfi->ptr_bitmap = (ptr)0;
vfi->installs_library_entry = 0;
for (s = 0; s < vspaces_count; s++) {
vfasl_chunk *c;
c = malloc(sizeof(vfasl_chunk));
c->bytes = (ptr)0;
c->length = 0;
c->used = 0;
c->swept = 0;
c->next = (ptr)0;
vfi->spaces[s].first = c;
vfi->spaces[s].total_bytes = 0;
}
}
static void vfasl_free_chunks(vfasl_info *vfi) {
int s;
for (s = 0; s < vspaces_count; s++) {
vfasl_chunk *c, *next;
for (c = vfi->spaces[s].first; c; c = next) {
next = c->next;
if (c->bytes)
free(c->bytes);
free(c);
}
}
}
ptr S_to_vfasl(ptr v) ptr S_to_vfasl(ptr v)
{ {
vfasl_info *vfi; vfasl_info *vfi;
@ -420,44 +618,13 @@ ptr S_to_vfasl(ptr v)
vfi = malloc(sizeof(vfasl_info)); vfi = malloc(sizeof(vfasl_info));
vfi->base_addr = (ptr)0; vfasl_init(vfi);
vfi->sym_count = 0;
vfi->symref_count = 0;
vfi->symrefs = (ptr)0;
vfi->base_rtd = S_G.base_rtd;
vfi->rtdref_count = 0;
vfi->rtdrefs = (ptr)0;
vfi->singletonref_count = 0;
vfi->singletonrefs = (ptr)0;
vfi->graph = make_vfasl_hash_table();
vfi->ptr_bitmap = (ptr)0;
/* First pass: determine sizes */ /* First pass: determine sizes */
for (s = 0; s < vspaces_count; s++) {
vfasl_chunk *c;
c = malloc(sizeof(vfasl_chunk));
c->bytes = (ptr)0;
c->length = 0;
c->used = 0;
c->swept = 0;
c->next = (ptr)0;
vfi->spaces[s].first = c;
vfi->spaces[s].total_bytes = 0;
}
(void)vfasl_copy_all(vfi, v); (void)vfasl_copy_all(vfi, v);
for (s = 0; s < vspaces_count; s++) { vfasl_free_chunks(vfi);
vfasl_chunk *c, *next;
for (c = vfi->spaces[s].first; c; c = next) {
next = c->next;
free(c->bytes);
free(c);
}
}
free_vfasl_hash_table(vfi->graph); free_vfasl_hash_table(vfi->graph);
@ -480,8 +647,12 @@ ptr S_to_vfasl(ptr v)
header.rtd_offset = vfi->spaces[vspace_symbol].total_bytes; header.rtd_offset = vfi->spaces[vspace_symbol].total_bytes;
header.closure_offset = header.rtd_offset + vfi->spaces[vspace_rtd].total_bytes; header.closure_offset = header.rtd_offset + vfi->spaces[vspace_rtd].total_bytes;
header.code_offset = header.closure_offset + vfi->spaces[vspace_closure].total_bytes; header.impure_offset = header.closure_offset + vfi->spaces[vspace_closure].total_bytes;
header.other_offset = header.code_offset + vfi->spaces[vspace_code].total_bytes; header.pure_typed_offset = header.impure_offset + vfi->spaces[vspace_impure].total_bytes;
header.impure_record_offset = header.pure_typed_offset + vfi->spaces[vspace_pure_typed].total_bytes;
header.code_offset = header.impure_record_offset + vfi->spaces[vspace_impure_record].total_bytes;
header.data_offset = header.code_offset + vfi->spaces[vspace_code].total_bytes;
header.reloc_offset = header.data_offset + vfi->spaces[vspace_data].total_bytes;
header.symref_count = vfi->symref_count; header.symref_count = vfi->symref_count;
header.rtdref_count = vfi->rtdref_count; header.rtdref_count = vfi->rtdref_count;
@ -503,7 +674,7 @@ ptr S_to_vfasl(ptr v)
vfi->base_addr = p; vfi->base_addr = p;
/* Set pointers to vspaces based on sizes frm first pass */ /* Set pointers to vspaces based on sizes from first pass */
for (s = 0; s < vspaces_count; s++) { for (s = 0; s < vspaces_count; s++) {
vfasl_chunk *c; vfasl_chunk *c;
@ -585,10 +756,11 @@ ptr S_to_vfasl(ptr v)
sort_offsets(vfi->symrefs, vfi->symref_count); sort_offsets(vfi->symrefs, vfi->symref_count);
sort_offsets(vfi->rtdrefs, vfi->rtdref_count); sort_offsets(vfi->rtdrefs, vfi->rtdref_count);
sort_offsets(vfi->singletonrefs, vfi->singletonref_count); sort_offsets(vfi->singletonrefs, vfi->singletonref_count);
for (s = 0; s < vspaces_count; s++) { for (s = 0; s < vspaces_count; s++) {
free(vfi->spaces[s].first); free(vfi->spaces[s].first->bytes = (ptr)0);
} }
vfasl_free_chunks(vfi);
free_vfasl_hash_table(vfi->graph); free_vfasl_hash_table(vfi->graph);
@ -597,6 +769,41 @@ ptr S_to_vfasl(ptr v)
return bv; return bv;
} }
/* If compiled code uses `$install-library-entry`, then it can't be
combined into a single vfasled object, because the installation
needs to be evaluated for laster vfasls. Recognize a non-combinable
value as anything that references the C entry or even mentions the
symbol `$install-library-entry` (as defined in "library.ss"). If
non-boot code mentions the symbol `$install-library-entry`, it just
isn't as optimal.
This is an expensive test, since we perform half of a vfasl
encoding to look for `$install-library-entry`. */
IBOOL S_vfasl_can_combinep(ptr v)
{
IBOOL installs;
vfasl_info *vfi;
fasl_init_entry_tables();
/* Run a "first pass" */
vfi = malloc(sizeof(vfasl_info));
vfasl_init(vfi);
(void)vfasl_copy_all(vfi, v);
vfasl_free_chunks(vfi);
free_vfasl_hash_table(vfi->graph);
installs = vfi->installs_library_entry;
free(vfi);
return !installs;
}
/************************************************************/
/* Traversals for saving */
static ptr vfasl_copy_all(vfasl_info *vfi, ptr v) { static ptr vfasl_copy_all(vfasl_info *vfi, ptr v) {
seginfo *si; seginfo *si;
int s; int s;
@ -628,7 +835,7 @@ static ptr vfasl_copy_all(vfasl_info *vfi, ptr v) {
pp = ptr_add(pp, sweep(vfi, TYPE((ptr)pp, type_closure))); pp = ptr_add(pp, sweep(vfi, TYPE((ptr)pp, type_closure)));
} }
break; break;
case vspace_array: case vspace_impure:
while (pp < pp_end) { while (pp < pp_end) {
vfasl_relocate(vfi, pp); vfasl_relocate(vfi, pp);
pp = ptr_add(pp, sizeof(ptr)); pp = ptr_add(pp, sizeof(ptr));
@ -636,7 +843,8 @@ static ptr vfasl_copy_all(vfasl_info *vfi, ptr v) {
break; break;
case vspace_rtd: case vspace_rtd:
case vspace_code: case vspace_code:
case vspace_typed: case vspace_pure_typed:
case vspace_impure_record:
while (pp < pp_end) { while (pp < pp_end) {
pp = ptr_add(pp, sweep(vfi, TYPE((ptr)pp, type_typed_object))); pp = ptr_add(pp, sweep(vfi, TYPE((ptr)pp, type_typed_object)));
} }
@ -759,8 +967,14 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
} }
s = vspace_rtd; s = vspace_rtd;
} else } else {
s = vspace_typed; /* See gc.c for original rationale but the fine-grained
choices only matter when loading into the static
generation, so we make */
s = (RECORDDESCMPM(rtd) == FIX(0)
? vspace_pure_typed
: vspace_impure_record);
}
n = size_record_inst(UNFIX(RECORDDESCSIZE(rtd))); n = size_record_inst(UNFIX(RECORDDESCSIZE(rtd)));
@ -773,8 +987,10 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
iptr len, n; iptr len, n;
len = Svector_length(pp); len = Svector_length(pp);
n = size_vector(len); n = size_vector(len);
FIND_ROOM(vfi, vspace_typed, type_typed_object, n, p); FIND_ROOM(vfi, vspace_impure, type_typed_object, n, p);
copy_ptrs(type_typed_object, p, pp, n); copy_ptrs(type_typed_object, p, pp, n);
/* pad if necessary */
if ((len & 1) == 0) INITVECTIT(p, len) = FIX(0);
} else if (TYPEP(tf, mask_string, type_string)) { } else if (TYPEP(tf, mask_string, type_string)) {
iptr n; iptr n;
n = size_string(Sstring_length(pp)); n = size_string(Sstring_length(pp));
@ -794,19 +1010,27 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
vfasl_fail(vfi, "tlc"); vfasl_fail(vfi, "tlc");
return (ptr)0; return (ptr)0;
} else if (TYPEP(tf, mask_box, type_box)) { } else if (TYPEP(tf, mask_box, type_box)) {
FIND_ROOM(vfi, vspace_typed, type_typed_object, size_box, p); FIND_ROOM(vfi, vspace_impure, type_typed_object, size_box, p);
BOXTYPE(p) = (iptr)tf; BOXTYPE(p) = (iptr)tf;
INITBOXREF(p) = Sunbox(pp); INITBOXREF(p) = Sunbox(pp);
} else if ((iptr)tf == type_ratnum) { } else if ((iptr)tf == type_ratnum) {
FIND_ROOM(vfi, vspace_typed, type_typed_object, size_ratnum, p); /* note: vspace_impure is suboptimal for loading into static
generation, but these will be rare in boot code */
FIND_ROOM(vfi, vspace_impure, type_typed_object, size_ratnum, p);
RATTYPE(p) = type_ratnum; RATTYPE(p) = type_ratnum;
RATNUM(p) = RATNUM(pp); RATNUM(p) = RATNUM(pp);
RATDEN(p) = RATDEN(pp); RATDEN(p) = RATDEN(pp);
/* pad */
((void **)UNTYPE(p, type_typed_object))[3] = (ptr)0;
} else if ((iptr)tf == type_exactnum) { } else if ((iptr)tf == type_exactnum) {
FIND_ROOM(vfi, vspace_typed, type_typed_object, size_exactnum, p); /* note: vspace_impure is suboptimal for loading into static
generation, but these will be rare in boot code */
FIND_ROOM(vfi, vspace_impure, type_typed_object, size_exactnum, p);
EXACTNUM_TYPE(p) = type_exactnum; EXACTNUM_TYPE(p) = type_exactnum;
EXACTNUM_REAL_PART(p) = EXACTNUM_REAL_PART(pp); EXACTNUM_REAL_PART(p) = EXACTNUM_REAL_PART(pp);
EXACTNUM_IMAG_PART(p) = EXACTNUM_IMAG_PART(pp); EXACTNUM_IMAG_PART(p) = EXACTNUM_IMAG_PART(pp);
/* pad */
((void **)UNTYPE(p, type_typed_object))[3] = (ptr)0;
} else if ((iptr)tf == type_inexactnum) { } else if ((iptr)tf == type_inexactnum) {
FIND_ROOM(vfi, vspace_data, type_typed_object, size_inexactnum, p); FIND_ROOM(vfi, vspace_data, type_typed_object, size_inexactnum, p);
INEXACTNUM_TYPE(p) = type_inexactnum; INEXACTNUM_TYPE(p) = type_inexactnum;
@ -825,17 +1049,8 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
n = size_code(CODELEN(pp)); n = size_code(CODELEN(pp));
FIND_ROOM(vfi, vspace_code, type_typed_object, n, p); FIND_ROOM(vfi, vspace_code, type_typed_object, n, p);
copy_ptrs(type_typed_object, p, pp, n); copy_ptrs(type_typed_object, p, pp, n);
if (CODERELOC(pp) == (ptr)0) { if (CODERELOC(pp) == (ptr)0)
/* We only get here if we're vfasling code that belongs in vfasl_fail(vfi, "code without relocation");
the static generation. */
ptr l; iptr ln;
ln = size_reloc_table(0);
FIND_ROOM(vfi, vspace_reloc, typemod, ln, l);
RELOCSIZE(l) = 0;
RELOCCODE(l) = p;
CODERELOC(p) = l;
vfasl_register_pointer(vfi, &CODERELOC(p));
}
} else if ((iptr)tf == type_rtd_counts) { } else if ((iptr)tf == type_rtd_counts) {
/* prune counts, since GC will recreate as needed */ /* prune counts, since GC will recreate as needed */
return Sfalse; return Sfalse;
@ -854,7 +1069,7 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
vfasl_fail(vfi, "weakpair"); vfasl_fail(vfi, "weakpair");
return (ptr)0; return (ptr)0;
} else { } else {
FIND_ROOM(vfi, vspace_array, type_pair, size_pair, p); FIND_ROOM(vfi, vspace_impure, type_pair, size_pair, p);
} }
INITCAR(p) = Scar(pp); INITCAR(p) = Scar(pp);
INITCDR(p) = Scdr(pp); INITCDR(p) = Scdr(pp);
@ -864,6 +1079,9 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
if (CODETYPE(code) & (code_flag_continuation << code_flags_offset)) { if (CODETYPE(code) & (code_flag_continuation << code_flags_offset)) {
vfasl_fail(vfi, "continuation"); vfasl_fail(vfi, "continuation");
return (ptr)0; return (ptr)0;
} else if (CODETYPE(code) & (code_flag_mutable_closure << code_flags_offset)) {
vfasl_fail(vfi, "mutable closure");
return (ptr)0;
} else { } else {
iptr len, n; iptr len, n;
len = CLOSLEN(pp); len = CLOSLEN(pp);
@ -880,6 +1098,8 @@ static ptr copy(vfasl_info *vfi, ptr pp, seginfo *si) {
INITSYMSPLIST(p) = Snil; INITSYMSPLIST(p) = Snil;
INITSYMNAME(p) = SYMNAME(pp); INITSYMNAME(p) = SYMNAME(pp);
INITSYMHASH(p) = SYMHASH(pp); INITSYMHASH(p) = SYMHASH(pp);
if (Sstringp(SYMNAME(pp)))
vfasl_check_install_library_entry(vfi, SYMNAME(pp));
} else if (t == type_flonum) { } else if (t == type_flonum) {
FIND_ROOM(vfi, vspace_data, type_flonum, size_flonum, p); FIND_ROOM(vfi, vspace_data, type_flonum, size_flonum, p);
FLODAT(p) = FLODAT(pp); FLODAT(p) = FLODAT(pp);
@ -1062,6 +1282,10 @@ static uptr sweep_record(vfasl_info *vfi, ptr x)
return size_record_inst(UNFIX(RECORDDESCSIZE(rtd))); return size_record_inst(UNFIX(RECORDDESCSIZE(rtd)));
} }
/*************************************************************/
/* Code and relocation handling for save and load */
#define VFASL_RELOC_TAG_BITS 3 #define VFASL_RELOC_TAG_BITS 3
#define VFASL_RELOC_C_ENTRY_TAG 1 #define VFASL_RELOC_C_ENTRY_TAG 1
@ -1116,6 +1340,8 @@ static uptr sweep_code_object(vfasl_info *vfi, ptr co) {
if ((which_singleton = detect_singleton(obj))) { if ((which_singleton = detect_singleton(obj))) {
obj = FIX(VFASL_RELOC_SINGLETON(which_singleton)); obj = FIX(VFASL_RELOC_SINGLETON(which_singleton));
} else if ((pos = vfasl_hash_table_ref(S_G.c_entries, obj))) { } else if ((pos = vfasl_hash_table_ref(S_G.c_entries, obj))) {
if ((uptr)pos == CENTRY_install_library_entry)
vfi->installs_library_entry = 1;
obj = FIX(VFASL_RELOC_C_ENTRY(pos)); obj = FIX(VFASL_RELOC_C_ENTRY(pos));
} else if ((pos = vfasl_hash_table_ref(S_G.library_entries, obj))) { } else if ((pos = vfasl_hash_table_ref(S_G.library_entries, obj))) {
obj = FIX(VFASL_RELOC_LIBRARY_ENTRY(pos)); obj = FIX(VFASL_RELOC_LIBRARY_ENTRY(pos));
@ -1133,29 +1359,35 @@ static uptr sweep_code_object(vfasl_info *vfi, ptr co) {
obj = (ptr)ptr_diff(obj, vfi->base_addr); obj = (ptr)ptr_diff(obj, vfi->base_addr);
} }
S_set_code_obj("vfasl", RELOC_TYPE(entry) | reloc_force_abs, co, a, obj, item_off); S_set_code_obj("vfasl", reloc_abs, co, a, obj, item_off);
} }
RELOCCODE(t) = co; RELOCCODE(t) = (ptr)ptr_diff(co, vfi->base_addr);
CODERELOC(co) = t; CODERELOC(co) = (ptr)ptr_diff(t, vfi->base_addr);
/* no vfasl_register_pointer, since relink_code can handle it */
vfasl_register_pointer(vfi, &RELOCCODE(t));
vfasl_register_pointer(vfi, &CODERELOC(co));
return size_code(CODELEN(co)); return size_code(CODELEN(co));
} }
static void relink_code(ptr co, ptr sym_base, ptr dest_base) { static void relink_code(ptr co, ptr sym_base, ptr *vspaces, uptr *vspace_offsets, IBOOL to_static) {
ptr t; iptr a, m, n; ptr t; iptr a, m, n;
t = CODERELOC(co); t = CODERELOC(co);
t = ptr_add(vspaces[vspace_reloc], (uptr)t - vspace_offsets[vspace_reloc]);
if (to_static)
CODERELOC(co) = (ptr)0;
else {
CODERELOC(co) = t;
RELOCCODE(t) = co;
}
m = RELOCSIZE(t); m = RELOCSIZE(t);
a = 0; a = 0;
n = 0; n = 0;
while (n < m) { while (n < m) {
uptr entry, item_off, code_off; ptr obj; uptr entry, item_off, code_off; ptr obj;
entry = RELOCIT(t, n); n += 1; entry = RELOCIT(t, n); n += 1;
if (RELOC_EXTENDED_FORMAT(entry)) { if (RELOC_EXTENDED_FORMAT(entry)) {
item_off = RELOCIT(t, n); n += 1; item_off = RELOCIT(t, n); n += 1;
@ -1165,7 +1397,7 @@ static void relink_code(ptr co, ptr sym_base, ptr dest_base) {
code_off = RELOC_CODE_OFFSET(entry); code_off = RELOC_CODE_OFFSET(entry);
} }
a += code_off; a += code_off;
obj = S_get_code_obj(RELOC_TYPE(entry) | reloc_force_abs, co, a, item_off); obj = S_get_code_obj(reloc_abs, co, a, item_off);
if (IMMEDIATE(obj)) { if (IMMEDIATE(obj)) {
if (Sfixnump(obj)) { if (Sfixnump(obj)) {
@ -1193,7 +1425,8 @@ static void relink_code(ptr co, ptr sym_base, ptr dest_base) {
} }
} else { } else {
uptr offset = (uptr)obj; uptr offset = (uptr)obj;
obj = ptr_add(dest_base, offset);
obj = find_pointer_from_offset(offset, vspaces, vspace_offsets);
if ((TYPEBITS(obj) == type_typed_object) if ((TYPEBITS(obj) == type_typed_object)
&& (TYPEFIELD(obj) == S_G.base_rtd)) { && (TYPEFIELD(obj) == S_G.base_rtd)) {
/* Similar to symbols: potentially replace with interned */ /* Similar to symbols: potentially replace with interned */
@ -1209,6 +1442,18 @@ static void relink_code(ptr co, ptr sym_base, ptr dest_base) {
} }
} }
static ptr find_pointer_from_offset(uptr p_off, ptr *vspaces, uptr *vspace_offsets)
{
int s = 0;
ITYPE t = TYPEBITS(p_off);
p_off = (uptr)UNTYPE(p_off, t);
while (p_off >= vspace_offsets[s+1])
s++;
return TYPE(ptr_add(vspaces[s], p_off - vspace_offsets[s]), t);
}
/*************************************************************/ /*************************************************************/
static void fasl_init_entry_tables() static void fasl_init_entry_tables()
@ -1239,6 +1484,20 @@ static void fasl_init_entry_tables()
tc_mutex_release() tc_mutex_release()
} }
static void vfasl_check_install_library_entry(vfasl_info *vfi, ptr name)
{
const char *ile = "$install-library-entry";
iptr len = Sstring_length(name), i;
for (i = 0; i < len; i++) {
if (Sstring_ref(name, i) != (unsigned)ile[i])
return;
}
if (!ile[i])
vfi->installs_library_entry = 1;
}
/*************************************************************/ /*************************************************************/
static int detect_singleton(ptr p) { static int detect_singleton(ptr p) {

View File

@ -1614,7 +1614,8 @@
(do-make-boot-header who out machine bootfiles))) (do-make-boot-header who out machine bootfiles)))
(set-who! vfasl-convert-file (set-who! vfasl-convert-file
(let ([->vfasl (foreign-procedure "(cs)to_vfasl" (scheme-object) scheme-object)]) (let ([->vfasl (foreign-procedure "(cs)to_vfasl" (scheme-object) scheme-object)]
[vfasl-can-combine? (foreign-procedure "(cs)vfasl_can_combinep" (scheme-object) boolean)])
(lambda (in-file out-file bootfile*) (lambda (in-file out-file bootfile*)
(let ([op ($open-file-output-port who out-file (let ([op ($open-file-output-port who out-file
(if (compile-compressed) (if (compile-compressed)
@ -1626,15 +1627,28 @@
(emit-boot-header op (constant machine-type) bootfile*)) (emit-boot-header op (constant machine-type) bootfile*))
(let ([ip ($open-file-input-port who in-file (file-options compressed))]) (let ([ip ($open-file-input-port who in-file (file-options compressed))])
(on-reset (close-port ip) (on-reset (close-port ip)
(let loop () (let* ([write-out (lambda (x)
(let ([x (fasl-read ip)]) (emit-header op (constant machine-type))
(unless (eof-object? x) (let ([bv (->vfasl x)])
(emit-header op (constant machine-type)) (put-u8 op (constant fasl-type-vfasl-size))
(let ([bv (->vfasl x)]) (put-uptr op (bytevector-length bv))
(put-u8 op (constant fasl-type-vfasl-size)) (put-bytevector op bv)))]
(put-uptr op (bytevector-length bv)) [write-out-accum (lambda (accum)
(put-bytevector op bv)) (unless (null? accum)
(loop)))) (write-out (list->vector (reverse accum)))))])
(let loop ([accum '()])
(let ([x (fasl-read ip)])
(cond
[(eof-object? x)
(write-out-accum accum)]
[(not (vfasl-can-combine? x))
(write-out-accum accum)
(write-out x)
(loop '())]
[(vector? x)
(loop (append (reverse (vector->list x)) accum))]
[else
(loop (cons x accum))]))))
(close-port ip))) (close-port ip)))
(close-port op)))))))) (close-port op))))))))

View File

@ -74,6 +74,7 @@
($hand-coded 'nonprocedure-code))) ($hand-coded 'nonprocedure-code)))
(define $foreign-entry ($hand-coded '$foreign-entry-procedure)) (define $foreign-entry ($hand-coded '$foreign-entry-procedure))
;; The name `$install-library-entry` is special to `vfasl-can-combine?`
(define $install-library-entry (define $install-library-entry
($hand-coded '$install-library-entry-procedure)) ($hand-coded '$install-library-entry-procedure))