From 46388cf899408a377164b4226ce7a01be6db8114 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 14 Nov 2024 10:47:38 +0000 Subject: [PATCH] WIP: Add ABIOverride type for `def` field Together with #54899, this PR is intending to replicate the functionality of #54373, which allowed particular specializations to have a different ABI signature than what would be suggested by the MethodInstance's `specTypes` field. This PR handles that by adding a special `ABIOverwrite` type, which, when placed in the `def` field of a `CodeInstance` instructs the system to use the given signature instead. --- Compiler/src/stmtinfo.jl | 6 ++-- base/boot.jl | 6 ++++ base/show.jl | 8 ++++- src/aotcompile.cpp | 16 +++++----- src/builtins.c | 9 +++--- src/codegen.cpp | 69 +++++++++++++++++++++++----------------- src/debuginfo.cpp | 4 +-- src/engine.cpp | 2 +- src/gf.c | 17 +++++----- src/interpreter.c | 4 +-- src/ircode.c | 2 +- src/jitlayers.cpp | 14 ++++---- src/jitlayers.h | 1 + src/jl_exported_data.inc | 1 + src/jltypes.c | 2 +- src/julia.h | 10 +++++- src/julia_internal.h | 7 ++++ src/precompile_utils.c | 2 +- src/staticdata.c | 14 ++++---- src/staticdata_utils.c | 16 +++++----- test/precompile.jl | 4 +-- 21 files changed, 129 insertions(+), 85 deletions(-) diff --git a/Compiler/src/stmtinfo.jl b/Compiler/src/stmtinfo.jl index 4f55f068e9456..49f7835da05b7 100644 --- a/Compiler/src/stmtinfo.jl +++ b/Compiler/src/stmtinfo.jl @@ -71,7 +71,7 @@ function _add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, mi_edge::Boo mi = specialize_method(m) # don't allow `Method`-edge for this optimized format edge = mi else - mi = edge.def + mi = edge.def::MethodInstance end if mi.specTypes === m.spec_types add_one_edge!(edges, edge) @@ -103,7 +103,7 @@ function add_one_edge!(edges::Vector{Any}, edge::MethodInstance) while i <= length(edges) edgeᵢ = edges[i] edgeᵢ isa Int && (i += 2 + edgeᵢ; continue) - edgeᵢ isa CodeInstance && (edgeᵢ = edgeᵢ.def) + edgeᵢ isa CodeInstance && (edgeᵢ = edgeᵢ.def::MethodInstance) edgeᵢ isa MethodInstance || (i += 1; continue) if edgeᵢ === edge && !(i > 1 && edges[i-1] isa Type) return # found existing covered edge @@ -118,7 +118,7 @@ function add_one_edge!(edges::Vector{Any}, edge::CodeInstance) while i <= length(edges) edgeᵢ_orig = edgeᵢ = edges[i] edgeᵢ isa Int && (i += 2 + edgeᵢ; continue) - edgeᵢ isa CodeInstance && (edgeᵢ = edgeᵢ.def) + edgeᵢ isa CodeInstance && (edgeᵢ = edgeᵢ.def::MethodInstance) edgeᵢ isa MethodInstance || (i += 1; continue) if edgeᵢ === edge.def && !(i > 1 && edges[i-1] isa Type) if edgeᵢ_orig isa MethodInstance diff --git a/base/boot.jl b/base/boot.jl index 4badedae3cfb7..dfd77958ed5ca 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -465,6 +465,12 @@ struct InitError <: WrappedException error end +struct ABIOverride + abi::Type + def::MethodInstance + ABIOverride(@nospecialize(abi::Type), def::MethodInstance) = new(abi, def) +end + struct PrecompilableError <: Exception end String(s::String) = s # no constructor yet diff --git a/base/show.jl b/base/show.jl index cb36488b92bc1..d2f43e1ae92cc 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1353,7 +1353,13 @@ end show(io::IO, mi::Core.MethodInstance) = show_mi(io, mi) function show(io::IO, codeinst::Core.CodeInstance) print(io, "CodeInstance for ") - show_mi(io, codeinst.def) + def = codeinst.def + if isa(def, Core.ABIOverride) + show_mi(io, def.def) + print(io, " (ABI Overridden)") + else + show_mi(io, def::MethodInstance) + end end function show_mi(io::IO, mi::Core.MethodInstance, from_stackframe::Bool=false) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index ba9a3c05e41ff..6dbb14c9ec945 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -105,7 +105,7 @@ jl_get_llvm_mis_impl(void *native_code, size_t *num_elements, jl_method_instance assert(*num_elements == map.size()); size_t i = 0; for (auto &ci : map) { - data[i++] = ci.first->def; + data[i++] = jl_get_ci_mi(ci.first); } } @@ -455,14 +455,14 @@ static void compile_workqueue(jl_codegen_params_t ¶ms, egal_set &method_root if ((policy != CompilationPolicy::Default || params.params->trim) && jl_atomic_load_relaxed(&codeinst->inferred) == jl_nothing) { // XXX: SOURCE_MODE_FORCE_SOURCE is wrong here (neither sufficient nor necessary) - codeinst = jl_type_infer(codeinst->def, jl_atomic_load_relaxed(&codeinst->max_world), SOURCE_MODE_FORCE_SOURCE); + codeinst = jl_type_infer(jl_get_ci_mi(codeinst), jl_atomic_load_relaxed(&codeinst->max_world), SOURCE_MODE_FORCE_SOURCE); } if (codeinst) { orc::ThreadSafeModule result_m = - jl_create_ts_module(name_from_method_instance(codeinst->def), + jl_create_ts_module(name_from_method_instance(jl_get_ci_mi(codeinst)), params.tsctx, params.DL, params.TargetTriple); auto decls = jl_emit_codeinst(result_m, codeinst, NULL, params); - record_method_roots(method_roots, codeinst->def); + record_method_roots(method_roots, jl_get_ci_mi(codeinst)); if (result_m) it = compiled_functions.insert(std::make_pair(codeinst, std::make_pair(std::move(result_m), std::move(decls)))).first; } @@ -501,7 +501,7 @@ static void compile_workqueue(jl_codegen_params_t ¶ms, egal_set &method_root proto.decl->setLinkage(GlobalVariable::InternalLinkage); //protodecl->setAlwaysInline(); jl_init_function(proto.decl, params.TargetTriple); - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); 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? @@ -641,12 +641,12 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm data->jl_fvar_map[codeinst] = std::make_tuple((uint32_t)-3, (uint32_t)-3); } else { - orc::ThreadSafeModule result_m = jl_create_ts_module(name_from_method_instance(codeinst->def), + orc::ThreadSafeModule result_m = jl_create_ts_module(name_from_method_instance(jl_get_ci_mi(codeinst)), params.tsctx, clone.getModuleUnlocked()->getDataLayout(), Triple(clone.getModuleUnlocked()->getTargetTriple())); jl_llvm_functions_t decls = jl_emit_codeinst(result_m, codeinst, NULL, params); JL_GC_PROMISE_ROOTED(codeinst->def); // analyzer seems confused - record_method_roots(method_roots, codeinst->def); + record_method_roots(method_roots, jl_get_ci_mi(codeinst)); if (result_m) compiled_functions[codeinst] = {std::move(result_m), std::move(decls)}; else if (jl_options.trim != JL_TRIM_NO) { @@ -2267,7 +2267,7 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, jl_ // To get correct names in the IR this needs to be at least 2 output.temporary_roots = jl_alloc_array_1d(jl_array_any_type, 0); JL_GC_PUSH1(&output.temporary_roots); - auto decls = jl_emit_code(m, mi, src, output); + auto decls = jl_emit_code(m, mi, src, NULL, output); output.temporary_roots = nullptr; JL_GC_POP(); // GC the global_targets array contents now since reflection doesn't need it diff --git a/src/builtins.c b/src/builtins.c index 4b9c1ad6043c2..867c1f1855b57 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1589,11 +1589,12 @@ JL_CALLABLE(jl_f_invoke) return jl_gf_invoke_by_method(m, args[0], &args[2], nargs - 1); } else if (jl_is_code_instance(argtypes)) { jl_code_instance_t *codeinst = (jl_code_instance_t*)args[1]; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); jl_callptr_t invoke = jl_atomic_load_acquire(&codeinst->invoke); // N.B.: specTypes need not be a subtype of the method signature. We need to check both. - if (!jl_tuple1_isa(args[0], &args[2], nargs - 1, (jl_datatype_t*)codeinst->def->specTypes) || - (jl_is_method(codeinst->def->def.value) && !jl_tuple1_isa(args[0], &args[2], nargs - 1, (jl_datatype_t*)codeinst->def->def.method->sig))) { - jl_type_error("invoke: argument type error", codeinst->def->specTypes, arg_tuple(args[0], &args[2], nargs - 1)); + if (!jl_tuple1_isa(args[0], &args[2], nargs - 1, (jl_datatype_t*)mi->specTypes) || + (jl_is_method(mi->def.value) && !jl_tuple1_isa(args[0], &args[2], nargs - 1, (jl_datatype_t*)mi->def.method->sig))) { + jl_type_error("invoke: argument type error", mi->specTypes, arg_tuple(args[0], &args[2], nargs - 1)); } if (jl_atomic_load_relaxed(&codeinst->min_world) > jl_current_task->world_age || jl_current_task->world_age > jl_atomic_load_relaxed(&codeinst->max_world)) { @@ -1609,7 +1610,7 @@ JL_CALLABLE(jl_f_invoke) if (codeinst->owner != jl_nothing) { jl_error("Failed to invoke or compile external codeinst"); } - return jl_invoke(args[0], &args[2], nargs - 1, codeinst->def); + return jl_invoke(args[0], &args[2], nargs - 1, mi); } } if (!jl_is_tuple_type(jl_unwrap_unionall(argtypes))) diff --git a/src/codegen.cpp b/src/codegen.cpp index 21591acedc632..77ed65757b657 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2991,9 +2991,8 @@ static bool uses_specsig(jl_value_t *sig, bool needsparams, jl_value_t *rettype, return false; // jlcall sig won't require any box allocations } -static std::pair uses_specsig(jl_method_instance_t *lam, jl_value_t *rettype, bool prefer_specsig) +static std::pair uses_specsig(jl_value_t *abi, jl_method_instance_t *lam, jl_value_t *rettype, bool prefer_specsig) { - jl_value_t *sig = lam->specTypes; bool needsparams = false; if (jl_is_method(lam->def.method)) { if ((size_t)jl_subtype_env_size(lam->def.method->sig) != jl_svec_len(lam->sparam_vals)) @@ -3003,7 +3002,7 @@ static std::pair uses_specsig(jl_method_instance_t *lam, jl_value_t needsparams = true; } } - return std::make_pair(uses_specsig(sig, needsparams, rettype, prefer_specsig), needsparams); + return std::make_pair(uses_specsig(abi, needsparams, rettype, prefer_specsig), needsparams); } @@ -4311,6 +4310,7 @@ static jl_llvm_functions_t orc::ThreadSafeModule &TSM, jl_method_instance_t *lam, jl_code_info_t *src, + jl_value_t *abi, jl_value_t *rettype, jl_codegen_params_t ¶ms); @@ -5428,6 +5428,13 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt) return emit_invoke(ctx, lival, argv, nargs, rt); } +static jl_value_t *get_ci_abi(jl_code_instance_t *ci) +{ + if (jl_typeof(ci->def) == (jl_value_t*)jl_abioverride_type) + return ((jl_abi_overwrite_t*)ci->def)->abi; + return jl_get_ci_mi(ci)->specTypes; +} + static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, ArrayRef argv, size_t nargs, jl_value_t *rt) { ++EmittedInvokes; @@ -5442,7 +5449,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, ArrayR else { ci = lival.constant; assert(jl_is_code_instance(ci)); - mi = ((jl_code_instance_t*)ci)->def; + mi = jl_get_ci_mi((jl_code_instance_t*)ci); } assert(jl_is_method_instance(mi)); if (mi == ctx.linfo) { @@ -5471,7 +5478,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, ArrayR } else if (invoke != jl_fptr_sparam_addr) { bool specsig, needsparams; - std::tie(specsig, needsparams) = uses_specsig(mi, codeinst->rettype, ctx.params->prefer_specsig); + std::tie(specsig, needsparams) = uses_specsig(get_ci_abi(codeinst), mi, codeinst->rettype, ctx.params->prefer_specsig); std::string name; StringRef protoname; bool need_to_emit = true; @@ -7190,7 +7197,7 @@ Function *emit_tojlinvoke(jl_code_instance_t *codeinst, StringRef theFptrName, M jl_init_function(f, params.TargetTriple); if (trim_may_error(params.params->trim)) { // TODO: Debuginfo! - push_frames(ctx, ctx.linfo, codeinst->def, 1); + push_frames(ctx, ctx.linfo, jl_get_ci_mi(codeinst), 1); } jl_name_jlfunc_args(params, f); //f->setAlwaysInline(); @@ -7207,7 +7214,7 @@ Function *emit_tojlinvoke(jl_code_instance_t *codeinst, StringRef theFptrName, M } else { theFunc = prepare_call(jlinvoke_func); - theFarg = literal_pointer_val(ctx, (jl_value_t*)codeinst->def); + theFarg = literal_pointer_val(ctx, (jl_value_t*)jl_get_ci_mi(codeinst)); } theFarg = track_pjlvalue(ctx, theFarg); auto args = f->arg_begin(); @@ -8316,13 +8323,13 @@ get_specsig_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *rt, jl } /* aka Core.Compiler.tuple_tfunc */ -static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq) +static jl_datatype_t *compute_va_type(jl_value_t *sig, size_t nreq) { - size_t nvargs = jl_nparams(lam->specTypes)-nreq; + size_t nvargs = jl_nparams(sig)-nreq; jl_svec_t *tupargs = jl_alloc_svec(nvargs); JL_GC_PUSH1(&tupargs); - for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) { - jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i); + for (size_t i = nreq; i < jl_nparams(sig); ++i) { + jl_value_t *argType = jl_nth_slot_type(sig, i); // n.b. specTypes is required to be a datatype by construction for specsig if (is_uniquerep_Type(argType)) argType = jl_typeof(jl_tparam0(argType)); @@ -8362,6 +8369,7 @@ static jl_llvm_functions_t orc::ThreadSafeModule &TSM, jl_method_instance_t *lam, jl_code_info_t *src, + jl_value_t *abi, jl_value_t *jlrettype, jl_codegen_params_t ¶ms) { @@ -8440,7 +8448,7 @@ static jl_llvm_functions_t int n_ssavalues = jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_nrows(src->ssavaluetypes); size_t vinfoslen = jl_array_dim0(src->slotflags); ctx.slots.resize(vinfoslen, jl_varinfo_t(ctx.builder.getContext())); - assert(lam->specTypes); // the specTypes field should always be assigned + assert(abi); // the specTypes field should always be assigned // create SAvalue locations for SSAValue objects @@ -8449,7 +8457,7 @@ static jl_llvm_functions_t ctx.ssavalue_usecount.assign(n_ssavalues, 0); bool specsig, needsparams; - std::tie(specsig, needsparams) = uses_specsig(lam, jlrettype, params.params->prefer_specsig); + std::tie(specsig, needsparams) = uses_specsig(abi, lam, jlrettype, params.params->prefer_specsig); // step 3. some variable analysis size_t i; @@ -8459,7 +8467,7 @@ static jl_llvm_functions_t jl_sym_t *argname = slot_symbol(ctx, i); if (argname == jl_unused_sym) continue; - jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i); + jl_value_t *ty = jl_nth_slot_type(abi, i); // TODO: jl_nth_slot_type should call jl_rewrap_unionall // specTypes is required to be a datatype by construction for specsig, but maybe not otherwise // OpaqueClosure implicitly loads the env @@ -8477,7 +8485,7 @@ static jl_llvm_functions_t if (va && ctx.vaSlot != -1) { jl_varinfo_t &varinfo = ctx.slots[ctx.vaSlot]; varinfo.isArgument = true; - vatyp = specsig ? compute_va_type(lam, nreq) : (jl_tuple_type); + vatyp = specsig ? compute_va_type(abi, nreq) : (jl_tuple_type); varinfo.value = mark_julia_type(ctx, (Value*)NULL, false, vatyp); } @@ -8528,7 +8536,7 @@ static jl_llvm_functions_t ArgNames[i] = name; } } - returninfo = get_specsig_function(ctx, M, NULL, declarations.specFunctionObject, lam->specTypes, + returninfo = get_specsig_function(ctx, M, NULL, declarations.specFunctionObject, abi, jlrettype, ctx.is_opaque_closure, JL_FEAT_TEST(ctx,gcstack_arg), ArgNames, nreq); f = cast(returninfo.decl.getCallee()); @@ -8562,7 +8570,7 @@ static jl_llvm_functions_t std::string wrapName; raw_string_ostream(wrapName) << "jfptr_" << ctx.name << "_" << jl_atomic_fetch_add_relaxed(&globalUniqueGeneratedNames, 1); declarations.functionObject = wrapName; - size_t nparams = jl_nparams(lam->specTypes); + size_t nparams = jl_nparams(abi); gen_invoke_wrapper(lam, jlrettype, returninfo, nparams, retarg, ctx.is_opaque_closure, declarations.functionObject, M, ctx.emission_context); // TODO: add attributes: maybe_mark_argument_dereferenceable(Arg, argType) // TODO: add attributes: dereferenceable @@ -8585,7 +8593,7 @@ static jl_llvm_functions_t if (!params.getContext().shouldDiscardValueNames() && ctx.emission_context.params->debug_info_level >= 2 && lam->def.method && jl_is_method(lam->def.method) && lam->specTypes != (jl_value_t*)jl_emptytuple_type) { ios_t sigbuf; ios_mem(&sigbuf, 0); - jl_static_show_func_sig((JL_STREAM*) &sigbuf, (jl_value_t*)lam->specTypes); + jl_static_show_func_sig((JL_STREAM*) &sigbuf, (jl_value_t*)abi); f->addFnAttr("julia.fsig", StringRef(sigbuf.buf, sigbuf.size)); ios_close(&sigbuf); } @@ -8642,7 +8650,7 @@ static jl_llvm_functions_t else if (!specsig) subrty = debugcache.jl_di_func_sig; else - subrty = get_specsig_di(ctx, debugcache, jlrettype, lam->specTypes, dbuilder); + subrty = get_specsig_di(ctx, debugcache, jlrettype, abi, dbuilder); SP = dbuilder.createFunction(nullptr ,dbgFuncName // Name ,f->getName() // LinkageName @@ -8974,7 +8982,7 @@ static jl_llvm_functions_t nullptr, nullptr, /*isboxed*/true, AtomicOrdering::NotAtomic, false, sizeof(void*)); } else { - jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i); + jl_value_t *argType = jl_nth_slot_type(abi, i); // TODO: jl_nth_slot_type should call jl_rewrap_unionall? // specTypes is required to be a datatype by construction for specsig, but maybe not otherwise bool isboxed = deserves_argbox(argType); @@ -9048,10 +9056,10 @@ static jl_llvm_functions_t assert(vi.boxroot == NULL); } else if (specsig) { - ctx.nvargs = jl_nparams(lam->specTypes) - nreq; + ctx.nvargs = jl_nparams(abi) - nreq; SmallVector vargs(ctx.nvargs); - for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) { - jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i); + for (size_t i = nreq; i < jl_nparams(abi); ++i) { + jl_value_t *argType = jl_nth_slot_type(abi, i); // n.b. specTypes is required to be a datatype by construction for specsig bool isboxed = deserves_argbox(argType); Type *llvmArgType = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, argType); @@ -9977,6 +9985,7 @@ jl_llvm_functions_t jl_emit_code( orc::ThreadSafeModule &m, jl_method_instance_t *li, jl_code_info_t *src, + jl_value_t *abi, jl_codegen_params_t ¶ms) { JL_TIMING(CODEGEN, CODEGEN_LLVM); @@ -9985,8 +9994,10 @@ jl_llvm_functions_t jl_emit_code( assert((params.params == &jl_default_cgparams /* fast path */ || !params.cache || compare_cgparams(params.params, &jl_default_cgparams)) && "functions compiled with custom codegen params must not be cached"); + if (!abi) + abi = li->specTypes; JL_TRY { - decls = emit_function(m, li, src, src->rettype, params); + decls = emit_function(m, li, src, abi, src->rettype, params); auto stream = *jl_ExecutionEngine->get_dump_emitted_mi_name_stream(); if (stream) { jl_printf(stream, "%s\t", decls.specFunctionObject.c_str()); @@ -10054,11 +10065,11 @@ jl_llvm_functions_t jl_emit_codeinst( jl_codegen_params_t ¶ms) { JL_TIMING(CODEGEN, CODEGEN_Codeinst); - jl_timing_show_method_instance(codeinst->def, JL_TIMING_DEFAULT_BLOCK); + jl_timing_show_method_instance(jl_get_ci_mi(codeinst), JL_TIMING_DEFAULT_BLOCK); JL_GC_PUSH1(&src); if (!src) { src = (jl_code_info_t*)jl_atomic_load_relaxed(&codeinst->inferred); - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); jl_method_t *def = mi->def.method; // Check if this is the generic method for opaque closure wrappers - // if so, this must compile specptr such that it holds the specptr -> invoke wrapper @@ -10076,7 +10087,7 @@ jl_llvm_functions_t jl_emit_codeinst( } } assert(jl_egal((jl_value_t*)jl_atomic_load_relaxed(&codeinst->debuginfo), (jl_value_t*)src->debuginfo) && "trying to generate code for a codeinst for an incompatible src"); - jl_llvm_functions_t decls = jl_emit_code(m, codeinst->def, src, params); + jl_llvm_functions_t decls = jl_emit_code(m, jl_get_ci_mi(codeinst), src, get_ci_abi(codeinst), params); const std::string &specf = decls.specFunctionObject; const std::string &f = decls.functionObject; @@ -10084,7 +10095,7 @@ jl_llvm_functions_t jl_emit_codeinst( // Prepare debug info to receive this function // record that this function name came from this linfo, // so we can build a reverse mapping for debug-info. - bool toplevel = !jl_is_method(codeinst->def->def.method); + bool toplevel = !jl_is_method(jl_get_ci_mi(codeinst)->def.method); if (!toplevel) { //Safe b/c params holds context lock const DataLayout &DL = m.getModuleUnlocked()->getDataLayout(); @@ -10100,7 +10111,7 @@ jl_llvm_functions_t jl_emit_codeinst( jl_value_t *inferred = jl_atomic_load_relaxed(&codeinst->inferred); // don't change inferred state if (inferred) { - jl_method_t *def = codeinst->def->def.method; + jl_method_t *def = jl_get_ci_mi(codeinst)->def.method; if (// keep code when keeping everything !(JL_DELETE_NON_INLINEABLE) || // aggressively keep code when debugging level >= 2 diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 31f1ba8281a89..ce8406bf91490 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -167,7 +167,7 @@ void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const D // Non-opaque-closure MethodInstances are considered globally rooted // through their methods, but for OC, we need to create a global root // here. - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); if (jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure) jl_as_global_root((jl_value_t*)mi, 1); getJITDebugRegistry().add_code_in_flight(name, codeinst, DL); @@ -374,7 +374,7 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object, jl_method_instance_t *mi = NULL; if (codeinst) { JL_GC_PROMISE_ROOTED(codeinst); - mi = codeinst->def; + mi = jl_get_ci_mi(codeinst); } jl_profile_atomic([&]() JL_NOTSAFEPOINT { if (mi) diff --git a/src/engine.cpp b/src/engine.cpp index 2b68de731c4dd..858f37b55e85e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -139,7 +139,7 @@ void jl_engine_fulfill(jl_code_instance_t *ci, jl_code_info_t *src) { jl_task_t *ct = jl_current_task; std::unique_lock lock(engine_lock); - auto record = Reservations.find(InferKey{ci->def, ci->owner}); + auto record = Reservations.find(InferKey{jl_get_ci_mi(ci), ci->owner}); if (record == Reservations.end() || record->second.ci != ci) return; assert(jl_atomic_load_relaxed(&ct->tid) == record->second.tid); diff --git a/src/gf.c b/src/gf.c index bbf065a4fac0d..8e9b423d32915 100644 --- a/src/gf.c +++ b/src/gf.c @@ -538,7 +538,7 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( jl_task_t *ct = jl_current_task; jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_instance_t), jl_code_instance_type); - codeinst->def = mi; + codeinst->def = (jl_value_t*)mi; codeinst->owner = owner; jl_atomic_store_relaxed(&codeinst->edges, edges); jl_atomic_store_relaxed(&codeinst->min_world, min_world); @@ -1772,17 +1772,18 @@ static void invalidate_code_instance(jl_code_instance_t *replaced, size_t max_wo JL_GC_POP(); } //jl_static_show(JL_STDERR, (jl_value_t*)replaced->def); - if (!jl_is_method(replaced->def->def.method)) + jl_method_instance_t *replaced_mi = jl_get_ci_mi(replaced); + if (!jl_is_method(replaced_mi->def.method)) return; // shouldn't happen, but better to be safe - JL_LOCK(&replaced->def->def.method->writelock); + JL_LOCK(&replaced_mi->def.method->writelock); if (jl_atomic_load_relaxed(&replaced->max_world) == ~(size_t)0) { assert(jl_atomic_load_relaxed(&replaced->min_world) - 1 <= max_world && "attempting to set illogical world constraints (probable race condition)"); jl_atomic_store_release(&replaced->max_world, max_world); } assert(jl_atomic_load_relaxed(&replaced->max_world) <= max_world); // recurse to all backedges to update their valid range also - _invalidate_backedges(replaced->def, max_world, depth + 1); - JL_UNLOCK(&replaced->def->def.method->writelock); + _invalidate_backedges(replaced_mi, max_world, depth + 1); + JL_UNLOCK(&replaced_mi->def.method->writelock); } static void _invalidate_backedges(jl_method_instance_t *replaced_mi, size_t max_world, int depth) { @@ -2329,7 +2330,7 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry) int replaced_edge; if (invokeTypes) { // n.b. normally we must have mi.specTypes <: invokeTypes <: m.sig (though it might not strictly hold), so we only need to check the other subtypes - if (jl_egal(invokeTypes, caller->def->def.method->sig)) + if (jl_egal(invokeTypes, jl_get_ci_mi(caller)->def.method->sig)) replaced_edge = 0; // if invokeTypes == m.sig, then the only way to change this invoke is to replace the method itself else replaced_edge = jl_subtype(invokeTypes, type) && is_replacing(ambig, type, m, d, n, invokeTypes, NULL, morespec); @@ -2907,7 +2908,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t jl_callptr_t ucache_invoke = jl_atomic_load_acquire(&ucache->invoke); if (ucache_invoke == NULL) { if ((!jl_is_method(def) || def->source == jl_nothing) && - !jl_cached_uninferred(jl_atomic_load_relaxed(&ucache->def->cache), world)) { + !jl_cached_uninferred(jl_atomic_load_relaxed(&jl_get_ci_mi(ucache)->cache), world)) { jl_throw(jl_new_struct(jl_missingcodeerror_type, (jl_value_t*)mi)); } jl_generate_fptr_for_unspecialized(ucache); @@ -2953,7 +2954,7 @@ jl_value_t *jl_fptr_args(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_co jl_value_t *jl_fptr_sparam(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_code_instance_t *m) { - jl_svec_t *sparams = m->def->sparam_vals; + jl_svec_t *sparams = jl_get_ci_mi(m)->sparam_vals; assert(sparams != jl_emptysvec); jl_fptr_sparam_t invoke = jl_atomic_load_relaxed(&m->specptr.fptr3); assert(invoke && "Forgot to set specptr for jl_fptr_sparam!"); diff --git a/src/interpreter.c b/src/interpreter.c index a465fe27f5084..b9bd1997caa17 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -154,7 +154,7 @@ static jl_value_t *do_invoke(jl_value_t **args, size_t nargs, interpreter_state if (codeinst->owner != jl_nothing) { jl_error("Failed to invoke or compile external codeinst"); } - result = jl_invoke(argv[0], nargs == 2 ? NULL : &argv[1], nargs - 2, codeinst->def); + result = jl_invoke(argv[0], nargs == 2 ? NULL : &argv[1], nargs - 2, jl_get_ci_mi(codeinst)); } } else { result = jl_invoke(argv[0], nargs == 2 ? NULL : &argv[1], nargs - 2, (jl_method_instance_t*)c); @@ -767,7 +767,7 @@ jl_code_info_t *jl_code_for_interpreter(jl_method_instance_t *mi, size_t world) jl_value_t *NOINLINE jl_fptr_interpret_call(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_code_instance_t *codeinst) { interpreter_state *s; - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); jl_task_t *ct = jl_current_task; size_t world = ct->world_age; jl_code_info_t *src = NULL; diff --git a/src/ircode.c b/src/ircode.c index 9e64e3fe2b574..99c5833ac3be7 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -1194,7 +1194,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t ios_close(s.s); JL_UNLOCK(&m->writelock); // Might GC if (metadata) { - code->parent = metadata->def; + code->parent = jl_get_ci_mi(metadata); jl_gc_wb(code, code->parent); code->rettype = metadata->rettype; jl_gc_wb(code, code->rettype); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 80867daade267..7f2b86c921af8 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -379,7 +379,7 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t jl_init_function(proto.decl, params.TargetTriple); // TODO: maybe this can be cached in codeinst->specfptr? int8_t gc_state = jl_gc_unsafe_enter(ct->ptls); // codegen may contain safepoints (such as jl_subtype calls) - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); 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); @@ -569,7 +569,7 @@ static void jl_compile_codeinst_now(jl_code_instance_t *codeinst) jl_ExecutionEngine->addModule(std::move(TSM)); // may safepoint // If logging of the compilation stream is enabled, // then dump the method-instance specialization type to the stream - jl_method_instance_t *mi = codeinst->def; + jl_method_instance_t *mi = jl_get_ci_mi(codeinst); if (jl_is_method(mi->def.method)) { auto stream = *jl_ExecutionEngine->get_dump_compiles_stream(); if (stream) { @@ -690,7 +690,7 @@ static void jl_emit_codeinst_to_jit( params.cache = true; params.imaging_mode = imaging_default(); orc::ThreadSafeModule result_m = - jl_create_ts_module(name_from_method_instance(codeinst->def), params.tsctx, params.DL, params.TargetTriple); + jl_create_ts_module(name_from_method_instance(jl_get_ci_mi(codeinst)), params.tsctx, params.DL, params.TargetTriple); params.temporary_roots = jl_alloc_array_1d(jl_array_any_type, 0); JL_GC_PUSH1(¶ms.temporary_roots); jl_llvm_functions_t decls = jl_emit_codeinst(result_m, codeinst, src, params); // contains safepoints @@ -698,7 +698,7 @@ static void jl_emit_codeinst_to_jit( JL_GC_POP(); return; } - jl_optimize_roots(params, codeinst->def, *result_m.getModuleUnlocked()); // contains safepoints + jl_optimize_roots(params, jl_get_ci_mi(codeinst), *result_m.getModuleUnlocked()); // contains safepoints params.temporary_roots = nullptr; JL_GC_POP(); { // drop lock before acquiring engine_lock @@ -899,14 +899,14 @@ void jl_generate_fptr_for_unspecialized_impl(jl_code_instance_t *unspec) compiler_start_time = jl_hrtime(); jl_code_info_t *src = NULL; JL_GC_PUSH1(&src); - jl_method_t *def = unspec->def->def.method; + jl_method_t *def = jl_get_ci_mi(unspec)->def.method; if (jl_is_method(def)) { src = (jl_code_info_t*)def->source; if (src && (jl_value_t*)src != jl_nothing) src = jl_uncompress_ir(def, NULL, (jl_value_t*)src); } else { - jl_method_instance_t *mi = unspec->def; + jl_method_instance_t *mi = jl_get_ci_mi(unspec); jl_code_instance_t *uninferred = jl_cached_uninferred( jl_atomic_load_relaxed(&mi->cache), 1); assert(uninferred); @@ -2213,7 +2213,7 @@ StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_callptr_t invoke, jl else { stream_fname << "jlsys_"; } - const char* unadorned_name = jl_symbol_name(codeinst->def->def.method->name); + const char* unadorned_name = jl_symbol_name(jl_get_ci_mi(codeinst)->def.method->name); stream_fname << unadorned_name << "_" << RLST_inc++; *fname = std::move(stream_fname.str()); // store to ReverseLocalSymbolTable addGlobalMapping(*fname, Addr); diff --git a/src/jitlayers.h b/src/jitlayers.h index 6665be6a33faa..191235febad62 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -277,6 +277,7 @@ jl_llvm_functions_t jl_emit_code( orc::ThreadSafeModule &M, jl_method_instance_t *mi, jl_code_info_t *src, + jl_value_t *abi, jl_codegen_params_t ¶ms); jl_llvm_functions_t jl_emit_codeinst( diff --git a/src/jl_exported_data.inc b/src/jl_exported_data.inc index 8711c14514145..62acce6ce1d65 100644 --- a/src/jl_exported_data.inc +++ b/src/jl_exported_data.inc @@ -116,6 +116,7 @@ XX(jl_simplevector_type) \ XX(jl_slotnumber_type) \ XX(jl_ssavalue_type) \ + XX(jl_abioverride_type) \ XX(jl_stackovf_exception) \ XX(jl_string_type) \ XX(jl_symbol_type) \ diff --git a/src/jltypes.c b/src/jltypes.c index 52b993cd5aa4d..25bac828edf06 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3656,7 +3656,7 @@ void jl_init_types(void) JL_GC_DISABLED "specsigflags", "precompile", "relocatability", "invoke", "specptr"), // function object decls jl_svec(18, - jl_method_instance_type, + jl_any_type, jl_any_type, jl_any_type, jl_ulong_type, diff --git a/src/julia.h b/src/julia.h index a9864aad16ccc..54f792b984609 100644 --- a/src/julia.h +++ b/src/julia.h @@ -426,7 +426,7 @@ typedef struct _jl_opaque_closure_t { // This type represents an executable operation typedef struct _jl_code_instance_t { JL_DATA_TYPE - jl_method_instance_t *def; // method this is specialized from + jl_value_t *def; // MethodInstance or ABIOverride jl_value_t *owner; // Compiler token this belongs to, `jl_nothing` is reserved for native _Atomic(struct _jl_code_instance_t*) next; // pointer to the next cache entry @@ -479,6 +479,13 @@ typedef struct _jl_code_instance_t { } specptr; // private data for `jlcall entry point } jl_code_instance_t; +// May be used as the ->def field of a CodeInstance to override the ABI +typedef struct _jl_abi_overwrite_t { + JL_DATA_TYPE + jl_value_t *abi; + jl_method_instance_t *def; +} jl_abi_overwrite_t; + // all values are callable as Functions typedef jl_value_t jl_function_t; @@ -935,6 +942,7 @@ extern JL_DLLIMPORT jl_datatype_t *jl_fielderror_type JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_datatype_t *jl_atomicerror_type JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_datatype_t *jl_missingcodeerror_type JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_datatype_t *jl_lineinfonode_type JL_GLOBALLY_ROOTED; +extern JL_DLLIMPORT jl_datatype_t *jl_abioverride_type JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_stackovf_exception JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_memory_exception JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_readonlymemory_exception JL_GLOBALLY_ROOTED; diff --git a/src/julia_internal.h b/src/julia_internal.h index 4741316093f95..5efc56ca91f5d 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -693,6 +693,13 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( uint32_t effects, jl_value_t *analysis_results, uint8_t relocatability, jl_debuginfo_t *di, jl_svec_t *edges /* , int absolute_max*/); +STATIC_INLINE jl_method_instance_t *jl_get_ci_mi(jl_code_instance_t *ci) +{ + if (jl_typeof(ci->def) == (jl_value_t*)jl_abioverride_type) + return ((jl_abi_overwrite_t*)ci->def)->def; + return (jl_method_instance_t*)ci->def; +} + JL_DLLEXPORT const char *jl_debuginfo_file(jl_debuginfo_t *debuginfo) JL_NOTSAFEPOINT; JL_DLLEXPORT const char *jl_debuginfo_file1(jl_debuginfo_t *debuginfo) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_module_t *jl_debuginfo_module1(jl_value_t *debuginfo_def) JL_NOTSAFEPOINT; diff --git a/src/precompile_utils.c b/src/precompile_utils.c index 81c60ba70d29f..51776f5ae0ea4 100644 --- a/src/precompile_utils.c +++ b/src/precompile_utils.c @@ -338,7 +338,7 @@ static void *jl_precompile_worklist(jl_array_t *worklist, jl_array_t *extext_met n = jl_array_nrows(new_ext_cis); for (i = 0; i < n; i++) { jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(new_ext_cis, i); - precompile_enq_specialization_(ci->def, m); + precompile_enq_specialization_(jl_get_ci_mi(ci), m); } } } diff --git a/src/staticdata.c b/src/staticdata.c index 1665b5be4ed0f..60435270a9a8a 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -101,7 +101,7 @@ extern "C" { // TODO: put WeakRefs on the weak_refs list during deserialization // TODO: handle finalizers -#define NUM_TAGS 193 +#define NUM_TAGS 194 // An array of references that need to be restored from the sysimg // This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C. @@ -216,6 +216,7 @@ jl_value_t **const*const get_tags(void) { INSERT_TAG(jl_addrspace_typename); INSERT_TAG(jl_addrspacecore_type); INSERT_TAG(jl_debuginfo_type); + INSERT_TAG(jl_abioverride_type); // special typenames INSERT_TAG(jl_tuple_typename); @@ -908,13 +909,14 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ } if (s->incremental && jl_is_code_instance(v)) { jl_code_instance_t *ci = (jl_code_instance_t*)v; + jl_method_instance_t *mi = jl_get_ci_mi(ci); // make sure we don't serialize other reachable cache entries of foreign methods // Should this now be: // if (ci !in ci->defs->cache) // record_field_change((jl_value_t**)&ci->next, NULL); // Why are we checking that the method/module this originates from is in_image? // and then disconnect this CI? - if (jl_object_in_image((jl_value_t*)ci->def->def.value)) { + if (jl_object_in_image((jl_value_t*)mi->def.value)) { // TODO: if (ci in ci->defs->cache) record_field_change((jl_value_t**)&ci->next, NULL); } @@ -922,8 +924,8 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ if (inferred && inferred != jl_nothing) { // disregard if there is nothing here to delete (e.g. builtins, unspecialized) if (!is_relocatable_ci(&relocatable_ext_cis, ci)) record_field_change((jl_value_t**)&ci->inferred, jl_nothing); - else if (jl_is_method(ci->def->def.method) && // don't delete toplevel code - ci->def->def.method->source) { // don't delete code from optimized opaque closures that can't be reconstructed (and builtins) + else if (jl_is_method(mi->def.method) && // don't delete toplevel code + mi->def.method->source) { // don't delete code from optimized opaque closures that can't be reconstructed (and builtins) if (jl_atomic_load_relaxed(&ci->max_world) != ~(size_t)0 || // delete all code that cannot run jl_atomic_load_relaxed(&ci->invoke) == jl_fptr_const_return) { // delete all code that just returns a constant record_field_change((jl_value_t**)&ci->inferred, jl_nothing); @@ -1808,7 +1810,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED fptr_id = JL_API_CONST; } else { - if (jl_is_method(ci->def->def.method)) { + if (jl_is_method(jl_get_ci_mi(ci)->def.method)) { builtin_id = jl_fptr_id(jl_atomic_load_relaxed(&ci->specptr.fptr)); if (builtin_id) { // found in the table of builtins assert(builtin_id >= 2); @@ -2353,7 +2355,7 @@ static void jl_update_all_fptrs(jl_serializer_state *s, jl_image_t *image) jl_code_instance_t *codeinst = (jl_code_instance_t*)(base + offset); assert(jl_is_method(codeinst->def->def.method) && jl_atomic_load_relaxed(&codeinst->invoke) != jl_fptr_const_return); assert(specfunc ? jl_atomic_load_relaxed(&codeinst->invoke) != NULL : jl_atomic_load_relaxed(&codeinst->invoke) == NULL); - linfos[i] = codeinst->def; // now it's a MethodInstance + linfos[i] = jl_get_ci_mi(codeinst); // now it's a MethodInstance void *fptr = fvars.ptrs[i]; for (; clone_idx < fvars.nclones; clone_idx++) { uint32_t idx = fvars.clone_idxs[clone_idx] & jl_sysimg_val_mask; diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index ea0b7216155bd..5ff7a7b1b1fc0 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -188,7 +188,7 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, jl_code_instance_t *be; i = get_next_edge(mi->backedges, i, NULL, &be); JL_GC_PROMISE_ROOTED(be); // get_next_edge propagates the edge for us here - int child_found = has_backedge_to_worklist(be->def, visited, stack); + int child_found = has_backedge_to_worklist(jl_get_ci_mi(be), visited, stack); if (child_found == 1 || child_found == 2) { // found what we were looking for, so terminate early found = 1; @@ -219,7 +219,7 @@ static int is_relocatable_ci(htable_t *relocatable_ext_cis, jl_code_instance_t * { if (!ci->relocatability) return 0; - jl_method_instance_t *mi = ci->def; + jl_method_instance_t *mi = jl_get_ci_mi(ci); jl_method_t *m = mi->def.method; if (!ptrhash_has(relocatable_ext_cis, ci) && jl_object_in_image((jl_value_t*)m) && (!jl_is_method(m) || jl_object_in_image((jl_value_t*)m->module))) return 0; @@ -249,7 +249,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list) assert(jl_is_code_instance(ci)); if (!ci->relocatability) continue; - jl_method_instance_t *mi = ci->def; + jl_method_instance_t *mi = jl_get_ci_mi(ci); jl_method_t *m = mi->def.method; if (ci->owner == jl_nothing && jl_atomic_load_relaxed(&ci->inferred) && jl_is_method(m) && jl_object_in_image((jl_value_t*)m->module)) { int found = has_backedge_to_worklist(mi, &visited, &stack); @@ -283,7 +283,7 @@ static void jl_collect_new_roots(htable_t *relocatable_ext_cis, jl_array_t *root for (size_t i = 0; i < l; i++) { jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(new_ext_cis, i); assert(jl_is_code_instance(ci)); - jl_method_t *m = ci->def->def.method; + jl_method_t *m = jl_get_ci_mi(ci)->def.method; assert(jl_is_method(m)); ptrhash_put(&mset, (void*)m, (void*)m); ptrhash_put(relocatable_ext_cis, (void*)ci, (void*)ci); @@ -864,7 +864,7 @@ static int jl_verify_method(jl_code_instance_t *codeinst, size_t *minworld, size *minworld = 1; size_t current_world = jl_atomic_load_relaxed(&jl_world_counter); *maxworld = current_world; - assert(jl_is_method_instance(codeinst->def) && jl_is_method(codeinst->def->def.method)); + assert(jl_is_method_instance(jl_get_ci_mi(codeinst)) && jl_is_method(jl_get_ci_mi(codeinst)->def.method)); void **bp = ptrhash_bp(visiting, codeinst); if (*bp != HT_NOTFOUND) return (char*)*bp - (char*)HT_NOTFOUND; // cycle idx @@ -893,7 +893,7 @@ static int jl_verify_method(jl_code_instance_t *codeinst, size_t *minworld, size size_t max_valid2; assert(!jl_is_method(edge)); // `Method`-edge isn't allowed for the optimized one-edge format if (jl_is_code_instance(edge)) - edge = (jl_value_t*)((jl_code_instance_t*)edge)->def; + edge = (jl_value_t*)jl_get_ci_mi((jl_code_instance_t*)edge); if (jl_is_method_instance(edge)) { jl_method_instance_t *mi = (jl_method_instance_t*)edge; sig = jl_type_intersection(mi->def.method->sig, (jl_value_t*)mi->specTypes); // TODO: ?? @@ -917,7 +917,7 @@ static int jl_verify_method(jl_code_instance_t *codeinst, size_t *minworld, size continue; } if (jl_is_code_instance(callee)) - callee = ((jl_code_instance_t*)callee)->def; + callee = jl_get_ci_mi((jl_code_instance_t*)callee); if (jl_is_method_instance(callee)) { meth = callee->def.method; } @@ -1048,7 +1048,7 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_ci_list) for (size_t i = 0; i < nedges; i++) { jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_array_ptr_ref(edges, i); jl_svec_t *callees = jl_atomic_load_relaxed(&codeinst->edges); - jl_method_instance_t *caller = codeinst->def; + jl_method_instance_t *caller = jl_get_ci_mi(codeinst); jl_verify_method_graph(codeinst, &stack, &visiting); size_t minvalid = jl_atomic_load_relaxed(&codeinst->min_world); size_t maxvalid = jl_atomic_load_relaxed(&codeinst->max_world); diff --git a/test/precompile.jl b/test/precompile.jl index 1607d4c6b502b..90ed6a08c3e6e 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -915,7 +915,7 @@ precompile_test_harness("code caching") do dir # external callers mods = Module[] for be in mi.backedges - push!(mods, (be.def.def::Method).module) # XXX + push!(mods, ((be.def::MethodInstance).def::Method).module) # XXX end @test MA ∈ mods @test MB ∈ mods @@ -1837,7 +1837,7 @@ precompile_test_harness("PkgCacheInspector") do load_path m = only(external_methods).func::Method @test m.name == :repl_cmd && m.nargs < 2 @test new_ext_cis === nothing || any(new_ext_cis) do ci - mi = ci.def + mi = ci.def::MethodInstance mi.specTypes == Tuple{typeof(Base.repl_cmd), Int, String} end end