[pypy-commit] stmgc gc-small-uniform: in-progress
arigo
noreply at buildbot.pypy.org
Sat Apr 5 19:38:04 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-small-uniform
Changeset: r1130:b75f80e3f905
Date: 2014-04-05 19:37 +0200
http://bitbucket.org/pypy/stmgc/changeset/b75f80e3f905/
Log: in-progress
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -64,7 +64,12 @@
object_t *_stm_allocate_old(ssize_t size_rounded_up)
{
/* only for tests xxx but stm_setup_prebuilt() uses this now too */
- char *p = allocate_outside_nursery_large(size_rounded_up);
+ char *p;
+ if (size_rounded_up > GC_LAST_SMALL_SIZE)
+ p = allocate_outside_nursery_large(size_rounded_up);
+ else
+ p = allocate_outside_nursery_small(size_rounded_up);
+
memset(p, 0, size_rounded_up);
object_t *o = (object_t *)(p - stm_object_pages);
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -103,7 +103,7 @@
realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
size = stmcb_size_rounded_up((struct object_s *)realobj);
- if (size >= GC_N_SMALL_REQUESTS) {
+ if (size > GC_LAST_SMALL_SIZE) {
/* case 1: object is not small enough.
Ask gcpage.c for an allocation via largemalloc. */
diff --git a/c7/stm/smallmalloc.c b/c7/stm/smallmalloc.c
--- a/c7/stm/smallmalloc.c
+++ b/c7/stm/smallmalloc.c
@@ -3,10 +3,33 @@
#endif
+#define PAGE_SMSIZE_START END_NURSERY_PAGE
+#define PAGE_SMSIZE_END NB_PAGES
+
+typedef struct {
+ uint8_t sz;
+} fpsz_t;
+
+static fpsz_t full_pages_object_size[PAGE_SMSIZE_END - PAGE_SMSIZE_START];
+/* ^^^ This array contains the size (in number of words) of the objects
+ in the given page, provided it's a "full page of small objects". It
+ is 0 if it's not such a page, if it's fully free, or if it's in
+ small_page_lists. It is not 0 as soon as the page enters the
+ segment's 'small_malloc_data.loc_free' (even if the page is not
+ technically full yet, it will be very soon in this case).
+*/
+
+static fpsz_t *get_fp_sz(char *smallpage)
+{
+ uintptr_t pagenum = (((char *)smallpage) - stm_object_pages) / 4096;
+ return &full_pages_object_size[pagenum - PAGE_SMSIZE_START];
+}
+
+
static void teardown_smallmalloc(void)
{
memset(small_page_lists, 0, sizeof(small_page_lists));
- assert(free_uniform_pages == NULL);
+ assert(free_uniform_pages == NULL); /* done by the previous line */
first_small_uniform_loc = (uintptr_t) -1;
}
@@ -69,6 +92,7 @@
/* Succeeded: we have a page in 'smallpage' */
*fl = smallpage->header.next;
+ get_fp_sz((char *)smallpage)->sz = n;
return (char *)smallpage;
}
@@ -101,6 +125,7 @@
/* The first slot is immediately returned */
*fl = following;
+ get_fp_sz((char *)smallpage)->sz = n;
return (char *)smallpage;
}
@@ -114,7 +139,7 @@
static inline char *allocate_outside_nursery_small(uint64_t size)
{
OPT_ASSERT((size & 7) == 0);
- OPT_ASSERT(16 <= size && size < 8 * GC_N_SMALL_REQUESTS);
+ OPT_ASSERT(16 <= size && size <= GC_LAST_SMALL_SIZE);
struct small_free_loc_s *TLPREFIX *fl =
&STM_PSEGMENT->small_malloc_data.loc_free[size / 8];
@@ -127,3 +152,28 @@
*fl = result->next;
return (char *)result;
}
+
+void _stm_smallmalloc_sweep(void)
+{
+ long i;
+ for (i = 2; i < GC_N_SMALL_REQUESTS; i++) {
+ struct small_page_list_s *page = small_page_lists[i];
+ while (page != NULL) {
+ /* for every page in small_page_lists: assert that the
+ corresponding full_pages_object_size[] entry is 0 */
+ assert(get_fp_sz((char *)page)->sz == 0);
+ abort(); // walk
+ page = page->nextpage;
+ }
+ }
+
+ fpsz_t *fpsz_start = get_fp_sz(uninitialized_page_stop);
+ fpsz_t *fpsz_end = &full_pages_object_size[PAGE_SMSIZE_END -
+ PAGE_SMSIZE_START];
+ fpsz_t *fpsz;
+ for (fpsz = fpsz_start; fpsz < fpsz_end; fpsz++) {
+ if (fpsz->sz != 0) {
+ abort(); // walk
+ }
+ }
+}
diff --git a/c7/stm/smallmalloc.h b/c7/stm/smallmalloc.h
--- a/c7/stm/smallmalloc.h
+++ b/c7/stm/smallmalloc.h
@@ -8,6 +8,7 @@
*/
#define GC_N_SMALL_REQUESTS 36
+#define GC_LAST_SMALL_SIZE (8 * (GC_N_SMALL_REQUESTS - 1))
struct small_free_loc_s {
@@ -19,8 +20,9 @@
free. */
struct small_free_loc_s header;
- /* A chained list of all small pages containing objects of
- a given small size, and that have at least one free object. */
+ /* A chained list of all small pages containing objects of a given
+ small size, and that have at least one free object. It points
+ *inside* the next page, to another struct small_page_list_s. */
struct small_page_list_s *nextpage;
/* This structure is only two words, so it always fits inside one
@@ -57,7 +59,8 @@
static inline char *allocate_outside_nursery_small(uint64_t size)
__attribute__((always_inline));
-static char *_allocate_small_slowpath(uint64_t size);
+void _stm_smallmalloc_sweep(void);
+
static void teardown_smallmalloc(void);
static inline bool is_small_uniform(object_t *obj) {
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -125,6 +125,8 @@
void _stm_large_dump(void);
bool (*_stm_largemalloc_keep)(char *data);
void _stm_largemalloc_sweep(void);
+bool (*_stm_smallmalloc_keep)(char *data);
+void _stm_smallmalloc_sweep(void);
void _stm_start_safe_point(void);
void _stm_stop_safe_point(void);
void _stm_set_nursery_free_count(uint64_t free_count);
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -81,6 +81,7 @@
void *memset(void *s, int c, size_t n);
bool (*_stm_largemalloc_keep)(char *data);
void _stm_largemalloc_sweep(void);
+void _stm_smallmalloc_sweep(void);
ssize_t stmcb_size_rounded_up(struct object_s *obj);
@@ -290,6 +291,8 @@
assert HDR == 8
GCFLAG_WRITE_BARRIER = lib._STM_GCFLAG_WRITE_BARRIER
NB_SEGMENTS = lib.STM_NB_SEGMENTS
+GC_N_SMALL_REQUESTS = 36
+GC_LAST_SMALL_SIZE = 8 * (GC_N_SMALL_REQUESTS - 1)
class Conflict(Exception):
diff --git a/c7/test/test_smallmalloc.py b/c7/test/test_smallmalloc.py
new file mode 100644
--- /dev/null
+++ b/c7/test/test_smallmalloc.py
@@ -0,0 +1,32 @@
+from support import *
+
+
+def pageof(p):
+ return int(ffi.cast("uintptr_t", p)) >> 12
+
+
+class TestLargeMalloc(BaseTest):
+
+ def test_simple_uniform(self):
+ page0 = [stm_allocate_old(16) for i in range(0, 4096, 16)]
+ assert len(set(map(pageof, page0))) == 1
+ #
+ page1 = [stm_allocate_old(16) for i in range(0, 4096, 16)]
+ assert len(set(map(pageof, page1))) == 1
+ #
+ assert len(set(map(pageof, page0 + page1))) == 2
+
+ def test_different_sizes_different_pages(self):
+ seen = []
+ for i in range(2, GC_N_SMALL_REQUESTS):
+ p = pageof(stm_allocate_old(8 * i))
+ assert p not in seen
+ seen.append(p)
+ for i in range(2, GC_N_SMALL_REQUESTS):
+ p = pageof(stm_allocate_old(8 * i))
+ assert p == seen[0]
+ seen.pop(0)
+
+ def test_sweep_freeing(self):
+ p1 = stm_allocate_old(16)
+ lib._stm_smallmalloc_sweep()
More information about the pypy-commit
mailing list