@@ -92,7 +92,7 @@ If set to `true`, record per-method-instance timings within type inference in th
9292__set_measure_typeinf (onoff:: Bool ) = __measure_typeinf__[] = onoff
9393const __measure_typeinf__ = RefValue {Bool} (false )
9494
95- function finish! (interp:: AbstractInterpreter , caller:: InferenceState )
95+ function finish! (interp:: AbstractInterpreter , caller:: InferenceState , validation_world :: UInt )
9696 result = caller. result
9797 opt = result. src
9898 if opt isa OptimizationState
@@ -108,12 +108,7 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState)
108108 ci = result. ci
109109 # if we aren't cached, we don't need this edge
110110 # but our caller might, so let's just make it anyways
111- if last (result. valid_worlds) >= get_world_counter ()
112- # TODO : this should probably come after all store_backedges (after optimizations) for the entire graph in finish_cycle
113- # since we should be requiring that all edges first get their backedges set, as a batch
114- result. valid_worlds = WorldRange (first (result. valid_worlds), typemax (UInt))
115- end
116- if last (result. valid_worlds) == typemax (UInt)
111+ if last (result. valid_worlds) >= validation_world
117112 # if we can record all of the backedges in the global reverse-cache,
118113 # we can now widen our applicability in the global cache too
119114 store_backedges (ci, edges)
@@ -202,7 +197,14 @@ function finish_nocycle(::AbstractInterpreter, frame::InferenceState)
202197 if opt isa OptimizationState # implies `may_optimize(caller.interp) === true`
203198 optimize (frame. interp, opt, frame. result)
204199 end
205- finish! (frame. interp, frame)
200+ validation_world = get_world_counter ()
201+ finish! (frame. interp, frame, validation_world)
202+ if isdefined (frame. result, :ci )
203+ # After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
204+ # (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
205+ # validity.
206+ ccall (:jl_promote_ci_to_current , Cvoid, (Any, UInt), frame. result. ci, validation_world)
207+ end
206208 if frame. cycleid != 0
207209 frames = frame. callstack:: Vector{AbsIntState}
208210 @assert frames[end ] === frame
@@ -236,10 +238,19 @@ function finish_cycle(::AbstractInterpreter, frames::Vector{AbsIntState}, cyclei
236238 optimize (caller. interp, opt, caller. result)
237239 end
238240 end
241+ validation_world = get_world_counter ()
242+ cis = CodeInstance[]
239243 for frameid = cycleid: length (frames)
240244 caller = frames[frameid]:: InferenceState
241- finish! (caller. interp, caller)
245+ finish! (caller. interp, caller, validation_world)
246+ if isdefined (caller. result, :ci )
247+ push! (cis, caller. result. ci)
248+ end
242249 end
250+ # After validation, under the world_counter_lock, set max_world to typemax(UInt) for all dependencies
251+ # (recursively). From that point onward the ordinary backedge mechanism is responsible for maintaining
252+ # validity.
253+ ccall (:jl_promote_cis_to_current , Cvoid, (Ptr{CodeInstance}, Csize_t, UInt), cis, length (cis), validation_world)
243254 resize! (frames, cycleid - 1 )
244255 return nothing
245256end
@@ -1266,6 +1277,7 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim::
12661277 tocompile = Vector {CodeInstance} ()
12671278 codeinfos = []
12681279 # first compute the ABIs of everything
1280+ latest = true # whether this_world == world_counter()
12691281 for this_world in reverse (sort! (worlds))
12701282 interp = NativeInterpreter (this_world)
12711283 for i = 1 : length (methods)
@@ -1278,18 +1290,18 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim::
12781290 # then we want to compile and emit this
12791291 if item. def. primary_world <= this_world <= item. def. deleted_world
12801292 ci = typeinf_ext (interp, item, SOURCE_MODE_NOT_REQUIRED)
1281- ci isa CodeInstance && ! use_const_api (ci) && push! (tocompile, ci)
1293+ ci isa CodeInstance && push! (tocompile, ci)
12821294 end
1283- elseif item isa SimpleVector
1295+ elseif item isa SimpleVector && latest
12841296 (rt:: Type , sig:: Type ) = item
12851297 # make a best-effort attempt to enqueue the relevant code for the ccallable
12861298 ptr = ccall (:jl_get_specialization1 ,
12871299 #= MethodInstance =# Ptr{Cvoid}, (Any, Csize_t, Cint),
12881300 sig, this_world, #= mt_cache =# 0 )
12891301 if ptr != = C_NULL
1290- mi = unsafe_pointer_to_objref (ptr)
1302+ mi = unsafe_pointer_to_objref (ptr):: MethodInstance
12911303 ci = typeinf_ext (interp, mi, SOURCE_MODE_NOT_REQUIRED)
1292- ci isa CodeInstance && ! use_const_api (ci) && push! (tocompile, ci)
1304+ ci isa CodeInstance && push! (tocompile, ci)
12931305 end
12941306 # additionally enqueue the ccallable entrypoint / adapter, which implicitly
12951307 # invokes the above ci
@@ -1305,7 +1317,7 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim::
13051317 mi = get_ci_mi (callee)
13061318 def = mi. def
13071319 if use_const_api (callee)
1308- src = codeinfo_for_const (interp, mi, code . rettype_const)
1320+ src = codeinfo_for_const (interp, mi, callee . rettype_const)
13091321 elseif haskey (interp. codegen, callee)
13101322 src = interp. codegen[callee]
13111323 elseif isa (def, Method) && ccall (:jl_get_module_infer , Cint, (Any,), def. module) == 0 && ! trim
@@ -1327,6 +1339,7 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim::
13271339 println (" warning: failed to get code for " , mi)
13281340 end
13291341 end
1342+ latest = false
13301343 end
13311344 return codeinfos
13321345end
0 commit comments