Skip to content

Commit 7ea8a9a

Browse files
authored
Refactor Binding data structures in preparation for partition (#54788)
This is a re-worked extraction of #54654, adjusted to support the new semantics arrived at over the course of that thread. Note that this is the data-structure change only. The semantics in this PR still match current master to the greatest extent possible. The core idea here is to split `Binding` in two: A new `Binding` with minimal data and a `BindingPartition` that holds all data that is world-age partitioned. In the present PR, these are always in 1:1 correspondednce, but after #54654, there will be multiple `BindingPartition`s for every `Binding`. Essentially the `owner` and `ty` fields have been merged into a new `restriction` field of `BindingPartition`, which may also hold the value of a constant (consistent with the final semantics reached in #54654). The non-partitioned binding->value field is now used exclusively for non-constant globals. The disambiguation for how to interpret the `restriction` field happens via flags. `->imported` grew to 2 bits and can now be one of `NONE`/`IMPLICIT`/ `EXPLICIT`/`GUARD`. `GUARD` corresponds to the old `b->owner == NULL` case. `NONE` corresponds to the old `b->owner == b` case, while IMPLICIT/EXPLICIT correspond to `b->owner != b` and the old `imported` flag. Other than that, the behavior of the flags is unchanged. Additionally, fields are provided for `min_world`/`max_world`/`next`, but these are unused in this PR and prepratory only.
1 parent b5af119 commit 7ea8a9a

30 files changed

+1031
-542
lines changed

base/client.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ function load_REPL()
417417
return nothing
418418
end
419419

420-
global active_repl
420+
global active_repl::Any
421421
global active_repl_backend = nothing
422422

423423
function run_fallback_repl(interactive::Bool)

base/reflection.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,27 @@ function _fieldnames(@nospecialize t)
207207
return t.name.names
208208
end
209209

210+
const BINDING_KIND_GLOBAL = 0x0
211+
const BINDING_KIND_CONST = 0x1
212+
const BINDING_KIND_CONST_IMPORT = 0x2
213+
const BINDING_KIND_IMPLICIT = 0x3
214+
const BINDING_KIND_EXPLICIT = 0x4
215+
const BINDING_KIND_IMPORTED = 0x5
216+
const BINDING_KIND_FAILED = 0x6
217+
const BINDING_KIND_DECLARED = 0x7
218+
const BINDING_KIND_GUARD = 0x8
219+
220+
function lookup_binding_partition(world::UInt, b::Core.Binding)
221+
ccall(:jl_get_binding_partition, Ref{Core.BindingPartition}, (Any, UInt), b, world)
222+
end
223+
224+
function lookup_binding_partition(world::UInt, gr::Core.GlobalRef)
225+
ccall(:jl_get_globalref_partition, Ref{Core.BindingPartition}, (Any, UInt), gr, world)
226+
end
227+
228+
binding_kind(bpart::Core.BindingPartition) = ccall(:jl_bpart_get_kind, UInt8, (Any,), bpart)
229+
binding_kind(m::Module, s::Symbol) = binding_kind(lookup_binding_partition(tls_world_age(), GlobalRef(m, s)))
230+
210231
"""
211232
fieldname(x::DataType, i::Integer)
212233

doc/src/manual/variables-and-scoping.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ ERROR: invalid redefinition of constant x
743743
julia> const y = 1.0
744744
1.0
745745
746-
julia> y = 2.0
746+
julia> const y = 2.0
747747
WARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors.
748748
2.0
749749
```
@@ -761,7 +761,7 @@ julia> const a = [1]
761761
1-element Vector{Int64}:
762762
1
763763
764-
julia> a = [1]
764+
julia> const a = [1]
765765
WARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.
766766
1-element Vector{Int64}:
767767
1
@@ -782,7 +782,7 @@ f (generic function with 1 method)
782782
julia> f()
783783
1
784784
785-
julia> x = 2
785+
julia> const x = 2
786786
WARNING: redefinition of constant x. This may fail, cause incorrect answers, or produce other errors.
787787
2
788788

src/ast.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint
175175
jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx);
176176
jl_sym_t *var = scmsym_to_julia(fl_ctx, args[0]);
177177
jl_binding_t *b = jl_get_module_binding(ctx->module, var, 0);
178-
return (b != NULL && jl_atomic_load_relaxed(&b->owner) == b) ? fl_ctx->T : fl_ctx->F;
178+
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
179+
return (bpart != NULL && decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F;
179180
}
180181

181182
static value_t fl_nothrow_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
@@ -204,8 +205,14 @@ static value_t fl_nothrow_julia_global(fl_context_t *fl_ctx, value_t *args, uint
204205
var = scmsym_to_julia(fl_ctx, args[1]);
205206
}
206207
jl_binding_t *b = jl_get_module_binding(mod, var, 0);
207-
b = b ? jl_atomic_load_relaxed(&b->owner) : NULL;
208-
return b != NULL && jl_atomic_load_relaxed(&b->value) != NULL ? fl_ctx->T : fl_ctx->F;
208+
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
209+
jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
210+
if (!bpart)
211+
return fl_ctx->F;
212+
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
213+
return fl_ctx->F;
214+
return (jl_bkind_is_some_constant(decode_restriction_kind(pku)) ?
215+
decode_restriction_value(pku) : jl_atomic_load_relaxed(&b->value)) != NULL ? fl_ctx->T : fl_ctx->F;
209216
}
210217

211218
static value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) JL_NOTSAFEPOINT

src/builtins.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,19 +1369,10 @@ JL_CALLABLE(jl_f_get_binding_type)
13691369
jl_sym_t *var = (jl_sym_t*)args[1];
13701370
JL_TYPECHK(get_binding_type, module, (jl_value_t*)mod);
13711371
JL_TYPECHK(get_binding_type, symbol, (jl_value_t*)var);
1372-
jl_value_t *ty = jl_get_binding_type(mod, var);
1373-
if (ty == (jl_value_t*)jl_nothing) {
1374-
jl_binding_t *b = jl_get_module_binding(mod, var, 0);
1375-
if (b == NULL)
1376-
return (jl_value_t*)jl_any_type;
1377-
jl_binding_t *b2 = jl_atomic_load_relaxed(&b->owner);
1378-
if (b2 != b)
1379-
return (jl_value_t*)jl_any_type;
1380-
jl_value_t *old_ty = NULL;
1381-
jl_atomic_cmpswap_relaxed(&b->ty, &old_ty, (jl_value_t*)jl_any_type);
1382-
return jl_atomic_load_relaxed(&b->ty);
1383-
}
1384-
return ty;
1372+
jl_value_t *ret = jl_get_binding_type(mod, var);
1373+
if (ret == jl_nothing)
1374+
return (jl_value_t*)jl_any_type;
1375+
return ret;
13851376
}
13861377

13871378
JL_CALLABLE(jl_f_swapglobal)
@@ -2509,6 +2500,7 @@ void jl_init_primitives(void) JL_GC_DISABLED
25092500
add_builtin("QuoteNode", (jl_value_t*)jl_quotenode_type);
25102501
add_builtin("NewvarNode", (jl_value_t*)jl_newvarnode_type);
25112502
add_builtin("Binding", (jl_value_t*)jl_binding_type);
2503+
add_builtin("BindingPartition", (jl_value_t*)jl_binding_partition_type);
25122504
add_builtin("GlobalRef", (jl_value_t*)jl_globalref_type);
25132505
add_builtin("NamedTuple", (jl_value_t*)jl_namedtuple_type);
25142506

src/cgutils.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -568,23 +568,6 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p)
568568
return load;
569569
}
570570

571-
// Returns ctx.types().T_pjlvalue
572-
static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p)
573-
{
574-
// emit a pointer to any jl_value_t which will be valid across reloading code
575-
if (p == NULL)
576-
return Constant::getNullValue(ctx.types().T_pjlvalue);
577-
// bindings are prefixed with jl_bnd#
578-
jl_globalref_t *gr = p->globalref;
579-
Value *pgv = gr ? julia_pgv(ctx, "jl_bnd#", gr->name, gr->mod, p) : julia_pgv(ctx, "jl_bnd#", p);
580-
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const);
581-
auto load = ai.decorateInst(maybe_mark_load_dereferenceable(
582-
ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))),
583-
false, sizeof(jl_binding_t), alignof(jl_binding_t)));
584-
setName(ctx.emission_context, load, pgv->getName());
585-
return load;
586-
}
587-
588571
// bitcast a value, but preserve its address space when dealing with pointer types
589572
static Value *emit_bitcast(jl_codectx_t &ctx, Value *v, Type *jl_value)
590573
{

0 commit comments

Comments
 (0)