Skip to content

Commit 23a8f42

Browse files
committed
Optimize jl_add_*_finalizer fast path to avoid a lock
* Make `finalizer_list` thread local * Optimize usage of `arraylist_t` in `gc.c` * Also starts to explicitly pass `ptls` around to reduce TLS access overhead More consistently use `ptls` for the tls pointer of the current thread and `ptls2` for the tls pointer of other threads.
1 parent 6f9c469 commit 23a8f42

15 files changed

+308
-194
lines changed

base/base.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,16 @@ function finalizer(o::ANY, f::ANY)
7070
if isimmutable(o)
7171
error("objects of type ", typeof(o), " cannot be finalized")
7272
end
73-
ccall(:jl_gc_add_finalizer, Void, (Any,Any), o, f)
73+
ccall(:jl_gc_add_finalizer_th, Void, (Ptr{Void}, Any, Any),
74+
Core.getptls(), o, f)
7475
end
7576
function finalizer{T}(o::T, f::Ptr{Void})
7677
@_inline_meta
7778
if isimmutable(T)
7879
error("objects of type ", T, " cannot be finalized")
7980
end
80-
ccall(:jl_gc_add_ptr_finalizer, Void, (Any, Ptr{Void}), o, f)
81+
ccall(:jl_gc_add_ptr_finalizer, Void, (Ptr{Void}, Any, Ptr{Void}),
82+
Core.getptls(), o, f)
8183
end
8284

8385
finalize(o::ANY) = ccall(:jl_finalize, Void, (Any,), o)

