Author: Nicolas Truessel <[email protected]>
Branch: quad-color-gc
Changeset: r87126:86dfb2ca9890
Date: 2016-09-14 08:11 +0200
http://bitbucket.org/pypy/pypy/changeset/86dfb2ca9890/
Log: QCGC update (performance)
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
@@ -25,6 +25,8 @@
QCGC_STATIC QCGC_INLINE void initialize_shadowstack(void);
QCGC_STATIC QCGC_INLINE void destroy_shadowstack(void);
+QCGC_STATIC object_t *bump_allocate(size_t size);
+
void qcgc_initialize(void) {
initialize_shadowstack();
qcgc_state.prebuilt_objects = qcgc_shadow_stack_create(16); // XXX
@@ -79,14 +81,14 @@
if (LIKELY(size <= 1<<QCGC_LARGE_ALLOC_THRESHOLD_EXP)) {
// Use bump / fit allocator
//if (qcgc_allocator_state.use_bump_allocator) {
- if (true) {
- result = qcgc_bump_allocate(size);
+ if (false) {
+ result = bump_allocate(size);
} else {
result = qcgc_fit_allocate(size);
// Fallback to bump allocator
if (result == NULL) {
- result = qcgc_bump_allocate(size);
+ result = bump_allocate(size);
}
}
} else {
@@ -140,11 +142,13 @@
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.gray_stack_size++;
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.gray_stack_size++;
qcgc_state.gp_gray_stack = qcgc_gray_stack_push(
qcgc_state.gp_gray_stack, object);
}
@@ -153,6 +157,7 @@
qcgc_arena_cell_index((cell_t *)
object)) == BLOCK_BLACK) {
// This was black before, push it to gray stack again
arena_t *arena = qcgc_arena_addr((cell_t *) object);
+ qcgc_state.gray_stack_size++;
arena->gray_stack = qcgc_gray_stack_push(
arena->gray_stack, object);
}
@@ -199,3 +204,11 @@
free(qcgc_shadowstack.base);
}
+
+QCGC_STATIC object_t *bump_allocate(size_t size) {
+ if (UNLIKELY(qcgc_allocator_state.bump_state.remaining_cells <
+ bytes_to_cells(size))) {
+ qcgc_bump_allocator_renew_block();
+ }
+ return qcgc_bump_allocate(size);
+}
diff --git a/rpython/translator/c/src/qcgc/src/allocator.c
b/rpython/translator/c/src/qcgc/src/allocator.c
--- a/rpython/translator/c/src/qcgc/src/allocator.c
+++ b/rpython/translator/c/src/qcgc/src/allocator.c
@@ -3,15 +3,10 @@
#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 QCGC_INLINE void bump_allocator_assign(cell_t *ptr, size_t cells);
-QCGC_STATIC QCGC_INLINE void bump_allocator_advance(size_t cells);
-QCGC_STATIC void bump_allocator_renew_block(void);
QCGC_STATIC QCGC_INLINE bool is_small(size_t cells);
QCGC_STATIC QCGC_INLINE size_t small_index(size_t cells);
@@ -71,20 +66,21 @@
}
void qcgc_fit_allocator_add(cell_t *ptr, size_t cells) {
- 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});
- }
+#if CHECKED
+ assert(cells > 0);
+#endif
+ 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});
}
}
@@ -92,42 +88,8 @@
* Bump Allocator
*
******************************************************************************/
-object_t *qcgc_bump_allocate(size_t bytes) {
+void qcgc_bump_allocator_renew_block(void) {
#if CHECKED
- assert(bytes <= 1<<QCGC_LARGE_ALLOC_THRESHOLD_EXP);
-#endif
- size_t cells = bytes_to_cells(bytes);
- if (UNLIKELY(cells > qcgc_allocator_state.bump_state.remaining_cells)) {
- if (LIKELY(qcgc_allocator_state.bump_state.remaining_cells >
0)) {
- qcgc_arena_set_blocktype(
-
qcgc_arena_addr(qcgc_allocator_state.bump_state.bump_ptr),
- qcgc_arena_cell_index(
-
qcgc_allocator_state.bump_state.bump_ptr),
- BLOCK_FREE);
- }
- bump_allocator_renew_block();
- }
- cell_t *mem = qcgc_allocator_state.bump_state.bump_ptr;
- bump_allocator_advance(cells);
-
- qcgc_arena_set_blocktype(qcgc_arena_addr(mem),
qcgc_arena_cell_index(mem),
- BLOCK_WHITE);
- /*
- if (qcgc_allocator_state.bump_state.remaining_cells > 0) {
-
qcgc_arena_set_blocktype(qcgc_allocator_state.bump_state.bump_ptr,
- BLOCK_FREE);
- }
- */
-
- 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) {
for (size_t i = 1; i <
qcgc_allocator_state.bump_state.remaining_cells;
i++) {
@@ -139,30 +101,16 @@
}
}
#endif
- return result;
-}
-
-QCGC_STATIC void bump_allocator_renew_block(void) {
-#if CHECKED
+ // Add remaining memory to fit allocator
if (qcgc_allocator_state.bump_state.remaining_cells > 0) {
- assert(qcgc_arena_get_blocktype(
- qcgc_arena_addr(
qcgc_allocator_state.bump_state.bump_ptr),
- qcgc_arena_cell_index(
-
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_arena_addr(
-
qcgc_allocator_state.bump_state.bump_ptr + i),
- qcgc_arena_cell_index(
-
qcgc_allocator_state.bump_state.bump_ptr + i))
- == BLOCK_EXTENT);
- }
+ qcgc_arena_set_blocktype(
+
qcgc_arena_addr(qcgc_allocator_state.bump_state.bump_ptr),
+ qcgc_arena_cell_index(
+
qcgc_allocator_state.bump_state.bump_ptr),
+ BLOCK_FREE);
+ qcgc_fit_allocator_add(qcgc_allocator_state.bump_state.bump_ptr,
+
qcgc_allocator_state.bump_state.remaining_cells);
}
-#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.
@@ -215,11 +163,6 @@
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();
@@ -365,7 +308,6 @@
qcgc_allocator_state.fit_state.large_free_list[index],
0);
- qcgc_arena_mark_allocated(item.ptr, cells);
qcgc_arena_set_blocktype(qcgc_arena_addr(item.ptr),
qcgc_arena_cell_index(item.ptr),
BLOCK_WHITE);
if (item.size - cells > 0) {
@@ -379,10 +321,6 @@
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;
}
diff --git a/rpython/translator/c/src/qcgc/src/allocator.h
b/rpython/translator/c/src/qcgc/src/allocator.h
--- a/rpython/translator/c/src/qcgc/src/allocator.h
+++ b/rpython/translator/c/src/qcgc/src/allocator.h
@@ -2,6 +2,8 @@
#include "../qcgc.h"
+#include <string.h>
+
#include "arena.h"
#include "bag.h"
@@ -69,15 +71,6 @@
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
@@ -99,3 +92,42 @@
* @param cells Size of memory region in cells
*/
void qcgc_fit_allocator_add(cell_t *ptr, size_t cells);
+
+QCGC_STATIC QCGC_INLINE size_t bytes_to_cells(size_t bytes) {
+ return (bytes + sizeof(cell_t) - 1) / sizeof(cell_t);
+}
+
+/**
+ * Find a new block for the bump allocator
+ */
+void qcgc_bump_allocator_renew_block(void);
+
+/**
+ * Allocate new memory region using bump allocator.
+ * Bump allocator must have enough space for desired bytes
+ * (client is responsible, use qcgc_bump_allocator_renew_block)
+ *
+ * @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
+ */
+QCGC_STATIC QCGC_INLINE object_t *qcgc_bump_allocate(size_t bytes) {
+ size_t cells = bytes_to_cells(bytes);
+
+ cell_t *mem = qcgc_allocator_state.bump_state.bump_ptr;
+
+ qcgc_arena_set_blocktype(qcgc_arena_addr(mem),
qcgc_arena_cell_index(mem),
+ BLOCK_WHITE);
+
+ qcgc_allocator_state.bump_state.bump_ptr += cells;
+ qcgc_allocator_state.bump_state.remaining_cells -= cells;
+
+ 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;
+}
diff --git a/rpython/translator/c/src/qcgc/src/collector.c
b/rpython/translator/c/src/qcgc/src/collector.c
--- a/rpython/translator/c/src/qcgc/src/collector.c
+++ b/rpython/translator/c/src/qcgc/src/collector.c
@@ -20,6 +20,7 @@
while (qcgc_state.gp_gray_stack->index > 0) {
object_t *top =
qcgc_gray_stack_top(qcgc_state.gp_gray_stack);
+ qcgc_state.gray_stack_size--;
qcgc_state.gp_gray_stack = qcgc_gray_stack_pop(
qcgc_state.gp_gray_stack);
qcgc_pop_object(top);
@@ -31,6 +32,7 @@
while (arena->gray_stack->index > 0) {
object_t *top =
qcgc_gray_stack_top(arena->gray_stack);
+ qcgc_state.gray_stack_size--;
arena->gray_stack =
qcgc_gray_stack_pop(arena->gray_stack);
qcgc_pop_object(top);
}
@@ -53,6 +55,7 @@
while (to_process > 0 && qcgc_state.gp_gray_stack->index > 0) {
object_t *top = qcgc_gray_stack_top(qcgc_state.gp_gray_stack);
+ qcgc_state.gray_stack_size--;
qcgc_state.gp_gray_stack = qcgc_gray_stack_pop(
qcgc_state.gp_gray_stack);
qcgc_pop_object(top);
@@ -66,6 +69,7 @@
while (to_process > 0 && arena->gray_stack->index > 0) {
object_t *top = qcgc_gray_stack_top(arena->gray_stack);
+ qcgc_state.gray_stack_size--;
arena->gray_stack =
qcgc_gray_stack_pop(arena->gray_stack);
qcgc_pop_object(top);
to_process--;
@@ -99,6 +103,7 @@
// because of the write barrier
size_t count = qcgc_state.prebuilt_objects->count;
for (size_t i = 0; i < count; i++) {
+ qcgc_state.gray_stack_size++;
qcgc_state.gp_gray_stack = qcgc_gray_stack_push(
qcgc_state.gp_gray_stack,
qcgc_state.prebuilt_objects->items[i]);
@@ -157,6 +162,7 @@
if (qcgc_hbtable_mark(object)) {
// Did mark it / was white before
object->flags |= QCGC_GRAY_FLAG;
+ qcgc_state.gray_stack_size++;
qcgc_state.gp_gray_stack = qcgc_gray_stack_push(
qcgc_state.gp_gray_stack,
object);
}
@@ -169,6 +175,7 @@
if (qcgc_arena_get_blocktype(arena, index) == BLOCK_WHITE) {
object->flags |= QCGC_GRAY_FLAG;
qcgc_arena_set_blocktype(arena, index, BLOCK_BLACK);
+ qcgc_state.gray_stack_size++;
arena->gray_stack =
qcgc_gray_stack_push(arena->gray_stack, object);
}
}
diff --git a/rpython/translator/c/src/qcgc/src/core.c
b/rpython/translator/c/src/qcgc/src/core.c
deleted file mode 100644
--- a/rpython/translator/c/src/qcgc/src/core.c
+++ /dev/null
@@ -1,184 +0,0 @@
-#include "core.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <sys/mman.h>
-
-#include "allocator.h"
-#include "collector.h"
-#include "event_logger.h"
-#include "gc_state.h"
-#include "hugeblocktable.h"
-#include "signal_handler.h"
-
-#define env_or_fallback(var, env_name, fallback) do { \
- char *env_val = getenv(env_name);
\
- if (env_val != NULL) {
\
- if (1 != sscanf(env_val, "%zu", &var)) {
\
- var = fallback;
\
- }
\
- } else {
\
- var = fallback;
\
- }
\
-} while(0)
-
-QCGC_STATIC QCGC_INLINE void _initialize_shadowstack(void);
-QCGC_STATIC QCGC_INLINE 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(qcgc_state.major_collection_threshold,
"QCGC_MAJOR_COLLECTION",
- QCGC_MAJOR_COLLECTION_THRESHOLD);
- env_or_fallback(qcgc_state.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);
-}
-
-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 >
- qcgc_state.major_collection_threshold) {
- qcgc_collect();
- }
- if (qcgc_state.bytes_since_incmark > qcgc_state.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;
-}
-
-void qcgc_collect(void) {
- qcgc_mark(false);
- qcgc_sweep();
- qcgc_state.bytes_since_collection = 0;
-}
-
-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);
- }
- }
-}
-
-/******************************************************************************/
-
-QCGC_STATIC QCGC_INLINE 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 QCGC_INLINE 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/src/core.h
b/rpython/translator/c/src/qcgc/src/core.h
deleted file mode 100644
--- a/rpython/translator/c/src/qcgc/src/core.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-#include "config.h"
-
-#include <stddef.h>
-
-#include "object.h"
-
-
-void qcgc_initialize(void);
-void qcgc_destroy(void);
-object_t *qcgc_allocate(size_t size);
-void qcgc_collect(void);
-void qcgc_write(object_t *object);
diff --git a/rpython/translator/c/src/qcgc/src/gray_stack.c
b/rpython/translator/c/src/qcgc/src/gray_stack.c
--- a/rpython/translator/c/src/qcgc/src/gray_stack.c
+++ b/rpython/translator/c/src/qcgc/src/gray_stack.c
@@ -1,13 +1,8 @@
#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));
@@ -16,44 +11,17 @@
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) {
+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) {
+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/src/gray_stack.h
b/rpython/translator/c/src/qcgc/src/gray_stack.h
--- a/rpython/translator/c/src/qcgc/src/gray_stack.h
+++ b/rpython/translator/c/src/qcgc/src/gray_stack.h
@@ -12,9 +12,35 @@
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);
+gray_stack_t *gray_stack_grow(gray_stack_t *stack);
__attribute__ ((warn_unused_result))
-gray_stack_t *qcgc_gray_stack_pop(gray_stack_t *stack);
+gray_stack_t *gray_stack_shrink(gray_stack_t *stack);
+
+__attribute__ ((warn_unused_result))
+QCGC_STATIC QCGC_INLINE 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++;
+ return stack;
+}
+
+QCGC_STATIC QCGC_INLINE object_t *qcgc_gray_stack_top(gray_stack_t *stack) {
+#if CHECKED
+ assert(stack->index != 0);
+#endif
+ return stack->items[stack->index - 1];
+}
+
+__attribute__ ((warn_unused_result))
+QCGC_STATIC QCGC_INLINE 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--;
+ return stack;
+}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit