| 76 | } |
| 77 | |
| 78 | void gc_root::gc_sweep() { |
| 79 | gc_collecting = true; |
| 80 | while ( gc_first ) { |
| 81 | auto node = gc_first; |
| 82 | gc_unlink(node); |
| 83 | uint32_t swept_magic = GC_MAGIC_SWEPT_PREFIX | (node->gc_magic & 0xFFFFu); |
| 84 | #if DAS_GC_DEBUG |
| 85 | // !!! DO NOT REMOVE !!! |
| 86 | // Memory poisoning mode for debugging use-after-sweep. |
| 87 | // Destroys the object but keeps memory allocated with 0xCD fill. |
| 88 | // gc_magic (with type tag) and gc_id are restored so crashed nodes can be identified. |
| 89 | // Set DAS_GC_DEBUG=1 to enable, then use DAS_GC_BREAK_ON_ID to find the creator. |
| 90 | { |
| 91 | uint64_t saved_id = node->gc_id; |
| 92 | node->~gc_node(); |
| 93 | #ifdef _MSC_VER |
| 94 | auto sz = _msize(node); |
| 95 | #elif defined(__APPLE__) |
| 96 | auto sz = malloc_size(node); |
| 97 | #else |
| 98 | auto sz = malloc_usable_size(node); |
| 99 | #endif |
| 100 | memset(node, 0xCD, sz); |
| 101 | node->gc_magic = swept_magic; |
| 102 | node->gc_id = saved_id; |
| 103 | } |
| 104 | #else |
| 105 | node->gc_magic = swept_magic; |
| 106 | delete node; |
| 107 | #endif |
| 108 | } |
| 109 | gc_collecting = false; |
| 110 | } |
| 111 | |
| 112 | void gc_root::gc_dump_to_thread_root() { |
| 113 | auto & threadRoot = gc_get_thread_root(); |
no test coverage detected