vm: object start recording in cards is now independent of allocation strategy
parent
d22d5466fc
commit
e482940dca
|
@ -1,8 +1,20 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
struct aging_space : old_space {
|
||||
aging_space(cell size, cell start) : old_space(size,start) {}
|
||||
struct aging_space : zone {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,6 @@ struct code_heap_layout {
|
|||
{
|
||||
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> {
|
||||
|
|
|
@ -95,7 +95,7 @@ struct copying_collector : collector<TargetGeneration,Policy> {
|
|||
|
||||
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);
|
||||
end = start + ((object *)start)->size();
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ template<typename Generation> void data_heap::reset_generation(Generation *gen)
|
|||
|
||||
clear_cards(gen);
|
||||
clear_decks(gen);
|
||||
gen->clear_object_start_offsets();
|
||||
gen->starts.clear_object_start_offsets();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
13
vm/heap.hpp
13
vm/heap.hpp
|
@ -28,6 +28,11 @@ template<typename Block, typename HeapLayout> struct heap {
|
|||
return (Block *)seg->end;
|
||||
}
|
||||
|
||||
Block *next_block_after(heap_block *block)
|
||||
{
|
||||
return (Block *)((cell)block + layout.block_size(block));
|
||||
}
|
||||
|
||||
void clear_free_list();
|
||||
void add_to_free_list(free_heap_block *block);
|
||||
void build_free_list(cell size);
|
||||
|
@ -50,7 +55,7 @@ template<typename Block, typename HeapLayout> struct heap {
|
|||
|
||||
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));
|
||||
scan = next;
|
||||
}
|
||||
|
@ -229,7 +234,7 @@ void heap<Block,HeapLayout>::heap_usage(cell *used, cell *total_free, cell *max_
|
|||
else
|
||||
*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)
|
||||
{
|
||||
if(scan->free_p()) break;
|
||||
else scan = layout.next_block_after(scan);
|
||||
else scan = next_block_after(scan);
|
||||
}
|
||||
|
||||
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())
|
||||
|
|
|
@ -203,7 +203,7 @@ void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_ba
|
|||
while(obj)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,8 +148,17 @@ struct header {
|
|||
struct object {
|
||||
NO_TYPE_CHECK;
|
||||
header h;
|
||||
cell *slots() { return (cell *)this; }
|
||||
|
||||
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 */
|
||||
|
|
|
@ -70,10 +70,15 @@ template<typename Block, typename HeapLayout> struct mark_bits {
|
|||
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)
|
||||
{
|
||||
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 end_mask = ((u64)1 << end.second) - 1;
|
||||
|
|
|
@ -3,23 +3,24 @@
|
|||
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_end = object_start_offsets + addr_to_card(size_);
|
||||
}
|
||||
|
||||
old_space::~old_space()
|
||||
object_start_map::~object_start_map()
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
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)
|
||||
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 */
|
||||
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);
|
||||
if(object_start_offsets[idx] == card_starts_inside_object)
|
||||
object_start_offsets[idx] = ((cell)obj & addr_card_mask);
|
||||
card obj_start = ((cell)obj & addr_card_mask);
|
||||
object_start_offsets[idx] = std::min(object_start_offsets[idx],obj_start);
|
||||
}
|
||||
|
||||
object *old_space::allot(cell size)
|
||||
{
|
||||
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()
|
||||
void object_start_map::clear_object_start_offsets()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,19 +3,18 @@ namespace factor
|
|||
|
||||
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_end;
|
||||
|
||||
old_space(cell size_, cell start_);
|
||||
~old_space();
|
||||
object_start_map(cell size_, cell start_);
|
||||
~object_start_map();
|
||||
|
||||
cell first_object_in_card(cell card_index);
|
||||
cell find_object_containing_card(cell card_index);
|
||||
void record_object_start_offset(object *obj);
|
||||
object *allot(cell size);
|
||||
void clear_object_start_offsets();
|
||||
cell next_object_after(cell scan);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,33 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
struct tenured_space : old_space {
|
||||
tenured_space(cell size, cell start) : old_space(size,start) {}
|
||||
struct tenured_space_layout {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,15 @@ struct zone {
|
|||
here = h + align(size,data_alignment);
|
||||
return (object *)h;
|
||||
}
|
||||
|
||||
cell next_object_after(cell scan)
|
||||
{
|
||||
cell size = ((object *)scan)->size();
|
||||
if(scan + size < here)
|
||||
return scan + size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue