Skip to content

Commit 749a3e4

Browse files
authored
Fix codeinstance mapping when using nested interpretation (#755)
* Fix codeinstance mapping when using nested interpretation * syntax? * syntax? * correct * add comment * fix 1.13
1 parent 03d1170 commit 749a3e4

1 file changed

Lines changed: 62 additions & 11 deletions

File tree

src/jlgen.jl

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,15 @@ function Base.precompile(@nospecialize(job::CompilerJob))
683683
return true
684684
end
685685

686+
687+
const HAS_LLVM_GET_CIS = (
688+
VERSION >= v"1.13.0-DEV.1120" || (
689+
Libdl.dlsym(
690+
unsafe_load(cglobal(:jl_libjulia_handle, Ptr{Cvoid})), :jl_get_llvm_cis, throw_error = false
691+
) !== nothing
692+
)
693+
)
694+
686695
function compile_method_instance(@nospecialize(job::CompilerJob))
687696
if job.source.def.primary_world > job.world
688697
error("Cannot compile $(job.source) for world $(job.world); method is only valid from world $(job.source.def.primary_world) onwards")
@@ -799,22 +808,20 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
799808
end
800809
end
801810

802-
if VERSION >= v"1.13.0-DEV.1120"
811+
code_instances = Core.CodeInstance[]
812+
813+
if HAS_LLVM_GET_CIS
803814
# on sufficiently recent versions of Julia, we can query the CIs compiled.
804815
# this is required after the move to `invoke(::CodeInstance)`, because our
805816
# lookup function (used to populate method_instances) isn't always called then.
806817

807818
num_cis = Ref{Csize_t}(0)
808819
@ccall jl_get_llvm_cis(native_code::Ptr{Cvoid}, num_cis::Ptr{Csize_t},
809820
C_NULL::Ptr{Cvoid})::Nothing
810-
resize!(method_instances, num_cis[])
821+
resize!(code_instances, num_cis[])
811822
@ccall jl_get_llvm_cis(native_code::Ptr{Cvoid}, num_cis::Ptr{Csize_t},
812-
method_instances::Ptr{Cvoid})::Nothing
813-
814-
for (i, ci) in enumerate(method_instances)
815-
method_instances[i] = ci.def::MethodInstance
816-
end
817-
823+
code_instances::Ptr{Cvoid}
824+
)::Nothing
818825
elseif VERSION >= v"1.12.0-DEV.1703"
819826
# slightly older versions of Julia used MIs directly
820827

@@ -826,11 +833,53 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
826833
method_instances::Ptr{Cvoid})::Nothing
827834
end
828835

836+
if !HAS_LLVM_GET_CIS
837+
for mi in method_instances
838+
ci = ci_cache_lookup(cache, mi, job.world, job.world)
839+
ci === nothing && continue
840+
841+
llvm_func_idx = Ref{Int32}(-1)
842+
llvm_specfunc_idx = Ref{Int32}(-1)
843+
ccall(
844+
:jl_get_function_id, Nothing,
845+
(Ptr{Cvoid}, Any, Ptr{Int32}, Ptr{Int32}),
846+
native_code, ci, llvm_func_idx, llvm_specfunc_idx
847+
)
848+
# Suppose we have two nested interpreters in use at the same time.
849+
# Looking up a ci from the cache is not unique for a given mi.
850+
# Consequently its possible we may not have compiled the ci found
851+
# by the cache (instead having compiled the ci from the other interp).
852+
if llvm_func_idx[] == -1
853+
continue
854+
end
855+
push!(code_instances, ci)
856+
end
857+
else
858+
# To avoid a clash in the compiled cache containing both with an interpreter token (like GPUCompiler.GPUCompilerCacheToken) and native,
859+
# prefer the non-native code-instance.
860+
# TODO: in the future we should migrate compiled to have the ci as the key, not the mi.
861+
native_mis = Set{MethodInstance}()
862+
for ci in code_instances
863+
if ci.owner !== nothing
864+
push!(native_mis, ci.def::MethodInstance)
865+
end
866+
end
867+
filter!(code_instances) do ci
868+
return ci.owner !== nothing || in(ci.def, native_mis)
869+
end
870+
end
871+
872+
# Avoid redundant code_instances. This is necessary to avoid false positives trying to add the same key'd mi to the compiled Dict.
873+
unique!(code_instances)
874+
875+
resize!(method_instances, length(code_instances))
876+
for (i, ci) in enumerate(code_instances)
877+
method_instances[i] = ci.def::MethodInstance
878+
end
879+
829880
# process all compiled method instances
830881
compiled = Dict()
831-
for mi in method_instances
832-
ci = ci_cache_lookup(cache, mi, job.world, job.world)
833-
ci === nothing && continue
882+
for (ci, mi) in zip(code_instances, method_instances)
834883

835884
# get the function index
836885
llvm_func_idx = Ref{Int32}(-1)
@@ -859,6 +908,8 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
859908
nothing
860909
end
861910

911+
@assert !haskey(compiled, mi)
912+
862913
# NOTE: it's not safe to store raw LLVM functions here, since those may get
863914
# removed or renamed during optimization, so we store their name instead.
864915
compiled[mi] = (; ci, func=llvm_func, specfunc=llvm_specfunc)

0 commit comments

Comments
 (0)