GC now scans literal data area

slava 2006-08-09 20:15:27 +00:00
parent af1dcf3990
commit 3b2d14c4c0
8 changed files with 354 additions and 333 deletions

View File

@ -27,6 +27,7 @@ endif
OBJS = $(PLAF_OBJS) \
vm/alien.o \
vm/bignum.o \
vm/compiler.o \
vm/debug.o \
vm/factor.o \
vm/ffi_test.o \

275
vm/compiler.c Normal file
View File

@ -0,0 +1,275 @@
#include "factor.h"
void iterate_code_heap(CELL start, CELL end, CODE_HEAP_ITERATOR iter)
{
while(start < end)
{
F_COMPILED *compiled = (F_COMPILED *)start;
CELL code_start = start + sizeof(F_COMPILED);
CELL reloc_start = code_start + compiled->code_length;
CELL literal_start = reloc_start + compiled->reloc_length;
CELL literal_end = literal_start + compiled->literal_length;
iter(compiled,code_start,reloc_start,literal_start,literal_end);
start = literal_end;
}
}
void undefined_symbol(void)
{
general_error(ERROR_UNDEFINED_SYMBOL,F,F,true);
}
#define LITERAL_REF(literal_start,num) ((literal_start) + CELLS * (num))
INLINE CELL get_literal(CELL literal_start, CELL num)
{
if(!literal_start)
critical_error("Only RT_LABEL relocations can appear in the label-relocation-table",0);
return get(LITERAL_REF(literal_start,num));
}
CELL get_rel_symbol(F_REL *rel, CELL literal_start)
{
CELL arg = REL_ARGUMENT(rel);
F_ARRAY *pair = untag_array(get_literal(literal_start,arg));
F_STRING *symbol = untag_string(get(AREF(pair,0)));
CELL library = get(AREF(pair,1));
DLL *dll = (library == F ? NULL : untag_dll(library));
if(dll != NULL && !dll->dll)
return (CELL)undefined_symbol;
CELL sym = (CELL)ffi_dlsym(dll,symbol,false);
if(!sym)
return (CELL)undefined_symbol;
return sym;
}
CELL get_rel_word(F_REL *rel, CELL literal_start)
{
CELL arg = REL_ARGUMENT(rel);
F_WORD *word = untag_word(get_literal(literal_start,arg));
return (CELL)word->xt;
}
INLINE CELL compute_code_rel(F_REL *rel,
CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
CELL offset = rel->offset + code_start;
F_ARRAY *array;
switch(REL_TYPE(rel))
{
case RT_PRIMITIVE:
return primitive_to_xt(REL_ARGUMENT(rel));
case RT_DLSYM:
return get_rel_symbol(rel,literal_start);
case RT_HERE:
return offset;
case RT_CARDS:
return cards_offset;
case RT_LITERAL:
return LITERAL_REF(literal_start,REL_ARGUMENT(rel));
case RT_WORD:
return get_rel_word(rel,literal_start);
case RT_LABEL:
if(labels == NULL)
critical_error("RT_LABEL can only appear in label-relocation-table",0);
array = untag_array_fast(labels->array);
return to_cell(get(AREF(array,REL_ARGUMENT(rel))))
+ code_start;
default:
critical_error("Unsupported rel type",rel->type);
return -1;
}
}
INLINE void reloc_set_2_2(CELL cell, CELL value)
{
put(cell - CELLS,((get(cell - CELLS) & ~0xffff) | ((value >> 16) & 0xffff)));
put(cell,((get(cell) & ~0xffff) | (value & 0xffff)));
}
void apply_relocation(F_REL *rel, CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
CELL original;
CELL absolute_value;
CELL relative_value;
CELL offset = rel->offset + code_start;
/* to_c_string can fill up the heap */
maybe_gc(0);
absolute_value = compute_code_rel(rel,code_start,literal_start,labels);
relative_value = absolute_value - offset;
switch(REL_CLASS(rel))
{
case REL_ABSOLUTE_CELL:
put(offset,absolute_value);
break;
case REL_ABSOLUTE:
*(u32*)offset = absolute_value;
break;
case REL_RELATIVE:
*(u32*)offset = relative_value - sizeof(u32);
break;
case REL_ABSOLUTE_2_2:
reloc_set_2_2(offset,absolute_value);
break;
case REL_RELATIVE_2_2:
reloc_set_2_2(offset,relative_value);
break;
case REL_RELATIVE_2:
original = *(u32*)offset;
original &= ~REL_RELATIVE_2_MASK;
*(u32*)offset = (original | relative_value);
break;
case REL_RELATIVE_3:
original = *(u32*)offset;
original &= ~REL_RELATIVE_3_MASK;
*(u32*)offset = (original | relative_value);
break;
default:
critical_error("Unsupported rel class",REL_CLASS(rel));
return;
}
}
void finalize_code_block(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literal_start, CELL literal_end)
{
F_REL *rel = (F_REL *)reloc_start;
F_REL *rel_end = (F_REL *)literal_start;
/* apply relocations */
while(rel < rel_end)
apply_relocation(rel++,code_start,literal_start,NULL);
}
void collect_literals_step(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literal_start, CELL literal_end)
{
CELL scan;
for(scan = literal_start; scan < literal_end; scan += CELLS)
copy_handle((CELL*)scan);
}
void collect_literals(void)
{
iterate_code_heap(compiling.base,compiling.here,collect_literals_step);
}
void init_compiler(CELL size)
{
compiling.base = compiling.here
= (CELL)(alloc_bounded_block(size)->start);
if(compiling.base == 0)
fatal_error("Cannot allocate code heap",size);
compiling.limit = compiling.base + size;
last_flush = compiling.base;
}
void deposit_vector(F_VECTOR *vector, CELL format)
{
CELL count = untag_fixnum_fast(vector->top);
F_ARRAY *array = untag_array_fast(vector->array);
CELL i;
if(format == 1)
{
for(i = 0; i < count; i++)
cput(compiling.here + i,to_fixnum(get(AREF(array,i))));
}
else if(format == CELLS)
{
CELL dest = compiling.here;
for(i = 0; i < count; i++)
{
put(dest,to_fixnum(get(AREF(array,i))));
dest += CELLS;
}
}
else
fatal_error("Bad format param to deposit_vector()",format);
compiling.here += count * format;
}
void fixup_labels(F_VECTOR *label_rel, CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
F_ARRAY *array = untag_array_fast(label_rel->array);
CELL length = untag_fixnum_fast(label_rel->top);
CELL i;
for(i = 0; i < length; i += 2)
{
F_REL rel;
rel.type = to_cell(get(AREF(array,i)));
rel.offset = to_cell(get(AREF(array,i + 1)));
apply_relocation(&rel,code_start,literal_start,labels);
}
}
void add_compiled_block(CELL code_format, F_VECTOR *code, F_VECTOR *label_rel,
F_VECTOR *labels, F_VECTOR *literals, F_VECTOR *rel)
{
CELL start = compiling.here;
CELL code_length = untag_fixnum_fast(code->top) * code_format;
CELL rel_length = untag_fixnum_fast(rel->top) * CELLS;
CELL literal_length = untag_fixnum_fast(literals->top) * CELLS;
/* compiled header */
F_COMPILED header;
header.code_length = align8(code_length);
header.reloc_length = rel_length;
header.literal_length = literal_length;
memcpy((void*)compiling.here,&header,sizeof(F_COMPILED));
compiling.here += sizeof(F_COMPILED);
/* code */
deposit_vector(code,code_format);
compiling.here = align8(compiling.here);
/* relation info */
deposit_vector(rel,CELLS);
/* literals */
deposit_vector(literals,CELLS);
/* labels */
fixup_labels(label_rel,start + sizeof(F_COMPILED),0,labels);
/* push the XT of the new word on the stack */
box_unsigned_cell(start + sizeof(F_COMPILED));
}
void primitive_add_compiled_block(void)
{
CELL code_format = to_cell(dpop());
F_VECTOR *code = untag_vector(dpop());
F_VECTOR *label_rel = untag_vector(dpop());
F_VECTOR *labels = untag_vector(dpop());
F_VECTOR *literals = untag_vector(dpop());
F_VECTOR *rel = untag_vector(dpop());
add_compiled_block(code_format,code,label_rel,labels,literals,rel);
}
void primitive_finalize_compile(void)
{
flush_icache((void*)last_flush,compiling.here - last_flush);
iterate_code_heap(last_flush,compiling.here,finalize_code_block);
last_flush = compiling.here;
}

