@@ -45,14 +45,168 @@ macro LineInfoNode(method)
4545end
4646
4747
48+ function rewrite_inst (inst)
49+ @show inst
50+ if Meta. isexpr (inst, :call )
51+ rep = Expr (:call , call_with_reactant, inst. args... )
52+ @show rep
53+ return rep
54+ end
55+ if Meta. isexpr (inst, :invoke )
56+ return Expr (:call , inst. args[2 : end ]. .. )
57+ end
58+ return inst
59+ end
60+
4861const REDUB_ARGUMENTS_NAME = gensym (" redub_arguments" )
4962
50- function call_with_reactant_generator (world:: UInt , source:: LineNumberNode , self, @nospecialize (args))
63+ function arg_partially_inline! (code:: Vector{Any} , slot_replacements:: Vector{Any} ,
64+ @nospecialize (type_signature)#= ::Type{<:Tuple}=# ,
65+ static_param_values:: Vector{Any} ,
66+ slot_offset:: Int , arg_offset:: Int , statement_offset:: Int ,
67+ boundscheck:: Symbol )
68+ for i = 1 : length (code)
69+ isassigned (code, i) || continue
70+ code[i] = _arg_partially_inline! (code[i], slot_replacements, type_signature,
71+ static_param_values, slot_offset, arg_offset,
72+ statement_offset, boundscheck)
73+ end
74+ return code
75+ end
76+
77+ function _arg_partially_inline! (@nospecialize (x), slot_replacements:: Vector{Any} ,
78+ @nospecialize (type_signature), static_param_values:: Vector{Any} ,
79+ slot_offset:: Int , arg_offset:: Int , statement_offset:: Int ,
80+ boundscheck:: Symbol )
81+ if isa (x, Core. SSAValue)
82+ return Core. SSAValue (x. id + statement_offset)
83+ end
84+ if isa (x, Core. GotoNode)
85+ return Core. GotoNode (x. label + statement_offset)
86+ end
87+ if isa (x, Core. SlotNumber)
88+ id = x. id
89+ if 1 <= id <= length (slot_replacements)
90+ return slot_replacements[id]
91+ end
92+ return Core. SlotNumber (id + slot_offset)
93+ end
94+ if isa (x, Core. Argument)
95+ return Core. SlotNumber (x. n + arg_offset)
96+ end
97+ if isa (x, Core. NewvarNode)
98+ return Core. NewvarNode (_arg_partially_inline! (x. slot, slot_replacements, type_signature,
99+ static_param_values, slot_offset, arg_offset,
100+ statement_offset, boundscheck))
101+ end
102+ if isa (x, Core. PhiNode)
103+ arg_partially_inline! (x. values, slot_replacements, type_signature, static_param_values,
104+ slot_offset, arg_offset, statement_offset, boundscheck)
105+ x. edges .+ = slot_offset
106+ return x
107+ end
108+ if isa (x, Core. ReturnNode)
109+ return Core. ReturnNode (
110+ _arg_partially_inline! (x. val, slot_replacements, type_signature, static_param_values,
111+ slot_offset, arg_offset, statement_offset, boundscheck),
112+ )
113+ end
114+ if isa (x, Core. GotoIfNot)
115+ return Core. GotoIfNot (
116+ _arg_partially_inline! (x. cond, slot_replacements, type_signature, static_param_values,
117+ slot_offset, arg_offset, statement_offset, boundscheck),
118+ x. dest + statement_offset,
119+ )
120+ end
121+ if isdefined (Core, :EnterNode ) && isa (x, Core. EnterNode)
122+ return Core. EnterNode (x, x. catch_dest + statement_offset)
123+ end
124+ if isa (x, Expr)
125+ head = x. head
126+ if head === :static_parameter
127+ if isassigned (static_param_values, x. args[1 ])
128+ return QuoteNode (static_param_values[x. args[1 ]])
129+ end
130+ return x
131+ elseif head === :cfunction
132+ @assert ! isa (type_signature, UnionAll) || ! isempty (spvals)
133+ if ! isa (x. args[2 ], QuoteNode) # very common no-op
134+ x. args[2 ] = Core. Compiler. _partially_inline! (x. args[2 ], slot_replacements, type_signature,
135+ static_param_values, slot_offset, arg_offset,
136+ statement_offset, boundscheck)
137+ end
138+ x. args[3 ] = Core. Compiler. _instantiate_type_in_env (x. args[3 ], type_signature, static_param_values)
139+ x. args[4 ] = Core. svec (Any[Core. Compiler. _instantiate_type_in_env (argt, type_signature, static_param_values) for argt in x. args[4 ]]. .. )
140+ elseif head === :foreigncall
141+ @assert ! isa (type_signature, UnionAll) || ! isempty (static_param_values)
142+ for i = 1 : length (x. args)
143+ if i == 2
144+ x. args[2 ] = Core. Compiler. _instantiate_type_in_env (x. args[2 ], type_signature, static_param_values)
145+ elseif i == 3
146+ x. args[3 ] = Core. svec (Any[Core. Compiler. _instantiate_type_in_env (argt, type_signature, static_param_values) for argt in x. args[3 ]]. .. )
147+ elseif i == 4
148+ @assert isa (x. args[4 ], Int)
149+ elseif i == 5
150+ @assert isa ((x. args[5 ]:: QuoteNode ). value, Union{Symbol, Tuple{Symbol, UInt8}})
151+ else
152+ x. args[i] = _arg_partially_inline! (x. args[i], slot_replacements,
153+ type_signature, static_param_values,
154+ slot_offset, statement_offset, arg_offset,
155+ boundscheck)
156+ end
157+ end
158+ elseif head === :boundscheck
159+ if boundscheck === :propagate
160+ return x
161+ elseif boundscheck === :off
162+ return false
163+ else
164+ return true
165+ end
166+ elseif head === :gotoifnot
167+ x. args[1 ] = _arg_partially_inline! (x. args[1 ], slot_replacements, type_signature,
168+ static_param_values, slot_offset, arg_offset,
169+ statement_offset, boundscheck)
170+ x. args[2 ] += statement_offset
171+ elseif head === :isdefined
172+ arg = x. args[1 ]
173+ # inlining a QuoteNode or literal into `Expr(:isdefined, x)` is invalid, replace with true
174+ if isa (arg, Core. SlotNumber)
175+ id = arg. id
176+ if 1 <= id <= length (slot_replacements)
177+ replacement = slot_replacements[id]
178+ if isa (replacement, Union{Core. SlotNumber, GlobalRef, Symbol})
179+ return Expr (:isdefined , replacement)
180+ else
181+ @assert ! isa (replacement, Expr)
182+ return true
183+ end
184+ end
185+ return Expr (:isdefined , Core. SlotNumber (id + slot_offset))
186+ elseif isexpr (arg, :static_parameter )
187+ if isassigned (static_param_values, arg. args[1 ])
188+ return true
189+ end
190+ return x
191+ else
192+ @assert isa (arg, Union{GlobalRef, Symbol})
193+ return x
194+ end
195+ elseif ! Core. Compiler. is_meta_expr_head (head)
196+ arg_partially_inline! (x. args, slot_replacements, type_signature, static_param_values,
197+ slot_offset, arg_offset, statement_offset, boundscheck)
198+ end
199+ end
200+ return x
201+ end
202+
203+ function call_with_reactant_generator (world:: UInt , source:: LineNumberNode , self, @nospecialize (redub_arguments))
51204 @nospecialize
52205
206+ args = redub_arguments
53207 @show args
54208
55- stub = Core. GeneratedFunctionStub (identity, Core. svec (:call_with_reactant , REDUB_ARGUMENTS_NAME ), Core. svec ())
209+ stub = Core. GeneratedFunctionStub (identity, Core. svec (:call_with_reactant , :redub_arguments ), Core. svec ())
56210
57211 # look up the method match
58212 builtin_error = :(throw (AssertionError (" Unsupported call_with_reactant of builtin $args " )))
@@ -85,7 +239,40 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
85239 (Any, Any, Any), match. method, match. spec_types, match. sparams)
86240
87241 result = Core. Compiler. InferenceResult (mi, Core. Compiler. typeinf_lattice (interp))
88- src = Core. Compiler. retrieve_code_info (mi, world)
242+ @static if true
243+ frame = Core. Compiler. InferenceState (result, #= cache_mode=# :local , interp)
244+ @assert frame != = nothing
245+ Core. Compiler. typeinf (interp, frame)
246+ @assert Core. Compiler. is_inferred (frame)
247+
248+ # if Core.Compiler.result_is_constabi(interp, frame.result)
249+ # rt = frame.result.result::Core.Compiler.Const
250+ # src = Core.Compiler.codeinfo_for_const(interp, frame.linfo, rt.val)
251+ # else
252+ opt = Core. Compiler. OptimizationState (frame, interp)
253+
254+ caller = frame. result
255+ @static if VERSION < v " 1.11-"
256+ ir = Core. Compiler. run_passes (opt. src, opt, caller)
257+ else
258+ ir = Core. Compiler. run_passes_ipo_safe (opt. src, opt, caller)
259+ Core. Compiler. ipo_dataflow_analysis! (interp, opt, ir, caller)
260+ end
261+
262+ for (i, inst) in enumerate (ir. stmts)
263+ @static if VERSION < v " 1.11"
264+ Core. Compiler. setindex! (ir. stmts[i], rewrite_inst (inst[:inst ]), :inst )
265+ else
266+ Core. Compiler. setindex! (ir. stmts[i], rewrite_inst (inst[:stmt ]), :stmt )
267+ end
268+ end
269+ Core. Compiler. finish (interp, opt, ir, caller)
270+
271+ src = Core. Compiler. ir_to_codeinf! (opt)
272+ # end
273+ else
274+ src = Core. Compiler. retrieve_code_info (mi, world)
275+ end
89276
90277 # prepare a new code info
91278 code_info = copy (src)
@@ -99,7 +286,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
99286 code_info. min_world = lookup_result. valid_worlds. min_world
100287 code_info. max_world = lookup_result. valid_worlds. max_world
101288
102- code_info. slotnames = Any[:call_with_reactant , REDUB_ARGUMENTS_NAME , code_info. slotnames... ]
289+ code_info. slotnames = Any[:call_with_reactant , :redub_arguments , code_info. slotnames... ]
103290 code_info. slotflags = UInt8[0x00 , 0x00 , code_info. slotflags... ]
104291 # code_info.slotnames = Any[:call_with_reactant, REDUB_ARGUMENTS_NAME] #code_info.slotnames...]
105292 # code_info.slotflags = UInt8[0x00, 0x00] # code_info.slotflags...]
@@ -163,8 +350,13 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
163350 @show code_info. code
164351
165352 @show n_prepended_slots
353+ @static if false
166354 Base. Meta. partially_inline! (code_info. code, fn_args, method. sig, Any[static_params... ],
167355 n_prepended_slots, length (overdubbed_code), :propagate )
356+ else
357+ arg_partially_inline! (code_info. code, fn_args, method. sig, Any[static_params... ],
358+ n_prepended_slots, n_prepended_slots, length (overdubbed_code), :propagate )
359+ end
168360 @show code_info. code
169361
170362 # callexpr = Expr(:call, Core.OpaqueClosure(ir), fn_args...)
@@ -181,6 +373,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
181373
182374 @show overdubbed_code
183375
376+ @static if false
184377 for i in eachindex (overdubbed_code)
185378 prev = overdubbed_code[i]
186379 if Base. Meta. isexpr (prev, :call )
@@ -193,6 +386,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
193386 end
194387 end
195388 end
389+ end
196390
197391 #= == set `code_info`/`reflection` fields accordingly ===#
198392
@@ -204,9 +398,12 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
204398 code_info. codelocs = overdubbed_codelocs
205399 code_info. ssavaluetypes = length (overdubbed_code)
206400 code_info. ssaflags = [0x00 for _ in 1 : length (overdubbed_code)] # XXX we need to copy flags that are set for the original code
207- self_result = Core. Compiler. InferenceResult (self_mi, Core. Compiler. typeinf_lattice (interp))
208401
209402 @show code_info
403+ return code_info
404+
405+ self_result = Core. Compiler. InferenceResult (self_mi, Core. Compiler. typeinf_lattice (interp))
406+
210407
211408 @show self
212409 self_meths = Base. _methods_by_ftype (Tuple{self, Vararg{Any}}, - 1 , world)
@@ -241,6 +438,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
241438 else
242439 ir = Core. Compiler. run_passes_ipo_safe (ir, opt, caller)
243440 Core. Compiler. ipo_dataflow_analysis! (interp, opt, ir, caller)
441+
244442 end
245443 Core. Compiler. finish (interp, opt, ir, caller)
246444
@@ -255,7 +453,7 @@ function call_with_reactant_generator(world::UInt, source::LineNumberNode, self,
255453 return src
256454end
257455
258- @eval function call_with_reactant ($ REDUB_ARGUMENTS_NAME ... )
456+ @eval function call_with_reactant (redub_arguments ... )
259457 $ (Expr (:meta , :generated_only ))
260458 $ (Expr (:meta , :generated , call_with_reactant_generator))
261459end
0 commit comments