@@ -47,7 +47,6 @@ type InferenceState
47
47
48
48
# info on the state of inference and the linfo
49
49
linfo:: LambdaInfo
50
- destination:: LambdaInfo # results need to be copied here when we finish
51
50
nargs:: Int
52
51
stmt_types:: Vector{Any}
53
52
# return type
@@ -73,11 +72,9 @@ type InferenceState
73
72
inworkq:: Bool
74
73
optimize:: Bool
75
74
inferred:: Bool
76
- tfunc_bp:: Union{TypeMapEntry, Void}
77
75
78
76
function InferenceState (linfo:: LambdaInfo , optimize:: Bool )
79
77
@assert isa (linfo. code,Array{Any,1 })
80
- linfo. inInference = true
81
78
nslots = length (linfo. slotnames)
82
79
nl = label_counter (linfo. code)+ 1
83
80
@@ -156,12 +153,12 @@ type InferenceState
156
153
inmodule = isdefined (linfo, :def ) ? linfo. def. module : current_module () # toplevel thunks are inferred in the current module
157
154
frame = new (
158
155
sp, nl, Dict {SSAValue, Bool} (), inmodule, 0 , false ,
159
- linfo, linfo, la, s, Union{}, W, n,
156
+ linfo, la, s, Union{}, W, n,
160
157
cur_hand, handler_at, n_handlers,
161
158
ssavalue_uses, ssavalue_init,
162
159
ObjectIdDict (), # Dict{InferenceState, Vector{LineNum}}(),
163
160
Vector {Tuple{InferenceState, Vector{LineNum}}} (),
164
- false , false , false , optimize, false , nothing )
161
+ false , false , false , optimize, false )
165
162
push! (active, frame)
166
163
nactive[] += 1
167
164
return frame
@@ -1387,25 +1384,25 @@ function newvar!(sv::InferenceState, typ)
1387
1384
end
1388
1385
1389
1386
# create a specialized LambdaInfo from a method
1390
- function specialize_method (method:: Method , types:: ANY , sp:: SimpleVector )
1391
- li = ccall (:jl_get_specialized , Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
1392
- return li
1387
+ function specialize_method (method:: Method , types:: ANY , sp:: SimpleVector , cached)
1388
+ if cached
1389
+ return ccall (:jl_specializations_get_linfo , Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
1390
+ else
1391
+ return ccall (:jl_get_specialized , Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
1392
+ end
1393
1393
end
1394
1394
1395
1395
# create copies of any field that type-inference might modify
1396
1396
function unshare_linfo! (li:: LambdaInfo )
1397
- if ! isa (li. code, Array{Any,1 })
1397
+ orig = li. def. lambda_template
1398
+ if isa (li. code, Array{UInt8,1 })
1398
1399
li. code = ccall (:jl_uncompress_ast , Any, (Any,Any), li, li. code)
1399
- else
1400
- li. code = copy_exprargs (li . code)
1400
+ elseif li . code === orig . code
1401
+ li. code = copy_exprargs (orig . code)
1401
1402
end
1402
- li. slotnames = copy (li. slotnames)
1403
- li. slotflags = copy (li. slotflags)
1404
- if isa (li. slottypes, Array)
1405
- li. slottypes = copy (li. slottypes)
1406
- end
1407
- if isa (li. ssavaluetypes, Array)
1408
- li. ssavaluetypes = copy (li. ssavaluetypes)
1403
+ if ! li. def. isstaged
1404
+ li. slotnames = copy (li. slotnames)
1405
+ li. slotflags = copy (li. slotflags)
1409
1406
end
1410
1407
return li
1411
1408
end
@@ -1414,9 +1411,11 @@ end
1414
1411
function typeinf_edge (method:: Method , atypes:: ANY , sparams:: SimpleVector , needtree:: Bool , optimize:: Bool , cached:: Bool , caller)
1415
1412
local code = nothing
1416
1413
local frame = nothing
1417
- # check cached specializations
1418
- # for an existing result stored there
1419
- if cached
1414
+ if isa (caller, LambdaInfo)
1415
+ code = caller
1416
+ elseif cached
1417
+ # check cached specializations
1418
+ # for an existing result stored there
1420
1419
if ! is (method. specializations, nothing )
1421
1420
code = ccall (:jl_specializations_lookup , Any, (Any, Any), method, atypes)
1422
1421
if isa (code, Void)
@@ -1436,89 +1435,80 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
1436
1435
code = nothing
1437
1436
end
1438
1437
end
1438
+ end
1439
1439
1440
- if isa (code, LambdaInfo) && code. inInference
1441
- # inference on this signature may be in progress,
1442
- # find the corresponding frame in the active list
1443
- for infstate in active
1444
- infstate === nothing && continue
1445
- infstate = infstate:: InferenceState
1446
- if code === infstate. linfo
1447
- frame = infstate
1448
- break
1440
+ if caller === nothing && in_typeinf_loop
1441
+ # if the caller needed the ast, but we are already in the typeinf loop
1442
+ # then just return early -- we can't fulfill this request
1443
+ # if the client was inlining, then this means we decided not to try to infer this
1444
+ # particular signature (due to signature coarsening in abstract_call_gf_by_type)
1445
+ # and attempting to force it now would be a bad idea (non terminating)
1446
+ skip = true
1447
+ if method. module == _topmod (method. module) || (isdefined (Main, :Base ) && method. module == Main. Base)
1448
+ # however, some gf have special tfunc and meaning they wouldn't have been inferred yet
1449
+ # check the same conditions from abstract_call to detect this case
1450
+ if method. name == :promote_type || method. name == :typejoin
1451
+ skip = false
1452
+ elseif method. name == :getindex || method. name == :next || method. name == :indexed_next
1453
+ argtypes = atypes. parameters
1454
+ if length (argtypes)> 2 && argtypes[3 ] ⊑ Int
1455
+ at2 = widenconst (argtypes[2 ])
1456
+ if (at2 <: Tuple ||
1457
+ (isa (at2, DataType) && isdefined (Main, :Base ) && isdefined (Main. Base, :Pair ) &&
1458
+ (at2:: DataType ). name === Main. Base. Pair. name))
1459
+ skip = false
1460
+ end
1449
1461
end
1450
1462
end
1451
1463
end
1464
+ if skip
1465
+ return (nothing , Union{}, false )
1466
+ end
1452
1467
end
1453
1468
1454
- if isa (caller, LambdaInfo)
1455
- code = caller
1456
- end
1457
-
1458
- if frame === nothing
1459
- # inference not started yet, make a new frame for a new lambda
1460
- # add lam to be inferred and record the edge
1461
-
1462
- if caller === nothing && in_typeinf_loop
1463
- # if the caller needed the ast, but we are already in the typeinf loop
1464
- # then just return early -- we can't fulfill this request
1465
- # if the client was inlining, then this means we decided not to try to infer this
1466
- # particular signature (due to signature coarsening in abstract_call_gf_by_type)
1467
- # and attempting to force it now would be a bad idea (non terminating)
1468
- skip = true
1469
- if method. module == _topmod (method. module) || (isdefined (Main, :Base ) && method. module == Main. Base)
1470
- # however, some gf have special tfunc and meaning they wouldn't have been inferred yet
1471
- # check the same conditions from abstract_call to detect this case
1472
- if method. name == :promote_type || method. name == :typejoin
1473
- skip = false
1474
- elseif method. name == :getindex || method. name == :next || method. name == :indexed_next
1475
- argtypes = atypes. parameters
1476
- if length (argtypes)> 2 && argtypes[3 ] ⊑ Int
1477
- at2 = widenconst (argtypes[2 ])
1478
- if (at2 <: Tuple ||
1479
- (isa (at2, DataType) && isdefined (Main, :Base ) && isdefined (Main. Base, :Pair ) &&
1480
- (at2:: DataType ). name === Main. Base. Pair. name))
1481
- skip = false
1482
- end
1483
- end
1484
- end
1485
- end
1486
- if skip
1487
- return (nothing , Union{}, false )
1488
- end
1469
+ if isa (code, LambdaInfo) && code. code != = nothing
1470
+ # reuse the existing code object
1471
+ linfo = code
1472
+ @assert typeseq (linfo. specTypes, atypes)
1473
+ elseif method. isstaged
1474
+ if ! isleaftype (atypes)
1475
+ # don't call staged functions on abstract types.
1476
+ # (see issues #8504, #10230)
1477
+ # we can't guarantee that their type behavior is monotonic.
1478
+ return (nothing , Any, false )
1479
+ end
1480
+ try
1481
+ # user code might throw errors – ignore them
1482
+ linfo = specialize_method (method, atypes, sparams, cached)
1483
+ catch
1484
+ return (nothing , Any, false )
1489
1485
end
1486
+ else
1487
+ linfo = specialize_method (method, atypes, sparams, cached)
1488
+ end
1490
1489
1491
- if isa (code, LambdaInfo) && code. code != = nothing
1492
- # reuse the existing code object
1493
- linfo = code
1494
- @assert typeseq (linfo. specTypes, atypes)
1495
- elseif method. isstaged
1496
- if ! isleaftype (atypes)
1497
- # don't call staged functions on abstract types.
1498
- # (see issues #8504, #10230)
1499
- # we can't guarantee that their type behavior is monotonic.
1500
- return (nothing , Any, false )
1501
- end
1502
- try
1503
- # user code might throw errors – ignore them
1504
- linfo = specialize_method (method, atypes, sparams)
1505
- catch
1506
- return (nothing , Any, false )
1490
+ if linfo. inInference
1491
+ # inference on this signature may be in progress,
1492
+ # find the corresponding frame in the active list
1493
+ for infstate in active
1494
+ infstate === nothing && continue
1495
+ infstate = infstate:: InferenceState
1496
+ if linfo === infstate. linfo
1497
+ frame = infstate
1498
+ break
1507
1499
end
1508
- else
1509
- linfo = specialize_method (method, atypes, sparams)
1510
1500
end
1511
- # our stack frame inference context
1501
+ # TODO : this assertion seems iffy
1502
+ assert (frame != = nothing )
1503
+ else
1504
+ # inference not started yet, make a new frame for a new lambda
1505
+ linfo. inInference = true
1512
1506
frame = InferenceState (unshare_linfo! (linfo:: LambdaInfo ), optimize)
1513
- if cached
1514
- frame. tfunc_bp = ccall (:jl_specializations_insert , Ref{TypeMapEntry}, (Any, Any, Any), method, atypes, linfo)
1515
- end
1516
1507
end
1517
1508
frame = frame:: InferenceState
1518
1509
1519
- if ! isa (caller, Void) && ! isa (caller, LambdaInfo)
1520
- # if we were called from inside inference,
1521
- # the caller will be the InferenceState object
1510
+ if isa (caller, InferenceState)
1511
+ # if we were called from inside inference, the caller will be the InferenceState object
1522
1512
# for which the edge was required
1523
1513
caller = caller:: InferenceState
1524
1514
if haskey (caller. edges, frame)
@@ -1554,26 +1544,30 @@ function typeinf_ext(linfo::LambdaInfo)
1554
1544
if isdefined (linfo, :def )
1555
1545
# method lambda - infer this specialization via the method cache
1556
1546
(code, _t, _) = typeinf_edge (linfo. def, linfo. specTypes, linfo. sparam_vals, true , true , true , linfo)
1557
- if code. inferred
1547
+ if code. inferred && linfo != = code
1548
+ # This case occurs when the IR for a function has been deleted.
1549
+ # `code` will be a newly-created LambdaInfo, and we need to copy its
1550
+ # contents to the existing one to copy the info to the method cache.
1558
1551
linfo. inferred = true
1559
1552
linfo. inInference = false
1560
- if linfo != = code
1561
- linfo. code = code. code
1562
- linfo. slotnames = code. slotnames
1563
- linfo. slottypes = code. slottypes
1564
- linfo. slotflags = code. slotflags
1565
- linfo. ssavaluetypes = code. ssavaluetypes
1566
- linfo. rettype = code. rettype
1567
- linfo. pure = code. pure
1568
- end
1569
- end
1553
+ linfo. code = code . code
1554
+ linfo. slotnames = code. slotnames
1555
+ linfo. slottypes = code. slottypes
1556
+ linfo. slotflags = code. slotflags
1557
+ linfo. ssavaluetypes = code. ssavaluetypes
1558
+ linfo. rettype = code. rettype
1559
+ linfo. pure = code. pure
1560
+ linfo. inlineable = code. inlineable
1561
+ end
1562
+ return code
1570
1563
else
1571
1564
# toplevel lambda - infer directly
1565
+ linfo. inInference = true
1572
1566
frame = InferenceState (linfo, true )
1573
1567
typeinf_loop (frame)
1574
1568
@assert frame. inferred # TODO : deal with this better
1569
+ return linfo
1575
1570
end
1576
- nothing
1577
1571
end
1578
1572
1579
1573
@@ -1947,20 +1941,6 @@ function finish(me::InferenceState)
1947
1941
end
1948
1942
me. linfo. rettype = me. bestguess
1949
1943
1950
- if me. destination != = me. linfo
1951
- out = me. destination
1952
- out. inferred = true
1953
- out. inInference = false
1954
- out. code = me. linfo. code
1955
- out. slotnames = me. linfo. slotnames
1956
- out. slottypes = me. linfo. slottypes
1957
- out. slotflags = me. linfo. slotflags
1958
- out. ssavaluetypes = me. linfo. ssavaluetypes
1959
- out. rettype = me. linfo. rettype
1960
- out. pure = me. linfo. pure
1961
- out. inlineable = me. linfo. inlineable
1962
- end
1963
-
1964
1944
# lazy-delete the item from active for several reasons:
1965
1945
# efficiency, correctness, and recursion-safety
1966
1946
nactive[] -= 1
0 commit comments