// Assumes _tlcBuffer/_tlcBufferCount hold the garbage list void ThreadLocalCollector::evict_local_garbage() { // scan the garbage blocks to evict all blocks reachable from the garbage list size_t evict_cursor = _tlcBufferCount; size_t scan_cursor = 0; while (scan_cursor < _tlcBufferCount) { void *block = _tlcBuffer[scan_cursor++]; Subzone *subzone = Subzone::subzone(block); usword_t q = subzone->quantum_index_unchecked(block); if (subzone->is_scanned(q)) { scan_local_block(subzone, q, block); } } usword_t global_size = 0; while (evict_cursor < _tlcBufferCount) { void *block = _tlcBuffer[evict_cursor++]; // evict this block, since it is reachable from garbage, but not itself garbage. Subzone *subzone = Subzone::subzone(block); usword_t q = subzone->quantum_index_unchecked(block); subzone->make_global(q); _localBlocks.remove(block); global_size += subzone->size(q); } if (global_size != 0) _zone->adjust_allocation_counter(global_size); }
void ThreadLocalCollector::evict_local_garbage(size_t count, vm_address_t garbage[]) { set_marked_blocks_buffer(NULL); // scan the garbage blocks first. _markedBlocksCounter = 0; for (size_t i = 0; i < count; ++i) { void *block = (void*)garbage[i]; Subzone *sz = Subzone::subzone(block); usword_t layout = sz->layout(block); if (!(layout & AUTO_UNSCANNED)) { Range range(block, sz->size(block)); const unsigned char *map = (layout & AUTO_OBJECT) ? _zone->layout_map_for_block(block) : NULL; if (map) scan_with_layout(range, map, NULL); // TLC doesn't need the write barrier. else scan_range(range, NULL); } } // if no blocks were marked, then no evicitions needed. if (_markedBlocksCounter == 0) return; // now, mark all blocks reachable from the garbage blocks themselves. scan_marked_blocks(); for (uint32_t i = _localBlocks.firstOccupiedSlot(); i <= _localBlocks.lastOccupiedSlot(); i++) { if (!_localBlocks.validPointerAtIndex(i)) continue; if (_localBlocks.wasMarked(i)) { void *block = _localBlocks[i]; Subzone *subzone = Subzone::subzone(block); // evict this block, since it is reachable from garbage, but not itself garbage. subzone->make_global(block); _localBlocks.remove(i); } } }