}
void factor_vm::print_word(ostream& out, word* word, cell nesting) {
- if (tagged<object>(word->vocabulary).type_p(STRING_TYPE))
+ if (TAG(word->vocabulary) == STRING_TYPE)
out << untag<string>(word->vocabulary) << ":";
- if (tagged<object>(word->name).type_p(STRING_TYPE))
+ if (TAG(word->name) == STRING_TYPE)
out << untag<string>(word->name);
else {
out << "#<not a string: ";
}
void factor_vm::print_byte_array(ostream& out, byte_array* array, cell nesting) {
+ (void)nesting;
cell length = array->capacity;
cell i;
bool trimmed;
quotation* quot;
- switch (tagged<object>(obj).type()) {
+ switch (TAG(obj)) {
case FIXNUM_TYPE:
out << untag_fixnum(obj);
break;
print_alien(out, untag<alien>(obj), nesting - 1);
break;
default:
- out << "#<" << type_name(tagged<object>(obj).type()) << " @ ";
+ out << "#<" << type_name(TAG(obj)) << " @ ";
out << (void*)obj << ">";
break;
}
dump_cell(out, from);
}
-template <typename Generation>
-void factor_vm::dump_generation(ostream& out, const char* name, Generation* gen) {
- out << name << ": ";
- out << "Start=" << gen->start;
- out << ", size=" << gen->size;
- out << ", end=" << gen->end;
- out << endl;
+void dump_memory_range(ostream& out, const char* name, cell name_w,
+ cell start, cell end) {
+ out << setw(static_cast<int>(name_w)) << left << name << ": ";
+
+ out << "[" << (void*)start << " -> " << (void*)end << "] ";
+ out << setw(10) << right << (end - start) << " bytes" << endl;
}
-void factor_vm::dump_generations(ostream& out) {
- out << hex;
+template <typename Generation>
+void dump_generation(ostream& out, const char* name, Generation* gen) {
+ dump_memory_range(out, name, 10, gen->start, gen->end);
+}
- dump_generation(out, "Nursery", &nursery);
+void factor_vm::dump_memory_layout(ostream& out) {
+ dump_generation(out, "Nursery", data->nursery);
dump_generation(out, "Aging", data->aging);
dump_generation(out, "Tenured", data->tenured);
-
- out << "Cards:";
- out << "base=" << (cell)data->cards << ", ";
- out << "size=" << (cell)(data->cards_end - data->cards) << endl;
- out << dec;
+ dump_memory_range(out, "Cards", 10, (cell)data->cards, (cell)data->cards_end);
+
+ out << endl << "Contexts:" << endl << endl;
+ FACTOR_FOR_EACH(active_contexts) {
+ context* the_ctx = *iter;
+ segment* ds = the_ctx->datastack_seg;
+ segment* rs = the_ctx->retainstack_seg;
+ segment* cs = the_ctx->callstack_seg;
+ if (the_ctx == ctx) {
+ out << " Active:" << endl;
+ }
+ dump_memory_range(out, " Datastack", 14, ds->start, ds->end);
+ dump_memory_range(out, " Retainstack", 14, rs->start, rs->end);
+ dump_memory_range(out, " Callstack", 14, cs->start, cs->end);
+ out << endl;
+ }
}
void factor_vm::dump_objects(ostream& out, cell type) {
each_object(object_dumper);
}
-struct find_data_reference_slot_visitor {
- cell look_for;
- object* obj;
- factor_vm* parent;
- ostream& out;
-
- find_data_reference_slot_visitor(cell look_for,
- object* obj,
- factor_vm* parent,
- ostream& out)
- : look_for(look_for), obj(obj), parent(parent), out(out) {}
-
- void operator()(cell* scan) {
- if (look_for == *scan) {
+void factor_vm::find_data_references(ostream& out, cell look_for) {
+ primitive_full_gc();
+ auto find_data_ref_func = [&](object* obj, cell* slot) {
+ if (look_for == *slot) {
out << padded_address((cell)obj) << " ";
- parent->print_nested_obj(out, tag_dynamic(obj), 2);
+ print_nested_obj(out, tag_dynamic(obj), 2);
out << endl;
}
- }
-};
-
-struct dump_edges_slot_visitor {
- object* obj;
- factor_vm* parent;
- ostream& out;
-
- dump_edges_slot_visitor(cell, object* obj, factor_vm* parent, ostream& out)
- : obj(obj), parent(parent), out(out) {}
-
- void operator()(cell* scan) {
- if (TAG(*scan) > F_TYPE)
- out << (void*)tag_dynamic(obj) << " ==> " << (void*)*scan << endl;
- }
-};
-
-template <typename SlotVisitor> struct data_reference_object_visitor {
- cell look_for;
- factor_vm* parent;
- ostream& out;
-
- data_reference_object_visitor(cell look_for, factor_vm* parent, ostream& out)
- : look_for(look_for), parent(parent), out(out) {}
-
- void operator()(object* obj) {
- SlotVisitor visitor(look_for, obj, parent, out);
- obj->each_slot(visitor);
- }
-};
-
-void factor_vm::find_data_references(ostream& out, cell look_for) {
- data_reference_object_visitor<find_data_reference_slot_visitor>
- visitor(look_for, this, out);
- each_object(visitor);
+ };
+ each_object_each_slot(find_data_ref_func);
}
void factor_vm::dump_edges(ostream& out) {
- data_reference_object_visitor<dump_edges_slot_visitor> visitor(0, this, out);
- each_object(visitor);
+ primitive_full_gc();
+ auto dump_edges_func = [&](object* obj, cell* scan) {
+ if (TAG(*scan) > F_TYPE) {
+ out << (void*)tag_dynamic(obj);
+ out << " ==> ";
+ out << (void*)*scan << endl;
+ }
+ };
+ each_object_each_slot(dump_edges_func);
}
struct code_block_printer {
if (scan->free_p())
status = "free";
else {
- reloc_size += parent->object_size(scan->relocation);
- parameter_size += parent->object_size(scan->parameters);
+ reloc_size += object_size(scan->relocation);
+ parameter_size += object_size(scan->parameters);
if (parent->code->allocator->state.marked_p((cell)scan))
status = "marked";
}
};
-/* Dump all code blocks for debugging */
+// Dump all code blocks for debugging
void factor_vm::dump_code_heap(ostream& out) {
code_block_printer printer(this, out);
- code->allocator->iterate(printer);
+ code->allocator->iterate(printer, no_fixup());
out << printer.reloc_size << " bytes used by relocation tables" << endl;
out << printer.parameter_size << " bytes used by parameter tables" << endl;
}
<< endl;
cout << " . <addr> -- print object at tagged <addr>"
<< endl;
- cout << " g -- dump generations" << endl;
+ cout << " g -- dump memory layout" << endl;
cout << " ds dr -- dump data, retain stacks" << endl;
cout << " trim -- toggle output trimming" << endl;
cout << " data -- data heap dump" << endl;
}
static void exit_fep(factor_vm* vm) {
- vm->unlock_console();
- vm->handle_ctrl_c();
+ unlock_console();
+ handle_ctrl_c();
vm->fep_p = false;
}
cin >> setw(1024) >> cmd >> setw(0);
if (!cin.good()) {
if (!seen_command) {
- /* If we exit with an EOF immediately, then
- dump stacks. This is useful for builder and
- other cases where Factor is run with stdin
- redirected to /dev/null */
+ // If we exit with an EOF immediately, then
+ // dump stacks. This is useful for builder and
+ // other cases where Factor is run with stdin
+ // redirected to /dev/null
fep_disabled = true;
print_datastack(cout);
for (cell i = 0; i < special_object_count; i++)
dump_cell(cout, (cell)&special_objects[i]);
} else if (cmd == "g")
- dump_generations(cout);
+ dump_memory_layout(cout);
else if (cmd == "c") {
exit_fep(this);
return;
ctx->push(addr);
} else if (cmd == "code")
dump_code_heap(cout);
- else if (cmd == "compact-gc")
- primitive_compact_gc();
else if (cmd == "gc")
primitive_full_gc();
else if (cmd == "compact-gc")
}
void factor_vm::primitive_die() {
- cout << "The die word was called by the library. Unless you called it "
- "yourself," << endl;
- cout << "you have triggered a bug in Factor. Please report."
- << endl;
- factorbug();
+ critical_error("The die word was called by the library.", 0);
}
}