Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpart: Also partition ->deprecated #57449

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Compiler/src/Compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ using Core: ABIOverride, Builtin, CodeInstance, IntrinsicFunction, MethodInstanc
using Base
using Base: @_foldable_meta, @_gc_preserve_begin, @_gc_preserve_end, @nospecializeinfer,
BINDING_KIND_GLOBAL, BINDING_KIND_UNDEF_CONST, BINDING_KIND_BACKDATED_CONST, BINDING_KIND_DECLARED,
BINDING_FLAG_DEPWARN,
Base, BitVector, Bottom, Callable, DataTypeFieldDesc,
EffectsOverride, Filter, Generator, IteratorSize, JLOptions, NUM_EFFECTS_OVERRIDES,
OneTo, Ordering, RefValue, SizeUnknown, _NAMEDTUPLE_NAME,
Expand Down
14 changes: 9 additions & 5 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2391,7 +2391,7 @@ function abstract_throw_methoderror(interp::AbstractInterpreter, argtypes::Vecto
return Future(CallMeta(Union{}, exct, EFFECTS_THROWS, NoCallInfo()))
end

const generic_getglobal_effects = Effects(EFFECTS_THROWS, consistent=ALWAYS_FALSE, inaccessiblememonly=ALWAYS_FALSE)
const generic_getglobal_effects = Effects(EFFECTS_THROWS, effect_free=ALWAYS_FALSE, consistent=ALWAYS_FALSE, inaccessiblememonly=ALWAYS_FALSE) #= effect_free for depwarn =#
const generic_getglobal_exct = Union{ArgumentError, TypeError, ConcurrencyViolationError, UndefVarError}
function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, @nospecialize(M), @nospecialize(s))
⊑ = partialorder(typeinf_lattice(interp))
Expand Down Expand Up @@ -3519,32 +3519,36 @@ end

function abstract_eval_partition_load(interp::AbstractInterpreter, partition::Core.BindingPartition)
kind = binding_kind(partition)
isdepwarn = (partition.kind & BINDING_FLAG_DEPWARN) != 0
local_getglobal_effects = Effects(generic_getglobal_effects, effect_free=isdepwarn ? ALWAYS_FALSE : ALWAYS_TRUE)
if is_some_guard(kind) || kind == BINDING_KIND_UNDEF_CONST
if InferenceParams(interp).assume_bindings_static
return RTEffects(Union{}, UndefVarError, EFFECTS_THROWS)
else
# We do not currently assume an invalidation for guard -> defined transitions
# return RTEffects(Union{}, UndefVarError, EFFECTS_THROWS)
return RTEffects(Any, UndefVarError, generic_getglobal_effects)
return RTEffects(Any, UndefVarError, local_getglobal_effects)
end
end

if is_defined_const_binding(kind)
if kind == BINDING_KIND_BACKDATED_CONST
# Infer this as guard. We do not want a later const definition to retroactively improve
# inference results in an earlier world.
return RTEffects(Any, UndefVarError, generic_getglobal_effects)
return RTEffects(Any, UndefVarError, local_getglobal_effects)
end
rt = Const(partition_restriction(partition))
return RTEffects(rt, Union{}, Effects(EFFECTS_TOTAL, inaccessiblememonly=is_mutation_free_argtype(rt) ? ALWAYS_TRUE : ALWAYS_FALSE))
return RTEffects(rt, Union{}, Effects(EFFECTS_TOTAL,
inaccessiblememonly=is_mutation_free_argtype(rt) ? ALWAYS_TRUE : ALWAYS_FALSE,
effect_free=isdepwarn ? ALWAYS_FALSE : ALWAYS_TRUE))
end

if kind == BINDING_KIND_DECLARED
rt = Any
else
rt = partition_restriction(partition)
end
return RTEffects(rt, UndefVarError, generic_getglobal_effects)
return RTEffects(rt, UndefVarError, local_getglobal_effects)
end

function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, saw_latestworld::Bool, sv::AbsIntState)
Expand Down
5 changes: 5 additions & 0 deletions base/runtime_internals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ const BINDING_KIND_UNDEF_CONST = 0x9
const BINDING_KIND_BACKDATED_CONST = 0xa

const BINDING_FLAG_EXPORTED = 0x10
const BINDING_FLAG_DEPRECATED = 0x20
const BINDING_FLAG_DEPWARN = 0x40

const BINDING_KIND_MASK = 0x0f
const BINDING_FLAG_MASK = 0xf0

