VM cleanup: replace some #defines with constants and inline functions
parent
4a2492c3fc
commit
3bf8134476
|
@ -24,10 +24,7 @@ void iterate_callstack(cell top, cell bottom, CALLSTACK_ITER iterator)
|
||||||
|
|
||||||
void iterate_callstack_object(callstack *stack, CALLSTACK_ITER iterator)
|
void iterate_callstack_object(callstack *stack, CALLSTACK_ITER iterator)
|
||||||
{
|
{
|
||||||
cell top = (cell)FIRST_STACK_FRAME(stack);
|
iterate_callstack((cell)stack->top(),(cell)stack->bottom(),iterator);
|
||||||
cell bottom = top + untag_fixnum(stack->length);
|
|
||||||
|
|
||||||
iterate_callstack(top,bottom,iterator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callstack *allot_callstack(cell size)
|
callstack *allot_callstack(cell size)
|
||||||
|
@ -75,7 +72,7 @@ PRIMITIVE(callstack)
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
callstack *stack = allot_callstack(size);
|
callstack *stack = allot_callstack(size);
|
||||||
memcpy(FIRST_STACK_FRAME(stack),top,size);
|
memcpy(stack->top(),top,size);
|
||||||
dpush(tag<callstack>(stack));
|
dpush(tag<callstack>(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +81,7 @@ PRIMITIVE(set_callstack)
|
||||||
callstack *stack = untag_check<callstack>(dpop());
|
callstack *stack = untag_check<callstack>(dpop());
|
||||||
|
|
||||||
set_callstack(stack_chain->callstack_bottom,
|
set_callstack(stack_chain->callstack_bottom,
|
||||||
FIRST_STACK_FRAME(stack),
|
stack->top(),
|
||||||
untag_fixnum(stack->length),
|
untag_fixnum(stack->length),
|
||||||
memcpy);
|
memcpy);
|
||||||
|
|
||||||
|
@ -173,12 +170,11 @@ PRIMITIVE(callstack_to_array)
|
||||||
dpush(tag<array>(frames));
|
dpush(tag<array>(frames));
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_frame *innermost_stack_frame(callstack *callstack)
|
stack_frame *innermost_stack_frame(callstack *stack)
|
||||||
{
|
{
|
||||||
stack_frame *top = FIRST_STACK_FRAME(callstack);
|
stack_frame *top = stack->top();
|
||||||
cell bottom = (cell)top + untag_fixnum(callstack->length);
|
stack_frame *bottom = stack->bottom();
|
||||||
|
stack_frame *frame = bottom - 1;
|
||||||
stack_frame *frame = (stack_frame *)bottom - 1;
|
|
||||||
|
|
||||||
while(frame >= top && frame_successor(frame) >= top)
|
while(frame >= top && frame_successor(frame) >= top)
|
||||||
frame = frame_successor(frame);
|
frame = frame_successor(frame);
|
||||||
|
|
|
@ -6,8 +6,6 @@ inline static cell callstack_size(cell size)
|
||||||
return sizeof(callstack) + size;
|
return sizeof(callstack) + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIRST_STACK_FRAME(stack) (stack_frame *)((stack) + 1)
|
|
||||||
|
|
||||||
typedef void (*CALLSTACK_ITER)(stack_frame *frame);
|
typedef void (*CALLSTACK_ITER)(stack_frame *frame);
|
||||||
|
|
||||||
stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom);
|
stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom);
|
||||||
|
|
|
@ -3,6 +3,21 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static relocation_type relocation_type_of(relocation_entry r)
|
||||||
|
{
|
||||||
|
return (relocation_type)((r & 0xf0000000) >> 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
static relocation_class relocation_class_of(relocation_entry r)
|
||||||
|
{
|
||||||
|
return (relocation_class)((r & 0x0f000000) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell relocation_offset_of(relocation_entry r)
|
||||||
|
{
|
||||||
|
return (r & 0x00ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
void flush_icache_for(code_block *block)
|
void flush_icache_for(code_block *block)
|
||||||
{
|
{
|
||||||
flush_icache((cell)block,block->size);
|
flush_icache((cell)block,block->size);
|
||||||
|
@ -125,11 +140,11 @@ void *get_rel_symbol(array *literals, cell index)
|
||||||
cell compute_relocation(relocation_entry rel, cell index, code_block *compiled)
|
cell compute_relocation(relocation_entry rel, cell index, code_block *compiled)
|
||||||
{
|
{
|
||||||
array *literals = untag<array>(compiled->literals);
|
array *literals = untag<array>(compiled->literals);
|
||||||
cell offset = REL_OFFSET(rel) + (cell)compiled->xt();
|
cell offset = relocation_offset_of(rel) + (cell)compiled->xt();
|
||||||
|
|
||||||
#define ARG array_nth(literals,index)
|
#define ARG array_nth(literals,index)
|
||||||
|
|
||||||
switch(REL_TYPE(rel))
|
switch(relocation_type_of(rel))
|
||||||
{
|
{
|
||||||
case RT_PRIMITIVE:
|
case RT_PRIMITIVE:
|
||||||
return (cell)primitives[untag_fixnum(ARG)];
|
return (cell)primitives[untag_fixnum(ARG)];
|
||||||
|
@ -174,7 +189,7 @@ void iterate_relocations(code_block *compiled, relocation_iterator iter)
|
||||||
{
|
{
|
||||||
relocation_entry rel = relocation->data<relocation_entry>()[i];
|
relocation_entry rel = relocation->data<relocation_entry>()[i];
|
||||||
iter(rel,index,compiled);
|
iter(rel,index,compiled);
|
||||||
index += number_of_parameters(REL_TYPE(rel));
|
index += number_of_parameters(relocation_type_of(rel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,25 +232,25 @@ void store_address_in_code_block(cell klass, cell offset, fixnum absolute_value)
|
||||||
store_address_2_2((cell *)offset,absolute_value);
|
store_address_2_2((cell *)offset,absolute_value);
|
||||||
break;
|
break;
|
||||||
case RC_ABSOLUTE_PPC_2:
|
case RC_ABSOLUTE_PPC_2:
|
||||||
store_address_masked((cell *)offset,absolute_value,REL_ABSOLUTE_PPC_2_MASK,0);
|
store_address_masked((cell *)offset,absolute_value,rel_absolute_ppc_2_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_RELATIVE_PPC_2:
|
case RC_RELATIVE_PPC_2:
|
||||||
store_address_masked((cell *)offset,relative_value,REL_RELATIVE_PPC_2_MASK,0);
|
store_address_masked((cell *)offset,relative_value,rel_relative_ppc_2_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_RELATIVE_PPC_3:
|
case RC_RELATIVE_PPC_3:
|
||||||
store_address_masked((cell *)offset,relative_value,REL_RELATIVE_PPC_3_MASK,0);
|
store_address_masked((cell *)offset,relative_value,rel_relative_ppc_3_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_RELATIVE_ARM_3:
|
case RC_RELATIVE_ARM_3:
|
||||||
store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
|
store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
|
||||||
REL_RELATIVE_ARM_3_MASK,2);
|
rel_relative_arm_3_mask,2);
|
||||||
break;
|
break;
|
||||||
case RC_INDIRECT_ARM:
|
case RC_INDIRECT_ARM:
|
||||||
store_address_masked((cell *)offset,relative_value - sizeof(cell),
|
store_address_masked((cell *)offset,relative_value - sizeof(cell),
|
||||||
REL_INDIRECT_ARM_MASK,0);
|
rel_indirect_arm_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_INDIRECT_ARM_PC:
|
case RC_INDIRECT_ARM_PC:
|
||||||
store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
|
store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2,
|
||||||
REL_INDIRECT_ARM_MASK,0);
|
rel_indirect_arm_mask,0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
critical_error("Bad rel class",klass);
|
critical_error("Bad rel class",klass);
|
||||||
|
@ -245,12 +260,12 @@ void store_address_in_code_block(cell klass, cell offset, fixnum absolute_value)
|
||||||
|
|
||||||
void update_literal_references_step(relocation_entry rel, cell index, code_block *compiled)
|
void update_literal_references_step(relocation_entry rel, cell index, code_block *compiled)
|
||||||
{
|
{
|
||||||
if(REL_TYPE(rel) == RT_IMMEDIATE)
|
if(relocation_type_of(rel) == RT_IMMEDIATE)
|
||||||
{
|
{
|
||||||
cell offset = REL_OFFSET(rel) + (cell)(compiled + 1);
|
cell offset = relocation_offset_of(rel) + (cell)(compiled + 1);
|
||||||
array *literals = untag<array>(compiled->literals);
|
array *literals = untag<array>(compiled->literals);
|
||||||
fixnum absolute_value = array_nth(literals,index);
|
fixnum absolute_value = array_nth(literals,index);
|
||||||
store_address_in_code_block(REL_CLASS(rel),offset,absolute_value);
|
store_address_in_code_block(relocation_class_of(rel),offset,absolute_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,14 +312,14 @@ void relocate_code_block_step(relocation_entry rel, cell index, code_block *comp
|
||||||
tagged<byte_array>(compiled->relocation).untag_check();
|
tagged<byte_array>(compiled->relocation).untag_check();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
store_address_in_code_block(REL_CLASS(rel),
|
store_address_in_code_block(relocation_class_of(rel),
|
||||||
REL_OFFSET(rel) + (cell)compiled->xt(),
|
relocation_offset_of(rel) + (cell)compiled->xt(),
|
||||||
compute_relocation(rel,index,compiled));
|
compute_relocation(rel,index,compiled));
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_word_references_step(relocation_entry rel, cell index, code_block *compiled)
|
void update_word_references_step(relocation_entry rel, cell index, code_block *compiled)
|
||||||
{
|
{
|
||||||
relocation_type type = REL_TYPE(rel);
|
relocation_type type = relocation_type_of(rel);
|
||||||
if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
|
if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
|
||||||
relocate_code_block_step(rel,index,compiled);
|
relocate_code_block_step(rel,index,compiled);
|
||||||
}
|
}
|
||||||
|
@ -369,7 +384,7 @@ void mark_stack_frame_step(stack_frame *frame)
|
||||||
/* Mark code blocks executing in currently active stack frames. */
|
/* Mark code blocks executing in currently active stack frames. */
|
||||||
void mark_active_blocks(context *stacks)
|
void mark_active_blocks(context *stacks)
|
||||||
{
|
{
|
||||||
if(collecting_gen == TENURED)
|
if(collecting_gen == data->tenured())
|
||||||
{
|
{
|
||||||
cell top = (cell)stacks->callstack_top;
|
cell top = (cell)stacks->callstack_top;
|
||||||
cell bottom = (cell)stacks->callstack_bottom;
|
cell bottom = (cell)stacks->callstack_bottom;
|
||||||
|
@ -410,7 +425,7 @@ void mark_object_code_block(object *object)
|
||||||
/* 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->last_scan = NURSERY;
|
compiled->last_scan = data->nursery();
|
||||||
compiled->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);
|
||||||
|
@ -480,7 +495,7 @@ code_block *add_code_block(
|
||||||
|
|
||||||
/* compiled header */
|
/* compiled header */
|
||||||
compiled->type = type;
|
compiled->type = type;
|
||||||
compiled->last_scan = NURSERY;
|
compiled->last_scan = data->nursery();
|
||||||
compiled->needs_fixup = true;
|
compiled->needs_fixup = true;
|
||||||
compiled->relocation = relocation.value();
|
compiled->relocation = relocation.value();
|
||||||
|
|
||||||
|
@ -499,7 +514,7 @@ code_block *add_code_block(
|
||||||
|
|
||||||
/* next time we do a minor GC, we have to scan the code heap for
|
/* next time we do a minor GC, we have to scan the code heap for
|
||||||
literals */
|
literals */
|
||||||
last_code_heap_scan = NURSERY;
|
last_code_heap_scan = data->nursery();
|
||||||
|
|
||||||
return compiled;
|
return compiled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,17 +51,14 @@ enum relocation_class {
|
||||||
RC_INDIRECT_ARM_PC
|
RC_INDIRECT_ARM_PC
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REL_ABSOLUTE_PPC_2_MASK 0xffff
|
static const cell rel_absolute_ppc_2_mask = 0xffff;
|
||||||
#define REL_RELATIVE_PPC_2_MASK 0xfffc
|
static const cell rel_relative_ppc_2_mask = 0xfffc;
|
||||||
#define REL_RELATIVE_PPC_3_MASK 0x3fffffc
|
static const cell rel_relative_ppc_3_mask = 0x3fffffc;
|
||||||
#define REL_INDIRECT_ARM_MASK 0xfff
|
static const cell rel_indirect_arm_mask = 0xfff;
|
||||||
#define REL_RELATIVE_ARM_3_MASK 0xffffff
|
static const cell rel_relative_arm_3_mask = 0xffffff;
|
||||||
|
|
||||||
/* code relocation table consists of a table of entries for each fixup */
|
/* code relocation table consists of a table of entries for each fixup */
|
||||||
typedef u32 relocation_entry;
|
typedef u32 relocation_entry;
|
||||||
#define REL_TYPE(r) (relocation_type)(((r) & 0xf0000000) >> 28)
|
|
||||||
#define REL_CLASS(r) (relocation_class)(((r) & 0x0f000000) >> 24)
|
|
||||||
#define REL_OFFSET(r) ((r) & 0x00ffffff)
|
|
||||||
|
|
||||||
void flush_icache_for(code_block *compiled);
|
void flush_icache_for(code_block *compiled);
|
||||||
|
|
||||||
|
|
|
@ -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->size < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
|
if(block->size < free_list_count * block_size_increment)
|
||||||
{
|
{
|
||||||
int index = 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;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ void build_free_list(heap *heap, cell size)
|
||||||
|
|
||||||
clear_free_list(heap);
|
clear_free_list(heap);
|
||||||
|
|
||||||
size = (size + BLOCK_SIZE_INCREMENT - 1) & ~(BLOCK_SIZE_INCREMENT - 1);
|
size = (size + block_size_increment - 1) & ~(block_size_increment - 1);
|
||||||
|
|
||||||
heap_block *scan = first_block(heap);
|
heap_block *scan = first_block(heap);
|
||||||
free_heap_block *end = (free_heap_block *)(heap->seg->start + size);
|
free_heap_block *end = (free_heap_block *)(heap->seg->start + size);
|
||||||
|
@ -101,9 +101,9 @@ static free_heap_block *find_free_block(heap *heap, cell size)
|
||||||
{
|
{
|
||||||
cell attempt = size;
|
cell attempt = size;
|
||||||
|
|
||||||
while(attempt < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
|
while(attempt < free_list_count * block_size_increment)
|
||||||
{
|
{
|
||||||
int index = attempt / BLOCK_SIZE_INCREMENT;
|
int index = attempt / block_size_increment;
|
||||||
free_heap_block *block = heap->free.small_blocks[index];
|
free_heap_block *block = heap->free.small_blocks[index];
|
||||||
if(block)
|
if(block)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ static free_heap_block *split_free_block(heap *heap, free_heap_block *block, cel
|
||||||
/* Allocate a block of memory from the mark and sweep GC heap */
|
/* Allocate a block of memory from the mark and sweep GC heap */
|
||||||
heap_block *heap_allot(heap *heap, cell size)
|
heap_block *heap_allot(heap *heap, cell size)
|
||||||
{
|
{
|
||||||
size = (size + BLOCK_SIZE_INCREMENT - 1) & ~(BLOCK_SIZE_INCREMENT - 1);
|
size = (size + block_size_increment - 1) & ~(block_size_increment - 1);
|
||||||
|
|
||||||
free_heap_block *block = find_free_block(heap,size);
|
free_heap_block *block = find_free_block(heap,size);
|
||||||
if(block)
|
if(block)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
#define FREE_LIST_COUNT 16
|
static const cell free_list_count = 16;
|
||||||
#define BLOCK_SIZE_INCREMENT 32
|
static const cell block_size_increment = 32;
|
||||||
|
|
||||||
struct heap_free_list {
|
struct heap_free_list {
|
||||||
free_heap_block *small_blocks[FREE_LIST_COUNT];
|
free_heap_block *small_blocks[free_list_count];
|
||||||
free_heap_block *large_blocks;
|
free_heap_block *large_blocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ void reset_retainstack()
|
||||||
rs = rs_bot - sizeof(cell);
|
rs = rs_bot - sizeof(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RESERVED (64 * sizeof(cell))
|
static const cell stack_reserved = (64 * sizeof(cell));
|
||||||
|
|
||||||
void fix_stacks()
|
void fix_stacks()
|
||||||
{
|
{
|
||||||
if(ds + sizeof(cell) < ds_bot || ds + RESERVED >= ds_top) reset_datastack();
|
if(ds + sizeof(cell) < ds_bot || ds + stack_reserved >= ds_top) reset_datastack();
|
||||||
if(rs + sizeof(cell) < rs_bot || rs + RESERVED >= rs_top) reset_retainstack();
|
if(rs + sizeof(cell) < rs_bot || rs + stack_reserved >= rs_top) reset_retainstack();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called before entry into foreign C code. Note that ds and rs might
|
/* called before entry into foreign C code. Note that ds and rs might
|
||||||
|
|
|
@ -27,7 +27,7 @@ inline static void check_call_site(cell return_address)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define B_MASK 0x3fffffc
|
static const cell b_mask = 0x3fffffc;
|
||||||
|
|
||||||
inline static void *get_call_target(cell return_address)
|
inline static void *get_call_target(cell return_address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,15 +9,15 @@ bool performing_gc;
|
||||||
bool performing_compaction;
|
bool performing_compaction;
|
||||||
cell collecting_gen;
|
cell collecting_gen;
|
||||||
|
|
||||||
/* if true, we collecting AGING space for the second time, so if it is still
|
/* if true, we collecting aging space for the second time, so if it is still
|
||||||
full, we go on to collect TENURED */
|
full, we go on to collect tenured */
|
||||||
bool collecting_aging_again;
|
bool collecting_aging_again;
|
||||||
|
|
||||||
/* in case a generation fills up in the middle of a gc, we jump back
|
/* in case a generation fills up in the middle of a gc, we jump back
|
||||||
up to try collecting the next generation. */
|
up to try collecting the next generation. */
|
||||||
jmp_buf gc_jmp;
|
jmp_buf gc_jmp;
|
||||||
|
|
||||||
gc_stats stats[MAX_GEN_COUNT];
|
gc_stats stats[max_gen_count];
|
||||||
u64 cards_scanned;
|
u64 cards_scanned;
|
||||||
u64 decks_scanned;
|
u64 decks_scanned;
|
||||||
u64 card_scan_time;
|
u64 card_scan_time;
|
||||||
|
@ -36,7 +36,7 @@ data_heap *old_data_heap;
|
||||||
void init_data_gc()
|
void init_data_gc()
|
||||||
{
|
{
|
||||||
performing_gc = false;
|
performing_gc = false;
|
||||||
last_code_heap_scan = NURSERY;
|
last_code_heap_scan = data->nursery();
|
||||||
collecting_aging_again = false;
|
collecting_aging_again = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,11 +66,11 @@ static bool should_copy_p(object *untagged)
|
||||||
{
|
{
|
||||||
if(in_zone(newspace,untagged))
|
if(in_zone(newspace,untagged))
|
||||||
return false;
|
return false;
|
||||||
if(collecting_gen == TENURED)
|
if(collecting_gen == data->tenured())
|
||||||
return true;
|
return true;
|
||||||
else if(HAVE_AGING_P && collecting_gen == AGING)
|
else if(data->have_aging_p() && collecting_gen == data->aging())
|
||||||
return !in_zone(&data->generations[TENURED],untagged);
|
return !in_zone(&data->generations[data->tenured()],untagged);
|
||||||
else if(collecting_gen == NURSERY)
|
else if(collecting_gen == data->nursery())
|
||||||
return in_zone(&nursery,untagged);
|
return in_zone(&nursery,untagged);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -186,19 +186,19 @@ static void copy_gen_cards(cell gen)
|
||||||
|
|
||||||
/* if we are collecting the nursery, we care about old->nursery pointers
|
/* if we are collecting the nursery, we care about old->nursery pointers
|
||||||
but not old->aging pointers */
|
but not old->aging pointers */
|
||||||
if(collecting_gen == NURSERY)
|
if(collecting_gen == data->nursery())
|
||||||
{
|
{
|
||||||
mask = CARD_POINTS_TO_NURSERY;
|
mask = card_points_to_nursery;
|
||||||
|
|
||||||
/* after the collection, no old->nursery pointers remain
|
/* after the collection, no old->nursery pointers remain
|
||||||
anywhere, but old->aging pointers might remain in tenured
|
anywhere, but old->aging pointers might remain in tenured
|
||||||
space */
|
space */
|
||||||
if(gen == TENURED)
|
if(gen == data->tenured())
|
||||||
unmask = CARD_POINTS_TO_NURSERY;
|
unmask = card_points_to_nursery;
|
||||||
/* after the collection, all cards in aging space can be
|
/* after the collection, all cards in aging space can be
|
||||||
cleared */
|
cleared */
|
||||||
else if(HAVE_AGING_P && gen == AGING)
|
else if(data->have_aging_p() && gen == data->aging())
|
||||||
unmask = CARD_MARK_MASK;
|
unmask = card_mark_mask;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
critical_error("bug in copy_gen_cards",gen);
|
critical_error("bug in copy_gen_cards",gen);
|
||||||
|
@ -208,20 +208,20 @@ static void copy_gen_cards(cell gen)
|
||||||
/* if we are collecting aging space into tenured space, we care about
|
/* if we are collecting aging space into tenured space, we care about
|
||||||
all old->nursery and old->aging pointers. no old->aging pointers can
|
all old->nursery and old->aging pointers. no old->aging pointers can
|
||||||
remain */
|
remain */
|
||||||
else if(HAVE_AGING_P && collecting_gen == AGING)
|
else if(data->have_aging_p() && collecting_gen == data->aging())
|
||||||
{
|
{
|
||||||
if(collecting_aging_again)
|
if(collecting_aging_again)
|
||||||
{
|
{
|
||||||
mask = CARD_POINTS_TO_AGING;
|
mask = card_points_to_aging;
|
||||||
unmask = CARD_MARK_MASK;
|
unmask = card_mark_mask;
|
||||||
}
|
}
|
||||||
/* after we collect aging space into the aging semispace, no
|
/* after we collect aging space into the aging semispace, no
|
||||||
old->nursery pointers remain but tenured space might still have
|
old->nursery pointers remain but tenured space might still have
|
||||||
pointers to aging space. */
|
pointers to aging space. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mask = CARD_POINTS_TO_AGING;
|
mask = card_points_to_aging;
|
||||||
unmask = CARD_POINTS_TO_NURSERY;
|
unmask = card_points_to_nursery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -366,8 +366,8 @@ static cell copy_next_from_aging(cell scan)
|
||||||
{
|
{
|
||||||
obj++;
|
obj++;
|
||||||
|
|
||||||
cell tenured_start = data->generations[TENURED].start;
|
cell tenured_start = data->generations[data->tenured()].start;
|
||||||
cell tenured_end = data->generations[TENURED].end;
|
cell tenured_end = data->generations[data->tenured()].end;
|
||||||
|
|
||||||
cell newspace_start = newspace->start;
|
cell newspace_start = newspace->start;
|
||||||
cell newspace_end = newspace->end;
|
cell newspace_end = newspace->end;
|
||||||
|
@ -421,17 +421,17 @@ static cell copy_next_from_tenured(cell scan)
|
||||||
|
|
||||||
void copy_reachable_objects(cell scan, cell *end)
|
void copy_reachable_objects(cell scan, cell *end)
|
||||||
{
|
{
|
||||||
if(collecting_gen == NURSERY)
|
if(collecting_gen == data->nursery())
|
||||||
{
|
{
|
||||||
while(scan < *end)
|
while(scan < *end)
|
||||||
scan = copy_next_from_nursery(scan);
|
scan = copy_next_from_nursery(scan);
|
||||||
}
|
}
|
||||||
else if(HAVE_AGING_P && collecting_gen == AGING)
|
else if(data->have_aging_p() && collecting_gen == data->aging())
|
||||||
{
|
{
|
||||||
while(scan < *end)
|
while(scan < *end)
|
||||||
scan = copy_next_from_aging(scan);
|
scan = copy_next_from_aging(scan);
|
||||||
}
|
}
|
||||||
else if(collecting_gen == TENURED)
|
else if(collecting_gen == data->tenured())
|
||||||
{
|
{
|
||||||
while(scan < *end)
|
while(scan < *end)
|
||||||
scan = copy_next_from_tenured(scan);
|
scan = copy_next_from_tenured(scan);
|
||||||
|
@ -443,12 +443,12 @@ static void begin_gc(cell requested_bytes)
|
||||||
{
|
{
|
||||||
if(growing_data_heap)
|
if(growing_data_heap)
|
||||||
{
|
{
|
||||||
if(collecting_gen != TENURED)
|
if(collecting_gen != data->tenured())
|
||||||
critical_error("Invalid parameters to begin_gc",0);
|
critical_error("Invalid parameters to begin_gc",0);
|
||||||
|
|
||||||
old_data_heap = data;
|
old_data_heap = data;
|
||||||
set_data_heap(grow_data_heap(old_data_heap,requested_bytes));
|
set_data_heap(grow_data_heap(old_data_heap,requested_bytes));
|
||||||
newspace = &data->generations[TENURED];
|
newspace = &data->generations[data->tenured()];
|
||||||
}
|
}
|
||||||
else if(collecting_accumulation_gen_p())
|
else if(collecting_accumulation_gen_p())
|
||||||
{
|
{
|
||||||
|
@ -491,12 +491,12 @@ static void end_gc(cell gc_elapsed)
|
||||||
if(collecting_accumulation_gen_p())
|
if(collecting_accumulation_gen_p())
|
||||||
{
|
{
|
||||||
/* all younger generations except are now empty.
|
/* all younger generations except are now empty.
|
||||||
if collecting_gen == NURSERY here, we only have 1 generation;
|
if collecting_gen == data->nursery() here, we only have 1 generation;
|
||||||
old-school Cheney collector */
|
old-school Cheney collector */
|
||||||
if(collecting_gen != NURSERY)
|
if(collecting_gen != data->nursery())
|
||||||
reset_generations(NURSERY,collecting_gen - 1);
|
reset_generations(data->nursery(),collecting_gen - 1);
|
||||||
}
|
}
|
||||||
else if(collecting_gen == NURSERY)
|
else if(collecting_gen == data->nursery())
|
||||||
{
|
{
|
||||||
nursery.here = nursery.start;
|
nursery.here = nursery.start;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +504,7 @@ static void end_gc(cell gc_elapsed)
|
||||||
{
|
{
|
||||||
/* all generations up to and including the one
|
/* all generations up to and including the one
|
||||||
collected are now empty */
|
collected are now empty */
|
||||||
reset_generations(NURSERY,collecting_gen);
|
reset_generations(data->nursery(),collecting_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
collecting_aging_again = false;
|
collecting_aging_again = false;
|
||||||
|
@ -534,17 +534,17 @@ void garbage_collection(cell gen,
|
||||||
{
|
{
|
||||||
/* We have no older generations we can try collecting, so we
|
/* We have no older generations we can try collecting, so we
|
||||||
resort to growing the data heap */
|
resort to growing the data heap */
|
||||||
if(collecting_gen == TENURED)
|
if(collecting_gen == data->tenured())
|
||||||
{
|
{
|
||||||
growing_data_heap = true;
|
growing_data_heap = true;
|
||||||
|
|
||||||
/* see the comment in unmark_marked() */
|
/* see the comment in unmark_marked() */
|
||||||
unmark_marked(&code);
|
unmark_marked(&code);
|
||||||
}
|
}
|
||||||
/* we try collecting AGING space twice before going on to
|
/* we try collecting aging space twice before going on to
|
||||||
collect TENURED */
|
collect tenured */
|
||||||
else if(HAVE_AGING_P
|
else if(data->have_aging_p()
|
||||||
&& collecting_gen == AGING
|
&& collecting_gen == data->aging()
|
||||||
&& !collecting_aging_again)
|
&& !collecting_aging_again)
|
||||||
{
|
{
|
||||||
collecting_aging_again = true;
|
collecting_aging_again = true;
|
||||||
|
@ -575,7 +575,7 @@ void garbage_collection(cell gen,
|
||||||
{
|
{
|
||||||
code_heap_scans++;
|
code_heap_scans++;
|
||||||
|
|
||||||
if(collecting_gen == TENURED)
|
if(collecting_gen == data->tenured())
|
||||||
free_unmarked(&code,(heap_iterator)update_literal_and_word_references);
|
free_unmarked(&code,(heap_iterator)update_literal_and_word_references);
|
||||||
else
|
else
|
||||||
copy_code_heap_roots();
|
copy_code_heap_roots();
|
||||||
|
@ -595,7 +595,7 @@ void garbage_collection(cell gen,
|
||||||
|
|
||||||
void gc()
|
void gc()
|
||||||
{
|
{
|
||||||
garbage_collection(TENURED,false,0);
|
garbage_collection(data->tenured(),false,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIMITIVE(gc)
|
PRIMITIVE(gc)
|
||||||
|
@ -610,7 +610,7 @@ PRIMITIVE(gc_stats)
|
||||||
cell i;
|
cell i;
|
||||||
u64 total_gc_time = 0;
|
u64 total_gc_time = 0;
|
||||||
|
|
||||||
for(i = 0; i < MAX_GEN_COUNT; i++)
|
for(i = 0; i < max_gen_count; i++)
|
||||||
{
|
{
|
||||||
gc_stats *s = &stats[i];
|
gc_stats *s = &stats[i];
|
||||||
result.add(allot_cell(s->collections));
|
result.add(allot_cell(s->collections));
|
||||||
|
@ -635,8 +635,7 @@ PRIMITIVE(gc_stats)
|
||||||
|
|
||||||
void clear_gc_stats()
|
void clear_gc_stats()
|
||||||
{
|
{
|
||||||
int i;
|
for(cell i = 0; i < max_gen_count; i++)
|
||||||
for(i = 0; i < MAX_GEN_COUNT; i++)
|
|
||||||
memset(&stats[i],0,sizeof(gc_stats));
|
memset(&stats[i],0,sizeof(gc_stats));
|
||||||
|
|
||||||
cards_scanned = 0;
|
cards_scanned = 0;
|
||||||
|
@ -683,7 +682,7 @@ PRIMITIVE(become)
|
||||||
|
|
||||||
VM_C_API void minor_gc()
|
VM_C_API void minor_gc()
|
||||||
{
|
{
|
||||||
garbage_collection(NURSERY,false,0);
|
garbage_collection(data->nursery(),false,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,10 @@ void gc();
|
||||||
|
|
||||||
inline static bool collecting_accumulation_gen_p()
|
inline static bool collecting_accumulation_gen_p()
|
||||||
{
|
{
|
||||||
return ((HAVE_AGING_P
|
return ((data->have_aging_p()
|
||||||
&& collecting_gen == AGING
|
&& collecting_gen == data->aging()
|
||||||
&& !collecting_aging_again)
|
&& !collecting_aging_again)
|
||||||
|| collecting_gen == TENURED);
|
|| collecting_gen == data->tenured());
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_handle(cell *handle);
|
void copy_handle(cell *handle);
|
||||||
|
@ -39,7 +39,7 @@ void garbage_collection(volatile cell gen,
|
||||||
/* We leave this many bytes free at the top of the nursery so that inline
|
/* We leave this many bytes free at the top of the nursery so that inline
|
||||||
allocation (which does not call GC because of possible roots in volatile
|
allocation (which does not call GC because of possible roots in volatile
|
||||||
registers) does not run out of memory */
|
registers) does not run out of memory */
|
||||||
#define ALLOT_BUFFER_ZONE 1024
|
static const cell allot_buffer_zone = 1024;
|
||||||
|
|
||||||
inline static object *allot_zone(zone *z, cell a)
|
inline static object *allot_zone(zone *z, cell a)
|
||||||
{
|
{
|
||||||
|
@ -63,11 +63,11 @@ inline static object *allot_object(header header, cell size)
|
||||||
|
|
||||||
object *obj;
|
object *obj;
|
||||||
|
|
||||||
if(nursery.size - ALLOT_BUFFER_ZONE > size)
|
if(nursery.size - allot_buffer_zone > size)
|
||||||
{
|
{
|
||||||
/* If there is insufficient room, collect the nursery */
|
/* If there is insufficient room, collect the nursery */
|
||||||
if(nursery.here + ALLOT_BUFFER_ZONE + size > nursery.end)
|
if(nursery.here + allot_buffer_zone + size > nursery.end)
|
||||||
garbage_collection(NURSERY,false,0);
|
garbage_collection(data->nursery(),false,0);
|
||||||
|
|
||||||
cell h = nursery.here;
|
cell h = nursery.here;
|
||||||
nursery.here = h + align8(size);
|
nursery.here = h + align8(size);
|
||||||
|
@ -77,20 +77,20 @@ inline static object *allot_object(header header, cell size)
|
||||||
tenured space */
|
tenured space */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
zone *tenured = &data->generations[TENURED];
|
zone *tenured = &data->generations[data->tenured()];
|
||||||
|
|
||||||
/* If tenured space does not have enough room, collect */
|
/* If tenured space does not have enough room, collect */
|
||||||
if(tenured->here + size > tenured->end)
|
if(tenured->here + size > tenured->end)
|
||||||
{
|
{
|
||||||
gc();
|
gc();
|
||||||
tenured = &data->generations[TENURED];
|
tenured = &data->generations[data->tenured()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it still won't fit, grow the heap */
|
/* If it still won't fit, grow the heap */
|
||||||
if(tenured->here + size > tenured->end)
|
if(tenured->here + size > tenured->end)
|
||||||
{
|
{
|
||||||
garbage_collection(TENURED,true,size);
|
garbage_collection(data->tenured(),true,size);
|
||||||
tenured = &data->generations[TENURED];
|
tenured = &data->generations[data->tenured()];
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = allot_zone(tenured,size);
|
obj = allot_zone(tenured,size);
|
||||||
|
|
|
@ -26,10 +26,10 @@ cell init_zone(zone *z, cell size, cell start)
|
||||||
|
|
||||||
void init_card_decks()
|
void init_card_decks()
|
||||||
{
|
{
|
||||||
cell start = align(data->seg->start,DECK_SIZE);
|
cell start = align(data->seg->start,deck_size);
|
||||||
allot_markers_offset = (cell)data->allot_markers - (start >> CARD_BITS);
|
allot_markers_offset = (cell)data->allot_markers - (start >> card_bits);
|
||||||
cards_offset = (cell)data->cards - (start >> CARD_BITS);
|
cards_offset = (cell)data->cards - (start >> card_bits);
|
||||||
decks_offset = (cell)data->decks - (start >> DECK_BITS);
|
decks_offset = (cell)data->decks - (start >> deck_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
data_heap *alloc_data_heap(cell gens,
|
data_heap *alloc_data_heap(cell gens,
|
||||||
|
@ -37,9 +37,9 @@ data_heap *alloc_data_heap(cell gens,
|
||||||
cell aging_size,
|
cell aging_size,
|
||||||
cell tenured_size)
|
cell tenured_size)
|
||||||
{
|
{
|
||||||
young_size = align(young_size,DECK_SIZE);
|
young_size = align(young_size,deck_size);
|
||||||
aging_size = align(aging_size,DECK_SIZE);
|
aging_size = align(aging_size,deck_size);
|
||||||
tenured_size = align(tenured_size,DECK_SIZE);
|
tenured_size = align(tenured_size,deck_size);
|
||||||
|
|
||||||
data_heap *data = (data_heap *)safe_malloc(sizeof(data_heap));
|
data_heap *data = (data_heap *)safe_malloc(sizeof(data_heap));
|
||||||
data->young_size = young_size;
|
data->young_size = young_size;
|
||||||
|
@ -58,42 +58,42 @@ data_heap *alloc_data_heap(cell gens,
|
||||||
return NULL; /* can't happen */
|
return NULL; /* can't happen */
|
||||||
}
|
}
|
||||||
|
|
||||||
total_size += DECK_SIZE;
|
total_size += deck_size;
|
||||||
|
|
||||||
data->seg = alloc_segment(total_size);
|
data->seg = alloc_segment(total_size);
|
||||||
|
|
||||||
data->generations = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
|
data->generations = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
|
||||||
data->semispaces = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
|
data->semispaces = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
|
||||||
|
|
||||||
cell cards_size = total_size >> CARD_BITS;
|
cell cards_size = total_size >> card_bits;
|
||||||
data->allot_markers = (cell *)safe_malloc(cards_size);
|
data->allot_markers = (cell *)safe_malloc(cards_size);
|
||||||
data->allot_markers_end = data->allot_markers + cards_size;
|
data->allot_markers_end = data->allot_markers + cards_size;
|
||||||
|
|
||||||
data->cards = (cell *)safe_malloc(cards_size);
|
data->cards = (cell *)safe_malloc(cards_size);
|
||||||
data->cards_end = data->cards + cards_size;
|
data->cards_end = data->cards + cards_size;
|
||||||
|
|
||||||
cell decks_size = total_size >> DECK_BITS;
|
cell decks_size = total_size >> deck_bits;
|
||||||
data->decks = (cell *)safe_malloc(decks_size);
|
data->decks = (cell *)safe_malloc(decks_size);
|
||||||
data->decks_end = data->decks + decks_size;
|
data->decks_end = data->decks + decks_size;
|
||||||
|
|
||||||
cell alloter = align(data->seg->start,DECK_SIZE);
|
cell alloter = align(data->seg->start,deck_size);
|
||||||
|
|
||||||
alloter = init_zone(&data->generations[TENURED],tenured_size,alloter);
|
alloter = init_zone(&data->generations[data->tenured()],tenured_size,alloter);
|
||||||
alloter = init_zone(&data->semispaces[TENURED],tenured_size,alloter);
|
alloter = init_zone(&data->semispaces[data->tenured()],tenured_size,alloter);
|
||||||
|
|
||||||
if(data->gen_count == 3)
|
if(data->gen_count == 3)
|
||||||
{
|
{
|
||||||
alloter = init_zone(&data->generations[AGING],aging_size,alloter);
|
alloter = init_zone(&data->generations[data->aging()],aging_size,alloter);
|
||||||
alloter = init_zone(&data->semispaces[AGING],aging_size,alloter);
|
alloter = init_zone(&data->semispaces[data->aging()],aging_size,alloter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->gen_count >= 2)
|
if(data->gen_count >= 2)
|
||||||
{
|
{
|
||||||
alloter = init_zone(&data->generations[NURSERY],young_size,alloter);
|
alloter = init_zone(&data->generations[data->nursery()],young_size,alloter);
|
||||||
alloter = init_zone(&data->semispaces[NURSERY],0,alloter);
|
alloter = init_zone(&data->semispaces[data->nursery()],0,alloter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->seg->end - alloter > DECK_SIZE)
|
if(data->seg->end - alloter > deck_size)
|
||||||
critical_error("Bug in alloc_data_heap",alloter);
|
critical_error("Bug in alloc_data_heap",alloter);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -141,12 +141,12 @@ void clear_allot_markers(cell from, cell to)
|
||||||
/* NOTE: reverse order due to heap layout. */
|
/* NOTE: reverse order due to heap layout. */
|
||||||
card *first_card = addr_to_allot_marker((object *)data->generations[to].start);
|
card *first_card = addr_to_allot_marker((object *)data->generations[to].start);
|
||||||
card *last_card = addr_to_allot_marker((object *)data->generations[from].end);
|
card *last_card = addr_to_allot_marker((object *)data->generations[from].end);
|
||||||
memset(first_card,INVALID_ALLOT_MARKER,last_card - first_card);
|
memset(first_card,invalid_allot_marker,last_card - first_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_generation(cell i)
|
void reset_generation(cell i)
|
||||||
{
|
{
|
||||||
zone *z = (i == NURSERY ? &nursery : &data->generations[i]);
|
zone *z = (i == data->nursery() ? &nursery : &data->generations[i]);
|
||||||
|
|
||||||
z->here = z->start;
|
z->here = z->start;
|
||||||
if(secure_gc)
|
if(secure_gc)
|
||||||
|
@ -169,11 +169,11 @@ void reset_generations(cell from, cell to)
|
||||||
void set_data_heap(data_heap *data_)
|
void set_data_heap(data_heap *data_)
|
||||||
{
|
{
|
||||||
data = data_;
|
data = data_;
|
||||||
nursery = data->generations[NURSERY];
|
nursery = data->generations[data->nursery()];
|
||||||
init_card_decks();
|
init_card_decks();
|
||||||
clear_cards(NURSERY,TENURED);
|
clear_cards(data->nursery(),data->tenured());
|
||||||
clear_decks(NURSERY,TENURED);
|
clear_decks(data->nursery(),data->tenured());
|
||||||
clear_allot_markers(NURSERY,TENURED);
|
clear_allot_markers(data->nursery(),data->tenured());
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_data_heap(cell gens,
|
void init_data_heap(cell gens,
|
||||||
|
@ -298,7 +298,7 @@ PRIMITIVE(data_room)
|
||||||
cell gen;
|
cell gen;
|
||||||
for(gen = 0; gen < data->gen_count; gen++)
|
for(gen = 0; gen < data->gen_count; gen++)
|
||||||
{
|
{
|
||||||
zone *z = (gen == NURSERY ? &nursery : &data->generations[gen]);
|
zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]);
|
||||||
a.add(tag_fixnum((z->end - z->here) >> 10));
|
a.add(tag_fixnum((z->end - z->here) >> 10));
|
||||||
a.add(tag_fixnum((z->size) >> 10));
|
a.add(tag_fixnum((z->size) >> 10));
|
||||||
}
|
}
|
||||||
|
@ -314,7 +314,7 @@ cell heap_scan_ptr;
|
||||||
/* Disables GC and activates next-object ( -- obj ) primitive */
|
/* Disables GC and activates next-object ( -- obj ) primitive */
|
||||||
void begin_scan()
|
void begin_scan()
|
||||||
{
|
{
|
||||||
heap_scan_ptr = data->generations[TENURED].start;
|
heap_scan_ptr = data->generations[data->tenured()].start;
|
||||||
gc_off = true;
|
gc_off = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ cell next_object()
|
||||||
if(!gc_off)
|
if(!gc_off)
|
||||||
general_error(ERROR_HEAP_SCAN,F,F,NULL);
|
general_error(ERROR_HEAP_SCAN,F,F,NULL);
|
||||||
|
|
||||||
if(heap_scan_ptr >= data->generations[TENURED].here)
|
if(heap_scan_ptr >= data->generations[data->tenured()].here)
|
||||||
return F;
|
return F;
|
||||||
|
|
||||||
object *obj = (object *)heap_scan_ptr;
|
object *obj = (object *)heap_scan_ptr;
|
||||||
|
|
|
@ -34,20 +34,22 @@ struct data_heap {
|
||||||
|
|
||||||
cell *decks;
|
cell *decks;
|
||||||
cell *decks_end;
|
cell *decks_end;
|
||||||
|
|
||||||
|
/* the 0th generation is where new objects are allocated. */
|
||||||
|
cell nursery() { return 0; }
|
||||||
|
|
||||||
|
/* where objects hang around */
|
||||||
|
cell aging() { return gen_count - 2; }
|
||||||
|
|
||||||
|
/* the oldest generation */
|
||||||
|
cell tenured() { return gen_count - 1; }
|
||||||
|
|
||||||
|
bool have_aging_p() { return gen_count > 2; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern data_heap *data;
|
extern data_heap *data;
|
||||||
|
|
||||||
/* the 0th generation is where new objects are allocated. */
|
static const cell max_gen_count = 3;
|
||||||
#define NURSERY 0
|
|
||||||
/* where objects hang around */
|
|
||||||
#define AGING (data->gen_count-2)
|
|
||||||
#define HAVE_AGING_P (data->gen_count>2)
|
|
||||||
/* the oldest generation */
|
|
||||||
#define TENURED (data->gen_count-1)
|
|
||||||
|
|
||||||
#define MIN_GEN_COUNT 1
|
|
||||||
#define MAX_GEN_COUNT 3
|
|
||||||
|
|
||||||
inline static bool in_zone(zone *z, object *pointer)
|
inline static bool in_zone(zone *z, object *pointer)
|
||||||
{
|
{
|
||||||
|
|
16
vm/image.cpp
16
vm/image.cpp
|
@ -31,7 +31,7 @@ static void load_data_heap(FILE *file, image_header *h, vm_parameters *p)
|
||||||
|
|
||||||
clear_gc_stats();
|
clear_gc_stats();
|
||||||
|
|
||||||
zone *tenured = &data->generations[TENURED];
|
zone *tenured = &data->generations[data->tenured()];
|
||||||
|
|
||||||
fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
|
fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
|
||||||
|
|
||||||
|
@ -92,10 +92,10 @@ bool save_image(const vm_char *filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zone *tenured = &data->generations[TENURED];
|
zone *tenured = &data->generations[data->tenured()];
|
||||||
|
|
||||||
h.magic = IMAGE_MAGIC;
|
h.magic = image_magic;
|
||||||
h.version = IMAGE_VERSION;
|
h.version = image_version;
|
||||||
h.data_relocation_base = tenured->start;
|
h.data_relocation_base = tenured->start;
|
||||||
h.data_size = tenured->here - tenured->start;
|
h.data_size = tenured->here - tenured->start;
|
||||||
h.code_relocation_base = code.seg->start;
|
h.code_relocation_base = code.seg->start;
|
||||||
|
@ -165,7 +165,7 @@ static void data_fixup(cell *cell)
|
||||||
if(immediate_p(*cell))
|
if(immediate_p(*cell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zone *tenured = &data->generations[TENURED];
|
zone *tenured = &data->generations[data->tenured()];
|
||||||
*cell += (tenured->start - data_relocation_base);
|
*cell += (tenured->start - data_relocation_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ void relocate_data()
|
||||||
data_fixup(&bignum_pos_one);
|
data_fixup(&bignum_pos_one);
|
||||||
data_fixup(&bignum_neg_one);
|
data_fixup(&bignum_neg_one);
|
||||||
|
|
||||||
zone *tenured = &data->generations[TENURED];
|
zone *tenured = &data->generations[data->tenured()];
|
||||||
|
|
||||||
for(relocating = tenured->start;
|
for(relocating = tenured->start;
|
||||||
relocating < tenured->here;
|
relocating < tenured->here;
|
||||||
|
@ -313,10 +313,10 @@ void load_image(vm_parameters *p)
|
||||||
if(fread(&h,sizeof(image_header),1,file) != 1)
|
if(fread(&h,sizeof(image_header),1,file) != 1)
|
||||||
fatal_error("Cannot read image header",0);
|
fatal_error("Cannot read image header",0);
|
||||||
|
|
||||||
if(h.magic != IMAGE_MAGIC)
|
if(h.magic != image_magic)
|
||||||
fatal_error("Bad image: magic number check failed",h.magic);
|
fatal_error("Bad image: magic number check failed",h.magic);
|
||||||
|
|
||||||
if(h.version != IMAGE_VERSION)
|
if(h.version != image_version)
|
||||||
fatal_error("Bad image: version number check failed",h.version);
|
fatal_error("Bad image: version number check failed",h.version);
|
||||||
|
|
||||||
load_data_heap(file,&h,p);
|
load_data_heap(file,&h,p);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
#define IMAGE_MAGIC 0x0f0e0d0c
|
static const cell image_magic = 0x0f0e0d0c;
|
||||||
#define IMAGE_VERSION 4
|
static const cell image_version = 4;
|
||||||
|
|
||||||
struct image_header {
|
struct image_header {
|
||||||
cell magic;
|
cell magic;
|
||||||
|
|
|
@ -23,8 +23,15 @@ inline static cell align(cell a, cell b)
|
||||||
return (a + (b-1)) & ~(b-1);
|
return (a + (b-1)) & ~(b-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define align8(a) align(a,8)
|
inline static cell align8(cell a)
|
||||||
#define align_page(a) align(a,getpagesize())
|
{
|
||||||
|
return align(a,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static cell align_page(cell a)
|
||||||
|
{
|
||||||
|
return align(a,getpagesize());
|
||||||
|
}
|
||||||
|
|
||||||
#define WORD_SIZE (signed)(sizeof(cell)*8)
|
#define WORD_SIZE (signed)(sizeof(cell)*8)
|
||||||
|
|
||||||
|
@ -297,12 +304,6 @@ struct dll : public object {
|
||||||
void *dll;
|
void *dll;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct callstack : public object {
|
|
||||||
static const cell type_number = CALLSTACK_TYPE;
|
|
||||||
/* tagged */
|
|
||||||
cell length;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stack_frame
|
struct stack_frame
|
||||||
{
|
{
|
||||||
void *xt;
|
void *xt;
|
||||||
|
@ -310,6 +311,15 @@ struct stack_frame
|
||||||
cell size;
|
cell size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct callstack : public object {
|
||||||
|
static const cell type_number = CALLSTACK_TYPE;
|
||||||
|
/* tagged */
|
||||||
|
cell length;
|
||||||
|
|
||||||
|
stack_frame *top() { return (stack_frame *)(this + 1); }
|
||||||
|
stack_frame *bottom() { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
|
||||||
|
};
|
||||||
|
|
||||||
struct tuple : public object {
|
struct tuple : public object {
|
||||||
static const cell type_number = TUPLE_TYPE;
|
static const cell type_number = TUPLE_TYPE;
|
||||||
/* tagged layout */
|
/* tagged layout */
|
||||||
|
|
39
vm/math.cpp
39
vm/math.cpp
|
@ -24,8 +24,8 @@ PRIMITIVE(fixnum_divint)
|
||||||
fixnum y = untag_fixnum(dpop()); \
|
fixnum y = untag_fixnum(dpop()); \
|
||||||
fixnum x = untag_fixnum(dpeek());
|
fixnum x = untag_fixnum(dpeek());
|
||||||
fixnum result = x / y;
|
fixnum result = x / y;
|
||||||
if(result == -FIXNUM_MIN)
|
if(result == -fixnum_min)
|
||||||
drepl(allot_integer(-FIXNUM_MIN));
|
drepl(allot_integer(-fixnum_min));
|
||||||
else
|
else
|
||||||
drepl(tag_fixnum(result));
|
drepl(tag_fixnum(result));
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,9 @@ PRIMITIVE(fixnum_divmod)
|
||||||
{
|
{
|
||||||
cell y = ((cell *)ds)[0];
|
cell y = ((cell *)ds)[0];
|
||||||
cell x = ((cell *)ds)[-1];
|
cell x = ((cell *)ds)[-1];
|
||||||
if(y == tag_fixnum(-1) && x == tag_fixnum(FIXNUM_MIN))
|
if(y == tag_fixnum(-1) && x == tag_fixnum(fixnum_min))
|
||||||
{
|
{
|
||||||
((cell *)ds)[-1] = allot_integer(-FIXNUM_MIN);
|
((cell *)ds)[-1] = allot_integer(-fixnum_min);
|
||||||
((cell *)ds)[0] = tag_fixnum(0);
|
((cell *)ds)[0] = tag_fixnum(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -50,9 +50,20 @@ PRIMITIVE(fixnum_divmod)
|
||||||
* If we're shifting right by n bits, we won't overflow as long as none of the
|
* If we're shifting right by n bits, we won't overflow as long as none of the
|
||||||
* high WORD_SIZE-TAG_BITS-n bits are set.
|
* high WORD_SIZE-TAG_BITS-n bits are set.
|
||||||
*/
|
*/
|
||||||
#define SIGN_MASK(x) ((x) >> (WORD_SIZE - 1))
|
static inline fixnum sign_mask(fixnum x)
|
||||||
#define BRANCHLESS_MAX(x,y) ((x) - (((x) - (y)) & SIGN_MASK((x) - (y))))
|
{
|
||||||
#define BRANCHLESS_ABS(x) ((x ^ SIGN_MASK(x)) - SIGN_MASK(x))
|
return x >> (WORD_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline fixnum branchless_max(fixnum x, fixnum y)
|
||||||
|
{
|
||||||
|
return (x - ((x - y) & sign_mask(x - y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline fixnum branchless_abs(fixnum x)
|
||||||
|
{
|
||||||
|
return (x ^ sign_mask(x)) - sign_mask(x);
|
||||||
|
}
|
||||||
|
|
||||||
PRIMITIVE(fixnum_shift)
|
PRIMITIVE(fixnum_shift)
|
||||||
{
|
{
|
||||||
|
@ -63,14 +74,14 @@ PRIMITIVE(fixnum_shift)
|
||||||
return;
|
return;
|
||||||
else if(y < 0)
|
else if(y < 0)
|
||||||
{
|
{
|
||||||
y = BRANCHLESS_MAX(y,-WORD_SIZE + 1);
|
y = branchless_max(y,-WORD_SIZE + 1);
|
||||||
drepl(tag_fixnum(x >> -y));
|
drepl(tag_fixnum(x >> -y));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(y < WORD_SIZE - TAG_BITS)
|
else if(y < WORD_SIZE - TAG_BITS)
|
||||||
{
|
{
|
||||||
fixnum mask = -((fixnum)1 << (WORD_SIZE - 1 - TAG_BITS - y));
|
fixnum mask = -((fixnum)1 << (WORD_SIZE - 1 - TAG_BITS - y));
|
||||||
if(!(BRANCHLESS_ABS(x) & mask))
|
if(!(branchless_abs(x) & mask))
|
||||||
{
|
{
|
||||||
drepl(tag_fixnum(x << y));
|
drepl(tag_fixnum(x << y));
|
||||||
return;
|
return;
|
||||||
|
@ -226,7 +237,7 @@ cell unbox_array_size()
|
||||||
case FIXNUM_TYPE:
|
case FIXNUM_TYPE:
|
||||||
{
|
{
|
||||||
fixnum n = untag_fixnum(dpeek());
|
fixnum n = untag_fixnum(dpeek());
|
||||||
if(n >= 0 && n < (fixnum)ARRAY_SIZE_MAX)
|
if(n >= 0 && n < (fixnum)array_size_max)
|
||||||
{
|
{
|
||||||
dpop();
|
dpop();
|
||||||
return n;
|
return n;
|
||||||
|
@ -236,7 +247,7 @@ cell unbox_array_size()
|
||||||
case BIGNUM_TYPE:
|
case BIGNUM_TYPE:
|
||||||
{
|
{
|
||||||
bignum * zero = untag<bignum>(bignum_zero);
|
bignum * zero = untag<bignum>(bignum_zero);
|
||||||
bignum * max = cell_to_bignum(ARRAY_SIZE_MAX);
|
bignum * max = cell_to_bignum(array_size_max);
|
||||||
bignum * n = untag<bignum>(dpeek());
|
bignum * n = untag<bignum>(dpeek());
|
||||||
if(bignum_compare(n,zero) != bignum_comparison_less
|
if(bignum_compare(n,zero) != bignum_comparison_less
|
||||||
&& bignum_compare(n,max) == bignum_comparison_less)
|
&& bignum_compare(n,max) == bignum_comparison_less)
|
||||||
|
@ -248,7 +259,7 @@ cell unbox_array_size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(ARRAY_SIZE_MAX),NULL);
|
general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(array_size_max),NULL);
|
||||||
return 0; /* can't happen */
|
return 0; /* can't happen */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +439,7 @@ VM_C_API void box_unsigned_cell(cell cell)
|
||||||
|
|
||||||
VM_C_API void box_signed_8(s64 n)
|
VM_C_API void box_signed_8(s64 n)
|
||||||
{
|
{
|
||||||
if(n < FIXNUM_MIN || n > FIXNUM_MAX)
|
if(n < fixnum_min || n > fixnum_max)
|
||||||
dpush(tag<bignum>(long_long_to_bignum(n)));
|
dpush(tag<bignum>(long_long_to_bignum(n)));
|
||||||
else
|
else
|
||||||
dpush(tag_fixnum(n));
|
dpush(tag_fixnum(n));
|
||||||
|
@ -450,7 +461,7 @@ VM_C_API s64 to_signed_8(cell obj)
|
||||||
|
|
||||||
VM_C_API void box_unsigned_8(u64 n)
|
VM_C_API void box_unsigned_8(u64 n)
|
||||||
{
|
{
|
||||||
if(n > FIXNUM_MAX)
|
if(n > fixnum_max)
|
||||||
dpush(tag<bignum>(ulong_long_to_bignum(n)));
|
dpush(tag<bignum>(ulong_long_to_bignum(n)));
|
||||||
else
|
else
|
||||||
dpush(tag_fixnum(n));
|
dpush(tag_fixnum(n));
|
||||||
|
|
11
vm/math.hpp
11
vm/math.hpp
|
@ -5,10 +5,9 @@ extern cell bignum_zero;
|
||||||
extern cell bignum_pos_one;
|
extern cell bignum_pos_one;
|
||||||
extern cell bignum_neg_one;
|
extern cell bignum_neg_one;
|
||||||
|
|
||||||
#define cell_MAX (cell)(-1)
|
static const fixnum fixnum_max = (((fixnum)1 << (WORD_SIZE - TAG_BITS - 1)) - 1);
|
||||||
#define FIXNUM_MAX (((fixnum)1 << (WORD_SIZE - TAG_BITS - 1)) - 1)
|
static const fixnum fixnum_min = (-((fixnum)1 << (WORD_SIZE - TAG_BITS - 1)));
|
||||||
#define FIXNUM_MIN (-((fixnum)1 << (WORD_SIZE - TAG_BITS - 1)))
|
static const fixnum array_size_max = ((cell)1 << (WORD_SIZE - TAG_BITS - 2));
|
||||||
#define ARRAY_SIZE_MAX ((cell)1 << (WORD_SIZE - TAG_BITS - 2))
|
|
||||||
|
|
||||||
PRIMITIVE(fixnum_add);
|
PRIMITIVE(fixnum_add);
|
||||||
PRIMITIVE(fixnum_subtract);
|
PRIMITIVE(fixnum_subtract);
|
||||||
|
@ -45,7 +44,7 @@ PRIMITIVE(byte_array_to_bignum);
|
||||||
|
|
||||||
inline static cell allot_integer(fixnum x)
|
inline static cell allot_integer(fixnum x)
|
||||||
{
|
{
|
||||||
if(x < FIXNUM_MIN || x > FIXNUM_MAX)
|
if(x < fixnum_min || x > fixnum_max)
|
||||||
return tag<bignum>(fixnum_to_bignum(x));
|
return tag<bignum>(fixnum_to_bignum(x));
|
||||||
else
|
else
|
||||||
return tag_fixnum(x);
|
return tag_fixnum(x);
|
||||||
|
@ -53,7 +52,7 @@ inline static cell allot_integer(fixnum x)
|
||||||
|
|
||||||
inline static cell allot_cell(cell x)
|
inline static cell allot_cell(cell x)
|
||||||
{
|
{
|
||||||
if(x > (cell)FIXNUM_MAX)
|
if(x > (cell)fixnum_max)
|
||||||
return tag<bignum>(cell_to_bignum(x));
|
return tag<bignum>(cell_to_bignum(x));
|
||||||
else
|
else
|
||||||
return tag_fixnum(x);
|
return tag_fixnum(x);
|
||||||
|
|
|
@ -12,24 +12,24 @@ VM_C_API factor::cell decks_offset;
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
/* if CARD_POINTS_TO_NURSERY is set, CARD_POINTS_TO_AGING must also be set. */
|
/* if card_points_to_nursery is set, card_points_to_aging must also be set. */
|
||||||
#define CARD_POINTS_TO_NURSERY 0x80
|
static const cell card_points_to_nursery = 0x80;
|
||||||
#define CARD_POINTS_TO_AGING 0x40
|
static const cell card_points_to_aging = 0x40;
|
||||||
#define CARD_MARK_MASK (CARD_POINTS_TO_NURSERY | CARD_POINTS_TO_AGING)
|
static const cell card_mark_mask = (card_points_to_nursery | card_points_to_aging);
|
||||||
typedef u8 card;
|
typedef u8 card;
|
||||||
|
|
||||||
#define CARD_BITS 8
|
static const cell card_bits = 8;
|
||||||
#define CARD_SIZE (1<<CARD_BITS)
|
static const cell card_size = (1<<card_bits);
|
||||||
#define ADDR_CARD_MASK (CARD_SIZE-1)
|
static const cell addr_card_mask = (card_size-1);
|
||||||
|
|
||||||
inline static card *addr_to_card(cell a)
|
inline static card *addr_to_card(cell a)
|
||||||
{
|
{
|
||||||
return (card*)(((cell)(a) >> CARD_BITS) + cards_offset);
|
return (card*)(((cell)(a) >> card_bits) + cards_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static cell card_to_addr(card *c)
|
inline static cell card_to_addr(card *c)
|
||||||
{
|
{
|
||||||
return ((cell)c - cards_offset) << CARD_BITS;
|
return ((cell)c - cards_offset) << card_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static cell card_offset(card *c)
|
inline static cell card_offset(card *c)
|
||||||
|
@ -39,48 +39,48 @@ inline static cell card_offset(card *c)
|
||||||
|
|
||||||
typedef u8 card_deck;
|
typedef u8 card_deck;
|
||||||
|
|
||||||
#define DECK_BITS (CARD_BITS + 10)
|
static const cell deck_bits = (card_bits + 10);
|
||||||
#define DECK_SIZE (1<<DECK_BITS)
|
static const cell deck_size = (1<<deck_bits);
|
||||||
#define ADDR_DECK_MASK (DECK_SIZE-1)
|
static const cell addr_deck_mask = (deck_size-1);
|
||||||
|
|
||||||
inline static card_deck *addr_to_deck(cell a)
|
inline static card_deck *addr_to_deck(cell a)
|
||||||
{
|
{
|
||||||
return (card_deck *)(((cell)a >> DECK_BITS) + decks_offset);
|
return (card_deck *)(((cell)a >> deck_bits) + decks_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static cell deck_to_addr(card_deck *c)
|
inline static cell deck_to_addr(card_deck *c)
|
||||||
{
|
{
|
||||||
return ((cell)c - decks_offset) << DECK_BITS;
|
return ((cell)c - decks_offset) << deck_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static card *deck_to_card(card_deck *d)
|
inline static card *deck_to_card(card_deck *d)
|
||||||
{
|
{
|
||||||
return (card *)((((cell)d - decks_offset) << (DECK_BITS - CARD_BITS)) + cards_offset);
|
return (card *)((((cell)d - decks_offset) << (deck_bits - card_bits)) + cards_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INVALID_ALLOT_MARKER 0xff
|
static const cell invalid_allot_marker = 0xff;
|
||||||
|
|
||||||
extern cell allot_markers_offset;
|
extern cell allot_markers_offset;
|
||||||
|
|
||||||
inline static card *addr_to_allot_marker(object *a)
|
inline static card *addr_to_allot_marker(object *a)
|
||||||
{
|
{
|
||||||
return (card *)(((cell)a >> CARD_BITS) + allot_markers_offset);
|
return (card *)(((cell)a >> card_bits) + allot_markers_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the write barrier must be called any time we are potentially storing a
|
/* the write barrier must be called any time we are potentially storing a
|
||||||
pointer from an older generation to a younger one */
|
pointer from an older generation to a younger one */
|
||||||
inline static void write_barrier(object *obj)
|
inline static void write_barrier(object *obj)
|
||||||
{
|
{
|
||||||
*addr_to_card((cell)obj) = CARD_MARK_MASK;
|
*addr_to_card((cell)obj) = card_mark_mask;
|
||||||
*addr_to_deck((cell)obj) = CARD_MARK_MASK;
|
*addr_to_deck((cell)obj) = card_mark_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need to remember the first object allocated in the card */
|
/* we need to remember the first object allocated in the card */
|
||||||
inline static void allot_barrier(object *address)
|
inline static void allot_barrier(object *address)
|
||||||
{
|
{
|
||||||
card *ptr = addr_to_allot_marker(address);
|
card *ptr = addr_to_allot_marker(address);
|
||||||
if(*ptr == INVALID_ALLOT_MARKER)
|
if(*ptr == invalid_allot_marker)
|
||||||
*ptr = ((cell)address & ADDR_CARD_MASK);
|
*ptr = ((cell)address & addr_card_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue