vm: object start recording in cards is now independent of allocation strategy

db4
Slava Pestov 2009-10-20 13:47:04 -05:00
parent d22d5466fc
commit e482940dca
12 changed files with 91 additions and 49 deletions

View File

@ -1,8 +1,20 @@
namespace factor namespace factor
{ {
struct aging_space : old_space { struct aging_space : zone {
aging_space(cell size, cell start) : old_space(size,start) {} object_start_map starts;
aging_space(cell size, cell start) :
zone(size,start), starts(size,start) {}
object *allot(cell size)
{
if(here + size > end) return NULL;
object *obj = zone::allot(size);
starts.record_object_start_offset(obj);
return obj;
}
}; };
} }

View File

@ -6,11 +6,6 @@ struct code_heap_layout {
{ {
return block->size(); return block->size();
} }
heap_block *next_block_after(heap_block *block)
{
return (heap_block *)((cell)block + block_size(block));
}
}; };
struct code_heap : heap<heap_block,code_heap_layout> { struct code_heap : heap<heap_block,code_heap_layout> {

View File

@ -95,7 +95,7 @@ struct copying_collector : collector<TargetGeneration,Policy> {
if(end < card_start_address(card_index)) if(end < card_start_address(card_index))
{ {
start = gen->find_object_containing_card(card_index - gen_start_card); start = gen->starts.find_object_containing_card(card_index - gen_start_card);
binary_start = start + this->parent->binary_payload_start((object *)start); binary_start = start + this->parent->binary_payload_start((object *)start);
end = start + ((object *)start)->size(); end = start + ((object *)start)->size();
} }

View File

@ -52,7 +52,7 @@ template<typename Generation> void data_heap::reset_generation(Generation *gen)
clear_cards(gen); clear_cards(gen);
clear_decks(gen); clear_decks(gen);
gen->clear_object_start_offsets(); gen->starts.clear_object_start_offsets();
} }
} }

View File

@ -28,6 +28,11 @@ template<typename Block, typename HeapLayout> struct heap {
return (Block *)seg->end; return (Block *)seg->end;
} }
Block *next_block_after(heap_block *block)
{
return (Block *)((cell)block + layout.block_size(block));
}
void clear_free_list(); void clear_free_list();
void add_to_free_list(free_heap_block *block); void add_to_free_list(free_heap_block *block);
void build_free_list(cell size); void build_free_list(cell size);
@ -50,7 +55,7 @@ template<typename Block, typename HeapLayout> struct heap {
while(scan != end) while(scan != end)
{ {
Block *next = layout.next_block_after(scan); Block *next = next_block_after(scan);
if(!scan->free_p()) iter(scan,layout.block_size(scan)); if(!scan->free_p()) iter(scan,layout.block_size(scan));
scan = next; scan = next;
} }
@ -229,7 +234,7 @@ void heap<Block,HeapLayout>::heap_usage(cell *used, cell *total_free, cell *max_
else else
*used += size; *used += size;
scan = layout.next_block_after(scan); scan = next_block_after(scan);
} }
} }
@ -243,7 +248,7 @@ cell heap<Block,HeapLayout>::heap_size()
while(scan != end) while(scan != end)
{ {
if(scan->free_p()) break; if(scan->free_p()) break;
else scan = layout.next_block_after(scan); else scan = next_block_after(scan);
} }
if(scan != end) if(scan != end)
@ -308,7 +313,7 @@ void heap<Block,HeapLayout>::sweep_heap(Iterator &iter)
} }
} }
scan = layout.next_block_after(scan); scan = next_block_after(scan);
} }
if(prev && prev->free_p()) if(prev && prev->free_p())

View File

@ -203,7 +203,7 @@ void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_ba
while(obj) while(obj)
{ {
relocate_object((object *)obj,data_relocation_base,code_relocation_base); relocate_object((object *)obj,data_relocation_base,code_relocation_base);
data->tenured->record_object_start_offset((object *)obj); data->tenured->starts.record_object_start_offset((object *)obj);
obj = data->tenured->next_object_after(obj); obj = data->tenured->next_object_after(obj);
} }
} }

View File

@ -148,8 +148,17 @@ struct header {
struct object { struct object {
NO_TYPE_CHECK; NO_TYPE_CHECK;
header h; header h;
cell *slots() { return (cell *)this; }
cell size(); cell size();
cell *slots() { return (cell *)this; }
/* Only valid for objects in tenured space; must fast to free_heap_block
to do anything with it if its free */
bool free_p()
{
return h.value & 1 == 1;
}
}; };
/* Assembly code makes assumptions about the layout of this struct */ /* Assembly code makes assumptions about the layout of this struct */

View File

@ -70,10 +70,15 @@ template<typename Block, typename HeapLayout> struct mark_bits {
return (bits[pair.first] & ((u64)1 << pair.second)) != 0; return (bits[pair.first] & ((u64)1 << pair.second)) != 0;
} }
Block *next_block_after(Block *block)
{
return (Block *)((cell)block + layout.block_size(block));
}
void set_bitmap_range(u64 *bits, Block *address) void set_bitmap_range(u64 *bits, Block *address)
{ {
std::pair<cell,cell> start = bitmap_deref(address); std::pair<cell,cell> start = bitmap_deref(address);
std::pair<cell,cell> end = bitmap_deref(layout.next_block_after(address)); std::pair<cell,cell> end = bitmap_deref(next_block_after(address));
u64 start_mask = ((u64)1 << start.second) - 1; u64 start_mask = ((u64)1 << start.second) - 1;
u64 end_mask = ((u64)1 << end.second) - 1; u64 end_mask = ((u64)1 << end.second) - 1;

View File

@ -3,23 +3,24 @@
namespace factor namespace factor
{ {
old_space::old_space(cell size_, cell start_) : zone(size_,start_) object_start_map::object_start_map(cell size_, cell start_) :
size(size_), start(start_)
{ {
object_start_offsets = new card[addr_to_card(size_)]; object_start_offsets = new card[addr_to_card(size_)];
object_start_offsets_end = object_start_offsets + addr_to_card(size_); object_start_offsets_end = object_start_offsets + addr_to_card(size_);
} }
old_space::~old_space() object_start_map::~object_start_map()
{ {
delete[] object_start_offsets; delete[] object_start_offsets;
} }
cell old_space::first_object_in_card(cell card_index) cell object_start_map::first_object_in_card(cell card_index)
{ {
return object_start_offsets[card_index]; return object_start_offsets[card_index];
} }
cell old_space::find_object_containing_card(cell card_index) cell object_start_map::find_object_containing_card(cell card_index)
{ {
if(card_index == 0) if(card_index == 0)
return start; return start;
@ -41,34 +42,16 @@ cell old_space::find_object_containing_card(cell card_index)
} }
/* we need to remember the first object allocated in the card */ /* we need to remember the first object allocated in the card */
void old_space::record_object_start_offset(object *obj) void object_start_map::record_object_start_offset(object *obj)
{ {
cell idx = addr_to_card((cell)obj - start); cell idx = addr_to_card((cell)obj - start);
if(object_start_offsets[idx] == card_starts_inside_object) card obj_start = ((cell)obj & addr_card_mask);
object_start_offsets[idx] = ((cell)obj & addr_card_mask); object_start_offsets[idx] = std::min(object_start_offsets[idx],obj_start);
} }
object *old_space::allot(cell size) void object_start_map::clear_object_start_offsets()
{
if(here + size > end) return NULL;
object *obj = zone::allot(size);
record_object_start_offset(obj);
return obj;
}
void old_space::clear_object_start_offsets()
{ {
memset(object_start_offsets,card_starts_inside_object,addr_to_card(size)); memset(object_start_offsets,card_starts_inside_object,addr_to_card(size));
} }
cell old_space::next_object_after(cell scan)
{
cell size = ((object *)scan)->size();
if(scan + size < here)
return scan + size;
else
return 0;
}
} }

View File

@ -3,19 +3,18 @@ namespace factor
static const cell card_starts_inside_object = 0xff; static const cell card_starts_inside_object = 0xff;
struct old_space : zone { struct object_start_map {
cell size, start;
card *object_start_offsets; card *object_start_offsets;
card *object_start_offsets_end; card *object_start_offsets_end;
old_space(cell size_, cell start_); object_start_map(cell size_, cell start_);
~old_space(); ~object_start_map();
cell first_object_in_card(cell card_index); cell first_object_in_card(cell card_index);
cell find_object_containing_card(cell card_index); cell find_object_containing_card(cell card_index);
void record_object_start_offset(object *obj); void record_object_start_offset(object *obj);
object *allot(cell size);
void clear_object_start_offsets(); void clear_object_start_offsets();
cell next_object_after(cell scan);
}; };
} }

View File

@ -1,8 +1,33 @@
namespace factor namespace factor
{ {
struct tenured_space : old_space { struct tenured_space_layout {
tenured_space(cell size, cell start) : old_space(size,start) {} cell block_size(object *block)
{
if(block->free_p())
{
free_heap_block *free_block = (free_heap_block *)block;
return free_block->size();
}
else
return block->size();
}
};
struct tenured_space : zone {
object_start_map starts;
tenured_space(cell size, cell start) :
zone(size,start), starts(size,start) {}
object *allot(cell size)
{
if(here + size > end) return NULL;
object *obj = zone::allot(size);
starts.record_object_start_offset(obj);
return obj;
}
}; };
} }

View File

@ -21,6 +21,15 @@ struct zone {
here = h + align(size,data_alignment); here = h + align(size,data_alignment);
return (object *)h; return (object *)h;
} }
cell next_object_after(cell scan)
{
cell size = ((object *)scan)->size();
if(scan + size < here)
return scan + size;
else
return 0;
}
}; };
} }