vm: object start recording in cards is now independent of allocation strategy
parent
d22d5466fc
commit
e482940dca
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
13
vm/heap.hpp
13
vm/heap.hpp
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue