diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 0519f0012ec6c9..5ddce03f5dadf6 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -905,10 +905,12 @@ function resolve_todo(mi::MethodInstance, result::Union{MethodMatch,InferenceRes if src isa String && inferred_result !== nothing # if the inferred source for this globally-cached method is available, # use it destructively as it will never be used again - ir = inflate_ir!(inferred_result.inferred_src, mi) + src = inferred_result.inferred_src + preserve_local_sources = OptimizationParams(state.interp).preserve_local_sources else - ir = retrieve_ir_for_inlining(mi, src) + preserve_local_sources = true end + ir = retrieve_ir_for_inlining(mi, src, preserve_local_sources) return InliningTodo(mi, ir, effects) end @@ -987,12 +989,22 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, return resolve_todo(mi, match, argtypes, info, flag, state; invokesig, inferred_result) end -function retrieve_ir_for_inlining(mi::MethodInstance, src::String) +function retrieve_ir_for_inlining(mi::MethodInstance, src::String, ::Bool=true) src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src)::CodeInfo return inflate_ir!(src, mi) end -retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo) = inflate_ir(src, mi) -retrieve_ir_for_inlining(mi::MethodInstance, ir::IRCode) = copy(ir) +function retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo, preserve_local_sources::Bool=true) + if preserve_local_sources + src = copy(src) + end + return inflate_ir!(src, mi) +end +function retrieve_ir_for_inlining(::MethodInstance, ir::IRCode, preserve_local_sources::Bool=true) + if preserve_local_sources + ir = copy(ir) + end + return ir +end function flags_for_effects(effects::Effects) flags::UInt32 = 0 @@ -1524,7 +1536,9 @@ function semiconcrete_result_item(result::SemiConcreteResult, return compileable_specialization(mi, result.effects, et, info; compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes) else - return InliningTodo(mi, retrieve_ir_for_inlining(mi, result.ir), result.effects) + preserve_local_sources = OptimizationParams(state.interp).preserve_local_sources + ir = retrieve_ir_for_inlining(mi, result.ir, preserve_local_sources) + return InliningTodo(mi, ir, result.effects) end end diff --git a/base/compiler/types.jl b/base/compiler/types.jl index c53256c61ace94..ba05131d4e3a3a 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -253,6 +253,11 @@ Parameters that control optimizer operation. optimizer license to move side effects (that are proven not observed within a particular code path) across a throwing call. Defaults to `false`. --- +- `opt_params.preserve_local_sources::Bool = false`\\ + If `true`, the inliner is restricted from modifying locally-cached sources that are + retained in `CallInfo` objects and always makes their copies before inlining them into + caller context. Defaults to `false`. +--- """ struct OptimizationParams inlining::Bool @@ -263,6 +268,7 @@ struct OptimizationParams max_tuple_splat::Int compilesig_invokes::Bool assume_fatal_throw::Bool + preserve_local_sources::Bool function OptimizationParams( inlining::Bool, @@ -272,7 +278,8 @@ struct OptimizationParams inline_error_path_cost::Int, max_tuple_splat::Int, compilesig_invokes::Bool, - assume_fatal_throw::Bool) + assume_fatal_throw::Bool, + preserve_local_sources::Bool) return new( inlining, inline_cost_threshold, @@ -281,7 +288,8 @@ struct OptimizationParams inline_error_path_cost, max_tuple_splat, compilesig_invokes, - assume_fatal_throw) + assume_fatal_throw, + preserve_local_sources) end end function OptimizationParams( @@ -293,7 +301,8 @@ function OptimizationParams( #=inline_error_path_cost::Int=# 20, #=max_tuple_splat::Int=# 32, #=compilesig_invokes::Bool=# true, - #=assume_fatal_throw::Bool=# false); + #=assume_fatal_throw::Bool=# false, + #=preserve_local_sources::Bool=# false); inlining::Bool = params.inlining, inline_cost_threshold::Int = params.inline_cost_threshold, inline_nonleaf_penalty::Int = params.inline_nonleaf_penalty, @@ -301,7 +310,8 @@ function OptimizationParams( inline_error_path_cost::Int = params.inline_error_path_cost, max_tuple_splat::Int = params.max_tuple_splat, compilesig_invokes::Bool = params.compilesig_invokes, - assume_fatal_throw::Bool = params.assume_fatal_throw) + assume_fatal_throw::Bool = params.assume_fatal_throw, + preserve_local_sources::Bool = params.preserve_local_sources) return OptimizationParams( inlining, inline_cost_threshold, @@ -310,7 +320,8 @@ function OptimizationParams( inline_error_path_cost, max_tuple_splat, compilesig_invokes, - assume_fatal_throw) + assume_fatal_throw, + preserve_local_sources) end """