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)
{
return frame_code(frame)->block.type;
return frame_code(frame)->type;
}
cell frame_executing(stack_frame *frame)

View File

@ -5,7 +5,7 @@ namespace factor
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)
@ -122,7 +122,7 @@ void update_literal_references_step(relocation_entry rel, cell index, code_block
/* Update pointers to literals from compiled code. */
void update_literal_references(code_block *compiled)
{
if(!compiled->block.needs_fixup)
if(!compiled->needs_fixup)
{
iterate_relocations(compiled,update_literal_references_step);
flush_icache_for(compiled);
@ -133,12 +133,12 @@ void update_literal_references(code_block *compiled)
aging and nursery collections */
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())
compiled->block.last_scan = collecting_gen;
compiled->last_scan = collecting_gen;
else
compiled->block.last_scan = collecting_gen + 1;
compiled->last_scan = collecting_gen + 1;
/* initialize chase pointer */
cell scan = newspace->here;
@ -208,7 +208,7 @@ to update references to other words, without worrying about literals
or dlsyms. */
void update_word_references(code_block *compiled)
{
if(compiled->block.needs_fixup)
if(compiled->needs_fixup)
relocate_code_block(compiled);
/* update_word_references() is always applied to every block in
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
the code heap with dead PICs that will be freed on the next
GC, we add them to the free list immediately. */
else if(compiled->block.type == PIC_TYPE)
heap_free(&code,&compiled->block);
else if(compiled->type == PIC_TYPE)
heap_free(&code,compiled);
else
{
iterate_relocations(compiled,update_word_references_step);
@ -248,7 +248,7 @@ void mark_code_block(code_block *compiled)
{
check_code_address((cell)compiled);
mark_block(&compiled->block);
mark_block(compiled);
copy_handle(&compiled->literals);
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 */
void relocate_code_block(code_block *compiled)
{
compiled->block.last_scan = NURSERY;
compiled->block.needs_fixup = false;
compiled->last_scan = NURSERY;
compiled->needs_fixup = false;
iterate_relocations(compiled,relocate_code_block_step);
flush_icache_for(compiled);
}
@ -474,9 +474,9 @@ code_block *add_code_block(
code_block *compiled = allot_code_block(code_length);
/* compiled header */
compiled->block.type = type;
compiled->block.last_scan = NURSERY;
compiled->block.needs_fixup = true;
compiled->type = type;
compiled->last_scan = NURSERY;
compiled->needs_fixup = true;
compiled->relocation = relocation.value();
/* 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)
{
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];
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 */
if((cell)(end + 1) <= heap->seg->end)
{
end->block.status = B_FREE;
end->block.size = heap->seg->end - (cell)end;
end->status = B_FREE;
end->size = heap->seg->end - (cell)end;
/* add final free block */
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)
{
if(block->block.status != B_FREE)
if(block->status != B_FREE)
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)
{
assert_free_block(block);
if(block->block.size >= size)
if(block->size >= size)
{
if(prev)
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)
{
if(block->block.size != size )
if(block->size != size )
{
/* split the block in two */
free_heap_block *split = (free_heap_block *)((cell)block + size);
split->block.status = B_FREE;
split->block.size = block->block.size - size;
split->status = B_FREE;
split->size = block->size - size;
split->next_free = block->next_free;
block->block.size = size;
block->size = size;
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->block.status = B_ALLOCATED;
return &block->block;
block->status = B_ALLOCATED;
return block;
}
else
return NULL;
@ -303,16 +303,16 @@ cell heap_size(heap *heap)
}
/* 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);
cell address = (cell)first_block(heap);
char *address = (char *)first_block(heap);
while(scan)
{
if(scan->status == B_ALLOCATED)
{
scan->forwarding = (heap_block *)address;
forwarding[scan] = address;
address += scan->size;
}
else if(scan->status == B_MARKED)
@ -321,10 +321,10 @@ cell compute_heap_forwarding(heap *heap)
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);
@ -332,8 +332,8 @@ void compact_heap(heap *heap)
{
heap_block *next = next_block(heap,scan);
if(scan->status == B_ALLOCATED && scan != scan->forwarding)
memcpy(scan->forwarding,scan,scan->size);
if(scan->status == B_ALLOCATED)
memmove(forwarding[scan],scan,scan->size);
scan = next;
}
}

View File

@ -25,8 +25,8 @@ void unmark_marked(heap *heap);
void free_unmarked(heap *heap, heap_iterator iter);
void heap_usage(heap *h, cell *used, cell *total_free, cell *max_free);
cell heap_size(heap *h);
cell compute_heap_forwarding(heap *h);
void compact_heap(heap *h);
cell compute_heap_forwarding(heap *h, std::tr1::unordered_map<heap_block *,char *> &forwarding);
void compact_heap(heap *h, std::tr1::unordered_map<heap_block *,char *> &forwarding);
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));
}
static std::tr1::unordered_map<heap_block *,char *> forwarding;
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)
@ -132,7 +134,7 @@ void forward_frame_xt(stack_frame *frame)
FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset);
}
void forward_object_xts(void)
void forward_object_xts()
{
begin_scan();
@ -215,13 +217,13 @@ void compact_code_heap(void)
gc();
/* 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 */
forward_object_xts();
/* Actually perform the compaction */
compact_heap(&code);
compact_heap(&code,forwarding);
/* Update word and quotation XTs */
fixup_object_xts();

View File

@ -22,7 +22,7 @@ void deallocate_inline_cache(cell return_address)
/* Find the call target. */
void *old_xt = get_call_target(return_address);
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
/* The call target was either another PIC,
@ -31,7 +31,7 @@ void deallocate_inline_cache(cell return_address)
#endif
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

View File

@ -193,26 +193,19 @@ struct heap_block
unsigned char status; /* free or allocated? */
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 */
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 */
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;
};
struct code_block
struct code_block : public heap_block
{
heap_block block;
cell literals; /* # bytes */
cell relocation; /* tagged pointer to byte-array or f */

View File

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

View File

@ -251,7 +251,7 @@ void quotation_jit::iterate_quotation()
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);
quot->code = code;

View File

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

View File

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