Skip to content

Commit

Permalink
Refactor Binding data structures in preparation for partition (#54788)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Keno authored and KristofferC committed Sep 12, 2024
1 parent 5baa07a commit 96f9b6b
Show file tree
Hide file tree
Showing 30 changed files with 1,031 additions and 542 deletions.
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ function load_REPL()
return nothing
end

global active_repl
global active_repl::Any
global active_repl_backend = nothing

function run_fallback_repl(interactive::Bool)
Expand Down
21 changes: 21 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,27 @@ function _fieldnames(@nospecialize t)
return t.name.names
end

const BINDING_KIND_GLOBAL = 0x0
const BINDING_KIND_CONST = 0x1
const BINDING_KIND_CONST_IMPORT = 0x2
const BINDING_KIND_IMPLICIT = 0x3
const BINDING_KIND_EXPLICIT = 0x4
const BINDING_KIND_IMPORTED = 0x5
const BINDING_KIND_FAILED = 0x6
const BINDING_KIND_DECLARED = 0x7
const BINDING_KIND_GUARD = 0x8

function lookup_binding_partition(world::UInt, b::Core.Binding)
ccall(:jl_get_binding_partition, Ref{Core.BindingPartition}, (Any, UInt), b, world)
end

function lookup_binding_partition(world::UInt, gr::Core.GlobalRef)
ccall(:jl_get_globalref_partition, Ref{Core.BindingPartition}, (Any, UInt), gr, world)
end

binding_kind(bpart::Core.BindingPartition) = ccall(:jl_bpart_get_kind, UInt8, (Any,), bpart)
binding_kind(m::Module, s::Symbol) = binding_kind(lookup_binding_partition(tls_world_age(), GlobalRef(m, s)))

"""
fieldname(x::DataType, i::Integer)
Expand Down
6 changes: 3 additions & 3 deletions doc/src/manual/variables-and-scoping.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ ERROR: invalid redefinition of constant x
julia> const y = 1.0
1.0
julia> y = 2.0
julia> const y = 2.0
WARNING: redefinition of constant y. This may fail, cause incorrect answers, or produce other errors.
2.0
```
Expand All @@ -761,7 +761,7 @@ julia> const a = [1]
1-element Vector{Int64}:
1
julia> a = [1]
julia> const a = [1]
WARNING: redefinition of constant a. This may fail, cause incorrect answers, or produce other errors.
1-element Vector{Int64}:
1
Expand All @@ -782,7 +782,7 @@ f (generic function with 1 method)
julia> f()
1
julia> x = 2
julia> const x = 2
WARNING: redefinition of constant x. This may fail, cause incorrect answers, or produce other errors.
2
Expand Down
13 changes: 10 additions & 3 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint
jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx);
jl_sym_t *var = scmsym_to_julia(fl_ctx, args[0]);
jl_binding_t *b = jl_get_module_binding(ctx->module, var, 0);
return (b != NULL && jl_atomic_load_relaxed(&b->owner) == b) ? fl_ctx->T : fl_ctx->F;
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;
}

static value_t fl_nothrow_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
Expand Down Expand Up @@ -204,8 +205,14 @@ static value_t fl_nothrow_julia_global(fl_context_t *fl_ctx, value_t *args, uint
var = scmsym_to_julia(fl_ctx, args[1]);
}
jl_binding_t *b = jl_get_module_binding(mod, var, 0);
b = b ? jl_atomic_load_relaxed(&b->owner) : NULL;
return b != NULL && jl_atomic_load_relaxed(&b->value) != NULL ? fl_ctx->T : fl_ctx->F;
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);
if (!bpart)
return fl_ctx->F;
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
return fl_ctx->F;
return (jl_bkind_is_some_constant(decode_restriction_kind(pku)) ?
decode_restriction_value(pku) : jl_atomic_load_relaxed(&b->value)) != NULL ? fl_ctx->T : fl_ctx->F;
}

static value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) JL_NOTSAFEPOINT
Expand Down
18 changes: 5 additions & 13 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1369,19 +1369,10 @@ JL_CALLABLE(jl_f_get_binding_type)
jl_sym_t *var = (jl_sym_t*)args[1];
JL_TYPECHK(get_binding_type, module, (jl_value_t*)mod);
JL_TYPECHK(get_binding_type, symbol, (jl_value_t*)var);
jl_value_t *ty = jl_get_binding_type(mod, var);
if (ty == (jl_value_t*)jl_nothing) {
jl_binding_t *b = jl_get_module_binding(mod, var, 0);
if (b == NULL)
return (jl_value_t*)jl_any_type;
jl_binding_t *b2 = jl_atomic_load_relaxed(&b->owner);
if (b2 != b)
return (jl_value_t*)jl_any_type;
jl_value_t *old_ty = NULL;
jl_atomic_cmpswap_relaxed(&b->ty, &old_ty, (jl_value_t*)jl_any_type);
return jl_atomic_load_relaxed(&b->ty);
}
return ty;
jl_value_t *ret = jl_get_binding_type(mod, var);
if (ret == jl_nothing)
return (jl_value_t*)jl_any_type;
return ret;
}

JL_CALLABLE(jl_f_swapglobal)
Expand Down Expand Up @@ -2509,6 +2500,7 @@ void jl_init_primitives(void) JL_GC_DISABLED
add_builtin("QuoteNode", (jl_value_t*)jl_quotenode_type);
add_builtin("NewvarNode", (jl_value_t*)jl_newvarnode_type);
add_builtin("Binding", (jl_value_t*)jl_binding_type);
add_builtin("BindingPartition", (jl_value_t*)jl_binding_partition_type);
add_builtin("GlobalRef", (jl_value_t*)jl_globalref_type);
add_builtin("NamedTuple", (jl_value_t*)jl_namedtuple_type);

Expand Down
17 changes: 0 additions & 17 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,23 +568,6 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p)
return load;
}

// Returns ctx.types().T_pjlvalue
static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p)
{
// emit a pointer to any jl_value_t which will be valid across reloading code
if (p == NULL)
return Constant::getNullValue(ctx.types().T_pjlvalue);
// bindings are prefixed with jl_bnd#
jl_globalref_t *gr = p->globalref;
Value *pgv = gr ? julia_pgv(ctx, "jl_bnd#", gr->name, gr->mod, p) : julia_pgv(ctx, "jl_bnd#", p);
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const);
auto load = ai.decorateInst(maybe_mark_load_dereferenceable(
ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))),
false, sizeof(jl_binding_t), alignof(jl_binding_t)));
setName(ctx.emission_context, load, pgv->getName());
return load;
}

// bitcast a value, but preserve its address space when dealing with pointer types
static Value *emit_bitcast(jl_codectx_t &ctx, Value *v, Type *jl_value)
{
Expand Down
Loading

0 comments on commit 96f9b6b

Please sign in to comment.