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); }
|
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() {
|
void code_heap::sweep() {
|
||||||
clear_free_blocks_from_all_blocks_iterator clearer(this);
|
auto clear_free_blocks_from_all_blocks = [&](code_block* block, cell size) {
|
||||||
allocator->sweep(clearer);
|
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
|
#ifdef FACTOR_DEBUG
|
||||||
verify_all_blocks_set();
|
verify_all_blocks_set();
|
||||||
#endif
|
#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() {
|
void code_heap::verify_all_blocks_set() {
|
||||||
all_blocks_set_verifier verifier(&all_blocks);
|
auto all_blocks_set_verifier = [&](code_block* block, cell size) {
|
||||||
allocator->iterate(verifier);
|
all_blocks.find((cell)block) != all_blocks.end();
|
||||||
|
};
|
||||||
|
allocator->iterate(all_blocks_set_verifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
code_block* code_heap::code_block_for_address(cell address) {
|
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;
|
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() {
|
void code_heap::initialize_all_blocks_set() {
|
||||||
all_blocks.clear();
|
all_blocks.clear();
|
||||||
all_blocks_set_inserter inserter(this);
|
auto all_blocks_set_inserter = [&](code_block* block, cell size) {
|
||||||
allocator->iterate(inserter);
|
all_blocks.insert((cell)block);
|
||||||
|
};
|
||||||
|
allocator->iterate(all_blocks_set_inserter);
|
||||||
#ifdef FACTOR_DEBUG
|
#ifdef FACTOR_DEBUG
|
||||||
verify_all_blocks_set();
|
verify_all_blocks_set();
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,24 +97,14 @@ void code_heap::initialize_all_blocks_set() {
|
||||||
/* Allocate a code heap during startup */
|
/* Allocate a code heap during startup */
|
||||||
void factor_vm::init_code_heap(cell size) { code = new code_heap(size); }
|
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.
|
/* Update pointers to words referenced from all code blocks.
|
||||||
Only needed after redefining an existing word.
|
Only needed after redefining an existing word.
|
||||||
If generic words were redefined, inline caches need to be reset. */
|
If generic words were redefined, inline caches need to be reset. */
|
||||||
void factor_vm::update_code_heap_words(bool reset_inline_caches) {
|
void factor_vm::update_code_heap_words(bool reset_inline_caches) {
|
||||||
word_updater updater(this, reset_inline_caches);
|
auto word_updater = [&](code_block* block, cell size) {
|
||||||
each_code_block(updater);
|
update_word_references(block, reset_inline_caches);
|
||||||
|
};
|
||||||
|
each_code_block(word_updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix up new words only.
|
/* 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)));
|
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() {
|
void factor_vm::primitive_strip_stack_traces() {
|
||||||
stack_trace_stripper stripper;
|
auto stack_trace_stripper = [](code_block* block, cell size) {
|
||||||
each_code_block(stripper);
|
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;
|
std::vector<cell> objects;
|
||||||
|
|
||||||
void operator()(code_block* compiled, cell size) {
|
auto code_block_accumulator = [&](code_block* block, cell size) {
|
||||||
objects.push_back(compiled->owner);
|
objects.push_back(block->owner);
|
||||||
objects.push_back(compiled->parameters);
|
objects.push_back(block->parameters);
|
||||||
objects.push_back(compiled->relocation);
|
objects.push_back(block->relocation);
|
||||||
|
|
||||||
objects.push_back(tag_fixnum(compiled->type()));
|
objects.push_back(tag_fixnum(block->type()));
|
||||||
objects.push_back(tag_fixnum(compiled->size()));
|
objects.push_back(tag_fixnum(block->size()));
|
||||||
|
|
||||||
/* Note: the entry point is always a multiple of the heap
|
/* Note: the entry point is always a multiple of the heap
|
||||||
alignment (16 bytes). We cannot allocate while iterating
|
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
|
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
|
if it were a fixnum, and have library code shift it to the
|
||||||
left by 4. */
|
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 & (data_alignment - 1)) == 0);
|
||||||
FACTOR_ASSERT((entry_point & TAG_MASK) == FIXNUM_TYPE);
|
FACTOR_ASSERT((entry_point & TAG_MASK) == FIXNUM_TYPE);
|
||||||
objects.push_back(entry_point);
|
objects.push_back(entry_point);
|
||||||
}
|
};
|
||||||
};
|
each_code_block(code_block_accumulator);
|
||||||
|
return std_vector_to_array(objects);
|
||||||
/* Allocates memory */
|
|
||||||
cell factor_vm::code_blocks() {
|
|
||||||
code_block_accumulator accum;
|
|
||||||
each_code_block(accum);
|
|
||||||
return std_vector_to_array(accum.objects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocates memory */
|
/* Allocates memory */
|
||||||
|
|
|
@ -143,24 +143,17 @@ void factor_vm::primitive_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 {
|
|
||||||
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 */
|
/* Allocates memory */
|
||||||
cell factor_vm::instances(cell type) {
|
cell factor_vm::instances(cell type) {
|
||||||
primitive_full_gc();
|
primitive_full_gc();
|
||||||
object_accumulator accum(type);
|
|
||||||
each_object(accum);
|
std::vector<cell> objects;
|
||||||
return std_vector_to_array(accum.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 */
|
/* 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() {
|
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);
|
each_object(checker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
vm/debug.cpp
27
vm/debug.cpp
|
@ -286,27 +286,16 @@ void factor_vm::dump_generations(ostream& out) {
|
||||||
out << dec;
|
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) {
|
void factor_vm::dump_objects(ostream& out, cell type) {
|
||||||
primitive_full_gc();
|
primitive_full_gc();
|
||||||
object_dumper dumper(this, type, out);
|
auto object_dumper = [&](object* obj) {
|
||||||
each_object(dumper);
|
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 {
|
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() {
|
template <typename Block> void free_list_allocator<Block>::sweep() {
|
||||||
null_sweep_iterator<Block> none;
|
auto null_sweep = [](Block* free_block, cell size) { };
|
||||||
sweep(none);
|
sweep(null_sweep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Block, typename Iterator> struct heap_compactor {
|
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) {
|
void free_list_allocator<Block>::iterate(Iterator& iter, Fixup fixup) {
|
||||||
cell scan = this->start;
|
cell scan = this->start;
|
||||||
while (scan != this->end) {
|
while (scan != this->end) {
|
||||||
cell size = fixup.size((Block*)scan);
|
Block* block = (Block*)scan;
|
||||||
if (!((Block*)scan)->free_p())
|
cell size = fixup.size(block);
|
||||||
iter((Block*)scan, size);
|
if (!block->free_p())
|
||||||
|
iter(block, size);
|
||||||
scan += size;
|
scan += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue