@@ -15,6 +15,7 @@ struct InferenceParams
15
15
inlining:: Bool
16
16
17
17
# parameters limiting potentially-infinite types (configurable)
18
+ MAX_METHODS:: Int
18
19
MAX_TUPLETYPE_LEN:: Int
19
20
MAX_TUPLE_DEPTH:: Int
20
21
MAX_TUPLE_SPLAT:: Int
@@ -24,12 +25,13 @@ struct InferenceParams
24
25
# reasonable defaults
25
26
function InferenceParams (world:: UInt ;
26
27
inlining:: Bool = inlining_enabled (),
28
+ max_methods:: Int = 4 ,
27
29
tupletype_len:: Int = 15 ,
28
30
tuple_depth:: Int = 4 ,
29
31
tuple_splat:: Int = 16 ,
30
32
union_splitting:: Int = 4 ,
31
33
apply_union_enum:: Int = 8 )
32
- return new (world, inlining, tupletype_len,
34
+ return new (world, inlining, max_methods, tupletype_len,
33
35
tuple_depth, tuple_splat, union_splitting, apply_union_enum)
34
36
end
35
37
end
@@ -1280,7 +1282,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState)
1280
1282
end
1281
1283
min_valid = UInt[typemin (UInt)]
1282
1284
max_valid = UInt[typemax (UInt)]
1283
- applicable = _methods_by_ftype (argtype, 4 , sv. params. world, min_valid, max_valid)
1285
+ applicable = _methods_by_ftype (argtype, sv . params . MAX_METHODS , sv. params. world, min_valid, max_valid)
1284
1286
rettype = Bottom
1285
1287
if applicable === false
1286
1288
# this means too many methods matched
@@ -1431,7 +1433,7 @@ function precise_container_type(arg::ANY, typ::ANY, vtypes::VarTable, sv::Infere
1431
1433
if isa (typ, Const)
1432
1434
val = typ. val
1433
1435
if isa (val, SimpleVector) || isa (val, Tuple)
1434
- return Any[ abstract_eval_constant (x ) for x in val ]
1436
+ return Any[ Const (val[i] ) for i in 1 : length ( val) ] # avoid making a tuple Generator here!
1435
1437
end
1436
1438
end
1437
1439
@@ -1499,44 +1501,64 @@ function abstract_iteration(itertype::ANY, vtypes::VarTable, sv::InferenceState)
1499
1501
return Vararg{valtype}
1500
1502
end
1501
1503
1504
+ function tuple_tail_elem (init:: ANY , ct)
1505
+ return Vararg{widenconst (foldl ((a, b) -> tmerge (a, unwrapva (b)), init, ct))}
1506
+ end
1507
+
1502
1508
# do apply(af, fargs...), where af is a function value
1503
- function abstract_apply (af:: ANY , fargs:: Vector{Any} , aargtypes:: Vector{Any} , vtypes:: VarTable , sv:: InferenceState )
1509
+ function abstract_apply (aft:: ANY , fargs:: Vector{Any} , aargtypes:: Vector{Any} , vtypes:: VarTable , sv:: InferenceState )
1510
+ if ! isa (aft, Const) && ! isconstType (aft)
1511
+ if ! (isleaftype (aft) || aft <: Type ) || (aft <: Builtin ) || (aft <: IntrinsicFunction )
1512
+ return Any
1513
+ end
1514
+ # non-constant function, but type is known
1515
+ end
1504
1516
res = Union{}
1505
1517
nargs = length (fargs)
1506
1518
assert (nargs == length (aargtypes))
1507
- splitunions = countunionsplit (aargtypes) <= sv. params. MAX_APPLY_UNION_ENUM
1508
- ctypes = Any[Any[]]
1519
+ splitunions = 1 < countunionsplit (aargtypes) <= sv. params. MAX_APPLY_UNION_ENUM
1520
+ ctypes = Any[Any[aft ]]
1509
1521
for i = 1 : nargs
1510
1522
if aargtypes[i] === Any
1511
1523
# bail out completely and infer as f(::Any...)
1512
- # instead could keep what we got so far and just append a Vararg{Any} (by just
1513
- # using the normal logic from below), but that makes the time of the subarray
1514
- # test explode
1515
- ctypes = Any[Any[Vararg{Any}]]
1524
+ # instead could infer the precise types for the types up to this point and just append a Vararg{Any}
1525
+ # (by just using the normal logic from below), but that makes the time of the subarray test explode
1526
+ push! (ctypes[1 ], Vararg{Any})
1516
1527
break
1517
1528
end
1518
- ctypes´ = []
1519
- for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
1520
- cti = precise_container_type (fargs[i], ti, vtypes, sv)
1521
- for ct in ctypes
1522
- if ! isempty (ct) && isvarargtype (ct[end ])
1523
- tail = foldl ((a,b)-> tmerge (a,unwrapva (b)), unwrapva (ct[end ]), cti)
1524
- push! (ctypes´, push! (ct[1 : end - 1 ], Vararg{widenconst (tail)}))
1525
- else
1526
- push! (ctypes´, append_any (ct, cti))
1529
+ end
1530
+ if length (ctypes[1 ]) == 1
1531
+ for i = 1 : nargs
1532
+ ctypes´ = []
1533
+ for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
1534
+ cti = precise_container_type (fargs[i], ti, vtypes, sv)
1535
+ for ct in ctypes
1536
+ if ! isempty (ct) && isvarargtype (ct[end ])
1537
+ tail = tuple_tail_elem (unwrapva (ct[end ]), cti)
1538
+ push! (ctypes´, push! (ct[1 : (end - 1 )], tail))
1539
+ else
1540
+ push! (ctypes´, append_any (ct, cti))
1541
+ end
1527
1542
end
1528
1543
end
1544
+ ctypes = ctypes´
1529
1545
end
1530
- ctypes = ctypes´
1531
1546
end
1532
1547
for ct in ctypes
1533
1548
if length (ct) > sv. params. MAX_TUPLETYPE_LEN
1534
- tail = foldl ((a,b) -> tmerge (a, unwrapva (b)), Bottom, ct[sv. params. MAX_TUPLETYPE_LEN: end ])
1549
+ tail = tuple_tail_elem ( Bottom, ct[sv. params. MAX_TUPLETYPE_LEN: end ])
1535
1550
resize! (ct, sv. params. MAX_TUPLETYPE_LEN)
1536
- ct[end ] = Vararg{widenconst (tail)}
1551
+ ct[end ] = tail
1552
+ end
1553
+ if isa (aft, Const)
1554
+ rt = abstract_call (aft. val, (), ct, vtypes, sv)
1555
+ elseif isconstType (aft)
1556
+ rt = abstract_call (aft. parameters[1 ], (), ct, vtypes, sv)
1557
+ else
1558
+ astype = argtypes_to_type (ct)
1559
+ rt = abstract_call_gf_by_type (nothing , astype, sv)
1537
1560
end
1538
- at = append_any (Any[Const (af)], ct)
1539
- res = tmerge (res, abstract_call (af, (), at, vtypes, sv))
1561
+ res = tmerge (res, rt)
1540
1562
if res === Any
1541
1563
break
1542
1564
end
@@ -1651,20 +1673,7 @@ typename_static(t::ANY) = isType(t) ? _typename(t.parameters[1]) : Any
1651
1673
function abstract_call (f:: ANY , fargs:: Union{Tuple{},Vector{Any}} , argtypes:: Vector{Any} , vtypes:: VarTable , sv:: InferenceState )
1652
1674
if f === _apply
1653
1675
length (fargs) > 1 || return Any
1654
- aft = argtypes[2 ]
1655
- if isa (aft, Const)
1656
- af = aft. val
1657
- else
1658
- if isType (aft) && isleaftype (aft. parameters[1 ])
1659
- af = aft. parameters[1 ]
1660
- elseif isleaftype (aft) && isdefined (aft, :instance )
1661
- af = aft. instance
1662
- else
1663
- # TODO jb/functions: take advantage of case where non-constant `af`'s type is known
1664
- return Any
1665
- end
1666
- end
1667
- return abstract_apply (af, fargs[3 : end ], argtypes[3 : end ], vtypes, sv)
1676
+ return abstract_apply (argtypes[2 ], fargs[3 : end ], argtypes[3 : end ], vtypes, sv)
1668
1677
end
1669
1678
1670
1679
la = length (argtypes)
@@ -2508,12 +2517,14 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller
2508
2517
frame = resolve_call_cycle! (code, caller)
2509
2518
if frame === nothing
2510
2519
code. inInference = true
2511
- frame = InferenceState (code, true , true , caller. params) # always optimize and cache edge targets
2520
+ frame = InferenceState (code, #= optimize =# true , #= cached =# true , caller. params) # always optimize and cache edge targets
2512
2521
if frame === nothing
2513
2522
code. inInference = false
2514
2523
return Any, nothing
2515
2524
end
2516
- frame. parent = caller
2525
+ if caller. cached # don't involve uncached functions in cycle resolution
2526
+ frame. parent = caller
2527
+ end
2517
2528
typeinf (frame)
2518
2529
return frame. bestguess, frame. inferred ? frame. linfo : nothing
2519
2530
end
@@ -2849,6 +2860,7 @@ end
2849
2860
# ### finalize and record the result of running type inference ####
2850
2861
2851
2862
function isinlineable (m:: Method , src:: CodeInfo )
2863
+ # compute the cost (size) of inlining this code
2852
2864
inlineable = false
2853
2865
cost = 1000
2854
2866
if m. module === _topmod (m. module)
@@ -2941,7 +2953,25 @@ function optimize(me::InferenceState)
2941
2953
end
2942
2954
2943
2955
# determine and cache inlineability
2944
- if ! me. src. inlineable && ! force_noinline && isdefined (me. linfo, :def )
2956
+ if ! force_noinline
2957
+ # don't keep ASTs for functions specialized on a Union argument
2958
+ # TODO : this helps avoid a type-system bug mis-computing sparams during intersection
2959
+ sig = unwrap_unionall (me. linfo. specTypes)
2960
+ if isa (sig, DataType) && sig. name === Tuple. name
2961
+ for P in sig. parameters
2962
+ P = unwrap_unionall (P)
2963
+ if isa (P, Union)
2964
+ force_noinline = true
2965
+ break
2966
+ end
2967
+ end
2968
+ else
2969
+ force_noinline = true
2970
+ end
2971
+ end
2972
+ if force_noinline
2973
+ me. src. inlineable = false
2974
+ elseif ! me. src. inlineable && isdefined (me. linfo, :def )
2945
2975
me. src. inlineable = isinlineable (me. linfo. def, me. src)
2946
2976
end
2947
2977
me. src. inferred = true
0 commit comments