Skip to content

Commit 40fbc88

Browse files
authored
bpart: Move kind enum into its intended place (#57385)
The original design for the BindingPartition datastructure had ->restriction and ->kind as separate non-atomic fields. However, to support the old semantics, we created an intermediate state where both the restriciton and the kind were placed into ->restriction as a pointer-int-union (i.e. using the low three bits of the pointer to store an int). In #57341, I removed that last semantic place that needed to update these both atomically. This PR removes all the remaining non-semantic places and changes the datastructure back to its indended design. This is a necessary prerequisitve to be able to use more than three ->kind bits, which will be required for export invalidation (#57377), as well as some nicer error messages in failure cases.
1 parent cff8bd6 commit 40fbc88

12 files changed

+156
-319
lines changed

src/ast.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint
178178
jl_sym_t *var = scmsym_to_julia(fl_ctx, args[0]);
179179
jl_binding_t *b = jl_get_module_binding(ctx->module, var, 0);
180180
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
181-
return (bpart != NULL && decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F;
181+
return (bpart != NULL && bpart->kind == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F;
182182
}
183183

184184
// Used to generate a unique suffix for a given symbol (e.g. variable or type name)

src/clangsa/GCChecker.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,6 @@ bool GCChecker::isGCTrackedType(QualType QT) {
856856
Name.ends_with_insensitive("jl_stenv_t") ||
857857
Name.ends_with_insensitive("jl_varbinding_t") ||
858858
Name.ends_with_insensitive("set_world") ||
859-
Name.ends_with_insensitive("jl_ptr_kind_union_t") ||
860859
Name.ends_with_insensitive("jl_codectx_t")) {
861860
return true;
862861
}

src/codegen.cpp

+28-35
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ static const auto jlcheckbpwritable_func = new JuliaFunction<>{
926926
nullptr,
927927
};
928928
static const auto jlgetbindingvalue_func = new JuliaFunction<>{
929-
XSTR(jl_reresolve_binding_value_seqcst),
929+
XSTR(jl_get_binding_value_seqcst),
930930
[](LLVMContext &C) {
931931
auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
932932
auto T_prjlvalue = JuliaType::get_prjlvalue_ty(C);
@@ -3113,9 +3113,9 @@ static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex)
31133113
jl_sym_t *sym = (jl_sym_t*)ex;
31143114
jl_binding_t *bnd = jl_get_module_binding(ctx.module, sym, 0);
31153115
jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
3116-
jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
3117-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
3118-
return decode_restriction_value(pku);
3116+
jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
3117+
if (bpart && jl_bkind_is_some_constant(bpart->kind))
3118+
return bpart->restriction;
31193119
return NULL;
31203120
}
31213121
if (jl_is_slotnumber(ex) || jl_is_argument(ex))
@@ -3138,10 +3138,10 @@ static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex)
31383138
s = jl_globalref_name(ex);
31393139
jl_binding_t *bnd = jl_get_module_binding(jl_globalref_mod(ex), s, 0);
31403140
jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
3141-
jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
3141+
jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
31423142
jl_value_t *v = NULL;
3143-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
3144-
v = decode_restriction_value(pku);
3143+
if (bpart && jl_bkind_is_some_constant(bpart->kind))
3144+
v = bpart->restriction;
31453145
if (v) {
31463146
if (bnd->deprecated)
31473147
cg_bdw(ctx, s, bnd);
@@ -3165,10 +3165,10 @@ static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex)
31653165
if (s && jl_is_symbol(s)) {
31663166
jl_binding_t *bnd = jl_get_module_binding(m, s, 0);
31673167
jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
3168-
jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
3168+
jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
31693169
jl_value_t *v = NULL;
3170-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
3171-
v = decode_restriction_value(pku);
3170+
if (bpart && jl_bkind_is_some_constant(bpart->kind))
3171+
v = bpart->restriction;
31723172
if (v) {
31733173
if (bnd->deprecated)
31743174
cg_bdw(ctx, s, bnd);
@@ -3418,50 +3418,44 @@ static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *
34183418
if (!bpart) {
34193419
return emit_globalref_runtime(ctx, bnd, mod, name);
34203420
}
3421-
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
3422-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
3423-
// try to look this up now.
3424-
// TODO: This is bad and we'd like to delete it.
3425-
jl_get_binding(mod, name);
3426-
}
34273421
// bpart was updated in place - this will change with full partition
3428-
pku = jl_atomic_load_acquire(&bpart->restriction);
3429-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
3422+
if (jl_bkind_is_some_guard(bpart->kind)) {
34303423
// Redo the lookup at runtime
34313424
return emit_globalref_runtime(ctx, bnd, mod, name);
34323425
} else {
34333426
while (true) {
34343427
if (!bpart)
34353428
break;
3436-
if (!jl_bkind_is_some_import(decode_restriction_kind(pku)))
3429+
if (!jl_bkind_is_some_import(bpart->kind))
34373430
break;
34383431
if (bnd->deprecated) {
34393432
cg_bdw(ctx, name, bnd);
34403433
}
3441-
bnd = (jl_binding_t*)decode_restriction_value(pku);
3434+
bnd = (jl_binding_t*)bpart->restriction;
34423435
bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
34433436
if (!bpart)
34443437
break;
3445-
pku = jl_atomic_load_acquire(&bpart->restriction);
34463438
}
3447-
enum jl_partition_kind kind = decode_restriction_kind(pku);
3448-
if (bpart && (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST)) {
3449-
jl_value_t *constval = decode_restriction_value(pku);
3450-
if (!constval) {
3451-
undef_var_error_ifnot(ctx, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), name, (jl_value_t*)mod);
3452-
return jl_cgval_t();
3439+
if (bpart) {
3440+
enum jl_partition_kind kind = bpart->kind;
3441+
if (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST) {
3442+
jl_value_t *constval = bpart->restriction;
3443+
if (!constval) {
3444+
undef_var_error_ifnot(ctx, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), name, (jl_value_t*)mod);
3445+
return jl_cgval_t();
3446+
}
3447+
return mark_julia_const(ctx, constval);
34533448
}
3454-
return mark_julia_const(ctx, constval);
34553449
}
34563450
}
3457-
if (!bpart || decode_restriction_kind(pku) != BINDING_KIND_GLOBAL) {
3451+
if (!bpart || bpart->kind != BINDING_KIND_GLOBAL) {
34583452
return emit_globalref_runtime(ctx, bnd, mod, name);
34593453
}
34603454
Value *bp = julia_binding_gv(ctx, bnd);
34613455
if (bnd->deprecated) {
34623456
cg_bdw(ctx, name, bnd);
34633457
}
3464-
jl_value_t *ty = decode_restriction_value(pku);
3458+
jl_value_t *ty = bpart->restriction;
34653459
bp = julia_binding_pvalue(ctx, bp);
34663460
if (ty == nullptr)
34673461
ty = (jl_value_t*)jl_any_type;
@@ -3477,9 +3471,8 @@ static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *s
34773471
jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
34783472
Value *bp = julia_binding_gv(ctx, bnd);
34793473
if (bpart) {
3480-
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
3481-
if (decode_restriction_kind(pku) == BINDING_KIND_GLOBAL) {
3482-
jl_value_t *ty = decode_restriction_value(pku);
3474+
if (bpart->kind == BINDING_KIND_GLOBAL) {
3475+
jl_value_t *ty = bpart->restriction;
34833476
if (ty != nullptr) {
34843477
const std::string fname = issetglobal ? "setglobal!" : isreplaceglobal ? "replaceglobal!" : isswapglobal ? "swapglobal!" : ismodifyglobal ? "modifyglobal!" : "setglobalonce!";
34853478
if (!ismodifyglobal) {
@@ -4164,8 +4157,8 @@ static jl_cgval_t emit_isdefinedglobal(jl_codectx_t &ctx, jl_module_t *modu, jl_
41644157
Value *isnull = NULL;
41654158
jl_binding_t *bnd = allow_import ? jl_get_binding(modu, name) : jl_get_module_binding(modu, name, 0);
41664159
jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
4167-
jl_ptr_kind_union_t pku = bpart ? jl_atomic_load_relaxed(&bpart->restriction) : encode_restriction(NULL, BINDING_KIND_GUARD);
4168-
if (decode_restriction_kind(pku) == BINDING_KIND_GLOBAL || jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
4160+
enum jl_partition_kind kind = bpart ? bpart->kind : BINDING_KIND_GUARD;
4161+
if (kind == BINDING_KIND_GLOBAL || jl_bkind_is_some_constant(kind)) {
41694162
if (jl_get_binding_value_if_const(bnd))
41704163
return mark_julia_const(ctx, jl_true);
41714164
Value *bp = julia_binding_gv(ctx, bnd);

src/gc-stock.c

-10
Original file line numberDiff line numberDiff line change
@@ -2448,16 +2448,6 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_
24482448
if (npointers == 0)
24492449
return;
24502450
uintptr_t nptr = (npointers << 2 | (bits & GC_OLD));
2451-
if (vt == jl_binding_partition_type) {
2452-
// BindingPartition has a special union of jl_value_t and flag bits
2453-
// but is otherwise regular.
2454-
jl_binding_partition_t *bpart = (jl_binding_partition_t*)jl_valueof(o);
2455-
jl_value_t *val = decode_restriction_value(
2456-
jl_atomic_load_relaxed(&bpart->restriction));
2457-
if (val)
2458-
gc_heap_snapshot_record_binding_partition_edge((jl_value_t*)bpart, val);
2459-
gc_try_claim_and_push(mq, val, &nptr);
2460-
}
24612451
assert((layout->nfields > 0 || layout->flags.fielddesc_type == 3) &&
24622452
"opaque types should have been handled specially");
24632453
if (layout->flags.fielddesc_type == 0) {

src/jltypes.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3262,8 +3262,8 @@ void jl_init_types(void) JL_GC_DISABLED
32623262

32633263
jl_binding_partition_type =
32643264
jl_new_datatype(jl_symbol("BindingPartition"), core, jl_any_type, jl_emptysvec,
3265-
jl_perm_symsvec(5, "restriction", "min_world", "max_world", "next", "reserved"),
3266-
jl_svec(5, jl_uint64_type /* Special GC-supported union of Any and flags*/,
3265+
jl_perm_symsvec(5, "restriction", "min_world", "max_world", "next", "kind"),
3266+
jl_svec(5, jl_any_type,
32673267
jl_ulong_type, jl_ulong_type, jl_any_type/*jl_binding_partition_type*/, jl_ulong_type),
32683268
jl_emptysvec, 0, 1, 0);
32693269
const static uint32_t binding_partition_atomicfields[] = { 0b01101 }; // Set fields 1, 3, 4 as atomic

src/julia.h

+2-8
Original file line numberDiff line numberDiff line change
@@ -706,12 +706,6 @@ enum jl_partition_kind {
706706
BINDING_KIND_IMPLICIT_RECOMPUTE = 0xb
707707
};
708708

709-
#ifdef _P64
710-
// Union of a ptr and a 3 bit field.
711-
typedef uintptr_t jl_ptr_kind_union_t;
712-
#else
713-
typedef struct __attribute__((aligned(8))) { jl_value_t *val; size_t kind; } jl_ptr_kind_union_t;
714-
#endif
715709
typedef struct __attribute__((aligned(8))) _jl_binding_partition_t {
716710
JL_DATA_TYPE
717711
/* union {
@@ -727,11 +721,11 @@ typedef struct __attribute__((aligned(8))) _jl_binding_partition_t {
727721
*
728722
* This field is updated atomically with both kind and restriction
729723
*/
730-
_Atomic(jl_ptr_kind_union_t) restriction;
724+
jl_value_t *restriction;
731725
size_t min_world;
732726
_Atomic(size_t) max_world;
733727
_Atomic(struct _jl_binding_partition_t *) next;
734-
size_t reserved; // Reserved for ->kind. Currently this holds the low bits of ->restriction during serialization
728+
enum jl_partition_kind kind;
735729
} jl_binding_partition_t;
736730

737731
typedef struct _jl_binding_t {

src/julia_internal.h

+13-73
Original file line numberDiff line numberDiff line change
@@ -932,62 +932,6 @@ jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name
932932
int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva, int isinferred);
933933
JL_DLLEXPORT int jl_is_valid_oc_argtype(jl_tupletype_t *argt, jl_method_t *source);
934934

935-
EXTERN_INLINE_DECLARE enum jl_partition_kind decode_restriction_kind(jl_ptr_kind_union_t pku) JL_NOTSAFEPOINT
936-
{
937-
#ifdef _P64
938-
uint8_t bits = (pku & 0x7);
939-
jl_value_t *val = (jl_value_t*)(pku & ~0x7);
940-
941-
if (val == NULL) {
942-
if (bits == BINDING_KIND_IMPLICIT) {
943-
return BINDING_KIND_GUARD;
944-
}
945-
if (bits == BINDING_KIND_CONST) {
946-
return BINDING_KIND_UNDEF_CONST;
947-
}
948-
} else {
949-
if (bits == BINDING_KIND_DECLARED) {
950-
return BINDING_KIND_BACKDATED_CONST;
951-
}
952-
}
953-
954-
return (enum jl_partition_kind)bits;
955-
#else
956-
return (enum jl_partition_kind)pku.kind;
957-
#endif
958-
}
959-
960-
STATIC_INLINE jl_value_t *decode_restriction_value(jl_ptr_kind_union_t JL_PROPAGATES_ROOT pku) JL_NOTSAFEPOINT
961-
{
962-
#ifdef _P64
963-
jl_value_t *val = (jl_value_t*)(pku & ~0x7);
964-
return val;
965-
#else
966-
return pku.val;
967-
#endif
968-
}
969-
970-
STATIC_INLINE jl_ptr_kind_union_t encode_restriction(jl_value_t *val, enum jl_partition_kind kind) JL_NOTSAFEPOINT
971-
{
972-
#ifdef _P64
973-
if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST)
974-
assert(val == NULL);
975-
else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST || kind == BINDING_KIND_BACKDATED_CONST)
976-
assert(val != NULL);
977-
if (kind == BINDING_KIND_GUARD)
978-
kind = BINDING_KIND_IMPLICIT;
979-
else if (kind == BINDING_KIND_UNDEF_CONST)
980-
kind = BINDING_KIND_CONST;
981-
else if (kind == BINDING_KIND_BACKDATED_CONST)
982-
kind = BINDING_KIND_DECLARED;
983-
assert((((uintptr_t)val) & 0x7) == 0);
984-
return ((jl_ptr_kind_union_t)val) | kind;
985-
#else
986-
jl_ptr_kind_union_t ret = { val, kind };
987-
return ret;
988-
#endif
989-
}
990-
991935
STATIC_INLINE int jl_bkind_is_some_import(enum jl_partition_kind kind) JL_NOTSAFEPOINT {
992936
return kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED;
993937
}
@@ -1008,35 +952,31 @@ JL_DLLEXPORT jl_binding_partition_t *jl_get_binding_partition(jl_binding_t *b JL
1008952
JL_DLLEXPORT jl_binding_partition_t *jl_get_binding_partition_all(jl_binding_t *b JL_PROPAGATES_ROOT, size_t min_world, size_t max_world) JL_GLOBALLY_ROOTED;
1009953

1010954
EXTERN_INLINE_DECLARE uint8_t jl_bpart_get_kind(jl_binding_partition_t *bpart) JL_NOTSAFEPOINT {
1011-
return decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction));
955+
return (uint8_t)bpart->kind;
1012956
}
1013957

1014-
STATIC_INLINE jl_ptr_kind_union_t jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart JL_PROPAGATES_ROOT, size_t world) JL_NOTSAFEPOINT;
1015-
STATIC_INLINE jl_ptr_kind_union_t jl_walk_binding_inplace_all(jl_binding_t **bnd, jl_binding_partition_t **bpart JL_PROPAGATES_ROOT, size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
958+
STATIC_INLINE void jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart JL_PROPAGATES_ROOT, size_t world) JL_NOTSAFEPOINT;
959+
STATIC_INLINE void jl_walk_binding_inplace_all(jl_binding_t **bnd, jl_binding_partition_t **bpart JL_PROPAGATES_ROOT, size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
1016960

1017961
#ifndef __clang_analyzer__
1018-
STATIC_INLINE jl_ptr_kind_union_t jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart, size_t world) JL_NOTSAFEPOINT
962+
STATIC_INLINE void jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart, size_t world) JL_NOTSAFEPOINT
1019963
{
1020964
while (1) {
1021-
if (!*bpart)
1022-
return encode_restriction(NULL, BINDING_KIND_GUARD);
1023-
jl_ptr_kind_union_t pku = jl_atomic_load_acquire(&(*bpart)->restriction);
1024-
if (!jl_bkind_is_some_import(decode_restriction_kind(pku)))
1025-
return pku;
1026-
*bnd = (jl_binding_t*)decode_restriction_value(pku);
965+
if (!jl_bkind_is_some_import((*bpart)->kind))
966+
return;
967+
*bnd = (jl_binding_t*)(*bpart)->restriction;
1027968
*bpart = jl_get_binding_partition(*bnd, world);
1028969
}
1029970
}
1030971

1031-
STATIC_INLINE jl_ptr_kind_union_t jl_walk_binding_inplace_all(jl_binding_t **bnd, jl_binding_partition_t **bpart, size_t min_world, size_t max_world) JL_NOTSAFEPOINT
972+
STATIC_INLINE void jl_walk_binding_inplace_all(jl_binding_t **bnd, jl_binding_partition_t **bpart, size_t min_world, size_t max_world) JL_NOTSAFEPOINT
1032973
{
1033974
while (1) {
1034-
if (!*bpart)
1035-
return encode_restriction(NULL, BINDING_KIND_GUARD);
1036-
jl_ptr_kind_union_t pku = jl_atomic_load_acquire(&(*bpart)->restriction);
1037-
if (!jl_bkind_is_some_import(decode_restriction_kind(pku)))
1038-
return pku;
1039-
*bnd = (jl_binding_t*)decode_restriction_value(pku);
975+
if (!(*bpart))
976+
return;
977+
if (!jl_bkind_is_some_import((*bpart)->kind))
978+
return;
979+
*bnd = (jl_binding_t*)(*bpart)->restriction;
1040980
*bpart = jl_get_binding_partition_all(*bnd, min_world, max_world);
1041981
}
1042982
}

src/method.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -1056,13 +1056,12 @@ JL_DLLEXPORT jl_value_t *jl_declare_const_gf(jl_module_t *mod, jl_sym_t *name)
10561056
size_t new_world = jl_atomic_load_relaxed(&jl_world_counter) + 1;
10571057
jl_binding_t *b = jl_get_binding_for_method_def(mod, name, new_world);
10581058
jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world);
1059-
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
10601059
jl_value_t *gf = NULL;
1061-
enum jl_partition_kind kind = decode_restriction_kind(pku);
1060+
enum jl_partition_kind kind = bpart->kind;
10621061
if (!jl_bkind_is_some_guard(kind) && kind != BINDING_KIND_DECLARED && kind != BINDING_KIND_IMPLICIT) {
1063-
pku = jl_walk_binding_inplace(&b, &bpart, new_world);
1064-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
1065-
gf = decode_restriction_value(pku);
1062+
jl_walk_binding_inplace(&b, &bpart, new_world);
1063+
if (jl_bkind_is_some_constant(bpart->kind)) {
1064+
gf = bpart->restriction;
10661065
JL_GC_PROMISE_ROOTED(gf);
10671066
jl_check_gf(gf, b->globalref->name);
10681067
JL_UNLOCK(&world_counter_lock);

0 commit comments

Comments
 (0)