@@ -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 = 4 ,
22
+ tuple_splat:: Int = 16 , 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
@@ -1008,9 +1027,9 @@ function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes::VarTable
1008
1027
# can be collapsed to a call to the applied func
1009
1028
at = append_any (Any[type_typeof (af)], ctypes... )
1010
1029
n = length (at)
1011
- if n- 1 > MAX_TUPLETYPE_LEN
1012
- tail = foldl ((a,b)-> tmerge (a,unwrapva (b)), Bottom, at[MAX_TUPLETYPE_LEN+ 1 : n])
1013
- at = vcat (at[1 : MAX_TUPLETYPE_LEN], Any[Vararg{widenconst (tail)}])
1030
+ if n- 1 > sv . params . MAX_TUPLETYPE_LEN
1031
+ tail = foldl ((a,b)-> tmerge (a,unwrapva (b)), Bottom, at[sv . params . MAX_TUPLETYPE_LEN+ 1 : n])
1032
+ at = vcat (at[1 : sv . params . MAX_TUPLETYPE_LEN], Any[Vararg{widenconst (tail)}])
1014
1033
end
1015
1034
return abstract_call (af, (), at, vtypes, sv)
1016
1035
end
@@ -1027,6 +1046,7 @@ function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, vtypes::VarTable, sv:
1027
1046
end
1028
1047
1029
1048
if f === return_type && length (argtypes) == 3
1049
+ # NOTE: only considering calls to return_type without InferenceParams arg
1030
1050
tt = argtypes[3 ]
1031
1051
if isType (tt)
1032
1052
af_argtype = tt. parameters[1 ]
@@ -1130,7 +1150,7 @@ function abstract_call(f::ANY, fargs, argtypes::Vector{Any}, vtypes::VarTable, s
1130
1150
return Type
1131
1151
end
1132
1152
1133
- if sv. inlining
1153
+ if sv. params . inlining
1134
1154
# need to model the special inliner for ^
1135
1155
# to ensure we have added the same edge
1136
1156
if isdefined (Main, :Base ) &&
@@ -1523,7 +1543,8 @@ end
1523
1543
1524
1544
1525
1545
# build (and start inferring) the inference frame for the linfo
1526
- function typeinf_frame (linfo:: MethodInstance , optimize:: Bool , cached:: Bool , caller)
1546
+ function typeinf_frame (linfo:: MethodInstance , caller, optimize:: Bool , cached:: Bool ,
1547
+ params:: InferenceParams )
1527
1548
frame = nothing
1528
1549
if linfo. inInference
1529
1550
# inference on this signature may be in progress,
@@ -1552,7 +1573,7 @@ function typeinf_frame(linfo::MethodInstance, optimize::Bool, cached::Bool, call
1552
1573
src = get_source (linfo)
1553
1574
end
1554
1575
linfo. inInference = true
1555
- frame = InferenceState (linfo, src, optimize, inlining_enabled (), cached )
1576
+ frame = InferenceState (linfo, src, optimize, cached, params )
1556
1577
end
1557
1578
frame = frame:: InferenceState
1558
1579
@@ -1593,7 +1614,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller
1593
1614
end
1594
1615
end
1595
1616
end
1596
- frame = typeinf_frame (code, true , true , caller)
1617
+ frame = typeinf_frame (code, caller, true , true , caller. params )
1597
1618
frame === nothing && return Any
1598
1619
frame = frame:: InferenceState
1599
1620
return frame. bestguess
@@ -1602,12 +1623,14 @@ end
1602
1623
# ### entry points for inferring a MethodInstance given a type signature ####
1603
1624
1604
1625
# compute an inferred AST and return type
1605
- function typeinf_code (method:: Method , atypes:: ANY , sparams:: SimpleVector , optimize:: Bool , cached:: Bool )
1626
+ function typeinf_code (method:: Method , atypes:: ANY , sparams:: SimpleVector ,
1627
+ optimize:: Bool , cached:: Bool , params:: InferenceParams )
1606
1628
code = code_for_method (method, atypes, sparams)
1607
1629
code === nothing && return (nothing , Any)
1608
- return typeinf_code (code:: MethodInstance , optimize, cached)
1630
+ return typeinf_code (code:: MethodInstance , optimize, cached, params )
1609
1631
end
1610
- function typeinf_code (linfo:: MethodInstance , optimize:: Bool , cached:: Bool )
1632
+ function typeinf_code (linfo:: MethodInstance , optimize:: Bool , cached:: Bool ,
1633
+ params:: InferenceParams )
1611
1634
for i = 1 : 2 # test-and-lock-and-test
1612
1635
if cached && isdefined (linfo, :inferred )
1613
1636
# see if this code already exists in the cache
@@ -1638,7 +1661,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool)
1638
1661
end
1639
1662
i == 1 && ccall (:jl_typeinf_begin , Void, ())
1640
1663
end
1641
- frame = typeinf_frame (linfo, optimize, cached, nothing )
1664
+ frame = typeinf_frame (linfo, nothing , optimize, cached, params )
1642
1665
ccall (:jl_typeinf_end , Void, ())
1643
1666
frame === nothing && return (nothing , Any)
1644
1667
frame = frame:: InferenceState
@@ -1647,7 +1670,8 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool)
1647
1670
end
1648
1671
1649
1672
# compute (and cache) an inferred AST and return the inferred return type
1650
- function typeinf_type (method:: Method , atypes:: ANY , sparams:: SimpleVector , cached:: Bool = true )
1673
+ function typeinf_type (method:: Method , atypes:: ANY , sparams:: SimpleVector ,
1674
+ cached:: Bool , params:: InferenceParams )
1651
1675
code = code_for_method (method, atypes, sparams)
1652
1676
code === nothing && return nothing
1653
1677
code = code:: MethodInstance
@@ -1664,7 +1688,7 @@ function typeinf_type(method::Method, atypes::ANY, sparams::SimpleVector, cached
1664
1688
end
1665
1689
i == 1 && ccall (:jl_typeinf_begin , Void, ())
1666
1690
end
1667
- frame = typeinf_frame (code, cached, cached, nothing )
1691
+ frame = typeinf_frame (code, nothing , cached, cached, params )
1668
1692
ccall (:jl_typeinf_end , Void, ())
1669
1693
frame === nothing && return nothing
1670
1694
frame = frame:: InferenceState
@@ -1675,13 +1699,14 @@ end
1675
1699
function typeinf_ext (linfo:: MethodInstance )
1676
1700
if isdefined (linfo, :def )
1677
1701
# method lambda - infer this specialization via the method cache
1678
- (code, typ) = typeinf_code (linfo, true , true )
1702
+ (code, typ) = typeinf_code (linfo, true , true , InferenceParams () )
1679
1703
return code
1680
1704
else
1681
1705
# toplevel lambda - infer directly
1682
1706
linfo. inInference = true
1683
1707
ccall (:jl_typeinf_begin , Void, ())
1684
- frame = InferenceState (linfo, linfo. inferred:: CodeInfo , true , inlining_enabled (), true )
1708
+ frame = InferenceState (linfo, linfo. inferred:: CodeInfo ,
1709
+ true , true , InferenceParams ())
1685
1710
typeinf_loop (frame)
1686
1711
ccall (:jl_typeinf_end , Void, ())
1687
1712
@assert frame. inferred # TODO : deal with this better
@@ -2141,7 +2166,6 @@ function type_annotate!(sv::InferenceState)
2141
2166
body = src. code:: Array{Any,1}
2142
2167
nexpr = length (body)
2143
2168
i = 1
2144
- optimize = sv. optimize:: Bool
2145
2169
while i <= nexpr
2146
2170
st_i = states[i]
2147
2171
expr = body[i]
@@ -2154,7 +2178,7 @@ function type_annotate!(sv::InferenceState)
2154
2178
id = expr. args[1 ]. id
2155
2179
record_slot_type! (id, widenconst (states[i+ 1 ][id]. typ), src. slottypes)
2156
2180
end
2157
- elseif optimize
2181
+ elseif sv . optimize
2158
2182
if ((isa (expr, Expr) && is_meta_expr (expr:: Expr )) ||
2159
2183
isa (expr, LineNumberNode))
2160
2184
i += 1
@@ -2437,7 +2461,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2437
2461
end
2438
2462
topmod = _topmod (sv)
2439
2463
# special-case inliners for known pure functions that compute types
2440
- if sv. inlining
2464
+ if sv. params . inlining
2441
2465
if isconstType (e. typ,true )
2442
2466
if (is (f, apply_type) || is (f, fieldtype) || is (f, typeof) ||
2443
2467
istopfunction (topmod, f, :typejoin ) ||
@@ -2471,7 +2495,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2471
2495
function invoke_NF ()
2472
2496
# converts a :call to :invoke
2473
2497
local nu = countunionsplit (atypes)
2474
- nu > MAX_UNION_SPLITTING && return NF
2498
+ nu > sv . params . MAX_UNION_SPLITTING && return NF
2475
2499
2476
2500
if nu > 1
2477
2501
local spec_hit = nothing
@@ -2571,12 +2595,12 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2571
2595
end
2572
2596
return NF
2573
2597
end
2574
- if ! sv. inlining
2598
+ if ! sv. params . inlining
2575
2599
return invoke_NF ()
2576
2600
end
2577
2601
2578
- if length (atype_unlimited. parameters) - 1 > MAX_TUPLETYPE_LEN
2579
- atype = limit_tuple_type (atype_unlimited)
2602
+ if length (atype_unlimited. parameters) - 1 > sv . params . MAX_TUPLETYPE_LEN
2603
+ atype = limit_tuple_type (atype_unlimited, sv . params )
2580
2604
else
2581
2605
atype = atype_unlimited
2582
2606
end
@@ -2657,7 +2681,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2657
2681
linfo = code_for_method (method, metharg, methsp)
2658
2682
end
2659
2683
if isa (linfo, MethodInstance)
2660
- frame = typeinf_frame (linfo:: MethodInstance , true , true , nothing )
2684
+ frame = typeinf_frame (linfo:: MethodInstance , nothing , true , true , sv . params )
2661
2685
end
2662
2686
end
2663
2687
if isa (frame, InferenceState) && frame. inferred
@@ -3082,7 +3106,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3082
3106
end
3083
3107
end
3084
3108
3085
- if sv. inlining
3109
+ if sv. params . inlining
3086
3110
if isdefined (Main, :Base ) &&
3087
3111
((isdefined (Main. Base, :^ ) && is (f, Main. Base.:^ )) ||
3088
3112
(isdefined (Main. Base, :.^ ) && is (f, Main. Base.:.^ ))) &&
@@ -3161,7 +3185,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3161
3185
elseif isa (aarg, Tuple)
3162
3186
newargs[i- 2 ] = Any[ QuoteNode (x) for x in aarg ]
3163
3187
elseif isa (t, DataType) && t. name === Tuple. name && ! isvatuple (t) &&
3164
- effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= MAX_TUPLE_SPLAT
3188
+ effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= sv . params . MAX_TUPLE_SPLAT
3165
3189
# apply(f,t::(x,y)) => f(t[1],t[2])
3166
3190
tp = t. parameters
3167
3191
newargs[i- 2 ] = Any[ mk_getfield (aarg,j,tp[j]) for j= 1 : length (tp) ]
@@ -3962,10 +3986,12 @@ function reindex_labels!(sv::InferenceState)
3962
3986
end
3963
3987
end
3964
3988
3965
- function return_type (f:: ANY , t:: ANY )
3989
+ function return_type (f:: ANY , t:: ANY , params:: InferenceParams = InferenceParams ())
3990
+ # NOTE: if not processed by pure_eval_call during inference, a call to return_type
3991
+ # might use difference InferenceParams than the method it is contained in...
3966
3992
rt = Union{}
3967
3993
for m in _methods (f, t, - 1 )
3968
- ty = typeinf_type (m[3 ], m[1 ], m[2 ])
3994
+ ty = typeinf_type (m[3 ], m[1 ], m[2 ], true , params )
3969
3995
ty === nothing && return Any
3970
3996
rt = tmerge (rt, ty)
3971
3997
rt === Any && break
@@ -3999,7 +4025,7 @@ let fs = Any[typeinf_ext, typeinf_loop, typeinf_edge, occurs_outside_getfield, e
3999
4025
typ[i] = typ[i]. ub
4000
4026
end
4001
4027
end
4002
- typeinf_type (m[3 ], Tuple{typ... }, m[2 ])
4028
+ typeinf_type (m[3 ], Tuple{typ... }, m[2 ], true , InferenceParams () )
4003
4029
end
4004
4030
end
4005
4031
end
0 commit comments