cell frame_type(stack_frame *frame)
{
- return frame_code(frame)->block.type;
+ return frame_code(frame)->type;
}
cell frame_executing(stack_frame *frame)
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)
/* 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);
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;
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
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);
{
check_code_address((cell)compiled);
- mark_block(&compiled->block);
+ mark_block(compiled);
copy_handle(&compiled->literals);
copy_handle(&compiled->relocation);
/* 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);
}
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 */
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;
}
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);
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);
}
while(block)
{
assert_free_block(block);
- if(block->block.size >= size)
+ if(block->size >= size)
{
if(prev)
prev->next_free = block->next_free;
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);
}
{
block = split_free_block(heap,block,size);
- block->block.status = B_ALLOCATED;
- return &block->block;
+ block->status = B_ALLOCATED;
+ return block;
}
else
return NULL;
}
/* 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)
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 *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;
}
}
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)
{
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)
FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset);
}
-void forward_object_xts(void)
+void forward_object_xts()
{
begin_scan();
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();
/* 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,
#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
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 */
#include <assert.h>
#endif
+/* C headers */
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <sys/param.h>
+/* C++ headers */
+#include <tr1/unordered_map>
+
+/* Factor headers */
#include "layouts.hpp"
#include "platform.hpp"
#include "primitives.hpp"
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;
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 */
inline bool word_optimized_p(word *word)
{
- return word->code->block.type == WORD_TYPE;
+ return word->code->type == WORD_TYPE;
}
PRIMITIVE(optimized_p);