[pypy-commit] pypy quad-color-gc: Update qcgc codebase
ntruessel
pypy.commits at gmail.com
Mon Sep 12 05:09:32 EDT 2016
Author: Nicolas Truessel <ntruessel at njsm.de>
Branch: quad-color-gc
Changeset: r87021:636d1082681c
Date: 2016-09-12 11:08 +0200
http://bitbucket.org/pypy/pypy/changeset/636d1082681c/
Log: Update qcgc codebase
diff --git a/rpython/translator/c/src/qcgc/allocator.c b/rpython/translator/c/src/qcgc/allocator.c
--- a/rpython/translator/c/src/qcgc/allocator.c
+++ b/rpython/translator/c/src/qcgc/allocator.c
@@ -215,7 +215,7 @@
object_t *qcgc_fit_allocate(size_t bytes) {
#if CHECKED
- free_list_consistency_check();
+ //free_list_consistency_check();
#endif
size_t cells = bytes_to_cells(bytes);
cell_t *mem;
diff --git a/rpython/translator/c/src/qcgc/config.h b/rpython/translator/c/src/qcgc/config.h
--- a/rpython/translator/c/src/qcgc/config.h
+++ b/rpython/translator/c/src/qcgc/config.h
@@ -13,8 +13,7 @@
#define LOG_ALLOCATION 0 // Enable allocation log (warning:
// significant performance impact)
-#define QCGC_SHADOWSTACK_SIZE 128 // Number of initial entries for
- // shadow stack
+#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
@@ -52,3 +51,4 @@
#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/gc_state.h b/rpython/translator/c/src/qcgc/gc_state.h
--- a/rpython/translator/c/src/qcgc/gc_state.h
+++ b/rpython/translator/c/src/qcgc/gc_state.h
@@ -25,7 +25,8 @@
* Global state of the garbage collector
*/
struct qcgc_state {
- shadow_stack_t *shadow_stack;
+ object_t **shadow_stack;
+ object_t **shadow_stack_base;
shadow_stack_t *prebuilt_objects;
weakref_bag_t *weakrefs;
gray_stack_t *gp_gray_stack;
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
@@ -5,10 +5,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <sys/mman.h>
#include "allocator.h"
+#include "event_logger.h"
#include "hugeblocktable.h"
-#include "event_logger.h"
+#include "signal_handler.h"
#define env_or_fallback(var, env_name, fallback) while(0) { \
char *env_val = getenv(env_name); \
@@ -28,9 +30,11 @@
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) {
- qcgc_state.shadow_stack = qcgc_shadow_stack_create(QCGC_SHADOWSTACK_SIZE);
+ 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
@@ -47,13 +51,15 @@
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();
- free(qcgc_state.shadow_stack);
+ destroy_shadowstack();
free(qcgc_state.prebuilt_objects);
free(qcgc_state.weakrefs);
free(qcgc_state.gp_gray_stack);
@@ -67,14 +73,14 @@
qcgc_state.phase = GC_MARK;
qcgc_push_object(object);
}
- qcgc_state.shadow_stack =
- qcgc_shadow_stack_push(qcgc_state.shadow_stack, object);
+
+ *qcgc_state.shadow_stack = object;
+ qcgc_state.shadow_stack++;
}
object_t *qcgc_shadowstack_pop(void) {
- object_t *result = qcgc_shadow_stack_top(qcgc_state.shadow_stack);
- qcgc_state.shadow_stack = qcgc_shadow_stack_pop(qcgc_state.shadow_stack);
- return result;
+ qcgc_state.shadow_stack--;
+ return *qcgc_state.shadow_stack;
}
/*******************************************************************************
@@ -225,8 +231,10 @@
// If we do this for the first time, push all roots.
// All further changes to the roots (new additions) will be added
// by qcgc_shadowstack_push
- for (size_t i = 0; i < qcgc_state.shadow_stack->count; i++) {
- qcgc_push_object(qcgc_state.shadow_stack->items[i]);
+ for (object_t **it = qcgc_state.shadow_stack_base;
+ it < qcgc_state.shadow_stack;
+ it++) {
+ qcgc_push_object(*it);
}
// If we do this for the first time, push all prebuilt objects.
@@ -483,3 +491,28 @@
}
}
}
+
+QCGC_STATIC void *trap_page_addr(object_t **shadow_stack) {
+ object_t **shadow_stack_end = shadow_stack + QCGC_SHADOWSTACK_SIZE;
+ char *in_trap_page = (((char *)shadow_stack_end) + 4095);
+ void *rounded_trap_page = (void *)(((uintptr_t)in_trap_page) & (~4095));
+ return rounded_trap_page;
+}
+
+QCGC_STATIC void initialize_shadowstack(void) {
+ size_t stack_size = QCGC_SHADOWSTACK_SIZE * sizeof(object_t *);
+ // allocate stack + size for alignement + trap page
+ object_t **stack = (object_t **) malloc(stack_size + 8192);
+ assert(stack != NULL);
+ mprotect(trap_page_addr(stack), 4096, PROT_NONE);
+
+ qcgc_state.shadow_stack = stack;
+ qcgc_state.shadow_stack_base = stack;
+}
+
+QCGC_STATIC void destroy_shadowstack(void) {
+ mprotect(trap_page_addr(qcgc_state.shadow_stack_base), 4096, PROT_READ |
+ PROT_WRITE);
+
+ free(qcgc_state.shadow_stack_base);
+}
diff --git a/rpython/translator/c/src/qcgc/signal_handler.c b/rpython/translator/c/src/qcgc/signal_handler.c
new file mode 100644
--- /dev/null
+++ b/rpython/translator/c/src/qcgc/signal_handler.c
@@ -0,0 +1,61 @@
+#include "signal_handler.h"
+
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "arena.h"
+#include "allocator.h"
+#include "gc_state.h"
+
+QCGC_STATIC void handle_error(int signo, siginfo_t *siginfo, void *context);
+QCGC_STATIC bool is_stack_overflow(void *addr);
+QCGC_STATIC bool is_in_arena(void *addr);
+
+void setup_signal_handler(void) {
+ struct sigaction sa;
+
+ sa.sa_handler = NULL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sa.sa_sigaction = &handle_error;
+
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ perror("sigaction");
+ abort();
+ }
+}
+
+QCGC_STATIC void handle_error(int signo, siginfo_t *siginfo, void *context) {
+ UNUSED(signo);
+ UNUSED(context);
+
+ if (is_stack_overflow(siginfo->si_addr)) {
+ fprintf(stderr, "Stack overflow: Too many root objects\n");
+ } else if (is_in_arena(siginfo->si_addr)) {
+ fprintf(stderr, "Internal segmentation fault: accessing %p\n",
+ siginfo->si_addr);
+ } else {
+ fprintf(stderr, "External segmentation fault: accessing %p\n",
+ siginfo->si_addr);
+ }
+ exit(EXIT_FAILURE);
+}
+
+QCGC_STATIC bool is_stack_overflow(void *addr) {
+ void *shadow_stack_end = (void *)(qcgc_state.shadow_stack_base +
+ QCGC_SHADOWSTACK_SIZE);
+ return (addr >= shadow_stack_end && addr < shadow_stack_end + 8192);
+}
+
+QCGC_STATIC bool is_in_arena(void *addr) {
+ arena_t *arena = qcgc_arena_addr((cell_t *) addr);
+ size_t count = qcgc_allocator_state.arenas->count;
+ for (size_t i = 0; i < count; i++) {
+ if (arena == qcgc_allocator_state.arenas->items[i]) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/rpython/translator/c/src/qcgc/signal_handler.h b/rpython/translator/c/src/qcgc/signal_handler.h
new file mode 100644
--- /dev/null
+++ b/rpython/translator/c/src/qcgc/signal_handler.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "config.h"
+
+void setup_signal_handler(void);
More information about the pypy-commit
mailing list