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

staticdata: remove reinit_ccallable #56987

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
2 changes: 1 addition & 1 deletion src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ void *jl_emit_native_impl(jl_array_t *codeinfos, LLVMOrcThreadSafeModuleRef llvm
else {
jl_value_t *sig = jl_array_ptr_ref(codeinfos, ++i);
assert(jl_is_type(item) && jl_is_type(sig));
jl_compile_extern_c(wrap(&clone), &params, NULL, item, sig);
jl_generate_ccallable(clone.getModuleUnlocked(), nullptr, item, sig, params);
}
}
// finally, make sure all referenced methods get fixed up, particularly if the user declined to compile them
Expand Down
1 change: 0 additions & 1 deletion src/codegen-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ JL_DLLEXPORT void jl_get_llvm_gvs_fallback(void *native_code, arraylist_t *gvs)
JL_DLLEXPORT void jl_get_llvm_external_fns_fallback(void *native_code, arraylist_t *gvs) UNAVAILABLE
JL_DLLEXPORT void jl_get_llvm_mis_fallback(void *native_code, arraylist_t* MIs) UNAVAILABLE

JL_DLLEXPORT void jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE
JL_DLLEXPORT jl_value_t *jl_dump_method_asm_fallback(jl_method_instance_t *linfo, size_t world,
char emit_mc, char getwrapper, const char* asm_variant, const char *debuginfo, char binary) UNAVAILABLE
JL_DLLEXPORT jl_value_t *jl_dump_function_ir_fallback(jl_llvmf_dump_t *dump, char strip_ir_metadata, char dump_module, const char *debuginfo) UNAVAILABLE
Expand Down
38 changes: 38 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4607,6 +4607,44 @@ JL_DLLEXPORT void jl_typeinf_timing_end(uint64_t start, int is_recompile)
}
}

// declare a C-callable entry point; called during code loading from the toplevel
JL_DLLEXPORT void jl_extern_c(jl_value_t *declrt, jl_tupletype_t *sigt)
{
// validate arguments. try to do as many checks as possible here to avoid
// throwing errors later during codegen.
JL_TYPECHK(@ccallable, type, declrt);
if (!jl_is_tuple_type(sigt))
jl_type_error("@ccallable", (jl_value_t*)jl_anytuple_type_type, (jl_value_t*)sigt);
// check that f is a guaranteed singleton type
jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
if (!jl_is_datatype(ft) || !jl_is_datatype_singleton(ft))
jl_error("@ccallable: function object must be a singleton");

// compute / validate return type
if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
jl_error("@ccallable: return type must be concrete and correspond to a C type");
if (!jl_type_mappable_to_c(declrt))
jl_error("@ccallable: return type doesn't correspond to a C type");

// validate method signature
size_t i, nargs = jl_nparams(sigt);
for (i = 1; i < nargs; i++) {
jl_value_t *ati = jl_tparam(sigt, i);
if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati))
jl_error("@ccallable: argument types must be concrete");
}

// save a record of this so that the alias is generated when we write an object file
jl_method_t *meth = (jl_method_t*)jl_methtable_lookup(ft->name->mt, (jl_value_t*)sigt, jl_atomic_load_acquire(&jl_world_counter));
if (!jl_is_method(meth))
jl_error("@ccallable: could not find requested method");
JL_GC_PUSH1(&meth);
meth->ccallable = jl_svec2(declrt, (jl_value_t*)sigt);
jl_gc_wb(meth, meth->ccallable);
JL_GC_POP();
}


