[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