[pypy-commit] pypy quad-color-gc: Update qcgc codebase again
ntruessel
pypy.commits at gmail.com
Tue Sep 13 03:31:23 EDT 2016
Author: Nicolas Truessel <ntruessel at 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;
More information about the pypy-commit
mailing list