#endif
} else {
/* If we don't have free slots in the buffer, allocate a new one and
- * set it's address to GC_ROOT_BUFFER_MAX_ENTRIES that have special
+ * set it's address above GC_ROOT_BUFFER_MAX_ENTRIES that have special
* meaning.
*/
- if (!*additional_buffer || (*additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) {
+ if (!GC_G(additional_buffer) || GC_G(additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) {
gc_additional_buffer *new_buffer = emalloc(sizeof(gc_additional_buffer));
new_buffer->used = 0;
- new_buffer->next = *additional_buffer;
- *additional_buffer = new_buffer;
+ new_buffer->next = GC_G(additional_buffer);
+ GC_G(additional_buffer) = new_buffer;
}
- buf = (*additional_buffer)->buf + (*additional_buffer)->used;
- (*additional_buffer)->used++;
+ buf = GC_G(additional_buffer)->buf + GC_G(additional_buffer)->used;
#if 1
/* optimization: color is already GC_BLACK (0) */
- GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES;
+ GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES + GC_G(additional_buffer)->used;
#else
- GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES);
+ GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES) + GC_G(additional_buffer)->used;
#endif
- /* modify type to prevent indirect destruction */
- GC_TYPE(ref) |= GC_FAKE_BUFFER_FLAG;
+ GC_G(additional_buffer)->used++;
}
if (buf) {
- GC_REFCOUNT(ref)++;
buf->ref = ref;
buf->next = GC_G(roots).next;
buf->prev = &GC_G(roots);
current = GC_G(roots).next;
while (current != &GC_G(roots)) {
- GC_REFCOUNT(current->ref)++;
if (GC_REF_GET_COLOR(current->ref) == GC_WHITE) {
- count += gc_collect_white(current->ref, flags, additional_buffer);
+ count += gc_collect_white(current->ref, flags);
}
current = current->next;
}
tail_call:
if (root ||
(GC_ADDRESS(GC_INFO(ref)) != 0 &&
- GC_REF_GET_COLOR(ref) == GC_BLACK &&
- GC_ADDRESS(GC_INFO(ref)) != GC_ROOT_BUFFER_MAX_ENTRIES)) {
+ GC_REF_GET_COLOR(ref) == GC_BLACK)) {
GC_TRACE_REF(ref, "removing from buffer");
- GC_REFCOUNT(ref)--;
if (root) {
+ if (EXPECTED(GC_ADDRESS(GC_INFO(root->ref)) < GC_ROOT_BUFFER_MAX_ENTRIES)) {
+ gc_remove_from_roots(root);
+ } else {
+ gc_remove_from_additional_roots(root);
+ }
GC_INFO(ref) = 0;
- GC_REMOVE_FROM_ROOTS(root);
root = NULL;
} else {
GC_REMOVE_FROM_BUFFER(ref);