VM: Refactor data_heap* to Factor style

db4
Erik Charlebois 2013-05-11 21:56:29 -04:00
parent fb34be6fa7
commit 75e6c88534
3 changed files with 217 additions and 249 deletions

View File

@ -1,186 +1,161 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
void factor_vm::init_card_decks() void factor_vm::init_card_decks() {
{ cards_offset = (cell) data->cards - addr_to_card(data->start);
cards_offset = (cell)data->cards - addr_to_card(data->start); decks_offset = (cell) data->decks - addr_to_deck(data->start);
decks_offset = (cell)data->decks - addr_to_deck(data->start);
} }
data_heap::data_heap(cell young_size_, data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_) {
cell aging_size_, young_size_ = align(young_size_, deck_size);
cell tenured_size_) aging_size_ = align(aging_size_, deck_size);
{ tenured_size_ = align(tenured_size_, deck_size);
young_size_ = align(young_size_,deck_size);
aging_size_ = align(aging_size_,deck_size);
tenured_size_ = align(tenured_size_,deck_size);
young_size = young_size_; young_size = young_size_;
aging_size = aging_size_; aging_size = aging_size_;
tenured_size = tenured_size_; tenured_size = tenured_size_;
cell total_size = young_size + 2 * aging_size + tenured_size + deck_size; cell total_size = young_size + 2 * aging_size + tenured_size + deck_size;
seg = new segment(total_size,false); seg = new segment(total_size, false);
cell cards_size = addr_to_card(total_size); cell cards_size = addr_to_card(total_size);
cards = new card[cards_size]; cards = new card[cards_size];
cards_end = cards + cards_size; cards_end = cards + cards_size;
memset(cards,0,cards_size); memset(cards, 0, cards_size);
cell decks_size = addr_to_deck(total_size); cell decks_size = addr_to_deck(total_size);
decks = new card_deck[decks_size]; decks = new card_deck[decks_size];
decks_end = decks + decks_size; decks_end = decks + decks_size;
memset(decks,0,decks_size); memset(decks, 0, decks_size);
start = align(seg->start,deck_size); start = align(seg->start, deck_size);
tenured = new tenured_space(tenured_size,start); tenured = new tenured_space(tenured_size, start);
aging = new aging_space(aging_size,tenured->end); aging = new aging_space(aging_size, tenured->end);
aging_semispace = new aging_space(aging_size,aging->end); aging_semispace = new aging_space(aging_size, aging->end);
nursery = new nursery_space(young_size,aging_semispace->end); nursery = new nursery_space(young_size, aging_semispace->end);
FACTOR_ASSERT(seg->end - nursery->end <= deck_size); FACTOR_ASSERT(seg->end - nursery->end <= deck_size);
} }
data_heap::~data_heap() data_heap::~data_heap() {
{ delete seg;
delete seg; delete nursery;
delete nursery; delete aging;
delete aging; delete aging_semispace;
delete aging_semispace; delete tenured;
delete tenured; delete[] cards;
delete[] cards; delete[] decks;
delete[] decks;
} }
data_heap *data_heap::grow(cell requested_bytes) data_heap* data_heap::grow(cell requested_bytes) {
{ cell new_tenured_size = (tenured_size * 2) + requested_bytes;
cell new_tenured_size = (tenured_size * 2) + requested_bytes; return new data_heap(young_size, aging_size, new_tenured_size);
return new data_heap(young_size,
aging_size,
new_tenured_size);
} }
template<typename Generation> void data_heap::clear_cards(Generation *gen) template <typename Generation> void data_heap::clear_cards(Generation* gen) {
{ cell first_card = addr_to_card(gen->start - start);
cell first_card = addr_to_card(gen->start - start); cell last_card = addr_to_card(gen->end - start);
cell last_card = addr_to_card(gen->end - start); memset(&cards[first_card], 0, last_card - first_card);
memset(&cards[first_card],0,last_card - first_card);
} }
template<typename Generation> void data_heap::clear_decks(Generation *gen) template <typename Generation> void data_heap::clear_decks(Generation* gen) {
{ cell first_deck = addr_to_deck(gen->start - start);
cell first_deck = addr_to_deck(gen->start - start); cell last_deck = addr_to_deck(gen->end - start);
cell last_deck = addr_to_deck(gen->end - start); memset(&decks[first_deck], 0, last_deck - first_deck);
memset(&decks[first_deck],0,last_deck - first_deck);
} }
void data_heap::reset_generation(nursery_space *gen) void data_heap::reset_generation(nursery_space* gen) { gen->here = gen->start; }
{
gen->here = gen->start; void data_heap::reset_generation(aging_space* gen) {
gen->here = gen->start;
clear_cards(gen);
clear_decks(gen);
gen->starts.clear_object_start_offsets();
} }
void data_heap::reset_generation(aging_space *gen) void data_heap::reset_generation(tenured_space* gen) {
{ clear_cards(gen);
gen->here = gen->start; clear_decks(gen);
clear_cards(gen);
clear_decks(gen);
gen->starts.clear_object_start_offsets();
} }
void data_heap::reset_generation(tenured_space *gen) bool data_heap::high_fragmentation_p() {
{ return (tenured->largest_free_block() <= high_water_mark());
clear_cards(gen);
clear_decks(gen);
} }
bool data_heap::high_fragmentation_p() bool data_heap::low_memory_p() {
{ return (tenured->free_space() <= high_water_mark());
return (tenured->largest_free_block() <= high_water_mark());
} }
bool data_heap::low_memory_p() void data_heap::mark_all_cards() {
{ memset(cards, -1, cards_end - cards);
return (tenured->free_space() <= high_water_mark()); memset(decks, -1, decks_end - decks);
} }
void data_heap::mark_all_cards() void factor_vm::set_data_heap(data_heap* data_) {
{ data = data_;
memset(cards,-1,cards_end - cards); nursery = *data->nursery;
memset(decks,-1,decks_end - decks); init_card_decks();
} }
void factor_vm::set_data_heap(data_heap *data_) void factor_vm::init_data_heap(cell young_size, cell aging_size,
{ cell tenured_size) {
data = data_; set_data_heap(new data_heap(young_size, aging_size, tenured_size));
nursery = *data->nursery;
init_card_decks();
} }
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size) data_heap_room factor_vm::data_room() {
{ data_heap_room room;
set_data_heap(new data_heap(young_size,aging_size,tenured_size));
}
data_heap_room factor_vm::data_room() room.nursery_size = nursery.size;
{ room.nursery_occupied = nursery.occupied_space();
data_heap_room room; room.nursery_free = nursery.free_space();
room.aging_size = data->aging->size;
room.aging_occupied = data->aging->occupied_space();
room.aging_free = data->aging->free_space();
room.tenured_size = data->tenured->size;
room.tenured_occupied = data->tenured->occupied_space();
room.tenured_total_free = data->tenured->free_space();
room.tenured_contiguous_free = data->tenured->largest_free_block();
room.tenured_free_block_count = data->tenured->free_block_count();
room.cards = data->cards_end - data->cards;
room.decks = data->decks_end - data->decks;
room.mark_stack = mark_stack.capacity() * sizeof(cell);
room.nursery_size = nursery.size; return room;
room.nursery_occupied = nursery.occupied_space();
room.nursery_free = nursery.free_space();
room.aging_size = data->aging->size;
room.aging_occupied = data->aging->occupied_space();
room.aging_free = data->aging->free_space();
room.tenured_size = data->tenured->size;
room.tenured_occupied = data->tenured->occupied_space();
room.tenured_total_free = data->tenured->free_space();
room.tenured_contiguous_free = data->tenured->largest_free_block();
room.tenured_free_block_count = data->tenured->free_block_count();
room.cards = data->cards_end - data->cards;
room.decks = data->decks_end - data->decks;
room.mark_stack = mark_stack.capacity() * sizeof(cell);
return room;
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_data_room() void factor_vm::primitive_data_room() {
{ data_heap_room room = data_room();
data_heap_room room = data_room(); ctx->push(tag<byte_array>(byte_array_from_value(&room)));
ctx->push(tag<byte_array>(byte_array_from_value(&room)));
} }
struct object_accumulator { struct object_accumulator {
cell type; cell type;
std::vector<cell> objects; std::vector<cell> objects;
explicit object_accumulator(cell type_) : type(type_) {} explicit object_accumulator(cell type_) : type(type_) {}
void operator()(object *obj) void operator()(object* obj) {
{ if (type == TYPE_COUNT || obj->type() == type)
if(type == TYPE_COUNT || obj->type() == type) objects.push_back(tag_dynamic(obj));
objects.push_back(tag_dynamic(obj)); }
}
}; };
/* Allocates memory */ /* Allocates memory */
cell factor_vm::instances(cell type) cell factor_vm::instances(cell type) {
{ object_accumulator accum(type);
object_accumulator accum(type); each_object(accum);
each_object(accum); return std_vector_to_array(accum.objects);
return std_vector_to_array(accum.objects);
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_all_instances() void factor_vm::primitive_all_instances() {
{ primitive_full_gc();
primitive_full_gc(); ctx->push(instances(TYPE_COUNT));
ctx->push(instances(TYPE_COUNT));
} }
} }

View File

@ -1,57 +1,54 @@
namespace factor namespace factor {
{
struct data_heap { struct data_heap {
cell start; cell start;
cell young_size; cell young_size;
cell aging_size; cell aging_size;
cell tenured_size; cell tenured_size;
segment *seg; segment* seg;
nursery_space *nursery; nursery_space* nursery;
aging_space *aging; aging_space* aging;
aging_space *aging_semispace; aging_space* aging_semispace;
tenured_space *tenured; tenured_space* tenured;
card *cards; card* cards;
card *cards_end; card* cards_end;
card_deck *decks; card_deck* decks;
card_deck *decks_end; card_deck* decks_end;
explicit data_heap(cell young_size, cell aging_size, cell tenured_size); explicit data_heap(cell young_size, cell aging_size, cell tenured_size);
~data_heap(); ~data_heap();
data_heap *grow(cell requested_size); data_heap* grow(cell requested_size);
template<typename Generation> void clear_cards(Generation *gen); template <typename Generation> void clear_cards(Generation* gen);
template<typename Generation> void clear_decks(Generation *gen); template <typename Generation> void clear_decks(Generation* gen);
void reset_generation(nursery_space *gen); void reset_generation(nursery_space* gen);
void reset_generation(aging_space *gen); void reset_generation(aging_space* gen);
void reset_generation(tenured_space *gen); void reset_generation(tenured_space* gen);
bool high_fragmentation_p(); bool high_fragmentation_p();
bool low_memory_p(); bool low_memory_p();
void mark_all_cards(); void mark_all_cards();
cell high_water_mark() { cell high_water_mark() { return nursery->size + aging->size; }
return nursery->size + aging->size;
}
}; };
struct data_heap_room { struct data_heap_room {
cell nursery_size; cell nursery_size;
cell nursery_occupied; cell nursery_occupied;
cell nursery_free; cell nursery_free;
cell aging_size; cell aging_size;
cell aging_occupied; cell aging_occupied;
cell aging_free; cell aging_free;
cell tenured_size; cell tenured_size;
cell tenured_occupied; cell tenured_occupied;
cell tenured_total_free; cell tenured_total_free;
cell tenured_contiguous_free; cell tenured_contiguous_free;
cell tenured_free_block_count; cell tenured_free_block_count;
cell cards; cell cards;
cell decks; cell decks;
cell mark_stack; cell mark_stack;
}; };
} }

View File

@ -3,99 +3,95 @@
/* A tool to debug write barriers. Call check_data_heap() to ensure that all /* A tool to debug write barriers. Call check_data_heap() to ensure that all
cards that should be marked are actually marked. */ cards that should be marked are actually marked. */
namespace factor namespace factor {
{
enum generation { enum generation {
nursery_generation, nursery_generation,
aging_generation, aging_generation,
tenured_generation tenured_generation
}; };
inline generation generation_of(factor_vm *parent, object *obj) inline generation generation_of(factor_vm* parent, object* obj) {
{ if (parent->data->nursery->contains_p(obj))
if(parent->data->nursery->contains_p(obj)) return nursery_generation;
return nursery_generation; else if (parent->data->aging->contains_p(obj))
else if(parent->data->aging->contains_p(obj)) return aging_generation;
return aging_generation; else if (parent->data->tenured->contains_p(obj))
else if(parent->data->tenured->contains_p(obj)) return tenured_generation;
return tenured_generation; else {
else critical_error("Bad object", (cell) obj);
{ return (generation) - 1;
critical_error("Bad object",(cell)obj); }
return (generation)-1;
}
} }
struct slot_checker { struct slot_checker {
factor_vm *parent; factor_vm* parent;
object *obj; object* obj;
generation gen; generation gen;
explicit slot_checker(factor_vm *parent_, object *obj_, generation gen_) : explicit slot_checker(factor_vm* parent_, object* obj_, generation gen_)
parent(parent_), obj(obj_), gen(gen_) {} : parent(parent_), obj(obj_), gen(gen_) {}
void check_write_barrier(cell *slot_ptr, generation target, char mask) void check_write_barrier(cell* slot_ptr, generation target, char mask) {
{ cell object_card_pointer = parent->cards_offset + ((cell) obj >> card_bits);
cell object_card_pointer = parent->cards_offset + ((cell)obj >> card_bits); cell slot_card_pointer =
cell slot_card_pointer = parent->cards_offset + ((cell)slot_ptr >> card_bits); parent->cards_offset + ((cell) slot_ptr >> card_bits);
char slot_card_value = *(char *)slot_card_pointer; char slot_card_value = *(char*)slot_card_pointer;
if((slot_card_value & mask) != mask) if ((slot_card_value & mask) != mask) {
{ std::cout << "card not marked" << std::endl;
std::cout << "card not marked" << std::endl; std::cout << "source generation: " << gen << std::endl;
std::cout << "source generation: " << gen << std::endl; std::cout << "target generation: " << target << std::endl;
std::cout << "target generation: " << target << std::endl; std::cout << "object: 0x" << std::hex << (cell)
std::cout << "object: 0x" << std::hex << (cell)obj << std::dec << std::endl; obj << std::dec << std::endl;
std::cout << "object type: " << obj->type() << std::endl; std::cout << "object type: " << obj->type() << std::endl;
std::cout << "slot pointer: 0x" << std::hex << (cell)slot_ptr << std::dec << std::endl; std::cout << "slot pointer: 0x" << std::hex << (cell)
std::cout << "slot value: 0x" << std::hex << *slot_ptr << std::dec << std::endl; slot_ptr << std::dec << std::endl;
std::cout << "card of object: 0x" << std::hex << object_card_pointer << std::dec << std::endl; std::cout << "slot value: 0x" << std::hex << *slot_ptr << std::dec
std::cout << "card of slot: 0x" << std::hex << slot_card_pointer << std::dec << std::endl; << std::endl;
std::cout << std::endl; std::cout << "card of object: 0x" << std::hex << object_card_pointer
parent->factorbug(); << std::dec << std::endl;
} std::cout << "card of slot: 0x" << std::hex << slot_card_pointer
} << std::dec << std::endl;
std::cout << std::endl;
parent->factorbug();
}
}
void operator()(cell *slot_ptr) void operator()(cell* slot_ptr) {
{ if (!immediate_p(*slot_ptr)) {
if(!immediate_p(*slot_ptr)) generation target = generation_of(parent, untag<object>(*slot_ptr));
{ switch (gen) {
generation target = generation_of(parent,untag<object>(*slot_ptr)); case nursery_generation:
switch(gen) break;
{ case aging_generation:
case nursery_generation: if (target == nursery_generation)
break; check_write_barrier(slot_ptr, target, card_points_to_nursery);
case aging_generation: break;
if(target == nursery_generation) case tenured_generation:
check_write_barrier(slot_ptr,target,card_points_to_nursery); if (target == nursery_generation)
break; check_write_barrier(slot_ptr, target, card_points_to_nursery);
case tenured_generation: else if (target == aging_generation)
if(target == nursery_generation) check_write_barrier(slot_ptr, target, card_points_to_aging);
check_write_barrier(slot_ptr,target,card_points_to_nursery); break;
else if(target == aging_generation) }
check_write_barrier(slot_ptr,target,card_points_to_aging); }
break; }
}
}
}
}; };
struct object_checker { struct object_checker {
factor_vm *parent; factor_vm* parent;
explicit object_checker(factor_vm *parent_) : parent(parent_) {} explicit object_checker(factor_vm* parent_) : parent(parent_) {}
void operator()(object *obj) void operator()(object* obj) {
{ slot_checker checker(parent, obj, generation_of(parent, obj));
slot_checker checker(parent,obj,generation_of(parent,obj)); obj->each_slot(checker);
obj->each_slot(checker); }
}
}; };
void factor_vm::check_data_heap() void factor_vm::check_data_heap() {
{ object_checker checker(this);
object_checker checker(this); each_object(checker);
each_object(checker);
} }
} }