Skip to content

Commit 26cdba0

Browse files
committed
simplify pool allocations by splitting pages in two lists
1 parent cc8d6f6 commit 26cdba0

File tree

1 file changed

+53
-52
lines changed

1 file changed

+53
-52
lines changed

src/gc.c

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,20 @@ typedef struct _gcval_t {
9898
} gcval_t;
9999

100100
typedef struct _pool_t {
101-
gcval_t *freelist ;
101+
gcval_t *freelist;
102+
gcval_t *newpages;
102103
uint16_t end_offset; // avoid to compute this at each allocation
103104
uint16_t osize;
104105
uint16_t nfree;
105-
struct {
106-
uint16_t allocd : 1;
107-
uint16_t linear : 1;
108-
};
109106
} pool_t;
110107

111108
// pool page metadata
112109
typedef struct _gcpage_t {
113110
struct {
114111
uint16_t pool_n : 8;
115-
uint16_t allocd : 1;
112+
uint16_t allocd : 1; // true if an allocation happened in this page since last sweep
116113
// this is a bitwise | of all gc_bits in this page
117114
uint16_t gc_bits : 2;
118-
// if this is 1, the freelist in this page contains only 2 cells.
119-
// the first free cell and the last cell of the page
120-
// every cell in between is free
121-
uint16_t linear : 1;
122115
};
123116
uint16_t nfree;
124117
uint16_t nmarked;
@@ -486,7 +479,7 @@ static __attribute__((noinline)) void *malloc_page(void)
486479

487480
static inline void free_page(void *p)
488481
{
489-
size_t pg_idx = -1;
482+
int pg_idx = -1;
490483
int i;
491484
for(i = 0; i < HEAP_COUNT && heaps[i] != NULL; i++) {
492485
pg_idx = ((char*)p - (char*)&heaps[i]->pages[0])/GC_PAGE_SZ;
@@ -929,36 +922,12 @@ static inline gcval_t *reset_page(pool_t *p, gcpage_t *pg, gcval_t *fl)
929922
gcval_t *beg = (gcval_t*)PAGE_DATA(pg);
930923
gcval_t *end = (gcval_t*)((char*)beg + (pg->nfree - 1)*p->osize);
931924
end->next = fl;
932-
pg->linear = 1;
933925
pg->allocd = 0;
934926
pg->fl_begin_offset = 0;
935927
pg->fl_end_offset = (char*)end - (char*)beg;
936928
return beg;
937929
}
938930

939-
// assign p->freelist = next
940-
// takes care of flushing the page metadata cache
941-
// if page(p->freelist) != page(next)
942-
static inline void _update_freelist(pool_t* p, gcval_t* next)
943-
{
944-
gcval_t *cur = p->freelist;
945-
p->freelist = next;
946-
if (__likely(GC_PAGE_DATA(cur) == GC_PAGE_DATA(next))) return;
947-
gcpage_t *cpg = cur ? GC_PAGE(cur) : NULL;
948-
gcpage_t *npg = next ? GC_PAGE(next) : NULL;
949-
if (npg == cpg) return;
950-
if (cpg) {
951-
cpg->linear = p->linear;
952-
cpg->nfree = p->nfree;
953-
cpg->allocd = p->allocd;
954-
}
955-
if (npg) {
956-
p->linear = npg->linear;
957-
p->nfree = npg->nfree;
958-
p->allocd = npg->allocd;
959-
}
960-
}
961-
962931
static __attribute__((noinline)) void add_page(pool_t *p)
963932
{
964933
char *data = malloc_page();
@@ -967,30 +936,46 @@ static __attribute__((noinline)) void add_page(pool_t *p)
967936
gcpage_t *pg = GC_PAGE(data);
968937
pg->data_offset = data - (char*)pg;
969938
pg->osize = p->osize;
970-
gcval_t *fl = reset_page(p, pg, p->freelist);
971-
_update_freelist(p, fl);
939+
gcval_t *fl = reset_page(p, pg, p->newpages);
940+
p->newpages = fl;
972941
}
973942

974943
static inline void *__pool_alloc(pool_t* p, int osize, int end_offset)
975944
{
976945
gcval_t *v, *end;
977946
if (__unlikely((allocd_bytes += osize) >= 0)) {
978-
allocd_bytes -= osize;
947+
// allocd_bytes -= osize;
979948
jl_gc_collect();
980-
allocd_bytes += osize;
949+
// allocd_bytes += osize;
981950
}
982951
v = p->freelist;
952+
if (v) {
953+
gcval_t* next = v->next;
954+
v->flags = 0;
955+
p->nfree--;
956+
p->freelist = next;
957+
if (__unlikely(GC_PAGE_DATA(v) != GC_PAGE_DATA(next))) {
958+
gcpage_t* pg = GC_PAGE(v);
959+
pg->nfree = 0;
960+
pg->allocd = 1;
961+
if (next)
962+
p->nfree = GC_PAGE(next)->nfree;
963+
}
964+
return v;
965+
}
966+
v = p->newpages;
983967
if (__unlikely(!v)) {
984968
add_page(p);
985-
v = p->freelist;
969+
v = p->newpages;
986970
}
987971
end = (gcval_t*)&(GC_PAGE_DATA(v)[end_offset]);
988-
p->nfree--;
989-
p->allocd = 1;
990-
if (p->linear && v != end) {
991-
p->freelist = (gcval_t*)((char*)v + osize);
972+
if (__likely(v != end)) {
973+
p->newpages = (gcval_t*)((char*)v + osize);
992974
} else {
993-
_update_freelist(p, v->next);
975+
gcpage_t* pg = GC_PAGE(v);
976+
pg->nfree = 0;
977+
pg->allocd = 1;
978+
p->newpages = v->next;
994979
}
995980
v->flags = 0;
996981
return v;
@@ -1044,14 +1029,27 @@ static int freed_pages = 0;
10441029
static int lazy_freed_pages = 0;
10451030
static int page_done = 0;
10461031
static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl,int,int);
1047-
static void _update_freelist(pool_t* p, gcval_t* next);
10481032
static void sweep_pool_region(int heap_i, int sweep_mask)
10491033
{
10501034
region_t* heap = heaps[heap_i];
10511035
gcval_t **pfl[N_POOLS];
10521036
for (int i = 0; i < N_POOLS; i++) {
1053-
_update_freelist(&norm_pools[i], NULL);
1037+
gcval_t* last = norm_pools[i].freelist;
1038+
if (last) {
1039+
gcpage_t* pg = GC_PAGE(last);
1040+
pg->allocd = 1;
1041+
pg->nfree = norm_pools[i].nfree;
1042+
}
1043+
norm_pools[i].freelist = NULL;
10541044
pfl[i] = &norm_pools[i].freelist;
1045+
1046+
last = norm_pools[i].newpages;
1047+
if (last) {
1048+
gcpage_t* pg = GC_PAGE(last);
1049+
pg->nfree = (GC_PAGE_SZ - ((char*)last - GC_PAGE_DATA(last)))/norm_pools[i].osize;
1050+
pg->allocd = 1;
1051+
}
1052+
norm_pools[i].newpages = NULL;
10551053
}
10561054
int ub = 0;
10571055
int lb = heaps_lb[heap_i];
@@ -1076,9 +1074,7 @@ static void sweep_pool_region(int heap_i, int sweep_mask)
10761074
for (pool_t* p = norm_pools; p < norm_pools + N_POOLS; p++) {
10771075
*pfl[i++] = NULL;
10781076
if (p->freelist) {
1079-
gcval_t *begin = p->freelist;
1080-
p->freelist = NULL;
1081-
_update_freelist(p, begin);
1077+
p->nfree = GC_PAGE(p->freelist)->nfree;
10821078
}
10831079
}
10841080
}
@@ -1179,9 +1175,13 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma
11791175
if (sweep_mask == GC_MARKED_NOESC && lazy_freed_pages <= default_collect_interval/(4*4096)) {
11801176
gcval_t *begin = reset_page(p, pg, 0);
11811177
*prev_pfl = begin;
1182-
pfl = (gcval_t**)((char*)begin + ((int)pg->nfree - 1)*osize);
1178+
gcval_t** pend = (gcval_t**)((char*)begin + ((int)pg->nfree - 1)*osize);
1179+
gcval_t* npg = p->newpages;
1180+
*pend = npg;
1181+
p->newpages = begin;
11831182
begin->next = (gcval_t*)0;
11841183
lazy_freed_pages++;
1184+
pfl = prev_pfl;
11851185
}
11861186
else {
11871187
pfl = prev_pfl;
@@ -1198,7 +1198,6 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma
11981198
}
11991199
else {
12001200
pg->gc_bits = pg_gc_bits;
1201-
pg->linear = 0;
12021201
nfree += pg->nfree;
12031202
}
12041203

@@ -2071,6 +2070,7 @@ void jl_gc_collect(void)
20712070
void *ptr = rem_bindings.items[i];
20722071
gc_bits(gc_val_buf(ptr)) = GC_MARKED;
20732072
}
2073+
20742074
for (int i = 0; i < last_remset->len; i++) {
20752075
uintptr_t item = (uintptr_t)last_remset->items[i];
20762076
void* ptr = (void*)(item & ~(uintptr_t)1);
@@ -2440,6 +2440,7 @@ void jl_gc_init(void)
24402440
assert(szc[i] % 4 == 0);
24412441
norm_pools[i].osize = szc[i];
24422442
norm_pools[i].freelist = NULL;
2443+
norm_pools[i].newpages = NULL;
24432444
norm_pools[i].end_offset = ((GC_PAGE_SZ/szc[i]) - 1)*szc[i];
24442445
}
24452446

0 commit comments

Comments
 (0)