|
1 | 1 | module CompilerDevTools |
2 | 2 |
|
3 | 3 | using Compiler |
| 4 | +using Compiler: argextype, widenconst |
4 | 5 | using Core.IR |
| 6 | +using Base: isexpr |
| 7 | + |
| 8 | +mutable struct SplitCacheOwner end |
5 | 9 |
|
6 | | -struct SplitCacheOwner; end |
7 | 10 | struct SplitCacheInterp <: Compiler.AbstractInterpreter |
8 | 11 | world::UInt |
| 12 | + owner::SplitCacheOwner |
9 | 13 | inf_params::Compiler.InferenceParams |
10 | 14 | opt_params::Compiler.OptimizationParams |
11 | 15 | inf_cache::Vector{Compiler.InferenceResult} |
12 | 16 | codegen_cache::IdDict{CodeInstance,CodeInfo} |
13 | 17 | function SplitCacheInterp(; |
14 | 18 | world::UInt = Base.get_world_counter(), |
| 19 | + owner::SplitCacheOwner = SplitCacheOwner(), |
15 | 20 | inf_params::Compiler.InferenceParams = Compiler.InferenceParams(), |
16 | 21 | opt_params::Compiler.OptimizationParams = Compiler.OptimizationParams(), |
17 | 22 | inf_cache::Vector{Compiler.InferenceResult} = Compiler.InferenceResult[]) |
18 | | - new(world, inf_params, opt_params, inf_cache, IdDict{CodeInstance,CodeInfo}()) |
| 23 | + new(world, owner, inf_params, opt_params, inf_cache, IdDict{CodeInstance,CodeInfo}()) |
19 | 24 | end |
20 | 25 | end |
21 | 26 |
|
22 | 27 | Compiler.InferenceParams(interp::SplitCacheInterp) = interp.inf_params |
23 | 28 | Compiler.OptimizationParams(interp::SplitCacheInterp) = interp.opt_params |
24 | 29 | Compiler.get_inference_world(interp::SplitCacheInterp) = interp.world |
25 | 30 | Compiler.get_inference_cache(interp::SplitCacheInterp) = interp.inf_cache |
26 | | -Compiler.cache_owner(::SplitCacheInterp) = SplitCacheOwner() |
| 31 | +Compiler.cache_owner(interp::SplitCacheInterp) = interp.owner |
27 | 32 | Compiler.codegen_cache(interp::SplitCacheInterp) = interp.codegen_cache |
28 | 33 |
|
29 | 34 | import Core.OptimizedGenerics.CompilerPlugins: typeinf, typeinf_edge |
30 | | -@eval @noinline typeinf(::SplitCacheOwner, mi::MethodInstance, source_mode::UInt8) = |
31 | | - Base.invoke_in_world(which(typeinf, Tuple{SplitCacheOwner, MethodInstance, UInt8}).primary_world, Compiler.typeinf_ext_toplevel, SplitCacheInterp(; world=Base.tls_world_age()), mi, source_mode) |
| 35 | +@eval @noinline typeinf(owner::SplitCacheOwner, mi::MethodInstance, source_mode::UInt8) = |
| 36 | + Base.invoke_in_world(which(typeinf, Tuple{SplitCacheOwner, MethodInstance, UInt8}).primary_world, Compiler.typeinf_ext_toplevel, SplitCacheInterp(; world=Base.tls_world_age(), owner), mi, source_mode) |
32 | 37 |
|
33 | | -@eval @noinline function typeinf_edge(::SplitCacheOwner, mi::MethodInstance, parent_frame::Compiler.InferenceState, world::UInt, source_mode::UInt8) |
| 38 | +@eval @noinline function typeinf_edge(owner::SplitCacheOwner, mi::MethodInstance, parent_frame::Compiler.InferenceState, world::UInt, source_mode::UInt8) |
34 | 39 | # TODO: This isn't quite right, we're just sketching things for now |
35 | | - interp = SplitCacheInterp(; world) |
| 40 | + interp = SplitCacheInterp(; world, owner) |
36 | 41 | Compiler.typeinf_edge(interp, mi.def, mi.specTypes, Core.svec(), parent_frame, false, false) |
37 | 42 | end |
38 | 43 |
|
39 | | -function with_new_compiler(f, args...) |
40 | | - mi = @ccall jl_method_lookup(Any[f, args...]::Ptr{Any}, (1+length(args))::Csize_t, Base.tls_world_age()::Csize_t)::Ref{Core.MethodInstance} |
41 | | - world = Base.tls_world_age() |
| 44 | +function lookup_method_instance(f, args...) |
| 45 | + @ccall jl_method_lookup(Any[f, args...]::Ptr{Any}, (1+length(args))::Csize_t, Base.tls_world_age()::Csize_t)::Ref{Core.MethodInstance} |
| 46 | +end |
| 47 | + |
| 48 | +function Compiler.optimize(interp::SplitCacheInterp, opt::Compiler.OptimizationState, caller::Compiler.InferenceResult) |
| 49 | + @invoke Compiler.optimize(interp::Compiler.AbstractInterpreter, opt::Compiler.OptimizationState, caller::Compiler.InferenceResult) |
| 50 | + ir = opt.ir::Compiler.IRCode |
| 51 | + override = GlobalRef(@__MODULE__(), :with_new_compiler) |
| 52 | + for inst in ir.stmts |
| 53 | + stmt = inst[:stmt] |
| 54 | + isexpr(stmt, :call) || continue |
| 55 | + f = stmt.args[1] |
| 56 | + f === override && continue |
| 57 | + if isa(f, GlobalRef) |
| 58 | + T = widenconst(argextype(f, ir)) |
| 59 | + T <: Core.Builtin && continue |
| 60 | + end |
| 61 | + insert!(stmt.args, 1, override) |
| 62 | + insert!(stmt.args, 3, interp.owner) |
| 63 | + end |
| 64 | +end |
| 65 | + |
| 66 | +with_new_compiler(f, args...; owner::SplitCacheOwner = SplitCacheOwner()) = with_new_compiler(f, owner, args...) |
| 67 | + |
| 68 | +function with_new_compiler(f, owner::SplitCacheOwner, args...) |
| 69 | + mi = lookup_method_instance(f, args...) |
42 | 70 | new_compiler_ci = Core.OptimizedGenerics.CompilerPlugins.typeinf( |
43 | | - SplitCacheOwner(), mi, Compiler.SOURCE_MODE_ABI |
| 71 | + owner, mi, Compiler.SOURCE_MODE_ABI |
44 | 72 | ) |
45 | 73 | invoke(f, new_compiler_ci, args...) |
46 | 74 | end |
|
0 commit comments