68
vm/compiler.h Normal file
View File

@ -0,0 +1,68 @@
/* The compiled code heap is structured into blocks. */
typedef struct
{
CELL code_length; /* # bytes */
CELL reloc_length; /* # bytes */
CELL literal_length; /* # bytes */
} F_COMPILED;
typedef void (*CODE_HEAP_ITERATOR)(F_COMPILED *compiled, CELL code_start,
CELL reloc_start, CELL literal_start, CELL literal_end);
void iterate_code_heap(CELL start, CELL end, CODE_HEAP_ITERATOR iter);
typedef enum {
/* arg is a primitive number */
RT_PRIMITIVE,
/* arg is a literal table index, holding an array pair (symbol/dll) */
RT_DLSYM,
/* store current address here */
RT_HERE,
/* store the offset of the card table from the data heap base */
RT_CARDS,
/* an indirect literal from the word's literal table */
RT_LITERAL,
/* a word */
RT_WORD,
/* a local label */
RT_LABEL
} F_RELTYPE;
#define REL_ABSOLUTE_CELL 0
#define REL_ABSOLUTE 1
#define REL_RELATIVE 2
#define REL_ABSOLUTE_2_2 3
#define REL_RELATIVE_2_2 4
#define REL_RELATIVE_2 5
#define REL_RELATIVE_3 6
#define REL_RELATIVE_2_MASK 0xfffc
#define REL_RELATIVE_3_MASK 0x3fffffc
/* the rel type is built like a cell to avoid endian-specific code in
the compiler */
#define REL_TYPE(r) ((r)->type & 0x000000ff)
#define REL_CLASS(r) (((r)->type & 0x0000ff00) >> 8)
#define REL_ARGUMENT(r) (((r)->type & 0xffff0000) >> 16)
/* code relocation consists of a table of entries for each fixup */
typedef struct {
CELL type;
CELL offset;
} F_REL;
void apply_relocation(F_REL *rel, CELL code_start, CELL literal_start,
F_VECTOR *labels);
void finalize_code_block(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literal_start, CELL literal_end);
void collect_literals(void);
void init_compiler(CELL size);
void primitive_add_compiled_block(void);
CELL last_flush;
void primitive_finalize_compile(void);

