Skip to content

Commit f5b224d

Browse files
committed
Optimize GC allocation
* Pass TLS pointer explicitly to GC allocation functions * Clean up GC allocation functions to take advantage of compiler constant propagation. * Do not initialize tag twice * Remove `jl_gc_pool_t::nfree`
1 parent 63babf4 commit f5b224d

19 files changed

+408
-388
lines changed

base/boot.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ end
248248
type WeakRef
249249
value
250250
WeakRef() = WeakRef(nothing)
251-
WeakRef(v::ANY) = ccall(:jl_gc_new_weakref, Ref{WeakRef}, (Any,), v)
251+
WeakRef(v::ANY) = ccall(:jl_gc_new_weakref_th, Ref{WeakRef},
252+
(Ptr{Void}, Any), getptls(), v)
252253
end
253254

254255
TypeVar(n::Symbol) =

src/alloc.c

+75-55
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ typedef struct {
113113
// Note that this function updates len
114114
static jl_value_t *jl_new_bits_internal(jl_value_t *dt, void *data, size_t *len)
115115
{
116+
jl_ptls_t ptls = jl_get_ptls_states();
116117
assert(jl_is_datatype(dt));
117118
jl_datatype_t *bt = (jl_datatype_t*)dt;
118119
size_t nb = jl_datatype_size(bt);
@@ -127,7 +128,7 @@ static jl_value_t *jl_new_bits_internal(jl_value_t *dt, void *data, size_t *len)
127128
if (bt == jl_int32_type) return jl_box_int32(*(int32_t*)data);
128129
if (bt == jl_float64_type) return jl_box_float64(*(double*)data);
129130

130-
jl_value_t *v = (jl_value_t*)newobj((jl_value_t*)bt, NWORDS(nb));
131+
jl_value_t *v = jl_gc_alloc(ptls, nb, bt);
131132
switch (nb) {
132133
case 1: *(int8_t*) jl_data_ptr(v) = *(int8_t*)data; break;
133134
case 2: *(int16_t*) jl_data_ptr(v) = *(int16_t*)data; break;
@@ -224,11 +225,12 @@ JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i)
224225

225226
JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...)
226227
{
228+
jl_ptls_t ptls = jl_get_ptls_states();
227229
if (type->instance != NULL) return type->instance;
228230
va_list args;
229231
size_t nf = jl_datatype_nfields(type);
230232
va_start(args, type);
231-
jl_value_t *jv = newstruct(type);
233+
jl_value_t *jv = jl_gc_alloc(ptls, type->size, type);
232234
for(size_t i=0; i < nf; i++) {
233235
jl_set_nth_field(jv, i, va_arg(args, jl_value_t*));
234236
}
@@ -239,9 +241,10 @@ JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...)
239241
JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args,
240242
uint32_t na)
241243
{
244+
jl_ptls_t ptls = jl_get_ptls_states();
242245
if (type->instance != NULL) return type->instance;
243246
size_t nf = jl_datatype_nfields(type);
244-
jl_value_t *jv = newstruct(type);
247+
jl_value_t *jv = jl_gc_alloc(ptls, type->size, type);
245248
for(size_t i=0; i < na; i++) {
246249
jl_set_nth_field(jv, i, args[i]);
247250
}
@@ -255,10 +258,12 @@ JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args,
255258

256259
JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type)
257260
{
261+
jl_ptls_t ptls = jl_get_ptls_states();
258262
if (type->instance != NULL) return type->instance;
259-
jl_value_t *jv = newstruct(type);
260-
if (type->size > 0)
261-
memset(jl_data_ptr(jv), 0, type->size);
263+
size_t size = type->size;
264+
jl_value_t *jv = jl_gc_alloc(ptls, size, type);
265+
if (size > 0)
266+
memset(jl_data_ptr(jv), 0, size);
262267
return jv;
263268
}
264269

@@ -385,9 +390,10 @@ static void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_expr_t *ast)
385390

