@@ -2118,90 +2118,97 @@ end
2118
2118
# static parameters are ok if all the static parameter values are leaf types,
2119
2119
# meaning they are fully known.
2120
2120
function inlineable (f:: ANY , e:: Expr , atype:: ANY , sv:: StaticVarInfo , enclosing_ast:: Expr )
2121
- if ! (isa (f,Function) || isa (f,IntrinsicFunction))
2122
- return NF
2123
- end
2124
- atypes = atype. parameters
2125
- argexprs = e. args[2 : end ]
2121
+ local linfo,
2122
+ metharg:: Type ,
2123
+ methsp:: SimpleVector ,
2124
+ atypes = atype. parameters,
2125
+ argexprs = e. args[2 : end ],
2126
+ incompletematch = false ,
2127
+ isgf = false
2128
+ if isa (f, LambdaStaticData)
2129
+ linfo = f
2130
+ metharg = Tuple
2131
+ methsp = svec ()
2132
+ else
2133
+ if ! (isa (f,Function) || isa (f,IntrinsicFunction))
2134
+ return NF
2135
+ end
2126
2136
2127
- if is (f, typeassert) && length (atypes)== 2
2128
- # typeassert(x::S, T) => x, when S<:T
2129
- if isType (atypes[2 ]) && isleaftype (atypes[2 ]) &&
2130
- atypes[1 ] <: atypes [2 ]. parameters[1 ]
2131
- return (e. args[2 ],())
2137
+ if is (f, typeassert) && length (atypes)== 2
2138
+ # typeassert(x::S, T) => x, when S<:T
2139
+ if isType (atypes[2 ]) && isleaftype (atypes[2 ]) &&
2140
+ atypes[1 ] <: atypes [2 ]. parameters[1 ]
2141
+ return (e. args[2 ],())
2142
+ end
2132
2143
end
2133
- end
2134
- if length (atypes)== 2 && is (f,unbox) && isa (atypes[2 ],DataType) && ! atypes[2 ]. mutable && atypes[2 ]. pointerfree
2135
- # remove redundant unbox
2136
- return (e. args[3 ],())
2137
- end
2138
- topmod = _topmod ()
2139
- if istopfunction (topmod, f, :isbits ) && length (atypes)== 1 && isType (atypes[1 ]) &&
2140
- effect_free (argexprs[1 ],sv,true ) && isleaftype (atypes[1 ]. parameters[1 ])
2141
- return (isbits (atypes[1 ]. parameters[1 ]),())
2142
- end
2143
- # special-case inliners for known pure functions that compute types
2144
- if isType (e. typ)
2145
- if (is (f,apply_type) || is (f,fieldtype) ||
2146
- istopfunction (topmod, f, :typejoin ) ||
2147
- istopfunction (topmod, f, :promote_type )) &&
2148
- isleaftype (e. typ. parameters[1 ])
2149
- return (e. typ. parameters[1 ],())
2144
+ if length (atypes)== 2 && is (f,unbox) && isa (atypes[2 ],DataType) && ! atypes[2 ]. mutable && atypes[2 ]. pointerfree
2145
+ # remove redundant unbox
2146
+ return (e. args[3 ],())
2147
+ end
2148
+ topmod = _topmod ()
2149
+ if istopfunction (topmod, f, :isbits ) && length (atypes)== 1 && isType (atypes[1 ]) &&
2150
+ effect_free (argexprs[1 ],sv,true ) && isleaftype (atypes[1 ]. parameters[1 ])
2151
+ return (isbits (atypes[1 ]. parameters[1 ]),())
2152
+ end
2153
+ # special-case inliners for known pure functions that compute types
2154
+ if isType (e. typ)
2155
+ if (is (f,apply_type) || is (f,fieldtype) ||
2156
+ istopfunction (topmod, f, :typejoin ) ||
2157
+ istopfunction (topmod, f, :promote_type )) &&
2158
+ isleaftype (e. typ. parameters[1 ])
2159
+ return (e. typ. parameters[1 ],())
2160
+ end
2161
+ end
2162
+ if isa (f,IntrinsicFunction)
2163
+ return NF
2150
2164
end
2151
- end
2152
- if isa (f,IntrinsicFunction)
2153
- return NF
2154
- end
2155
2165
2156
- meth = _methods (f, atype, 1 )
2157
- if meth === false || length (meth) != 1
2158
- return NF
2159
- end
2160
- meth = meth[1 ]:: SimpleVector
2166
+ local methfunc:: Function
2167
+ if isgeneric (f)
2168
+ isgf = true
2169
+ meth = _methods (f, atype, 1 )
2170
+ if meth === false || length (meth) != 1
2171
+ return NF
2172
+ end
2173
+ meth = meth[1 ]:: SimpleVector
2174
+ linfo = try
2175
+ func_for_method (meth[3 ],atype,meth[2 ])
2176
+ catch
2177
+ NF
2178
+ end
2179
+ if linfo === NF
2180
+ return NF
2181
+ end
2182
+ metharg = meth[1 ]
2183
+ methsp = meth[2 ]
2184
+ methfunc = meth[3 ]. func
2185
+ methsig = meth[3 ]. sig
2186
+ if ! (atype <: metharg )
2187
+ incompletematch = true
2188
+ if ! inline_incompletematch_allowed || ! isdefined (Main,:Base )
2189
+ # provide global disable if this optimization is not desirable
2190
+ # need Main.Base defined for MethodError
2191
+ return NF
2192
+ end
2193
+ end
2194
+ else
2195
+ if ! isdefined (f, :code )
2196
+ return NF
2197
+ end
2198
+ linfo = f. code
2199
+ metharg = Tuple
2200
+ methsp = svec ()
2201
+ methfunc = f
2202
+ end
2161
2203
2162
- local linfo
2163
- linfo = try
2164
- func_for_method (meth[3 ],atype,meth[2 ])
2165
- catch
2166
- NF
2167
- end
2168
- if linfo === NF
2169
- return NF
2204
+ if length (methfunc. env) > 0
2205
+ # can't inline something with an env
2206
+ return NF
2207
+ end
2170
2208
end
2171
2209
linfo = linfo:: LambdaStaticData
2172
2210
2173
- # # This code tries to limit the argument list length only when it is
2174
- # # growing due to recursion.
2175
- # # It might be helpful for some things, but turns out not to be
2176
- # # necessary to get max performance from recursive varargs functions.
2177
- # if length(atypes) > MAX_TUPLETYPE_LEN
2178
- # # check call stack to see if this argument list is growing
2179
- # st = inference_stack
2180
- # while !isa(st, EmptyCallStack)
2181
- # if st.ast === linfo.def.ast && length(atypes) > length(st.types)
2182
- # atypes = limit_tuple_type(atypes)
2183
- # meth = _methods(f, atypes, 1)
2184
- # if meth === false || length(meth) != 1
2185
- # return NF
2186
- # end
2187
- # meth = meth[1]::Tuple
2188
- # linfo2 = meth[3].func.code
2189
- # if linfo2 !== linfo
2190
- # return NF
2191
- # end
2192
- # linfo = linfo2
2193
- # break
2194
- # end
2195
- # st = st.prev
2196
- # end
2197
- # end
2198
-
2199
- if ! isa (linfo,LambdaStaticData) || length (meth[3 ]. func. env) > 0
2200
- return NF
2201
- end
2202
-
2203
- sp = meth[2 ]:: SimpleVector
2204
- sp = svec (sp... , linfo. sparams... )
2211
+ sp = svec (methsp... , linfo. sparams... )
2205
2212
spvals = Any[ sp[i] for i in 2 : 2 : length (sp) ]
2206
2213
for i= 1 : length (spvals)
2207
2214
si = spvals[i]
@@ -2213,21 +2220,10 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
2213
2220
end
2214
2221
end
2215
2222
2216
- metharg = meth[1 ]:: Type
2217
2223
methargs = metharg. parameters
2218
2224
nm = length (methargs)
2219
- if ! (atype <: metharg )
2220
- incompletematch = true
2221
- if ! inline_incompletematch_allowed || ! isdefined (Main,:Base )
2222
- # provide global disable if this optimization is not desirable
2223
- # need Main.Base defined for MethodError
2224
- return NF
2225
- end
2226
- else
2227
- incompletematch = false
2228
- end
2229
2225
2230
- (ast, ty) = typeinf (linfo, metharg, meth[ 2 ] , linfo, true , true )
2226
+ (ast, ty) = typeinf (linfo, metharg, methsp , linfo, true , true )
2231
2227
if is (ast,())
2232
2228
return NF
2233
2229
end
@@ -2255,18 +2251,18 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
2255
2251
if is (f, next) || is (f, done) || is (f, unsafe_convert) || is (f, cconvert)
2256
2252
cost ÷= 4
2257
2253
end
2258
- inline_op = (f=== (+ ) || f=== (* ) || f=== min || f=== max) && (3 <= length (argexprs) <= 9 ) &&
2259
- meth[ 3 ] . sig == Tuple{Any,Any,Any,Vararg{Any}}
2254
+ inline_op = isgeneric (f) && (f=== (+ ) || f=== (* ) || f=== min || f=== max) && (3 <= length (argexprs) <= 9 ) &&
2255
+ methsig == Tuple{Any,Any,Any,Vararg{Any}}
2260
2256
if ! inline_op && ! inline_worthy (body, cost)
2261
2257
if incompletematch
2262
2258
# inline a typeassert-based call-site, rather than a
2263
2259
# full generic lookup, using the inliner to handle
2264
2260
# all the fiddly details
2265
2261
numarg = length (argexprs)
2266
2262
newnames = unique_names (ast,numarg)
2267
- sp = ()
2263
+ methsp = sp
2264
+ sp = svec ()
2268
2265
spvals = []
2269
- meth = svec (metharg, sp)
2270
2266
locals = []
2271
2267
newcall = Expr (:call , e. args[1 ])
2272
2268
newcall. typ = ty
@@ -2297,7 +2293,10 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
2297
2293
na = length (args)
2298
2294
2299
2295
isva = false
2300
- if na> 0 && is_rest_arg (ast. args[1 ][na])
2296
+ if na > 0 && is_rest_arg (ast. args[1 ][na])
2297
+ if length (argexprs) < na - 1
2298
+ return (Expr (:call , TopNode (:error ), " too few arguments" ), [])
2299
+ end
2301
2300
vaname = args[na]
2302
2301
len_argexprs = length (argexprs)
2303
2302
valen = len_argexprs- na+ 1
@@ -2334,12 +2333,15 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
2334
2333
isva = true
2335
2334
end
2336
2335
elseif na != length (argexprs)
2337
- # we have a method match only because an earlier
2338
- # inference step shortened our call args list, even
2339
- # though we have too many arguments to actually
2340
- # call this function
2341
- @assert isvarargtype (atypes[na])
2342
- return NF
2336
+ if isgf
2337
+ # we have a method match only because an earlier
2338
+ # inference step shortened our call args list, even
2339
+ # though we have too many arguments to actually
2340
+ # call this function
2341
+ @assert isvarargtype (atypes[na])
2342
+ return NF
2343
+ end
2344
+ return (Expr (:call , TopNode (:error ), " wrong number of arguments" ), [])
2343
2345
end
2344
2346
2345
2347
@assert na == length (argexprs)
@@ -2558,7 +2560,7 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
2558
2560
lastexpr = pop! (body. args)
2559
2561
if isa (lastexpr,LabelNode)
2560
2562
push! (body. args, lastexpr)
2561
- push! (body. args, Expr (:call ,:error , " fatal error in type inference" ))
2563
+ push! (body. args, Expr (:call , TopNode ( :error ), " fatal error in type inference" ))
2562
2564
lastexpr = nothing
2563
2565
else
2564
2566
@assert isa (lastexpr,Expr) " inference.jl:1774"
@@ -2745,18 +2747,25 @@ function inlining_pass(e::Expr, sv, ast)
2745
2747
end
2746
2748
end
2747
2749
end
2748
- f1 = f = isconstantfunc (arg1, sv)
2749
- if ! is (f,false )
2750
- f = _ieval (f)
2751
- end
2752
- if (! isa (f,Function) && ! isa (f,IntrinsicFunction) &&
2753
- (f1 != = false || typeintersect (exprtype (arg1,sv), Function) === Bottom))
2754
- modu = (inference_stack:: CallStack ). mod
2755
- if ! _iisdefined (:call )
2756
- return (e,stmts)
2750
+
2751
+ if isa (e. args[1 ], LambdaStaticData)
2752
+ f = e. args[1 ]
2753
+ else
2754
+ f1 = f = isconstantfunc (arg1, sv)
2755
+ if ! is (f,false )
2756
+ f = _ieval (f)
2757
+ end
2758
+ if (! isa (f,Function) && ! isa (f,IntrinsicFunction) &&
2759
+ (f1 != = false || typeintersect (exprtype (arg1,sv), Function) === Bottom))
2760
+ modu = (inference_stack:: CallStack ). mod
2761
+ if ! _iisdefined (:call )
2762
+ return (e,stmts)
2763
+ end
2764
+ f = _ieval (:call )
2765
+ e. args = Any[is_global (sv,:call ) ? (:call ) : GlobalRef (modu, :call ), e. args... ]
2766
+ elseif f1 === false
2767
+ return (e, stmts)
2757
2768
end
2758
- f = _ieval (:call )
2759
- e. args = Any[is_global (sv,:call ) ? (:call ) : GlobalRef (modu, :call ), e. args... ]
2760
2769
end
2761
2770
2762
2771
if isdefined (Main, :Base ) &&
0 commit comments