is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_BACKDATED_CONST)
is_some_const_binding(kind::UInt8) = (is_defined_const_binding(kind) || kind == BINDING_KIND_UNDEF_CONST)
Expand Down
17 changes: 15 additions & 2 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3375,8 +3375,21 @@ function print_partition(io::IO, partition::Core.BindingPartition)
else
print(io, max_world)
end
if (partition.kind & BINDING_FLAG_EXPORTED) != 0
print(io, " [exported]")
if (partition.kind & BINDING_FLAG_MASK) != 0
first = false
print(io, " [")
if (partition.kind & BINDING_FLAG_EXPORTED) != 0
print(io, "exported")
end
if (partition.kind & BINDING_FLAG_DEPRECATED) != 0
first ? (first = false) : print(io, ",")
print(io, "deprecated")
end
if (partition.kind & BINDING_FLAG_DEPWARN) != 0
first ? (first = false) : print(io, ",")
print(io, "depwarn")
end
print(io, "]")
end
print(io, " - ")
kind = binding_kind(partition)
Expand Down
119 changes: 59 additions & 60 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,13 +907,12 @@ static const auto jldeclareglobal_func = new JuliaFunction<>{
{T_pjlvalue, T_pjlvalue, T_prjlvalue, getInt32Ty(C)}, false); },
nullptr,
};
static const auto jlgetbindingorerror_func = new JuliaFunction<>{
XSTR(jl_get_binding_or_error),
static const auto jldepcheck_func = new JuliaFunction<>{
XSTR(jl_binding_deprecation_check),
[](LLVMContext &C) {
auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
return FunctionType::get(T_pjlvalue,
{T_pjlvalue, T_pjlvalue}, false);
},
return FunctionType::get(getVoidTy(C),
{T_pjlvalue}, false); },
nullptr,
};
static const auto jlcheckbpwritable_func = new JuliaFunction<>{
Expand Down Expand Up @@ -3067,20 +3066,6 @@ static void mallocVisitLine(jl_codectx_t &ctx, StringRef filename, int line, Val

// --- constant determination ---

static void show_source_loc(jl_codectx_t &ctx, JL_STREAM *out)
{
jl_printf(out, "in %s at %s", ctx.name, ctx.file.str().c_str());
}

static void cg_bdw(jl_codectx_t &ctx, jl_sym_t *var, jl_binding_t *b)
{
jl_binding_deprecation_warning(ctx.module, var, b);
if (b->deprecated == 1 && jl_options.depwarn) {
show_source_loc(ctx, JL_STDERR);
jl_printf(JL_STDERR, "\n");
}
}

static jl_value_t *static_apply_type(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> args, size_t nargs)
{
assert(nargs > 1);
Expand All @@ -3105,6 +3090,12 @@ static jl_value_t *static_apply_type(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> arg
return result;
}

static void emit_depwarn_check(jl_codectx_t &ctx, jl_binding_t *b)
{
Value *bp = julia_binding_gv(ctx, b);
ctx.builder.CreateCall(prepare_call(jldepcheck_func), { bp });
}

// try to statically evaluate, NULL if not possible. note that this may allocate, and as
// such the resulting value should not be embedded directly in the generated code.
static jl_value_t *static_eval(jl_codectx_t &ctx, jl_value_t *ex)
Expand All @@ -3113,9 +3104,13 @@ 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_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
if (bpart && jl_bkind_is_some_constant(jl_binding_kind(bpart)))
int possibly_deprecated = 0;
jl_walk_binding_inplace_all(&bnd, &bpart, &possibly_deprecated, ctx.min_world, ctx.max_world);
if (bpart && jl_bkind_is_some_constant(jl_binding_kind(bpart))) {
if (possibly_deprecated)
emit_depwarn_check(ctx, bnd);
return bpart->restriction;
}
return NULL;
}
if (jl_is_slotnumber(ex) || jl_is_argument(ex))
Expand All @@ -3138,13 +3133,14 @@ 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_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
int possibly_deprecated = 0;
jl_walk_binding_inplace_all(&bnd, &bpart, &possibly_deprecated, ctx.min_world, ctx.max_world);
jl_value_t *v = NULL;
if (bpart && jl_bkind_is_some_constant(jl_binding_kind(bpart)))
v = bpart->restriction;
if (v) {
if (bnd->deprecated)
cg_bdw(ctx, s, bnd);
if (possibly_deprecated)
emit_depwarn_check(ctx, bnd);
return v;
}
return NULL;
Expand All @@ -3165,13 +3161,14 @@ 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_walk_binding_inplace_all(&bnd, &bpart, ctx.min_world, ctx.max_world);
int possibly_deprecated = 0;
jl_walk_binding_inplace_all(&bnd, &bpart, &possibly_deprecated, ctx.min_world, ctx.max_world);
jl_value_t *v = NULL;
if (bpart && jl_bkind_is_some_constant(jl_binding_kind(bpart)))
v = bpart->restriction;
if (v) {
if (bnd->deprecated)
cg_bdw(ctx, s, bnd);
if (possibly_deprecated)
emit_depwarn_check(ctx, bnd);
return v;
}
}
Expand Down Expand Up @@ -3417,48 +3414,47 @@ 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);
}
// bpart was updated in place - this will change with full partition
if (jl_bkind_is_some_guard(jl_binding_kind(bpart))) {
// 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(jl_binding_kind(bpart)))
break;
if (bnd->deprecated) {
cg_bdw(ctx, name, bnd);
}
bnd = (jl_binding_t*)bpart->restriction;
bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
if (!bpart)
break;
}
if (bpart) {
enum jl_partition_kind kind = jl_binding_kind(bpart);
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);
int possibly_deprecated = 0;
int saw_explicit = 0;
while (bpart) {
if (!saw_explicit && (bpart->kind & BINDING_FLAG_DEPWARN))
possibly_deprecated = 1;
enum jl_partition_kind kind = jl_binding_kind(bpart);
if (!jl_bkind_is_some_import(kind))
break;
if (kind != BINDING_KIND_IMPLICIT)
saw_explicit = 1;
bnd = (jl_binding_t*)bpart->restriction;
bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
}
Value *bp = NULL;
if (bpart) {
enum jl_partition_kind kind = jl_binding_kind(bpart);
if (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST) {
if (possibly_deprecated) {
bp = julia_binding_gv(ctx, bnd);
ctx.builder.CreateCall(prepare_call(jldepcheck_func), { bp });
}
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);
}
}
if (!bpart || jl_binding_kind(bpart) != 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);
bp = julia_binding_gv(ctx, bnd);
if (possibly_deprecated) {
ctx.builder.CreateCall(prepare_call(jldepcheck_func), { bp });
}
jl_value_t *ty = bpart->restriction;
bp = julia_binding_pvalue(ctx, bp);
Value *bpval = julia_binding_pvalue(ctx, bp);
if (ty == nullptr)
ty = (jl_value_t*)jl_any_type;
return update_julia_type(ctx, emit_checked_var(ctx, bp, name, (jl_value_t*)mod, false, ctx.tbaa().tbaa_binding), ty);
return update_julia_type(ctx, emit_checked_var(ctx, bpval, name, (jl_value_t*)mod, false, ctx.tbaa().tbaa_binding), ty);
}

