From 3b2d14c4c01e7d1898f4300f8e5118dfdbbc235d Mon Sep 17 00:00:00 2001 From: slava Date: Wed, 9 Aug 2006 20:15:27 +0000 Subject: [PATCH] GC now scans literal data area --- Makefile | 1 + vm/compiler.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++ vm/compiler.h | 68 +++++++++++++ vm/factor.h | 1 + vm/image.c | 157 ++-------------------------- vm/image.h | 50 --------- vm/run.c | 116 --------------------- vm/run.h | 19 ---- 8 files changed, 354 insertions(+), 333 deletions(-) create mode 100644 vm/compiler.c create mode 100644 vm/compiler.h diff --git a/Makefile b/Makefile index 284abddbeb..4f91379f4e 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/vm/compiler.c b/vm/compiler.c new file mode 100644 index 0000000000..de1714081a --- /dev/null +++ b/vm/compiler.c @@ -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; +} diff --git a/vm/compiler.h b/vm/compiler.h new file mode 100644 index 0000000000..941a8c99d6 --- /dev/null +++ b/vm/compiler.h @@ -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); diff --git a/vm/factor.h b/vm/factor.h index a3529299a2..db8b15966e 100644 --- a/vm/factor.h +++ b/vm/factor.h @@ -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" diff --git a/vm/image.c b/vm/image.c index 0b17c5a9cb..e18d2d46b3 100644 --- a/vm/image.c +++ b/vm/image.c @@ -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); } diff --git a/vm/image.h b/vm/image.h index 8684cd65e9..8d9fd7d1aa 100644 --- a/vm/image.h +++ b/vm/image.h @@ -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))); -} diff --git a/vm/run.c b/vm/run.c index a689f31fcc..53a2290caa 100644 --- a/vm/run.c +++ b/vm/run.c @@ -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; -} diff --git a/vm/run.h b/vm/run.h index 170b502476..a7a49e3e73 100644 --- a/vm/run.h +++ b/vm/run.h @@ -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);