@@ -67,6 +67,11 @@ using Base: specializations
67
67
@test success (run (` $(Base. julia_cmd ()) --project=$(joinpath (@__DIR__ , " PC_D" )) -e $script 1` ))
68
68
Pkg. activate (projfile)
69
69
70
+ preffile = joinpath (@__DIR__ , " PC_D" , " LocalPreferences.toml" )
71
+ if isfile (preffile)
72
+ rm (preffile)
73
+ end
74
+
70
75
oldval = PrecompileTools. verbose[]
71
76
PrecompileTools. verbose[] = true
72
77
mktemp () do path, io
@@ -85,27 +90,28 @@ using Base: specializations
85
90
# Mimic the format written to `_jl_debug_method_invalidation`
86
91
# As a source of MethodInstances, `getproperty` has lots
87
92
m = which (getproperty, (Any, Symbol))
88
- mis = Core. MethodInstance[]
93
+ mis, cis = Core. MethodInstance[], Core . CodeInstance []
89
94
for mi in specializations (m)
90
- length (mis ) >= 10 && break
95
+ length (cis ) >= 10 && break
91
96
mi === nothing && continue
92
97
push! (mis, mi)
98
+ isdefined (mi, :cache ) && push! (cis, mi. cache)
93
99
end
94
- # These mimic the invalidation lists in SnoopCompile's `test/snoopr.jl`
100
+ # These mimic the format of the logs produced by `jl_debug_method_invalidation` (both variants)
95
101
invs = Any[mis[1 ], 0 , mis[2 ], 1 , Tuple{}, m, " jl_method_table_insert" ]
96
- @test PrecompileTools. invalidation_leaves (invs) == Set ([mis[2 ]])
102
+ @test PrecompileTools. invalidation_leaves (invs, [] ) == Set ([mis[2 ]])
97
103
invs = Any[mis[1 ], 0 , mis[2 ], 1 , mis[3 ], 1 , Tuple{}, m, " jl_method_table_insert" ]
98
- @test PrecompileTools. invalidation_leaves (invs) == Set ([mis[2 ], mis[3 ]])
104
+ @test PrecompileTools. invalidation_leaves (invs, [] ) == Set ([mis[2 ], mis[3 ]])
99
105
invs = Any[mis[1 ], 0 , mis[2 ], 1 , Tuple{}, mis[1 ], 1 , mis[3 ], " jl_method_table_insert" , m, " jl_method_table_insert" ]
100
- @test PrecompileTools. invalidation_leaves (invs) == Set (mis[1 : 3 ])
106
+ @test PrecompileTools. invalidation_leaves (invs, [] ) == Set (mis[1 : 3 ])
101
107
invs = Any[mis[1 ], 1 , mis[2 ], " jl_method_table_disable" , m, " jl_method_table_disable" ]
102
- @test PrecompileTools. invalidation_leaves (invs) == Set ([mis[1 ], mis[2 ]])
108
+ @test PrecompileTools. invalidation_leaves (invs, [] ) == Set ([mis[1 ], mis[2 ]])
103
109
invs = Any[mis[1 ], 1 , mis[2 ], " jl_method_table_disable" , mis[3 ], " jl_method_table_insert" , m]
104
- @test Set ([mis[1 ], mis[2 ]]) ⊆ PrecompileTools. invalidation_leaves (invs)
110
+ @test Set ([mis[1 ], mis[2 ]]) ⊆ PrecompileTools. invalidation_leaves (invs, [] )
105
111
invs = Any[mis[1 ], 1 , mis[2 ], " jl_method_table_insert" , mis[2 ], " invalidate_mt_cache" , m, " jl_method_table_insert" ]
106
- @test PrecompileTools. invalidation_leaves (invs) == Set ([mis[1 ], mis[2 ]])
107
- invs = Any[Tuple{}, " insert_backedges_callee" , 55 , Any[m], mis[ 2 ], " verify_methods" , 55 ]
108
- @test PrecompileTools. invalidation_leaves (invs) == Set ([mis[ 2 ]] )
112
+ @test PrecompileTools. invalidation_leaves (invs, [] ) == Set ([mis[1 ], mis[2 ]])
113
+ invs = Any[m, " method_globalref " , cis[ 1 ], nothing , Tuple{}, " insert_backedges_callee" , cis[ 2 ] , Any[m], cis[ 3 ], " verify_methods" , cis[ 4 ] ]
114
+ @test PrecompileTools. invalidation_leaves ([], invs) == Set (Core . Compiler . get_ci_mi .(cis[ 1 : 3 ]) )
109
115
110
116
# Coverage isn't on during package precompilation, so let's test a few things here
111
117
PrecompileTools. precompile_mi (mis[1 ])
@@ -115,6 +121,7 @@ using Base: specializations
115
121
mktempdir () do dir
116
122
push! (LOAD_PATH , dir)
117
123
cd (dir) do
124
+ # Method insertion invalidations
118
125
for ((pkg1, pkg2, pkg3), recompile) in (((" RC_A" , " RC_B" , " RC_C" ), false ,),
119
126
((" RC_D" , " RC_E" , " RC_F" ), true ))
120
127
Pkg. generate (pkg1)
@@ -174,6 +181,73 @@ using Base: specializations
174
181
wc = Base. get_world_counter ()
175
182
@test recompile ? mi. cache. max_world >= wc : mi. cache. max_world < wc
176
183
end
184
+
185
+ # Edge-invalidation
186
+ for ((pkg1, pkg2, pkg3), recompile) in (((" RC_G" , " RC_H" , " RC_I" ), false ,),
187
+ ((" RC_J" , " RC_K" , " RC_L" ), true ))
188
+ Pkg. generate (pkg1)
189
+ open (joinpath (dir, pkg1, " src" , pkg1* " .jl" ), " w" ) do io
190
+ println (io, """
191
+ module $pkg1
192
+ nbits(::Int8) = 8
193
+ nbits(::Int16) = 16
194
+ end
195
+ """ )
196
+ end
197
+ Pkg. generate (pkg2)
198
+ Pkg. activate (joinpath (dir, pkg2))
199
+ Pkg. develop (PackageSpec (path= joinpath (dir, pkg1)))
200
+ open (joinpath (dir, pkg2, " src" , pkg2* " .jl" ), " w" ) do io
201
+ println (io, """
202
+ module $pkg2
203
+ using $pkg1
204
+ call_nbits(c) = $pkg1 .nbits(only(c))
205
+ begin
206
+ Base.Experimental.@force_compile
207
+ call_nbits(Any[Int8(5)])
208
+ end
209
+ end
210
+ """ )
211
+ end
212
+ Pkg. generate (pkg3)
213
+ Pkg. activate (joinpath (dir, pkg3))
214
+ Pkg. develop (PackageSpec (path= joinpath (dir, pkg1)))
215
+ Pkg. develop (PackageSpec (path= joinpath (dir, pkg2)))
216
+ Pkg. develop (PackageSpec (path= dirname (@__DIR__ ))) # depend on PrecompileTools
217
+ open (joinpath (dir, pkg3, " src" , pkg3* " .jl" ), " w" ) do io
218
+ if recompile
219
+ println (io, """
220
+ module $pkg3
221
+ using PrecompileTools
222
+ @recompile_invalidations begin
223
+ using $pkg1
224
+ $pkg1 .nbits(::Int32) = 32 # This will cause an edge invalidation
225
+ using $pkg2
226
+ end
227
+ end
228
+ """ )
229
+ else
230
+ println (io, """
231
+ module $pkg3
232
+ using PrecompileTools
233
+ using $pkg1
234
+ $pkg1 .nbits(::Int32) = 32 # This will cause an edge invalidation
235
+ using $pkg2
236
+ end
237
+ """ )
238
+ end
239
+ end
240
+
241
+ @eval using $ (Symbol (pkg3))
242
+ mod3 = Base. @invokelatest getglobal (@__MODULE__ , Symbol (pkg3))
243
+ mod2 = Base. @invokelatest getglobal (mod3, Symbol (pkg2))
244
+ mod1 = Base. @invokelatest getglobal (mod2, Symbol (pkg1))
245
+ m = only (methods (mod2. call_nbits))
246
+ mi = first (specializations (m))
247
+ wc = Base. get_world_counter ()
248
+ @test recompile ? mi. cache. max_world >= wc : mi. cache. max_world < wc
249
+ end
250
+
177
251
end
178
252
pop! (LOAD_PATH )
179
253
end
0 commit comments