@@ -98,27 +98,20 @@ typedef struct _gcval_t {
98
98
} gcval_t ;
99
99
100
100
typedef struct _pool_t {
101
- gcval_t * freelist ;
101
+ gcval_t * freelist ;
102
+ gcval_t * newpages ;
102
103
uint16_t end_offset ; // avoid to compute this at each allocation
103
104
uint16_t osize ;
104
105
uint16_t nfree ;
105
- struct {
106
- uint16_t allocd : 1 ;
107
- uint16_t linear : 1 ;
108
- };
109
106
} pool_t ;
110
107
111
108
// pool page metadata
112
109
typedef struct _gcpage_t {
113
110
struct {
114
111
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
116
113
// this is a bitwise | of all gc_bits in this page
117
114
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 ;
122
115
};
123
116
uint16_t nfree ;
124
117
uint16_t nmarked ;
@@ -486,7 +479,7 @@ static __attribute__((noinline)) void *malloc_page(void)
486
479
487
480
static inline void free_page (void * p )
488
481
{
489
- size_t pg_idx = -1 ;
482
+ int pg_idx = -1 ;
490
483
int i ;
491
484
for (i = 0 ; i < HEAP_COUNT && heaps [i ] != NULL ; i ++ ) {
492
485
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)
929
922
gcval_t * beg = (gcval_t * )PAGE_DATA (pg );
930
923
gcval_t * end = (gcval_t * )((char * )beg + (pg -> nfree - 1 )* p -> osize );
931
924
end -> next = fl ;
932
- pg -> linear = 1 ;
933
925
pg -> allocd = 0 ;
934
926
pg -> fl_begin_offset = 0 ;
935
927
pg -> fl_end_offset = (char * )end - (char * )beg ;
936
928
return beg ;
937
929
}
938
930
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
-
962
931
static __attribute__((noinline )) void add_page (pool_t * p )
963
932
{
964
933
char * data = malloc_page ();
@@ -967,30 +936,46 @@ static __attribute__((noinline)) void add_page(pool_t *p)
967
936
gcpage_t * pg = GC_PAGE (data );
968
937
pg -> data_offset = data - (char * )pg ;
969
938
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 ;
972
941
}
973
942
974
943
static inline void * __pool_alloc (pool_t * p , int osize , int end_offset )
975
944
{
976
945
gcval_t * v , * end ;
977
946
if (__unlikely ((allocd_bytes += osize ) >= 0 )) {
978
- allocd_bytes -= osize ;
947
+ // allocd_bytes -= osize;
979
948
jl_gc_collect ();
980
- allocd_bytes += osize ;
949
+ // allocd_bytes += osize;
981
950
}
982
951
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 ;
983
967
if (__unlikely (!v )) {
984
968
add_page (p );
985
- v = p -> freelist ;
969
+ v = p -> newpages ;
986
970
}
987
971
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 );
992
974
} 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 ;
994
979
}
995
980
v -> flags = 0 ;
996
981
return v ;
@@ -1044,14 +1029,27 @@ static int freed_pages = 0;
1044
1029
static int lazy_freed_pages = 0 ;
1045
1030
static int page_done = 0 ;
1046
1031
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 );
1048
1032
static void sweep_pool_region (int heap_i , int sweep_mask )
1049
1033
{
1050
1034
region_t * heap = heaps [heap_i ];
1051
1035
gcval_t * * pfl [N_POOLS ];
1052
1036
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 ;
1054
1044
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 ;
1055
1053
}
1056
1054
int ub = 0 ;
1057
1055
int lb = heaps_lb [heap_i ];
@@ -1076,9 +1074,7 @@ static void sweep_pool_region(int heap_i, int sweep_mask)
1076
1074
for (pool_t * p = norm_pools ; p < norm_pools + N_POOLS ; p ++ ) {
1077
1075
* pfl [i ++ ] = NULL ;
1078
1076
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 ;
1082
1078
}
1083
1079
}
1084
1080
}
@@ -1179,9 +1175,13 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma
1179
1175
if (sweep_mask == GC_MARKED_NOESC && lazy_freed_pages <= default_collect_interval /(4 * 4096 )) {
1180
1176
gcval_t * begin = reset_page (p , pg , 0 );
1181
1177
* 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 ;
1183
1182
begin -> next = (gcval_t * )0 ;
1184
1183
lazy_freed_pages ++ ;
1184
+ pfl = prev_pfl ;
1185
1185
}
1186
1186
else {
1187
1187
pfl = prev_pfl ;
@@ -1198,7 +1198,6 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma
1198
1198
}
1199
1199
else {
1200
1200
pg -> gc_bits = pg_gc_bits ;
1201
- pg -> linear = 0 ;
1202
1201
nfree += pg -> nfree ;
1203
1202
}
1204
1203
@@ -2071,6 +2070,7 @@ void jl_gc_collect(void)
2071
2070
void * ptr = rem_bindings .items [i ];
2072
2071
gc_bits (gc_val_buf (ptr )) = GC_MARKED ;
2073
2072
}
2073
+
2074
2074
for (int i = 0 ; i < last_remset -> len ; i ++ ) {
2075
2075
uintptr_t item = (uintptr_t )last_remset -> items [i ];
2076
2076
void * ptr = (void * )(item & ~(uintptr_t )1 );
@@ -2440,6 +2440,7 @@ void jl_gc_init(void)
2440
2440
assert (szc [i ] % 4 == 0 );
2441
2441
norm_pools [i ].osize = szc [i ];
2442
2442
norm_pools [i ].freelist = NULL ;
2443
+ norm_pools [i ].newpages = NULL ;
2443
2444
norm_pools [i ].end_offset = ((GC_PAGE_SZ /szc [i ]) - 1 )* szc [i ];
2444
2445
}
2445
2446
0 commit comments