From 40fbc8893a1daf935b1a77d597a3f638db61b03d Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 13 Feb 2025 08:56:47 -0500 Subject: [PATCH] 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. --- src/ast.c | 2 +- src/clangsa/GCChecker.cpp | 1 - src/codegen.cpp | 63 ++++++------- src/gc-stock.c | 10 -- src/jltypes.c | 4 +- src/julia.h | 10 +- src/julia_internal.h | 86 +++-------------- src/method.c | 9 +- src/module.c | 192 +++++++++++++++++--------------------- src/staticdata.c | 42 +-------- src/toplevel.c | 54 +++-------- test/syntax.jl | 2 +- 12 files changed, 156 insertions(+), 319 deletions(-) diff --git a/src/ast.c b/src/ast.c index 0f24d96393f2f..f643f4a2f40fe 100644 --- a/src/ast.c +++ b/src/ast.c @@ -178,7 +178,7 @@ static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint jl_sym_t *var = scmsym_to_julia(fl_ctx, args[0]); jl_binding_t *b = jl_get_module_binding(ctx->module, var, 0); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - return (bpart != NULL && decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F; + return (bpart != NULL && bpart->kind == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F; } // Used to generate a unique suffix for a given symbol (e.g. variable or type name) diff --git a/src/clangsa/GCChecker.cpp b/src/clangsa/GCChecker.cpp index fdbe5ec9d9e29..af07ca2227839 100644 --- a/src/clangsa/GCChecker.cpp +++ b/src/clangsa/GCChecker.cpp @@ -856,7 +856,6 @@ bool GCChecker::isGCTrackedType(QualType QT) { Name.ends_with_insensitive("jl_stenv_t") || Name.ends_with_insensitive("jl_varbinding_t") || Name.ends_with_insensitive("set_world") || - Name.ends_with_insensitive("jl_ptr_kind_union_t") || Name.ends_with_insensitive("jl_codectx_t")) { return true; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 025bb7c792443..26f34d63e578f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -926,7 +926,7 @@ static const auto jlcheckbpwritable_func = new JuliaFunction<>{ nullptr, }; static const auto jlgetbindingvalue_func = new JuliaFunction<>{ - XSTR(jl_reresolve_binding_value_seqcst), + XSTR(jl_get_binding_value_seqcst), [](LLVMContext &C) { auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C); 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) jl_sym_t *sym = (jl_sym_t*)ex; jl_binding_t *bnd = jl_get_module_binding(ctx.module, sym, 0); jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) - return decode_restriction_value(pku); + jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); + if (bpart && jl_bkind_is_some_constant(bpart->kind)) + return bpart->restriction; return NULL; } 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) s = jl_globalref_name(ex); jl_binding_t *bnd = jl_get_module_binding(jl_globalref_mod(ex), s, 0); jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); + jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); jl_value_t *v = NULL; - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) - v = decode_restriction_value(pku); + if (bpart && jl_bkind_is_some_constant(bpart->kind)) + v = bpart->restriction; if (v) { if (bnd->deprecated) cg_bdw(ctx, s, bnd); @@ -3165,10 +3165,10 @@ static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex) if (s && jl_is_symbol(s)) { jl_binding_t *bnd = jl_get_module_binding(m, s, 0); jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); + jl_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world); jl_value_t *v = NULL; - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) - v = decode_restriction_value(pku); + if (bpart && jl_bkind_is_some_constant(bpart->kind)) + v = bpart->restriction; if (v) { if (bnd->deprecated) 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 * if (!bpart) { return emit_globalref_runtime(ctx, bnd, mod, name); } - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) { - // try to look this up now. - // TODO: This is bad and we'd like to delete it. - jl_get_binding(mod, name); - } // bpart was updated in place - this will change with full partition - pku = jl_atomic_load_acquire(&bpart->restriction); - if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) { + if (jl_bkind_is_some_guard(bpart->kind)) { // Redo the lookup at runtime return emit_globalref_runtime(ctx, bnd, mod, name); } else { while (true) { if (!bpart) break; - if (!jl_bkind_is_some_import(decode_restriction_kind(pku))) + if (!jl_bkind_is_some_import(bpart->kind)) break; if (bnd->deprecated) { cg_bdw(ctx, name, bnd); } - bnd = (jl_binding_t*)decode_restriction_value(pku); + bnd = (jl_binding_t*)bpart->restriction; bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); if (!bpart) break; - pku = jl_atomic_load_acquire(&bpart->restriction); } - enum jl_partition_kind kind = decode_restriction_kind(pku); - if (bpart && (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST)) { - jl_value_t *constval = decode_restriction_value(pku); - if (!constval) { - undef_var_error_ifnot(ctx, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), name, (jl_value_t*)mod); - return jl_cgval_t(); + if (bpart) { + enum jl_partition_kind kind = bpart->kind; + if (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST) { + jl_value_t *constval = bpart->restriction; + if (!constval) { + undef_var_error_ifnot(ctx, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), name, (jl_value_t*)mod); + return jl_cgval_t(); + } + return mark_julia_const(ctx, constval); } - return mark_julia_const(ctx, constval); } } - if (!bpart || decode_restriction_kind(pku) != BINDING_KIND_GLOBAL) { + if (!bpart || bpart->kind != BINDING_KIND_GLOBAL) { return emit_globalref_runtime(ctx, bnd, mod, name); } Value *bp = julia_binding_gv(ctx, bnd); if (bnd->deprecated) { cg_bdw(ctx, name, bnd); } - jl_value_t *ty = decode_restriction_value(pku); + jl_value_t *ty = bpart->restriction; bp = julia_binding_pvalue(ctx, bp); if (ty == nullptr) 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 jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); Value *bp = julia_binding_gv(ctx, bnd); if (bpart) { - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - if (decode_restriction_kind(pku) == BINDING_KIND_GLOBAL) { - jl_value_t *ty = decode_restriction_value(pku); + if (bpart->kind == BINDING_KIND_GLOBAL) { + jl_value_t *ty = bpart->restriction; if (ty != nullptr) { const std::string fname = issetglobal ? "setglobal!" : isreplaceglobal ? "replaceglobal!" : isswapglobal ? "swapglobal!" : ismodifyglobal ? "modifyglobal!" : "setglobalonce!"; if (!ismodifyglobal) { @@ -4164,8 +4157,8 @@ static jl_cgval_t emit_isdefinedglobal(jl_codectx_t &ctx, jl_module_t *modu, jl_ Value *isnull = NULL; jl_binding_t *bnd = allow_import ? jl_get_binding(modu, name) : jl_get_module_binding(modu, name, 0); jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world); - jl_ptr_kind_union_t pku = bpart ? jl_atomic_load_relaxed(&bpart->restriction) : encode_restriction(NULL, BINDING_KIND_GUARD); - if (decode_restriction_kind(pku) == BINDING_KIND_GLOBAL || jl_bkind_is_some_constant(decode_restriction_kind(pku))) { + enum jl_partition_kind kind = bpart ? bpart->kind : BINDING_KIND_GUARD; + if (kind == BINDING_KIND_GLOBAL || jl_bkind_is_some_constant(kind)) { if (jl_get_binding_value_if_const(bnd)) return mark_julia_const(ctx, jl_true); Value *bp = julia_binding_gv(ctx, bnd); diff --git a/src/gc-stock.c b/src/gc-stock.c index d0f0baf4f4715..3d3bc9f485e51 100644 --- a/src/gc-stock.c +++ b/src/gc-stock.c @@ -2448,16 +2448,6 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ if (npointers == 0) return; uintptr_t nptr = (npointers << 2 | (bits & GC_OLD)); - if (vt == jl_binding_partition_type) { - // BindingPartition has a special union of jl_value_t and flag bits - // but is otherwise regular. - jl_binding_partition_t *bpart = (jl_binding_partition_t*)jl_valueof(o); - jl_value_t *val = decode_restriction_value( - jl_atomic_load_relaxed(&bpart->restriction)); - if (val) - gc_heap_snapshot_record_binding_partition_edge((jl_value_t*)bpart, val); - gc_try_claim_and_push(mq, val, &nptr); - } assert((layout->nfields > 0 || layout->flags.fielddesc_type == 3) && "opaque types should have been handled specially"); if (layout->flags.fielddesc_type == 0) { diff --git a/src/jltypes.c b/src/jltypes.c index dc7422460c0cf..e21d8ac184302 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3262,8 +3262,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_binding_partition_type = jl_new_datatype(jl_symbol("BindingPartition"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(5, "restriction", "min_world", "max_world", "next", "reserved"), - jl_svec(5, jl_uint64_type /* Special GC-supported union of Any and flags*/, + jl_perm_symsvec(5, "restriction", "min_world", "max_world", "next", "kind"), + jl_svec(5, jl_any_type, jl_ulong_type, jl_ulong_type, jl_any_type/*jl_binding_partition_type*/, jl_ulong_type), jl_emptysvec, 0, 1, 0); const static uint32_t binding_partition_atomicfields[] = { 0b01101 }; // Set fields 1, 3, 4 as atomic diff --git a/src/julia.h b/src/julia.h index 1fd709f42ee31..2d50bbb1cf3b6 100644 --- a/src/julia.h +++ b/src/julia.h @@ -706,12 +706,6 @@ enum jl_partition_kind { BINDING_KIND_IMPLICIT_RECOMPUTE = 0xb }; -#ifdef _P64 -// Union of a ptr and a 3 bit field. -typedef uintptr_t jl_ptr_kind_union_t; -#else -typedef struct __attribute__((aligned(8))) { jl_value_t *val; size_t kind; } jl_ptr_kind_union_t; -#endif typedef struct __attribute__((aligned(8))) _jl_binding_partition_t { JL_DATA_TYPE /* union { @@ -727,11 +721,11 @@ typedef struct __attribute__((aligned(8))) _jl_binding_partition_t { * * This field is updated atomically with both kind and restriction */ - _Atomic(jl_ptr_kind_union_t) restriction; + jl_value_t *restriction; size_t min_world; _Atomic(size_t) max_world; _Atomic(struct _jl_binding_partition_t *) next; - size_t reserved; // Reserved for ->kind. Currently this holds the low bits of ->restriction during serialization + enum jl_partition_kind kind; } jl_binding_partition_t; typedef struct _jl_binding_t { diff --git a/src/julia_internal.h b/src/julia_internal.h index 02729b7a4c6e7..0f52f82ac8230 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -932,62 +932,6 @@ jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva, int isinferred); JL_DLLEXPORT int jl_is_valid_oc_argtype(jl_tupletype_t *argt, jl_method_t *source); -EXTERN_INLINE_DECLARE enum jl_partition_kind decode_restriction_kind(jl_ptr_kind_union_t pku) JL_NOTSAFEPOINT -{ -#ifdef _P64 - uint8_t bits = (pku & 0x7); - jl_value_t *val = (jl_value_t*)(pku & ~0x7); - - if (val == NULL) { - if (bits == BINDING_KIND_IMPLICIT) { - return BINDING_KIND_GUARD; - } - if (bits == BINDING_KIND_CONST) { - return BINDING_KIND_UNDEF_CONST; - } - } else { - if (bits == BINDING_KIND_DECLARED) { - return BINDING_KIND_BACKDATED_CONST; - } - } - - return (enum jl_partition_kind)bits; -#else - return (enum jl_partition_kind)pku.kind; -#endif -} - -STATIC_INLINE jl_value_t *decode_restriction_value(jl_ptr_kind_union_t JL_PROPAGATES_ROOT pku) JL_NOTSAFEPOINT -{ -#ifdef _P64 - jl_value_t *val = (jl_value_t*)(pku & ~0x7); - return val; -#else - return pku.val; -#endif -} - -STATIC_INLINE jl_ptr_kind_union_t encode_restriction(jl_value_t *val, enum jl_partition_kind kind) JL_NOTSAFEPOINT -{ -#ifdef _P64 - if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST) - assert(val == NULL); - else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST || kind == BINDING_KIND_BACKDATED_CONST) - assert(val != NULL); - if (kind == BINDING_KIND_GUARD) - kind = BINDING_KIND_IMPLICIT; - else if (kind == BINDING_KIND_UNDEF_CONST) - kind = BINDING_KIND_CONST; - else if (kind == BINDING_KIND_BACKDATED_CONST) - kind = BINDING_KIND_DECLARED; - assert((((uintptr_t)val) & 0x7) == 0); - return ((jl_ptr_kind_union_t)val) | kind; -#else - jl_ptr_kind_union_t ret = { val, kind }; - return ret; -#endif -} - STATIC_INLINE int jl_bkind_is_some_import(enum jl_partition_kind kind) JL_NOTSAFEPOINT { return kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED; } @@ -1008,35 +952,31 @@ JL_DLLEXPORT jl_binding_partition_t *jl_get_binding_partition(jl_binding_t *b JL 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; EXTERN_INLINE_DECLARE uint8_t jl_bpart_get_kind(jl_binding_partition_t *bpart) JL_NOTSAFEPOINT { - return decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)); + return (uint8_t)bpart->kind; } -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; -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; +STATIC_INLINE void jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart JL_PROPAGATES_ROOT, size_t world) JL_NOTSAFEPOINT; +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; #ifndef __clang_analyzer__ -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 +STATIC_INLINE void jl_walk_binding_inplace(jl_binding_t **bnd, jl_binding_partition_t **bpart, size_t world) JL_NOTSAFEPOINT { while (1) { - if (!*bpart) - return encode_restriction(NULL, BINDING_KIND_GUARD); - jl_ptr_kind_union_t pku = jl_atomic_load_acquire(&(*bpart)->restriction); - if (!jl_bkind_is_some_import(decode_restriction_kind(pku))) - return pku; - *bnd = (jl_binding_t*)decode_restriction_value(pku); + if (!jl_bkind_is_some_import((*bpart)->kind)) + return; + *bnd = (jl_binding_t*)(*bpart)->restriction; *bpart = jl_get_binding_partition(*bnd, world); } } -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 +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 { while (1) { - if (!*bpart) - return encode_restriction(NULL, BINDING_KIND_GUARD); - jl_ptr_kind_union_t pku = jl_atomic_load_acquire(&(*bpart)->restriction); - if (!jl_bkind_is_some_import(decode_restriction_kind(pku))) - return pku; - *bnd = (jl_binding_t*)decode_restriction_value(pku); + if (!(*bpart)) + return; + if (!jl_bkind_is_some_import((*bpart)->kind)) + return; + *bnd = (jl_binding_t*)(*bpart)->restriction; *bpart = jl_get_binding_partition_all(*bnd, min_world, max_world); } } diff --git a/src/method.c b/src/method.c index 68542fdacabb6..0fc0e0ca1f87d 100644 --- a/src/method.c +++ b/src/method.c @@ -1056,13 +1056,12 @@ JL_DLLEXPORT jl_value_t *jl_declare_const_gf(jl_module_t *mod, jl_sym_t *name) size_t new_world = jl_atomic_load_relaxed(&jl_world_counter) + 1; jl_binding_t *b = jl_get_binding_for_method_def(mod, name, new_world); jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); jl_value_t *gf = NULL; - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (!jl_bkind_is_some_guard(kind) && kind != BINDING_KIND_DECLARED && kind != BINDING_KIND_IMPLICIT) { - pku = jl_walk_binding_inplace(&b, &bpart, new_world); - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) { - gf = decode_restriction_value(pku); + jl_walk_binding_inplace(&b, &bpart, new_world); + if (jl_bkind_is_some_constant(bpart->kind)) { + gf = bpart->restriction; JL_GC_PROMISE_ROOTED(gf); jl_check_gf(gf, b->globalref->name); JL_UNLOCK(&world_counter_lock); diff --git a/src/module.c b/src/module.c index dda43546927c5..a5a9481d15e72 100644 --- a/src/module.c +++ b/src/module.c @@ -14,18 +14,15 @@ extern "C" { // In this translation unit and this translation unit only emit this symbol `extern` for use by julia EXTERN_INLINE_DEFINE uint8_t jl_bpart_get_kind(jl_binding_partition_t *bpart) JL_NOTSAFEPOINT; -extern inline enum jl_partition_kind decode_restriction_kind(jl_ptr_kind_union_t pku) JL_NOTSAFEPOINT; static jl_binding_partition_t *new_binding_partition(void) { jl_binding_partition_t *bpart = (jl_binding_partition_t*)jl_gc_alloc(jl_current_task->ptls, sizeof(jl_binding_partition_t), jl_binding_partition_type); - jl_atomic_store_relaxed(&bpart->restriction, encode_restriction(NULL, BINDING_KIND_GUARD)); + bpart->restriction = NULL; + bpart->kind = BINDING_KIND_GUARD; bpart->min_world = 0; jl_atomic_store_relaxed(&bpart->max_world, (size_t)-1); jl_atomic_store_relaxed(&bpart->next, NULL); -#ifdef _P64 - bpart->reserved = 0; -#endif return bpart; } @@ -38,12 +35,12 @@ static int eq_bindings(jl_binding_partition_t *owner, jl_binding_t *alias, size_ jl_binding_partition_t *alias_bpart = jl_get_binding_partition(alias, world); if (owner == alias_bpart) return 1; - jl_ptr_kind_union_t owner_pku = jl_walk_binding_inplace(&ownerb, &owner, world); - jl_ptr_kind_union_t alias_pku = jl_walk_binding_inplace(&alias, &alias_bpart, world); - if (jl_bkind_is_some_constant(decode_restriction_kind(owner_pku)) && - jl_bkind_is_some_constant(decode_restriction_kind(alias_pku)) && - decode_restriction_value(owner_pku) && - decode_restriction_value(alias_pku) == decode_restriction_value(owner_pku)) + jl_walk_binding_inplace(&ownerb, &owner, world); + jl_walk_binding_inplace(&alias, &alias_bpart, world); + if (jl_bkind_is_some_constant(owner->kind) && + jl_bkind_is_some_constant(alias_bpart->kind) && + owner->restriction && + alias_bpart->restriction == owner->restriction) return 1; return owner == alias_bpart; } @@ -56,7 +53,8 @@ void jl_check_new_binding_implicit( modstack_t *tmp = st; for (; tmp != NULL; tmp = tmp->prev) { if (tmp->b == b) { - jl_atomic_store_relaxed(&new_bpart->restriction, encode_restriction(NULL, BINDING_KIND_FAILED /* BINDING_KIND_CYCLE */)); + new_bpart->restriction = NULL; + new_bpart->kind = BINDING_KIND_FAILED; /* BINDING_KIND_CYCLE */ return; } } @@ -142,10 +140,13 @@ void jl_check_new_binding_implicit( new_bpart->min_world = min_world; jl_atomic_store_relaxed(&new_bpart->max_world, max_world); if (impb) { - jl_atomic_store_relaxed(&new_bpart->restriction, encode_restriction((jl_value_t*)impb, BINDING_KIND_IMPLICIT)); + new_bpart->kind = BINDING_KIND_IMPLICIT; + new_bpart->restriction = (jl_value_t*)impb; + jl_gc_wb(new_bpart, impb); // TODO: World age constraints? } else { - jl_atomic_store_relaxed(&new_bpart->restriction, encode_restriction(NULL, guard_kind)); + new_bpart->kind = guard_kind; + new_bpart->restriction = NULL; } JL_GC_POP(); return; @@ -265,15 +266,14 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3( } jl_binding_partition_t *new_bpart = NULL; jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); while (!new_bpart) { - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_constant(kind)) { if (!val) { new_bpart = bpart; break; } - jl_value_t *old = decode_restriction_value(pku); + jl_value_t *old = bpart->restriction; JL_GC_PROMISE_ROOTED(old); if (jl_egal(val, old)) { new_bpart = bpart; @@ -287,11 +287,10 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3( jl_symbol_name(mod->name), jl_symbol_name(var)); } if (bpart->min_world == new_world) { - if (!jl_atomic_cmpswap(&bpart->restriction, &pku, encode_restriction(val, constant_kind))) { - continue; - } else if (val) { + bpart->kind = constant_kind; + bpart->restriction = val; + if (val) jl_gc_wb(bpart, val); - } new_bpart = bpart; } else { new_bpart = jl_replace_binding_locked(b, bpart, val, constant_kind, new_world); @@ -302,8 +301,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3( // declared const, global, or imported. jl_binding_partition_t *prev_bpart = bpart; for (;;) { - jl_ptr_kind_union_t prev_pku = jl_atomic_load_relaxed(&prev_bpart->restriction); - enum jl_partition_kind prev_kind = decode_restriction_kind(prev_pku); + enum jl_partition_kind prev_kind = prev_bpart->kind; if (jl_bkind_is_some_constant(prev_kind) || prev_kind == BINDING_KIND_GLOBAL || (jl_bkind_is_some_import(prev_kind))) { need_backdate = 0; @@ -318,7 +316,9 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3( // the entire backdate range. if (need_backdate) { jl_binding_partition_t *backdate_bpart = new_binding_partition(); - jl_atomic_store_relaxed(&backdate_bpart->restriction, encode_restriction(val, BINDING_KIND_BACKDATED_CONST)); + backdate_bpart->kind = BINDING_KIND_BACKDATED_CONST; + backdate_bpart->restriction = val; + jl_gc_wb_fresh(backdate_bpart, val); jl_atomic_store_relaxed(&backdate_bpart->max_world, new_world - 1); jl_atomic_store_release(&new_bpart->next, backdate_bpart); jl_gc_wb(new_bpart, backdate_bpart); @@ -499,8 +499,7 @@ static jl_module_t *jl_binding_dbgmodule(jl_binding_t *b, jl_module_t *m, jl_sym JL_DLLEXPORT void jl_check_binding_currently_writable(jl_binding_t *b, jl_module_t *m, jl_sym_t *s) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (kind != BINDING_KIND_GLOBAL && kind != BINDING_KIND_DECLARED && !jl_bkind_is_some_constant(kind)) { if (jl_bkind_is_some_guard(kind)) { jl_errorf("Global %s.%s does not exist and cannot be assigned.\n" @@ -559,13 +558,13 @@ static inline void check_backdated_binding(jl_binding_t *b, enum jl_partition_ki JL_DLLEXPORT jl_value_t *jl_get_binding_value(jl_binding_t *b) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - enum jl_partition_kind kind = decode_restriction_kind(pku); + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_guard(kind)) return NULL; if (jl_bkind_is_some_constant(kind)) { check_backdated_binding(b, kind); - return decode_restriction_value(pku); + return bpart->restriction; } assert(!jl_bkind_is_some_import(kind)); return jl_atomic_load_relaxed(&b->value); @@ -574,13 +573,13 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value(jl_binding_t *b) JL_DLLEXPORT jl_value_t *jl_get_binding_value_seqcst(jl_binding_t *b) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - enum jl_partition_kind kind = decode_restriction_kind(pku); + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_guard(kind)) return NULL; if (jl_bkind_is_some_constant(kind)) { check_backdated_binding(b, kind); - return decode_restriction_value(pku); + return bpart->restriction; } assert(!jl_bkind_is_some_import(kind)); return jl_atomic_load(&b->value); @@ -589,14 +588,14 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_seqcst(jl_binding_t *b) JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_const(jl_binding_t *b) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - enum jl_partition_kind kind = decode_restriction_kind(pku); + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_guard(kind)) return NULL; if (!jl_bkind_is_some_constant(kind)) return NULL; check_backdated_binding(b, kind); - return decode_restriction_value(pku); + return bpart->restriction; } JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved_and_const(jl_binding_t *b) @@ -611,14 +610,13 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved_and_const(jl_binding_t size_t max_world = jl_atomic_load_relaxed(&bpart->max_world); if (bpart->min_world > jl_current_task->world_age || jl_current_task->world_age > max_world) return NULL; - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_guard(kind)) return NULL; if (!jl_bkind_is_some_constant(kind)) return NULL; check_backdated_binding(b, kind); - return decode_restriction_value(pku); + return bpart->restriction; } JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved(jl_binding_t *b) @@ -633,58 +631,44 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved(jl_binding_t *b) size_t max_world = jl_atomic_load_relaxed(&bpart->max_world); if (bpart->min_world > jl_current_task->world_age || jl_current_task->world_age > max_world) return NULL; - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_guard(kind)) return NULL; if (jl_bkind_is_some_import(kind)) return NULL; if (jl_bkind_is_some_constant(kind)) { check_backdated_binding(b, kind); - return decode_restriction_value(pku); + return bpart->restriction; } return jl_atomic_load_relaxed(&b->value); } JL_DLLEXPORT jl_value_t *jl_bpart_get_restriction_value(jl_binding_partition_t *bpart) { - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - jl_value_t *v = decode_restriction_value(pku); + jl_value_t *v = bpart->restriction; if (!v) jl_throw(jl_undefref_exception); return v; } -JL_DLLEXPORT jl_value_t *jl_reresolve_binding_value_seqcst(jl_binding_t *b) -{ - /* - jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - if (jl_bkind_is_some_guard(decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)))) { - jl_resolve_owner(b, b->globalref->mod, b->globalref->name, NULL, jl_current_task->world_age); - } - */ - return jl_get_binding_value_seqcst(b); -} - // get binding for adding a method // like jl_get_binding_wr, but has different error paths and messages JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var, size_t new_world) { jl_binding_t *b = jl_get_module_binding(m, var, 1); jl_binding_partition_t *bpart = jl_get_binding_partition(b, new_world); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); - if (kind == BINDING_KIND_GLOBAL || kind == BINDING_KIND_DECLARED || jl_bkind_is_some_constant(decode_restriction_kind(pku))) + enum jl_partition_kind kind = bpart->kind; + if (kind == BINDING_KIND_GLOBAL || kind == BINDING_KIND_DECLARED || jl_bkind_is_some_constant(kind)) return b; if (jl_bkind_is_some_guard(kind)) { check_safe_newbinding(m, var); return b; } jl_binding_t *ownerb = b; - pku = jl_walk_binding_inplace(&ownerb, &bpart, new_world); + jl_walk_binding_inplace(&ownerb, &bpart, new_world); jl_value_t *f = NULL; - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) - f = decode_restriction_value(pku); + if (jl_bkind_is_some_constant(bpart->kind)) + f = bpart->restriction; if (f == NULL) { if (kind == BINDING_KIND_IMPLICIT) { check_safe_newbinding(m, var); @@ -734,9 +718,8 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_ static jl_module_t *jl_binding_dbgmodule(jl_binding_t *b, jl_module_t *m, jl_sym_t *var) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - if (jl_bkind_is_some_import(decode_restriction_kind(pku))) { - return ((jl_binding_t*)decode_restriction_value(pku))->globalref->mod; + if (jl_bkind_is_some_import(bpart->kind)) { + return ((jl_binding_t*)bpart->restriction)->globalref->mod; } return m; } @@ -750,17 +733,17 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_type(jl_module_t *m, jl_sym_t *var) jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); if (b == NULL) return jl_nothing; - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + if (jl_bkind_is_some_guard(bpart->kind)) return jl_nothing; - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) { + if (jl_bkind_is_some_constant(bpart->kind)) { // TODO: We would like to return the type of the constant, but // currently code relies on this returning any to bypass conversion // before an attempted assignment to a constant. - // return jl_typeof(jl_atomic_load_relaxed(&bpart->restriction)); + // return bpart->restriction; return (jl_value_t*)jl_any_type; } - return decode_restriction_value(pku); + return bpart->restriction; } JL_DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) @@ -792,7 +775,7 @@ JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_module_binding(m, var, 0); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - return b && decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_IMPORTED; + return b && bpart->kind == BINDING_KIND_IMPORTED; } extern const char *jl_filename; @@ -853,8 +836,6 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname, { jl_binding_t *b = jl_get_binding(from, s); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - (void)pku; if (b->deprecated) { if (jl_get_binding_value(b) == jl_nothing) { // silently skip importing deprecated values assigned to nothing (to allow later mutation) @@ -877,9 +858,9 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname, jl_binding_t *ownerb = b; jl_binding_partition_t *ownerbpart = bpart; - jl_ptr_kind_union_t owner_pku = jl_walk_binding_inplace(&ownerb, &ownerbpart, jl_current_task->world_age); + jl_walk_binding_inplace(&ownerb, &ownerbpart, jl_current_task->world_age); - if (jl_bkind_is_some_guard(decode_restriction_kind(owner_pku))) { + if (jl_bkind_is_some_guard(ownerbpart->kind)) { jl_printf(JL_STDERR, "WARNING: Imported binding %s.%s was undeclared at import time during import to %s.\n", jl_symbol_name(from->name), jl_symbol_name(s), @@ -894,10 +875,10 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname, JL_LOCK(&world_counter_lock); size_t new_world = jl_atomic_load_acquire(&jl_world_counter)+1; jl_binding_partition_t *btopart = jl_get_binding_partition(bto, new_world); - jl_ptr_kind_union_t bto_pku = jl_atomic_load_relaxed(&btopart->restriction); - if (decode_restriction_kind(bto_pku) == BINDING_KIND_GUARD || - decode_restriction_kind(bto_pku) == BINDING_KIND_IMPLICIT || - decode_restriction_kind(bto_pku) == BINDING_KIND_FAILED) { + enum jl_partition_kind btokind = btopart->kind; + if (btokind == BINDING_KIND_GUARD || + btokind == BINDING_KIND_IMPLICIT || + btokind == BINDING_KIND_FAILED) { jl_binding_partition_t *new_bpart = jl_replace_binding_locked(bto, btopart, (jl_value_t*)b, (explici != 0) ? BINDING_KIND_IMPORTED : BINDING_KIND_EXPLICIT, new_world); if (jl_atomic_load_relaxed(&new_bpart->max_world) == ~(size_t)0) @@ -907,12 +888,12 @@ static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *asname, else { if (eq_bindings(bpart, bto, new_world)) { // already imported - potentially upgrade _EXPLICIT to _IMPORTED - if (decode_restriction_kind(bto_pku) == BINDING_KIND_EXPLICIT && explici != 0) { + if (btokind == BINDING_KIND_EXPLICIT && explici != 0) { jl_replace_binding_locked(bto, btopart, (jl_value_t*)b, BINDING_KIND_IMPORTED, new_world); jl_atomic_store_release(&jl_world_counter, new_world); } } - else if (jl_bkind_is_some_import(decode_restriction_kind(bto_pku))) { + else if (jl_bkind_is_some_import(btokind)) { // already imported from somewhere else jl_printf(JL_STDERR, "WARNING: ignoring conflicting import of %s.%s into %s\n", @@ -1000,8 +981,7 @@ JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from) jl_binding_t *tob = jl_get_module_binding(to, var, 0); if (tob) { jl_binding_partition_t *tobpart = jl_get_binding_partition(tob, new_world); - jl_ptr_kind_union_t tobpku = jl_atomic_load_relaxed(&tobpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(tobpku); + enum jl_partition_kind kind = tobpart->kind; if (kind == BINDING_KIND_IMPLICIT || jl_bkind_is_some_guard(kind)) { jl_replace_binding_locked(tob, tobpart, NULL, BINDING_KIND_IMPLICIT_RECOMPUTE, new_world); } @@ -1055,16 +1035,15 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import) // u jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); if (!bpart) return 0; - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); if (!allow_import) { - if (!bpart || jl_bkind_is_some_import(decode_restriction_kind(pku))) + if (!bpart || jl_bkind_is_some_import(bpart->kind)) return 0; } else { - pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); } - if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) + if (jl_bkind_is_some_guard(bpart->kind)) return 0; - if (jl_bkind_is_defined_constant(decode_restriction_kind(pku))) { + if (jl_bkind_is_defined_constant(bpart->kind)) { // N.B.: No backdated check for isdefined return 1; } @@ -1075,7 +1054,7 @@ JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_module_binding(m, var, 0); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - return b && (b->exportp || decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GLOBAL); + return b && (b->exportp || bpart->kind == BINDING_KIND_GLOBAL); } JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) @@ -1188,7 +1167,8 @@ JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var jl_binding_partition_t *bpart = jl_get_binding_partition(bp, jl_current_task->world_age); bpart->min_world = 0; jl_atomic_store_release(&bpart->max_world, ~(size_t)0); - jl_atomic_store_release(&bpart->restriction, encode_restriction(val, BINDING_KIND_CONST)); + bpart->kind = BINDING_KIND_CONST; + bpart->restriction = val; jl_gc_wb(bpart, val); } @@ -1253,10 +1233,13 @@ JL_DLLEXPORT jl_binding_partition_t *jl_replace_binding_locked(jl_binding_t *b, assert(!restriction_val); jl_check_new_binding_implicit(new_bpart /* callee rooted */, b, NULL, new_world); } - else - jl_atomic_store_relaxed(&new_bpart->restriction, encode_restriction(restriction_val, kind)); + else { + new_bpart->kind = kind; + new_bpart->restriction = restriction_val; + jl_gc_wb_fresh(new_bpart, restriction_val); + } jl_atomic_store_relaxed(&new_bpart->next, old_bpart); - jl_gc_wb(new_bpart, old_bpart); + jl_gc_wb_fresh(new_bpart, old_bpart); jl_atomic_store_release(&b->partitions, new_bpart); jl_gc_wb(b, new_bpart); @@ -1299,7 +1282,7 @@ JL_DLLEXPORT int jl_globalref_is_const(jl_globalref_t *gr) jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); if (!bpart) return 0; - return jl_bkind_is_some_constant(decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction))); + return jl_bkind_is_some_constant(bpart->kind); } JL_DLLEXPORT void jl_disable_binding(jl_globalref_t *gr) @@ -1309,7 +1292,7 @@ JL_DLLEXPORT void jl_disable_binding(jl_globalref_t *gr) b = jl_get_module_binding(gr->mod, gr->name, 1); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - if (decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GUARD) { + if (bpart->kind == BINDING_KIND_GUARD) { // Already guard return; } @@ -1323,8 +1306,8 @@ JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_binding(m, var); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - return b && jl_bkind_is_some_constant(decode_restriction_kind(pku)); + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + return b && jl_bkind_is_some_constant(bpart->kind); } // set the deprecated flag for a binding: @@ -1375,10 +1358,9 @@ jl_value_t *jl_check_binding_assign_value(jl_binding_t *b JL_PROPAGATES_ROOT, jl { JL_GC_PUSH1(&rhs); // callee-rooted jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (jl_bkind_is_some_constant(kind)) { - jl_value_t *old = decode_restriction_value(pku); + jl_value_t *old = bpart->restriction; JL_GC_PROMISE_ROOTED(old); if (jl_egal(rhs, old)) { JL_GC_POP(); @@ -1388,7 +1370,7 @@ jl_value_t *jl_check_binding_assign_value(jl_binding_t *b JL_PROPAGATES_ROOT, jl jl_symbol_name(mod->name), jl_symbol_name(var)); } assert(kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_GLOBAL); - jl_value_t *old_ty = kind == BINDING_KIND_DECLARED ? (jl_value_t*)jl_any_type : decode_restriction_value(pku); + jl_value_t *old_ty = kind == BINDING_KIND_DECLARED ? (jl_value_t*)jl_any_type : bpart->restriction; JL_GC_PROMISE_ROOTED(old_ty); if (old_ty != (jl_value_t*)jl_any_type && jl_typeof(rhs) != old_ty) { if (!jl_isa(rhs, old_ty)) @@ -1426,12 +1408,12 @@ JL_DLLEXPORT jl_value_t *jl_checked_replace(jl_binding_t *b, jl_module_t *mod, j JL_DLLEXPORT jl_value_t *jl_checked_modify(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *op, jl_value_t *rhs) { jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - assert(!jl_bkind_is_some_guard(decode_restriction_kind(pku)) && !jl_bkind_is_some_import(decode_restriction_kind(pku))); - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) + enum jl_partition_kind kind = bpart->kind; + assert(!jl_bkind_is_some_guard(kind) && !jl_bkind_is_some_import(kind)); + if (jl_bkind_is_some_constant(kind)) jl_errorf("invalid assignment to constant %s.%s", jl_symbol_name(mod->name), jl_symbol_name(var)); - jl_value_t *ty = decode_restriction_value(pku); + jl_value_t *ty = bpart->restriction; JL_GC_PROMISE_ROOTED(ty); return modify_value(ty, &b->value, (jl_value_t*)b, op, rhs, 1, mod, var); } @@ -1478,7 +1460,7 @@ void append_module_names(jl_array_t* a, jl_module_t *m, int all, int imported, i int hidden = jl_symbol_name(asname)[0]=='#'; int main_public = (m == jl_main_module && !(asname == jl_eval_sym || asname == jl_include_sym)); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - enum jl_partition_kind kind = decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)); + enum jl_partition_kind kind = bpart->kind; if (((b->publicp) || (imported && (kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_IMPORTED)) || (usings && kind == BINDING_KIND_EXPLICIT) || @@ -1565,7 +1547,7 @@ JL_DLLEXPORT void jl_clear_implicit_imports(jl_module_t *m) if ((void*)b == jl_nothing) break; jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - if (decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_IMPLICIT) { + if (bpart->kind == BINDING_KIND_IMPLICIT) { jl_atomic_store_relaxed(&b->partitions, NULL); } } diff --git a/src/staticdata.c b/src/staticdata.c index 0c1405581debe..c29448c491eb7 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1001,7 +1001,7 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ } else if (jl_is_binding_partition(v)) { jl_binding_partition_t *bpart = (jl_binding_partition_t*)v; - jl_queue_for_serialization_(s, decode_restriction_value(jl_atomic_load_relaxed(&bpart->restriction)), 1, immediate); + jl_queue_for_serialization_(s, bpart->restriction, 1, immediate); jl_queue_for_serialization_(s, get_replaceable_field((jl_value_t**)&bpart->next, 0), 1, immediate); } else if (layout->nfields > 0) { @@ -1680,13 +1680,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED } else if (jl_is_binding_partition(v)) { jl_binding_partition_t *bpart = (jl_binding_partition_t*)v; - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - jl_value_t *restriction_val = decode_restriction_value(pku); - static_assert(offsetof(jl_binding_partition_t, restriction) == 0, "BindingPartition layout mismatch"); - write_pointerfield(s, restriction_val); -#ifndef _P64 - write_uint(f, decode_restriction_kind(pku)); -#endif + write_pointerfield(s, bpart->restriction); size_t max_world = jl_atomic_load_relaxed(&bpart->max_world); if (s->incremental) { if (max_world == ~(size_t)0) { @@ -1708,13 +1702,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED write_uint(f, max_world); } write_pointerfield(s, (jl_value_t*)jl_atomic_load_relaxed(&bpart->next)); -#ifdef _P64 - write_uint(f, decode_restriction_kind(pku)); // This will be moved back into place during deserialization (if necessary) - static_assert(sizeof(jl_binding_partition_t) == 5*sizeof(void*), "BindingPartition layout mismatch"); -#else - write_uint(f, 0); - static_assert(sizeof(jl_binding_partition_t) == 6*sizeof(void*), "BindingPartition layout mismatch"); -#endif + write_uint(f, bpart->kind); } else { // Generic object::DataType serialization by field @@ -3510,11 +3498,10 @@ static void jl_validate_binding_partition(jl_binding_t *b, jl_binding_partition_ if (jl_atomic_load_relaxed(&bpart->max_world) != ~(size_t)0) return; - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (!jl_bkind_is_some_import(kind)) return; - jl_binding_t *imported_binding = (jl_binding_t*)decode_restriction_value(pku); + jl_binding_t *imported_binding = (jl_binding_t*)bpart->restriction; jl_binding_partition_t *latest_imported_bpart = jl_atomic_load_relaxed(&imported_binding->partitions); if (!latest_imported_bpart) return; @@ -4015,25 +4002,6 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl } } } - // Move the binding bits back to their correct place -#ifdef _P64 - jl_svec_t *table = jl_atomic_load_relaxed(&mod->bindings); - for (size_t i = 0; i < jl_svec_len(table); i++) { - jl_binding_t *b = (jl_binding_t*)jl_svecref(table, i); - if ((jl_value_t*)b == jl_nothing) - continue; - jl_binding_partition_t *bpart = jl_atomic_load_relaxed(&b->partitions); - while (bpart) { - jl_ptr_kind_union_t pku = encode_restriction( - (jl_value_t*)jl_atomic_load_relaxed(&bpart->restriction), - (enum jl_partition_kind)bpart->reserved); - jl_atomic_store_relaxed(&bpart->restriction, pku); - bpart->reserved = 0; - bpart = jl_atomic_load_relaxed(&bpart->next); - } - } - -#endif } else { abort(); diff --git a/src/toplevel.c b/src/toplevel.c index e2c58b6345c8d..9bb82a3451848 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -157,32 +157,7 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex } } else { - jl_binding_t *b = jl_get_module_binding(parent_module, name, 1); - jl_binding_partition_t *bpart = jl_get_binding_partition(b, ct->world_age); - jl_ptr_kind_union_t pku = encode_restriction(NULL, BINDING_KIND_UNDEF_CONST); - jl_ptr_kind_union_t new_pku = encode_restriction((jl_value_t*)newm, BINDING_KIND_CONST); - if (!jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku)) { - if (decode_restriction_kind(pku) != BINDING_KIND_CONST) { - jl_declare_constant_val(b, parent_module, name, (jl_value_t*)newm); - } else { - // As a special exception allow binding replacement of modules - if (!jl_is_module(decode_restriction_value(pku))) { - jl_errorf("invalid redefinition of constant %s", jl_symbol_name(name)); - } - if (jl_generating_output()) - jl_errorf("cannot replace module %s during compilation", jl_symbol_name(name)); - jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", jl_symbol_name(name)); - pku = jl_atomic_exchange(&bpart->restriction, new_pku); - } - jl_gc_wb(bpart, newm); - if (decode_restriction_value(pku) != NULL && jl_is_module(decode_restriction_value(pku))) { - // create a hidden gc root for the old module - JL_LOCK(&jl_modules_mutex); - uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, decode_restriction_value(pku)); - *refcnt += 1; - JL_UNLOCK(&jl_modules_mutex); - } - } + jl_declare_constant_val(NULL, parent_module, name, (jl_value_t*)newm); } if (parent_module == jl_main_module && name == jl_symbol("Base")) { @@ -332,29 +307,27 @@ void jl_declare_global(jl_module_t *m, jl_value_t *arg, jl_value_t *set_type, in global_type = (jl_value_t*)jl_any_type; while (1) { bpart = jl_get_binding_partition(b, new_world); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (kind != BINDING_KIND_GLOBAL) { if (jl_bkind_is_some_guard(kind) || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_IMPLICIT) { - if (decode_restriction_kind(pku) == new_kind) { + if (kind == new_kind) { if (!set_type) goto done; goto check_type; } check_safe_newbinding(gm, gs); if (bpart->min_world == new_world) { - if (jl_atomic_cmpswap(&bpart->restriction, &pku, encode_restriction(global_type, new_kind))) { - break; - } - if (set_type) - jl_gc_wb(bpart, set_type); + bpart->kind = new_kind; + bpart->restriction = global_type; + if (global_type) + jl_gc_wb(bpart, global_type); continue; } else { jl_replace_binding_locked(b, bpart, global_type, new_kind, new_world); } break; } else if (set_type) { - if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) { + if (jl_bkind_is_some_constant(kind)) { jl_errorf("cannot set type for constant %s.%s.", jl_symbol_name(gm->name), jl_symbol_name(gs)); } else { @@ -366,7 +339,7 @@ void jl_declare_global(jl_module_t *m, jl_value_t *arg, jl_value_t *set_type, in if (set_type) { check_type: ; - jl_value_t *old_ty = decode_restriction_value(pku); + jl_value_t *old_ty = bpart->restriction; JL_GC_PROMISE_ROOTED(old_ty); if (!jl_types_equal(set_type, old_ty)) { jl_errorf("cannot set type for global %s.%s. It already has a value or is already set to a different type.", @@ -682,14 +655,13 @@ static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import, jl_sym // TODO: this is a bit race-y with what error message we might print jl_binding_t *b = jl_get_module_binding(m, name, 1); jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - enum jl_partition_kind kind = decode_restriction_kind(pku); + enum jl_partition_kind kind = bpart->kind; if (kind != BINDING_KIND_GUARD && kind != BINDING_KIND_FAILED && kind != BINDING_KIND_DECLARED && kind != BINDING_KIND_IMPLICIT) { // Unlike regular constant declaration, we allow this as long as we eventually end up at a constant. - pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - if (decode_restriction_kind(pku) == BINDING_KIND_CONST || decode_restriction_kind(pku) == BINDING_KIND_BACKDATED_CONST || decode_restriction_kind(pku) == BINDING_KIND_CONST_IMPORT) { + jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); + if (bpart->kind == BINDING_KIND_CONST || bpart->kind == BINDING_KIND_BACKDATED_CONST || bpart->kind == BINDING_KIND_CONST_IMPORT) { // Already declared (e.g. on another thread) or imported. - if (decode_restriction_value(pku) == (jl_value_t*)import) + if (bpart->restriction == (jl_value_t*)import) return; } jl_errorf("importing %s into %s conflicts with an existing global", diff --git a/test/syntax.jl b/test/syntax.jl index 5f49f13fca641..67a6976adfcec 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -3977,7 +3977,7 @@ module ReplacementContainer const x = 1 end const Old = ReplaceMe - @test_warn r"WARNING: replacing module ReplaceMe" @eval module ReplaceMe + @eval module ReplaceMe const x = 2 end end