View File

@ -25,6 +25,7 @@
#include "types.h"
#include "io.h"
#include "image.h"
#include "compiler.h"
#include "primitives.h"
#include "stack.h"
#include "alien.h"

View File

@ -170,159 +170,20 @@ void relocate_data()
}
}
void undefined_symbol(void)
void relocate_code_block(F_COMPILED *relocating, CELL code_start,
CELL reloc_start, CELL literal_start, CELL literal_end)
{
general_error(ERROR_UNDEFINED_SYMBOL,F,F,true);
}
#define LITERAL_REF(literal_start,num) ((literal_start) + CELLS * (num))
INLINE CELL get_literal(CELL literal_start, CELL num)
{
if(!literal_start)
critical_error("Only RT_LABEL relocations can appear in the label-relocation-table",0);
return get(LITERAL_REF(literal_start,num));
}
CELL get_rel_symbol(F_REL *rel, CELL literal_start)
{
CELL arg = REL_ARGUMENT(rel);
F_ARRAY *pair = untag_array(get_literal(literal_start,arg));
F_STRING *symbol = untag_string(get(AREF(pair,0)));
CELL library = get(AREF(pair,1));
DLL *dll = (library == F ? NULL : untag_dll(library));
CELL sym;
if(dll != NULL && !dll->dll)
return (CELL)undefined_symbol;
sym = (CELL)ffi_dlsym(dll,symbol,false);
if(!sym)
return (CELL)undefined_symbol;
return sym;
}
CELL get_rel_word(F_REL *rel, CELL literal_start)
{
CELL arg = REL_ARGUMENT(rel);
F_WORD *word = untag_word(get_literal(literal_start,arg));
return (CELL)word->xt;
}
INLINE CELL compute_code_rel(F_REL *rel,
CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
CELL offset = rel->offset + code_start;
F_ARRAY *array = untag_array_fast(labels->array);
switch(REL_TYPE(rel))
{
case RT_PRIMITIVE:
return primitive_to_xt(REL_ARGUMENT(rel));
case RT_DLSYM:
return get_rel_symbol(rel,literal_start);
case RT_HERE:
return offset;
case RT_CARDS:
return cards_offset;
case RT_LITERAL:
return LITERAL_REF(literal_start,REL_ARGUMENT(rel));
case RT_WORD:
return get_rel_word(rel,literal_start);
case RT_LABEL:
if(labels == NULL)
critical_error("RT_LABEL can only appear in label-relocation-table",0);
return to_cell(get(AREF(array,REL_ARGUMENT(rel))))
+ code_start;
default:
critical_error("Unsupported rel type",rel->type);
return -1;
}
}
void relocate_code_step(F_REL *rel, CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
CELL original;
CELL absolute_value;
CELL relative_value;
CELL offset = rel->offset + code_start;
/* to_c_string can fill up the heap */
maybe_gc(0);
absolute_value = compute_code_rel(rel,code_start,literal_start,labels);
relative_value = absolute_value - offset;
switch(REL_CLASS(rel))
{
case REL_ABSOLUTE_CELL:
put(offset,absolute_value);
break;
case REL_ABSOLUTE:
*(u32*)offset = absolute_value;
break;
case REL_RELATIVE:
*(u32*)offset = relative_value - sizeof(u32);
break;
case REL_ABSOLUTE_2_2:
reloc_set_2_2(offset,absolute_value);
break;
case REL_RELATIVE_2_2:
reloc_set_2_2(offset,relative_value);
break;
case REL_RELATIVE_2:
original = *(u32*)offset;
original &= ~REL_RELATIVE_2_MASK;
*(u32*)offset = (original | relative_value);
break;
case REL_RELATIVE_3:
original = *(u32*)offset;
original &= ~REL_RELATIVE_3_MASK;
*(u32*)offset = (original | relative_value);
break;
default:
critical_error("Unsupported rel class",REL_CLASS(rel));
return;
}
}
CELL relocate_code_next(CELL relocating)
{
F_COMPILED* compiled = (F_COMPILED*)relocating;
if(compiled->header != COMPILED_HEADER)
critical_error("Wrong compiled header",relocating);
CELL code_start = relocating + sizeof(F_COMPILED);
CELL reloc_start = code_start + compiled->code_length;
CELL literal_start = reloc_start + compiled->reloc_length;
F_REL *rel = (F_REL *)reloc_start;
F_REL *rel_end = (F_REL *)literal_start;
/* apply relocations */
while(rel < rel_end)
relocate_code_step(rel++,code_start,literal_start,NULL);
CELL *scan = (CELL*)literal_start;
CELL *literal_end = (CELL*)(literal_start + compiled->literal_length);
/* relocate literal table data */
while(scan < literal_end)
data_fixup(scan++);
CELL scan;
return (CELL)literal_end;
for(scan = literal_start; scan < literal_end; scan += CELLS)
data_fixup((CELL*)scan);
finalize_code_block(relocating,code_start,reloc_start,
literal_start,literal_end);
}
void relocate_code()
{
/* start relocating from the end of the space reserved for literals */
CELL relocating = compiling.base;
while(relocating < compiling.here)
relocating = relocate_code_next(relocating);
iterate_code_heap(compiling.base,compiling.here,relocate_code_block);
}

