VM: move changes of structs to lambda functions
parent
365b39e0cc
commit
4dfac78fc1
118
vm/code_heap.cpp
118
vm/code_heap.cpp
|
@ -49,43 +49,25 @@ void code_heap::free(code_block* compiled) {
|
|||
|
||||
void code_heap::flush_icache() { factor::flush_icache(seg->start, seg->size); }
|
||||
|
||||
struct clear_free_blocks_from_all_blocks_iterator {
|
||||
code_heap* code;
|
||||
|
||||
clear_free_blocks_from_all_blocks_iterator(code_heap* code) : code(code) {}
|
||||
|
||||
void operator()(code_block* free_block, cell size) {
|
||||
std::set<cell>::iterator erase_from =
|
||||
code->all_blocks.lower_bound((cell)free_block);
|
||||
std::set<cell>::iterator erase_to =
|
||||
code->all_blocks.lower_bound((cell)free_block + size);
|
||||
|
||||
code->all_blocks.erase(erase_from, erase_to);
|
||||
}
|
||||
};
|
||||
|
||||
void code_heap::sweep() {
|
||||
clear_free_blocks_from_all_blocks_iterator clearer(this);
|
||||
allocator->sweep(clearer);
|
||||
auto clear_free_blocks_from_all_blocks = [&](code_block* block, cell size) {
|
||||
std::set<cell>::iterator erase_from =
|
||||
all_blocks.lower_bound((cell)block);
|
||||
std::set<cell>::iterator erase_to =
|
||||
all_blocks.lower_bound((cell)block + size);
|
||||
all_blocks.erase(erase_from, erase_to);
|
||||
};
|
||||
allocator->sweep(clear_free_blocks_from_all_blocks);
|
||||
#ifdef FACTOR_DEBUG
|
||||
verify_all_blocks_set();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct all_blocks_set_verifier {
|
||||
std::set<cell>* all_blocks;
|
||||
|
||||
all_blocks_set_verifier(std::set<cell>* all_blocks)
|
||||
: all_blocks(all_blocks) {}
|
||||
|
||||
void operator()(code_block* block, cell size) {
|
||||
FACTOR_ASSERT(all_blocks->find((cell)block) != all_blocks->end());
|
||||
}
|
||||
};
|
||||
|
||||
void code_heap::verify_all_blocks_set() {
|
||||
all_blocks_set_verifier verifier(&all_blocks);
|
||||
allocator->iterate(verifier);
|
||||
auto all_blocks_set_verifier = [&](code_block* block, cell size) {
|
||||
all_blocks.find((cell)block) != all_blocks.end();
|
||||
};
|
||||
allocator->iterate(all_blocks_set_verifier);
|
||||
}
|
||||
|
||||
code_block* code_heap::code_block_for_address(cell address) {
|
||||
|
@ -101,20 +83,12 @@ code_block* code_heap::code_block_for_address(cell address) {
|
|||
return found_block;
|
||||
}
|
||||
|
||||
struct all_blocks_set_inserter {
|
||||
code_heap* code;
|
||||
|
||||
all_blocks_set_inserter(code_heap* code) : code(code) {}
|
||||
|
||||
void operator()(code_block* block, cell size) {
|
||||
code->all_blocks.insert((cell)block);
|
||||
}
|
||||
};
|
||||
|
||||
void code_heap::initialize_all_blocks_set() {
|
||||
all_blocks.clear();
|
||||
all_blocks_set_inserter inserter(this);
|
||||
allocator->iterate(inserter);
|
||||
auto all_blocks_set_inserter = [&](code_block* block, cell size) {
|
||||
all_blocks.insert((cell)block);
|
||||
};
|
||||
allocator->iterate(all_blocks_set_inserter);
|
||||
#ifdef FACTOR_DEBUG
|
||||
verify_all_blocks_set();
|
||||
#endif
|
||||
|
@ -123,24 +97,14 @@ void code_heap::initialize_all_blocks_set() {
|
|||
/* Allocate a code heap during startup */
|
||||
void factor_vm::init_code_heap(cell size) { code = new code_heap(size); }
|
||||
|
||||
struct word_updater {
|
||||
factor_vm* parent;
|
||||
bool reset_inline_caches;
|
||||
|
||||
word_updater(factor_vm* parent, bool reset_inline_caches)
|
||||
: parent(parent), reset_inline_caches(reset_inline_caches) {}
|
||||
|
||||
void operator()(code_block* compiled, cell size) {
|
||||
parent->update_word_references(compiled, reset_inline_caches);
|
||||
}
|
||||
};
|
||||
|
||||
/* Update pointers to words referenced from all code blocks.
|
||||
Only needed after redefining an existing word.
|
||||
If generic words were redefined, inline caches need to be reset. */
|
||||
void factor_vm::update_code_heap_words(bool reset_inline_caches) {
|
||||
word_updater updater(this, reset_inline_caches);
|
||||
each_code_block(updater);
|
||||
auto word_updater = [&](code_block* block, cell size) {
|
||||
update_word_references(block, reset_inline_caches);
|
||||
};
|
||||
each_code_block(word_updater);
|
||||
}
|
||||
|
||||
/* Fix up new words only.
|
||||
|
@ -207,29 +171,24 @@ void factor_vm::primitive_code_room() {
|
|||
ctx->push(tag<byte_array>(byte_array_from_value(&room)));
|
||||
}
|
||||
|
||||
struct stack_trace_stripper {
|
||||
stack_trace_stripper() {}
|
||||
|
||||
void operator()(code_block* compiled, cell size) {
|
||||
compiled->owner = false_object;
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::primitive_strip_stack_traces() {
|
||||
stack_trace_stripper stripper;
|
||||
each_code_block(stripper);
|
||||
auto stack_trace_stripper = [](code_block* block, cell size) {
|
||||
block->owner = false_object;
|
||||
};
|
||||
each_code_block(stack_trace_stripper);
|
||||
}
|
||||
|
||||
struct code_block_accumulator {
|
||||
/* Allocates memory */
|
||||
cell factor_vm::code_blocks() {
|
||||
std::vector<cell> objects;
|
||||
|
||||
void operator()(code_block* compiled, cell size) {
|
||||
objects.push_back(compiled->owner);
|
||||
objects.push_back(compiled->parameters);
|
||||
objects.push_back(compiled->relocation);
|
||||
auto code_block_accumulator = [&](code_block* block, cell size) {
|
||||
objects.push_back(block->owner);
|
||||
objects.push_back(block->parameters);
|
||||
objects.push_back(block->relocation);
|
||||
|
||||
objects.push_back(tag_fixnum(compiled->type()));
|
||||
objects.push_back(tag_fixnum(compiled->size()));
|
||||
objects.push_back(tag_fixnum(block->type()));
|
||||
objects.push_back(tag_fixnum(block->size()));
|
||||
|
||||
/* Note: the entry point is always a multiple of the heap
|
||||
alignment (16 bytes). We cannot allocate while iterating
|
||||
|
@ -237,18 +196,13 @@ struct code_block_accumulator {
|
|||
from_unsigned_cell() here. It is OK, however, to add it as
|
||||
if it were a fixnum, and have library code shift it to the
|
||||
left by 4. */
|
||||
cell entry_point = compiled->entry_point();
|
||||
cell entry_point = block->entry_point();
|
||||
FACTOR_ASSERT((entry_point & (data_alignment - 1)) == 0);
|
||||
FACTOR_ASSERT((entry_point & TAG_MASK) == FIXNUM_TYPE);
|
||||
objects.push_back(entry_point);
|
||||
}
|
||||
};
|
||||
|
||||
/* Allocates memory */
|
||||
cell factor_vm::code_blocks() {
|
||||
code_block_accumulator accum;
|
||||
each_code_block(accum);
|
||||
return std_vector_to_array(accum.objects);
|
||||
};
|
||||
each_code_block(code_block_accumulator);
|
||||
return std_vector_to_array(objects);
|
||||
}
|
||||
|
||||
/* Allocates memory */
|
||||
|
|
|
@ -143,24 +143,17 @@ void factor_vm::primitive_data_room() {
|
|||
ctx->push(tag<byte_array>(byte_array_from_value(&room)));
|
||||
}
|
||||
|
||||
struct object_accumulator {
|
||||
cell type;
|
||||
std::vector<cell> objects;
|
||||
|
||||
explicit object_accumulator(cell type) : type(type) {}
|
||||
|
||||
void operator()(object* obj) {
|
||||
if (type == TYPE_COUNT || obj->type() == type)
|
||||
objects.push_back(tag_dynamic(obj));
|
||||
}
|
||||
};
|
||||
|
||||
/* Allocates memory */
|
||||
cell factor_vm::instances(cell type) {
|
||||
primitive_full_gc();
|
||||
object_accumulator accum(type);
|
||||
each_object(accum);
|
||||
return std_vector_to_array(accum.objects);
|
||||
|
||||
std::vector<cell> objects;
|
||||
auto object_accumulator = [&](object* obj) {
|
||||
if (type == TYPE_COUNT || obj->type() == type)
|
||||
objects.push_back(tag_dynamic(obj));
|
||||
};
|
||||
each_object(object_accumulator);
|
||||
return std_vector_to_array(objects);
|
||||
}
|
||||
|
||||
/* Allocates memory */
|
||||
|
|
|
@ -74,20 +74,12 @@ struct slot_checker {
|
|||
}
|
||||
};
|
||||
|
||||
struct object_checker {
|
||||
factor_vm* parent;
|
||||
|
||||
object_checker(factor_vm* parent) : parent(parent) {}
|
||||
|
||||
void operator()(object* obj) {
|
||||
generation obj_gen = generation_of(parent, obj);
|
||||
slot_checker checker(parent, obj, obj_gen);
|
||||
obj->each_slot(checker);
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::check_data_heap() {
|
||||
object_checker checker(this);
|
||||
auto checker = [&](object* obj){
|
||||
generation obj_gen = generation_of(this, obj);
|
||||
slot_checker s_checker(this, obj, obj_gen);
|
||||
obj->each_slot(s_checker);
|
||||
};
|
||||
each_object(checker);
|
||||
}
|
||||
|
||||
|
|
27
vm/debug.cpp
27
vm/debug.cpp
|
@ -286,27 +286,16 @@ void factor_vm::dump_generations(ostream& out) {
|
|||
out << dec;
|
||||
}
|
||||
|
||||
struct object_dumper {
|
||||
factor_vm* parent;
|
||||
cell type;
|
||||
ostream& out;
|
||||
|
||||
object_dumper(factor_vm* parent, cell type, ostream& out)
|
||||
: parent(parent), type(type), out(out) {}
|
||||
|
||||
void operator()(object* obj) {
|
||||
if (type == TYPE_COUNT || obj->type() == type) {
|
||||
out << padded_address((cell)obj) << " ";
|
||||
parent->print_nested_obj(out, tag_dynamic(obj), 2);
|
||||
out << endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::dump_objects(ostream& out, cell type) {
|
||||
primitive_full_gc();
|
||||
object_dumper dumper(this, type, out);
|
||||
each_object(dumper);
|
||||
auto object_dumper = [&](object* obj) {
|
||||
if (type == TYPE_COUNT || obj->type() == type) {
|
||||
out << padded_address((cell)obj) << " ";
|
||||
print_nested_obj(out, tag_dynamic(obj), 2);
|
||||
out << endl;
|
||||
}
|
||||
};
|
||||
each_object(object_dumper);
|
||||
}
|
||||
|
||||
struct find_data_reference_slot_visitor {
|
||||
|
|
|
@ -120,13 +120,9 @@ void free_list_allocator<Block>::sweep(Iterator& iter) {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Block> struct null_sweep_iterator {
|
||||
void operator()(Block* free_block, cell size) {}
|
||||
};
|
||||
|
||||
template <typename Block> void free_list_allocator<Block>::sweep() {
|
||||
null_sweep_iterator<Block> none;
|
||||
sweep(none);
|
||||
auto null_sweep = [](Block* free_block, cell size) { };
|
||||
sweep(null_sweep);
|
||||
}
|
||||
|
||||
template <typename Block, typename Iterator> struct heap_compactor {
|
||||
|
@ -170,9 +166,10 @@ template <typename Iterator, typename Fixup>
|
|||
void free_list_allocator<Block>::iterate(Iterator& iter, Fixup fixup) {
|
||||
cell scan = this->start;
|
||||
while (scan != this->end) {
|
||||
cell size = fixup.size((Block*)scan);
|
||||
if (!((Block*)scan)->free_p())
|
||||
iter((Block*)scan, size);
|
||||
Block* block = (Block*)scan;
|
||||
cell size = fixup.size(block);
|
||||
if (!block->free_p())
|
||||
iter(block, size);
|
||||
scan += size;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue