Skip to content

Commit 9e1f5dc

Browse files
authored
Merge branch 'master' into prevent_stack_overflow_in_type_promotion
2 parents 4766ec7 + f7b986d commit 9e1f5dc

File tree

5 files changed

+203
-94
lines changed

5 files changed

+203
-94
lines changed

src/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ UV_HEADERS += uv/*.h
123123
endif
124124
PUBLIC_HEADERS := $(BUILDDIR)/julia_version.h $(wildcard $(SRCDIR)/support/*.h) $(addprefix $(SRCDIR)/,work-stealing-queue.h gc-interface.h gc-tls-common.h julia.h julia_assert.h julia_threads.h julia_fasttls.h julia_locks.h julia_atomics.h jloptions.h)
125125
ifneq (${MMTK_PLAN},None)
126-
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-mmtk.h)
126+
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-mmtk.h gc-wb-mmtk.h)
127127
else
128-
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-stock.h)
128+
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,gc-tls-stock.h gc-wb-stock.h)
129129
endif
130130
ifeq ($(OS),WINNT)
131131
PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,win32_ucontext.h)

src/gc-wb-mmtk.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
// ========================================================================= //
4+
// Runtime Write-Barriers
5+
// ========================================================================= //
6+
7+
#ifndef JL_GC_WB_H
8+
#define JL_GC_WB_H
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
extern void mmtk_object_reference_write_post(void* mutator, const void* parent, const void* ptr);
15+
extern void mmtk_object_reference_write_slow(void* mutator, const void* parent, const void* ptr);
16+
extern const void* MMTK_SIDE_LOG_BIT_BASE_ADDRESS;
17+
18+
#define MMTK_OBJECT_BARRIER (1)
19+
// Stickyimmix needs write barrier. Immix does not need write barrier.
20+
#ifdef MMTK_PLAN_IMMIX
21+
#define MMTK_NEEDS_WRITE_BARRIER (0)
22+
#endif
23+
#ifdef MMTK_PLAN_STICKYIMMIX
24+
#define MMTK_NEEDS_WRITE_BARRIER (1)
25+
#endif
26+
27+
// Directly call into MMTk for write barrier (debugging only)
28+
STATIC_INLINE void mmtk_gc_wb_full(const void *parent, const void *ptr) JL_NOTSAFEPOINT
29+
{
30+
jl_task_t *ct = jl_current_task;
31+
jl_ptls_t ptls = ct->ptls;
32+
mmtk_object_reference_write_post(&ptls->gc_tls.mmtk_mutator, parent, ptr);
33+
}
34+
35+
// Inlined fastpath
36+
STATIC_INLINE void mmtk_gc_wb_fast(const void *parent, const void *ptr) JL_NOTSAFEPOINT
37+
{
38+
if (MMTK_NEEDS_WRITE_BARRIER == MMTK_OBJECT_BARRIER) {
39+
intptr_t addr = (intptr_t) (void*) parent;
40+
uint8_t* meta_addr = (uint8_t*) (MMTK_SIDE_LOG_BIT_BASE_ADDRESS) + (addr >> 6);
41+
intptr_t shift = (addr >> 3) & 0b111;
42+
uint8_t byte_val = *meta_addr;
43+
if (((byte_val >> shift) & 1) == 1) {
44+
jl_task_t *ct = jl_current_task;
45+
jl_ptls_t ptls = ct->ptls;
46+
mmtk_object_reference_write_slow(&ptls->gc_tls.mmtk_mutator, parent, ptr);
47+
}
48+
}
49+
}
50+
51+
STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT
52+
{
53+
mmtk_gc_wb_fast(parent, ptr);
54+
}
55+
56+
STATIC_INLINE void jl_gc_wb_back(const void *ptr) JL_NOTSAFEPOINT // ptr isa jl_value_t*
57+
{
58+
mmtk_gc_wb_fast(ptr, (void*)0);
59+
}
60+
61+
STATIC_INLINE void jl_gc_multi_wb(const void *parent, const jl_value_t *ptr) JL_NOTSAFEPOINT
62+
{
63+
mmtk_gc_wb_fast(parent, (void*)0);
64+
}
65+
66+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_boxed(const jl_value_t *dest_owner, _Atomic(void*) * dest_p,
67+
jl_genericmemory_t *src, _Atomic(void*) * src_p,
68+
size_t* n) JL_NOTSAFEPOINT
69+
{
70+
mmtk_gc_wb_fast(dest_owner, (void*)0);
71+
}
72+
73+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_ptr(const jl_value_t *owner, jl_genericmemory_t *src, char* src_p,
74+
size_t n, jl_datatype_t *dt) JL_NOTSAFEPOINT
75+
{
76+
mmtk_gc_wb_fast(owner, (void*)0);
77+
}
78+
79+
80+
#ifdef __cplusplus
81+
}
82+
#endif
83+
84+
#endif

src/gc-wb-stock.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
// ========================================================================= //
4+
// Runtime Write-Barriers
5+
// ========================================================================= //
6+
7+
#ifndef JL_GC_WB_H
8+
#define JL_GC_WB_H
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT
15+
{
16+
// parent and ptr isa jl_value_t*
17+
if (__unlikely(jl_astaggedvalue(parent)->bits.gc == 3 /* GC_OLD_MARKED */ && // parent is old and not in remset
18+
(jl_astaggedvalue(ptr)->bits.gc & 1 /* GC_MARKED */) == 0)) // ptr is young
19+
jl_gc_queue_root((jl_value_t*)parent);
20+
}
21+
22+
STATIC_INLINE void jl_gc_wb_back(const void *ptr) JL_NOTSAFEPOINT // ptr isa jl_value_t*
23+
{
24+
// if ptr is old
25+
if (__unlikely(jl_astaggedvalue(ptr)->bits.gc == 3 /* GC_OLD_MARKED */)) {
26+
jl_gc_queue_root((jl_value_t*)ptr);
27+
}
28+
}
29+
30+
STATIC_INLINE void jl_gc_multi_wb(const void *parent, const jl_value_t *ptr) JL_NOTSAFEPOINT
31+
{
32+
// 3 == GC_OLD_MARKED
33+
// ptr is an immutable object
34+
if (__likely(jl_astaggedvalue(parent)->bits.gc != 3))
35+
return; // parent is young or in remset
36+
if (__likely(jl_astaggedvalue(ptr)->bits.gc == 3))
37+
return; // ptr is old and not in remset (thus it does not point to young)
38+
jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(ptr);
39+
const jl_datatype_layout_t *ly = dt->layout;
40+
if (ly->npointers)
41+
jl_gc_queue_multiroot((jl_value_t*)parent, ptr, dt);
42+
}
43+
44+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_boxed(const jl_value_t *dest_owner, _Atomic(void*) * dest_p,
45+
jl_genericmemory_t *src, _Atomic(void*) * src_p,
46+
size_t* n) JL_NOTSAFEPOINT
47+
{
48+
if (__unlikely(jl_astaggedvalue(dest_owner)->bits.gc == 3 /* GC_OLD_MARKED */ )) {
49+
jl_value_t *src_owner = jl_genericmemory_owner(src);
50+
size_t done = 0;
51+
if (jl_astaggedvalue(src_owner)->bits.gc != 3 /* GC_OLD_MARKED */) {
52+
if (dest_p < src_p || dest_p > src_p + (*n)) {
53+
for (; done < (*n); done++) { // copy forwards
54+
void *val = jl_atomic_load_relaxed(src_p + done);
55+
jl_atomic_store_release(dest_p + done, val);
56+
// `val` is young or old-unmarked
57+
if (val && !(jl_astaggedvalue(val)->bits.gc & 1 /* GC_MARKED */)) {
58+
jl_gc_queue_root(dest_owner);
59+
break;
60+
}
61+
}
62+
src_p += done;
63+
dest_p += done;
64+
}
65+
else {
66+
for (; done < (*n); done++) { // copy backwards
67+
void *val = jl_atomic_load_relaxed(src_p + (*n) - done - 1);
68+
jl_atomic_store_release(dest_p + (*n) - done - 1, val);
69+
// `val` is young or old-unmarked
70+
if (val && !(jl_astaggedvalue(val)->bits.gc & 1 /* GC_MARKED */)) {
71+
jl_gc_queue_root(dest_owner);
72+
break;
73+
}
74+
}
75+
}
76+
(*n) -= done;
77+
}
78+
}
79+
}
80+
81+
STATIC_INLINE void jl_gc_wb_genericmemory_copy_ptr(const jl_value_t *owner, jl_genericmemory_t *src, char* src_p,
82+
size_t n, jl_datatype_t *dt) JL_NOTSAFEPOINT
83+
{
84+
if (__unlikely(jl_astaggedvalue(owner)->bits.gc == 3 /* GC_OLD_MARKED */)) {
85+
jl_value_t *src_owner = jl_genericmemory_owner(src);
86+
size_t elsz = dt->layout->size;
87+
if (jl_astaggedvalue(src_owner)->bits.gc != 3 /* GC_OLD_MARKED */) {
88+
dt = (jl_datatype_t*)jl_tparam1(dt);
89+
for (size_t done = 0; done < n; done++) { // copy forwards
90+
char* s = (char*)src_p+done*elsz;
91+
if (*((jl_value_t**)s+dt->layout->first_ptr) != NULL)
92+
jl_gc_queue_multiroot(owner, s, dt);
93+
}
94+
}
95+
}
96+
}
97+
98+
#ifdef __cplusplus
99+
}
100+
#endif
101+
102+
#endif

src/julia.h

Lines changed: 13 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666

6767
typedef struct _jl_taggedvalue_t jl_taggedvalue_t;
6868
typedef struct _jl_tls_states_t *jl_ptls_t;
69+
typedef struct _jl_genericmemory_t jl_genericmemory_t;
6970

7071
#ifdef JL_LIBRARY_EXPORTS
7172
#include "uv.h"
@@ -1244,6 +1245,18 @@ STATIC_INLINE jl_value_t *jl_svecset(
12441245
#define jl_array_maxsize(a) (((jl_array_t*)(a))->ref.mem->length)
12451246
#define jl_array_len(a) (jl_array_ndims(a) == 1 ? jl_array_nrows(a) : jl_array_maxsize(a))
12461247

1248+
JL_DLLEXPORT JL_CONST_FUNC jl_gcframe_t **(jl_get_pgcstack)(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT;
1249+
#define jl_current_task (container_of(jl_get_pgcstack(), jl_task_t, gcstack))
1250+
1251+
STATIC_INLINE jl_value_t *jl_genericmemory_owner(jl_genericmemory_t *m JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
1252+
1253+
// write barriers
1254+
#ifndef MMTK_GC
1255+
#include "gc-wb-stock.h"
1256+
#else
1257+
#include "gc-wb-mmtk.h"
1258+
#endif
1259+
12471260
/*
12481261
how - allocation style
12491262
0 = data is inlined
@@ -1300,94 +1313,6 @@ STATIC_INLINE jl_value_t *jl_genericmemory_ptr_set(
13001313
}
13011314
#endif
13021315

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-
13911316
STATIC_INLINE uint8_t jl_memory_uint8_ref(void *m, size_t i) JL_NOTSAFEPOINT
13921317
{
13931318
jl_genericmemory_t *m_ = (jl_genericmemory_t*)m;
@@ -2402,8 +2327,6 @@ JL_DLLEXPORT void JL_NORETURN jl_throw(jl_value_t *e JL_MAYBE_UNROOTED);
24022327
JL_DLLEXPORT void JL_NORETURN jl_rethrow(void);
24032328
JL_DLLEXPORT void JL_NORETURN jl_rethrow_other(jl_value_t *e JL_MAYBE_UNROOTED);
24042329
JL_DLLEXPORT void JL_NORETURN jl_no_exc_handler(jl_value_t *e, jl_task_t *ct);
2405-
JL_DLLEXPORT JL_CONST_FUNC jl_gcframe_t **(jl_get_pgcstack)(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT;
2406-
#define jl_current_task (container_of(jl_get_pgcstack(), jl_task_t, gcstack))
24072330

24082331
extern JL_DLLIMPORT int jl_task_gcstack_offset;
24092332
extern JL_DLLIMPORT int jl_task_ptls_offset;

src/module.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,10 +748,10 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_
748748
else if (!b->did_print_implicit_import_admonition) {
749749
b->did_print_implicit_import_admonition = 1;
750750
jl_printf(JL_STDERR, "WARNING: Constructor for type \"%s\" was extended in `%s` without explicit qualification or import.\n"
751-
" NOTE: Assumed \"%s\" refers to `%s.%s`. This behavior is deprecated and may differ in future versions.`\n"
751+
" NOTE: Assumed \"%s\" refers to `%s.%s`. This behavior is deprecated and may differ in future versions.\n"
752752
" NOTE: This behavior may have differed in Julia versions prior to 1.12.\n"
753753
" Hint: If you intended to create a new generic function of the same name, use `function %s end`.\n"
754-
" Hint: To silence the warning, qualify `%s` as `%s.%s` or explicitly `import %s: %s`\n",
754+
" Hint: To silence the warning, qualify `%s` as `%s.%s` in the method signature or explicitly `import %s: %s`.\n",
755755
jl_symbol_name(var), jl_module_debug_name(m),
756756
jl_symbol_name(var), jl_module_debug_name(from), jl_symbol_name(var),
757757
jl_symbol_name(var), jl_symbol_name(var), jl_module_debug_name(from), jl_symbol_name(var),

0 commit comments

Comments
 (0)