View File

@ -41,46 +41,6 @@ INLINE void data_fixup(CELL *cell)
*cell += (tenured.base - data_relocation_base);
}
typedef enum {
/* arg is a primitive number */
RT_PRIMITIVE,
/* arg is a literal table index, holding an array pair (symbol/dll) */
RT_DLSYM,
/* store current address here */
RT_HERE,
/* store the offset of the card table from the data heap base */
RT_CARDS,
/* an indirect literal from the word's literal table */
RT_LITERAL,
/* a word */
RT_WORD,
/* a local label */
RT_LABEL
} F_RELTYPE;
#define REL_ABSOLUTE_CELL 0
#define REL_ABSOLUTE 1
#define REL_RELATIVE 2
#define REL_ABSOLUTE_2_2 3
#define REL_RELATIVE_2_2 4
#define REL_RELATIVE_2 5
#define REL_RELATIVE_3 6
#define REL_RELATIVE_2_MASK 0xfffc
#define REL_RELATIVE_3_MASK 0x3fffffc
/* the rel type is built like a cell to avoid endian-specific code in
the compiler */
#define REL_TYPE(r) ((r)->type & 0x000000ff)
#define REL_CLASS(r) (((r)->type & 0x0000ff00) >> 8)
#define REL_ARGUMENT(r) (((r)->type & 0xffff0000) >> 16)
/* code relocation consists of a table of entries for each fixup */
typedef struct {
CELL type;
CELL offset;
} F_REL;
CELL code_relocation_base;
INLINE void code_fixup(CELL *cell)
@ -89,14 +49,4 @@ INLINE void code_fixup(CELL *cell)
}
void relocate_data();
void relocate_code_step(F_REL *rel, CELL code_start, CELL literal_start,
F_VECTOR *labels);
CELL relocate_code_next(CELL relocating);
void relocate_code();
INLINE void reloc_set_2_2(CELL cell, CELL value)
{
put(cell - CELLS,((get(cell - CELLS) & ~0xffff) | ((value >> 16) & 0xffff)));
put(cell,((get(cell) & ~0xffff) | (value & 0xffff)));
}

