void Heap::freeUnmarked() { long bytes_freed = 0; for (int bidx = 0; bidx < NUM_BUCKETS; bidx++) { bytes_freed += freeChain(heads[bidx]); bytes_freed += freeChain(full_heads[bidx]); } LargeObj *cur = large_head; while (cur) { void *p = cur->data; GCObjectHeader* header = headerFromObject(p); if (isMarked(header)) { clearMark(header); } else { if (VERBOSITY() >= 2) printf("Freeing %p\n", p); bytes_freed += cur->mmap_size(); *cur->prev = cur->next; if (cur->next) cur->next->prev = cur->prev; LargeObj *to_free = cur; cur = cur->next; _freeLargeObj(to_free); continue; } cur = cur->next; } if (VERBOSITY("gc") >= 2) if (bytes_freed) printf("Freed %ld bytes\n", bytes_freed); }
static long freeChain(Block* head) { long bytes_freed = 0; while (head) { int num_objects = head->numObjects(); int first_obj = head->minObjIndex(); int atoms_per_obj = head->atomsPerObj(); for (int obj_idx = first_obj; obj_idx < num_objects; obj_idx++) { int atom_idx = obj_idx * atoms_per_obj; int bitmap_idx = atom_idx / 64; int bitmap_bit = atom_idx % 64; uint64_t mask = 1L << bitmap_bit; if (head->isfree[bitmap_idx] & mask) continue; void *p = &head->atoms[atom_idx]; GCObjectHeader* header = headerFromObject(p); if (isMarked(header)) { clearMark(header); } else { if (VERBOSITY() >= 2) printf("Freeing %p\n", p); //assert(p != (void*)0x127000d960); // the main module bytes_freed += head->size; head->isfree[bitmap_idx] |= mask; } } head = head->next; } return bytes_freed; }
static void markPhase() { #ifndef NVALGRIND // Have valgrind close its eyes while we do the conservative stack and data scanning, // since we'll be looking at potentially-uninitialized values: VALGRIND_DISABLE_ERROR_REPORTING; #endif TraceStack stack(roots); collectStackRoots(&stack); TraceStackGCVisitor visitor(&stack); //if (VERBOSITY()) printf("Found %d roots\n", stack.size()); while (void* p = stack.pop()) { assert(((intptr_t)p) % 8 == 0); GCObjectHeader* header = headerFromObject(p); //printf("%p\n", p); if (isMarked(header)) { //printf("Already marked, skipping\n"); continue; } //printf("Marking + scanning %p\n", p); setMark(header); ASSERT(KIND_OFFSET <= header->kind_id && header->kind_id < KIND_OFFSET + num_kinds, "%p %d", header, header->kind_id); if (header->kind_id == untracked_kind.kind_id) continue; //ASSERT(kind->_cookie == AllocationKind::COOKIE, "%lx %lx", kind->_cookie, AllocationKind::COOKIE); //AllocationKind::GCHandler gcf = kind->gc_handler; AllocationKind::GCHandler gcf = handlers[header->kind_id - KIND_OFFSET]; assert(gcf); //if (!gcf) { //std::string name = g.func_addr_registry.getFuncNameAtAddress((void*)kind, true); //ASSERT(gcf, "%p %s", kind, name.c_str()); //} gcf(&visitor, p); } #ifndef NVALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif }
static void markPhase() { TraceStack stack(roots); collectStackRoots(&stack); TraceStackGCVisitor visitor(&stack); //if (VERBOSITY()) printf("Found %d roots\n", stack.size()); while (void* p = stack.pop()) { assert(((intptr_t)p) % 8 == 0); GCObjectHeader* header = headerFromObject(p); //printf("%p\n", p); if (isMarked(header)) { //printf("Already marked, skipping\n"); continue; } //printf("Marking + scanning %p\n", p); setMark(header); ASSERT(KIND_OFFSET <= header->kind_id && header->kind_id < KIND_OFFSET + num_kinds, "%p %d", header, header->kind_id); if (header->kind_id == untracked_kind.kind_id) continue; //ASSERT(kind->_cookie == AllocationKind::COOKIE, "%lx %lx", kind->_cookie, AllocationKind::COOKIE); //AllocationKind::GCHandler gcf = kind->gc_handler; AllocationKind::GCHandler gcf = handlers[header->kind_id - KIND_OFFSET]; assert(gcf); //if (!gcf) { //std::string name = g.func_addr_registry.getFuncNameAtAddress((void*)kind, true); //ASSERT(gcf, "%p %s", kind, name.c_str()); //} gcf(&visitor, p); } }