@@ -74,6 +74,10 @@ mutable struct InstanceNode
74
74
end
75
75
end
76
76
77
+ Core. MethodInstance (node:: InstanceNode ) = node. mi
78
+ Base. convert (:: Type{MethodInstance} , node:: InstanceNode ) = node. mi
79
+ AbstractTrees. children (node:: InstanceNode ) = node. children
80
+
77
81
function getroot (node:: InstanceNode )
78
82
while isdefined (node, :parent )
79
83
node = node. parent
133
137
struct MethodInvalidations
134
138
method:: Method
135
139
reason:: Symbol # :inserting or :deleting
136
- mt_backedges:: Vector{Pair{Any,InstanceNode}} # sig=>root
140
+ mt_backedges:: Vector{Pair{Any,Union{ InstanceNode,MethodInstance} }} # sig=>root
137
141
backedges:: Vector{InstanceNode}
138
142
mt_cache:: Vector{MethodInstance}
139
143
mt_disable:: Vector{MethodInstance}
145
149
146
150
Base. isempty (methinvs:: MethodInvalidations ) = isempty (methinvs. mt_backedges) && isempty (methinvs. backedges) # ignore mt_cache
147
151
148
- countchildren (sigtree:: Pair{<:Any,InstanceNode} ) = countchildren (sigtree. second)
152
+ countchildren (sigtree:: Pair{<:Any,Union{InstanceNode,MethodInstance}} ) = countchildren (sigtree. second)
153
+ countchildren (:: MethodInstance ) = 1
149
154
150
155
function countchildren (methinvs:: MethodInvalidations )
151
156
n = 0
@@ -179,7 +184,15 @@ function Base.show(io::IO, methinvs::MethodInvalidations)
179
184
sig = nothing
180
185
if isa (root, Pair)
181
186
print (io, " signature " )
182
- printstyled (io, root. first, color = :light_cyan )
187
+ sig = root. first
188
+ if isa (sig, MethodInstance)
189
+ # "insert_backedges_callee"/"insert_backedges" (delayed) invalidations
190
+ printstyled (io, which (sig. specTypes), color = :light_cyan )
191
+ print (io, " (formerly " , sig. def, ' )' )
192
+ else
193
+ # `sig` (immediate) invalidations
194
+ printstyled (io, sig, color = :light_cyan )
195
+ end
183
196
print (io, " triggered " )
184
197
sig = root. first
185
198
root = root. second
@@ -189,7 +202,7 @@ function Base.show(io::IO, methinvs::MethodInvalidations)
189
202
print (io, " with " )
190
203
sig = root. mi. def. sig
191
204
end
192
- printstyled (io, root. mi , color = :light_yellow )
205
+ printstyled (io, convert (MethodInstance, root) , color = :light_yellow )
193
206
print (io, " (" , countchildren (root), " children)" )
194
207
if iscompact
195
208
i < n && print (io, " , " )
@@ -275,7 +288,29 @@ function invalidation_trees(list; exclude_corecompiler::Bool=true)
275
288
return reason
276
289
end
277
290
291
+ function handle_insert_backedges (list, i, callee)
292
+ ncovered = 0
293
+ while length (list) >= i+ 2 && list[i+ 2 ] == " insert_backedges_callee"
294
+ if isa (callee, Type)
295
+ newcallee = list[i+ 1 ]
296
+ if isa (newcallee, MethodInstance)
297
+ callee = newcallee
298
+ end
299
+ end
300
+ i += 2
301
+ end
302
+ while length (list) >= i+ 2 && list[i+ 2 ] == " insert_backedges"
303
+ caller = list[i+= 1 ]
304
+ i += 1
305
+ push! (delayed, callee => caller)
306
+ ncovered += 1
307
+ end
308
+ @assert ncovered > 0
309
+ return i
310
+ end
311
+
278
312
methodinvs = MethodInvalidations[]
313
+ delayed = Pair{Any,MethodInstance}[] # from "insert_backedges" invalidations
279
314
leaf = nothing
280
315
mt_backedges, backedges, mt_cache, mt_disable = methinv_storage ()
281
316
reason = nothing
@@ -320,8 +355,13 @@ function invalidation_trees(list; exclude_corecompiler::Bool=true)
320
355
end
321
356
leaf = nothing
322
357
end
358
+ elseif loctag == " insert_backedges_callee"
359
+ i = handle_insert_backedges (list, i, mi)
323
360
elseif loctag == " insert_backedges"
361
+ # pre Julia 1.8
324
362
println (" insert_backedges for " , mi)
363
+ Base. VERSION < v " 1.8.0-DEV" || error (" unexpected failure at " , i)
364
+ @assert leaf === nothing
325
365
else
326
366
error (" unexpected loctag " , loctag, " at " , i)
327
367
end
@@ -348,17 +388,51 @@ function invalidation_trees(list; exclude_corecompiler::Bool=true)
348
388
leaf = nothing
349
389
reason = nothing
350
390
elseif isa (item, Type)
351
- root = getroot (leaf)
352
- if ! exclude_corecompiler || ! from_corecompiler (root. mi)
353
- push! (mt_backedges, item=> root)
391
+ if length (list) > i && list[i+ 1 ] == " insert_backedges_callee"
392
+ i = handle_insert_backedges (list, i+ 1 , item)
393
+ else
394
+ root = getroot (leaf)
395
+ if ! exclude_corecompiler || ! from_corecompiler (root. mi)
396
+ push! (mt_backedges, item=> root)
397
+ end
398
+ leaf = nothing
354
399
end
355
- leaf = nothing
356
400
elseif isa (item, Core. TypeMapEntry) && list[i+ 1 ] == " invalidate_mt_cache"
357
401
i += 1
358
402
else
359
403
error (" unexpected item " , item, " at " , i)
360
404
end
361
405
end
406
+ @assert all (isempty, Any[mt_backedges, backedges, #= mt_cache, =# mt_disable])
407
+ # Handle the delayed invalidations
408
+ callee2idx = Dict {Method,Int} ()
409
+ for (i, methinvs) in enumerate (methodinvs)
410
+ for (sig, root) in methinvs. mt_backedges
411
+ for node in PreOrderDFS (root)
412
+ callee2idx[MethodInstance (node). def] = i
413
+ end
414
+ end
415
+ for root in methinvs. backedges
416
+ for node in PreOrderDFS (root)
417
+ callee2idx[MethodInstance (node). def] = i
418
+ end
419
+ end
420
+ end
421
+ trouble = similar (delayed, 0 )
422
+ for (callee, caller) in delayed
423
+ if isa (callee, MethodInstance)
424
+ idx = get (callee2idx, callee. def, nothing )
425
+ if idx != = nothing
426
+ push! (methodinvs[idx]. mt_backedges, callee => caller)
427
+ continue
428
+ end
429
+ end
430
+ push! (trouble, callee => caller)
431
+ end
432
+ if ! isempty (trouble)
433
+ @warn " Could not attribute the following delayed invalidations:"
434
+ display (trouble)
435
+ end
362
436
return sort! (methodinvs; by= countchildren)
363
437
end
364
438
@@ -402,7 +476,8 @@ function filtermod(mod::Module, methinvs::MethodInvalidations; recursive::Bool=f
402
476
end
403
477
mt_backedges = filter (pr-> hasmod (mod, pr. second), methinvs. mt_backedges)
404
478
backedges = filter (root-> hasmod (mod, root), methinvs. backedges)
405
- return MethodInvalidations (methinvs. method, methinvs. reason, mt_backedges, backedges, copy (methinvs. mt_cache), copy (methinvs. mt_disable))
479
+ return MethodInvalidations (methinvs. method, methinvs. reason, mt_backedges, backedges,
480
+ copy (methinvs. mt_cache), copy (methinvs. mt_disable))
406
481
end
407
482
408
483
function filtermod (mod:: Module , node:: InstanceNode )
@@ -428,6 +503,14 @@ function filtermod(mod::Module, node::InstanceNode)
428
503
return nothing
429
504
end
430
505
506
+ function filtermod (mod:: Module , mi:: MethodInstance )
507
+ m = mi. def
508
+ if isa (m, Method)
509
+ return m. module == mod ? mi : nothing
510
+ end
511
+ return m == mod ? mi : nothing
512
+ end
513
+
431
514
"""
432
515
methinvs = findcaller(method::Method, trees)
433
516
@@ -491,12 +574,14 @@ function findcaller(meth::Method, methinvs::MethodInvalidations)
491
574
for (sig, node) in methinvs. mt_backedges
492
575
ret = findcaller (meth, node)
493
576
ret === nothing && continue
494
- return MethodInvalidations (methinvs. method, methinvs. reason, [Pair {Any,InstanceNode} (sig, newtree (ret))], InstanceNode[], copy (methinvs. mt_cache), copy (methinvs. mt_disable))
577
+ return MethodInvalidations (methinvs. method, methinvs. reason, [Pair {Any,InstanceNode} (sig, newtree (ret))], InstanceNode[],
578
+ copy (methinvs. mt_cache), copy (methinvs. mt_disable))
495
579
end
496
580
for node in methinvs. backedges
497
581
ret = findcaller (meth, node)
498
582
ret === nothing && continue
499
- return MethodInvalidations (methinvs. method, methinvs. reason, Pair{Any,InstanceNode}[], [newtree (ret)], copy (methinvs. mt_cache), copy (methinvs. mt_disable))
583
+ return MethodInvalidations (methinvs. method, methinvs. reason, Pair{Any,InstanceNode}[], [newtree (ret)],
584
+ copy (methinvs. mt_cache), copy (methinvs. mt_disable))
500
585
end
501
586
return nothing
502
587
end
@@ -513,6 +598,8 @@ function findcaller(meth::Method, node::InstanceNode)
513
598
return nothing
514
599
end
515
600
601
+ findcaller (meth:: Method , mi:: MethodInstance ) = mi. def == meth ? mi : nothing
602
+
516
603
# Cthulhu integration
517
604
518
605
Cthulhu. backedges (node:: InstanceNode ) = sort (node. children; by= countchildren, rev= true )
0 commit comments