Skip to content

Commit 447dc2d

Browse files
authored
fix world_age_at_entry in codegen (JuliaLang#56700)
1 parent 9162b14 commit 447dc2d

File tree

3 files changed

+46
-50
lines changed

3 files changed

+46
-50
lines changed

src/ccall.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,18 +1712,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17121712
return ghostValue(ctx, jl_nothing_type);
17131713
}
17141714
else if (is_libjulia_func(jl_get_tls_world_age)) {
1715-
bool toplevel = !(ctx.linfo && jl_is_method(ctx.linfo->def.method));
1716-
if (!toplevel) { // top level code does not see a stable world age during execution
1717-
++CCALL_STAT(jl_get_tls_world_age);
1718-
assert(lrt == ctx.types().T_size);
1719-
assert(!isVa && !llvmcall && nccallargs == 0);
1720-
JL_GC_POP();
1721-
Instruction *world_age = cast<Instruction>(ctx.world_age_at_entry);
1722-
setName(ctx.emission_context, world_age, "task_world_age");
1723-
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe);
1724-
ai.decorateInst(world_age);
1725-
return mark_or_box_ccall_result(ctx, world_age, retboxed, rt, unionall, static_rt);
1726-
}
1715+
++CCALL_STAT(jl_get_tls_world_age);
1716+
assert(lrt == ctx.types().T_size);
1717+
assert(!isVa && !llvmcall && nccallargs == 0);
1718+
JL_GC_POP();
1719+
Value *world_age = get_tls_world_age(ctx);
1720+
return mark_or_box_ccall_result(ctx, world_age, retboxed, rt, unionall, static_rt);
17271721
}
17281722
else if (is_libjulia_func(jl_get_world_counter)) {
17291723
++CCALL_STAT(jl_get_world_counter);

src/codegen.cpp

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ class jl_codectx_t {
19851985

19861986
Value *pgcstack = NULL;
19871987
Instruction *topalloca = NULL;
1988-
Value *world_age_at_entry = NULL; // Not valid to use in toplevel code
1988+
Value *world_age_at_entry = NULL;
19891989

19901990
bool use_cache = false;
19911991
bool external_linkage = false;
@@ -2115,6 +2115,7 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i);
21152115
static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const Twine &msg);
21162116
static Value *get_current_task(jl_codectx_t &ctx);
21172117
static Value *get_current_ptls(jl_codectx_t &ctx);
2118+
static Value *get_tls_world_age(jl_codectx_t &ctx);
21182119
static Value *get_scope_field(jl_codectx_t &ctx);
21192120
static Value *get_tls_world_age_field(jl_codectx_t &ctx);
21202121
static void CreateTrap(IRBuilder<> &irbuilder, bool create_new_block = true);
@@ -7044,11 +7045,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
70447045
std::tie(F, specF) = get_oc_function(ctx, (jl_method_t*)source.constant, (jl_tupletype_t*)env_t, argt_typ, ub.constant);
70457046
if (F) {
70467047
jl_cgval_t jlcall_ptr = mark_julia_type(ctx, F, false, jl_voidpointer_type);
7047-
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe);
7048-
bool not_toplevel = (ctx.linfo && jl_is_method(ctx.linfo->def.method));
7049-
Instruction *I = not_toplevel ? cast<Instruction>(ctx.world_age_at_entry) :
7050-
ctx.builder.CreateAlignedLoad(ctx.types().T_size, get_tls_world_age_field(ctx), ctx.types().alignof_ptr);
7051-
jl_cgval_t world_age = mark_julia_type(ctx, ai.decorateInst(I), false, jl_long_type);
7048+
jl_cgval_t world_age = mark_julia_type(ctx, get_tls_world_age(ctx), false, jl_long_type);
70527049
jl_cgval_t fptr;
70537050
if (specF)
70547051
fptr = mark_julia_type(ctx, specF, false, jl_voidpointer_type);
@@ -7207,6 +7204,25 @@ static Value *get_tls_world_age_field(jl_codectx_t &ctx)
72077204
return emit_ptrgep(ctx, ct, offsetof(jl_task_t, world_age), "world_age");
72087205
}
72097206

