Skip to content

Commit

Permalink
codegen: reduce recursion in cfunction generation
Browse files Browse the repository at this point in the history
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 all of the brokenness that implied.
  • Loading branch information
vtjnash committed Dec 11, 2024
1 parent d269d7d commit a6aae8a
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 189 deletions.
2 changes: 1 addition & 1 deletion src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ static void compile_workqueue(jl_codegen_params_t &params, egal_set &method_root
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
// TODO: maybe this can be cached in codeinst->specfptr?
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke);
preal_decl = ""; // no need to fixup the name
}
if (!preal_decl.empty()) {
Expand Down
4 changes: 2 additions & 2 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2279,7 +2279,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx,
const jl_cgval_t argv[3] = { cmp, lhs, rhs };
jl_cgval_t ret;
if (modifyop) {
ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
ret = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type, nullptr);
}
else {
if (trim_may_error(ctx.params->trim)) {
Expand Down Expand Up @@ -4018,7 +4018,7 @@ static jl_cgval_t union_store(jl_codectx_t &ctx,
emit_lockstate_value(ctx, needlock, false);
const jl_cgval_t argv[3] = { cmp, oldval, rhs };
if (modifyop) {
rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type);
rhs = emit_invoke(ctx, *modifyop, argv, 3, (jl_value_t*)jl_any_type, nullptr);
}
else {
if (trim_may_error(ctx.params->trim)) {
Expand Down
231 changes: 78 additions & 153 deletions src/codegen.cpp

Large diffs are not rendered by default.

6 changes: 1 addition & 5 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3084,7 +3084,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_match_to_mi(jl_method_match_t *matc
}

// compile-time method lookup
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)
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, int mt_cache)
{
if (jl_has_free_typevars((jl_value_t*)types))
return NULL; // don't poison the cache due to a malformed query
Expand All @@ -3096,10 +3096,6 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES
size_t max_valid2 = ~(size_t)0;
int ambig = 0;
jl_value_t *matches = jl_matching_methods(types, jl_nothing, 1, 1, world, &min_valid2, &max_valid2, &ambig);
if (*min_valid < min_valid2)
*min_valid = min_valid2;
if (*max_valid > max_valid2)
*max_valid = max_valid2;
if (matches == jl_nothing || jl_array_nrows(matches) != 1 || ambig)
return NULL;
JL_GC_PUSH1(&matches);
Expand Down
56 changes: 35 additions & 21 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
jl_method_instance_t *mi = codeinst->def;
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke);
jl_gc_unsafe_leave(ct->ptls, gc_state);
preal_decl = ""; // no need to fixup the name
}
Expand Down Expand Up @@ -760,7 +760,7 @@ static void _jl_compile_codeinst(
}


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

// compile a C-callable alias
extern "C" JL_DLLEXPORT_CODEGEN
Expand All @@ -786,33 +786,47 @@ int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *
into = &backing;
}
bool success = true;
{
auto Lock = into->getContext().getLock();
Module *M = into->getModuleUnlocked();
jl_codegen_params_t params(into->getContext(), M->getDataLayout(), Triple(M->getTargetTriple()));
const char *name = "";
SmallVector<jl_code_instance_t*,0> dependencies;
into->withModuleDo([&](Module &M) {
jl_codegen_params_t params(into->getContext(), M.getDataLayout(), Triple(M.getTargetTriple()));
params.cache = p == NULL;
params.imaging_mode = imaging_default();
if (pparams == NULL) {
M->getContext().setDiscardValueNames(true);
M.getContext().setDiscardValueNames(true);
pparams = &params;
}
assert(pparams->tsctx.getContext() == into->getContext().getContext());
const char *name = jl_generate_ccallable(wrap(into), sysimg, declrt, sigt, *pparams);
assert(pparams->tsctx.getContext() == &M.getContext());
name = jl_generate_ccallable(&M, sysimg, declrt, sigt, *pparams);
if (!sysimg) {
jl_unique_gcsafe_lock lock(extern_c_lock);
if (jl_ExecutionEngine->getGlobalValueAddress(name)) {
success = false;
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (jl_ExecutionEngine->getGlobalValueAddress(name))
success = false;
}
if (success && p == NULL) {
jl_jit_globals(params.global_targets);
assert(params.workqueue.empty());
if (params._shared_module) {
jl_ExecutionEngine->optimizeDLSyms(*params._shared_module); // safepoint
jl_ExecutionEngine->addModule(orc::ThreadSafeModule(std::move(params._shared_module), params.tsctx));
if (success && params.cache) {
for (auto &it : params.workqueue) {
dependencies.push_back(it.first);
recursive_compile_graph(it.first, nullptr);
}
jl_analyze_workqueue(nullptr, *pparams, true);
assert(params.workqueue.empty());
finish_params(&M, params);
}
if (success && llvmmod == NULL) {
jl_ExecutionEngine->optimizeDLSyms(*M); // safepoint
jl_ExecutionEngine->addModule(std::move(*into));
}
});
if (!sysimg && success && llvmmod == NULL) {
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (!jl_ExecutionEngine->getGlobalValueAddress(name)) {
into->withModuleDo([&](Module &M) {
jl_ExecutionEngine->optimizeDLSyms(M); // safepoint
});
for (auto dep : dependencies)
jl_compile_codeinst_now(dep);
jl_ExecutionEngine->addModule(std::move(backing));
success = jl_ExecutionEngine->getGlobalValueAddress(name);
assert(success);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,7 @@ void emit_specsig_to_fptr1(
jl_value_t *calltype, jl_value_t *rettype, bool is_for_opaque_closure,
size_t nargs,
jl_codegen_params_t &params,
Function *target,
size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
Function *target) JL_NOTSAFEPOINT;
Function *get_or_emit_fptr1(StringRef Name, Module *M) JL_NOTSAFEPOINT;
void jl_init_function(Function *F, const Triple &TT) JL_NOTSAFEPOINT;

Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ _Atomic(jl_value_t*) *jl_table_peek_bp(jl_genericmemory_t *a, jl_value_t *key) J
JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*);

JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module);
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);
JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, int mt_cache);
jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp);
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);
JL_DLLEXPORT jl_value_t *jl_rettype_inferred_native(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
Expand Down
4 changes: 1 addition & 3 deletions src/precompile_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,8 @@ static void *jl_precompile_(jl_array_t *m, int external_linkage)
jl_value_t *item = jl_array_ptr_ref(m, i);
if (jl_is_method_instance(item)) {
mi = (jl_method_instance_t*)item;
size_t min_world = 0;
size_t max_world = ~(size_t)0;
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))
mi = jl_get_specialization1((jl_tupletype_t*)mi->specTypes, jl_atomic_load_acquire(&jl_world_counter), &min_world, &max_world, 0);
mi = jl_get_specialization1((jl_tupletype_t*)mi->specTypes, jl_atomic_load_acquire(&jl_world_counter), 0);
if (mi)
jl_array_ptr_1d_push(m2, (jl_value_t*)mi);
}
Expand Down
2 changes: 1 addition & 1 deletion test/llvmcall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ module ObjLoadTest
nothing
end
@test_throws(ErrorException("@ccallable was already defined for this method name"),
@eval @ccallable Cvoid jl_the_callback(not_the_method::Int) = "other")
@eval @ccallable String jl_the_callback(not_the_method::Int) = "other")
# Make sure everything up until here gets compiled
@test jl_the_callback() === nothing
@test jl_the_callback(1) == "other"
Expand Down

0 comments on commit a6aae8a

Please sign in to comment.