void ImmixGC::collect_finish(GCData* data) { collect_scan(data); ObjectArray* marked_set = object_memory_->swap_marked_set(); for(ObjectArray::iterator oi = marked_set->begin(); oi != marked_set->end(); ++oi) { Object* obj = *oi; if(obj) saw_object(obj); } delete marked_set; // Users manipulate values accessible from the data* within an // RData without running a write barrier. Thusly if we see any rdata // we must always scan it again here because it could contain new pointers. // // We do this in a loop because the scanning might generate new entries // on the mark stack. do { for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator()); i.more(); i.advance()) { capi::Handle* hdl = i.current(); if(!hdl->in_use_p()) continue; if(hdl->is_rdata()) { Object* obj = hdl->object(); if(obj->marked_p(object_memory_->mark())) { scan_object(obj); } } } } while(process_mark_stack()); // We've now finished marking the entire object graph. // Clean weakrefs before keeping additional objects alive // for finalization, so people don't get a hold of finalized // objects through weakrefs. clean_weakrefs(); // Marking objects to be Finalized can cause more things to continue to // live, so we must check the mark_stack again. do { walk_finalizers(); scan_fibers(data, true); } while(process_mark_stack()); // Remove unreachable locked objects still in the list if(data->threads()) { for(std::list<ManagedThread*>::iterator i = data->threads()->begin(); i != data->threads()->end(); ++i) { clean_locked_objects(*i, false); } } // Clear unreachable objects from the various remember sets unsigned int mark = object_memory_->mark(); object_memory_->unremember_objects(mark); }
/** * Performs a garbage collection of the immix space. */ void ImmixGC::collect(GCData* data) { gc_.clear_marks(); collect_scan(data); process_mark_stack(); collect_finish(data); }