#ifdef __cplusplus
}
#endif
134 changes: 0 additions & 134 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,140 +770,6 @@ void jl_emit_codeinst_to_jit_impl(
}


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
int jl_compile_extern_c_impl(LLVMOrcThreadSafeModuleRef llvmmod, void *p, void *sysimg, jl_value_t *declrt, jl_value_t *sigt)
{
auto ct = jl_current_task;
bool timed = (ct->reentrant_timing & 1) == 0;
if (timed)
ct->reentrant_timing |= 1;
uint64_t compiler_start_time = 0;
uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled);
if (measure_compile_time_enabled)
compiler_start_time = jl_hrtime();
jl_codegen_params_t *pparams = (jl_codegen_params_t*)p;
DataLayout DL = pparams ? pparams->DL : jl_ExecutionEngine->getDataLayout();
Triple TargetTriple = pparams ? pparams->TargetTriple : jl_ExecutionEngine->getTargetTriple();
orc::ThreadSafeContext ctx;
auto into = unwrap(llvmmod);
orc::ThreadSafeModule backing;
bool success = true;
const char *name = "";
if (into == NULL) {
ctx = pparams ? pparams->tsctx : jl_ExecutionEngine->makeContext();
backing = jl_create_ts_module("cextern", ctx, DL, TargetTriple);
into = &backing;
}
{ // params scope
jl_codegen_params_t params(into->getContext(), DL, TargetTriple);
if (pparams == NULL) {
params.cache = p == NULL;
params.imaging_mode = 0;
params.tsctx.getContext()->setDiscardValueNames(true);
pparams = &params;
}
Module &M = *into->getModuleUnlocked();
assert(pparams->tsctx.getContext() == &M.getContext());
name = jl_generate_ccallable(&M, sysimg, declrt, sigt, *pparams);
if (!sysimg && !p) {
{ // drop lock to keep analyzer happy (since it doesn't know we have the only reference to it)
auto release = std::move(params.tsctx_lock);
}
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (jl_ExecutionEngine->getGlobalValueAddress(name))
success = false;
}
params.tsctx_lock = params.tsctx.getLock(); // re-acquire lock
if (success && params.cache) {
size_t newest_world = jl_atomic_load_acquire(&jl_world_counter);
for (auto &it : params.workqueue) { // really just zero or one, and just the ABI not the rest of the metadata
jl_code_instance_t *codeinst = it.first;
JL_GC_PROMISE_ROOTED(codeinst);
jl_code_instance_t *newest_ci = jl_type_infer(jl_get_ci_mi(codeinst), newest_world, SOURCE_MODE_ABI);
if (newest_ci) {
if (jl_egal(codeinst->rettype, newest_ci->rettype))
it.first = codeinst;
jl_compile_codeinst_now(newest_ci);
}
}
jl_analyze_workqueue(nullptr, params, true);
assert(params.workqueue.empty());
finish_params(&M, params);
}
}
pparams = nullptr;
}
if (!sysimg && success && llvmmod == NULL) {
{ // lock scope
jl_unique_gcsafe_lock lock(extern_c_lock);
if (!jl_ExecutionEngine->getGlobalValueAddress(name)) {
{
auto Lock = backing.getContext().getLock();
jl_ExecutionEngine->optimizeDLSyms(*backing.getModuleUnlocked()); // safepoint
}
jl_ExecutionEngine->addModule(std::move(backing));
success = jl_ExecutionEngine->getGlobalValueAddress(name);
assert(success);
}
}
}
if (timed) {
if (measure_compile_time_enabled) {
auto end = jl_hrtime();
jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, end - compiler_start_time);
}
ct->reentrant_timing &= ~1ull;
}
return success;
}

// declare a C-callable entry point; called during code loading from the toplevel
extern "C" JL_DLLEXPORT_CODEGEN
void jl_extern_c_impl(jl_value_t *declrt, jl_tupletype_t *sigt)
{
// validate arguments. try to do as many checks as possible here to avoid
// throwing errors later during codegen.
JL_TYPECHK(@ccallable, type, declrt);
if (!jl_is_tuple_type(sigt))
jl_type_error("@ccallable", (jl_value_t*)jl_anytuple_type_type, (jl_value_t*)sigt);
// check that f is a guaranteed singleton type
jl_datatype_t *ft = (jl_datatype_t*)jl_tparam0(sigt);
if (!jl_is_datatype(ft) || !jl_is_datatype_singleton(ft))
jl_error("@ccallable: function object must be a singleton");

// compute / validate return type
if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
jl_error("@ccallable: return type must be concrete and correspond to a C type");
if (!jl_type_mappable_to_c(declrt))
jl_error("@ccallable: return type doesn't correspond to a C type");

// validate method signature
size_t i, nargs = jl_nparams(sigt);
for (i = 1; i < nargs; i++) {
jl_value_t *ati = jl_tparam(sigt, i);
if (!jl_is_concrete_type(ati) || jl_is_kind(ati) || !jl_type_mappable_to_c(ati))
jl_error("@ccallable: argument types must be concrete");
}

// save a record of this so that the alias is generated when we write an object file
jl_method_t *meth = (jl_method_t*)jl_methtable_lookup(ft->name->mt, (jl_value_t*)sigt, jl_atomic_load_acquire(&jl_world_counter));
if (!jl_is_method(meth))
jl_error("@ccallable: could not find requested method");
JL_GC_PUSH1(&meth);
meth->ccallable = jl_svec2(declrt, (jl_value_t*)sigt);
jl_gc_wb(meth, meth->ccallable);
JL_GC_POP();

// create the alias in the current runtime environment
int success = jl_compile_extern_c(NULL, NULL, NULL, declrt, (jl_value_t*)sigt);
if (!success)
jl_error("@ccallable was already defined for this method name");
}

extern "C" JL_DLLEXPORT_CODEGEN
int jl_compile_codeinst_impl(jl_code_instance_t *ci)
{
Expand Down
2 changes: 2 additions & 0 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ struct jl_codegen_params_t {
~jl_codegen_params_t() JL_NOTSAFEPOINT JL_NOTSAFEPOINT_LEAVE = default;
};

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

jl_llvm_functions_t jl_emit_code(
orc::ThreadSafeModule &M,
jl_method_instance_t *mi,
Expand Down
2 changes: 0 additions & 2 deletions src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,6 @@
YY(jl_dump_function_ir) \
YY(jl_dump_method_asm) \
YY(jl_emit_codeinst_to_jit) \
YY(jl_extern_c) \
YY(jl_get_llvmf_defn) \
YY(jl_get_llvm_function) \
YY(jl_get_llvm_module) \
Expand All @@ -534,7 +533,6 @@
YY(jl_register_fptrs) \
YY(jl_generate_fptr_for_unspecialized) \
YY(jl_compile_codeinst) \
YY(jl_compile_extern_c) \
YY(jl_teardown_codegen) \
YY(jl_jit_total_bytes) \
YY(jl_create_native) \
Expand Down
1 change: 0 additions & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1959,7 +1959,6 @@ JL_DLLEXPORT uint32_t jl_crc32c(uint32_t crc, const char *buf, size_t len);

JL_DLLIMPORT void jl_generate_fptr_for_unspecialized(jl_code_instance_t *unspec);
JL_DLLIMPORT int jl_compile_codeinst(jl_code_instance_t *unspec);
JL_DLLIMPORT int jl_compile_extern_c(LLVMOrcThreadSafeModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt);
JL_DLLIMPORT void jl_emit_codeinst_to_jit(jl_code_instance_t *codeinst, jl_code_info_t *src);

typedef struct {
Expand Down
51 changes: 3 additions & 48 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@

- step 3 combines the different sections (fields of `jl_serializer_state`) into one

- step 4 writes the values of the hard-coded tagged items and `ccallable_list`

Much of the "real work" during deserialization is done by `get_item_for_reloc`. But a few items require specific
attention:
- uniquing: during deserialization, the target item (an "external" type or MethodInstance) must be checked against
Expand Down Expand Up @@ -538,7 +536,6 @@ typedef struct {
arraylist_t uniquing_objs; // a list of locations that reference non-types that must be de-duplicated
arraylist_t fixup_types; // a list of locations of types requiring (re)caching
arraylist_t fixup_objs; // a list of locations of objects requiring (re)caching
arraylist_t ccallable_list; // @ccallable entry points to install
// mapping from a buildid_idx to a depmods_idx
jl_array_t *buildid_depmods_idxs;
// record of build_ids for all external linkages, in order of serialization for the current sysimg/pkgimg
Expand Down Expand Up @@ -1778,8 +1775,6 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
else {
newm->nroots_sysimg = m->roots ? jl_array_len(m->roots) : 0;
}
if (m->ccallable)
arraylist_push(&s->ccallable_list, (void*)reloc_offset);
}
else if (jl_is_method_instance(v)) {
assert(f == s->s);
Expand Down Expand Up @@ -2456,29 +2451,6 @@ static void jl_root_new_gvars(jl_serializer_state *s, jl_image_t *image, uint32_
}
}


static void jl_compile_extern(jl_method_t *m, void *sysimg_handle) JL_GC_DISABLED
{
// install ccallable entry point in JIT
assert(m); // makes clang-sa happy
jl_svec_t *sv = m->ccallable;
int success = jl_compile_extern_c(NULL, NULL, sysimg_handle, jl_svecref(sv, 0), jl_svecref(sv, 1));
if (!success)
jl_safe_printf("WARNING: @ccallable was already defined for this method name\n"); // enjoy a very bad time
assert(success || !sysimg_handle);
}


static void jl_reinit_ccallable(arraylist_t *ccallable_list, char *base, void *sysimg_handle)
{
for (size_t i = 0; i < ccallable_list->len; i++) {
uintptr_t item = (uintptr_t)ccallable_list->items[i];
jl_method_t *m = (jl_method_t*)(base + item);
jl_compile_extern(m, sysimg_handle);
}
}


// Code below helps slim down the images by
// removing cached types not referenced in the stream
static jl_svec_t *jl_prune_type_cache_hash(jl_svec_t *cache) JL_GC_DISABLED
Expand Down Expand Up @@ -3007,7 +2979,6 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
arraylist_new(&s.uniquing_objs, 0);
arraylist_new(&s.fixup_types, 0);
arraylist_new(&s.fixup_objs, 0);
arraylist_new(&s.ccallable_list, 0);
s.buildid_depmods_idxs = image_to_depmodidx(mod_array);
s.link_ids_relocs = jl_alloc_array_1d(jl_array_int32_type, 0);
s.link_ids_gctags = jl_alloc_array_1d(jl_array_int32_type, 0);
Expand Down Expand Up @@ -3252,7 +3223,6 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
write_uint32(f, jl_array_len(s.link_ids_external_fnvars));
ios_write(f, (char*)jl_array_data(s.link_ids_external_fnvars, uint32_t), jl_array_len(s.link_ids_external_fnvars) * sizeof(uint32_t));
write_uint32(f, external_fns_begin);
jl_write_arraylist(s.s, &s.ccallable_list);
}

assert(object_worklist.len == 0);
Expand All @@ -3264,7 +3234,6 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
arraylist_free(&s.uniquing_objs);
arraylist_free(&s.fixup_types);
arraylist_free(&s.fixup_objs);
arraylist_free(&s.ccallable_list);
arraylist_free(&s.memowner_list);
arraylist_free(&s.memref_list);
arraylist_free(&s.relocs_list);
Expand Down Expand Up @@ -3475,7 +3444,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
jl_array_t **extext_methods, jl_array_t **internal_methods,
jl_array_t **new_ext_cis, jl_array_t **method_roots_list,
jl_array_t **edges,
char **base, arraylist_t *ccallable_list, pkgcachesizes *cachesizes) JL_GC_DISABLED
pkgcachesizes *cachesizes) JL_GC_DISABLED
{
jl_task_t *ct = jl_current_task;
int en = jl_gc_enable(0);
Expand Down Expand Up @@ -3602,7 +3571,6 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
ios_read(f, (char*)jl_array_data(s.link_ids_external_fnvars, uint32_t), nlinks_external_fnvars * sizeof(uint32_t));
}
uint32_t external_fns_begin = read_uint32(f);
jl_read_arraylist(s.s, ccallable_list ? ccallable_list : &s.ccallable_list);
if (s.incremental) {
assert(restored && init_order && extext_methods && internal_methods && new_ext_cis && method_roots_list && edges);
*restored = (jl_array_t*)jl_delayed_reloc(&s, offset_restored);
Expand All @@ -3622,8 +3590,6 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl

char *image_base = (char*)&sysimg.buf[0];
reloc_t *relocs_base = (reloc_t*)&relocs.buf[0];
if (base)
*base = image_base;

s.s = &sysimg;
jl_read_reloclist(&s, s.link_ids_gctags, GC_OLD | GC_IN_IMAGE); // gctags
Expand Down Expand Up @@ -3967,11 +3933,6 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl

s.s = &sysimg;
jl_update_all_fptrs(&s, image); // fptr relocs and registration
if (!ccallable_list) {
// TODO: jl_sysimg_handle or img_handle?
jl_reinit_ccallable(&s.ccallable_list, image_base, jl_sysimg_handle);
arraylist_free(&s.ccallable_list);
}
s.s = NULL;

ios_close(&fptr_record);
Expand Down Expand Up @@ -4049,8 +4010,6 @@ static jl_value_t *jl_restore_package_image_from_stream(void* pkgimage_handle, i

assert(datastartpos > 0 && datastartpos < dataendpos);
needs_permalloc = jl_options.permalloc_pkgimg || needs_permalloc;
char *base;
arraylist_t ccallable_list;

jl_value_t *restored = NULL;
jl_array_t *init_order = NULL, *extext_methods = NULL, *internal_methods = NULL, *new_ext_cis = NULL, *method_roots_list = NULL, *edges = NULL;
Expand Down Expand Up @@ -4080,7 +4039,7 @@ static jl_value_t *jl_restore_package_image_from_stream(void* pkgimage_handle, i
ios_static_buffer(f, sysimg, len);
pkgcachesizes cachesizes;
jl_restore_system_image_from_stream_(f, image, depmods, checksum, (jl_array_t**)&restored, &init_order, &extext_methods, &internal_methods, &new_ext_cis, &method_roots_list,
&edges, &base, &ccallable_list, &cachesizes);
&edges, &cachesizes);
JL_SIGATOMIC_END();

// No special processing of `new_ext_cis` is required because recaching handled it
Expand Down Expand Up @@ -4111,10 +4070,6 @@ static jl_value_t *jl_restore_package_image_from_stream(void* pkgimage_handle, i
// now permit more methods to be added again
JL_UNLOCK(&world_counter_lock);

// reinit ccallables
jl_reinit_ccallable(&ccallable_list, base, pkgimage_handle);
arraylist_free(&ccallable_list);

jl_value_t *ext_edges = new_ext_cis ? (jl_value_t*)new_ext_cis : jl_nothing;

if (completeinfo) {
Expand Down Expand Up @@ -4142,7 +4097,7 @@ static jl_value_t *jl_restore_package_image_from_stream(void* pkgimage_handle, i
static void jl_restore_system_image_from_stream(ios_t *f, jl_image_t *image, uint32_t checksum)
{
JL_TIMING(LOAD_IMAGE, LOAD_Sysimg);
jl_restore_system_image_from_stream_(f, image, NULL, checksum | ((uint64_t)0xfdfcfbfa << 32), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
jl_restore_system_image_from_stream_(f, image, NULL, checksum | ((uint64_t)0xfdfcfbfa << 32), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}

JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(void* pkgimage_handle, const char *buf, jl_image_t *image, size_t sz, jl_array_t *depmods, int completeinfo, const char *pkgname, int needs_permalloc)
Expand Down
Loading
Loading