116
vm/run.c
View File

@ -274,119 +274,3 @@ void type_error(CELL type, CELL tagged)
{
general_error(ERROR_TYPE,tag_fixnum(type),tagged,true);
}
void init_compiler(CELL size)
{
compiling.base = compiling.here
= (CELL)(alloc_bounded_block(size)->start);
if(compiling.base == 0)
fatal_error("Cannot allocate code heap",size);
compiling.limit = compiling.base + size;
last_flush = compiling.base;
}
void collect_literals(void)
{
/* CELL i;
for(i = compiling.base; i < literal_top; i += CELLS)
copy_handle((CELL*)i); */
}
void deposit_vector(F_VECTOR *vector, CELL format)
{
CELL count = untag_fixnum_fast(vector->top);
F_ARRAY *array = untag_array_fast(vector->array);
CELL i;
if(format == 1)
{
for(i = 0; i < count; i++)
cput(compiling.here + i,to_fixnum(get(AREF(array,i))));
}
else if(format == CELLS)
{
CELL dest = compiling.here;
for(i = 0; i < count; i++)
{
put(dest,to_fixnum(get(AREF(array,i))));
dest += CELLS;
}
}
else
fatal_error("Bad format param to deposit_vector()",format);
compiling.here += count * format;
}
void fixup_labels(F_VECTOR *label_rel, CELL code_start, CELL literal_start,
F_VECTOR *labels)
{
F_ARRAY *array = untag_array_fast(label_rel->array);
CELL length = untag_fixnum_fast(label_rel->top);
CELL i;
for(i = 0; i < length; i += 2)
{
F_REL rel;
rel.type = to_cell(get(AREF(array,i)));
rel.offset = to_cell(get(AREF(array,i + 1)));
relocate_code_step(&rel,code_start,literal_start,labels);
}
}
void add_compiled_block(CELL code_format, F_VECTOR *code, F_VECTOR *label_rel,
F_VECTOR *labels, F_VECTOR *literals, F_VECTOR *rel)
{
CELL start = compiling.here;
CELL code_length = untag_fixnum_fast(code->top) * code_format;
CELL rel_length = untag_fixnum_fast(rel->top) * CELLS;
CELL literal_length = untag_fixnum_fast(literals->top) * CELLS;
/* compiled header */
F_COMPILED header;
header.header = COMPILED_HEADER;
header.code_length = align8(code_length);
header.reloc_length = rel_length;
header.literal_length = literal_length;
memcpy((void*)compiling.here,&header,sizeof(F_COMPILED));
compiling.here += sizeof(F_COMPILED);
/* code */
deposit_vector(code,code_format);
compiling.here = align8(compiling.here);
/* relation info */
deposit_vector(rel,CELLS);
/* literals */
deposit_vector(literals,CELLS);
/* labels */
fixup_labels(label_rel,start + sizeof(F_COMPILED),0,labels);
/* push the XT of the new word on the stack */
box_unsigned_cell(start + sizeof(F_COMPILED));
}
void primitive_add_compiled_block(void)
{
CELL code_format = to_cell(dpop());
F_VECTOR *code = untag_vector(dpop());
F_VECTOR *label_rel = untag_vector(dpop());
F_VECTOR *labels = untag_vector(dpop());
F_VECTOR *literals = untag_vector(dpop());
F_VECTOR *rel = untag_vector(dpop());
add_compiled_block(code_format,code,label_rel,labels,literals,rel);
}
void primitive_finalize_compile(void)
{
flush_icache((void*)last_flush,compiling.here - last_flush);
while(last_flush < compiling.here)
last_flush = relocate_code_next(last_flush);
last_flush = compiling.here;
}

View File

@ -97,22 +97,3 @@ void signal_error(int signal);
void type_error(CELL type, CELL tagged);
void primitive_throw(void);
void primitive_die(void);
/* The compiled code heap is structured into blocks. */
typedef struct
{
CELL header; /* = COMPILED_HEADER */
CELL code_length; /* # bytes */
CELL reloc_length; /* # bytes, see relocate.h */
CELL literal_length; /* # bytes, see relocate.h */
} F_COMPILED;
#define COMPILED_HEADER 0x01c3babe
void init_compiler(CELL size);
void collect_literals(void);
void primitive_add_compiled_block(void);
CELL last_flush;
void primitive_finalize_compile(void);