Skip to content

Commit 6349257

Browse files
authored
Merge branch 'master' into repl-autocomplete-fixes
2 parents 9f79b5b + 7e69710 commit 6349257

File tree

8 files changed

+162
-121
lines changed

8 files changed

+162
-121
lines changed

Diff for: base/binaryplatforms.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ function Base.parse(::Type{Platform}, triplet::String; validate_strict::Bool = f
751751
end
752752
os_version = nothing
753753
if os == "macos"
754-
os_version = extract_os_version("macos", r".*darwin([\d\.]+)"sa)
754+
os_version = extract_os_version("macos", r".*darwin([\d.]+)"sa)
755755
end
756756
if os == "freebsd"
757757
os_version = extract_os_version("freebsd", r".*freebsd([\d.]+)"sa)

Diff for: src/gc-interface.h

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define JL_GC_INTERFACE_H
99

1010
#include "dtypes.h"
11+
#include "julia_atomics.h"
1112

1213
#ifdef __cplusplus
1314
extern "C" {
@@ -17,6 +18,7 @@ struct _jl_tls_states_t;
1718
struct _jl_value_t;
1819
struct _jl_weakref_t;
1920
struct _jl_datatype_t;
21+
struct _jl_genericmemory_t;
2022

2123
// ========================================================================= //
2224
// GC Metrics
@@ -253,6 +255,19 @@ STATIC_INLINE void jl_gc_wb_knownold(const void *parent, const void *ptr) JL_NOT
253255
STATIC_INLINE void jl_gc_multi_wb(const void *parent,
254256
const struct _jl_value_t *ptr) JL_NOTSAFEPOINT;
255257

258+
// Write-barrier function that must be used after copying fields of elements of genericmemory objects
259+
// into another. It should be semantically equivalent to triggering multiple write barriers – one
260+
// per field of the object being copied, but may be special-cased for performance reasons.
261+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_ptr(const struct _jl_value_t *owner, struct _jl_genericmemory_t *src, char* src_p,
262+
size_t n, struct _jl_datatype_t *dt) JL_NOTSAFEPOINT;
263+
264+
// Similar to jl_gc_wb_genericmemory_copy but must be used when copying *boxed* elements of a genericmemory
265+
// object. Note that this barrier also performs the copying unlike jl_gc_wb_genericmemory_copy_ptr.
266+
// The parameters src_p, dest_p and n will be modified and will contain information about
267+
// the *uncopied* data after performing this barrier, and will be copied using memmove_refs.
268+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_boxed(const struct _jl_value_t *owner, _Atomic(void*) * dest_p,
269+
struct _jl_genericmemory_t *src, _Atomic(void*) * src_p,
270+
size_t* n) JL_NOTSAFEPOINT;
256271
#ifdef __cplusplus
257272
}
258273
#endif

Diff for: src/genericmemory.c

+2-41
Original file line numberDiff line numberDiff line change
@@ -235,36 +235,7 @@ JL_DLLEXPORT void jl_genericmemory_copyto(jl_genericmemory_t *dest, char* destda
235235
_Atomic(void*) * dest_p = (_Atomic(void*)*)destdata;
236236
_Atomic(void*) * src_p = (_Atomic(void*)*)srcdata;
237237
jl_value_t *owner = jl_genericmemory_owner(dest);
238-
if (__unlikely(jl_astaggedvalue(owner)->bits.gc == GC_OLD_MARKED)) {
239-
jl_value_t *src_owner = jl_genericmemory_owner(src);
240-
ssize_t done = 0;
241-
if (jl_astaggedvalue(src_owner)->bits.gc != GC_OLD_MARKED) {
242-
if (dest_p < src_p || dest_p > src_p + n) {
243-
for (; done < n; done++) { // copy forwards
244-
void *val = jl_atomic_load_relaxed(src_p + done);
245-
jl_atomic_store_release(dest_p + done, val);
246-
// `val` is young or old-unmarked
247-
if (val && !(jl_astaggedvalue(val)->bits.gc & GC_MARKED)) {
248-
jl_gc_queue_root(owner);
249-
break;
250-
}
251-
}
252-
src_p += done;
253-
dest_p += done;
254-
} else {
255-
for (; done < n; done++) { // copy backwards
256-
void *val = jl_atomic_load_relaxed(src_p + n - done - 1);
257-
jl_atomic_store_release(dest_p + n - done - 1, val);
258-
// `val` is young or old-unmarked
259-
if (val && !(jl_astaggedvalue(val)->bits.gc & GC_MARKED)) {
260-
jl_gc_queue_root(owner);
261-
break;
262-
}
263-
}
264-
}
265-
n -= done;
266-
}
267-
}
238+
jl_gc_wb_genericmemory_copy_boxed(owner, dest_p, src, src_p, &n);
268239
return memmove_refs(dest_p, src_p, n);
269240
}
270241
size_t elsz = layout->size;
@@ -280,17 +251,7 @@ JL_DLLEXPORT void jl_genericmemory_copyto(jl_genericmemory_t *dest, char* destda
280251
if (layout->first_ptr != -1) {
281252
memmove_refs((_Atomic(void*)*)destdata, (_Atomic(void*)*)srcdata, n * elsz / sizeof(void*));
282253
jl_value_t *owner = jl_genericmemory_owner(dest);
283-
if (__unlikely(jl_astaggedvalue(owner)->bits.gc == GC_OLD_MARKED)) {
284-
jl_value_t *src_owner = jl_genericmemory_owner(src);
285-
if (jl_astaggedvalue(src_owner)->bits.gc != GC_OLD_MARKED) {
286-
dt = (jl_datatype_t*)jl_tparam1(dt);
287-
for (size_t done = 0; done < n; done++) { // copy forwards
288-
char* s = (char*)src_p+done*elsz;
289-
if (*((jl_value_t**)s+layout->first_ptr) != NULL)
290-
jl_gc_queue_multiroot(owner, s, dt);
291-
}
292-
}
293-
}
254+
jl_gc_wb_genericmemory_copy_ptr(owner, src, src_p, n, dt);
294255
}
295256
else {
296257
memmove(destdata, srcdata, n * elsz);

Diff for: src/julia.h

+93-37
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ typedef struct {
162162
// jl_value_t *data[];
163163
} jl_svec_t;
164164

165-
JL_EXTENSION typedef struct {
165+
JL_EXTENSION typedef struct _jl_genericmemory_t {
166166
JL_DATA_TYPE
167167
size_t length;
168168
void *ptr;
@@ -1182,38 +1182,6 @@ JL_DLLEXPORT void jl_free_stack(void *stkbuf, size_t bufsz);
11821182
// thread-local allocator of the current thread.
11831183
JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value);
11841184

1185-
// GC write barriers
1186-
1187-
STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT
1188-
{
1189-
// parent and ptr isa jl_value_t*
1190-
if (__unlikely(jl_astaggedvalue(parent)->bits.gc == 3 /* GC_OLD_MARKED */ && // parent is old and not in remset
1191-
(jl_astaggedvalue(ptr)->bits.gc & 1 /* GC_MARKED */) == 0)) // ptr is young
1192-
jl_gc_queue_root((jl_value_t*)parent);
1193-
}
1194-
1195-
STATIC_INLINE void jl_gc_wb_back(const void *ptr) JL_NOTSAFEPOINT // ptr isa jl_value_t*
1196-
{
1197-
// if ptr is old
1198-
if (__unlikely(jl_astaggedvalue(ptr)->bits.gc == 3 /* GC_OLD_MARKED */)) {
1199-
jl_gc_queue_root((jl_value_t*)ptr);
1200-
}
1201-
}
1202-
1203-
STATIC_INLINE void jl_gc_multi_wb(const void *parent, const jl_value_t *ptr) JL_NOTSAFEPOINT
1204-
{
1205-
// 3 == GC_OLD_MARKED
1206-
// ptr is an immutable object
1207-
if (__likely(jl_astaggedvalue(parent)->bits.gc != 3))
1208-
return; // parent is young or in remset
1209-
if (__likely(jl_astaggedvalue(ptr)->bits.gc == 3))
1210-
return; // ptr is old and not in remset (thus it does not point to young)
1211-
jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(ptr);
1212-
const jl_datatype_layout_t *ly = dt->layout;
1213-
if (ly->npointers)
1214-
jl_gc_queue_multiroot((jl_value_t*)parent, ptr, dt);
1215-
}
1216-
12171185
JL_DLLEXPORT void jl_gc_safepoint(void);
12181186
JL_DLLEXPORT int jl_safepoint_suspend_thread(int tid, int waitstate);
12191187
JL_DLLEXPORT void jl_safepoint_suspend_all_threads(struct _jl_task_t *ct);
@@ -1332,6 +1300,94 @@ STATIC_INLINE jl_value_t *jl_genericmemory_ptr_set(
13321300
}
13331301
#endif
13341302

1303+
// GC write barriers
1304+
1305+
STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT
1306+
{
1307+
// parent and ptr isa jl_value_t*
1308+
if (__unlikely(jl_astaggedvalue(parent)->bits.gc == 3 /* GC_OLD_MARKED */ && // parent is old and not in remset
1309+
(jl_astaggedvalue(ptr)->bits.gc & 1 /* GC_MARKED */) == 0)) // ptr is young
1310+
jl_gc_queue_root((jl_value_t*)parent);
1311+
}
1312+
1313+
STATIC_INLINE void jl_gc_wb_back(const void *ptr) JL_NOTSAFEPOINT // ptr isa jl_value_t*
1314+
{
1315+
// if ptr is old
1316+
if (__unlikely(jl_astaggedvalue(ptr)->bits.gc == 3 /* GC_OLD_MARKED */)) {
1317+
jl_gc_queue_root((jl_value_t*)ptr);
1318+
}
1319+
}
1320+
1321+
STATIC_INLINE void jl_gc_multi_wb(const void *parent, const jl_value_t *ptr) JL_NOTSAFEPOINT
1322+
{
1323+
// 3 == GC_OLD_MARKED
1324+
// ptr is an immutable object
1325+
if (__likely(jl_astaggedvalue(parent)->bits.gc != 3))
1326+
return; // parent is young or in remset
1327+
if (__likely(jl_astaggedvalue(ptr)->bits.gc == 3))
1328+
return; // ptr is old and not in remset (thus it does not point to young)
1329+
jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(ptr);
1330+
const jl_datatype_layout_t *ly = dt->layout;
1331+
if (ly->npointers)
1332+
jl_gc_queue_multiroot((jl_value_t*)parent, ptr, dt);
1333+
}
1334+
1335+
STATIC_INLINE jl_value_t *jl_genericmemory_owner(jl_genericmemory_t *m JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
1336+
1337+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_boxed(const jl_value_t *dest_owner, _Atomic(void*) * dest_p,
1338+
jl_genericmemory_t *src, _Atomic(void*) * src_p,
1339+
size_t* n) JL_NOTSAFEPOINT
1340+
{
1341+
if (__unlikely(jl_astaggedvalue(dest_owner)->bits.gc == 3 /* GC_OLD_MARKED */ )) {
1342+
jl_value_t *src_owner = jl_genericmemory_owner(src);
1343+
size_t done = 0;
1344+
if (jl_astaggedvalue(src_owner)->bits.gc != 3 /* GC_OLD_MARKED */) {
1345+
if (dest_p < src_p || dest_p > src_p + (*n)) {
1346+
for (; done < (*n); done++) { // copy forwards
1347+
void *val = jl_atomic_load_relaxed(src_p + done);
1348+
jl_atomic_store_release(dest_p + done, val);
1349+
// `val` is young or old-unmarked
1350+
if (val && !(jl_astaggedvalue(val)->bits.gc & 1 /* GC_MARKED */)) {
1351+
jl_gc_queue_root(dest_owner);
1352+
break;
1353+
}
1354+
}
1355+
src_p += done;
1356+
dest_p += done;
1357+
}
1358+
else {
1359+
for (; done < (*n); done++) { // copy backwards
1360+
void *val = jl_atomic_load_relaxed(src_p + (*n) - done - 1);
1361+
jl_atomic_store_release(dest_p + (*n) - done - 1, val);
1362+
// `val` is young or old-unmarked
1363+
if (val && !(jl_astaggedvalue(val)->bits.gc & 1 /* GC_MARKED */)) {
1364+
jl_gc_queue_root(dest_owner);
1365+
break;
1366+
}
1367+
}
1368+
}
1369+
(*n) -= done;
1370+
}
1371+
}
1372+
}
1373+
1374+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_ptr(const jl_value_t *owner, jl_genericmemory_t *src, char* src_p,
1375+
size_t n, jl_datatype_t *dt) JL_NOTSAFEPOINT
1376+
{
1377+
if (__unlikely(jl_astaggedvalue(owner)->bits.gc == 3 /* GC_OLD_MARKED */)) {
1378+
jl_value_t *src_owner = jl_genericmemory_owner(src);
1379+
size_t elsz = dt->layout->size;
1380+
if (jl_astaggedvalue(src_owner)->bits.gc != 3 /* GC_OLD_MARKED */) {
1381+
dt = (jl_datatype_t*)jl_tparam1(dt);
1382+
for (size_t done = 0; done < n; done++) { // copy forwards
1383+
char* s = (char*)src_p+done*elsz;
1384+
if (*((jl_value_t**)s+dt->layout->first_ptr) != NULL)
1385+
jl_gc_queue_multiroot(owner, s, dt);
1386+
}
1387+
}
1388+
}
1389+
}
1390+
13351391
STATIC_INLINE uint8_t jl_memory_uint8_ref(void *m, size_t i) JL_NOTSAFEPOINT
13361392
{
13371393
jl_genericmemory_t *m_ = (jl_genericmemory_t*)m;
@@ -2077,10 +2133,10 @@ JL_DLLEXPORT jl_value_t *jl_checked_assignonce(jl_binding_t *b, jl_module_t *mod
20772133
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val(jl_binding_t *b JL_ROOTING_ARGUMENT, jl_module_t *mod, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);
20782134
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val2(jl_binding_t *b JL_ROOTING_ARGUMENT, jl_module_t *mod, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, enum jl_partition_kind);
20792135
JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from);
2080-
JL_DLLEXPORT void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s);
2081-
JL_DLLEXPORT void jl_module_use_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname);
2082-
JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s);
2083-
JL_DLLEXPORT void jl_module_import_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname);
2136+
JL_DLLEXPORT void jl_module_use(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s);
2137+
JL_DLLEXPORT void jl_module_use_as(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname);
2138+
JL_DLLEXPORT void jl_module_import(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s);
2139+
JL_DLLEXPORT void jl_module_import_as(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname);
20842140
JL_DLLEXPORT void jl_module_public(jl_module_t *from, jl_sym_t *s, int exported);
20852141
JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s);
20862142
JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var);

