@@ -5,11 +5,25 @@ import Core: _apply, svec, apply_type, Builtin, IntrinsicFunction, MethodInstanc
5
5
# ### parameters limiting potentially-infinite types ####
6
6
const MAX_TYPEUNION_LEN = 3
7
7
const MAX_TYPE_DEPTH = 7
8
- const MAX_TUPLETYPE_LEN = 15
9
- const MAX_TUPLE_DEPTH = 4
10
8
11
- const MAX_TUPLE_SPLAT = 16
12
- const MAX_UNION_SPLITTING = 4
9
+ immutable InferenceParams
10
+ # optimization
11
+ inlining:: Bool
12
+
13
+ # parameters limiting potentially-infinite types (configurable)
14
+ MAX_TUPLETYPE_LEN:: Int
15
+ MAX_TUPLE_DEPTH:: Int
16
+ MAX_TUPLE_SPLAT:: Int
17
+ MAX_UNION_SPLITTING:: Int
18
+
19
+ # reasonable defaults
20
+ InferenceParams (;inlining:: Bool = inlining_enabled (),
21
+ tupletype_len:: Int = 15 , tuple_depth:: Int = 16 ,
22
+ tuple_splat:: Int = 4 , union_splitting:: Int = 4 ) =
23
+ new (inlining, tupletype_len,
24
+ tuple_depth, tuple_splat, union_splitting)
25
+ end
26
+
13
27
const UNION_SPLIT_MISMATCH_ERROR = false
14
28
15
29
# alloc_elim_pass! relies on `Slot_AssignedOnce | Slot_UsedUndef` being
@@ -49,6 +63,8 @@ type InferenceState
49
63
mod:: Module
50
64
currpc:: LineNum
51
65
66
+ params:: InferenceParams
67
+
52
68
# info on the state of inference and the linfo
53
69
linfo:: MethodInstance # used here for the tuple (specTypes, env, Method)
54
70
src:: CodeInfo
@@ -74,14 +90,16 @@ type InferenceState
74
90
# iteration fixed-point detection
75
91
fixedpoint:: Bool
76
92
inworkq:: Bool
77
- # optimization
93
+
94
+ # TODO : put these in InferenceParams (depends on proper multi-methodcache support)
78
95
optimize:: Bool
79
- inlining:: Bool
80
96
cached:: Bool
97
+
81
98
inferred:: Bool
82
99
83
100
# src is assumed to be a newly-allocated CodeInfo, that can be modified in-place to contain intermediate results
84
- function InferenceState (linfo:: MethodInstance , src:: CodeInfo , optimize:: Bool , inlining:: Bool , cached:: Bool )
101
+ function InferenceState (linfo:: MethodInstance , src:: CodeInfo ,
102
+ optimize:: Bool , cached:: Bool , params:: InferenceParams )
85
103
code = src. code:: Array{Any,1}
86
104
nl = label_counter (code) + 1
87
105
toplevel = ! isdefined (linfo, :def )
@@ -113,7 +131,7 @@ type InferenceState
113
131
end
114
132
s[1 ][la] = VarState (Tuple, false )
115
133
else
116
- s[1 ][la] = VarState (tuple_tfunc (limit_tuple_depth (tupletype_tail (atypes, la))), false )
134
+ s[1 ][la] = VarState (tuple_tfunc (limit_tuple_depth (params, tupletype_tail (atypes, la))), false )
117
135
end
118
136
la -= 1
119
137
end
@@ -168,12 +186,13 @@ type InferenceState
168
186
inmodule = toplevel ? current_module () : linfo. def. module # toplevel thunks are inferred in the current module
169
187
frame = new (
170
188
sp, nl, inmodule, 0 ,
189
+ params,
171
190
linfo, src, nargs, s, Union{}, W, n,
172
191
cur_hand, handler_at, n_handlers,
173
192
ssavalue_uses, ssavalue_init,
174
193
ObjectIdDict (), # Dict{InferenceState, Vector{LineNum}}(),
175
194
Vector {Tuple{InferenceState, Vector{LineNum}}} (),
176
- false , false , optimize, inlining, cached, false )
195
+ false , false , optimize, cached, false )
177
196
push! (active, frame)
178
197
nactive[] += 1
179
198
return frame
@@ -669,7 +688,7 @@ function invoke_tfunc(f::ANY, types::ANY, argtype::ANY, sv::InferenceState)
669
688
if ! isleaftype (Type{types})
670
689
return Any
671
690
end
672
- argtype = typeintersect (types,limit_tuple_type (argtype))
691
+ argtype = typeintersect (types,limit_tuple_type (argtype, sv . params ))
673
692
if is (argtype,Bottom)
674
693
return Bottom
675
694
end
@@ -703,7 +722,7 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, sv::InferenceState)
703
722
if is (f,tuple)
704
723
for a in argtypes
705
724
if ! isa (a, Const)
706
- return tuple_tfunc (limit_tuple_depth (argtypes_to_type (argtypes)))
725
+ return tuple_tfunc (limit_tuple_depth (sv . params, argtypes_to_type (argtypes)))
707
726
end
708
727
end
709
728
return Const (tuple (map (a-> a. val, argtypes)... ))
@@ -766,28 +785,28 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, sv::InferenceState)
766
785
return tf[3 ](argtypes... )
767
786
end
768
787
769
- limit_tuple_depth (t:: ANY ) = limit_tuple_depth_ (t,0 )
788
+ limit_tuple_depth (params :: InferenceParams , t:: ANY ) = limit_tuple_depth_ (params, t,0 )
770
789
771
- function limit_tuple_depth_ (t:: ANY , d:: Int )
790
+ function limit_tuple_depth_ (params :: InferenceParams , t:: ANY , d:: Int )
772
791
if isa (t,Union)
773
792
# also limit within Union types.
774
793
# may have to recur into other stuff in the future too.
775
- return Union{map (x-> limit_tuple_depth_ (x,d+ 1 ), t. types)... }
794
+ return Union{map (x-> limit_tuple_depth_ (params, x,d+ 1 ), t. types)... }
776
795
end
777
796
if isa (t,TypeVar)
778
- return limit_tuple_depth_ (t. ub, d)
797
+ return limit_tuple_depth_ (params, t. ub, d)
779
798
end
780
799
if ! (isa (t,DataType) && t. name === Tuple. name)
781
800
return t
782
801
end
783
- if d > MAX_TUPLE_DEPTH
802
+ if d > params . MAX_TUPLE_DEPTH
784
803
return Tuple
785
804
end
786
- p = map (x-> limit_tuple_depth_ (x,d+ 1 ), t. parameters)
805
+ p = map (x-> limit_tuple_depth_ (params, x,d+ 1 ), t. parameters)
787
806
Tuple{p... }
788
807
end
789
808
790
- limit_tuple_type = (t:: ANY ) -> limit_tuple_type_n (t, MAX_TUPLETYPE_LEN)
809
+ limit_tuple_type = (t:: ANY , params :: InferenceParams ) -> limit_tuple_type_n (t, params . MAX_TUPLETYPE_LEN)
791
810
792
811
function limit_tuple_type_n (t:: ANY , lim:: Int )
793
812
p = t. parameters
802
821
803
822
# ### recursing into expression ####
804
823
805
- function abstract_call_gf_by_type (f:: ANY , argtype:: ANY , sv)
824
+ function abstract_call_gf_by_type (f:: ANY , argtype:: ANY , sv:: InferenceState )
806
825
tm = _topmod (sv)
807
826
# don't consider more than N methods. this trades off between
808
827
# compiler performance and generated code performance.
@@ -811,7 +830,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, sv)
811
830
# It is important for N to be >= the number of methods in the error()
812
831
# function, so we can still know that error() is always Bottom.
813
832
# here I picked 4.
814
- argtype = limit_tuple_type (argtype)
833
+ argtype = limit_tuple_type (argtype, sv . params )
815
834
argtypes = argtype. parameters
816
835
applicable = _methods_by_ftype (argtype, 4 )
817
836
rettype = Bottom
@@ -1006,9 +1025,10 @@ function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes::VarTable
1006
1025
# can be collapsed to a call to the applied func
1007
1026
at = append_any (Any[type_typeof (af)], ctypes... )
1008
1027
n = length (at)
1009
- if n- 1 > MAX_TUPLETYPE_LEN
1010
- tail = foldl ((a,b)-> tmerge (a,unwrapva (b)), Bottom, at[MAX_TUPLETYPE_LEN+ 1 : n])
1011
- at = vcat (at[1 : MAX_TUPLETYPE_LEN], Any[Vararg{tail}])
1028
+ if n- 1 > sv. params. MAX_TUPLETYPE_LEN
1029
+ tail = foldl ((a,b)-> tmerge (a,unwrapva (b)), Bottom,
1030
+ at[sv. params. MAX_TUPLETYPE_LEN+ 1 : n])
1031
+ at = vcat (at[1 : sv. params. MAX_TUPLETYPE_LEN], Any[Vararg{tail}])
1012
1032
end
1013
1033
return abstract_call (af, (), at, vtypes, sv)
1014
1034
end
@@ -1024,6 +1044,7 @@ function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, vtypes::VarTable, sv:
1024
1044
end
1025
1045
1026
1046
if f === return_type && length (argtypes) == 3
1047
+ # NOTE: only considering calls to return_type without InferenceParams arg
1027
1048
tt = argtypes[3 ]
1028
1049
if isType (tt)
1029
1050
af_argtype = tt. parameters[1 ]
@@ -1127,7 +1148,7 @@ function abstract_call(f::ANY, fargs, argtypes::Vector{Any}, vtypes::VarTable, s
1127
1148
return Type
1128
1149
end
1129
1150
1130
- if sv. inlining
1151
+ if sv. params . inlining
1131
1152
# need to model the special inliner for ^
1132
1153
# to ensure we have added the same edge
1133
1154
if isdefined (Main, :Base ) &&
@@ -1520,7 +1541,8 @@ end
1520
1541
1521
1542
1522
1543
# build (and start inferring) the inference frame for the linfo
1523
- function typeinf_frame (linfo:: MethodInstance , optimize:: Bool , cached:: Bool , caller)
1544
+ function typeinf_frame (linfo:: MethodInstance , caller, optimize:: Bool , cached:: Bool ,
1545
+ params:: InferenceParams )
1524
1546
frame = nothing
1525
1547
if linfo. inInference
1526
1548
# inference on this signature may be in progress,
@@ -1549,7 +1571,7 @@ function typeinf_frame(linfo::MethodInstance, optimize::Bool, cached::Bool, call
1549
1571
src = get_source (linfo)
1550
1572
end
1551
1573
linfo. inInference = true
1552
- frame = InferenceState (linfo, src, optimize, inlining_enabled (), cached )
1574
+ frame = InferenceState (linfo, src, optimize, cached, params )
1553
1575
end
1554
1576
frame = frame:: InferenceState
1555
1577
@@ -1590,7 +1612,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller
1590
1612
end
1591
1613
end
1592
1614
end
1593
- frame = typeinf_frame (code, true , true , caller)
1615
+ frame = typeinf_frame (code, caller, true , true , caller. params )
1594
1616
frame === nothing && return Any
1595
1617
frame = frame:: InferenceState
1596
1618
return frame. bestguess
@@ -1599,12 +1621,14 @@ end
1599
1621
# ### entry points for inferring a MethodInstance given a type signature ####
1600
1622
1601
1623
# compute an inferred AST and return type
1602
- function typeinf_code (method:: Method , atypes:: ANY , sparams:: SimpleVector , optimize:: Bool , cached:: Bool )
1624
+ function typeinf_code (method:: Method , atypes:: ANY , sparams:: SimpleVector ,
1625
+ optimize:: Bool , cached:: Bool , params:: InferenceParams )
1603
1626
code = code_for_method (method, atypes, sparams)
1604
1627
code === nothing && return (nothing , Any)
1605
- return typeinf_code (code:: MethodInstance , optimize, cached)
1628
+ return typeinf_code (code:: MethodInstance , optimize, cached, params )
1606
1629
end
1607
- function typeinf_code (linfo:: MethodInstance , optimize:: Bool , cached:: Bool )
1630
+ function typeinf_code (linfo:: MethodInstance , optimize:: Bool , cached:: Bool ,
1631
+ params:: InferenceParams )
1608
1632
for i = 1 : 2 # test-and-lock-and-test
1609
1633
if cached && isdefined (linfo, :inferred )
1610
1634
# see if this code already exists in the cache
@@ -1635,7 +1659,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool)
1635
1659
end
1636
1660
i == 1 && ccall (:jl_typeinf_begin , Void, ())
1637
1661
end
1638
- frame = typeinf_frame (linfo, optimize, cached, nothing )
1662
+ frame = typeinf_frame (linfo, nothing , optimize, cached, params )
1639
1663
ccall (:jl_typeinf_end , Void, ())
1640
1664
frame === nothing && return (nothing , Any)
1641
1665
frame = frame:: InferenceState
@@ -1644,7 +1668,8 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool)
1644
1668
end
1645
1669
1646
1670
# compute (and cache) an inferred AST and return the inferred return type
1647
- function typeinf_type (method:: Method , atypes:: ANY , sparams:: SimpleVector , cached:: Bool = true )
1671
+ function typeinf_type (method:: Method , atypes:: ANY , sparams:: SimpleVector ,
1672
+ cached:: Bool , params:: InferenceParams )
1648
1673
code = code_for_method (method, atypes, sparams)
1649
1674
code === nothing && return nothing
1650
1675
code = code:: MethodInstance
@@ -1661,7 +1686,7 @@ function typeinf_type(method::Method, atypes::ANY, sparams::SimpleVector, cached
1661
1686
end
1662
1687
i == 1 && ccall (:jl_typeinf_begin , Void, ())
1663
1688
end
1664
- frame = typeinf_frame (code, cached, cached, nothing )
1689
+ frame = typeinf_frame (code, nothing , cached, cached, params )
1665
1690
ccall (:jl_typeinf_end , Void, ())
1666
1691
frame === nothing && return nothing
1667
1692
frame = frame:: InferenceState
@@ -1672,13 +1697,14 @@ end
1672
1697
function typeinf_ext (linfo:: MethodInstance )
1673
1698
if isdefined (linfo, :def )
1674
1699
# method lambda - infer this specialization via the method cache
1675
- (code, typ) = typeinf_code (linfo, true , true )
1700
+ (code, typ) = typeinf_code (linfo, true , true , InferenceParams () )
1676
1701
return code
1677
1702
else
1678
1703
# toplevel lambda - infer directly
1679
1704
linfo. inInference = true
1680
1705
ccall (:jl_typeinf_begin , Void, ())
1681
- frame = InferenceState (linfo, linfo. inferred:: CodeInfo , true , inlining_enabled (), true )
1706
+ frame = InferenceState (linfo, linfo. inferred:: CodeInfo ,
1707
+ true , true , InferenceParams ())
1682
1708
typeinf_loop (frame)
1683
1709
ccall (:jl_typeinf_end , Void, ())
1684
1710
@assert frame. inferred # TODO : deal with this better
@@ -2138,7 +2164,6 @@ function type_annotate!(sv::InferenceState)
2138
2164
body = src. code:: Array{Any,1}
2139
2165
nexpr = length (body)
2140
2166
i = 1
2141
- optimize = sv. optimize:: Bool
2142
2167
while i <= nexpr
2143
2168
st_i = states[i]
2144
2169
expr = body[i]
@@ -2151,7 +2176,7 @@ function type_annotate!(sv::InferenceState)
2151
2176
id = expr. args[1 ]. id
2152
2177
record_slot_type! (id, widenconst (states[i+ 1 ][id]. typ), src. slottypes)
2153
2178
end
2154
- elseif optimize
2179
+ elseif sv . optimize
2155
2180
if ((isa (expr, Expr) && is_meta_expr (expr:: Expr )) ||
2156
2181
isa (expr, LineNumberNode))
2157
2182
i += 1
@@ -2426,7 +2451,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2426
2451
end
2427
2452
topmod = _topmod (sv)
2428
2453
# special-case inliners for known pure functions that compute types
2429
- if sv. inlining
2454
+ if sv. params . inlining
2430
2455
if isconstType (e. typ,true )
2431
2456
if (is (f, apply_type) || is (f, fieldtype) || is (f, typeof) ||
2432
2457
istopfunction (topmod, f, :typejoin ) ||
@@ -2460,7 +2485,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2460
2485
function invoke_NF ()
2461
2486
# converts a :call to :invoke
2462
2487
local nu = countunionsplit (atypes)
2463
- nu > MAX_UNION_SPLITTING && return NF
2488
+ nu > sv . params . MAX_UNION_SPLITTING && return NF
2464
2489
2465
2490
if nu > 1
2466
2491
local spec_hit = nothing
@@ -2560,12 +2585,12 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2560
2585
end
2561
2586
return NF
2562
2587
end
2563
- if ! sv. inlining
2588
+ if ! sv. params . inlining
2564
2589
return invoke_NF ()
2565
2590
end
2566
2591
2567
- if length (atype_unlimited. parameters) - 1 > MAX_TUPLETYPE_LEN
2568
- atype = limit_tuple_type (atype_unlimited)
2592
+ if length (atype_unlimited. parameters) - 1 > sv . params . MAX_TUPLETYPE_LEN
2593
+ atype = limit_tuple_type (atype_unlimited, sv . params )
2569
2594
else
2570
2595
atype = atype_unlimited
2571
2596
end
@@ -2646,7 +2671,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2646
2671
linfo = code_for_method (method, metharg, methsp)
2647
2672
end
2648
2673
if isa (linfo, MethodInstance)
2649
- frame = typeinf_frame (linfo:: MethodInstance , true , true , nothing )
2674
+ frame = typeinf_frame (linfo:: MethodInstance , nothing , true , true , sv . params )
2650
2675
end
2651
2676
end
2652
2677
if isa (frame, InferenceState) && frame. inferred
@@ -3071,7 +3096,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3071
3096
end
3072
3097
end
3073
3098
3074
- if sv. inlining
3099
+ if sv. params . inlining
3075
3100
if isdefined (Main, :Base ) &&
3076
3101
((isdefined (Main. Base, :^ ) && is (f, Main. Base.:^ )) ||
3077
3102
(isdefined (Main. Base, :.^ ) && is (f, Main. Base.:.^ ))) &&
@@ -3150,7 +3175,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3150
3175
elseif isa (aarg, Tuple)
3151
3176
newargs[i- 2 ] = Any[ QuoteNode (x) for x in aarg ]
3152
3177
elseif isa (t, DataType) && t. name === Tuple. name && ! isvatuple (t) &&
3153
- effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= MAX_TUPLE_SPLAT
3178
+ effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= sv . params . MAX_TUPLE_SPLAT
3154
3179
# apply(f,t::(x,y)) => f(t[1],t[2])
3155
3180
tp = t. parameters
3156
3181
newargs[i- 2 ] = Any[ mk_getfield (aarg,j,tp[j]) for j= 1 : length (tp) ]
@@ -3951,10 +3976,12 @@ function reindex_labels!(sv::InferenceState)
3951
3976
end
3952
3977
end
3953
3978
3954
- function return_type (f:: ANY , t:: ANY )
3979
+ function return_type (f:: ANY , t:: ANY , params:: InferenceParams = InferenceParams ())
3980
+ # NOTE: if not processed by pure_eval_call during inference, a call to return_type
3981
+ # might use difference InferenceParams than the method it is contained in...
3955
3982
rt = Union{}
3956
3983
for m in _methods (f, t, - 1 )
3957
- ty = typeinf_type (m[3 ], m[1 ], m[2 ])
3984
+ ty = typeinf_type (m[3 ], m[1 ], m[2 ], true , params )
3958
3985
ty === nothing && return Any
3959
3986
rt = tmerge (rt, ty)
3960
3987
rt === Any && break
@@ -3988,7 +4015,7 @@ let fs = Any[typeinf_ext, typeinf_loop, typeinf_edge, occurs_outside_getfield, e
3988
4015
typ[i] = typ[i]. ub
3989
4016
end
3990
4017
end
3991
- typeinf_type (m[3 ], Tuple{typ... }, m[2 ])
4018
+ typeinf_type (m[3 ], Tuple{typ... }, m[2 ], true , InferenceParams () )
3992
4019
end
3993
4020
end
3994
4021
end
0 commit comments