@@ -113,33 +113,55 @@ function invalidate_method_for_globalref!(gr::GlobalRef, method::Method, invalid
113113 end
114114end
115115
116- function invalidate_code_for_globalref! (b:: Core.Binding , invalidated_bpart:: Core.BindingPartition , new_bpart:: Union{Core.BindingPartition, Nothing} , new_max_world:: UInt )
116+ export_affecting_partition_flags (bpart:: Core.BindingPartition ) =
117+ ((bpart. kind & PARTITION_MASK_KIND) == PARTITION_KIND_GUARD,
118+ (bpart. kind & PARTITION_FLAG_EXPORTED) != 0 ,
119+ (bpart. kind & PARTITION_FLAG_DEPRECATED) != 0 )
120+
121+ function invalidate_code_for_globalref! (b:: Core.Binding , invalidated_bpart:: Core.BindingPartition , new_bpart:: Core.BindingPartition , new_max_world:: UInt )
117122 gr = b. globalref
118- if (b. flags & BINDING_FLAG_ANY_IMPLICIT_EDGES) != 0
119- foreach_module_mtable (gr. mod, new_max_world) do mt:: Core.MethodTable
120- for method in MethodList (mt)
121- invalidate_method_for_globalref! (gr, method, invalidated_bpart, new_max_world)
123+
124+ (_, (ib, ibpart)) = Compiler. walk_binding_partition (b, invalidated_bpart, new_max_world)
125+ (_, (nb, nbpart)) = Compiler. walk_binding_partition (b, new_bpart, new_max_world+ 1 )
126+
127+ # abstract_eval_globalref_partition is the maximum amount of information that inference
128+ # reads from a binding partition. If this information does not change - we do not need to
129+ # invalidate any code that inference created, because we know that the result will not change.
130+ need_to_invalidate_code =
131+ Compiler. abstract_eval_globalref_partition (nothing , ib, ibpart) != =
132+ Compiler. abstract_eval_globalref_partition (nothing , nb, nbpart)
133+
134+ need_to_invalidate_export = export_affecting_partition_flags (invalidated_bpart) != =
135+ export_affecting_partition_flags (new_bpart)
136+
137+ if need_to_invalidate_code
138+ if (b. flags & BINDING_FLAG_ANY_IMPLICIT_EDGES) != 0
139+ foreach_module_mtable (gr. mod, new_max_world) do mt:: Core.MethodTable
140+ for method in MethodList (mt)
141+ invalidate_method_for_globalref! (gr, method, invalidated_bpart, new_max_world)
142+ end
143+ return true
122144 end
123- return true
124145 end
125- end
126- if isdefined (b, : backedges)
127- for edge in b . backedges
128- if isa ( edge, CodeInstance )
129- ccall ( :jl_invalidate_code_instance , Cvoid, (Any, UInt), edge, new_max_world )
130- elseif isa (edge, Core . Binding)
131- isdefined (edge, :partitions ) || continue
132- latest_bpart = edge . partitions
133- latest_bpart . max_world == typemax (UInt ) || continue
134- is_some_imported ( binding_kind ( latest_bpart)) || continue
135- partition_restriction (latest_bpart) === b || continue
136- invalidate_code_for_globalref! (edge, latest_bpart, nothing , new_max_world)
137- else
138- invalidate_method_for_globalref! (gr, edge :: Method , invalidated_bpart, new_max_world)
146+ if isdefined (b, :backedges )
147+ for edge in b . backedges
148+ if isa (edge, CodeInstance)
149+ ccall ( :jl_invalidate_code_instance , Cvoid, (Any, UInt), edge, new_max_world )
150+ elseif isa ( edge, Core . Binding )
151+ isdefined (edge, :partitions ) || continue
152+ latest_bpart = edge . partitions
153+ latest_bpart. max_world == typemax (UInt) || continue
154+ is_some_imported ( binding_kind (latest_bpart) ) || continue
155+ partition_restriction ( latest_bpart) === b || continue
156+ invalidate_code_for_globalref! (edge, latest_bpart, latest_bpart, new_max_world)
157+ else
158+ invalidate_method_for_globalref! (gr, edge :: Method , invalidated_bpart, new_max_world)
159+ end
139160 end
140161 end
141162 end
142- if (invalidated_bpart. kind & PARTITION_FLAG_EXPORTED != 0 ) || (new_bpart != = nothing && (new_bpart. kind & PARTITION_FLAG_EXPORTED != 0 ))
163+
164+ if need_to_invalidate_code || need_to_invalidate_export
143165 # This binding was exported - we need to check all modules that `using` us to see if they
144166 # have a binding that is affected by this change.
145167 usings_backedges = ccall (:jl_get_module_usings_backedges , Any, (Any,), gr. mod)
@@ -151,8 +173,12 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core
151173 latest_bpart = user_binding. partitions
152174 latest_bpart. max_world == typemax (UInt) || continue
153175 binding_kind (latest_bpart) in (PARTITION_KIND_IMPLICIT, PARTITION_KIND_FAILED, PARTITION_KIND_GUARD) || continue
154- @atomic :release latest_bpart. max_world = new_max_world
155- invalidate_code_for_globalref! (convert (Core. Binding, user_binding), latest_bpart, nothing , new_max_world)
176+ new_bpart = need_to_invalidate_export ?
177+ ccall (:jl_maybe_reresolve_implicit , Any, (Any, Any, Csize_t), user_binding, latest_bpart, new_max_world) :
178+ latest_bpart
179+ if need_to_invalidate_code || new_bpart != = latest_bpart
180+ invalidate_code_for_globalref! (convert (Core. Binding, user_binding), latest_bpart, new_bpart, new_max_world)
181+ end
156182 end
157183 end
158184 end
0 commit comments