Diff for: src/module.c

+11-11
Original file line numberDiff line numberDiff line change
@@ -888,11 +888,11 @@ JL_DLLEXPORT void check_safe_import_from(jl_module_t *m)
888888
}
889889

890890
// NOTE: we use explici since explicit is a C++ keyword
891-
static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname, jl_sym_t *s, int explici)
891+
static void module_import_(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *asname, jl_sym_t *s, int explici)
892892
{
893893
check_safe_import_from(from);
894894
jl_binding_t *b = jl_get_binding(from, s);
895-
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
895+
jl_binding_partition_t *bpart = jl_get_binding_partition(b, ct->world_age);
896896
if (b->deprecated) {
897897
if (jl_get_binding_value(b) == jl_nothing) {
898898
// silently skip importing deprecated values assigned to nothing (to allow later mutation)
@@ -915,7 +915,7 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname,
915915

916916
jl_binding_t *ownerb = b;
917917
jl_binding_partition_t *ownerbpart = bpart;
918-
jl_walk_binding_inplace(&ownerb, &ownerbpart, jl_current_task->world_age);
918+
jl_walk_binding_inplace(&ownerb, &ownerbpart, ct->world_age);
919919

920920
if (jl_bkind_is_some_guard(jl_binding_kind(ownerbpart))) {
921921
jl_printf(JL_STDERR,
@@ -965,24 +965,24 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname,
965965
JL_UNLOCK(&world_counter_lock);
966966
}
967967

968-
JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s)
968+
JL_DLLEXPORT void jl_module_import(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s)
969969
{
970-
module_import_(to, from, s, s, 1);
970+
module_import_(ct, to, from, s, s, 1);
971971
}
972972

973-
JL_DLLEXPORT void jl_module_import_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
973+
JL_DLLEXPORT void jl_module_import_as(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
974974
{
975-
module_import_(to, from, asname, s, 1);
975+
module_import_(ct, to, from, asname, s, 1);
976976
}
977977

978-
JL_DLLEXPORT void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s)
978+
JL_DLLEXPORT void jl_module_use(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s)
979979
{
980-
module_import_(to, from, s, s, 0);
980+
module_import_(ct, to, from, s, s, 0);
981981
}
982982

983-
JL_DLLEXPORT void jl_module_use_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
983+
JL_DLLEXPORT void jl_module_use_as(jl_task_t *ct, jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
984984
{
985-
module_import_(to, from, asname, s, 0);
985+
module_import_(ct, to, from, asname, s, 0);
986986
}
987987

988988
void jl_add_usings_backedge(jl_module_t *from, jl_module_t *to)

Diff for: src/staticdata.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,10 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t
13441344
arraylist_push(&s->relocs_list, (void*)(reloc_offset + offsetof(jl_module_t, usings_backedges)));
13451345
arraylist_push(&s->relocs_list, (void*)backref_id(s, m->usings_backedges, s->link_ids_relocs));
13461346

1347+
// After reload, everything that has happened in this process happened semantically at
1348+
// (for .incremental) or before jl_require_world, so reset this flag.
1349+
jl_atomic_store_relaxed(&newm->export_set_changed_since_require_world, 0);
1350+
13471351
// write out the usings list
13481352
memset(&newm->usings._space, 0, sizeof(newm->usings._space));
13491353
if (m->usings.items == &m->usings._space[0]) {
@@ -1372,6 +1376,7 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t
13721376
newm->usings.items = (void**)tot;
13731377
arraylist_push(&s->relocs_list, (void*)(reloc_offset + offsetof(jl_module_t, usings.items)));
13741378
arraylist_push(&s->relocs_list, (void*)(((uintptr_t)DataRef << RELOC_TAG_OFFSET) + item));
1379+
newm = NULL; // `write_*(s->s)` below may invalidate `newm`, so defensively set it to NULL
13751380
size_t i;
13761381
for (i = 0; i < module_usings_length(m); i++) {
13771382
struct _jl_module_using *data = module_usings_getidx(m, i);
@@ -1395,10 +1400,6 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t
13951400
}
13961401
}
13971402
assert(ios_pos(s->s) - reloc_offset == tot);
1398-
1399-
// After reload, everything that has happened in this process happened semantically at
1400-
// (for .incremental) or before jl_require_world, so reset this flag.
1401-
jl_atomic_store_relaxed(&newm->export_set_changed_since_require_world, 0);
14021403
}
14031404

14041405
static void record_memoryref(jl_serializer_state *s, size_t reloc_offset, jl_genericmemoryref_t ref) {

0 commit comments

Comments
 (0)