Skip to content

Commit cea6a9a

Browse files
authored
codegen: reduce recursion in cfunction generation (#56806)
The regular code-path for this was only missing the age_ok handling, so add in that handling so we can delete the custom path here for the test and some of the brokenness that implied.
1 parent 9118ea7 commit cea6a9a

File tree

9 files changed

+146
-204
lines changed

9 files changed

+146
-204
lines changed

src/aotcompile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ static void compile_workqueue(jl_codegen_params_t &params, egal_set &method_root
505505
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
506506
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
507507
// TODO: maybe this can be cached in codeinst->specfptr?
508-
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
508+
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke);
509509
preal_decl = ""; // no need to fixup the name
510510
}
511511
if (!preal_decl.empty()) {

src/cgutils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx,
22792279
const jl_cgval_t argv[3] = { cmp, lhs, rhs };
22802280
jl_cgval_t ret;
22812281
if (modifyop) {
2282-
ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
2282+
ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type, nullptr);
22832283
}
22842284
else {
22852285
if (trim_may_error(ctx.params->trim)) {
@@ -4018,7 +4018,7 @@ static jl_cgval_t union_store(jl_codectx_t &ctx,
40184018
emit_lockstate_value(ctx, needlock, false);
40194019
const jl_cgval_t argv[3] = { cmp, oldval, rhs };
40204020
if (modifyop) {
4021-
rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
4021+
rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type, nullptr);
40224022
}
40234023
else {
40244024
if (trim_may_error(ctx.params->trim)) {

src/codegen.cpp

Lines changed: 82 additions & 158 deletions
Large diffs are not rendered by default.

src/gf.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,7 +3084,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_match_to_mi(jl_method_match_t *matc
30843084
}
30853085

30863086
// compile-time method lookup
3087-
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache)
3087+
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, int mt_cache)
30883088
{
30893089
if (jl_has_free_typevars((jl_value_t*)types))
30903090
return NULL; // don't poison the cache due to a malformed query
@@ -3096,10 +3096,6 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES
30963096
size_t max_valid2 = ~(size_t)0;
30973097
int ambig = 0;
30983098
jl_value_t *matches = jl_matching_methods(types, jl_nothing, 1, 1, world, &min_valid2, &max_valid2, &ambig);
3099-
if (*min_valid < min_valid2)
3100-
*min_valid = min_valid2;
3101-
if (*max_valid > max_valid2)
3102-
*max_valid = max_valid2;
31033099
if (matches == jl_nothing || jl_array_nrows(matches) != 1 || ambig)
31043100
return NULL;
31053101
JL_GC_PUSH1(&matches);

src/jitlayers.cpp

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
382382
jl_method_instance_t *mi = codeinst->def;
383383
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
384384
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
385-
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
385+
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke);
386386
jl_gc_unsafe_leave(ct->ptls, gc_state);
387387
preal_decl = ""; // no need to fixup the name
388388
}
@@ -713,7 +713,7 @@ static void jl_emit_codeinst_to_jit(
713713
int waiting = jl_analyze_workqueue(codeinst, params);
714714
if (waiting) {
715715
auto release = std::move(params.tsctx_lock); // unlock again before moving from it
716-
incompletemodules.insert(std::pair(codeinst, std::make_tuple(std::move(params), waiting)));
716+
incompletemodules.try_emplace(codeinst, std::move(params), waiting);
717717
}
718718
else {
719719
finish_params(result_m.getModuleUnlocked(), params);
@@ -760,7 +760,7 @@ static void _jl_compile_codeinst(
760760
}
761761

762762

763-
const char *jl_generate_ccallable(LLVMOrcThreadSafeModuleRef llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t &params);
763+
const char *jl_generate_ccallable(Module *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t &params);
764764

765765
// compile a C-callable alias
766766
extern "C" JL_DLLEXPORT_CODEGEN
@@ -774,45 +774,68 @@ int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *
774774
uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
775775
if (measure_compile_time_enabled)
776776
compiler_start_time = jl_hrtime();
777+
jl_codegen_params_t *pparams = (jl_codegen_params_t*)p;
778+
DataLayout DL = pparams ? pparams->DL : jl_ExecutionEngine->getDataLayout();
779+
Triple TargetTriple = pparams ? pparams->TargetTriple : jl_ExecutionEngine->getTargetTriple();
777780
orc::ThreadSafeContext ctx;
778781
auto into = unwrap(llvmmod);
779-
jl_codegen_params_t *pparams = (jl_codegen_params_t*)p;
780782
orc::ThreadSafeModule backing;
783+
bool success = true;
784+
const char *name = "";
785+
SmallVector<jl_code_instance_t*,0> dependencies;
781786
if (into == NULL) {
782-
if (!pparams) {
783-
ctx = jl_ExecutionEngine->makeContext();
784-
}
785-
backing = jl_create_ts_module("cextern", pparams ? pparams->tsctx : ctx, pparams ? pparams->DL : jl_ExecutionEngine->getDataLayout(), pparams ? pparams->TargetTriple : jl_ExecutionEngine->getTargetTriple());
787+
ctx = pparams ? pparams->tsctx : jl_ExecutionEngine->makeContext();
788+
backing = jl_create_ts_module("cextern", ctx, DL, TargetTriple);
786789
into = &backing;
787790
}
788-
bool success = true;
789-
{
790-
auto Lock = into->getContext().getLock();
791-
Module *M = into->getModuleUnlocked();
792-
jl_codegen_params_t params(into->getContext(), M->getDataLayout(), Triple(M->getTargetTriple()));
793-
params.imaging_mode = imaging_default();
791+
{ // params scope
792+
jl_codegen_params_t params(into->getContext(), DL, TargetTriple);
794793
if (pparams == NULL) {
795-
M->getContext().setDiscardValueNames(true);
794+
params.cache = p == NULL;
795+
params.imaging_mode = imaging_default();
796+
params.tsctx.getContext()->setDiscardValueNames(true);
796797
pparams = &params;
797798
}
798-
assert(pparams->tsctx.getContext() == into->getContext().getContext());
799-
const char *name = jl_generate_ccallable(wrap(into), sysimg, declrt, sigt, *pparams);
800-
if (!sysimg) {
801-
jl_unique_gcsafe_lock lock(extern_c_lock);
802-
if (jl_ExecutionEngine->getGlobalValueAddress(name)) {
803-
success = false;
799+
Module &M = *into->getModuleUnlocked();
800+
assert(pparams->tsctx.getContext() == &M.getContext());
801+
name = jl_generate_ccallable(&M, sysimg, declrt, sigt, *pparams);
802+
if (!sysimg && !p) {
803+
{ // drop lock to keep analyzer happy (since it doesn't know we have the only reference to it)
804+
auto release = std::move(params.tsctx_lock);
804805
}
805-
if (success && p == NULL) {
806-
jl_jit_globals(params.global_targets);
807-
assert(params.workqueue.empty());
808-
if (params._shared_module) {
809-
jl_ExecutionEngine->optimizeDLSyms(*params._shared_module); // safepoint
810-
jl_ExecutionEngine->addModule(orc::ThreadSafeModule(std::move(params._shared_module), params.tsctx));
806+
{ // lock scope
807+
jl_unique_gcsafe_lock lock(extern_c_lock);
808+
if (jl_ExecutionEngine->getGlobalValueAddress(name))
809+
success = false;
810+
}
811+
params.tsctx_lock = params.tsctx.getLock(); // re-acquire lock
812+
if (success && params.cache) {
813+
for (auto &it : params.workqueue) {
814+
jl_code_instance_t *codeinst = it.first;
815+
JL_GC_PROMISE_ROOTED(codeinst);
816+
dependencies.push_back(codeinst);
817+
recursive_compile_graph(codeinst, nullptr);
811818
}
819+
jl_analyze_workqueue(nullptr, params, true);
820+
assert(params.workqueue.empty());
821+
finish_params(&M, params);
812822
}
813-
if (success && llvmmod == NULL) {
814-
jl_ExecutionEngine->optimizeDLSyms(*M); // safepoint
815-
jl_ExecutionEngine->addModule(std::move(*into));
823+
}
824+
pparams = nullptr;
825+
}
826+
if (!sysimg && success && llvmmod == NULL) {
827+
{ // lock scope
828+
jl_unique_gcsafe_lock lock(extern_c_lock);
829+
if (!jl_ExecutionEngine->getGlobalValueAddress(name)) {
830+
for (auto dep : dependencies)
831+
jl_compile_codeinst_now(dep);
832+
{
833+
auto Lock = backing.getContext().getLock();
834+
jl_ExecutionEngine->optimizeDLSyms(*backing.getModuleUnlocked()); // safepoint
835+
}
836+
jl_ExecutionEngine->addModule(std::move(backing));
837+
success = jl_ExecutionEngine->getGlobalValueAddress(name);
838+
assert(success);
816839
}
817840
}
818841
}

src/jitlayers.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ struct jl_codegen_params_t {
260260
bool external_linkage = false;
261261
bool imaging_mode;
262262
bool use_swiftcc = true;
263-
jl_codegen_params_t(orc::ThreadSafeContext ctx, DataLayout DL, Triple triple)
263+
jl_codegen_params_t(orc::ThreadSafeContext ctx, DataLayout DL, Triple triple) JL_NOTSAFEPOINT JL_NOTSAFEPOINT_ENTER
264264
: tsctx(std::move(ctx)),
265265
tsctx_lock(tsctx.getLock()),
266266
DL(std::move(DL)),
@@ -271,6 +271,8 @@ struct jl_codegen_params_t {
271271
if (TargetTriple.isRISCV())
272272
use_swiftcc = false;
273273
}
274+
jl_codegen_params_t(jl_codegen_params_t &&) JL_NOTSAFEPOINT = default;
275+
~jl_codegen_params_t() JL_NOTSAFEPOINT JL_NOTSAFEPOINT_LEAVE = default;
274276
};
275277

276278
jl_llvm_functions_t jl_emit_code(
@@ -299,8 +301,7 @@ void emit_specsig_to_fptr1(
299301
jl_value_t *calltype, jl_value_t *rettype, bool is_for_opaque_closure,
300302
size_t nargs,
301303
jl_codegen_params_t &params,
302-
Function *target,
303-
size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
304+
Function *target) JL_NOTSAFEPOINT;
304305
Function *get_or_emit_fptr1(StringRef Name, Module *M) JL_NOTSAFEPOINT;
305306
void jl_init_function(Function *F, const Triple &TT) JL_NOTSAFEPOINT;
306307

src/julia_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ _Atomic(jl_value_t*) *jl_table_peek_bp(jl_genericmemory_t *a, jl_value_t *key) J
11951195
JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*);
11961196

11971197
JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module);
1198-
JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache);
1198+
JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, int mt_cache);
11991199
jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp);
12001200
JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *li JL_PROPAGATES_ROOT, size_t min_world, size_t max_world);
12011201
JL_DLLEXPORT jl_value_t *jl_rettype_inferred_native(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT;

src/precompile_utils.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,8 @@ static void *jl_precompile_(jl_array_t *m, int external_linkage)
264264
jl_value_t *item = jl_array_ptr_ref(m, i);
265265
if (jl_is_method_instance(item)) {
266266
mi = (jl_method_instance_t*)item;
267-
size_t min_world = 0;
268-
size_t max_world = ~(size_t)0;
269267
if (mi != jl_atomic_load_relaxed(&mi->def.method->unspecialized) && !jl_isa_compileable_sig((jl_tupletype_t*)mi->specTypes, mi->sparam_vals, mi->def.method))
270-
mi = jl_get_specialization1((jl_tupletype_t*)mi->specTypes, jl_atomic_load_acquire(&jl_world_counter), &min_world, &max_world, 0);
268+
mi = jl_get_specialization1((jl_tupletype_t*)mi->specTypes, jl_atomic_load_acquire(&jl_world_counter), 0);
271269
if (mi)
272270
jl_array_ptr_1d_push(m2, (jl_value_t*)mi);
273271
}

test/llvmcall.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ module ObjLoadTest
157157
nothing
158158
end
159159
@test_throws(ErrorException("@ccallable was already defined for this method name"),
160-
@eval @ccallable Cvoid jl_the_callback(not_the_method::Int) = "other")
160+
@eval @ccallable String jl_the_callback(not_the_method::Int) = "other")
161161
# Make sure everything up until here gets compiled
162162
@test jl_the_callback() === nothing
163163
@test jl_the_callback(1) == "other"

0 commit comments

Comments
 (0)