Skip to content

Commit e19c0da

Browse files
committed
Don't pin objects permanently in engine.cpp
1 parent 1956405 commit e19c0da

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

src/engine.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,24 @@ struct ReservationInfo {
1818

1919
struct InferKey {
2020
jl_method_instance_t *mi = nullptr;
21-
jl_pinned_ref(jl_value_t) owner = jl_pinned_ref_assume(jl_value_t, nullptr);
21+
jl_value_t *owner = nullptr;
2222
};
2323

2424
template<> struct llvm::DenseMapInfo<InferKey> {
2525
using FirstInfo = DenseMapInfo<jl_method_instance_t*>;
2626
using SecondInfo = DenseMapInfo<jl_value_t*>;
2727

2828
static inline InferKey getEmptyKey() {
29-
return InferKey{FirstInfo::getEmptyKey(),
30-
jl_pinned_ref_assume(jl_value_t, SecondInfo::getEmptyKey())};
29+
return InferKey{FirstInfo::getEmptyKey(), SecondInfo::getEmptyKey()};
3130
}
3231

3332
static inline InferKey getTombstoneKey() {
34-
return InferKey{FirstInfo::getTombstoneKey(),
35-
jl_pinned_ref_assume(jl_value_t, SecondInfo::getTombstoneKey())};
33+
return InferKey{FirstInfo::getTombstoneKey(), SecondInfo::getTombstoneKey()};
3634
}
3735

3836
static unsigned getHashValue(const InferKey& PairVal) {
3937
return detail::combineHashValue(FirstInfo::getHashValue(PairVal.mi),
40-
SecondInfo::getHashValue(jl_pinned_ref_get(PairVal.owner)));
38+
SecondInfo::getHashValue(PairVal.owner));
4139
}
4240

4341
static bool isEqual(const InferKey &LHS, const InferKey &RHS) {
@@ -66,22 +64,26 @@ jl_code_instance_t *jl_engine_reserve(jl_method_instance_t *m, jl_value_t *owner
6664
auto tid = jl_atomic_load_relaxed(&ct->tid);
6765
if (([tid, m, owner, ci] () -> bool { // necessary scope block / lambda for unique_lock
6866
jl_unique_gcsafe_lock lock(engine_lock);
69-
InferKey key{m, jl_pinned_ref_create(jl_value_t, owner)};
67+
arraylist_push(&objects_pinned_by_inference_engine, owner);
68+
InferKey key{m, owner};
7069
if ((signed)Awaiting.size() < tid + 1)
7170
Awaiting.resize(tid + 1);
7271
while (1) {
7372
auto record = Reservations.find(key);
7473
if (record == Reservations.end()) {
7574
Reservations[key] = ReservationInfo{tid, ci};
75+
arraylist_pop(&objects_pinned_by_inference_engine);
7676
return false;
7777
}
7878
// before waiting, need to run deadlock/cycle detection
7979
// there is a cycle if the thread holding our lease is blocked
8080
// and waiting for (transitively) any lease that is held by this thread
8181
auto wait_tid = record->second.tid;
8282
while (1) {
83-
if (wait_tid == tid)
83+
if (wait_tid == tid) {
84+
arraylist_pop(&objects_pinned_by_inference_engine);
8485
return true;
86+
}
8587
if ((signed)Awaiting.size() <= wait_tid)
8688
break; // no cycle, since it is running (and this should be unreachable)
8789
auto key2 = Awaiting[wait_tid];
@@ -97,6 +99,7 @@ jl_code_instance_t *jl_engine_reserve(jl_method_instance_t *m, jl_value_t *owner
9799
lock.wait(engine_wait);
98100
Awaiting[tid] = InferKey{};
99101
}
102+
arraylist_pop(&objects_pinned_by_inference_engine);
100103
})())
101104
ct->ptls->engine_nqueued--;
102105
JL_GC_POP();
@@ -106,7 +109,7 @@ jl_code_instance_t *jl_engine_reserve(jl_method_instance_t *m, jl_value_t *owner
106109
int jl_engine_hasreserved(jl_method_instance_t *m, jl_value_t *owner)
107110
{
108111
jl_task_t *ct = jl_current_task;
109-
InferKey key = {m, jl_pinned_ref_create(jl_value_t, owner)};
112+
InferKey key = {m, owner};
110113
std::unique_lock lock(engine_lock);
111114
auto record = Reservations.find(key);
112115
return record != Reservations.end() && record->second.tid == jl_atomic_load_relaxed(&ct->tid);
@@ -139,7 +142,7 @@ void jl_engine_fulfill(jl_code_instance_t *ci, jl_code_info_t *src)
139142
{
140143
jl_task_t *ct = jl_current_task;
141144
std::unique_lock lock(engine_lock);
142-
auto record = Reservations.find(InferKey{jl_get_ci_mi(ci), jl_pinned_ref_create(jl_value_t, ci->owner)});
145+
auto record = Reservations.find(InferKey{jl_get_ci_mi(ci), ci->owner});
143146
if (record == Reservations.end() || record->second.ci != ci)
144147
return;
145148
assert(jl_atomic_load_relaxed(&ct->tid) == record->second.tid);

src/gc-common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,8 @@ JL_DLLEXPORT int jl_gc_enable(int on)
687687
// MISC
688688
// =========================================================================== //
689689

690+
arraylist_t objects_pinned_by_inference_engine;
691+
690692
JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value)
691693
{
692694
jl_ptls_t ptls = jl_current_task->ptls;

src/gc-mmtk.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern void mmtk_post_alloc(void* mutator, void* refer, size_t bytes, int alloca
5555
extern void mmtk_store_obj_size_c(void* obj, size_t size);
5656
extern bool mmtk_is_pinned(void* obj);
5757
extern unsigned char mmtk_pin_object(void* obj);
58+
extern unsigned char mmtk_unpin_object(void* obj);
5859
extern bool mmtk_is_reachable_object(void* obj);
5960
extern bool mmtk_is_live_object(void* obj);
6061
extern bool mmtk_is_object_pinned(void* obj);
@@ -71,8 +72,9 @@ void jl_gc_init(void) {
7172
// TODO: use jl_options.heap_size_hint to set MMTk's fixed heap size? (see issue: https://github.com/mmtk/mmtk-julia/issues/167)
7273
JL_MUTEX_INIT(&finalizers_lock, "finalizers_lock");
7374

74-
jl_set_check_alive_fn(mmtk_is_reachable_object);
75+
jl_set_check_alive_type(mmtk_is_reachable_object);
7576

77+
arraylist_new(&objects_pinned_by_inference_engine, 0);
7678
arraylist_new(&to_finalize, 0);
7779
arraylist_new(&finalizer_list_marked, 0);
7880
gc_num.interval = default_collect_interval;
@@ -247,6 +249,24 @@ JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t collection) {
247249
// print_fragmentation();
248250
}
249251

252+
void gc_pin_objects_from_inference_engine(arraylist_t *objects_pinned_by_call)
253+
{
254+
for (size_t i = 0; i < objects_pinned_by_inference_engine.len; i++) {
255+
void *obj = objects_pinned_by_inference_engine.items[i];
256+
unsigned char got_pinned = mmtk_pin_object(obj);
257+
if (got_pinned) {
258+
arraylist_push(objects_pinned_by_call, obj);
259+
}
260+
}
261+
}
262+
263+
void gc_unpin_objects_from_inference_engine(arraylist_t *objects_pinned_by_call)
264+
{
265+
for (size_t i = 0; i < objects_pinned_by_call->len; i++) {
266+
void *obj = objects_pinned_by_call->items[i];
267+
mmtk_unpin_object(obj);
268+
}
269+
}
250270

251271
// Based on jl_gc_collect from gc-stock.c
252272
// called when stopping the thread in `mmtk_block_for_gc`
@@ -310,7 +330,12 @@ JL_DLLEXPORT void jl_gc_prepare_to_collect(void)
310330
jl_gc_notify_thread_yield(ptls, NULL);
311331
JL_LOCK_NOGC(&finalizers_lock); // all the other threads are stopped, so this does not make sense, right? otherwise, failing that, this seems like plausibly a deadlock
312332
#ifndef __clang_gcanalyzer__
333+
arraylist_t objects_pinned_by_call;
334+
arraylist_new(&objects_pinned_by_call, 0);
335+
gc_pin_objects_from_inference_engine(&objects_pinned_by_call);
313336
mmtk_block_thread_for_gc();
337+
gc_unpin_objects_from_inference_engine(&objects_pinned_by_call);
338+
arraylist_free(&objects_pinned_by_call);
314339
#endif
315340
JL_UNLOCK_NOGC(&finalizers_lock);
316341
}

src/gc-pinning-log.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ struct coalesced_pinning_log_t {
7272
struct pinning_log_t {
7373
linear_pinning_log_t linear_log;
7474
coalesced_pinning_log_t coalesced_log;
75-
check_alive_fn is_alive;
75+
check_alive_fn_type is_alive;
7676
std::mutex mu;
7777
pinning_log_entry_t *alloc_pinning_log_entry(void *pinned_object) {
7878
pinning_log_entry_t *e;
@@ -92,7 +92,7 @@ struct pinning_log_t {
9292
linear_log.reset_log_buffer();
9393
mu.unlock();
9494
}
95-
void set_check_alive_fn(check_alive_fn fn) {
95+
void set_check_alive_fn_type(check_alive_fn_type fn) {
9696
mu.lock();
9797
is_alive = fn;
9898
mu.unlock();
@@ -157,8 +157,8 @@ extern "C" {
157157

158158
int pinning_log_enabled;
159159

160-
JL_DLLEXPORT void jl_set_check_alive_fn(check_alive_fn fn) {
161-
pinning_log.set_check_alive_fn(fn);
160+
JL_DLLEXPORT void jl_set_check_alive_type(check_alive_fn_type fn) {
161+
pinning_log.set_check_alive_fn_type(fn);
162162
}
163163
JL_DLLEXPORT void jl_enable_pinning_log(void) {
164164
pinning_log_enabled = 1;

src/julia.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,8 +1346,9 @@ JL_DLLEXPORT JL_CONST_FUNC jl_gcframe_t **(jl_get_pgcstack)(void) JL_GLOBALLY_RO
13461346

13471347
// object pinning ------------------------------------------------------------
13481348

1349-
typedef bool (*check_alive_fn)(void *);
1350-
JL_DLLEXPORT void jl_set_check_alive_fn(check_alive_fn fn);
1349+
extern arraylist_t objects_pinned_by_inference_engine;
1350+
typedef bool (*check_alive_fn_type)(void *);
1351+
JL_DLLEXPORT void jl_set_check_alive_type(check_alive_fn_type fn);
13511352
JL_DLLEXPORT void jl_log_pinning_event(void *pinned_object, const char *filename, int lineno);
13521353
JL_DLLEXPORT void jl_print_pinning_log(void);
13531354

@@ -1396,14 +1397,14 @@ class pinned_ref {
13961397
explicit pinned_ref(void* p) : ptr(static_cast<T*>(p)) {}
13971398
operator void*() const { return ptr; }
13981399
T* get() const { return ptr; }
1399-
static pinned_ref create(void* p) { OBJ_PIN(p); return pinned_ref(p); }
1400+
static pinned_ref create(void* p, const char *file, int line) { jl_log_pinning_event(p, file, line); jl_gc_pin_object(p); return pinned_ref(p); }
14001401
static pinned_ref assume(void* p) { return pinned_ref(p); }
14011402
};
14021403

14031404
// Redefine macros for C++ to use the template version
14041405
#define jl_pinned_ref(T) pinned_ref<T>
14051406
#define jl_pinned_ref_assume(T, ptr) pinned_ref<T>::assume(ptr)
1406-
#define jl_pinned_ref_create(T, ptr) pinned_ref<T>::create(ptr)
1407+
#define jl_pinned_ref_create(T, ptr) pinned_ref<T>::create(ptr, __FILE__, __LINE__)
14071408
#define jl_pinned_ref_get(ref) (ref).get()
14081409

14091410
#else

0 commit comments

Comments
 (0)