7207+
// Get the value of the world age of the current task
7208+
static Value *get_tls_world_age(jl_codectx_t &ctx)
7209+
{
7210+
if (ctx.world_age_at_entry)
7211+
return ctx.world_age_at_entry;
7212+
IRBuilderBase::InsertPointGuard IP(ctx.builder);
7213+
bool toplevel = !jl_is_method(ctx.linfo->def.method);
7214+
if (!toplevel) {
7215+
ctx.builder.SetInsertPoint(ctx.topalloca->getParent(), ++ctx.topalloca->getIterator());
7216+
ctx.builder.SetCurrentDebugLocation(ctx.topalloca->getStableDebugLoc());
7217+
}
7218+
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe);
7219+
auto *world = ctx.builder.CreateAlignedLoad(ctx.types().T_size, get_tls_world_age_field(ctx), ctx.types().alignof_ptr);
7220+
ai.decorateInst(world);
7221+
if (!toplevel)
7222+
ctx.world_age_at_entry = world;
7223+
return world;
7224+
}
7225+
72107226
static Value *get_scope_field(jl_codectx_t &ctx)
72117227
{
72127228
Value *ct = get_current_task(ctx);
@@ -7524,9 +7540,8 @@ static Function* gen_cfun_wrapper(
75247540

75257541
auto world_age_field = get_tls_world_age_field(ctx);
75267542
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe);
7527-
Value *last_age = ai.decorateInst(
7543+
ctx.world_age_at_entry = ai.decorateInst(
75287544
ctx.builder.CreateAlignedLoad(ctx.types().T_size, world_age_field, ctx.types().alignof_ptr));
7529-
ctx.world_age_at_entry = last_age;
75307545
Value *world_v = ctx.builder.CreateAlignedLoad(ctx.types().T_size,
75317546
prepare_global_in(jl_Module, jlgetworld_global), ctx.types().alignof_ptr);
75327547
cast<LoadInst>(world_v)->setOrdering(AtomicOrdering::Acquire);
@@ -7808,7 +7823,7 @@ static Function* gen_cfun_wrapper(
78087823
r = NULL;
78097824
}
78107825

7811-
ctx.builder.CreateStore(last_age, world_age_field);
7826+
ctx.builder.CreateStore(ctx.world_age_at_entry, world_age_field);
78127827
ctx.builder.CreateRet(r);
78137828

78147829
ctx.builder.SetCurrentDebugLocation(noDbg);
@@ -8418,7 +8433,6 @@ static jl_llvm_functions_t
84188433
ctx.source = src;
84198434

84208435
std::map<int, BasicBlock*> labels;
8421-
bool toplevel = false;
84228436
ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module;
84238437
ctx.linfo = lam;
84248438
ctx.name = TSM.getModuleUnlocked()->getModuleIdentifier().data();
@@ -8438,7 +8452,6 @@ static jl_llvm_functions_t
84388452
if (vn != jl_unused_sym)
84398453
ctx.vaSlot = ctx.nargs - 1;
84408454
}
8441-
toplevel = !jl_is_method(lam->def.method);
84428455
ctx.rettype = jlrettype;
84438456
ctx.funcName = ctx.name;
84448457
ctx.spvals_ptr = NULL;
@@ -8776,12 +8789,12 @@ static jl_llvm_functions_t
87768789
// step 6. set up GC frame
87778790
allocate_gc_frame(ctx, b0);
87788791
Value *last_age = NULL;
8779-
auto world_age_field = get_tls_world_age_field(ctx);
8780-
{ // scope
8792+
Value *world_age_field = NULL;
8793+
if (ctx.is_opaque_closure) {
8794+
world_age_field = get_tls_world_age_field(ctx);
87818795
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe);
87828796
last_age = ai.decorateInst(ctx.builder.CreateAlignedLoad(
87838797
ctx.types().T_size, world_age_field, ctx.types().alignof_ptr));
8784-
ctx.world_age_at_entry = last_age; // Load world age for use in get_tls_world_age
87858798
}
87868799

87878800
// step 7. allocate local variables slots
@@ -9005,6 +9018,7 @@ static jl_llvm_functions_t
90059018
Value *worldaddr = emit_ptrgep(ctx, oc_this, offsetof(jl_opaque_closure_t, world));
90069019
jl_cgval_t closure_world = typed_load(ctx, worldaddr, NULL, (jl_value_t*)jl_long_type,
90079020
nullptr, nullptr, false, AtomicOrdering::NotAtomic, false, ctx.types().alignof_ptr.value());
9021+
assert(ctx.world_age_at_entry == nullptr);
90089022
ctx.world_age_at_entry = closure_world.V; // The tls world in a OC is the world of the closure
90099023
emit_unbox_store(ctx, closure_world, world_age_field, ctx.tbaa().tbaa_gcframe, ctx.types().alignof_ptr);
90109024

@@ -9282,19 +9296,11 @@ static jl_llvm_functions_t
92829296

92839297
Instruction &prologue_end = ctx.builder.GetInsertBlock()->back();
92849298

9285-
// step 11a. For top-level code, load the world age
9286-
if (toplevel && !ctx.is_opaque_closure) {
9287-
LoadInst *world = ctx.builder.CreateAlignedLoad(ctx.types().T_size,
9288-
prepare_global_in(jl_Module, jlgetworld_global), ctx.types().alignof_ptr);
9289-
world->setOrdering(AtomicOrdering::Acquire);
9290-
ctx.builder.CreateAlignedStore(world, world_age_field, ctx.types().alignof_ptr);
9291-
}
9292-
9293-
// step 11b. Emit the entry safepoint
9299+
// step 11a. Emit the entry safepoint
92949300
if (JL_FEAT_TEST(ctx, safepoint_on_entry))
92959301
emit_gc_safepoint(ctx.builder, ctx.types().T_size, get_current_ptls(ctx), ctx.tbaa().tbaa_const);
92969302

9297-
// step 11c. Do codegen in control flow order
9303+
// step 11b. Do codegen in control flow order
92989304
SmallVector<int, 0> workstack;
92999305
std::map<int, BasicBlock*> BB;
93009306
std::map<size_t, BasicBlock*> come_from_bb;
@@ -9966,8 +9972,7 @@ static jl_llvm_functions_t
99669972
Instruction *root = cast_or_null<Instruction>(ctx.slots[ctx.vaSlot].boxroot);
99679973
if (root) {
99689974
bool have_real_use = false;
9969-
for (Use &U : root->uses()) {
9970-
User *RU = U.getUser();
9975+
for (User *RU : root->users()) {
99719976
if (StoreInst *SRU = dyn_cast<StoreInst>(RU)) {
99729977
assert(isa<ConstantPointerNull>(SRU->getValueOperand()) || SRU->getValueOperand() == restTuple);
99739978
(void)SRU;
@@ -9986,21 +9991,21 @@ static jl_llvm_functions_t
99869991
}
99879992
}
99889993
if (!have_real_use) {
9989-
Instruction *use = NULL;
9990-
for (Use &U : root->uses()) {
9991-
if (use) // erase after the iterator moves on
9992-
use->eraseFromParent();
9993-
User *RU = U.getUser();
9994-
use = cast<Instruction>(RU);
9994+
for (User *RU : make_early_inc_range(root->users())) {
9995+
// This is safe because it checked above that each User is known and has at most one Use of root
9996+
cast<Instruction>(RU)->eraseFromParent();
99959997
}
9996-
if (use)
9997-
use->eraseFromParent();
99989998
root->eraseFromParent();
99999999
restTuple->eraseFromParent();
1000010000
}
1000110001
}
1000210002
}
1000310003

10004+
if (ctx.topalloca->use_empty()) {
10005+
ctx.topalloca->eraseFromParent();
10006+
ctx.topalloca = nullptr;
10007+
}
10008+
1000410009
// link the dependent llvmcall modules, but switch their function's linkage to internal
1000510010
// so that they don't conflict when they show up in the execution engine.
1000610011
Linker L(*jl_Module);

src/toplevel.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,10 +1050,7 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_val
10501050
// use codegen
10511051
mfunc = jl_method_instance_for_thunk(thk, m);
10521052
jl_resolve_globals_in_ir((jl_array_t*)thk->code, m, NULL, 0);
1053-
// Don't infer blocks containing e.g. method definitions, since it's probably not
1054-
// worthwhile and also unsound (see #24316).
1055-
// TODO: This is still not correct since an `eval` can happen elsewhere, but it
1056-
// helps in common cases.
1053+
// Don't infer blocks containing e.g. method definitions, since it's probably not worthwhile.
10571054
size_t world = jl_atomic_load_acquire(&jl_world_counter);
10581055
ct->world_age = world;
10591056
if (!has_defs && jl_get_module_infer(m) != 0) {

0 commit comments

Comments
 (0)