@@ -683,6 +683,15 @@ function Base.precompile(@nospecialize(job::CompilerJob))
683683 return true
684684end
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+
686695function 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