static bool read_input() { char* line = read_line(stdin); userlog(LOG_DEBUG, "input: %s", (line ? line : "<null>")); if (line == NULL || strcmp(line, "EXIT") == 0) { userlog(LOG_INFO, "exiting: %s", line); return false; } if (strcmp(line, "ROOTS") == 0) { array* new_roots = array_create(20); CHECK_NULL(new_roots, false); while (1) { line = read_line(stdin); userlog(LOG_DEBUG, "input: %s", (line ? line : "<null>")); if (line == NULL || strlen(line) == 0) { return false; } else if (strcmp(line, "#") == 0) { break; } else { int l = strlen(line); if (l > 1 && line[l-1] == '/') line[l-1] = '\0'; CHECK_NULL(array_push(new_roots, strdup(line)), false); } } return update_roots(new_roots); } userlog(LOG_INFO, "unrecognised command: %s", line); return true; }
/* Perform a mark_and_compact garbage collection, moving all live objects * to the start of the heap. Anything that we don't mark is dead. * * 1. Walk object graph starting from roots, marking live objects. * * 2. Walk all live objects and compute their forwarding addresses starting from start_of_heap. * * 3. Alter all non-NULL roots to point to the object's forwarding address. * * 4. For each live object: * a) alter all non-NULL managed pointer fields to point to the forwarding addresses. * b) unmark object * * 5. Physically move object to forwarding address towards front of heap and reset marked. * * This phase must be last as the object stores the forwarding address. When we move, * we overwrite objects and could kill a forwarding address in a live object. */ void gc() { if (DEBUG) printf("GC\n"); gc_mark(); // TODO: add next_live field to heap_object to avoid walking all objects to find live // oops actually must move objects from low to high ptr addresses. // reallocate all live objects starting from start_of_heap if (DEBUG) printf("FORWARD\n"); next_free_forwarding = heap; foreach_live(realloc_object); // for each marked (live) object, record forwarding address // make sure all roots point at new object addresses update_roots(); // can't move objects before updating roots; roots point at *old* location if (DEBUG) printf("UPDATE PTR FIELDS\n"); foreach_live(update_ptr_fields); // Now that we know where to move objects, update and move objects if (DEBUG) printf("COMPACT\n"); // TODO: can this be foreach_live()? foreach_object(move_live_objects_to_forwarding_addr); // also visits the dead to wack p->magic // reset highwater mark *after* we've moved everything around; foreach_object() uses next_free next_free = next_free_forwarding; // next object to be allocated would occur here if (DEBUG) printf("DONE GC\n"); }
static void run_self_test() { array* test_roots = array_create(1); char* cwd = malloc(PATH_MAX); if (getcwd(cwd, PATH_MAX) == NULL) { strncpy(cwd, ".", PATH_MAX); } array_push(test_roots, cwd); update_roots(test_roots); }