@@ -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