@@ -71,9 +71,10 @@ type InferenceState
71
71
typegotoredo:: Bool
72
72
inworkq:: Bool
73
73
optimize:: Bool
74
+ needtree:: Bool
74
75
inferred:: Bool
75
76
76
- function InferenceState (linfo:: LambdaInfo , optimize:: Bool )
77
+ function InferenceState (linfo:: LambdaInfo , optimize:: Bool , needtree :: Bool )
77
78
@assert isa (linfo. code,Array{Any,1 })
78
79
nslots = length (linfo. slotnames)
79
80
nl = label_counter (linfo. code)+ 1
@@ -158,7 +159,7 @@ type InferenceState
158
159
ssavalue_uses, ssavalue_init,
159
160
ObjectIdDict (), # Dict{InferenceState, Vector{LineNum}}(),
160
161
Vector {Tuple{InferenceState, Vector{LineNum}}} (),
161
- false , false , false , optimize, false )
162
+ false , false , false , optimize, needtree, false )
162
163
push! (active, frame)
163
164
nactive[] += 1
164
165
return frame
@@ -1473,6 +1474,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
1473
1474
# don't call staged functions on abstract types.
1474
1475
# (see issues #8504, #10230)
1475
1476
# we can't guarantee that their type behavior is monotonic.
1477
+ # XXX : this test is wrong if Types (such as DataType) are present
1476
1478
return (nothing , Any, false )
1477
1479
end
1478
1480
try
@@ -1485,6 +1487,8 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
1485
1487
linfo = specialize_method (method, atypes, sparams, cached)
1486
1488
end
1487
1489
1490
+ # XXX : the following logic is likely subtly broken if code.code was nothing,
1491
+ # although it seems unlikely something bad (infinite recursion) will happen as a result
1488
1492
if linfo. inInference
1489
1493
# inference on this signature may be in progress,
1490
1494
# find the corresponding frame in the active list
@@ -1498,10 +1502,13 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
1498
1502
end
1499
1503
# TODO : this assertion seems iffy
1500
1504
assert (frame != = nothing )
1505
+ if needtree
1506
+ frame. needtree = true
1507
+ end
1501
1508
else
1502
1509
# inference not started yet, make a new frame for a new lambda
1503
1510
linfo. inInference = true
1504
- frame = InferenceState (unshare_linfo! (linfo:: LambdaInfo ), optimize)
1511
+ frame = InferenceState (unshare_linfo! (linfo:: LambdaInfo ), optimize, needtree )
1505
1512
end
1506
1513
frame = frame:: InferenceState
1507
1514
@@ -1541,8 +1548,8 @@ end
1541
1548
function typeinf_ext (linfo:: LambdaInfo )
1542
1549
if isdefined (linfo, :def )
1543
1550
# method lambda - infer this specialization via the method cache
1544
- (code, _t, _ ) = typeinf_edge (linfo. def, linfo. specTypes, linfo. sparam_vals, true , true , true , linfo)
1545
- if code. inferred && linfo != = code
1551
+ (code, _t, inferred ) = typeinf_edge (linfo. def, linfo. specTypes, linfo. sparam_vals, true , true , true , linfo)
1552
+ if inferred && code. inferred && linfo != = code
1546
1553
# This case occurs when the IR for a function has been deleted.
1547
1554
# `code` will be a newly-created LambdaInfo, and we need to copy its
1548
1555
# contents to the existing one to copy the info to the method cache.
@@ -1562,7 +1569,7 @@ function typeinf_ext(linfo::LambdaInfo)
1562
1569
else
1563
1570
# toplevel lambda - infer directly
1564
1571
linfo. inInference = true
1565
- frame = InferenceState (linfo, true )
1572
+ frame = InferenceState (linfo, true , true )
1566
1573
typeinf_loop (frame)
1567
1574
@assert frame. inferred # TODO : deal with this better
1568
1575
return linfo
@@ -1875,7 +1882,8 @@ function isinlineable(linfo::LambdaInfo)
1875
1882
end
1876
1883
end
1877
1884
if ! inlineable
1878
- body = Expr (:block ); body. args = linfo. code
1885
+ body = Expr (:block )
1886
+ body. args = linfo. code
1879
1887
inlineable = inline_worthy (body, cost)
1880
1888
end
1881
1889
end
@@ -1903,9 +1911,6 @@ function finish(me::InferenceState)
1903
1911
end
1904
1912
type_annotate! (me. linfo, me. stmt_types, me, me. nargs)
1905
1913
1906
- # make sure (meta pure) is stripped from full tree
1907
- ispure = popmeta! (me. linfo. code, :pure )[1 ]
1908
-
1909
1914
# run optimization passes on fulltree
1910
1915
if me. optimize
1911
1916
# This pass is required for the AST to be valid in codegen
@@ -1923,22 +1928,34 @@ function finish(me::InferenceState)
1923
1928
reindex_labels! (me. linfo, me)
1924
1929
end
1925
1930
widen_all_consts! (me. linfo)
1926
-
1927
- # finalize and record the linfo result
1928
- me. inferred = true
1931
+ # make sure (meta pure) is stripped from full tree
1932
+ ispure = popmeta! (me . linfo. code, :pure )[ 1 ]
1933
+ me. linfo . pure = ispure
1929
1934
1930
1935
# determine and cache inlineability
1931
1936
me. linfo. inlineable = isinlineable (me. linfo)
1932
1937
1933
- if isdefined (me. linfo, :def )
1934
- # compress code for non-toplevel thunks
1935
- compressedtree = ccall (:jl_compress_ast , Any, (Any,Any), me. linfo, me. linfo. code)
1936
- me. linfo. code = compressedtree
1938
+ if ! me. needtree
1939
+ me. needtree = me. linfo. inlineable || ccall (:jl_is_cacheable_sig , Int32, (Any, Any, Any),
1940
+ me. linfo. specTypes, me. linfo. def. sig, me. linfo. def) != 0
1937
1941
end
1938
- me. linfo. pure = ispure
1942
+
1943
+ if me. needtree
1944
+ if isdefined (me. linfo, :def )
1945
+ # compress code for non-toplevel thunks
1946
+ compressedtree = ccall (:jl_compress_ast , Any, (Any,Any), me. linfo, me. linfo. code)
1947
+ me. linfo. code = compressedtree
1948
+ end
1949
+ else
1950
+ ccall (:jl_set_lambda_code_null , Void, (Any,), me. linfo)
1951
+ me. linfo. inlineable = false
1952
+ end
1953
+
1939
1954
ccall (:jl_set_lambda_rettype , Void, (Any, Any), me. linfo, me. bestguess)
1940
1955
me. linfo. inferred = true
1941
1956
me. linfo. inInference = false
1957
+ # finalize and record the linfo result
1958
+ me. inferred = true
1942
1959
1943
1960
# lazy-delete the item from active for several reasons:
1944
1961
# efficiency, correctness, and recursion-safety
0 commit comments