]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/debug.cpp
io.streams.256color: faster by caching styles
[factor.git] / vm / debug.cpp
index 6a7f332c70ab579b69a08b507962922f9acbaea6..4ffa5ac388947f6a9637a5c7ceedad4d04d90ebc 100644 (file)
@@ -4,6 +4,8 @@ using namespace std;
 
 namespace factor {
 
+bool factor_print_p = true;
+
 ostream& operator<<(ostream& out, const string* str) {
   for (cell i = 0; i < string_capacity(str); i++)
     out << (char)str->data()[i];
@@ -11,10 +13,10 @@ ostream& operator<<(ostream& out, const string* str) {
 }
 
 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: ";
@@ -60,6 +62,7 @@ void factor_vm::print_alien(ostream& out, alien* alien, cell nesting) {
 }
 
 void factor_vm::print_byte_array(ostream& out, byte_array* array, cell nesting) {
+  (void)nesting;
   cell length = array->capacity;
   cell i;
   bool trimmed;
@@ -110,7 +113,7 @@ void factor_vm::print_nested_obj(ostream& out, cell obj, fixnum nesting) {
 
   quotation* quot;
 
-  switch (tagged<object>(obj).type()) {
+  switch (TAG(obj)) {
     case FIXNUM_TYPE:
       out << untag_fixnum(obj);
       break;
@@ -156,7 +159,7 @@ void factor_vm::print_nested_obj(ostream& out, cell obj, fixnum nesting) {
       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;
   }
@@ -262,109 +265,75 @@ void factor_vm::dump_memory(ostream& out, cell from, cell to) {
     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;
-}
-
-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;
+  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) {
   primitive_full_gc();
-  object_dumper dumper(this, type, out);
-  each_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) {
+  auto object_dumper = [&](object* obj) {
+     if (type == TYPE_COUNT || obj->type() == type) {
       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);
-  }
-};
+  };
+  each_object(object_dumper);
+}
 
 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);
+  primitive_full_gc();
+  auto find_data_ref_func = [&](object* obj, cell* slot) {
+    if (look_for == *slot) {
+      out << padded_address((cell)obj) << " ";
+      print_nested_obj(out, tag_dynamic(obj), 2);
+      out << endl;
+    }
+  };
+  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 {
@@ -380,8 +349,8 @@ 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";
@@ -397,10 +366,10 @@ struct code_block_printer {
   }
 };
 
-/* 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;
 }
@@ -427,7 +396,7 @@ void factor_vm::factorbug_usage(bool advanced_p) {
          << 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;
@@ -454,8 +423,8 @@ void factor_vm::factorbug_usage(bool advanced_p) {
 }
 
 static void exit_fep(factor_vm* vm) {
-  vm->unlock_console();
-  vm->handle_ctrl_c();
+  unlock_console();
+  handle_ctrl_c();
   vm->fep_p = false;
 }
 
@@ -492,10 +461,10 @@ void factor_vm::factorbug() {
     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);
@@ -543,7 +512,7 @@ void factor_vm::factorbug() {
       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;
@@ -569,8 +538,6 @@ void factor_vm::factorbug() {
       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")
@@ -587,11 +554,7 @@ void factor_vm::factorbug() {
 }
 
 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);
 }
 
 }