66# `tls_world_age` should be used to look up the current world age. in most cases, this is
77# what you should use to invoke the compiler with.
88
9- tls_world_age () = ccall (:jl_get_tls_world_age , UInt, ())
10-
9+ if isdefined (Base, :tls_world_age )
10+ import Base: tls_world_age
11+ else
12+ tls_world_age () = ccall (:jl_get_tls_world_age , UInt, ())
13+ end
1114
1215# # looking up method instances
1316
14- export methodinstance
17+ export methodinstance, generic_methodinstance
1518
1619@inline function signature_type_by_tt (ft:: Type , tt:: Type )
1720 u = Base. unwrap_unionall (tt):: DataType
4952Look up the method instance that corresponds to invoking the function with type `ft` with
5053argument typed `tt`. If the `world` argument is specified, the look-up is static and will
5154always return the same result. If the `world` argument is not specified, the look-up is
52- dynamic and the returned method instance will depende on the current world age.
55+ dynamic and the returned method instance will depende on the current world age. If no method
56+ is found, a `MethodError` is thrown.
57+
58+ This function is highly optimized, and results do not need to be cached additionally.
5359
54- This call is highly optimized, and does not need to be cached additionally.
60+ Only use this function with concrete signatures, i.e., using the types of values you would
61+ pass at run time. For non-concrete signatures, use `generic_methodinstance` instead.
5562
56- If the method is not found, a `MethodError` is thrown.
5763"""
5864methodinstance
5965
66+ function generic_methodinstance (@nospecialize (ft:: Type ), @nospecialize (tt:: Type ),
67+ world:: Integer = tls_world_age ())
68+ sig = signature_type_by_tt (ft, tt)
69+
70+ match, _ = CC. _findsup (sig, nothing , world)
71+ match === nothing && throw (MethodError (ft, tt, world))
72+
73+ mi = CC. specialize_method (match)
74+
75+ return mi:: MethodInstance
76+ end
77+
6078# on 1.11 (JuliaLang/julia#52572, merged as part of JuliaLang/julia#52233) we can use
6179# Julia's cached method lookup to simply look up method instances at run time.
6280if VERSION >= v " 1.11.0-DEV.1552"
6381
6482# XXX : version of Base.method_instance that uses a function type
65- @inline function methodinstance (@nospecialize (ft:: Type ), @nospecialize (tt:: Type ), world:: Integer = tls_world_age ())
83+ @inline function methodinstance (@nospecialize (ft:: Type ), @nospecialize (tt:: Type ),
84+ world:: Integer = tls_world_age ())
6685 sig = signature_type_by_tt (ft, tt)
86+ @assert Base. isdispatchtuple (sig) # JuliaLang/julia#52233
6787
6888 mi = ccall (:jl_method_lookup_by_tt , Any,
6989 (Any, Csize_t, Any),
@@ -79,19 +99,10 @@ if VERSION >= v"1.11.0-DEV.1552"
7999 return mi
80100end
81101
82- # on older versions of Julia, the run-time lookup is much slower, so we'll need to cache it
102+ # on older versions of Julia, we always need to use the generic lookup
83103else
84104
85- function methodinstance (ft:: Type , tt:: Type , world:: Integer )
86- sig = signature_type_by_tt (ft, tt)
87-
88- match, _ = CC. _findsup (sig, nothing , world)
89- match === nothing && throw (MethodError (ft, tt, world))
90-
91- mi = CC. specialize_method (match)
92-
93- return mi:: MethodInstance
94- end
105+ const methodinstance = generic_methodinstance
95106
96107# on 1.10 (JuliaLang/julia#48611) generated functions know which world to generate code for.
97108# we can use this to cache and automatically invalidate method instance look-ups.
@@ -153,18 +164,15 @@ end
153164 $ (Expr (:meta , :generated , methodinstance_generator))
154165end
155166
156- # on really old versions, we can't cache the run-time lookup
157- else
158-
159- methodinstance (f, tt) = methodinstance (f, tt, tls_world_age ())
160-
161167end
162168
163169end
164170
165171
166172# # code instance cache
173+ const HAS_INTEGRATED_CACHE = VERSION >= v " 1.11.0-DEV.1552"
167174
175+ if ! HAS_INTEGRATED_CACHE
168176struct CodeCache
169177 dict:: IdDict{MethodInstance,Vector{CodeInstance}}
170178
@@ -292,6 +300,8 @@ function (callback::CodeCacheCallback)(replaced::MethodInstance, max_world::UInt
292300end
293301
294302end
303+ end # !HAS_INTEGRATED_CACHE
304+
295305
296306# # method overrides
297307
@@ -323,13 +333,47 @@ struct GPUInterpreter <: CC.AbstractInterpreter
323333 world:: UInt
324334 method_table:: GPUMethodTableView
325335
336+ @static if HAS_INTEGRATED_CACHE
337+ token:: Any
338+ else
326339 code_cache:: CodeCache
340+ end
327341 inf_cache:: Vector{CC.InferenceResult}
328342
329343 inf_params:: CC.InferenceParams
330344 opt_params:: CC.OptimizationParams
331345end
332346
347+ @static if HAS_INTEGRATED_CACHE
348+ function GPUInterpreter (world:: UInt = Base. get_world_counter ();
349+ method_table:: MTType ,
350+ token:: Any ,
351+ inf_params:: CC.InferenceParams ,
352+ opt_params:: CC.OptimizationParams )
353+ @assert world <= Base. get_world_counter ()
354+
355+ method_table = get_method_table_view (world, method_table)
356+ inf_cache = Vector {CC.InferenceResult} ()
357+
358+ return GPUInterpreter (world, method_table,
359+ token, inf_cache,
360+ inf_params, opt_params)
361+ end
362+
363+ function GPUInterpreter (interp:: GPUInterpreter ;
364+ world:: UInt = interp. world,
365+ method_table:: GPUMethodTableView = interp. method_table,
366+ token:: Any = interp. token,
367+ inf_cache:: Vector{CC.InferenceResult} = interp. inf_cache,
368+ inf_params:: CC.InferenceParams = interp. inf_params,
369+ opt_params:: CC.OptimizationParams = interp. opt_params)
370+ return GPUInterpreter (world, method_table,
371+ token, inf_cache,
372+ inf_params, opt_params)
373+ end
374+
375+ else
376+
333377function GPUInterpreter (world:: UInt = Base. get_world_counter ();
334378 method_table:: MTType ,
335379 code_cache:: CodeCache ,
@@ -356,12 +400,17 @@ function GPUInterpreter(interp::GPUInterpreter;
356400 code_cache, inf_cache,
357401 inf_params, opt_params)
358402end
403+ end # HAS_INTEGRATED_CACHE
359404
360405CC. InferenceParams (interp:: GPUInterpreter ) = interp. inf_params
361406CC. OptimizationParams (interp:: GPUInterpreter ) = interp. opt_params
362407#= CC.=# get_inference_world (interp:: GPUInterpreter ) = interp. world
363408CC. get_inference_cache (interp:: GPUInterpreter ) = interp. inf_cache
364- CC. code_cache (interp:: GPUInterpreter ) = WorldView (interp. code_cache, interp. world)
409+ if HAS_INTEGRATED_CACHE
410+ CC. cache_owner (interp:: GPUInterpreter ) = interp. token
411+ else
412+ CC. code_cache (interp:: GPUInterpreter ) = WorldView (interp. code_cache, interp. world)
413+ end
365414
366415# No need to do any locking since we're not putting our results into the runtime cache
367416CC. lock_mi_inference (interp:: GPUInterpreter , mi:: MethodInstance ) = nothing
413462
414463
415464# # world view of the cache
416-
417465using Core. Compiler: WorldView
418466
467+ if ! HAS_INTEGRATED_CACHE
468+
419469function CC. haskey (wvc:: WorldView{CodeCache} , mi:: MethodInstance )
420470 CC. get (wvc, mi, nothing ) != = nothing
421471end
@@ -454,6 +504,7 @@ function CC.setindex!(wvc::WorldView{CodeCache}, ci::CodeInstance, mi::MethodIns
454504 CC. setindex! (wvc. cache, ci, mi)
455505end
456506
507+ end # HAS_INTEGRATED_CACHE
457508
458509# # codegen/inference integration
459510
526577
527578function compile_method_instance (@nospecialize (job:: CompilerJob ))
528579 # populate the cache
529- cache = ci_cache (job)
530580 interp = get_interpreter (job)
581+ cache = CC. code_cache (interp)
531582 if ci_cache_lookup (cache, job. source, job. world, job. world) === nothing
532583 ci_cache_populate (interp, cache, job. source, job. world, job. world)
533584 end
0 commit comments