Author: Nicolas Truessel <ntrues...@njsm.de> Branch: quad-color-gc Changeset: r87057:2b705e789377 Date: 2016-09-12 21:13 +0200 http://bitbucket.org/pypy/pypy/changeset/2b705e789377/
Log: Update qcgc codebase again diff too long, truncating to 2000 out of 5319 lines diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -898,9 +898,7 @@ includes = ["qcgc.h"], separate_module_sources = [separate_source], # XXX separate_module_files = [os.path.join(library_dir, f) for f in - ["qcgc.c", "arena.c", "allocator.c", "bag.c", "event_logger.c", - "gray_stack.c", "shadow_stack.c", "hugeblocktable.c", - "signal_handler.c"]], + ["qcgc.c"]], ) return eci diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -946,10 +946,10 @@ def OP_QCGC_PUSH_ROOT(self, op): obj = self.expr(op.args[0]) - return 'qcgc_shadowstack_push((object_t *) %s);' % (obj,) + return 'qcgc_push_root((object_t *) %s);' % (obj,) def OP_QCGC_POP_ROOT(self, op): - return 'qcgc_shadowstack_pop();' + return 'qcgc_pop_root();' def OP_QCGC_ALLOCATE(self, op): # XXX: SET typeid @@ -967,4 +967,4 @@ def OP_QCGC_REGISTER_WEAKREF(self, op): weakref = self.expr(op.args[0]) fieldaddr = self.expr(op.args[1]) - return 'qcgc_register_weakref(%s, %s);' % (weakref, fieldaddr) + return 'qcgc_register_weakref((object_t *)%s, (object_t **)%s);' % (weakref, fieldaddr) diff --git a/rpython/translator/c/src/qcgc/allocator.c b/rpython/translator/c/src/qcgc/allocator.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/allocator.c +++ /dev/null @@ -1,428 +0,0 @@ -#include "allocator.h" - -#include <assert.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#include "hugeblocktable.h" - -QCGC_STATIC size_t bytes_to_cells(size_t bytes); - -QCGC_STATIC void bump_allocator_assign(cell_t *ptr, size_t cells); -QCGC_STATIC void bump_allocator_advance(size_t cells); -QCGC_STATIC void bump_allocator_renew_block(void); - -QCGC_STATIC bool is_small(size_t cells); -QCGC_STATIC size_t small_index(size_t cells); -QCGC_STATIC size_t large_index(size_t cells); -QCGC_STATIC size_t small_index_to_cells(size_t index); - -QCGC_STATIC cell_t *fit_allocator_small_first_fit(size_t index, size_t cells); -QCGC_STATIC cell_t *fit_allocator_large_fit(size_t index, size_t cells); -QCGC_STATIC cell_t *fit_allocator_large_first_fit(size_t index, size_t cells); - -QCGC_STATIC bool valid_block(cell_t *ptr, size_t cells); -QCGC_STATIC void free_list_consistency_check(void); - -void qcgc_allocator_initialize(void) { - qcgc_allocator_state.arenas = - qcgc_arena_bag_create(QCGC_ARENA_BAG_INIT_SIZE); - qcgc_allocator_state.free_arenas = qcgc_arena_bag_create(4); // XXX - - qcgc_allocator_state.use_bump_allocator = true; - - // Bump Allocator - qcgc_allocator_state.bump_state.bump_ptr = NULL; - qcgc_allocator_state.bump_state.remaining_cells = 0; - - // Fit Allocator - for (size_t i = 0; i < QCGC_SMALL_FREE_LISTS; i++) { - qcgc_allocator_state.fit_state.small_free_list[i] = - qcgc_linear_free_list_create(QCGC_SMALL_FREE_LIST_INIT_SIZE); - } - - for (size_t i = 0; i < QCGC_LARGE_FREE_LISTS; i++) { - qcgc_allocator_state.fit_state.large_free_list[i] = - qcgc_exp_free_list_create(QCGC_LARGE_FREE_LIST_INIT_SIZE); - } -} - -void qcgc_allocator_destroy(void) { - // Fit Allocator - for (size_t i = 0; i < QCGC_SMALL_FREE_LISTS; i++) { - free(qcgc_allocator_state.fit_state.small_free_list[i]); - } - - for (size_t i = 0; i < QCGC_LARGE_FREE_LISTS; i++) { - free(qcgc_allocator_state.fit_state.large_free_list[i]); - } - - // Arenas - size_t arena_count = qcgc_allocator_state.arenas->count; - for (size_t i = 0; i < arena_count; i++) { - qcgc_arena_destroy(qcgc_allocator_state.arenas->items[i]); - } - - arena_count = qcgc_allocator_state.free_arenas->count; - for (size_t i = 0; i < arena_count; i++) { - qcgc_arena_destroy(qcgc_allocator_state.free_arenas->items[i]); - } - - free(qcgc_allocator_state.arenas); - free(qcgc_allocator_state.free_arenas); -} - -void qcgc_fit_allocator_add(cell_t *ptr, size_t cells) { -#if CHECKED - if (cells > 0) { - assert((((object_t *)ptr)->flags & QCGC_PREBUILT_OBJECT) == 0); - assert((cell_t *) qcgc_arena_addr(ptr) != ptr); - assert(qcgc_arena_get_blocktype(ptr) == BLOCK_FREE); - if (qcgc_arena_addr(ptr) == qcgc_arena_addr(ptr + cells)) { - assert(qcgc_arena_get_blocktype(ptr + cells) != BLOCK_EXTENT); - } - for (size_t i = 1; i < cells; i++) { - assert(qcgc_arena_get_blocktype(ptr + i) == BLOCK_EXTENT); - } - } -#endif - if (cells > 0) { - if (is_small(cells)) { - size_t index = small_index(cells); - qcgc_allocator_state.fit_state.small_free_list[index] = - qcgc_linear_free_list_add( - qcgc_allocator_state.fit_state.small_free_list[index], - ptr); - } else { - size_t index = large_index(cells); - qcgc_allocator_state.fit_state.large_free_list[index] = - qcgc_exp_free_list_add( - qcgc_allocator_state.fit_state.large_free_list[index], - (struct exp_free_list_item_s) {ptr, cells}); - } - } -} - -/******************************************************************************* - * Bump Allocator * - ******************************************************************************/ - -object_t *qcgc_bump_allocate(size_t bytes) { -#if CHECKED - assert(bytes <= 1<<QCGC_LARGE_ALLOC_THRESHOLD_EXP); -#endif - size_t cells = bytes_to_cells(bytes); - if (cells > qcgc_allocator_state.bump_state.remaining_cells) { - bump_allocator_renew_block(); - } - cell_t *mem = qcgc_allocator_state.bump_state.bump_ptr; - bump_allocator_advance(cells); - - qcgc_arena_mark_allocated(mem, cells); - object_t *result = (object_t *) mem; - -#if QCGC_INIT_ZERO - memset(result, 0, cells * sizeof(cell_t)); -#endif - - result->flags |= QCGC_GRAY_FLAG; -#if CHECKED - assert(qcgc_arena_is_coalesced(qcgc_arena_addr((cell_t *)result))); - if (qcgc_allocator_state.bump_state.remaining_cells > 0) { - assert(qcgc_arena_get_blocktype( - qcgc_allocator_state.bump_state.bump_ptr) == BLOCK_FREE); - for (size_t i = 1; i < qcgc_allocator_state.bump_state.remaining_cells; - i++) { - assert(qcgc_arena_get_blocktype( - qcgc_allocator_state.bump_state.bump_ptr + i) - == BLOCK_EXTENT); - } - } -#endif - return result; -} - -QCGC_STATIC void bump_allocator_renew_block(void) { -#if CHECKED - if (qcgc_allocator_state.bump_state.remaining_cells > 0) { - assert(qcgc_arena_get_blocktype( - qcgc_allocator_state.bump_state.bump_ptr) == BLOCK_FREE); - for (size_t i = 1; i < qcgc_allocator_state.bump_state.remaining_cells; - i++) { - assert(qcgc_arena_get_blocktype( - qcgc_allocator_state.bump_state.bump_ptr + i) - == BLOCK_EXTENT); - } - } -#endif - // Add remaining memory to fit allocator - qcgc_fit_allocator_add(qcgc_allocator_state.bump_state.bump_ptr, - qcgc_allocator_state.bump_state.remaining_cells); - - // Try finding some huge block from fit allocator - exp_free_list_t *free_list = qcgc_allocator_state.fit_state. - large_free_list[QCGC_LARGE_FREE_LISTS - 1]; - while (free_list->count > 0 && !valid_block(free_list->items[0].ptr, - free_list->items[0].size)) { - free_list = qcgc_exp_free_list_remove_index(free_list, 0); - } - - if (free_list->count > 0) { - // Assign huge block to bump allocator - bump_allocator_assign(free_list->items[0].ptr, - free_list->items[0].size); - free_list = qcgc_exp_free_list_remove_index(free_list, 0); - } else { - // Grab a new arena - arena_t *arena = qcgc_arena_create(); - bump_allocator_assign(&(arena->cells[QCGC_ARENA_FIRST_CELL_INDEX]), - QCGC_ARENA_CELLS_COUNT - QCGC_ARENA_FIRST_CELL_INDEX); - qcgc_allocator_state.arenas = - qcgc_arena_bag_add(qcgc_allocator_state.arenas, arena); - } - - qcgc_allocator_state.fit_state. - large_free_list[QCGC_LARGE_FREE_LISTS - 1] = free_list; -#if CHECKED - assert(qcgc_allocator_state.bump_state.bump_ptr != NULL); - assert(qcgc_arena_get_blocktype(qcgc_allocator_state.bump_state.bump_ptr) == - BLOCK_FREE); - for (size_t i = 1; i < qcgc_allocator_state.bump_state.remaining_cells; - i++) { - assert(qcgc_arena_get_blocktype( - qcgc_allocator_state.bump_state.bump_ptr + i) - == BLOCK_EXTENT); - } -#endif -} - -QCGC_STATIC void bump_allocator_assign(cell_t *ptr, size_t cells) { -#if CHECKED - assert(qcgc_arena_get_blocktype(ptr) == BLOCK_FREE); - for (size_t i = 1; i < cells; i++) { - assert(qcgc_arena_get_blocktype(ptr + i) == BLOCK_EXTENT); - } -#endif - qcgc_allocator_state.bump_state.bump_ptr = ptr; - qcgc_allocator_state.bump_state.remaining_cells = cells; -} - -QCGC_STATIC void bump_allocator_advance(size_t cells) { - qcgc_allocator_state.bump_state.bump_ptr += cells; - qcgc_allocator_state.bump_state.remaining_cells -= cells; -} - -object_t *qcgc_fit_allocate(size_t bytes) { -#if CHECKED - //free_list_consistency_check(); -#endif - size_t cells = bytes_to_cells(bytes); - cell_t *mem; - - if (is_small(cells)) { - size_t index = small_index(cells); - mem = fit_allocator_small_first_fit(index, cells); - } else { - size_t index = large_index(cells); - mem = fit_allocator_large_fit(index, cells); - } - - if (mem == NULL) { - return NULL; - } - - object_t *result = (object_t *) mem; - -#if QCGC_INIT_ZERO - memset(result, 0, cells * sizeof(cell_t)); -#endif - - result->flags |= QCGC_GRAY_FLAG; - return result; -} - -/** - * Constraints: - * - Zero initialized - * - Aligned to arena size - * - Multiple of arena size - * - No header, metadata stored in hash-map - */ -object_t *qcgc_large_allocate(size_t bytes) { - object_t *result = aligned_alloc(QCGC_ARENA_SIZE, bytes); -#if QCGC_INIT_ZERO - memset(result, 0, bytes); -#endif - qcgc_hbtable_insert(result); - return result; -} - -void qcgc_fit_allocator_empty_lists(void) { - for (size_t i = 0; i < QCGC_SMALL_FREE_LISTS; i++) { - qcgc_allocator_state.fit_state.small_free_list[i]->count = 0; - } - - for (size_t i = 0; i < QCGC_LARGE_FREE_LISTS; i++) { - qcgc_allocator_state.fit_state.large_free_list[i]->count = 0; - } -} - -QCGC_STATIC cell_t *fit_allocator_small_first_fit(size_t index, size_t cells) { -#if CHECKED - assert(small_index_to_cells(index) >= cells); -#endif - cell_t *result = NULL; - for ( ; index < QCGC_SMALL_FREE_LISTS; index++) { - size_t list_cell_size = small_index_to_cells(index); - - if (qcgc_allocator_state.fit_state.small_free_list[index]->count > 0) { - result = qcgc_allocator_state.fit_state.small_free_list[index]-> - items[0]; - qcgc_allocator_state.fit_state.small_free_list[index] = - qcgc_linear_free_list_remove_index( - qcgc_allocator_state.fit_state.small_free_list[index], - 0); - qcgc_arena_mark_allocated(result, cells); - qcgc_fit_allocator_add(result + cells, list_cell_size - cells); - return result; - } - } - return fit_allocator_large_first_fit(0, cells); -} - -QCGC_STATIC cell_t *fit_allocator_large_fit(size_t index, size_t cells) { -#if CHECKED - assert(1u<<(index + QCGC_LARGE_FREE_LIST_FIRST_EXP) <= cells); - assert(1u<<(index + QCGC_LARGE_FREE_LIST_FIRST_EXP + 1) > cells); -#endif - size_t best_fit_index = qcgc_allocator_state.fit_state. - large_free_list[index]->count; - - cell_t *result = NULL; - size_t best_fit_cells = SIZE_MAX; - size_t count = qcgc_allocator_state.fit_state.large_free_list[index]->count; - for (size_t i = 0; i < count; i++) { - if (qcgc_allocator_state.fit_state.large_free_list[index]-> - items[i].size >= cells && - qcgc_allocator_state.fit_state.large_free_list[index]-> - items[i].size < best_fit_cells) { - result = qcgc_allocator_state.fit_state.large_free_list[index]-> - items[i].ptr; - best_fit_cells = qcgc_allocator_state.fit_state. - large_free_list[index]->items[i].size; - best_fit_index = i; - } - if (best_fit_cells == cells) { - break; - } - } - - if (result != NULL) { - // Best fit was found - assert(best_fit_index < qcgc_allocator_state.fit_state. - large_free_list[index]->count); - qcgc_allocator_state.fit_state.large_free_list[index] = - qcgc_exp_free_list_remove_index(qcgc_allocator_state.fit_state. - large_free_list[index], best_fit_index); - qcgc_arena_mark_allocated(result, cells); - qcgc_fit_allocator_add(result + cells, best_fit_cells - cells); - } else { - // No best fit, go for first fit - result = fit_allocator_large_first_fit(index + 1, cells); - } - return result; -} - -QCGC_STATIC cell_t *fit_allocator_large_first_fit(size_t index, size_t cells) { -#if CHECKED - assert(1u<<(index + QCGC_LARGE_FREE_LIST_FIRST_EXP) >= cells); -#endif - for ( ; index < QCGC_LARGE_FREE_LISTS; index++) { - if (qcgc_allocator_state.fit_state.large_free_list[index]->count > 0) { - struct exp_free_list_item_s item = - qcgc_allocator_state.fit_state.large_free_list[index]->items[0]; - qcgc_allocator_state.fit_state.large_free_list[index] = - qcgc_exp_free_list_remove_index( - qcgc_allocator_state.fit_state.large_free_list[index], - 0); - - qcgc_arena_mark_allocated(item.ptr, cells); - qcgc_fit_allocator_add(item.ptr + cells, item.size - cells); - return item.ptr; - } - } - return NULL; -} - -QCGC_STATIC size_t bytes_to_cells(size_t bytes) { - return (bytes + sizeof(cell_t) - 1) / sizeof(cell_t); -} - -QCGC_STATIC bool is_small(size_t cells) { - return cells <= QCGC_SMALL_FREE_LISTS; -} - -QCGC_STATIC size_t small_index(size_t cells) { -#if CHECKED - assert(is_small(cells)); -#endif - return cells - 1; -} - -QCGC_STATIC size_t large_index(size_t cells) { -#if CHECKED - assert(!is_small(cells)); -#endif - // shift such that the meaningless part disappears, i.e. everything that - // belongs into the first free list will become 1. - cells = cells >> QCGC_LARGE_FREE_LIST_FIRST_EXP; - - // calculates floor(log(cells)) - return MIN((8 * sizeof(unsigned long)) - __builtin_clzl(cells) - 1, QCGC_LARGE_FREE_LISTS - 1); -} - -QCGC_STATIC size_t small_index_to_cells(size_t index) { -#if CHECKED - assert(index < QCGC_SMALL_FREE_LISTS); -#endif - return index + 1; -} - -QCGC_STATIC bool valid_block(cell_t *ptr, size_t cells) { -#if CHECKED - assert(ptr != NULL); - assert(cells > 0); -#endif - return (qcgc_arena_get_blocktype(ptr) == BLOCK_FREE && ( - ((qcgc_arena_addr(ptr + cells)) == (arena_t *) (ptr + cells)) || - qcgc_arena_get_blocktype(ptr + cells) != BLOCK_EXTENT)); -} - -QCGC_STATIC void free_list_consistency_check(void) { - for (size_t i = 0; i < QCGC_SMALL_FREE_LISTS; i++) { - linear_free_list_t *free_list = - qcgc_allocator_state.fit_state.small_free_list[i]; - for (size_t j = 0; j < free_list->count; j++) { - cell_t *item = free_list->items[j]; - if (qcgc_arena_get_blocktype(item) == BLOCK_FREE) { - for (size_t s = 1; s < small_index_to_cells(i); s++) { - assert(qcgc_arena_get_blocktype(item + s) == BLOCK_EXTENT); - } - } - } - } - - for (size_t i = 0; i < QCGC_LARGE_FREE_LISTS; i++) { - exp_free_list_t *free_list = - qcgc_allocator_state.fit_state.large_free_list[i]; - for (size_t j = 0; j < free_list->count; j++) { - struct exp_free_list_item_s item = free_list->items[j]; - if (qcgc_arena_get_blocktype(item.ptr) == BLOCK_FREE) { - for (size_t s = 1; s < item.size; s++) { - assert(qcgc_arena_get_blocktype(item.ptr + s) == BLOCK_EXTENT); - } - } - } - } -} diff --git a/rpython/translator/c/src/qcgc/allocator.h b/rpython/translator/c/src/qcgc/allocator.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/allocator.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "config.h" - -#include <stddef.h> - -#include "arena.h" -#include "bag.h" -#include "object.h" - -/** - * Free lists: - * - * Small free lists: - * +---+---+-----+----+ - * index: | 0 | 1 | ... | 30 | - * +---+---+-----+----+ - * size (cells): | 1 | 2 | ... | 31 | - * +---+---+-----+----+ - * (31 is 2^QCGC_LARGE_FREE_LIST_FIRST_EXP - 1) - * - * Large free lists: - * +-----+-----+-----+---------+ - * index: | 0 | 1 | ... | x | - * +-----+-----+-----+---------+ - * minimal size (cells): | 2^5 | 2^6 | ... | 2^(x+5) | - * +-----+-----+-----+---------+ - * (5 is QCGC_LARGE_FREE_LIST_FIRST_EXP) - * - * where x is chosen such that 2^(x + 5) = 2^QCGC_LARGE_ALLOC_THRESHOLD_EXP - * (i.e. such that the last bin contains all blocks that are larger or equal - * than the threshold for huge blocks. These blocks can be returned to the - * bump allocator) - */ -#define QCGC_LARGE_FREE_LISTS (QCGC_LARGE_ALLOC_THRESHOLD_EXP - QCGC_LARGE_FREE_LIST_FIRST_EXP - 4 + 1) -// -4 because of turning bytes into cells, +1 because we start to count at 0 - -#define QCGC_SMALL_FREE_LISTS ((1<<QCGC_LARGE_FREE_LIST_FIRST_EXP) - 1) - -struct qcgc_allocator_state { - arena_bag_t *arenas; - arena_bag_t *free_arenas; - struct bump_state { - cell_t *bump_ptr; - size_t remaining_cells; - } bump_state; - struct fit_state { - linear_free_list_t *small_free_list[QCGC_SMALL_FREE_LISTS]; - exp_free_list_t *large_free_list[QCGC_LARGE_FREE_LISTS]; - } fit_state; - bool use_bump_allocator; -} qcgc_allocator_state; - -/** - * Initialize allocator - */ -void qcgc_allocator_initialize(void); - -/** - * Destroy allocator - */ -void qcgc_allocator_destroy(void); - -/** - * Allocate new memory region using fit allocator - * - * @param bytes Desired size of the memory region in bytes - * @return Pointer to memory large enough to hold size bytes, NULL in case of - * errors or if there is no block sufficently large block, already zero - * initialized if QCGC_INIT_ZERO is set - */ -object_t *qcgc_fit_allocate(size_t bytes); - -/** - * Allocate new memory region using bump allocator - * - * @param bytes Desired size of the memory region in bytes - * @return Pointer to memory large enough to hold size bytes, NULL in case of - * errors, already zero initialized if QCGC_INIT_ZERO is set - */ -object_t *qcgc_bump_allocate(size_t bytes); - -/** - * Allocate new memory region using huge block allocator - * - * @param bytes Desired size of the memory region in bytes - * @return Pointer to memory large enough to hold size bytes, NULL in case of - * errors, already zero initialized if QCGC_INIT_ZERO is set - */ -object_t *qcgc_large_allocate(size_t bytes); - -/** - * Empty all free lists (used before sweep) - */ -void qcgc_fit_allocator_empty_lists(void); - - -/** - * Add memory to free lists - * - * @param ptr Pointer to memory region - * @param cells Size of memory region in cells - */ -void qcgc_fit_allocator_add(cell_t *ptr, size_t cells); diff --git a/rpython/translator/c/src/qcgc/arena.c b/rpython/translator/c/src/qcgc/arena.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/arena.c +++ /dev/null @@ -1,398 +0,0 @@ -#include "arena.h" - -#include <assert.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <unistd.h> - -#if DEBUG_ZERO_ON_SWEEP -#include <string.h> -#endif - -#include "allocator.h" -#include "event_logger.h" -#include "gc_state.h" - -/** - * Internal functions - */ -QCGC_STATIC blocktype_t get_blocktype(arena_t *arena, size_t index); -QCGC_STATIC void set_blocktype(arena_t *arena, size_t index, blocktype_t type); - -arena_t *qcgc_arena_create(void) { - qcgc_event_logger_log(EVENT_NEW_ARENA, 0, NULL); - - arena_t *result; - // Linux: MAP_ANONYMOUS is initialized to zero - cell_t *mem = (cell_t *) mmap(0, 2 * QCGC_ARENA_SIZE, - PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if (mem == MAP_FAILED) { - // ERROR: OUT OF MEMORY - return NULL; - } - if (mem != qcgc_arena_addr(mem)->cells) { - // Not aligned -> align - cell_t *aligned_mem = (cell_t *)( - (intptr_t) qcgc_arena_addr(mem) + QCGC_ARENA_SIZE); - size_t size_before = (size_t)((intptr_t) aligned_mem - (intptr_t) mem); - size_t size_after = QCGC_ARENA_SIZE - size_before; - - munmap((void *) mem, size_before); - munmap((void *)((intptr_t) aligned_mem + QCGC_ARENA_SIZE), size_after); - result = (arena_t *) aligned_mem; - } else { - // free second half - munmap((void *)((intptr_t) mem + QCGC_ARENA_SIZE), QCGC_ARENA_SIZE); - result = (arena_t *) mem; - } - - // Init bitmaps: One large free block - qcgc_arena_set_bitmap_entry(result->mark_bitmap, QCGC_ARENA_FIRST_CELL_INDEX, true); - - // Create gray stack - result->gray_stack = qcgc_gray_stack_create(QCGC_GRAY_STACK_INIT_SIZE); - return result; -} - -void qcgc_arena_destroy(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - free(arena->gray_stack); - munmap((void *) arena, QCGC_ARENA_SIZE); -} - -arena_t *qcgc_arena_addr(cell_t *ptr) { - return (arena_t *)((intptr_t) ptr & ~(QCGC_ARENA_SIZE - 1)); -} - -size_t qcgc_arena_cell_index(cell_t *ptr) { - return (size_t)((intptr_t) ptr & (QCGC_ARENA_SIZE - 1)) >> 4; -} - -bool qcgc_arena_get_bitmap_entry(uint8_t *bitmap, size_t index) { -#if CHECKED - assert(bitmap != NULL); -#endif - return (((bitmap[index / 8] >> (index % 8)) & 0x1) == 0x01); -} - -void qcgc_arena_set_bitmap_entry(uint8_t *bitmap, size_t index, bool value) { -#if CHECKED - assert(bitmap != NULL); -#endif - if (value) { - bitmap[index / 8] |= 1<<(index % 8); - } else { - bitmap[index / 8] &= ~(1<<(index % 8)); - } -} - -QCGC_STATIC blocktype_t get_blocktype(arena_t *arena, size_t index) { -#if CHECKED - assert(arena != NULL); -#endif - uint8_t block_bit = qcgc_arena_get_bitmap_entry(arena->block_bitmap, index); - uint8_t mark_bit = qcgc_arena_get_bitmap_entry(arena->mark_bitmap, index); - - if (block_bit) { - if (mark_bit) { - return BLOCK_BLACK; - } else { - return BLOCK_WHITE; - } - } else { - if (mark_bit) { - return BLOCK_FREE; - } else { - return BLOCK_EXTENT; - } - } -} - -blocktype_t qcgc_arena_get_blocktype(cell_t *ptr) { - size_t index = qcgc_arena_cell_index(ptr); - arena_t *arena = qcgc_arena_addr(ptr); - - return get_blocktype(arena, index); -} - -QCGC_STATIC void set_blocktype(arena_t *arena, size_t index, blocktype_t type) { -#if CHECKED - assert(arena != NULL); -#endif - switch(type) { - case BLOCK_EXTENT: - qcgc_arena_set_bitmap_entry(arena->block_bitmap, index, false); - qcgc_arena_set_bitmap_entry(arena->mark_bitmap, index, false); - break; - case BLOCK_FREE: - qcgc_arena_set_bitmap_entry(arena->block_bitmap, index, false); - qcgc_arena_set_bitmap_entry(arena->mark_bitmap, index, true); - break; - case BLOCK_WHITE: - qcgc_arena_set_bitmap_entry(arena->block_bitmap, index, true); - qcgc_arena_set_bitmap_entry(arena->mark_bitmap, index, false); - break; - case BLOCK_BLACK: - qcgc_arena_set_bitmap_entry(arena->mark_bitmap, index, true); - qcgc_arena_set_bitmap_entry(arena->block_bitmap, index, true); - break; - } -} - -void qcgc_arena_set_blocktype(cell_t *ptr, blocktype_t type) { - size_t index = qcgc_arena_cell_index(ptr); - arena_t *arena = qcgc_arena_addr(ptr); - set_blocktype(arena, index, type); -} - -void qcgc_arena_mark_allocated(cell_t *ptr, size_t cells) { - size_t index = qcgc_arena_cell_index(ptr); - arena_t *arena = qcgc_arena_addr(ptr); -#if CHECKED - assert(get_blocktype(arena, index) == BLOCK_FREE); - for (size_t i = 1; i < cells; i++) { - assert(get_blocktype(arena, index + i) == BLOCK_EXTENT); - } -#endif - set_blocktype(arena, index, BLOCK_WHITE); - size_t index_of_next_block = index + cells; - if (index_of_next_block < QCGC_ARENA_CELLS_COUNT && - get_blocktype(arena, index_of_next_block) == BLOCK_EXTENT) { - set_blocktype(arena, index_of_next_block, BLOCK_FREE); - } -#if CHECKED - assert(get_blocktype(arena, index) == BLOCK_WHITE); - for (size_t i = 1; i < cells; i++) { - assert(get_blocktype(arena, index + i) == BLOCK_EXTENT); - } - if (index_of_next_block < QCGC_ARENA_CELLS_COUNT) { - assert(get_blocktype(arena, index + cells) != BLOCK_EXTENT); - } -#endif -} - -void qcgc_arena_mark_free(cell_t *ptr) { - qcgc_arena_set_blocktype(ptr, BLOCK_FREE); - // No coalescing, collector will do this -} - -bool qcgc_arena_pseudo_sweep(arena_t *arena) { -#if CHECKED - assert(arena != NULL); - assert(qcgc_arena_is_coalesced(arena)); - assert(qcgc_arena_addr(qcgc_allocator_state.bump_state.bump_ptr) == arena); -#endif - // Ignore free cell / largest block counting here, as blocks are not - // registerd in free lists as well - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (get_blocktype(arena, cell)) { - case BLOCK_BLACK: - set_blocktype(arena, cell, BLOCK_WHITE); - case BLOCK_FREE: // Fall through - case BLOCK_EXTENT: // Fall through - case BLOCK_WHITE: // Fall through - break; - } - } -#if CHECKED - assert(qcgc_arena_is_coalesced(arena)); -#endif - return false; -} - -bool qcgc_arena_sweep(arena_t *arena) { -#if CHECKED - assert(arena != NULL); - assert(qcgc_arena_is_coalesced(arena)); - //assert(qcgc_arena_addr(qcgc_allocator_state.bump_state.bump_ptr) != arena); -#endif - if (qcgc_arena_addr(qcgc_allocator_state.bump_state.bump_ptr) == arena) { - return qcgc_arena_pseudo_sweep(arena); - } - - size_t last_free_cell = 0; - bool free = true; - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (get_blocktype(arena, cell)) { - case BLOCK_EXTENT: - break; - case BLOCK_FREE: - if (last_free_cell != 0) { - // Coalesce - set_blocktype(arena, cell, BLOCK_EXTENT); - } else { - last_free_cell = cell; - } - // ==> last_free_cell != 0 - break; - case BLOCK_WHITE: - if (last_free_cell != 0) { - // Coalesce - set_blocktype(arena, cell, BLOCK_EXTENT); - } else { - set_blocktype(arena, cell, BLOCK_FREE); - last_free_cell = cell; - } - // ==> last_free_cell != 0 - break; - case BLOCK_BLACK: - set_blocktype(arena, cell, BLOCK_WHITE); - if (last_free_cell != 0) { - qcgc_fit_allocator_add(arena->cells + last_free_cell, - cell - last_free_cell); -#if DEBUG_ZERO_ON_SWEEP - memset(arena->cells + last_free_cell, 0, - sizeof(cell_t) * (cell - last_free_cell)); -#endif - qcgc_state.free_cells += cell - last_free_cell; - qcgc_state.largest_free_block = MAX( - qcgc_state.largest_free_block, - cell - last_free_cell); - last_free_cell = 0; - } - free = false; - // ==> last_free_cell == 0 - break; - } - } - if (last_free_cell != 0 && !free) { - qcgc_fit_allocator_add(arena->cells + last_free_cell, - QCGC_ARENA_CELLS_COUNT - last_free_cell); -#if DEBUG_ZERO_ON_SWEEP - memset(arena->cells + last_free_cell, 0, - sizeof(cell_t) * (QCGC_ARENA_CELLS_COUNT - last_free_cell)); -#endif - qcgc_state.free_cells += QCGC_ARENA_CELLS_COUNT - last_free_cell; - qcgc_state.largest_free_block = MAX( - qcgc_state.largest_free_block, - QCGC_ARENA_CELLS_COUNT - last_free_cell); - last_free_cell = 0; - } -#if CHECKED - assert(qcgc_arena_is_coalesced(arena)); - assert(free == qcgc_arena_is_empty(arena)); -#endif - return free; -} - -bool qcgc_arena_is_empty(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (qcgc_arena_get_blocktype((void *) &arena->cells[cell])) { - case BLOCK_WHITE: // Fall through - case BLOCK_BLACK: - return false; - - default: - break; - } - } - return true; -} - - -bool qcgc_arena_is_coalesced(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - bool prev_was_free = false; - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (qcgc_arena_get_blocktype((void *) &arena->cells[cell])) { - case BLOCK_WHITE: // Fall through - case BLOCK_BLACK: - prev_was_free = false; - break; - - case BLOCK_FREE: - if (prev_was_free) { - return false; - } else { - prev_was_free = true; - } - break; - - case BLOCK_EXTENT: - break; - } - } - return true; -} - -size_t qcgc_arena_free_blocks(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - size_t result = 0; - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (qcgc_arena_get_blocktype((void *) &arena->cells[cell])) { - case BLOCK_WHITE: // Fall through - case BLOCK_BLACK: - case BLOCK_EXTENT: - break; - - case BLOCK_FREE: - result++; - break; - } - } - return result; -} - -size_t qcgc_arena_white_blocks(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - size_t result = 0; - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (qcgc_arena_get_blocktype((void *) &arena->cells[cell])) { - case BLOCK_BLACK: // Fall through - case BLOCK_EXTENT: - case BLOCK_FREE: - break; - - case BLOCK_WHITE: - result++; - break; - } - } - return result; -} - -size_t qcgc_arena_black_blocks(arena_t *arena) { -#if CHECKED - assert(arena != NULL); -#endif - size_t result = 0; - for (size_t cell = QCGC_ARENA_FIRST_CELL_INDEX; - cell < QCGC_ARENA_CELLS_COUNT; - cell++) { - switch (qcgc_arena_get_blocktype((void *) &arena->cells[cell])) { - case BLOCK_WHITE: // Fall through - case BLOCK_FREE: - case BLOCK_EXTENT: - break; - - case BLOCK_BLACK: - result++; - break; - } - } - return result; -} diff --git a/rpython/translator/c/src/qcgc/arena.h b/rpython/translator/c/src/qcgc/arena.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/arena.h +++ /dev/null @@ -1,197 +0,0 @@ -/** - * @file arena.h - */ - -#pragma once - -#include "config.h" - -#include <stdbool.h> -#include <stdint.h> -#include <sys/types.h> - -#include "gray_stack.h" - -#define QCGC_ARENA_SIZE (1<<QCGC_ARENA_SIZE_EXP) - -#define QCGC_ARENA_BITMAP_SIZE (1<<(QCGC_ARENA_SIZE_EXP - 7)) // 1 / 128 -#define QCGC_ARENA_CELLS_COUNT (1<<(QCGC_ARENA_SIZE_EXP - 4)) - -#define QCGC_ARENA_FIRST_CELL_INDEX (1<<(QCGC_ARENA_SIZE_EXP - 10)) - -/** - * @typedef cell_t - * The smallest unit of memory that can be addressed and allocated in arenas. - */ -typedef uint8_t cell_t[16]; - -/** - * @typedef arena_t - * Arena object - */ -typedef union { - struct { - union { - gray_stack_t *gray_stack; - uint8_t block_bitmap[QCGC_ARENA_BITMAP_SIZE]; - }; - uint8_t mark_bitmap[QCGC_ARENA_BITMAP_SIZE]; - }; - cell_t cells[QCGC_ARENA_CELLS_COUNT]; -} arena_t; - -/** - * @typedef blocktype_t - * Blocktypes: - * - BLOCK_EXTENT Extension of previous block - * - BLOCK_FREE Free block - * - BLOCK_WHITE Allocated block, marked white - * - BLOCK_BLACK Allocated block, marked black - */ -typedef enum blocktype { - BLOCK_EXTENT, - BLOCK_FREE, - BLOCK_WHITE, - BLOCK_BLACK, -} blocktype_t; - -/** - * Create a new arena. - * - * @return Pointer to new arena, NULL in case of errors - */ -arena_t *qcgc_arena_create(void); - -/** - * Destroys an arena (return to OS). - * - * @param arena The arena to destroy - */ -void qcgc_arena_destroy(arena_t *arena); - -/** - * Arena pointer for given cell. - * - * @param ptr Pointer to cell for which you want to know the corresponding - * arena - * @return The arena the pointer belongs to - */ -arena_t *qcgc_arena_addr(cell_t *ptr); - -/** - * Index of cell in arena. - * - * @param ptr Pointer to cell for which you want to know the cell index - * @return Index of the cell to which ptr points to - */ -size_t qcgc_arena_cell_index(cell_t *ptr); - -/** - * Get bitmap value for given bitmap and cell index. - * - * @param bitmap Bitmap - * @param index Index of cell - * @return true if bitmap entry is set, false otherwise - */ -bool qcgc_arena_get_bitmap_entry(uint8_t *bitmap, size_t index); - -/** - * Set bitmap value for given bitmap and cell index. - * - * @param bitmap Bitmap - * @param index Index of cell - * @param value true to set entry, false to reset entry - */ -void qcgc_arena_set_bitmap_entry(uint8_t *bitmap, size_t index, bool value); - -/** - * Get blocktype. - * - * @param ptr Pointer to cell for which you want to know the blocktype - * @return Blocktype - */ -blocktype_t qcgc_arena_get_blocktype(cell_t *ptr); - -/** - * Set blocktype. - * - * @param ptr Pointer to cell for which you want to set the blocktype - * @param type Blocktype that should be set - */ -void qcgc_arena_set_blocktype(cell_t *ptr, blocktype_t type); - -/** - * Mark ptr as allocated area with given size. - * - * @param ptr Pointer to first cell of area - * @param cells Size in cells - */ -void qcgc_arena_mark_allocated(cell_t *ptr, size_t cells); - -/** - * Mark cell ptr point to as free (no coalescing). - * - * @param ptr Pointer to cell that should be marked as free - */ -void qcgc_arena_mark_free(cell_t *ptr); - -/** - * Sweep given arena. - * - * @param arena Arena - * @return Whether arena is empty after sweeping - */ -bool qcgc_arena_sweep(arena_t *arena); - -/** - * Sweep given arena, but only reset black to white, no white to free - * - * @param arena Arena - * @return Whether arena is empty after sweeping, always false - */ -bool qcgc_arena_pseudo_sweep(arena_t *arena); - - -/******************************************************************************* - * Debug functions * - ******************************************************************************/ - -/** - * Check whether arena is empty. - * - * @param arena Arena - * @return true iff given arena is empty - */ -bool qcgc_arena_is_empty(arena_t *arena); - -/** - * Check whether arena is coalesced (no consecutive free blocks). - * - * @param arena Arena - * @return true iff given arena is coalesced - */ -bool qcgc_arena_is_coalesced(arena_t *arena); - -/** - * Count free blocks. - * - * @param arena Arena - * @return Number of free blocks - */ -size_t qcgc_arena_free_blocks(arena_t *arena); - -/** - * Count white blocks. - * - * @param arena Arena - * @return Number of white blocks - */ -size_t qcgc_arena_white_blocks(arena_t *arena); - -/** - * Count black blocks. - * - * @param arena Arena - * @return Number of black blocks - */ -size_t qcgc_arena_black_blocks(arena_t *arena); diff --git a/rpython/translator/c/src/qcgc/bag.c b/rpython/translator/c/src/qcgc/bag.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/bag.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "bag.h" - -#include <assert.h> - -DEFINE_BAG(arena_bag, arena_t *); -DEFINE_BAG(linear_free_list, cell_t *); -DEFINE_BAG(exp_free_list, struct exp_free_list_item_s); -DEFINE_BAG(hbbucket, struct hbtable_entry_s); -DEFINE_BAG(weakref_bag, struct weakref_bag_item_s); diff --git a/rpython/translator/c/src/qcgc/bag.h b/rpython/translator/c/src/qcgc/bag.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/bag.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "config.h" - -#include <stddef.h> -#include <stdlib.h> - -#include "arena.h" - -#define DECLARE_BAG(name, type) \ -typedef struct name##_s { \ - size_t size; \ - size_t count; \ - type items[]; \ -} name##_t; \ - \ -__attribute__ ((warn_unused_result)) \ -name##_t *qcgc_##name##_create(size_t size); \ - \ -__attribute__ ((warn_unused_result)) \ -name##_t *qcgc_##name##_add(name##_t *self, type item); \ - \ -__attribute__ ((warn_unused_result)) \ -name##_t *qcgc_##name##_remove_index(name##_t *self, size_t index); - -#define DEFINE_BAG(name, type) \ - \ -QCGC_STATIC size_t name##_size(size_t size); \ - \ -__attribute__ ((warn_unused_result)) \ -QCGC_STATIC name##_t *name##_grow(name##_t *self); \ - \ -__attribute__ ((warn_unused_result)) \ -QCGC_STATIC name##_t *name##_shrink(name##_t *self); \ - \ -name##_t *qcgc_##name##_create(size_t size) { \ - name##_t *result = (name##_t *) malloc(name##_size(size)); \ - result->size = size; \ - result->count = 0; \ - return result; \ -} \ - \ -name##_t *qcgc_##name##_add(name##_t *self, type item) { \ - if (self->count >= self->size) { \ - self = name##_grow(self); \ - } \ - self->items[self->count++] = item; \ - return self; \ -} \ - \ -name##_t *qcgc_##name##_remove_index(name##_t *self, size_t index) { \ - if (index + 1 < self->count) { \ - self->items[index] = self->items[self->count - 1]; \ - } \ - self->count--; \ - \ - if (self->count < self->size / 4) { \ - self = name##_shrink(self); \ - } \ - return self; \ -} \ - \ -QCGC_STATIC name##_t *name##_grow(name##_t *self) { \ - name##_t *new_self = (name##_t *) realloc(self, \ - name##_size(self->size * 2)); \ - assert(new_self != NULL); \ - self = new_self; \ - self->size *= 2; \ - return self; \ -} \ - \ -QCGC_STATIC name##_t *name##_shrink(name##_t *self) { \ - name##_t *new_self = (name##_t *) realloc(self, \ - name##_size(self->size / 2)); \ - assert(new_self != NULL); \ - self = new_self; \ - self->size /= 2; \ - return self; \ -} \ - \ -QCGC_STATIC size_t name##_size(size_t size) { \ - return sizeof(name##_t) + size * sizeof(type); \ -} - -struct exp_free_list_item_s { - cell_t *ptr; - size_t size; -}; - -struct hbtable_entry_s { - object_t *object; - bool mark_flag; -}; - -struct weakref_bag_item_s { - object_t *weakrefobj; - object_t **target; -}; - -DECLARE_BAG(arena_bag, arena_t *); -DECLARE_BAG(linear_free_list, cell_t *); -DECLARE_BAG(exp_free_list, struct exp_free_list_item_s); -DECLARE_BAG(hbbucket, struct hbtable_entry_s); -DECLARE_BAG(weakref_bag, struct weakref_bag_item_s); diff --git a/rpython/translator/c/src/qcgc/config.h b/rpython/translator/c/src/qcgc/config.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/config.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#define CHECKED 0 // Enable runtime sanity checks -#define DEBUG_ZERO_ON_SWEEP 0 // Zero memory on sweep (debug only) - -#define QCGC_INIT_ZERO 1 // Init new objects with zero bytes - -/** - * Event logger - */ -#define EVENT_LOG 1 // Enable event log -#define LOGFILE "./qcgc_events.log" // Default logfile -#define LOG_ALLOCATION 0 // Enable allocation log (warning: - // significant performance impact) - -#define QCGC_SHADOWSTACK_SIZE 163840 // Total shadowstack size -#define QCGC_ARENA_BAG_INIT_SIZE 16 // Initial size of the arena bag -#define QCGC_ARENA_SIZE_EXP 20 // Between 16 (64kB) and 20 (1MB) -#define QCGC_LARGE_ALLOC_THRESHOLD_EXP 14 // Less than QCGC_ARENA_SIZE_EXP -#define QCGC_MARK_LIST_SEGMENT_SIZE 64 // TODO: Tune for performance -#define QCGC_GRAY_STACK_INIT_SIZE 128 // TODO: Tune for performance -#define QCGC_INC_MARK_MIN 64 // TODO: Tune for performance - -/** - * Fit allocator - */ -#define QCGC_LARGE_FREE_LIST_FIRST_EXP 5 // First exponent of large free list -#define QCGC_LARGE_FREE_LIST_INIT_SIZE 4 // Initial size for large free lists -#define QCGC_SMALL_FREE_LIST_INIT_SIZE 16 // Initial size for small free lists - -/** - * Auto Mark/Collect - */ -#define QCGC_MAJOR_COLLECTION_THRESHOLD (5 * (1<<QCGC_ARENA_SIZE_EXP)) -#define QCGC_INCMARK_THRESHOLD (1<<QCGC_ARENA_SIZE_EXP) - -/** - * DO NOT MODIFY BELOW HERE - */ - -#if QCGC_LARGE_ALLOC_THRESHOLD_EXP >= QCGC_ARENA_SIZE_EXP -#error "Inconsistent configuration. Huge block threshold must be smaller " \ - "than the arena size." -#endif - -#ifdef TESTING -#define QCGC_STATIC -#else -#define QCGC_STATIC static -#endif - -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define UNUSED(x) (void)(x) diff --git a/rpython/translator/c/src/qcgc/event_logger.c b/rpython/translator/c/src/qcgc/event_logger.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/event_logger.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "event_logger.h" - -#include <assert.h> -#include <time.h> -#include <stdio.h> - -#if EVENT_LOG -static struct { - FILE *logfile; -} event_logger_state; - -#endif - -void qcgc_event_logger_initialize(void) { -#if EVENT_LOG - event_logger_state.logfile = fopen(LOGFILE, "w"); - qcgc_event_logger_log(EVENT_LOG_START, 0, NULL); - - if (event_logger_state.logfile == NULL) { - fprintf(stderr, "%s\n", "Failed to create logfile."); - } -#endif -} - -void qcgc_event_logger_destroy(void) { -#if EVENT_LOG - qcgc_event_logger_log(EVENT_LOG_STOP, 0, NULL); - - if (event_logger_state.logfile != NULL) { - fflush(event_logger_state.logfile); - fclose(event_logger_state.logfile); - event_logger_state.logfile = NULL; - } -#endif -} - -void qcgc_event_logger_log(enum event_e event, uint32_t additional_data_size, - uint8_t *additional_data) { -#if EVENT_LOG -#if CHECKED - assert((additional_data_size == 0) == (additional_data == NULL)); -#endif // CHECKED - struct { - uint32_t sec; - uint32_t nsec; - uint8_t event_id; - uint32_t additional_data_size; - } __attribute__ ((packed)) log_entry; - - if (event_logger_state.logfile != NULL) { - struct timespec t; - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); - - log_entry.sec = (uint32_t) t.tv_sec; - log_entry.nsec = (uint32_t) t.tv_nsec; - log_entry.event_id = (uint8_t) event; - log_entry.additional_data_size = additional_data_size; - - // The size and nmemb fields are flipped intentionally - int result = 0; - result = fwrite(&log_entry, sizeof(log_entry), 1, - event_logger_state.logfile); - if (result != 1) { - fprintf(stderr, "%s\n", "Failed to write log entry."); - event_logger_state.logfile = NULL; - return; - } - if (additional_data_size > 0) { - result = fwrite(additional_data, additional_data_size, 1, - event_logger_state.logfile); - - if (result != 1) { - fprintf(stderr, "%s\n", "Failed to write additional data."); - event_logger_state.logfile = NULL; - return; - } - } - } - -#endif // EVENT_LOG -} diff --git a/rpython/translator/c/src/qcgc/event_logger.h b/rpython/translator/c/src/qcgc/event_logger.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/event_logger.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "config.h" - -#include <stddef.h> -#include <stdint.h> - -/** - * All events - */ -enum event_e { - EVENT_LOG_START, // = 0 - EVENT_LOG_STOP, - - EVENT_SWEEP_START, - EVENT_SWEEP_DONE, - - EVENT_ALLOCATE_START, - EVENT_ALLOCATE_DONE, // = 5 - - EVENT_NEW_ARENA, - - EVENT_MARK_START, - EVENT_MARK_DONE, -}; - -/** - * Initialize logger - */ -void qcgc_event_logger_initialize(void); - -/** - * Destroy logger - */ -void qcgc_event_logger_destroy(void); - -/** - * Log event - */ -void qcgc_event_logger_log(enum event_e event, uint32_t additional_data_size, - uint8_t *additional_data); diff --git a/rpython/translator/c/src/qcgc/gc_state.h b/rpython/translator/c/src/qcgc/gc_state.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/gc_state.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include <stddef.h> - -#include "bag.h" -#include "gray_stack.h" -#include "shadow_stack.h" - -/** - * @typedef gc_state_t - * Garbage collection states. - * - GC_PAUSE No gc in progress - * - GC_MARK Currently marking - * - GC_COLLECT Currently collecting - */ -typedef enum gc_phase { - GC_PAUSE, - GC_MARK, - GC_COLLECT, -} gc_phase_t; - -/** - * @var qcgc_state - * - * Global state of the garbage collector - */ -struct qcgc_state { - object_t **shadow_stack; - object_t **shadow_stack_base; - shadow_stack_t *prebuilt_objects; - weakref_bag_t *weakrefs; - gray_stack_t *gp_gray_stack; - size_t gray_stack_size; - gc_phase_t phase; - size_t bytes_since_collection; - size_t bytes_since_incmark; - size_t free_cells; // Overall amount of free cells without huge - // blocks and free areans. Valid right after sweep - size_t largest_free_block; // Size of the largest free block. - // (Free arenas don't count as free blocks) - // Valid right after sweep -} qcgc_state; diff --git a/rpython/translator/c/src/qcgc/gray_stack.c b/rpython/translator/c/src/qcgc/gray_stack.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/gray_stack.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "gray_stack.h" - -#include <assert.h> -#include <stdlib.h> - -#include "gc_state.h" - -QCGC_STATIC size_t gray_stack_size(size_t size); -QCGC_STATIC gray_stack_t *gray_stack_grow(gray_stack_t *stack); -QCGC_STATIC gray_stack_t *gray_stack_shrink(gray_stack_t *stack); - -gray_stack_t *qcgc_gray_stack_create(size_t size) { - gray_stack_t *result = (gray_stack_t *) malloc(gray_stack_size(size)); - result->size = size; - result->index = 0; - return result; -} - -gray_stack_t *qcgc_gray_stack_push(gray_stack_t *stack, object_t *item) { - if (stack->size == stack->index) { - stack = gray_stack_grow(stack); - } - stack->items[stack->index] = item; - stack->index++; - qcgc_state.gray_stack_size++; - return stack; -} - -object_t *qcgc_gray_stack_top(gray_stack_t *stack) { -#if CHECKED - assert(stack->index != 0); -#endif - return stack->items[stack->index - 1]; -} - -gray_stack_t *qcgc_gray_stack_pop(gray_stack_t *stack) { - // TODO: Add lower bound for size (config.h) - if (stack->index < stack->size / 4) { - stack = gray_stack_shrink(stack); - } - stack->index--; - qcgc_state.gray_stack_size--; - return stack; -} - -QCGC_STATIC size_t gray_stack_size(size_t size) { - return (sizeof(gray_stack_t) + size * sizeof(object_t *)); -} - -QCGC_STATIC gray_stack_t *gray_stack_grow(gray_stack_t *stack) { - stack = (gray_stack_t *) realloc(stack, gray_stack_size(stack->size * 2)); - stack->size *= 2; - return stack; -} - -QCGC_STATIC gray_stack_t *gray_stack_shrink(gray_stack_t *stack) { - stack = (gray_stack_t *) realloc(stack, gray_stack_size(stack->size / 2)); - stack->size /= 2; - return stack; -} diff --git a/rpython/translator/c/src/qcgc/gray_stack.h b/rpython/translator/c/src/qcgc/gray_stack.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/gray_stack.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "config.h" - -#include <stddef.h> - -#include "object.h" - -typedef struct gray_stack_s { - size_t index; - size_t size; - object_t *items[]; -} gray_stack_t; - -__attribute__ ((warn_unused_result)) -gray_stack_t *qcgc_gray_stack_create(size_t size); - -__attribute__ ((warn_unused_result)) -gray_stack_t *qcgc_gray_stack_push(gray_stack_t *stack, object_t *item); - -object_t *qcgc_gray_stack_top(gray_stack_t *stack); - -__attribute__ ((warn_unused_result)) -gray_stack_t *qcgc_gray_stack_pop(gray_stack_t *stack); diff --git a/rpython/translator/c/src/qcgc/hugeblocktable.c b/rpython/translator/c/src/qcgc/hugeblocktable.c deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/hugeblocktable.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "hugeblocktable.h" - -#include <assert.h> - -#include "gc_state.h" - -QCGC_STATIC size_t bucket(object_t *object); - -void qcgc_hbtable_initialize(void) { - qcgc_hbtable.mark_flag_ref = false; - for (size_t i = 0; i < QCGC_HBTABLE_BUCKETS; i++) { - qcgc_hbtable.bucket[i] = qcgc_hbbucket_create(4); - } -} - -void qcgc_hbtable_destroy(void) { - for (size_t i = 0; i < QCGC_HBTABLE_BUCKETS; i++) { - free(qcgc_hbtable.bucket[i]); - } -} - -void qcgc_hbtable_insert(object_t *object) { - size_t i = bucket(object); - qcgc_hbtable.bucket[i] = qcgc_hbbucket_add(qcgc_hbtable.bucket[i], - (struct hbtable_entry_s) { - .object = object, - .mark_flag = !qcgc_hbtable.mark_flag_ref}); -} - -bool qcgc_hbtable_mark(object_t *object) { - hbbucket_t *b = qcgc_hbtable.bucket[bucket(object)]; - size_t count = b->count; - for (size_t i = 0; i < count; i++) { - if (b->items[i].object == object) { - if (b->items[i].mark_flag != qcgc_hbtable.mark_flag_ref) { - b->items[i].mark_flag = qcgc_hbtable.mark_flag_ref; - return true; - } - return false; - } - } -#if CHECKED - assert(false); -#endif - return false; -} - -bool qcgc_hbtable_has(object_t *object) { - hbbucket_t *b = qcgc_hbtable.bucket[bucket(object)]; - size_t count = b->count; - for (size_t i = 0; i < count; i++) { - if (b->items[i].object == object) { - return true; - } - } - return false; -} - -bool qcgc_hbtable_is_marked(object_t *object) { - hbbucket_t *b = qcgc_hbtable.bucket[bucket(object)]; - size_t count = b->count; - for (size_t i = 0; i < count; i++) { - if (b->items[i].object == object) { - return b->items[i].mark_flag == qcgc_hbtable.mark_flag_ref; - } - } - return false; -} - -void qcgc_hbtable_sweep(void) { - for (size_t i = 0; i < QCGC_HBTABLE_BUCKETS; i++) { - hbbucket_t *b = qcgc_hbtable.bucket[i]; - size_t j = 0; - while(j < b->count) { - if (b->items[j].mark_flag != qcgc_hbtable.mark_flag_ref) { - // White object - free(b->items[j].object); - b = qcgc_hbbucket_remove_index(b, j); - } else { - // Black object - j++; - } - } - qcgc_hbtable.bucket[i] = b; - } - qcgc_hbtable.mark_flag_ref = !qcgc_hbtable.mark_flag_ref; -} - -QCGC_STATIC size_t bucket(object_t *object) { - return ((uintptr_t) object >> (QCGC_ARENA_SIZE_EXP)) % QCGC_HBTABLE_BUCKETS; -} diff --git a/rpython/translator/c/src/qcgc/hugeblocktable.h b/rpython/translator/c/src/qcgc/hugeblocktable.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/hugeblocktable.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "config.h" - -#include <stdbool.h> - -#include "bag.h" -#include "object.h" -#include "gray_stack.h" - -// Choosing a prime number, hoping for good results -#define QCGC_HBTABLE_BUCKETS 61 - -struct hbtable_s { - bool mark_flag_ref; - hbbucket_t *bucket[QCGC_HBTABLE_BUCKETS]; -} qcgc_hbtable; - -void qcgc_hbtable_initialize(void); -void qcgc_hbtable_destroy(void); -void qcgc_hbtable_insert(object_t *object); -bool qcgc_hbtable_mark(object_t *object); -bool qcgc_hbtable_has(object_t *object); -bool qcgc_hbtable_is_marked(object_t *object); -void qcgc_hbtable_sweep(void); diff --git a/rpython/translator/c/src/qcgc/object.h b/rpython/translator/c/src/qcgc/object.h deleted file mode 100644 --- a/rpython/translator/c/src/qcgc/object.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - - -#include "config.h" -#include <stdint.h> - -/** - * The lower half of flags is reserved for the library, the upper half for - * clients - */ -#define QCGC_GRAY_FLAG (1<<0) -#define QCGC_PREBUILT_OBJECT (1<<1) -#define QCGC_PREBUILT_REGISTERED (1<<2) - -typedef struct object_s { - uint32_t flags; -} object_t; diff --git a/rpython/translator/c/src/qcgc/qcgc.c b/rpython/translator/c/src/qcgc/qcgc.c --- a/rpython/translator/c/src/qcgc/qcgc.c +++ b/rpython/translator/c/src/qcgc/qcgc.c @@ -1,507 +1,26 @@ -#include "qcgc.h" +#include "src/config.h" +#include "src/allocator.h" +#include "src/arena.h" +#include "src/bag.h" +#include "src/collector.h" +#include "src/core.h" +#include "src/event_logger.h" +#include "src/gc_state.h" +#include "src/gray_stack.h" +#include "src/hugeblocktable.h" +#include "src/object.h" +#include "src/shadow_stack.h" +#include "src/signal_handler.h" +#include "src/weakref.h" -#include <assert.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/mman.h> - -#include "allocator.h" -#include "event_logger.h" -#include "hugeblocktable.h" -#include "signal_handler.h" - -#define env_or_fallback(var, env_name, fallback) while(0) { \ - char *env_val = getenv(env_name); \ - if (env_val != NULL) { \ - if (1 != sscanf(env_val, "%zu", &var)) { \ - var = fallback; \ - } \ - } \ -} - -void qcgc_mark(bool incremental); -void qcgc_pop_object(object_t *object); -void qcgc_push_object(object_t *object); -void qcgc_sweep(void); - -static size_t major_collection_threshold = QCGC_MAJOR_COLLECTION_THRESHOLD; -static size_t incmark_threshold = QCGC_INCMARK_THRESHOLD; - -QCGC_STATIC void update_weakrefs(void); -QCGC_STATIC void initialize_shadowstack(void); -QCGC_STATIC void destroy_shadowstack(void); - -void qcgc_initialize(void) { - initialize_shadowstack(); - qcgc_state.prebuilt_objects = qcgc_shadow_stack_create(16); // XXX - qcgc_state.weakrefs = qcgc_weakref_bag_create(16); // XXX - qcgc_state.gp_gray_stack = qcgc_gray_stack_create(16); // XXX - qcgc_state.gray_stack_size = 0; - qcgc_state.phase = GC_PAUSE; - qcgc_state.bytes_since_collection = 0; - qcgc_state.bytes_since_incmark = 0; - qcgc_state.free_cells = 0; - qcgc_state.largest_free_block = 0; - qcgc_allocator_initialize(); - qcgc_hbtable_initialize(); - qcgc_event_logger_initialize(); - - env_or_fallback(major_collection_threshold, "QCGC_MAJOR_COLLECTION", - QCGC_MAJOR_COLLECTION_THRESHOLD); - env_or_fallback(incmark_threshold, "QCGC_INCMARK", QCGC_INCMARK_THRESHOLD); - - setup_signal_handler(); -} - -void qcgc_destroy(void) { - qcgc_event_logger_destroy(); - qcgc_hbtable_destroy(); - qcgc_allocator_destroy(); - destroy_shadowstack(); - free(qcgc_state.prebuilt_objects); - free(qcgc_state.weakrefs); - free(qcgc_state.gp_gray_stack); -} - -/** - * Shadow stack - */ -void qcgc_shadowstack_push(object_t *object) { - *qcgc_state.shadow_stack = object; - qcgc_state.shadow_stack++; -} - -object_t *qcgc_shadowstack_pop(void) { - qcgc_state.shadow_stack--; - return *qcgc_state.shadow_stack; -} - -/******************************************************************************* - * Write barrier * - ******************************************************************************/ -void qcgc_write(object_t *object) { -#if CHECKED - assert(object != NULL); -#endif - if ((object->flags & QCGC_GRAY_FLAG) != 0) { - // Already gray, skip - return; - } - object->flags |= QCGC_GRAY_FLAG; - - // Register prebuilt object if necessary - if (((object->flags & QCGC_PREBUILT_OBJECT) != 0) && - ((object->flags & QCGC_PREBUILT_REGISTERED) == 0)) { - object->flags |= QCGC_PREBUILT_REGISTERED; - qcgc_state.prebuilt_objects = qcgc_shadow_stack_push( - qcgc_state.prebuilt_objects, object); - } - - if (qcgc_state.phase == GC_PAUSE) { - return; // We are done - } - - // Triggered barrier, we must not collect now - qcgc_state.phase = GC_MARK; - - // Test reachability of object and push if neccessary - if ((object->flags & QCGC_PREBUILT_OBJECT) != 0) { - // NOTE: No mark test here, as prebuilt objects are always reachable - // Push prebuilt object to general purpose gray stack - qcgc_state.gp_gray_stack = qcgc_gray_stack_push( - qcgc_state.gp_gray_stack, object); - } else if ((object_t *) qcgc_arena_addr((cell_t *) object) == object) { - if (qcgc_hbtable_is_marked(object)) { - // Push huge block to general purpose gray stack - qcgc_state.gp_gray_stack = qcgc_gray_stack_push( - qcgc_state.gp_gray_stack, object); - } - } else { - if (qcgc_arena_get_blocktype((cell_t *) object) == BLOCK_BLACK) { - // This was black before, push it to gray stack again - arena_t *arena = qcgc_arena_addr((cell_t *) object); - arena->gray_stack = qcgc_gray_stack_push( - arena->gray_stack, object); - } - } -} - -/******************************************************************************* - * Allocation * - ******************************************************************************/ - -object_t *qcgc_allocate(size_t size) { -#if LOG_ALLOCATION - qcgc_event_logger_log(EVENT_ALLOCATE_START, sizeof(size_t), - (uint8_t *) &size); -#endif - object_t *result; - - if (qcgc_state.bytes_since_collection > major_collection_threshold) { - qcgc_collect(); - } - if (qcgc_state.bytes_since_incmark > incmark_threshold) { - qcgc_mark(true); - } - - if (size <= 1<<QCGC_LARGE_ALLOC_THRESHOLD_EXP) { - // Use bump / fit allocator - if (qcgc_allocator_state.use_bump_allocator) { - result = qcgc_bump_allocate(size); - } else { - result = qcgc_fit_allocate(size); - - // Fallback to bump allocator - if (result == NULL) { - result = qcgc_bump_allocate(size); - } - } - } else { - // Use huge block allocator - result = qcgc_large_allocate(size); - } - - // XXX: Should we use cells instead of bytes? - qcgc_state.bytes_since_collection += size; - qcgc_state.bytes_since_incmark += size; - - -#if LOG_ALLOCATION - qcgc_event_logger_log(EVENT_ALLOCATE_DONE, sizeof(object_t *), - (uint8_t *) &result); -#endif - return result; -} - -/******************************************************************************* - * Collection * - ******************************************************************************/ - -mark_color_t qcgc_get_mark_color(object_t *object) { -#if CHECKED - assert(object != NULL); -#endif - blocktype_t blocktype = qcgc_arena_get_blocktype((cell_t *) object); - bool gray = (object->flags & QCGC_GRAY_FLAG) == QCGC_GRAY_FLAG; - if (blocktype == BLOCK_WHITE) { - if (gray) { - return MARK_COLOR_LIGHT_GRAY; - } else { - return MARK_COLOR_WHITE; - } - } else if(blocktype == BLOCK_BLACK) { - if (gray) { - return MARK_COLOR_DARK_GRAY; _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit