Store forwarding table off to the side instead of in the code block; saves one cell per code block

db4
Slava Pestov 2009-05-05 11:07:20 -05:00
parent 8486e6db82
commit 786b9096e2
11 changed files with 55 additions and 55 deletions

View File

@ -100,7 +100,7 @@ code_block *frame_code(stack_frame *frame)
cell frame_type(stack_frame *frame) cell frame_type(stack_frame *frame)
{ {
return frame_code(frame)->block.type; return frame_code(frame)->type;
} }
cell frame_executing(stack_frame *frame) cell frame_executing(stack_frame *frame)

View File

@ -5,7 +5,7 @@ namespace factor
void flush_icache_for(code_block *block) void flush_icache_for(code_block *block)
{ {
flush_icache((cell)block,block->block.size); flush_icache((cell)block,block->size);
} }
void iterate_relocations(code_block *compiled, relocation_iterator iter) void iterate_relocations(code_block *compiled, relocation_iterator iter)
@ -122,7 +122,7 @@ void update_literal_references_step(relocation_entry rel, cell index, code_block
/* Update pointers to literals from compiled code. */ /* Update pointers to literals from compiled code. */
void update_literal_references(code_block *compiled) void update_literal_references(code_block *compiled)
{ {
if(!compiled->block.needs_fixup) if(!compiled->needs_fixup)
{ {
iterate_relocations(compiled,update_literal_references_step); iterate_relocations(compiled,update_literal_references_step);
flush_icache_for(compiled); flush_icache_for(compiled);
@ -133,12 +133,12 @@ void update_literal_references(code_block *compiled)
aging and nursery collections */ aging and nursery collections */
void copy_literal_references(code_block *compiled) void copy_literal_references(code_block *compiled)
{ {
if(collecting_gen >= compiled->block.last_scan) if(collecting_gen >= compiled->last_scan)
{ {
if(collecting_accumulation_gen_p()) if(collecting_accumulation_gen_p())
compiled->block.last_scan = collecting_gen; compiled->last_scan = collecting_gen;
else else
compiled->block.last_scan = collecting_gen + 1; compiled->last_scan = collecting_gen + 1;
/* initialize chase pointer */ /* initialize chase pointer */
cell scan = newspace->here; cell scan = newspace->here;
@ -208,7 +208,7 @@ to update references to other words, without worrying about literals
or dlsyms. */ or dlsyms. */
void update_word_references(code_block *compiled) void update_word_references(code_block *compiled)
{ {
if(compiled->block.needs_fixup) if(compiled->needs_fixup)
relocate_code_block(compiled); relocate_code_block(compiled);
/* update_word_references() is always applied to every block in /* update_word_references() is always applied to every block in
the code heap. Since it resets all call sites to point to the code heap. Since it resets all call sites to point to
@ -217,8 +217,8 @@ void update_word_references(code_block *compiled)
are referenced after this is done. So instead of polluting are referenced after this is done. So instead of polluting
the code heap with dead PICs that will be freed on the next the code heap with dead PICs that will be freed on the next
GC, we add them to the free list immediately. */ GC, we add them to the free list immediately. */
else if(compiled->block.type == PIC_TYPE) else if(compiled->type == PIC_TYPE)
heap_free(&code,&compiled->block); heap_free(&code,compiled);
else else
{ {
iterate_relocations(compiled,update_word_references_step); iterate_relocations(compiled,update_word_references_step);
@ -248,7 +248,7 @@ void mark_code_block(code_block *compiled)
{ {
check_code_address((cell)compiled); check_code_address((cell)compiled);
mark_block(&compiled->block); mark_block(compiled);
copy_handle(&compiled->literals); copy_handle(&compiled->literals);
copy_handle(&compiled->relocation); copy_handle(&compiled->relocation);
@ -405,8 +405,8 @@ void relocate_code_block_step(relocation_entry rel, cell index, code_block *comp
/* Perform all fixups on a code block */ /* Perform all fixups on a code block */
void relocate_code_block(code_block *compiled) void relocate_code_block(code_block *compiled)
{ {
compiled->block.last_scan = NURSERY; compiled->last_scan = NURSERY;
compiled->block.needs_fixup = false; compiled->needs_fixup = false;
iterate_relocations(compiled,relocate_code_block_step); iterate_relocations(compiled,relocate_code_block_step);
flush_icache_for(compiled); flush_icache_for(compiled);
} }
@ -474,9 +474,9 @@ code_block *add_code_block(
code_block *compiled = allot_code_block(code_length); code_block *compiled = allot_code_block(code_length);
/* compiled header */ /* compiled header */
compiled->block.type = type; compiled->type = type;
compiled->block.last_scan = NURSERY; compiled->last_scan = NURSERY;
compiled->block.needs_fixup = true; compiled->needs_fixup = true;
compiled->relocation = relocation.value(); compiled->relocation = relocation.value();
/* slight space optimization */ /* slight space optimization */

View File

@ -22,9 +22,9 @@ void new_heap(heap *heap, cell size)
static void add_to_free_list(heap *heap, free_heap_block *block) static void add_to_free_list(heap *heap, free_heap_block *block)
{ {
if(block->block.size < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT) if(block->size < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
{ {
int index = block->block.size / BLOCK_SIZE_INCREMENT; int index = block->size / BLOCK_SIZE_INCREMENT;
block->next_free = heap->free.small_blocks[index]; block->next_free = heap->free.small_blocks[index];
heap->free.small_blocks[index] = block; heap->free.small_blocks[index] = block;
} }
@ -73,8 +73,8 @@ void build_free_list(heap *heap, cell size)
branch is only taken after loading a new image, not after code GC */ branch is only taken after loading a new image, not after code GC */
if((cell)(end + 1) <= heap->seg->end) if((cell)(end + 1) <= heap->seg->end)
{ {
end->block.status = B_FREE; end->status = B_FREE;
end->block.size = heap->seg->end - (cell)end; end->size = heap->seg->end - (cell)end;
/* add final free block */ /* add final free block */
add_to_free_list(heap,end); add_to_free_list(heap,end);
@ -93,7 +93,7 @@ void build_free_list(heap *heap, cell size)
static void assert_free_block(free_heap_block *block) static void assert_free_block(free_heap_block *block)
{ {
if(block->block.status != B_FREE) if(block->status != B_FREE)
critical_error("Invalid block in free list",(cell)block); critical_error("Invalid block in free list",(cell)block);
} }
@ -121,7 +121,7 @@ static free_heap_block *find_free_block(heap *heap, cell size)
while(block) while(block)
{ {
assert_free_block(block); assert_free_block(block);
if(block->block.size >= size) if(block->size >= size)
{ {
if(prev) if(prev)
prev->next_free = block->next_free; prev->next_free = block->next_free;
@ -139,14 +139,14 @@ static free_heap_block *find_free_block(heap *heap, cell size)
static free_heap_block *split_free_block(heap *heap, free_heap_block *block, cell size) static free_heap_block *split_free_block(heap *heap, free_heap_block *block, cell size)
{ {
if(block->block.size != size ) if(block->size != size )
{ {
/* split the block in two */ /* split the block in two */
free_heap_block *split = (free_heap_block *)((cell)block + size); free_heap_block *split = (free_heap_block *)((cell)block + size);
split->block.status = B_FREE; split->status = B_FREE;
split->block.size = block->block.size - size; split->size = block->size - size;
split->next_free = block->next_free; split->next_free = block->next_free;
block->block.size = size; block->size = size;
add_to_free_list(heap,split); add_to_free_list(heap,split);
} }
@ -163,8 +163,8 @@ heap_block *heap_allot(heap *heap, cell size)
{ {
block = split_free_block(heap,block,size); block = split_free_block(heap,block,size);
block->block.status = B_ALLOCATED; block->status = B_ALLOCATED;
return &block->block; return block;
} }
else else
return NULL; return NULL;
@ -303,16 +303,16 @@ cell heap_size(heap *heap)
} }
/* Compute where each block is going to go, after compaction */ /* Compute where each block is going to go, after compaction */
cell compute_heap_forwarding(heap *heap) cell compute_heap_forwarding(heap *heap, std::tr1::unordered_map<heap_block *,char *> &forwarding)
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block(heap);
cell address = (cell)first_block(heap); char *address = (char *)first_block(heap);
while(scan) while(scan)
{ {
if(scan->status == B_ALLOCATED) if(scan->status == B_ALLOCATED)
{ {
scan->forwarding = (heap_block *)address; forwarding[scan] = address;
address += scan->size; address += scan->size;
} }
else if(scan->status == B_MARKED) else if(scan->status == B_MARKED)
@ -321,10 +321,10 @@ cell compute_heap_forwarding(heap *heap)
scan = next_block(heap,scan); scan = next_block(heap,scan);
} }
return address - heap->seg->start; return (cell)address - heap->seg->start;
} }
void compact_heap(heap *heap) void compact_heap(heap *heap, std::tr1::unordered_map<heap_block *,char *> &forwarding)
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block(heap);
@ -332,8 +332,8 @@ void compact_heap(heap *heap)
{ {
heap_block *next = next_block(heap,scan); heap_block *next = next_block(heap,scan);
if(scan->status == B_ALLOCATED && scan != scan->forwarding) if(scan->status == B_ALLOCATED)
memcpy(scan->forwarding,scan,scan->size); memmove(forwarding[scan],scan,scan->size);
scan = next; scan = next;
} }
} }

View File

@ -25,8 +25,8 @@ void unmark_marked(heap *heap);
void free_unmarked(heap *heap, heap_iterator iter); void free_unmarked(heap *heap, heap_iterator iter);
void heap_usage(heap *h, cell *used, cell *total_free, cell *max_free); void heap_usage(heap *h, cell *used, cell *total_free, cell *max_free);
cell heap_size(heap *h); cell heap_size(heap *h);
cell compute_heap_forwarding(heap *h); cell compute_heap_forwarding(heap *h, std::tr1::unordered_map<heap_block *,char *> &forwarding);
void compact_heap(heap *h); void compact_heap(heap *h, std::tr1::unordered_map<heap_block *,char *> &forwarding);
inline static heap_block *next_block(heap *h, heap_block *block) inline static heap_block *next_block(heap *h, heap_block *block)
{ {

View File

@ -119,9 +119,11 @@ PRIMITIVE(code_room)
dpush(tag_fixnum(max_free / 1024)); dpush(tag_fixnum(max_free / 1024));
} }
static std::tr1::unordered_map<heap_block *,char *> forwarding;
code_block *forward_xt(code_block *compiled) code_block *forward_xt(code_block *compiled)
{ {
return (code_block *)compiled->block.forwarding; return (code_block *)forwarding[compiled];
} }
void forward_frame_xt(stack_frame *frame) void forward_frame_xt(stack_frame *frame)
@ -132,7 +134,7 @@ void forward_frame_xt(stack_frame *frame)
FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset); FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset);
} }
void forward_object_xts(void) void forward_object_xts()
{ {
begin_scan(); begin_scan();
@ -215,13 +217,13 @@ void compact_code_heap(void)
gc(); gc();
/* Figure out where the code heap blocks are going to end up */ /* Figure out where the code heap blocks are going to end up */
cell size = compute_heap_forwarding(&code); cell size = compute_heap_forwarding(&code, forwarding);
/* Update word and quotation code pointers */ /* Update word and quotation code pointers */
forward_object_xts(); forward_object_xts();
/* Actually perform the compaction */ /* Actually perform the compaction */
compact_heap(&code); compact_heap(&code,forwarding);
/* Update word and quotation XTs */ /* Update word and quotation XTs */
fixup_object_xts(); fixup_object_xts();

View File

@ -22,7 +22,7 @@ void deallocate_inline_cache(cell return_address)
/* Find the call target. */ /* Find the call target. */
void *old_xt = get_call_target(return_address); void *old_xt = get_call_target(return_address);
code_block *old_block = (code_block *)old_xt - 1; code_block *old_block = (code_block *)old_xt - 1;
cell old_type = old_block->block.type; cell old_type = old_block->type;
#ifdef FACTOR_DEBUG #ifdef FACTOR_DEBUG
/* The call target was either another PIC, /* The call target was either another PIC,
@ -31,7 +31,7 @@ void deallocate_inline_cache(cell return_address)
#endif #endif
if(old_type == PIC_TYPE) if(old_type == PIC_TYPE)
heap_free(&code,&old_block->block); heap_free(&code,old_block);
} }
/* Figure out what kind of type check the PIC needs based on the methods /* Figure out what kind of type check the PIC needs based on the methods

View File

@ -193,26 +193,19 @@ struct heap_block
unsigned char status; /* free or allocated? */ unsigned char status; /* free or allocated? */
unsigned char type; /* this is WORD_TYPE or QUOTATION_TYPE */ unsigned char type; /* this is WORD_TYPE or QUOTATION_TYPE */
unsigned char last_scan; /* the youngest generation in which this block's literals may live */ unsigned char last_scan; /* the youngest generation in which this block's literals may live */
char needs_fixup; /* is this a new block that needs full fixup? */ unsigned char needs_fixup; /* is this a new block that needs full fixup? */
/* In bytes, includes this header */ /* In bytes, includes this header */
cell size; cell size;
/* Used during compaction */
heap_block *forwarding;
}; };
struct free_heap_block struct free_heap_block : public heap_block
{ {
heap_block block;
/* Filled in on image load */
free_heap_block *next_free; free_heap_block *next_free;
}; };
struct code_block struct code_block : public heap_block
{ {
heap_block block;
cell literals; /* # bytes */ cell literals; /* # bytes */
cell relocation; /* tagged pointer to byte-array or f */ cell relocation; /* tagged pointer to byte-array or f */

View File

@ -9,6 +9,7 @@
#include <assert.h> #include <assert.h>
#endif #endif
/* C headers */
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
@ -20,6 +21,10 @@
#include <time.h> #include <time.h>
#include <sys/param.h> #include <sys/param.h>
/* C++ headers */
#include <tr1/unordered_map>
/* Factor headers */
#include "layouts.hpp" #include "layouts.hpp"
#include "platform.hpp" #include "platform.hpp"
#include "primitives.hpp" #include "primitives.hpp"

View File

@ -251,7 +251,7 @@ void quotation_jit::iterate_quotation()
void set_quot_xt(quotation *quot, code_block *code) void set_quot_xt(quotation *quot, code_block *code)
{ {
if(code->block.type != QUOTATION_TYPE) if(code->type != QUOTATION_TYPE)
critical_error("Bad param to set_quot_xt",(cell)code); critical_error("Bad param to set_quot_xt",(cell)code);
quot->code = code; quot->code = code;

View File

@ -44,7 +44,7 @@ PRIMITIVE(word_xt)
word *w = untag_check<word>(dpop()); word *w = untag_check<word>(dpop());
code_block *code = (profiling_p ? w->profiling : w->code); code_block *code = (profiling_p ? w->profiling : w->code);
dpush(allot_cell((cell)code->xt())); dpush(allot_cell((cell)code->xt()));
dpush(allot_cell((cell)code + code->block.size)); dpush(allot_cell((cell)code + code->size));
} }
/* Allocates memory */ /* Allocates memory */

View File

@ -9,7 +9,7 @@ void update_word_xt(cell word);
inline bool word_optimized_p(word *word) inline bool word_optimized_p(word *word)
{ {
return word->code->block.type == WORD_TYPE; return word->code->type == WORD_TYPE;
} }
PRIMITIVE(optimized_p); PRIMITIVE(optimized_p);