static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *sym, jl_cgval_t rval, const jl_cgval_t &cmp,
Expand All @@ -3471,6 +3467,7 @@ static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *s
Value *bp = julia_binding_gv(ctx, bnd);
if (bpart) {
if (jl_binding_kind(bpart) == BINDING_KIND_GLOBAL) {
int possibly_deprecated = bpart->kind & BINDING_FLAG_DEPWARN;
jl_value_t *ty = bpart->restriction;
if (ty != nullptr) {
const std::string fname = issetglobal ? "setglobal!" : isreplaceglobal ? "replaceglobal!" : isswapglobal ? "swapglobal!" : ismodifyglobal ? "modifyglobal!" : "setglobalonce!";
Expand All @@ -3483,6 +3480,9 @@ static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *s
}
bool isboxed = true;
bool maybe_null = jl_atomic_load_relaxed(&bnd->value) == NULL;
if (possibly_deprecated) {
ctx.builder.CreateCall(prepare_call(jldepcheck_func), { bp });
}
return typed_store(ctx,
julia_binding_pvalue(ctx, bp),
rval, cmp, ty,
Expand Down Expand Up @@ -10308,7 +10308,6 @@ static void init_jit_functions(void)
add_named_global(memcmp_func, &memcmp);
add_named_global(jltypeerror_func, &jl_type_error);
add_named_global(jlcheckassign_func, &jl_checked_assignment);
add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error);
add_named_global(jlcheckbpwritable_func, &jl_check_binding_currently_writable);
add_named_global(jlboundp_func, &jl_boundp);
for (auto it : builtin_func_map())
Expand Down
1 change: 0 additions & 1 deletion src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@
XX(jl_get_backtrace) \
XX(jl_get_binding) \
XX(jl_get_binding_for_method_def) \
XX(jl_get_binding_or_error) \
XX(jl_get_binding_wr) \
XX(jl_check_binding_currently_writable) \
XX(jl_get_cpu_name) \
Expand Down
16 changes: 14 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,21 @@ enum jl_partition_kind {
BINDING_KIND_IMPLICIT_RECOMPUTE = 0xb
};

// These are flags that get anded into the above
static const uint8_t BINDING_KIND_MASK = 0x0f;
static const uint8_t BINDING_FLAG_MASK = 0xf0;

//// These are flags that get anded into the above
//
// _EXPORTED: This binding partition is exported. In the world ranges covered by this partitions,
// other modules that `using` this module, may implicit import this binding.
static const uint8_t BINDING_FLAG_EXPORTED = 0x10;
// _DEPRECATED: This binding partition is deprecated. It is considered weak for the purposes of
// implicit import resolution.
static const uint8_t BINDING_FLAG_DEPRECATED = 0x20;
// _DEPWARN: This binding partition will print a deprecation warning on access. Note that _DEPWARN
// implies _DEPRECATED. However, the reverse is not true. Such bindings are usually used for functions,
// where calling the function itself will provide a (better) deprecation warning/error.
static const uint8_t BINDING_FLAG_DEPWARN = 0x40;

typedef struct __attribute__((aligned(8))) _jl_binding_partition_t {
JL_DATA_TYPE
Expand Down Expand Up @@ -2054,7 +2067,6 @@ JL_DLLEXPORT jl_value_t *jl_get_module_binding_or_nothing(jl_module_t *m, jl_sym

// get binding for reading
JL_DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var);
JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var);
JL_DLLEXPORT jl_value_t *jl_get_binding_type(jl_module_t *m, jl_sym_t *var);
// get binding for assignment
Expand Down
Loading