|
3 | 3 | # TODO set up a version who defines new interpreter with persistent cache? |
4 | 4 |
|
5 | 5 | """ |
6 | | - @newinterp NewInterpreter |
| 6 | + @newinterp NewInterpreter [ephemeral_cache::Bool=false] |
7 | 7 |
|
8 | 8 | Defines new `NewInterpreter <: AbstractInterpreter` whose cache is separated |
9 | 9 | from the native code cache, satisfying the minimum interface requirements. |
| 10 | +
|
| 11 | +When the `ephemeral_cache=true` option is specified, `NewInterpreter` will hold |
| 12 | +`CodeInstance` in an ephemeral non-integrated cache, rather than in the integrated |
| 13 | +`Core.Compiler.InternalCodeCache`. |
| 14 | +Keep in mind that ephemeral cache lacks support for invalidation and doesn't persist across |
| 15 | +sessions. However it is an usual Julia object of the type `code_cache::IdDict{MethodInstance,CodeInstance}`, |
| 16 | +making it easier for debugging and inspecting the compiler behavior. |
10 | 17 | """ |
11 | | -macro newinterp(InterpName) |
12 | | - cache_token = QuoteNode(gensym(string(InterpName, "Cache"))) |
| 18 | +macro newinterp(InterpName, ephemeral_cache::Bool=false) |
| 19 | + cache_token = QuoteNode(gensym(string(InterpName, "CacheToken"))) |
| 20 | + InterpCacheName = esc(Symbol(string(InterpName, "Cache"))) |
13 | 21 | InterpName = esc(InterpName) |
14 | 22 | C = Core |
15 | 23 | CC = Core.Compiler |
16 | 24 | quote |
| 25 | + $(ephemeral_cache && quote |
| 26 | + struct $InterpCacheName |
| 27 | + dict::IdDict{$C.MethodInstance,$C.CodeInstance} |
| 28 | + end |
| 29 | + $InterpCacheName() = $InterpCacheName(IdDict{$C.MethodInstance,$C.CodeInstance}()) |
| 30 | + end) |
17 | 31 | struct $InterpName <: $CC.AbstractInterpreter |
18 | 32 | meta # additional information |
19 | 33 | world::UInt |
20 | 34 | inf_params::$CC.InferenceParams |
21 | 35 | opt_params::$CC.OptimizationParams |
22 | 36 | inf_cache::Vector{$CC.InferenceResult} |
| 37 | + $(ephemeral_cache && :(code_cache::$InterpCacheName)) |
23 | 38 | function $InterpName(meta = nothing; |
24 | 39 | world::UInt = Base.get_world_counter(), |
25 | 40 | inf_params::$CC.InferenceParams = $CC.InferenceParams(), |
26 | 41 | opt_params::$CC.OptimizationParams = $CC.OptimizationParams(), |
27 | | - inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[]) |
28 | | - return new(meta, world, inf_params, opt_params, inf_cache) |
| 42 | + inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[], |
| 43 | + $(ephemeral_cache ? |
| 44 | + Expr(:kw, :(code_cache::$InterpCacheName), :($InterpCacheName())) : |
| 45 | + Expr(:kw, :_, :nothing))) |
| 46 | + return $(ephemeral_cache ? |
| 47 | + :(new(meta, world, inf_params, opt_params, inf_cache, code_cache)) : |
| 48 | + :(new(meta, world, inf_params, opt_params, inf_cache))) |
29 | 49 | end |
30 | 50 | end |
31 | 51 | $CC.InferenceParams(interp::$InterpName) = interp.inf_params |
32 | 52 | $CC.OptimizationParams(interp::$InterpName) = interp.opt_params |
33 | 53 | $CC.get_inference_world(interp::$InterpName) = interp.world |
34 | 54 | $CC.get_inference_cache(interp::$InterpName) = interp.inf_cache |
35 | 55 | $CC.cache_owner(::$InterpName) = $cache_token |
| 56 | + $(ephemeral_cache && quote |
| 57 | + $CC.code_cache(interp::$InterpName) = $CC.WorldView(interp.code_cache, $CC.WorldRange(interp.world)) |
| 58 | + $CC.get(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance, default) = get(wvc.cache.dict, mi, default) |
| 59 | + $CC.getindex(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = getindex(wvc.cache.dict, mi) |
| 60 | + $CC.haskey(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = haskey(wvc.cache.dict, mi) |
| 61 | + $CC.setindex!(wvc::$CC.WorldView{$InterpCacheName}, ci::$C.CodeInstance, mi::$C.MethodInstance) = setindex!(wvc.cache.dict, ci, mi) |
| 62 | + end) |
36 | 63 | end |
37 | 64 | end |
0 commit comments