@@ -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 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 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
@@ -2144,7 +2169,6 @@ function type_annotate!(sv::InferenceState)
2144
2169
body = src. code:: Array{Any,1}
2145
2170
nexpr = length (body)
2146
2171
i = 1
2147
- optimize = sv. optimize:: Bool
2148
2172
while i <= nexpr
2149
2173
st_i = states[i]
2150
2174
expr = body[i]
@@ -2157,7 +2181,7 @@ function type_annotate!(sv::InferenceState)
2157
2181
id = expr. args[1 ]. id
2158
2182
record_slot_type! (id, widenconst (states[i+ 1 ][id]. typ), src. slottypes)
2159
2183
end
2160
- elseif optimize
2184
+ elseif sv . optimize
2161
2185
if ((isa (expr, Expr) && is_meta_expr (expr:: Expr )) ||
2162
2186
isa (expr, LineNumberNode))
2163
2187
i += 1
@@ -2440,7 +2464,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2440
2464
end
2441
2465
topmod = _topmod (sv)
2442
2466
# special-case inliners for known pure functions that compute types
2443
- if sv. inlining
2467
+ if sv. params . inlining
2444
2468
if isconstType (e. typ,true )
2445
2469
if (f === apply_type || f === fieldtype || f === typeof ||
2446
2470
istopfunction (topmod, f, :typejoin ) ||
@@ -2474,7 +2498,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2474
2498
function invoke_NF ()
2475
2499
# converts a :call to :invoke
2476
2500
local nu = countunionsplit (atypes)
2477
- nu > MAX_UNION_SPLITTING && return NF
2501
+ nu > sv . params . MAX_UNION_SPLITTING && return NF
2478
2502
2479
2503
if nu > 1
2480
2504
local spec_hit = nothing
@@ -2574,12 +2598,12 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2574
2598
end
2575
2599
return NF
2576
2600
end
2577
- if ! sv. inlining
2601
+ if ! sv. params . inlining
2578
2602
return invoke_NF ()
2579
2603
end
2580
2604
2581
- if length (atype_unlimited. parameters) - 1 > MAX_TUPLETYPE_LEN
2582
- atype = limit_tuple_type (atype_unlimited)
2605
+ if length (atype_unlimited. parameters) - 1 > sv . params . MAX_TUPLETYPE_LEN
2606
+ atype = limit_tuple_type (atype_unlimited, sv . params )
2583
2607
else
2584
2608
atype = atype_unlimited
2585
2609
end
@@ -2660,7 +2684,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
2660
2684
linfo = code_for_method (method, metharg, methsp)
2661
2685
end
2662
2686
if isa (linfo, MethodInstance)
2663
- frame = typeinf_frame (linfo:: MethodInstance , true , true , nothing )
2687
+ frame = typeinf_frame (linfo:: MethodInstance , nothing , true , true , sv . params )
2664
2688
end
2665
2689
end
2666
2690
if isa (frame, InferenceState) && frame. inferred
@@ -3085,7 +3109,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3085
3109
end
3086
3110
end
3087
3111
3088
- if sv. inlining
3112
+ if sv. params . inlining
3089
3113
if isdefined (Main, :Base ) &&
3090
3114
((isdefined (Main. Base, :^ ) && f === Main. Base.:^ ) ||
3091
3115
(isdefined (Main. Base, :.^ ) && f === Main. Base.:.^ )) &&
@@ -3164,7 +3188,7 @@ function inlining_pass(e::Expr, sv::InferenceState)
3164
3188
elseif isa (aarg, Tuple)
3165
3189
newargs[i- 2 ] = Any[ QuoteNode (x) for x in aarg ]
3166
3190
elseif isa (t, DataType) && t. name === Tuple. name && ! isvatuple (t) &&
3167
- effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= MAX_TUPLE_SPLAT
3191
+ effect_free (aarg, sv. src, sv. mod, true ) && length (t. parameters) <= sv . params . MAX_TUPLE_SPLAT
3168
3192
# apply(f,t::(x,y)) => f(t[1],t[2])
3169
3193
tp = t. parameters
3170
3194
newargs[i- 2 ] = Any[ mk_getfield (aarg,j,tp[j]) for j= 1 : length (tp) ]
@@ -3965,10 +3989,12 @@ function reindex_labels!(sv::InferenceState)
3965
3989
end
3966
3990
end
3967
3991
3968
- function return_type (f:: ANY , t:: ANY )
3992
+ function return_type (f:: ANY , t:: ANY , params:: InferenceParams = InferenceParams ())
3993
+ # NOTE: if not processed by pure_eval_call during inference, a call to return_type
3994
+ # might use difference InferenceParams than the method it is contained in...
3969
3995
rt = Union{}
3970
3996
for m in _methods (f, t, - 1 )
3971
- ty = typeinf_type (m[3 ], m[1 ], m[2 ])
3997
+ ty = typeinf_type (m[3 ], m[1 ], m[2 ], true , params )
3972
3998
ty === nothing && return Any
3973
3999
rt = tmerge (rt, ty)
3974
4000
rt === Any && break
@@ -4002,7 +4028,7 @@ let fs = Any[typeinf_ext, typeinf_loop, typeinf_edge, occurs_outside_getfield, e
4002
4028
typ[i] = typ[i]. ub
4003
4029
end
4004
4030
end
4005
- typeinf_type (m[3 ], Tuple{typ... }, m[2 ])
4031
+ typeinf_type (m[3 ], Tuple{typ... }, m[2 ], true , InferenceParams () )
4006
4032
end
4007
4033
end
4008
4034
end
0 commit comments