@@ -15,7 +15,7 @@ function nonoverlay end
1515
1616@nospecialize
1717cassette_overlay_error () = error (" CassetteOverlay is available via `@overlaypass` macro" )
18- methodtable (:: Type{<:OverlayPass} ) = cassette_overlay_error ()
18+ methodtable (:: UInt , :: Type{<:OverlayPass} ) = cassette_overlay_error ()
1919getpass (args... ; kwargs... ) = cassette_overlay_error ()
2020nonoverlay (args... ; kwargs... ) = cassette_overlay_error ()
2121@specialize
@@ -54,7 +54,14 @@ function generate_overlay_src(world::UInt, source::SourceType, passtype, fargtyp
5454 selfname:: Symbol , fargsname:: Symbol )
5555 @nospecialize passtype fargtypes
5656 tt = Base. to_tuple_type (fargtypes)
57- match = Base. _which (tt; method_table= methodtable (passtype), raise= false , world)
57+ mt_worlds = methodtable (world, passtype)
58+ if mt_worlds isa Pair
59+ method_table, worlds = mt_worlds
60+ else
61+ method_table = mt_worlds
62+ worlds = nothing
63+ end
64+ match = Base. _which (tt; method_table, raise= false , world)
5865 match === nothing && return nothing # method match failed – the fallback implementation will raise a proper MethodError
5966 mi = Core. Compiler. specialize_method (match)
6067 src = Core. Compiler. retrieve_code_info (mi, world)
@@ -68,6 +75,9 @@ function generate_overlay_src(world::UInt, source::SourceType, passtype, fargtyp
6875 push! (invalid_code, (world, source, passtype, fargtypes, src, selfname, fargsname))
6976 # TODO `return nothing` when updating the minimum compat to 1.12
7077 end
78+ if worlds != = nothing
79+ src. min_world, src. max_world = max (src. min_world, first (worlds)), min (src. max_world, last (worlds))
80+ end
7181 return src
7282end
7383
@@ -92,7 +102,7 @@ macro overlaypass(args...)
92102 nonoverlaytype = typeof (CassetteOverlay. nonoverlay)
93103
94104 if method_table != = :nothing
95- mthd_tbl = :($ CassetteOverlay. methodtable (:: Type{$PassName} ) = $ (esc (method_table)))
105+ mthd_tbl = :($ CassetteOverlay. methodtable (:: UInt , :: Type{$PassName} ) = $ (esc (method_table)))
96106 else
97107 mthd_tbl = nothing
98108 end
@@ -153,14 +163,34 @@ macro overlaypass(args...)
153163 end
154164end
155165
166+ function isconst_at_world (m:: Module , var:: Symbol , world:: UInt )
167+ bpart = Base. lookup_binding_partition (world, GlobalRef (m, var))
168+ kind = Base. binding_kind (bpart)
169+ return Base. is_defined_const_binding (kind)
170+ end
171+
172+ function getglobal_at_world (m:: Module , var:: Symbol , world:: UInt )
173+ b = @ccall jl_get_binding (m:: Any , var:: Any ):: Any
174+ bp = Base. lookup_binding_partition (world, b)
175+ val_ptr = @ccall jl_get_binding_value_in_world (b:: Any , world:: Csize_t ):: Ptr{Any}
176+ if val_ptr == C_NULL
177+ throw (ccall (:jl_new_struct , Any, (Any, Any... ), UndefVarError, var, world, m))
178+ end
179+ return Pair {Any,UnitRange{UInt}} (unsafe_pointer_to_objref (val_ptr), bp. min_world: bp. max_world)
180+ end
181+
156182abstract type AbstractBindingOverlay{M, S} <: OverlayPass ; end
157- function methodtable (:: Type{<:AbstractBindingOverlay{M, S}} ) where {M, S}
183+ function methodtable (world :: UInt , :: Type{<:AbstractBindingOverlay{M, S}} ) where {M, S}
158184 if M === nothing
159185 return nothing
160186 end
161- @assert @invokelatest isconst (M, S)
162- mt = @invokelatest getglobal (M, S)
163- return mt:: MethodTable
187+ @static if VERSION ≥ v " 1.12-"
188+ @assert isconst_at_world (M, S, world)
189+ return getglobal_at_world (M, S, world)
190+ else
191+ @assert @invokelatest isconst (M, S)
192+ return getglobal (M, S):: MethodTable
193+ end
164194end
165195@overlaypass AbstractBindingOverlay nothing
166196
0 commit comments