6
6
# `tls_world_age` should be used to look up the current world age. in most cases, this is
7
7
# what you should use to invoke the compiler with.
8
8
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
11
14
12
15
# # looking up method instances
13
16
14
- export methodinstance
17
+ export methodinstance, generic_methodinstance
15
18
16
19
@inline function signature_type_by_tt (ft:: Type , tt:: Type )
17
20
u = Base. unwrap_unionall (tt):: DataType
49
52
Look up the method instance that corresponds to invoking the function with type `ft` with
50
53
argument typed `tt`. If the `world` argument is specified, the look-up is static and will
51
54
always 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.
53
59
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.
55
62
56
- If the method is not found, a `MethodError` is thrown.
57
63
"""
58
64
methodinstance
59
65
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
+
60
78
# on 1.11 (JuliaLang/julia#52572, merged as part of JuliaLang/julia#52233) we can use
61
79
# Julia's cached method lookup to simply look up method instances at run time.
62
80
if VERSION >= v " 1.11.0-DEV.1552"
63
81
64
82
# 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 ())
66
85
sig = signature_type_by_tt (ft, tt)
86
+ @assert Base. isdispatchtuple (sig) # JuliaLang/julia#52233
67
87
68
88
mi = ccall (:jl_method_lookup_by_tt , Any,
69
89
(Any, Csize_t, Any),
@@ -79,19 +99,10 @@ if VERSION >= v"1.11.0-DEV.1552"
79
99
return mi
80
100
end
81
101
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
83
103
else
84
104
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
95
106
96
107
# on 1.10 (JuliaLang/julia#48611) generated functions know which world to generate code for.
97
108
# we can use this to cache and automatically invalidate method instance look-ups.
@@ -153,18 +164,15 @@ end
153
164
$ (Expr (:meta , :generated , methodinstance_generator))
154
165
end
155
166
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
-
161
167
end
162
168
163
169
end
164
170
165
171
166
172
# # code instance cache
173
+ const HAS_INTEGRATED_CACHE = VERSION >= v " 1.11.0-DEV.1552"
167
174
175
+ if ! HAS_INTEGRATED_CACHE
168
176
struct CodeCache
169
177
dict:: IdDict{MethodInstance,Vector{CodeInstance}}
170
178
@@ -292,6 +300,8 @@ function (callback::CodeCacheCallback)(replaced::MethodInstance, max_world::UInt
292
300
end
293
301
294
302
end
303
+ end # !HAS_INTEGRATED_CACHE
304
+
295
305
296
306
# # method overrides
297
307
@@ -323,13 +333,47 @@ struct GPUInterpreter <: CC.AbstractInterpreter
323
333
world:: UInt
324
334
method_table:: GPUMethodTableView
325
335
336
+ @static if HAS_INTEGRATED_CACHE
337
+ token:: Any
338
+ else
326
339
code_cache:: CodeCache
340
+ end
327
341
inf_cache:: Vector{CC.InferenceResult}
328
342
329
343
inf_params:: CC.InferenceParams
330
344
opt_params:: CC.OptimizationParams
331
345
end
332
346
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
+
333
377
function GPUInterpreter (world:: UInt = Base. get_world_counter ();
334
378
method_table:: MTType ,
335
379
code_cache:: CodeCache ,
@@ -356,12 +400,17 @@ function GPUInterpreter(interp::GPUInterpreter;
356
400
code_cache, inf_cache,
357
401
inf_params, opt_params)
358
402
end
403
+ end # HAS_INTEGRATED_CACHE
359
404
360
405
CC. InferenceParams (interp:: GPUInterpreter ) = interp. inf_params
361
406
CC. OptimizationParams (interp:: GPUInterpreter ) = interp. opt_params
362
407
#= CC.=# get_inference_world (interp:: GPUInterpreter ) = interp. world
363
408
CC. 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
365
414
366
415
# No need to do any locking since we're not putting our results into the runtime cache
367
416
CC. lock_mi_inference (interp:: GPUInterpreter , mi:: MethodInstance ) = nothing
413
462
414
463
415
464
# # world view of the cache
416
-
417
465
using Core. Compiler: WorldView
418
466
467
+ if ! HAS_INTEGRATED_CACHE
468
+
419
469
function CC. haskey (wvc:: WorldView{CodeCache} , mi:: MethodInstance )
420
470
CC. get (wvc, mi, nothing ) != = nothing
421
471
end
@@ -454,6 +504,7 @@ function CC.setindex!(wvc::WorldView{CodeCache}, ci::CodeInstance, mi::MethodIns
454
504
CC. setindex! (wvc. cache, ci, mi)
455
505
end
456
506
507
+ end # HAS_INTEGRATED_CACHE
457
508
458
509
# # codegen/inference integration
459
510
526
577
527
578
function compile_method_instance (@nospecialize (job:: CompilerJob ))
528
579
# populate the cache
529
- cache = ci_cache (job)
530
580
interp = get_interpreter (job)
581
+ cache = CC. code_cache (interp)
531
582
if ci_cache_lookup (cache, job. source, job. world, job. world) === nothing
532
583
ci_cache_populate (interp, cache, job. source, job. world, job. world)
533
584
end
0 commit comments