@@ -38,7 +38,7 @@ struct SomeCase
3838end
3939
4040struct InvokeCase
41- invoke:: MethodInstance
41+ invoke:: Union{CodeInstance, MethodInstance}
4242 effects:: Effects
4343 info:: CallInfo
4444end
@@ -764,19 +764,20 @@ function rewrite_apply_exprargs!(todo::Vector{Pair{Int,Any}},
764764 return new_argtypes
765765end
766766
767- function compileable_specialization (mi :: MethodInstance , effects:: Effects ,
767+ function compileable_specialization (code :: Union{ MethodInstance,CodeInstance} , effects:: Effects ,
768768 et:: InliningEdgeTracker , @nospecialize (info:: CallInfo ), state:: InliningState )
769+ mi = code isa CodeInstance ? code. def : code
769770 mi_invoke = mi
770771 method, atype, sparams = mi. def:: Method , mi. specTypes, mi. sparam_vals
771772 if OptimizationParams (state. interp). compilesig_invokes
772773 new_atype = get_compileable_sig (method, atype, sparams)
773774 new_atype === nothing && return nothing
774775 if atype != = new_atype
775776 sp_ = ccall (:jl_type_intersection_with_env , Any, (Any, Any), new_atype, method. sig):: SimpleVector
776- if sparams == = sp_[2 ]:: SimpleVector
777- mi_invoke = specialize_method (method, new_atype, sparams)
778- mi_invoke === nothing && return nothing
779- end
777+ sparams = sp_[2 ]:: SimpleVector
778+ mi_invoke = specialize_method (method, new_atype, sparams)
779+ mi_invoke === nothing && return nothing
780+ code = mi_invoke
780781 end
781782 else
782783 # If this caller does not want us to optimize calls to use their
@@ -786,8 +787,15 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
786787 return nothing
787788 end
788789 end
789- add_inlining_edge! (et, mi_invoke) # to the dispatch lookup
790- return InvokeCase (mi_invoke, effects, info)
790+ # prefer using a CodeInstance gotten from the cache, since that is where the invoke target should get compiled to normally
791+ # TODO : can this code be gotten directly from inference sometimes?
792+ code = get (code_cache (state), mi_invoke, nothing )
793+ if ! isa (code, CodeInstance)
794+ # println("missing code for ", mi_invoke, " for ", mi)
795+ code = mi_invoke
796+ end
797+ add_inlining_edge! (et, code) # to the code and edges
798+ return InvokeCase (code, effects, info)
791799end
792800
793801struct InferredResult
@@ -844,18 +852,18 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult,
844852 src = @atomic :monotonic inferred_result. inferred
845853 effects = decode_effects (inferred_result. ipo_purity_bits)
846854 edge = inferred_result
847- else # there is no cached source available, bail out
855+ else # there is no cached source available for this, but there might be code for the compilation sig
848856 return compileable_specialization (mi, Effects (), et, info, state)
849857 end
850858
851859 # the duplicated check might have been done already within `analyze_method!`, but still
852860 # we need it here too since we may come here directly using a constant-prop' result
853861 if ! OptimizationParams (state. interp). inlining || is_stmt_noinline (flag)
854- return compileable_specialization (edge. def , effects, et, info, state)
862+ return compileable_specialization (edge, effects, et, info, state)
855863 end
856864
857865 src_inlining_policy (state. interp, src, info, flag) ||
858- return compileable_specialization (edge. def , effects, et, info, state)
866+ return compileable_specialization (edge, effects, et, info, state)
859867
860868 add_inlining_edge! (et, edge)
861869 if inferred_result isa CodeInstance
@@ -1423,18 +1431,19 @@ end
14231431
14241432function semiconcrete_result_item (result:: SemiConcreteResult ,
14251433 @nospecialize (info:: CallInfo ), flag:: UInt32 , state:: InliningState )
1426- mi = result. edge. def
1434+ code = result. edge
1435+ mi = code. def
14271436 et = InliningEdgeTracker (state)
14281437
14291438 if (! OptimizationParams (state. interp). inlining || is_stmt_noinline (flag) ||
14301439 # For `NativeInterpreter`, `SemiConcreteResult` may be produced for
14311440 # a `@noinline`-declared method when it's marked as `@constprop :aggressive`.
14321441 # Suppress the inlining here (unless inlining is requested at the callsite).
14331442 (is_declared_noinline (mi. def:: Method ) && ! is_stmt_inline (flag)))
1434- return compileable_specialization (mi , result. effects, et, info, state)
1443+ return compileable_specialization (code , result. effects, et, info, state)
14351444 end
14361445 src_inlining_policy (state. interp, result. ir, info, flag) ||
1437- return compileable_specialization (mi , result. effects, et, info, state)
1446+ return compileable_specialization (code , result. effects, et, info, state)
14381447
14391448 add_inlining_edge! (et, result. edge)
14401449 preserve_local_sources = OptimizationParams (state. interp). preserve_local_sources
@@ -1466,7 +1475,7 @@ may_inline_concrete_result(result::ConcreteResult) =
14661475function concrete_result_item (result:: ConcreteResult , @nospecialize (info:: CallInfo ), state:: InliningState )
14671476 if ! may_inline_concrete_result (result)
14681477 et = InliningEdgeTracker (state)
1469- return compileable_specialization (result. edge. def , result. effects, et, info, state)
1478+ return compileable_specialization (result. edge, result. effects, et, info, state)
14701479 end
14711480 @assert result. effects === EFFECTS_TOTAL
14721481 return ConstantCase (quoted (result. result), result. edge)
@@ -1522,11 +1531,7 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp
15221531 match = info. results[1 ]:: MethodMatch
15231532 match. fully_covers || return nothing
15241533 edge = info. edges[1 ]
1525- if edge === nothing
1526- edge = specialize_method (match)
1527- else
1528- edge = edge. def
1529- end
1534+ edge === nothing && return nothing
15301535 case = compileable_specialization (edge, Effects (), InliningEdgeTracker (state), info, state)
15311536 case === nothing && return nothing
15321537 stmt. head = :invoke_modify
@@ -1564,8 +1569,11 @@ function handle_finalizer_call!(ir::IRCode, idx::Int, stmt::Expr, info::Finalize
15641569 # `Core.Compiler` data structure into the global cache
15651570 item1 = cases[1 ]. item
15661571 if isa (item1, InliningTodo)
1567- push! (stmt. args, true )
1568- push! (stmt. args, item1. mi)
1572+ code = get (code_cache (state), item1. mi, nothing ) # COMBAK: this seems like a bad design, can we use stmt_info instead to store the correct info?
1573+ if code isa CodeInstance
1574+ push! (stmt. args, true )
1575+ push! (stmt. args, code)
1576+ end
15691577 elseif isa (item1, InvokeCase)
15701578 push! (stmt. args, false )
15711579 push! (stmt. args, item1. invoke)
@@ -1578,7 +1586,10 @@ end
15781586
15791587function handle_invoke_expr! (todo:: Vector{Pair{Int,Any}} , ir:: IRCode ,
15801588 idx:: Int , stmt:: Expr , @nospecialize (info:: CallInfo ), flag:: UInt32 , sig:: Signature , state:: InliningState )
1581- mi = stmt. args[1 ]:: MethodInstance
1589+ mi = stmt. args[1 ]
1590+ if ! (mi isa MethodInstance)
1591+ mi = (mi:: CodeInstance ). def
1592+ end
15821593 case = resolve_todo (mi, info, flag, state)
15831594 handle_single_case! (todo, ir, idx, stmt, case, false )
15841595 return nothing
0 commit comments