src/codegen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,7 @@ static uint64_t compute_obj_symsize(const object::ObjectFile *obj, uint64_t offs
13181318
extern "C" JL_DLLEXPORT
13191319
const jl_value_t *jl_dump_function_asm(void *f, int raw_mc)
13201320
{
1321+
jl_tls_states_t *ptls = jl_get_ptls_states();
13211322
std::string code;
13221323
llvm::raw_string_ostream stream(code);
13231324
#ifndef LLVM37
@@ -1362,7 +1363,7 @@ const jl_value_t *jl_dump_function_asm(void *f, int raw_mc)
13621363
return (jl_value_t*)jl_pchar_to_array((char*)fptr, symsize);
13631364
}
13641365

1365-
int8_t gc_state = jl_gc_safe_enter();
1366+
int8_t gc_state = jl_gc_safe_enter(ptls);
13661367
jl_dump_asm_internal(fptr, symsize, slide,
13671368
#ifndef USE_MCJIT
13681369
context,
@@ -1378,7 +1379,7 @@ const jl_value_t *jl_dump_function_asm(void *f, int raw_mc)
13781379
#ifndef LLVM37
13791380
fstream.flush();
13801381
#endif
1381-
jl_gc_safe_leave(gc_state);
1382+
jl_gc_safe_leave(ptls, gc_state);
13821383

13831384
return jl_cstr_to_string(const_cast<char*>(stream.str().c_str()));
13841385
}

src/debuginfo.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,10 @@ class JuliaJITEventListener: public JITEventListener
251251
virtual void NotifyFunctionEmitted(const Function &F, void *Code,
252252
size_t Size, const EmittedFunctionDetails &Details)
253253
{
254+
jl_tls_states_t *ptls = jl_get_ptls_states();
254255
// This function modify linfo->fptr in GC safe region.
255256
// This should be fine since the GC won't scan this field.
256-
int8_t gc_state = jl_gc_safe_enter();
257+
int8_t gc_state = jl_gc_safe_enter(ptls);
257258
uv_rwlock_wrlock(&threadsafe);
258259
StringRef sName = F.getName();
259260
StringMap<jl_lambda_info_t*>::iterator linfo_it = linfo_in_flight.find(sName);
@@ -274,7 +275,7 @@ class JuliaJITEventListener: public JITEventListener
274275
const_cast<Function*>(&F)->deleteBody();
275276
#endif
276277
uv_rwlock_wrunlock(&threadsafe);
277-
jl_gc_safe_leave(gc_state);
278+
jl_gc_safe_leave(ptls, gc_state);
278279
}
279280

280281
std::map<size_t, FuncInfo, revcomp>& getMap()
@@ -309,9 +310,10 @@ class JuliaJITEventListener: public JITEventListener
309310
virtual void NotifyObjectEmitted(const ObjectImage &obj)
310311
#endif
311312
{
313+
jl_tls_states_t *ptls = jl_get_ptls_states();
312314
// This function modify linfo->fptr in GC safe region.
313315
// This should be fine since the GC won't scan this field.
314-
int8_t gc_state = jl_gc_safe_enter();
316+
int8_t gc_state = jl_gc_safe_enter(ptls);
315317
uv_rwlock_wrlock(&threadsafe);
316318
#ifdef LLVM36
317319
object::section_iterator Section = debugObj.section_begin();
@@ -601,7 +603,7 @@ class JuliaJITEventListener: public JITEventListener
601603
#endif
602604
#endif
603605
uv_rwlock_wrunlock(&threadsafe);
604-
jl_gc_safe_leave(gc_state);
606+
jl_gc_safe_leave(ptls, gc_state);
605607
}
606608

607609
// must implement if we ever start freeing code
@@ -1174,17 +1176,18 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, int64_t *se
11741176
extern "C"
11751177
JL_DLLEXPORT jl_value_t *jl_get_dobj_data(uint64_t fptr)
11761178
{
1179+
jl_tls_states_t *ptls = jl_get_ptls_states();
11771180
// Used by Gallium.jl
11781181
const object::ObjectFile *object = NULL;
11791182
DIContext *context;
11801183
int64_t slide, section_slide;
1181-
int8_t gc_state = jl_gc_safe_enter();
1184+
int8_t gc_state = jl_gc_safe_enter(ptls);
11821185
if (!jl_DI_for_fptr(fptr, NULL, &slide, NULL, &object, NULL))
11831186
if (!jl_dylib_DI_for_fptr(fptr, &object, &context, &slide, &section_slide, false, NULL, NULL, NULL, NULL)) {
1184-
jl_gc_safe_leave(gc_state);
1187+
jl_gc_safe_leave(ptls, gc_state);
11851188
return jl_nothing;
11861189
}
1187-
jl_gc_safe_leave(gc_state);
1190+
jl_gc_safe_leave(ptls, gc_state);
11881191
if (object == NULL)
11891192
return jl_nothing;
11901193
return (jl_value_t*)jl_ptr_to_array_1d((jl_value_t*)jl_array_uint8_type,
@@ -1195,8 +1198,9 @@ JL_DLLEXPORT jl_value_t *jl_get_dobj_data(uint64_t fptr)
11951198
extern "C"
11961199
JL_DLLEXPORT uint64_t jl_get_section_start(uint64_t fptr)
11971200
{
1201+
jl_tls_states_t *ptls = jl_get_ptls_states();
11981202
// Used by Gallium.jl
1199-
int8_t gc_state = jl_gc_safe_enter();
1203+
int8_t gc_state = jl_gc_safe_enter(ptls);
12001204
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap();
12011205
std::map<size_t, ObjectInfo, revcomp>::iterator fit = objmap.lower_bound(fptr);
12021206

@@ -1212,7 +1216,7 @@ JL_DLLEXPORT uint64_t jl_get_section_start(uint64_t fptr)
12121216
}
12131217
}
12141218
uv_rwlock_rdunlock(&threadsafe);
1215-
jl_gc_safe_leave(gc_state);
1219+
jl_gc_safe_leave(ptls, gc_state);
12161220
return ret;
12171221
}
12181222

src/gc-debug.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,10 @@ static void gc_verify_track(void)
172172
clear_mark(GC_CLEAN);
173173
pre_mark();
174174
gc_mark_object_list(&to_finalize, 0);
175-
gc_mark_object_list(&finalizer_list, 0);
175+
for (int i = 0;i < jl_n_threads;i++) {
176+
jl_tls_states_t *ptls2 = jl_all_tls_states[i];
177+
gc_mark_object_list(&ptls2->finalizers, 0);
178+
}
176179
gc_mark_object_list(&finalizer_list_marked, 0);
177180
visit_mark_stack();
178181
if (lostval_parents.len == 0) {
@@ -215,7 +218,10 @@ void gc_verify(void)
215218
gc_verifying = 1;
216219
pre_mark();
217220
gc_mark_object_list(&to_finalize, 0);
218-
gc_mark_object_list(&finalizer_list, 0);
221+
for (int i = 0;i < jl_n_threads;i++) {
222+
jl_tls_states_t *ptls2 = jl_all_tls_states[i];
223+
gc_mark_object_list(&ptls2->finalizers, 0);
224+
}
219225
gc_mark_object_list(&finalizer_list_marked, 0);
220226
visit_mark_stack();
221227
int clean_len = bits_save[GC_CLEAN].len;

0 commit comments

Comments
 (0)