386391
JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info_uninit(void)
387392
{
393+
jl_ptls_t ptls = jl_get_ptls_states();
388394
jl_lambda_info_t *li =
389-
(jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type,
390-
NWORDS(sizeof(jl_lambda_info_t)));
395+
(jl_lambda_info_t*)jl_gc_alloc(ptls, sizeof(jl_lambda_info_t),
396+
jl_lambda_info_type);
391397
li->code = NULL;
392398
li->slotnames = li->slotflags = NULL;
393399
li->slottypes = li->ssavaluetypes = NULL;
@@ -578,8 +584,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
578584
{
579585
jl_ptls_t ptls = jl_get_ptls_states();
580586
jl_method_t *m =
581-
(jl_method_t*)newobj((jl_value_t*)jl_method_type,
582-
NWORDS(sizeof(jl_method_t)));
587+
(jl_method_t*)jl_gc_alloc(ptls, sizeof(jl_method_t), jl_method_type);
583588
m->specializations.unknown = jl_nothing;
584589
m->sig = NULL;
585590
m->tvars = NULL;
@@ -809,8 +814,10 @@ jl_sym_t *jl_demangle_typename(jl_sym_t *s)
809814

810815
JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module)
811816
{
812-
jl_methtable_t *mt = (jl_methtable_t*)jl_gc_allocobj(sizeof(jl_methtable_t));
813-
jl_set_typeof(mt, jl_methtable_type);
817+
jl_ptls_t ptls = jl_get_ptls_states();
818+
jl_methtable_t *mt =
819+
(jl_methtable_t*)jl_gc_alloc(ptls, sizeof(jl_methtable_t),
820+
jl_methtable_type);
814821
mt->name = jl_demangle_typename(name);
815822
mt->module = module;
816823
mt->defs.unknown = jl_nothing;
@@ -825,7 +832,10 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo
825832

826833
JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *module)
827834
{
828-
jl_typename_t *tn=(jl_typename_t*)newobj((jl_value_t*)jl_typename_type, NWORDS(sizeof(jl_typename_t)));
835+
jl_ptls_t ptls = jl_get_ptls_states();
836+
jl_typename_t *tn =
837+
(jl_typename_t*)jl_gc_alloc(ptls, sizeof(jl_typename_t),
838+
jl_typename_type);
829839
tn->name = name;
830840
tn->module = module;
831841
tn->primary = NULL;
@@ -856,12 +866,14 @@ jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super,
856866

857867
JL_DLLEXPORT jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields, int8_t fielddesc_type)
858868
{
869+
jl_ptls_t ptls = jl_get_ptls_states();
859870
// fielddesc_type is specified manually for builtin types
860871
// and is (will be) calculated automatically for user defined types.
861872
uint32_t fielddesc_size = jl_fielddesc_size(fielddesc_type);
862-
jl_datatype_t *t = (jl_datatype_t*)
863-
newobj((jl_value_t*)jl_datatype_type,
864-
NWORDS(sizeof(jl_datatype_t) + nfields * fielddesc_size));
873+
jl_datatype_t *t =
874+
(jl_datatype_t*)jl_gc_alloc(ptls, (sizeof(jl_datatype_t) +
875+
nfields * fielddesc_size),
876+
jl_datatype_type);
865877
// fielddesc_type should only be assigned here. It can cause data
866878
// corruption otherwise.
867879
t->fielddesc_type = fielddesc_type;
@@ -1080,14 +1092,17 @@ JL_DLLEXPORT jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *sup
10801092

10811093
JL_DLLEXPORT jl_value_t *jl_new_type_constructor(jl_svec_t *p, jl_value_t *body)
10821094
{
1095+
jl_ptls_t ptls = jl_get_ptls_states();
10831096
#ifndef NDEBUG
10841097
size_t i, np = jl_svec_len(p);
10851098
for (i = 0; i < np; i++) {
10861099
jl_tvar_t *tv = (jl_tvar_t*)jl_svecref(p, i);
10871100
assert(jl_is_typevar(tv) && !tv->bound);
10881101
}
10891102
#endif
1090-
jl_typector_t *tc = (jl_typector_t*)newobj((jl_value_t*)jl_typector_type, NWORDS(sizeof(jl_typector_t)));
1103+
jl_typector_t *tc =
1104+
(jl_typector_t*)jl_gc_alloc(ptls, sizeof(jl_typector_t),
1105+
jl_typector_type);
10911106
tc->parameters = p;
10921107
tc->body = body;
10931108
return (jl_value_t*)tc;
@@ -1099,10 +1114,10 @@ JL_DLLEXPORT jl_value_t *jl_new_type_constructor(jl_svec_t *p, jl_value_t *body)
10991114
#define BOXN_FUNC(nb,nw) \
11001115
JL_DLLEXPORT jl_value_t *jl_box##nb(jl_datatype_t *t, int##nb##_t x) \
11011116
{ \
1117+
jl_ptls_t ptls = jl_get_ptls_states(); \
11021118
assert(jl_isbits(t)); \
11031119
assert(jl_datatype_size(t) == sizeof(x)); \
1104-
jl_value_t *v = (jl_value_t*)jl_gc_alloc_##nw##w(); \
1105-
jl_set_typeof(v, t); \
1120+
jl_value_t *v = jl_gc_alloc(ptls, nw * sizeof(void*), t); \
11061121
*(int##nb##_t*)jl_data_ptr(v) = x; \
11071122
return v; \
11081123
}
@@ -1135,13 +1150,14 @@ UNBOX_FUNC(float32, float)
11351150
UNBOX_FUNC(float64, double)
11361151
UNBOX_FUNC(voidpointer, void*)
11371152

1138-
#define BOX_FUNC(typ,c_type,pfx,nw) \
1139-
JL_DLLEXPORT jl_value_t *pfx##_##typ(c_type x) \
1140-
{ \
1141-
jl_value_t *v = (jl_value_t*)jl_gc_alloc_##nw##w(); \
1142-
jl_set_typeof(v, jl_##typ##_type); \
1143-
*(c_type*)jl_data_ptr(v) = x; \
1144-
return v; \
1153+
#define BOX_FUNC(typ,c_type,pfx,nw) \
1154+
JL_DLLEXPORT jl_value_t *pfx##_##typ(c_type x) \
1155+
{ \
1156+
jl_ptls_t ptls = jl_get_ptls_states(); \
1157+
jl_value_t *v = jl_gc_alloc(ptls, nw * sizeof(void*), \
1158+
jl_##typ##_type); \
1159+
*(c_type*)jl_data_ptr(v) = x; \
1160+
return v; \
11451161
}
11461162
BOX_FUNC(float32, float, jl_box, 1)
11471163
BOX_FUNC(voidpointer, void*, jl_box, 1)
@@ -1153,26 +1169,28 @@ BOX_FUNC(float64, double, jl_box, 2)
11531169

11541170
#define NBOX_C 1024
11551171

1156-
#define SIBOX_FUNC(typ,c_type,nw) \
1157-
static jl_value_t *boxed_##typ##_cache[NBOX_C]; \
1158-
JL_DLLEXPORT jl_value_t *jl_box_##typ(c_type x) \
1159-
{ \
1160-
c_type idx = x+NBOX_C/2; \
1161-
if ((u##c_type)idx < (u##c_type)NBOX_C) \
1162-
return boxed_##typ##_cache[idx]; \
1163-
jl_value_t *v = (jl_value_t*)jl_gc_alloc_##nw##w(); \
1164-
jl_set_typeof(v, jl_##typ##_type); \
1165-
*(c_type*)jl_data_ptr(v) = x; \
1166-
return v; \
1172+
#define SIBOX_FUNC(typ,c_type,nw)\
1173+
static jl_value_t *boxed_##typ##_cache[NBOX_C]; \
1174+
JL_DLLEXPORT jl_value_t *jl_box_##typ(c_type x) \
1175+
{ \
1176+
jl_ptls_t ptls = jl_get_ptls_states(); \
1177+
c_type idx = x+NBOX_C/2; \
1178+
if ((u##c_type)idx < (u##c_type)NBOX_C) \
1179+
return boxed_##typ##_cache[idx]; \
1180+
jl_value_t *v = jl_gc_alloc(ptls, nw * sizeof(void*), \
1181+
jl_##typ##_type); \
1182+
*(c_type*)jl_data_ptr(v) = x; \
1183+
return v; \
11671184
}
11681185
#define UIBOX_FUNC(typ,c_type,nw) \
11691186
static jl_value_t *boxed_##typ##_cache[NBOX_C]; \
11701187
JL_DLLEXPORT jl_value_t *jl_box_##typ(c_type x) \
11711188
{ \
1189+
jl_ptls_t ptls = jl_get_ptls_states(); \
11721190
if (x < NBOX_C) \
11731191
return boxed_##typ##_cache[x]; \
1174-
jl_value_t *v = (jl_value_t*)jl_gc_alloc_##nw##w(); \
1175-
jl_set_typeof(v, jl_##typ##_type); \
1192+
jl_value_t *v = jl_gc_alloc(ptls, nw * sizeof(void*), \
1193+
jl_##typ##_type); \
11761194
*(c_type*)jl_data_ptr(v) = x; \
11771195
return v; \
11781196
}
@@ -1236,23 +1254,23 @@ void jl_init_box_caches(void)
12361254
}
12371255
}
12381256

1239-
void jl_mark_box_caches(void)
1257+
void jl_mark_box_caches(jl_ptls_t ptls)
12401258
{
12411259
int64_t i;
12421260
for(i=0; i < 256; i++) {
1243-
jl_gc_setmark(boxed_int8_cache[i]);
1244-
jl_gc_setmark(boxed_uint8_cache[i]);
1261+
jl_gc_setmark(ptls, boxed_int8_cache[i]);
1262+
jl_gc_setmark(ptls, boxed_uint8_cache[i]);
12451263
}
12461264
for(i=0; i < NBOX_C; i++) {
1247-
jl_gc_setmark(boxed_int16_cache[i]);
1248-
jl_gc_setmark(boxed_int32_cache[i]);
1249-
jl_gc_setmark(boxed_int64_cache[i]);
1250-
jl_gc_setmark(boxed_uint16_cache[i]);
1251-
jl_gc_setmark(boxed_uint32_cache[i]);
1252-
jl_gc_setmark(boxed_char_cache[i]);
1253-
jl_gc_setmark(boxed_uint64_cache[i]);
1254-
jl_gc_setmark(boxed_ssavalue_cache[i]);
1255-
jl_gc_setmark(boxed_slotnumber_cache[i]);
1265+
jl_gc_setmark(ptls, boxed_int16_cache[i]);
1266+
jl_gc_setmark(ptls, boxed_int32_cache[i]);
1267+
jl_gc_setmark(ptls, boxed_int64_cache[i]);
1268+
jl_gc_setmark(ptls, boxed_uint16_cache[i]);
1269+
jl_gc_setmark(ptls, boxed_uint32_cache[i]);
1270+
jl_gc_setmark(ptls, boxed_char_cache[i]);
1271+
jl_gc_setmark(ptls, boxed_uint64_cache[i]);
1272+
jl_gc_setmark(ptls, boxed_ssavalue_cache[i]);
1273+
jl_gc_setmark(ptls, boxed_slotnumber_cache[i]);
12561274
}
12571275
}
12581276

@@ -1267,10 +1285,11 @@ JL_DLLEXPORT jl_value_t *jl_box_bool(int8_t x)
12671285

12681286
jl_expr_t *jl_exprn(jl_sym_t *head, size_t n)
12691287
{
1288+
jl_ptls_t ptls = jl_get_ptls_states();
12701289
jl_array_t *ar = n==0 ? (jl_array_t*)jl_an_empty_vec_any : jl_alloc_vec_any(n);
12711290
JL_GC_PUSH1(&ar);
1272-
jl_expr_t *ex = (jl_expr_t*)jl_gc_alloc_3w(); assert(NWORDS(sizeof(jl_expr_t))==3);
1273-
jl_set_typeof(ex, jl_expr_type);
1291+
jl_expr_t *ex = (jl_expr_t*)jl_gc_alloc(ptls, sizeof(jl_expr_t),
1292+
jl_expr_type);
12741293
ex->head = head;
12751294
ex->args = ar;
12761295
ex->etype = (jl_value_t*)jl_any_type;
@@ -1280,14 +1299,15 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n)
12801299

12811300
JL_CALLABLE(jl_f__expr)
12821301
{
1302+
jl_ptls_t ptls = jl_get_ptls_states();
12831303
JL_NARGSV(Expr, 1);
12841304
JL_TYPECHK(Expr, symbol, args[0]);
12851305
jl_array_t *ar = jl_alloc_vec_any(nargs-1);
12861306
JL_GC_PUSH1(&ar);
12871307
for(size_t i=0; i < nargs-1; i++)
12881308
jl_array_ptr_set(ar, i, args[i+1]);
1289-
jl_expr_t *ex = (jl_expr_t*)jl_gc_alloc_3w(); assert(NWORDS(sizeof(jl_expr_t))==3);
1290-
jl_set_typeof(ex, jl_expr_type);
1309+
jl_expr_t *ex = (jl_expr_t*)jl_gc_alloc(ptls, sizeof(jl_expr_t),
1310+
jl_expr_type);
12911311
ex->head = (jl_sym_t*)args[0];
12921312
ex->args = ar;
12931313
ex->etype = (jl_value_t*)jl_any_type;

0 commit comments

Comments
 (0)