diff --git a/Compiler/test/inference.jl b/Compiler/test/inference.jl index fb17f1991dc45..a4294e2e45f6b 100644 --- a/Compiler/test/inference.jl +++ b/Compiler/test/inference.jl @@ -6291,3 +6291,10 @@ end <: Bool @test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs Core.get_binding_type(m, n, xs...) end <: Type + +# issue #59269 +function haskey_inference_test() + kwargs = Core.compilerbarrier(:const, Base.pairs((; item = false))) + return haskey(kwargs, :item) ? nothing : Any[] +end +@inferred haskey_inference_test() diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 598b618f0d1ed..c4c65504be424 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -520,14 +520,17 @@ function triplet(p::AbstractPlatform) ) # Tack on optional compiler ABI flags - if libgfortran_version(p) !== nothing - str = string(str, "-libgfortran", libgfortran_version(p).major) + libgfortran_version_ = libgfortran_version(p) + if libgfortran_version_ !== nothing + str = string(str, "-libgfortran", libgfortran_version_.major) end - if cxxstring_abi(p) !== nothing - str = string(str, "-", cxxstring_abi(p)) + cxxstring_abi_ = cxxstring_abi(p) + if cxxstring_abi_ !== nothing + str = string(str, "-", cxxstring_abi_) end - if libstdcxx_version(p) !== nothing - str = string(str, "-libstdcxx", libstdcxx_version(p).patch) + libstdcxx_version_ = libstdcxx_version(p) + if libstdcxx_version_ !== nothing + str = string(str, "-libstdcxx", libstdcxx_version_.patch) end # Tack on all extra tags diff --git a/base/essentials.jl b/base/essentials.jl index bf48f24f5234c..b817e53ec6c4d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -489,9 +489,9 @@ end Pairs{K, V, I, A}(data, itr) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :(data isa A ? data : convert(A, data)), :(itr isa I ? itr : convert(I, itr)))) Pairs{K, V}(data::A, itr::I) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :data, :itr)) Pairs{K}(data::A, itr::I) where {K, I, A} = $(Expr(:new, :(Pairs{K, eltype(A), I, A}), :data, :itr)) - Pairs(data::A, itr::I) where {I, A} = $(Expr(:new, :(Pairs{eltype(I), eltype(A), I, A}), :data, :itr)) + Pairs(data::A, itr::I) where {I, A} = $(Expr(:new, :(Pairs{I !== Nothing ? eltype(I) : keytype(A), eltype(A), I, A}), :data, :itr)) end -pairs(::Type{NamedTuple}) = Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} where {V, N, names, T<:NTuple{N, Any}} +pairs(::Type{NamedTuple}) = Pairs{Symbol, V, Nothing, NT} where {V, NT <: NamedTuple} """ Base.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)} diff --git a/base/idset.jl b/base/idset.jl index 95c9bf784f557..2d71898ab1c3a 100644 --- a/base/idset.jl +++ b/base/idset.jl @@ -10,6 +10,9 @@ IdSet{T}() constructs a set (see [`Set`](@ref)) using In the example below, the values are all `isequal` so they get overwritten in the ordinary `Set`. The `IdSet` compares by `===` and so preserves the 3 different values. +!!! compat "Julia 1.11" + Exported in Julia 1.11 and later. + # Examples ```jldoctest; filter = r"\\n\\s*(1|1\\.0|true)" julia> Set(Any[true, 1, 1.0]) diff --git a/base/invalidation.jl b/base/invalidation.jl index b55b09e29961d..4132231d9e852 100644 --- a/base/invalidation.jl +++ b/base/invalidation.jl @@ -155,9 +155,7 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core latest_bpart = user_binding.partitions latest_bpart.max_world == typemax(UInt) || continue is_some_implicit(binding_kind(latest_bpart)) || continue - new_bpart = need_to_invalidate_export ? - ccall(:jl_maybe_reresolve_implicit, Any, (Any, Csize_t), user_binding, new_max_world) : - latest_bpart + new_bpart = ccall(:jl_maybe_reresolve_implicit, Any, (Any, Csize_t), user_binding, new_max_world) if need_to_invalidate_code || new_bpart !== latest_bpart push!(queued_bindings, (convert(Core.Binding, user_binding), latest_bpart, new_bpart)) end diff --git a/base/iterators.jl b/base/iterators.jl index 29473561c452a..f7ae8138f6856 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -267,7 +267,7 @@ pairs(::IndexLinear, A::AbstractArray) = Pairs(A, LinearIndices(A)) # preserve indexing capabilities for known indexable types # faster than zip(keys(a), values(a)) for arrays pairs(tuple::Tuple) = Pairs{Int}(tuple, keys(tuple)) -pairs(nt::NamedTuple) = Pairs{Symbol}(nt, keys(nt)) +pairs(nt::NamedTuple) = Pairs{Symbol}(nt, nothing) pairs(v::Core.SimpleVector) = Pairs(v, LinearIndices(v)) pairs(A::AbstractVector) = pairs(IndexLinear(), A) # pairs(v::Pairs) = v # listed for reference, but already defined from being an AbstractDict @@ -275,40 +275,40 @@ pairs(A::AbstractVector) = pairs(IndexLinear(), A) pairs(::IndexCartesian, A::AbstractArray) = Pairs(A, Base.CartesianIndices(axes(A))) pairs(A::AbstractArray) = pairs(IndexCartesian(), A) -length(v::Pairs) = length(getfield(v, :itr)) -axes(v::Pairs) = axes(getfield(v, :itr)) -size(v::Pairs) = size(getfield(v, :itr)) +length(v::Pairs) = length(keys(v)) +axes(v::Pairs) = axes(keys(v)) +size(v::Pairs) = size(keys(v)) Base.@eval @propagate_inbounds function _pairs_elt(p::Pairs{K, V}, idx) where {K, V} return $(Expr(:new, :(Pair{K, V}), :idx, :(getfield(p, :data)[idx]))) end @propagate_inbounds function iterate(p::Pairs{K, V}, state...) where {K, V} - x = iterate(getfield(p, :itr), state...) + x = iterate(keys(p), state...) x === nothing && return x idx, next = x return (_pairs_elt(p, idx), next) end -@propagate_inbounds function iterate(r::Reverse{<:Pairs}, state=(reverse(getfield(r.itr, :itr)),)) +@propagate_inbounds function iterate(r::Reverse{<:Pairs}, state=(reverse(keys(r.itr)),)) x = iterate(state...) x === nothing && return x idx, next = x return (_pairs_elt(r.itr, idx), (state[1], next)) end -@inline isdone(v::Pairs, state...) = isdone(getfield(v, :itr), state...) +@inline isdone(v::Pairs, state...) = isdone(keys(v), state...) IteratorSize(::Type{<:Pairs{<:Any, <:Any, I}}) where {I} = IteratorSize(I) IteratorSize(::Type{<:Pairs{<:Any, <:Any, <:AbstractUnitRange, <:Tuple}}) = HasLength() function last(v::Pairs{K, V}) where {K, V} - idx = last(getfield(v, :itr)) + idx = last(keys(v)) return Pair{K, V}(idx, v[idx]) end -haskey(v::Pairs, key) = (key in getfield(v, :itr)) -keys(v::Pairs) = getfield(v, :itr) +haskey(v::Pairs, key) = key in keys(v) +keys(v::Pairs) = getfield(v, :itr) === nothing ? keys(getfield(v, :data)) : getfield(v, :itr) values(v::Pairs) = getfield(v, :data) # TODO: this should be a view of data subset by itr getindex(v::Pairs, key) = getfield(v, :data)[key] setindex!(v::Pairs, value, key) = (getfield(v, :data)[key] = value; v) diff --git a/base/loading.jl b/base/loading.jl index de212f79e93b7..c69f28cdc5a02 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1267,17 +1267,21 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No sv = try if ocachepath !== nothing @debug "Loading object cache file $ocachepath for $(repr("text/plain", pkg))" - ccall(:jl_restore_package_image_from_file, Ref{SimpleVector}, (Cstring, Any, Cint, Cstring, Cint), + ccall(:jl_restore_package_image_from_file, Any, (Cstring, Any, Cint, Cstring, Cint), ocachepath, depmods, #=completeinfo=#false, pkg.name, ignore_native) else @debug "Loading cache file $path for $(repr("text/plain", pkg))" - ccall(:jl_restore_incremental, Ref{SimpleVector}, (Cstring, Any, Cint, Cstring), + ccall(:jl_restore_incremental, Any, (Cstring, Any, Cint, Cstring), path, depmods, #=completeinfo=#false, pkg.name) end finally lock(require_lock) end + if isa(sv, Exception) + return sv + end + sv = sv::SimpleVector edges = sv[3]::Vector{Any} ext_edges = sv[4]::Union{Nothing,Vector{Any}} extext_methods = sv[5]::Vector{Any} @@ -2630,21 +2634,23 @@ function __require_prelocked(pkg::PkgId, env) @goto load_from_cache end # spawn off a new incremental pre-compile task for recursive `require` calls - loaded = maybe_cachefile_lock(pkg, path) do - # double-check the search now that we have lock - m = _require_search_from_serialized(pkg, path, UInt128(0), true) - m isa Module && return m - triggers = get(EXT_PRIMED, pkg, nothing) - loadable_exts = nothing - if triggers !== nothing # extension - loadable_exts = PkgId[] - for (ext′, triggers′) in EXT_PRIMED - if triggers′ ⊊ triggers - push!(loadable_exts, ext′) + loaded = let path = path, reasons = reasons + maybe_cachefile_lock(pkg, path) do + # double-check the search now that we have lock + m = _require_search_from_serialized(pkg, path, UInt128(0), true) + m isa Module && return m + triggers = get(EXT_PRIMED, pkg, nothing) + loadable_exts = nothing + if triggers !== nothing # extension + loadable_exts = PkgId[] + for (ext′, triggers′) in EXT_PRIMED + if triggers′ ⊊ triggers + push!(loadable_exts, ext′) + end end end + return compilecache(pkg, path; reasons, loadable_exts) end - return compilecache(pkg, path; reasons, loadable_exts) end loaded isa Module && return loaded if isnothing(loaded) # maybe_cachefile_lock returns nothing if it had to wait for another process diff --git a/base/namedtuple.jl b/base/namedtuple.jl index f71b13852b953..37f3a3ef8436b 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -343,7 +343,7 @@ merge(a::NamedTuple, b::NamedTuple{()}) = a merge(a::NamedTuple{()}, b::NamedTuple{()}) = a merge(a::NamedTuple{()}, b::NamedTuple) = b -merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, getfield(b, :data)) +merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,Nothing,<:NamedTuple}) = merge(a, getfield(b, :data)) merge(a::NamedTuple, b::Iterators.Zip{<:Tuple{Any,Any}}) = merge(a, NamedTuple{Tuple(b.is[1])}(b.is[2])) @@ -535,7 +535,7 @@ when it is printed in the stack trace view. ```julia julia> @Kwargs{init::Int} # the internal representation of keyword arguments -Base.Pairs{Symbol, Int64, Tuple{Symbol}, @NamedTuple{init::Int64}} +Base.Pairs{Symbol, Int64, Nothing, @NamedTuple{init::Int64}} julia> sum("julia"; init=1) ERROR: MethodError: no method matching +(::Char, ::Char) @@ -578,7 +578,7 @@ Stacktrace: macro Kwargs(ex) return :(let NT = @NamedTuple $ex - Base.Pairs{keytype(NT),eltype(NT),typeof(NT.parameters[1]),NT} + Base.Pairs{keytype(NT),eltype(NT),Nothing,NT} end) end diff --git a/base/show.jl b/base/show.jl index 8ee211b882eec..3d38770c2e2a7 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1106,6 +1106,8 @@ function show_type_name(io::IO, tn::Core.TypeName) end function maybe_kws_nt(x::DataType) + # manually-written version of + # x <: (Pairs{Symbol, eltype(NT), Nothing, NT} where NT <: NamedTuple) x.name === typename(Pairs) || return nothing length(x.parameters) == 4 || return nothing x.parameters[1] === Symbol || return nothing @@ -1115,7 +1117,7 @@ function maybe_kws_nt(x::DataType) types isa DataType || return nothing x.parameters[2] === eltype(p4) || return nothing isa(syms, Tuple) || return nothing - x.parameters[3] === typeof(syms) || return nothing + x.parameters[3] === Nothing || return nothing return p4 end return nothing @@ -3313,7 +3315,7 @@ function Base.showarg(io::IO, r::Iterators.Pairs{<:Integer, <:Any, <:Any, T}, to print(io, "pairs(IndexLinear(), ::", T, ")") end -function Base.showarg(io::IO, r::Iterators.Pairs{Symbol, <:Any, <:Any, T}, toplevel) where {T <: NamedTuple} +function Base.showarg(io::IO, r::Iterators.Pairs{Symbol, <:Any, Nothing, T}, toplevel) where {T <: NamedTuple} print(io, "pairs(::NamedTuple)") end diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 806c9468efed4..34af576737b33 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -365,4 +365,4 @@ function from(frame::StackFrame, m::Module) return parentmodule(frame) === m end -end +end # module StackTraces diff --git a/base/strings/string.jl b/base/strings/string.jl index 79ec12d11cb94..32fd47b45cf49 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -7,9 +7,9 @@ An error occurred when trying to access `str` at index `i` that is not valid. """ struct StringIndexError <: Exception string::AbstractString - index::Integer + index::Int end -@noinline string_index_err(s::AbstractString, i::Integer) = +@noinline string_index_err((@nospecialize s::AbstractString), i::Integer) = throw(StringIndexError(s, Int(i))) function Base.showerror(io::IO, exc::StringIndexError) s = exc.string diff --git a/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/md5 b/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/md5 deleted file mode 100644 index 585185b3c2983..0000000000000 --- a/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -39c0cb64a6c4226f8cb07518f592a8bc diff --git a/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/sha512 b/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/sha512 deleted file mode 100644 index 41693dd5c7625..0000000000000 --- a/deps/checksums/LinearAlgebra-6cc040592fd509ee048658e9afb8a99a2dc20e1b.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -31563375775a85fa5ae1f6584f0ebc1ffef8b66a2c76ea74111b21c5d6d171189768d40cf6a4decc203845c8d0c789da6688ad9a15ec9d5ee8e7700e1e08715b diff --git a/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/md5 b/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/md5 new file mode 100644 index 0000000000000..b8651ee8f2d46 --- /dev/null +++ b/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/md5 @@ -0,0 +1 @@ +f41f7e4247fddb5531dea530bee83024 diff --git a/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/sha512 b/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/sha512 new file mode 100644 index 0000000000000..6523086dbd0a1 --- /dev/null +++ b/deps/checksums/LinearAlgebra-b5a8bb07059f0d499c493c6db01980b060836f5a.tar.gz/sha512 @@ -0,0 +1 @@ +d2596e62f75841be0da013c8c41708577ae2527d3564d95081385d77fc00da514a46f25bbb42304b76127890018358cb191c80c18ba57818c2fde8ebedde260b diff --git a/deps/checksums/openlibm b/deps/checksums/openlibm index cad61fd42cf94..fc20184ac85da 100644 --- a/deps/checksums/openlibm +++ b/deps/checksums/openlibm @@ -1,38 +1,38 @@ -OpenLibm.v0.8.5+0.aarch64-apple-darwin.tar.gz/md5/5fcbd746e90712e396e76dc4e76724d0 -OpenLibm.v0.8.5+0.aarch64-apple-darwin.tar.gz/sha512/f4ac2bc38bdc723384b67119daa2974fb43da34b2e45cea2029ea48f92c84c4cad6dfb43521b09a1e89ddf8c5b8cc22a38fa4b78ba39ac7524fd6bd1ba897aa9 -OpenLibm.v0.8.5+0.aarch64-linux-gnu.tar.gz/md5/4d1b4cd566805b5179c5ecdd060da473 -OpenLibm.v0.8.5+0.aarch64-linux-gnu.tar.gz/sha512/a9fe1a3d2e3898c017eb8615b2f3dbb514995ff041ac964c931c99c60d8cfe4eab7563a9cd65058f42f83c812f33d998573a7c5cc56a2e3960a4657e459ed321 -OpenLibm.v0.8.5+0.aarch64-linux-musl.tar.gz/md5/413be59af62b3ce0ebafeca093e3179e -OpenLibm.v0.8.5+0.aarch64-linux-musl.tar.gz/sha512/7bd76373e047ba854066af61f1c56b2e3a4d28c266228d7b30f596eadbaec52b070548ae60d41840c425ad5d0829c6c0cdaf326f2f160ed7508877ab5ec1a4b1 -OpenLibm.v0.8.5+0.aarch64-unknown-freebsd.tar.gz/md5/80736f9022c695eb1198e0b591a8fa63 -OpenLibm.v0.8.5+0.aarch64-unknown-freebsd.tar.gz/sha512/c633644578265e7ccc259ceb0442457b8c09290b4861b66c86dd6be7b30c4e394e70728142798097d6fe3afcfb4d9d1bd7ef58513fe8eed5684a4fba51bf185a -OpenLibm.v0.8.5+0.armv6l-linux-gnueabihf.tar.gz/md5/8fe0900a318393a290907f016bc654c3 -OpenLibm.v0.8.5+0.armv6l-linux-gnueabihf.tar.gz/sha512/167100a2d46e68462ef9a66915ced881d6358f05337bd38f2f77176f41cfd5be37e3c5226dd5d7d59147bd3e1aa7fb0893c1c81e9516134d3ab663b5752c4969 -OpenLibm.v0.8.5+0.armv6l-linux-musleabihf.tar.gz/md5/e8566719387984604f19dc5f9354a783 -OpenLibm.v0.8.5+0.armv6l-linux-musleabihf.tar.gz/sha512/532dd2b764fa15f7a838fb14cccafd2d4fe8fa4a132ea8394479a719c7aee11442f1b8a18e5d4a26ca820fa696d9d2afc7f5ec63dd96fa3b6763cea72b7026c3 -OpenLibm.v0.8.5+0.armv7l-linux-gnueabihf.tar.gz/md5/8fe0900a318393a290907f016bc654c3 -OpenLibm.v0.8.5+0.armv7l-linux-gnueabihf.tar.gz/sha512/167100a2d46e68462ef9a66915ced881d6358f05337bd38f2f77176f41cfd5be37e3c5226dd5d7d59147bd3e1aa7fb0893c1c81e9516134d3ab663b5752c4969 -OpenLibm.v0.8.5+0.armv7l-linux-musleabihf.tar.gz/md5/e8566719387984604f19dc5f9354a783 -OpenLibm.v0.8.5+0.armv7l-linux-musleabihf.tar.gz/sha512/532dd2b764fa15f7a838fb14cccafd2d4fe8fa4a132ea8394479a719c7aee11442f1b8a18e5d4a26ca820fa696d9d2afc7f5ec63dd96fa3b6763cea72b7026c3 -OpenLibm.v0.8.5+0.i686-linux-gnu.tar.gz/md5/9580d34e69d6067427b9c33db631cfd3 -OpenLibm.v0.8.5+0.i686-linux-gnu.tar.gz/sha512/46934f82791f69ac5f5da0dab7dcc6e3e9a4577c3bb529e9c0519c38f140c7b54517c55ff3579cd4ed4df68f0863e006aa98e51873f1dab452ce9f853996429a -OpenLibm.v0.8.5+0.i686-linux-musl.tar.gz/md5/66bfc9611d04c5d609e7824cb076d24b -OpenLibm.v0.8.5+0.i686-linux-musl.tar.gz/sha512/1bda2395d44c22aba3d1aab2b08ae06f763d3755037d454aa73f8e8134289a1ab5d65862bbc5a17a7a6b9f2918eb87e926b21527ddc4471e2ea20d605ba14e2d -OpenLibm.v0.8.5+0.i686-w64-mingw32.tar.gz/md5/0e97311b2f08b57d79085635f01ccced -OpenLibm.v0.8.5+0.i686-w64-mingw32.tar.gz/sha512/ae061ea406c06969332af58ed6fdfce2825326d771d30274d90775a1709b0361b7ca1dc7e6b0b76b93e4dd7a81d1842510a2c835251ee0a0978d6c839d96070e -OpenLibm.v0.8.5+0.powerpc64le-linux-gnu.tar.gz/md5/8ecfff7db76eee29591a654871e88855 -OpenLibm.v0.8.5+0.powerpc64le-linux-gnu.tar.gz/sha512/af03993b162316dd581f6ba5d1c23bca4c26cb22356ab229f326c42e111acbdf7ef45c9ad05894fe2d68794a63670cf89888653f788192a38b9255ce4bc72e28 -OpenLibm.v0.8.5+0.riscv64-linux-gnu.tar.gz/md5/69e06de135940666791c984941e9c4ad -OpenLibm.v0.8.5+0.riscv64-linux-gnu.tar.gz/sha512/2ac84deb7eb80a6a6237eff6fe861fd2907b3c95d1a76366dea062f3f35228dbc67aa40bd982e646508b4ff7cb6ef029111e2c0325039e60679800d6c6886be5 -OpenLibm.v0.8.5+0.x86_64-apple-darwin.tar.gz/md5/bd671ab9fe01835cab3e42e7cfa790fb -OpenLibm.v0.8.5+0.x86_64-apple-darwin.tar.gz/sha512/8bf2e66df17effc1e8778453904ffc20127f785bf096873289e8fdd8b17069ca844faffbd9f7621b87a7cb0a0051037eb9402360f2a03cf8794fbac8f7719777 -OpenLibm.v0.8.5+0.x86_64-linux-gnu.tar.gz/md5/df7fab134fbce3b625e9a82376f23e79 -OpenLibm.v0.8.5+0.x86_64-linux-gnu.tar.gz/sha512/64d07434e0db79833f84a2225838456eb9532617d377a776b3a534a908b1673bc4f890903f95350e4045e05c29539d993a18ecadeb879761e279ec3947f74390 -OpenLibm.v0.8.5+0.x86_64-linux-musl.tar.gz/md5/ebef6bb7651d116b397e035f39adfb1b -OpenLibm.v0.8.5+0.x86_64-linux-musl.tar.gz/sha512/de9036073e5dba2721b4119ecbbd21a0c9f75b65aff9392b7e88e464da35b97135d62404477441d0dadd3a2f8d49f1082291b35bf4b626fb1096d36d401980bf -OpenLibm.v0.8.5+0.x86_64-unknown-freebsd.tar.gz/md5/1115497539f00a37af18aa6516d52268 -OpenLibm.v0.8.5+0.x86_64-unknown-freebsd.tar.gz/sha512/71a2c06d141b3671fd220f2d88d72e845848b6d2b08a7b3a6c4bb1d5cc27cc450e1e681647bb583e7ed6375d5a70748401e95e61dc95d7808f33a9aa06755337 -OpenLibm.v0.8.5+0.x86_64-w64-mingw32.tar.gz/md5/b6b5335f4c83f7ebf0f74cf753358f00 -OpenLibm.v0.8.5+0.x86_64-w64-mingw32.tar.gz/sha512/e8351ddda305b757f337bb7ea26c441968843b23861676f0bdd7bcf83bb3969af790d4112307d3204eb87fac044dda9be305f349700ebe9ba2bfe3d6df24fde8 -openlibm-db24332879c320606c37f77fea165e6ecb49153c.tar.gz/md5/2375dd448e77e59152442a4b33abda01 -openlibm-db24332879c320606c37f77fea165e6ecb49153c.tar.gz/sha512/36054e7051990d04913f054a0542e2e104273f61308e9a442c2dab3dd392d40c03f264fbeca93c4296218eed85dad71028989a225088254013d752f4407d57ef +OpenLibm.v0.8.7+0.aarch64-apple-darwin.tar.gz/md5/68dd4a8d49ed68ec464352220b006e66 +OpenLibm.v0.8.7+0.aarch64-apple-darwin.tar.gz/sha512/fc6f69c3477c99058a074784af2f19769de5fdfbecbcbec76ce1253de69788ff41304fe8677a50582f6628d3a50b889b0c56e19c0d7bb369c493d72810b2aef9 +OpenLibm.v0.8.7+0.aarch64-linux-gnu.tar.gz/md5/421644dba2a629013db582011b2e5f14 +OpenLibm.v0.8.7+0.aarch64-linux-gnu.tar.gz/sha512/429416fd411a06ab8576653fb5e07e6fc5e210a3d6939451a0d56593ae74c04c330ee7936fa10b6ca6c21748f697817e67506b98c49a11d39ae9a98a958bd6e8 +OpenLibm.v0.8.7+0.aarch64-linux-musl.tar.gz/md5/ee870854946972b6a2ff989cc1ca6c12 +OpenLibm.v0.8.7+0.aarch64-linux-musl.tar.gz/sha512/3f9c0514fdc296fa28562abfbc513bba442d48c3fdbe38622a0a9e16bfbfee39135247fcc4fd486abb629a86cc7afd342215baccb4db59d07a5a1fa2c8356549 +OpenLibm.v0.8.7+0.aarch64-unknown-freebsd.tar.gz/md5/02ca3e2e478e8d2eb3c7d24e1584ab6f +OpenLibm.v0.8.7+0.aarch64-unknown-freebsd.tar.gz/sha512/d1f44059270e5884bea9b7f14c15b251dff528002d3f1b61144b0d197891487b690917711ce648c298a7f8db6d8a2035b82acee3dfb2e9b18dc556a09c3b7128 +OpenLibm.v0.8.7+0.armv6l-linux-gnueabihf.tar.gz/md5/473f534041e403f04edb56846fcd8426 +OpenLibm.v0.8.7+0.armv6l-linux-gnueabihf.tar.gz/sha512/17e1c5cbd871091ac9e0057d334891bd795d690986b40ad903bfaaf89100604e5c0abb97e9675581d50893f85859e64f44139c9359149c629a9b06c20a8f46ae +OpenLibm.v0.8.7+0.armv6l-linux-musleabihf.tar.gz/md5/147b932a2d3b7b0636be22d849f33a5a +OpenLibm.v0.8.7+0.armv6l-linux-musleabihf.tar.gz/sha512/abd3ad5096ef280814dcff203aaa1cc39d53bc706913cc6aae92d33f7d0842760ccc44f6270f8023558347be8944b169d1d04e508f74f9158f6686484218ce2d +OpenLibm.v0.8.7+0.armv7l-linux-gnueabihf.tar.gz/md5/473f534041e403f04edb56846fcd8426 +OpenLibm.v0.8.7+0.armv7l-linux-gnueabihf.tar.gz/sha512/17e1c5cbd871091ac9e0057d334891bd795d690986b40ad903bfaaf89100604e5c0abb97e9675581d50893f85859e64f44139c9359149c629a9b06c20a8f46ae +OpenLibm.v0.8.7+0.armv7l-linux-musleabihf.tar.gz/md5/147b932a2d3b7b0636be22d849f33a5a +OpenLibm.v0.8.7+0.armv7l-linux-musleabihf.tar.gz/sha512/abd3ad5096ef280814dcff203aaa1cc39d53bc706913cc6aae92d33f7d0842760ccc44f6270f8023558347be8944b169d1d04e508f74f9158f6686484218ce2d +OpenLibm.v0.8.7+0.i686-linux-gnu.tar.gz/md5/7a7ceefec85b5054a1bc31b1fa93a7f8 +OpenLibm.v0.8.7+0.i686-linux-gnu.tar.gz/sha512/0117e9f8a2236757443fff50c530e2ffb7d713e1bf46997713a6987f8602ac8398748c3fc8c8ba0980d127408de0d2f0de5e53af2c1a911488723bfba531c0ba +OpenLibm.v0.8.7+0.i686-linux-musl.tar.gz/md5/39163327893bfa499c97d5dbfe892d10 +OpenLibm.v0.8.7+0.i686-linux-musl.tar.gz/sha512/68ac6dc53da509ef906ecab66070381de27b8d551d39c147982c7b5008ec21e6a3a32bbc2aa6cb4e5c3f883cae76fc1c96b5cdfca58b2dabbf05c734431bf594 +OpenLibm.v0.8.7+0.i686-w64-mingw32.tar.gz/md5/8bef2aa7010577a37b1d789980ecb97a +OpenLibm.v0.8.7+0.i686-w64-mingw32.tar.gz/sha512/6770de28fbf856fc21619f1aa0ac752d059a9bbb9668d56211cc4b33050835a41d2b6d5777c535d63c4083fb01d70b5874f63c65b93ea3ee15e3ac19372091e8 +OpenLibm.v0.8.7+0.powerpc64le-linux-gnu.tar.gz/md5/4fb864d30bcb12946228a37ef51577ec +OpenLibm.v0.8.7+0.powerpc64le-linux-gnu.tar.gz/sha512/c22c2ff04baa93547b006185138b162cc293f2c022433830cff14895ee49eb68d448d9731f0f92c8bfb4ab036648a2480be59cdf33b8ac52ab4d63131fde078c +OpenLibm.v0.8.7+0.riscv64-linux-gnu.tar.gz/md5/f09c74ff81b14c1d3c14263410ffbdd3 +OpenLibm.v0.8.7+0.riscv64-linux-gnu.tar.gz/sha512/7136dccc94d3324eb9f74ae05dc2e44cc5ddb3defdccb2e5f0b483205892111da7bf5bedb494190537d95fce45879096430d0298d6b520845aa804e94a047679 +OpenLibm.v0.8.7+0.x86_64-apple-darwin.tar.gz/md5/76c855df0fb8ceda368e6da3463429fc +OpenLibm.v0.8.7+0.x86_64-apple-darwin.tar.gz/sha512/0a3ff48d7c04cb9dc932b2d0a683063a366941b8f8f533b809d993621abd5f52606653afac98a045b7ead82f85394dfac728cb4a358f118779a3f72b53e0282a +OpenLibm.v0.8.7+0.x86_64-linux-gnu.tar.gz/md5/41c4d1525544c452d66c9fc11248a4fd +OpenLibm.v0.8.7+0.x86_64-linux-gnu.tar.gz/sha512/51abc0f0aa3b8a674c42228c41a87258d91e838f2bce7382d7da134f972ddd8b65a23330683d04702be21031db6a2b448081f5044b0640091e4aa47e9ffefe2e +OpenLibm.v0.8.7+0.x86_64-linux-musl.tar.gz/md5/781eeeffc650b41b25742005cab2dd3a +OpenLibm.v0.8.7+0.x86_64-linux-musl.tar.gz/sha512/945d3a1267d7435ccfb7342fe8d581dd28878ecac429d339924b3a49be6c25e7130759be68cf02e2e5c9dddf0ee6e5321bc9da8fbdf58f1e0dde3950ab866fe3 +OpenLibm.v0.8.7+0.x86_64-unknown-freebsd.tar.gz/md5/a947d491d424d891af54ef6db3990c52 +OpenLibm.v0.8.7+0.x86_64-unknown-freebsd.tar.gz/sha512/da477916536fcd7bb447dd6b7df1142c851a4ff027d5e1eca667736bd9eee8deda6aeacd7acf451b3246f16ddc8ec8f8fc35e8c4d4739858b8255b3d6be37b95 +OpenLibm.v0.8.7+0.x86_64-w64-mingw32.tar.gz/md5/26fcdd81d0e98542c6f7597993fabeee +OpenLibm.v0.8.7+0.x86_64-w64-mingw32.tar.gz/sha512/60705757778abb932009edf19250704ddb5f705a242e407195df9ced984f3855501f9034f170817dbd7770d6e8703353a4e0efb772c86c83d6d7a178c2aedb53 +openlibm-9fbeafcd4f1b6ef6aa3946c1c8faead50f38a94d.tar.gz/md5/7a2773e071b7aa1a39182dcb1e665a78 +openlibm-9fbeafcd4f1b6ef6aa3946c1c8faead50f38a94d.tar.gz/sha512/65f511aa223c9a1a7cc84b83415cc55a42786e08559620414e94aaa83414d32e868e6e9d3d460961dcb79998211fa80a04acd1c1f2bf9aa3fd49cd8324e2f9a0 diff --git a/deps/openlibm.version b/deps/openlibm.version index 788701a66301b..2d59624cbeb91 100644 --- a/deps/openlibm.version +++ b/deps/openlibm.version @@ -4,6 +4,6 @@ OPENLIBM_JLL_NAME := OpenLibm ## source build -OPENLIBM_VER := 0.8.5 -OPENLIBM_BRANCH=v0.8.5 -OPENLIBM_SHA1=db24332879c320606c37f77fea165e6ecb49153c +OPENLIBM_VER := 0.8.7 +OPENLIBM_BRANCH=v0.8.7 +OPENLIBM_SHA1=9fbeafcd4f1b6ef6aa3946c1c8faead50f38a94d diff --git a/doc/src/devdocs/diagnostics.md b/doc/src/devdocs/diagnostics.md new file mode 100644 index 0000000000000..386f65db2e665 --- /dev/null +++ b/doc/src/devdocs/diagnostics.md @@ -0,0 +1,37 @@ +# Diagnostics used by the package ecosystem + +This page documents "hooks" embedded in Julia that are primarily used by +external tools. Many of these tools are designed to perform analyses that are +too complicated to be made part of Julia proper. + +## SnoopCompile + +SnoopCompile "snoops" on Julia's compiler to extract information for analysis +about invalidations and type-inference. There are a few internals it uses for +different purposes: + +- recording invalidations: `Base.StaticData.debug_method_invalidation` and + `ccall(:jl_debug_method_invalidation, ...)`: these record different modes of + invalidation. Users of SnoopCompile will transiently turn these on when, e.g., + loading packages. Each produces a standard log format; messing with the log + format might require a complementary pull request to SnoopCompile. + SnoopCompile will process these logs and generate trees of invalidated + CodeInstances that are attributable to specific changes in the method tables + or bindings. +- observing inference: `ccall(:jl_set_newly_inferred, ...)` and + `ccall(:jl_set_inference_entrance_backtraces, ...)`: these are used to + understand how inference gets triggered. The main purpose is to allow + performance diagnostics to understand sources of TTFX. The second of these + `ccall`s records a backtrace on every entrance to type-inference, so that + SnoopCompile can determine the caller of a dynamically-dispatched call. This + is needed to attribute "cause" for new type inference. + + The `jl_set_inference_entrance_backtraces` function accepts an array where + inference entrance events will be recorded. Each inference event stores two + consecutive array elements: first the `CodeInstance` object, then the + backtrace representation. So for N inference events, the array will contain 2N + elements arranged as: `[ci₁, bt₁, ci₂, bt₂, ..., ciₙ, btₙ]`. + + Note that the backtrace elements `btᵢ` contain raw backtrace data that + typically needs to be processed using `stacktrace(Base._reformat_bt(btᵢ...))`. + to convert them into a usable stack trace format for analysis. diff --git a/doc/src/devdocs/eval.md b/doc/src/devdocs/eval.md index 8f2fd68159676..21ec343f7f6be 100644 --- a/doc/src/devdocs/eval.md +++ b/doc/src/devdocs/eval.md @@ -62,25 +62,11 @@ The 10,000 foot view of the whole process is as follows: ## [Parsing](@id dev-parsing) -The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed -inside Julia in [src/flisp](https://github.com/JuliaLang/julia/tree/master/src/flisp). - -The interface functions for this are primarily defined in [`jlfrontend.scm`](https://github.com/JuliaLang/julia/blob/master/src/jlfrontend.scm). -The code in [`ast.c`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) handles this handoff -on the Julia side. - -The other relevant files at this stage are [`julia-parser.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm), -which handles tokenizing Julia code and turning it into an AST, and [`julia-syntax.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-syntax.scm), -which handles transforming complex AST representations into simpler, "lowered" AST representations -which are more suitable for analysis and execution. - -If you want to test the parser without re-building Julia in its entirety, you can run the frontend -on its own as follows: - - $ cd src - $ flisp/flisp - > (load "jlfrontend.scm") - > (jl-parse-file "") +By default, Julia uses [JuliaSyntax.jl](https://github.com/JuliaLang/JuliaSyntax.jl) to produce the +AST. Historically, it used a small lisp program written in femtolisp, the source-code for which is +distributed inside Julia in [src/flisp](https://github.com/JuliaLang/julia/tree/master/src/flisp). +If the `JULIA_USE_FLISP_PARSER` environment variable is set to `1`, the old parser will be used +instead. ## [Macro Expansion](@id dev-macro-expansion) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 188b8b7f79f3a..385451af91b13 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -74,35 +74,6 @@ If memory usage is your concern, you can always replace objects with ones that c with `A = nothing`. The memory will be released the next time the garbage collector runs; you can force this to happen with [`GC.gc()`](@ref Base.GC.gc). Moreover, an attempt to use `A` will likely result in an error, because most methods are not defined on type `Nothing`. -### How can I modify the declaration of a type in my session? - -Perhaps you've defined a type and then realize you need to add a new field. If you try this at -the REPL, you get the error: - -``` -ERROR: invalid redefinition of constant MyType -``` - -Types in module `Main` cannot be redefined. - -While this can be inconvenient when you are developing new code, there's an excellent workaround. - Modules can be replaced by redefining them, and so if you wrap all your new code inside a module -you can redefine types and constants. You can't import the type names into `Main` and then expect -to be able to redefine them there, but you can use the module name to resolve the scope. In other -words, while developing you might use a workflow something like this: - -```julia -include("mynewcode.jl") # this defines a module MyModule -obj1 = MyModule.ObjConstructor(a, b) -obj2 = MyModule.somefunction(obj1) -# Got an error. Change something in "mynewcode.jl" -include("mynewcode.jl") # reload the module -obj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct -obj2 = MyModule.somefunction(obj1) # this time it worked! -obj3 = MyModule.someotherfunction(obj2, c) -... -``` - ## [Scripting](@id man-scripting) ### How do I check if the current file is being run as the main script? diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 4393a99c73380..c0a0bd2d14460 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -2169,9 +2169,14 @@ void jl_dump_native_impl(void *native_code, auto lock = TSCtx.getLock(); auto dataM = data->M.getModuleUnlocked(); - // Delete data when add_output thinks it's done with it - // Saves memory for use when multithreading - data_outputs = compile(*dataM, "text", threads, [data](Module &) { delete data; }); + data_outputs = compile(*dataM, "text", threads, [data, &lock, &TSCtx](Module &) { + // Delete data when add_output thinks it's done with it + // Saves memory for use when multithreading + auto lock2 = std::move(lock); + delete data; + // Drop last reference to shared LLVM::Context + auto TSCtx2 = std::move(TSCtx); + }); } if (params->emit_metadata) { diff --git a/src/datatype.c b/src/datatype.c index f6cdf21c81afb..5c771ed2a003a 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1108,6 +1108,10 @@ static inline jl_uint128_t zext_read128(const jl_value_t *x, size_t nb) JL_NOTSA memcpy(&y, x, nb); return y; } +static void assign_uint128(jl_value_t *v, jl_uint128_t x, size_t nb) JL_NOTSAFEPOINT +{ + memcpy(v, &x, nb); +} #endif JL_DLLEXPORT jl_value_t *jl_new_bits(jl_value_t *dt, const void *data) @@ -1173,6 +1177,8 @@ JL_DLLEXPORT jl_value_t *jl_atomic_new_bits(jl_value_t *dt, const char *data) *(uint64_t*)v = jl_atomic_load((_Atomic(uint64_t)*)data); #endif #if MAX_POINTERATOMIC_SIZE >= 16 + else if (nb <= 12) + assign_uint128(v, jl_atomic_load((_Atomic(jl_uint128_t)*)data), 12); else if (nb <= 16) *(jl_uint128_t*)v = jl_atomic_load((_Atomic(jl_uint128_t)*)data); #endif @@ -1239,6 +1245,8 @@ JL_DLLEXPORT jl_value_t *jl_atomic_swap_bits(jl_value_t *dt, char *dst, const jl *(uint64_t*)v = jl_atomic_exchange((_Atomic(uint64_t)*)dst, zext_read64(src, nb)); #endif #if MAX_POINTERATOMIC_SIZE >= 16 + else if (nb <= 12) + assign_uint128(v, jl_atomic_exchange((_Atomic(jl_uint128_t)*)dst, zext_read128(src, nb)), 12); else if (nb <= 16) *(jl_uint128_t*)v = jl_atomic_exchange((_Atomic(jl_uint128_t)*)dst, zext_read128(src, nb)); #endif @@ -1288,7 +1296,7 @@ JL_DLLEXPORT int jl_atomic_bool_cmpswap_bits(char *dst, const jl_value_t *expect return success; } -JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre-allocated output */, char *dst, const jl_value_t *expected, const jl_value_t *src, int nb) +JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* NEW pre-allocated output */, char *dst, const jl_value_t *expected, const jl_value_t *src, int nb) { // dst must have the required alignment for an atomic of the given size // n.b.: this does not spuriously fail if there are padding bits @@ -1359,18 +1367,19 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- #endif #if MAX_POINTERATOMIC_SIZE >= 16 else if (nb <= 16) { - jl_uint128_t *y128 = (jl_uint128_t*)y; if (dt == et) { - *y128 = zext_read128(expected, nb); + jl_uint128_t y128 = zext_read128(expected, nb); jl_uint128_t z128 = zext_read128(src, nb); while (1) { - success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, y128, z128); - if (success || (dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding) || !jl_egal__bits(y, expected, dt)) + success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, &y128, z128); + assign_uint128(y, y128, nb); + if (success || (dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding) || !jl_egal__bits(y, expected, dt)) { break; + } } } else { - *y128 = jl_atomic_load((_Atomic(jl_uint128_t)*)dst); + assign_uint128(y, jl_atomic_load((_Atomic(jl_uint128_t)*)dst), nb); success = 0; } } diff --git a/src/gc-common.c b/src/gc-common.c index c07b707b17709..87ddb68abc704 100644 --- a/src/gc-common.c +++ b/src/gc-common.c @@ -126,7 +126,7 @@ JL_DLLEXPORT void jl_gc_set_cb_notify_gc_pressure(jl_gc_cb_notify_gc_pressure_t // but with several fixes to improve the correctness of the computation and remove unnecessary parameters #define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \ ~(sizeof(void *) - 1))) -static size_t _aligned_msize(void *p) +static size_t _jl_aligned_msize(void *p) { void *alloc_ptr = *(void**)SAVED_PTR(p); return _msize(alloc_ptr) - ((char*)p - (char*)alloc_ptr); @@ -138,7 +138,7 @@ size_t memory_block_usable_size(void *p, int isaligned) JL_NOTSAFEPOINT { #if defined(_OS_WINDOWS_) if (isaligned) - return _aligned_msize(p); + return _jl_aligned_msize(p); else return _msize(p); #elif defined(_OS_DARWIN_) diff --git a/src/gf.c b/src/gf.c index 0757614b390db..06bf3b62deda0 100644 --- a/src/gf.c +++ b/src/gf.c @@ -492,6 +492,14 @@ jl_code_instance_t *jl_type_infer(jl_method_instance_t *mi, size_t world, uint8_ if (ci && !jl_is_code_instance(ci)) { ci = NULL; } + + // Record inference entrance backtrace if enabled + if (ci) { + JL_GC_PUSH1(&ci); + jl_push_inference_entrance_backtraces((jl_value_t*)ci); + JL_GC_POP(); + } + JL_GC_POP(); #endif @@ -1209,14 +1217,9 @@ static void jl_compilation_sig( int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition->called & (1 << (i_arg - 1))) && !jl_has_free_typevars(decl_i) && jl_subtype(elt, (jl_value_t*)jl_function_type)); - if (notcalled_func && (type_i == (jl_value_t*)jl_any_type || - type_i == (jl_value_t*)jl_function_type || - (jl_is_uniontype(type_i) && // Base.Callable - ((((jl_uniontype_t*)type_i)->a == (jl_value_t*)jl_function_type && - ((jl_uniontype_t*)type_i)->b == (jl_value_t*)jl_type_type) || - (((jl_uniontype_t*)type_i)->b == (jl_value_t*)jl_function_type && - ((jl_uniontype_t*)type_i)->a == (jl_value_t*)jl_type_type))))) { - // and attempt to despecialize types marked Function, Callable, or Any + if (notcalled_func && (jl_subtype((jl_value_t*)jl_function_type, type_i))) { + // and attempt to despecialize types marked as a supertype of Function (i.e. + // Function, Callable, Any, or a Union{Function, T}) // when called with a subtype of Function but is not called if (!*newparams) *newparams = jl_svec_copy(tt->parameters); jl_svecset(*newparams, i, (jl_value_t*)jl_function_type); @@ -1442,15 +1445,9 @@ JL_DLLEXPORT int jl_isa_compileable_sig( int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition->called & (1 << (i_arg - 1))) && !jl_has_free_typevars(decl_i) && jl_subtype(elt, (jl_value_t*)jl_function_type)); - if (notcalled_func && (type_i == (jl_value_t*)jl_any_type || - type_i == (jl_value_t*)jl_function_type || - (jl_is_uniontype(type_i) && // Base.Callable - ((((jl_uniontype_t*)type_i)->a == (jl_value_t*)jl_function_type && - ((jl_uniontype_t*)type_i)->b == (jl_value_t*)jl_type_type) || - (((jl_uniontype_t*)type_i)->b == (jl_value_t*)jl_function_type && - ((jl_uniontype_t*)type_i)->a == (jl_value_t*)jl_type_type))))) { - // and attempt to despecialize types marked Function, Callable, or Any - // when called with a subtype of Function but is not called + if (notcalled_func && jl_subtype((jl_value_t*)jl_function_type, type_i)) { + // and attempt to despecialize types marked as a supertype of Function (i.e. + // Function, Callable, Any, or a Union{Function, T}) if (elt == (jl_value_t*)jl_function_type) continue; JL_GC_POP(); @@ -3486,7 +3483,8 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t // Ok, compilation is enabled. We'll need to try to compile something (probably). // Everything from here on is considered (user facing) compile time - uint64_t start = jl_typeinf_timing_begin(); + uint64_t compilation_start = jl_hrtime(); + uint64_t inference_start = jl_typeinf_timing_begin(); // Special-handling for reentrancy // Is a recompile if there is cached code, and it was compiled (not only inferred) before int is_recompile = 0; @@ -3513,15 +3511,14 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t if (codeinst) { if (jl_is_compiled_codeinst(codeinst)) { - jl_typeinf_timing_end(start, is_recompile); + jl_typeinf_timing_end(inference_start, is_recompile); // Already compiled - e.g. constabi, or compiled by a different thread while we were waiting. return codeinst; } JL_GC_PUSH1(&codeinst); - double compile_time = jl_hrtime(); int did_compile = jl_compile_codeinst(codeinst); - compile_time = jl_hrtime() - compile_time; + double compile_time = jl_hrtime() - compilation_start; if (jl_atomic_load_relaxed(&codeinst->invoke) == NULL) { // Something went wrong. Bail to the fallback path. @@ -3551,7 +3548,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t if (ucache_invoke != jl_fptr_sparam && ucache_invoke != jl_fptr_interpret_call) { // only these care about the exact specTypes, otherwise we can use it directly - jl_typeinf_timing_end(start, is_recompile); + jl_typeinf_timing_end(inference_start, is_recompile); return ucache; } uint8_t specsigflags; @@ -3569,7 +3566,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t jl_mi_cache_insert(mi, codeinst); } jl_atomic_store_relaxed(&codeinst->precompile, 1); - jl_typeinf_timing_end(start, is_recompile); + jl_typeinf_timing_end(inference_start, is_recompile); return codeinst; } diff --git a/src/julia.h b/src/julia.h index 9bbdb2a092b97..34b2d79259ede 100644 --- a/src/julia.h +++ b/src/julia.h @@ -2274,6 +2274,8 @@ JL_DLLEXPORT jl_value_t *jl_object_top_module(jl_value_t* v) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_set_newly_inferred(jl_value_t *newly_inferred); JL_DLLEXPORT void jl_push_newly_inferred(jl_value_t *ci); +JL_DLLEXPORT void jl_set_inference_entrance_backtraces(jl_value_t *inference_entrance_backtraces); +JL_DLLEXPORT void jl_push_inference_entrance_backtraces(jl_value_t *ci); JL_DLLEXPORT void jl_write_compiler_output(void); // parsing diff --git a/src/julia_internal.h b/src/julia_internal.h index e9fc24dda22ca..9473f6be4b898 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1494,6 +1494,7 @@ size_t rec_backtrace_ctx(jl_bt_element_t *bt_data, size_t maxsize, bt_context_t size_t rec_backtrace_ctx_dwarf(jl_bt_element_t *bt_data, size_t maxsize, bt_context_t *ctx, jl_gcframe_t *pgcstack) JL_NOTSAFEPOINT; #endif JL_DLLEXPORT jl_value_t *jl_get_backtrace(void); +JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp, int skip); void jl_critical_error(int sig, int si_code, bt_context_t *context, jl_task_t *ct); JL_DLLEXPORT void jl_raise_debugger(void) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_gdblookup(void* ip) JL_NOTSAFEPOINT; diff --git a/src/module.c b/src/module.c index b6ed80e712c7e..b5d3e785bc96c 100644 --- a/src/module.c +++ b/src/module.c @@ -1775,16 +1775,20 @@ JL_DLLEXPORT void jl_disable_binding(jl_globalref_t *gr) jl_binding_t *b = gr->binding; if (!b) b = jl_get_module_binding(gr->mod, gr->name, 1); - jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - if (jl_binding_kind(bpart) == PARTITION_KIND_GUARD) { - // Already guard + for (;;) { + jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_atomic_load_acquire(&jl_world_counter)); + + if (jl_binding_kind(bpart) == PARTITION_KIND_GUARD) { + // Already guard + return; + } + + if (!jl_replace_binding(b, bpart, NULL, PARTITION_KIND_GUARD)) + continue; + return; } - - for (;;) - if (jl_replace_binding(b, bpart, NULL, PARTITION_KIND_GUARD)) - break; } JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index e676eabbddad3..1d8ed0e19b04b 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -131,6 +131,38 @@ JL_DLLEXPORT void jl_push_newly_inferred(jl_value_t* ci) JL_UNLOCK(&newly_inferred_mutex); } + +static jl_array_t *inference_entrance_backtraces JL_GLOBALLY_ROOTED /*FIXME*/ = NULL; +// Mutex for inference_entrance_backtraces +jl_mutex_t inference_entrance_backtraces_mutex; + +// Register array of inference entrance backtraces +JL_DLLEXPORT void jl_set_inference_entrance_backtraces(jl_value_t* _inference_entrance_backtraces) +{ + assert(_inference_entrance_backtraces == NULL || _inference_entrance_backtraces == jl_nothing || jl_is_array(_inference_entrance_backtraces)); + if (_inference_entrance_backtraces == jl_nothing) + _inference_entrance_backtraces = NULL; + JL_LOCK(&inference_entrance_backtraces_mutex); + inference_entrance_backtraces = (jl_array_t*) _inference_entrance_backtraces; + JL_UNLOCK(&inference_entrance_backtraces_mutex); +} + + +JL_DLLEXPORT void jl_push_inference_entrance_backtraces(jl_value_t* ci) +{ + JL_LOCK(&inference_entrance_backtraces_mutex); + if (inference_entrance_backtraces == NULL) { + JL_UNLOCK(&inference_entrance_backtraces_mutex); + return; + } + jl_value_t* backtrace = jl_backtrace_from_here(0, 1); + size_t end = jl_array_nrows(inference_entrance_backtraces); + jl_array_grow_end(inference_entrance_backtraces, 2); + jl_array_ptr_set(inference_entrance_backtraces, end, ci); + jl_array_ptr_set(inference_entrance_backtraces, end + 1, backtrace); + JL_UNLOCK(&inference_entrance_backtraces_mutex); +} + // compute whether a type references something internal to worklist // and thus could not have existed before deserialize // and thus does not need delayed unique-ing diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index 3b20e5feb3da3..4af706606d326 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -766,6 +766,5 @@ precompile(NamedTuple{(:pkg_uuid,)}, (Tuple{Base.UUID},)) precompile(Core.kwfunc(load_artifacts_toml), (NamedTuple{(:pkg_uuid,), Tuple{Base.UUID}}, typeof(load_artifacts_toml), String)) precompile(parse_mapping, (String, String, String)) precompile(parse_mapping, (Dict{String, Any}, String, String)) -precompile(Tuple{typeof(Artifacts._artifact_str), Module, String, Base.SubString{String}, String, Base.Dict{String, Any}, Base.SHA1, Base.BinaryPlatforms.Platform, Any}) - +precompile(Tuple{typeof(Artifacts.__artifact_str), Module, String, Base.SubString{String}, String, Base.Dict{String, Any}, Base.SHA1, Base.BinaryPlatforms.Platform, Base.Val{Artifacts}}) end # module Artifacts diff --git a/stdlib/LinearAlgebra.version b/stdlib/LinearAlgebra.version index 10e03e5e0f103..6ee231d7dd649 100644 --- a/stdlib/LinearAlgebra.version +++ b/stdlib/LinearAlgebra.version @@ -1,4 +1,4 @@ LINEARALGEBRA_BRANCH = release-1.12 -LINEARALGEBRA_SHA1 = 6cc040592fd509ee048658e9afb8a99a2dc20e1b +LINEARALGEBRA_SHA1 = b5a8bb07059f0d499c493c6db01980b060836f5a LINEARALGEBRA_GIT_URL := https://github.com/JuliaLang/LinearAlgebra.jl.git LINEARALGEBRA_TAR_URL = https://api.github.com/repos/JuliaLang/LinearAlgebra.jl/tarball/$1 diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index e0d3d3182b377..8d6093f744f14 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -163,7 +163,7 @@ version = "0.3.28+3" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.5+0" +version = "0.8.7+0" [[deps.OpenSSL_jll]] deps = ["Artifacts", "Libdl"] diff --git a/stdlib/OpenLibm_jll/Project.toml b/stdlib/OpenLibm_jll/Project.toml index 431528ee3f400..a98bf97de0574 100644 --- a/stdlib/OpenLibm_jll/Project.toml +++ b/stdlib/OpenLibm_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenLibm_jll" uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.5+0" +version = "0.8.7+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index e8dd01a0c3c89..03b4b4fec98f1 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -335,21 +335,23 @@ PATH_cache_condition::Union{Threads.Condition, Nothing} = nothing # used for syn next_cache_update::Float64 = 0.0 function maybe_spawn_cache_PATH() global PATH_cache_task, PATH_cache_condition, next_cache_update - # Extract to local variables to enable flow-sensitive type inference for these global variables - PATH_cache_task_local = PATH_cache_task - PATH_cache_condition_local = PATH_cache_condition @lock PATH_cache_lock begin + # Extract to local variables to enable flow-sensitive type inference for these global variables + PATH_cache_task_local = PATH_cache_task PATH_cache_task_local isa Task && !istaskdone(PATH_cache_task_local) && return time() < next_cache_update && return - PATH_cache_task = Threads.@spawn begin - REPLCompletions.cache_PATH() - @lock PATH_cache_lock begin - next_cache_update = time() + 10 # earliest next update can run is 10s after - PATH_cache_task = nothing # release memory when done - PATH_cache_condition_local !== nothing && notify(PATH_cache_condition_local) + PATH_cache_task = PATH_cache_task_local = Threads.@spawn begin + try + REPLCompletions.cache_PATH() + finally + @lock PATH_cache_lock begin + next_cache_update = time() + 10 # earliest next update can run is 10s after + PATH_cache_task = nothing # release memory when done + PATH_cache_condition_local = PATH_cache_condition + PATH_cache_condition_local !== nothing && notify(PATH_cache_condition_local) + end end end - PATH_cache_task_local = PATH_cache_task Base.errormonitor(PATH_cache_task_local) end end diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 43bea08e285f1..b3b141425e1a4 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -1092,7 +1092,7 @@ function test_only_arm_cache_refresh() # force the next cache update to happen immediately REPL.REPLCompletions.next_cache_update = 0 end - return REPL.REPLCompletions.PATH_cache_condition + return nothing end function test_only_wait_cache_path_done() diff --git a/stdlib/UUIDs/src/UUIDs.jl b/stdlib/UUIDs/src/UUIDs.jl index e29cf3ff7597e..a2fd13a1c7cd1 100644 --- a/stdlib/UUIDs/src/UUIDs.jl +++ b/stdlib/UUIDs/src/UUIDs.jl @@ -74,8 +74,8 @@ function _build_uuid1(rng::AbstractRNG, timestamp::UInt64) # mask off clock sequence and node u &= 0x00000000000000003fffffffffffffff - # set the unicast/multicast bit and version - u |= 0x00000000000010000000010000000000 + # set the version, variant, and unicast/multicast bit + u |= 0x00000000000010008000010000000000 ts_low = timestamp & typemax(UInt32) ts_mid = (timestamp >> 32) & typemax(UInt16) diff --git a/stdlib/UUIDs/test/runtests.jl b/stdlib/UUIDs/test/runtests.jl index c6da441076ea8..27bcad1f20dc5 100644 --- a/stdlib/UUIDs/test/runtests.jl +++ b/stdlib/UUIDs/test/runtests.jl @@ -42,6 +42,15 @@ u7 = uuid7() @test uuid_version(u7) == 7 end +@testset "Extraction of variant bits" begin + # RFC 4122, section 4.1.1 + uuid_variant(u::UUID) = Int((u.value >> 62) & 0x3) + @test uuid_variant(u1) == 2 + @test uuid_variant(u4) == 2 + @test uuid_variant(u5) == 2 + @test uuid_variant(u7) == 2 +end + @testset "Parsing from string" begin @test u1 == UUID(string(u1)) == UUID(GenericString(string(u1))) @test u4 == UUID(string(u4)) == UUID(GenericString(string(u4))) diff --git a/test/core.jl b/test/core.jl index a7746de08a710..db0e0905f12a3 100644 --- a/test/core.jl +++ b/test/core.jl @@ -243,6 +243,62 @@ k11840(::Type{Union{Tuple{Int32}, Tuple{Int64}}}) = '2' @test k11840(Tuple{Union{Int32, Int64}}) == '2' @test k11840(Union{Tuple{Int32}, Tuple{Int64}}) == '2' +# issue #59327 +@noinline f59327(f, x) = Any[f, x] +g59327(x) = f59327(+, Any[x][1]) +g59327(1) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(f59327), Function, Int}, + methods(f59327)[1].specializations) + +@noinline h59327(f::Union{Function, Nothing}, x) = Any[f, x] +i59327(x) = h59327(+, Any[x][1]) +i59327(1) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(h59327), Function, Int}, + methods(h59327)[1].specializations) + +@noinline j59327(f::Function, x) = Any[f, x] +k59327(x) = j59327(+, Any[x][1]) +k59327(1) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(j59327), Function, Int}, + methods(j59327)[1].specializations +) + +@noinline l59327(f::Base.Callable, x) = Any[f, x] +m59327(x) = l59327(+, Any[x][1]) +m59327(1) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(l59327), Function, Int}, + methods(l59327)[1].specializations +) + +# _do_ specialize if the signature has a `where` +@noinline n59327(f::F, x) where F = Any[f, x] +o59327(x) = n59327(+, Any[x][1]) +o59327(1) +@test !any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(n59327), Function, Int}, + methods(n59327)[1].specializations +) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(n59327), typeof(+), Int}, + methods(n59327)[1].specializations +) + +# _do_ specialize if the signature is specific +@noinline n59327(f::typeof(+), x) = Any[f, x] +o59327(x) = n59327(+, Any[x][1]) +o59327(1) +@test !any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(n59327), Function, Int}, + methods(n59327)[1].specializations +) +@test any( + mi->mi isa Core.MethodInstance && mi.specTypes == Tuple{typeof(n59327), typeof(+), Int}, + methods(n59327)[1].specializations +) # issue #20511 f20511(x::DataType) = 0 diff --git a/test/namedtuple.jl b/test/namedtuple.jl index b8dba5c06422e..0f54196879a43 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -163,6 +163,10 @@ end @test merge(NamedTuple(), [:a=>1, :b=>2, :c=>3, :a=>4, :c=>5]) == (a=4, b=2, c=5) @test merge((c=0, z=1), [:a=>1, :b=>2, :c=>3, :a=>4, :c=>5]) == (c=5, z=1, a=4, b=2) +# https://github.com/JuliaLang/julia/issues/59292 +@test merge((; a = 1), Base.Pairs((; b = 2, c = 3), (:b,))) == (a = 1, b = 2) +@test merge((; a = 1), Base.pairs((; b = 2, c = 3))) == (a = 1, b = 2, c = 3) + @test keys((a=1, b=2, c=3)) == (:a, :b, :c) @test keys(NamedTuple()) == () @test keys((a=1,)) == (:a,) diff --git a/test/rebinding.jl b/test/rebinding.jl index 1c2a4d7a0b91c..fa1f72cadfe4a 100644 --- a/test/rebinding.jl +++ b/test/rebinding.jl @@ -383,3 +383,28 @@ end # M3 connects all, so we should have a single partition @test access_and_count(:afterM3) == 1 + +# Test that delete_binding in an outdated world age works +module BindingTestModule; end +function create_and_delete_binding() + Core.eval(BindingTestModule, :(const x = 1)) + Base.delete_binding(BindingTestModule, :x) +end +create_and_delete_binding() +@test Base.binding_kind(BindingTestModule, :x) == Base.PARTITION_KIND_GUARD + +# Test that we properly invalidate bindings if the value changes, not just the +# export status (#59272) +module Invalidate59272 + using Test + module Foo + export Bar + struct Bar + # x + end + end + using .Foo + @test isa(Bar(), Foo.Bar) + Core.eval(Foo, :(struct Bar; x; end)) + @test Bar(1) == Foo.Bar(1) +end diff --git a/test/runtests.jl b/test/runtests.jl index 1872c888333da..a15816390986a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,6 +15,9 @@ include("buildkitetestjson.jl") using .BuildkiteTestJSON +const longrunning_delay = parse(Int, get(ENV, "JULIA_TEST_LONGRUNNING_DELAY", "45")) * 60 # minutes +const longrunning_interval = parse(Int, get(ENV, "JULIA_TEST_LONGRUNNING_INTERVAL", "15")) * 60 # minutes + (; tests, net_on, exit_on_error, use_revise, seed) = choosetests(ARGS) tests = unique(tests) @@ -175,10 +178,10 @@ cd(@__DIR__) do at = lpad("($wrkr)", name_align - textwidth(name) + 1, " ") lock(print_lock) try - printstyled(name, at, " |", " "^elapsed_align, - "started at $(now())", + printstyled(name, at, " |", " "^elapsed_align, color=:white) + printstyled("started at $(now())", (pid > 0 ? " on pid $pid" : ""), - "\n", color=:white) + "\n", color=:light_black) finally unlock(print_lock) end @@ -215,6 +218,10 @@ cd(@__DIR__) do # Monitor stdin and kill this task on ^C # but don't do this on Windows, because it may deadlock in the kernel running_tests = Dict{String, DateTime}() + + # Track timeout timers for each test + test_timers = Dict{String, Timer}() + if !Sys.iswindows() && isa(stdin, Base.TTY) t = current_task() stdin_monitor = @async begin @@ -249,6 +256,33 @@ cd(@__DIR__) do test = popfirst!(tests) running_tests[test] = now() wrkr = p + + # Create a timer for this test to report long-running status + test_timers[test] = Timer(longrunning_delay, interval=longrunning_interval) do timer + if haskey(running_tests, test) # Check test is still running + start_time = running_tests[test] + elapsed = now() - start_time + elapsed_minutes = elapsed.value ÷ (1000 * 60) + + elapsed_str = if elapsed_minutes >= 60 + hours, mins = divrem(elapsed_minutes, 60) + "$(hours)h $(mins)m" + else + "$(elapsed_minutes)m" + end + + @lock print_lock begin + print(test) + print(lpad("($(wrkr))", name_align - textwidth(test) + 1, " "), " | ") + # Calculate total width of data columns: "Time (s) | GC (s) | GC % | Alloc (MB) | RSS (MB)" + # This is: elapsed_align + 3 + gc_align + 3 + percent_align + 3 + alloc_align + 3 + rss_align + data_width = elapsed_align + gc_align + percent_align + alloc_align + rss_align + 12 # 12 = 4 * " | " + message = "has been running for $(elapsed_str)" + centered_message = lpad(rpad(message, (data_width + textwidth(message)) ÷ 2), data_width) + printstyled(centered_message, "\n", color=:light_black) + end + end + end before = time() resp, duration = try r = remotecall_fetch(@Base.world(runtests, ∞), wrkr, test, test_path(test); seed=seed) @@ -258,6 +292,10 @@ cd(@__DIR__) do Any[CapturedException(e, catch_backtrace())], time() - before end delete!(running_tests, test) + if haskey(test_timers, test) + close(test_timers[test]) + delete!(test_timers, test) + end push!(results, (test, resp, duration)) if length(resp) == 1 print_testworker_errored(test, wrkr, exit_on_error ? nothing : resp[1]) @@ -342,6 +380,9 @@ cd(@__DIR__) do if @isdefined stdin_monitor schedule(stdin_monitor, InterruptException(); error=true) end + if @isdefined test_timers + foreach(close, values(test_timers)) + end end #= diff --git a/test/show.jl b/test/show.jl index 7c51768579042..898ff7578a3e4 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1448,7 +1448,7 @@ test_repr("(:).a") @test repr(@NamedTuple{var"#"::Int64}) == "@NamedTuple{var\"#\"::Int64}" # Test general printing of `Base.Pairs` (it should not use the `@Kwargs` macro syntax) -@test repr(@Kwargs{init::Int}) == "Base.Pairs{Symbol, $Int, Tuple{Symbol}, @NamedTuple{init::$Int}}" +@test repr(@Kwargs{init::Int}) == "Base.Pairs{Symbol, $Int, Nothing, @NamedTuple{init::$Int}}" @testset "issue #42931" begin @test repr(NTuple{4, :A}) == "Tuple{:A, :A, :A, :A}" diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 3df0998fe88f6..169fc7c69f6c8 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -262,3 +262,39 @@ end @testset "Base.StackTraces docstrings" begin @test isempty(Docs.undocumented_names(StackTraces)) end + + +@testset "Dispatch backtraces" begin + # Check that it's possible to capture a backtrace upon entrance to inference + # This test ensures that SnoopCompile will continue working + # See in particular SnoopCompile/SnoopCompileCore/src/snoop_inference.jl + # and the "diagnostics" devdoc. + @noinline callee(x::Int) = sin(x) + caller(x) = invokelatest(callee, x) + + @test sin(0) == 0 # force compilation of sin(::Int) + dispatch_backtraces = [] + ccall(:jl_set_inference_entrance_backtraces, Cvoid, (Any,), dispatch_backtraces) + caller(3) + ccall(:jl_set_inference_entrance_backtraces, Cvoid, (Any,), nothing) + ln = @__LINE__() - 2 + fl = Symbol(@__FILE__()) + @test length(dispatch_backtraces) == 4 # 2 ci-backtrace pairs, stored as 4 separate elements + mcallee, mcaller = only(methods(callee)), only(methods(caller)) + # Extract pairs from the flattened array format: ci at odd indices, backtrace at even indices + pairs = [(dispatch_backtraces[i], dispatch_backtraces[i+1]) for i in 1:2:length(dispatch_backtraces)] + @test any(pairs) do (ci, trace) + # trace is a SimpleVector from jl_backtrace_from_here, need to reformat before stacktrace + bt = Base._reformat_bt(trace[1], trace[2]) + ci.def.def === mcallee && any(stacktrace(bt)) do sf + sf.file == fl && sf.line == ln + end + end + @test any(pairs) do (ci, trace) + # trace is a SimpleVector from jl_backtrace_from_here, need to reformat before stacktrace + bt = Base._reformat_bt(trace[1], trace[2]) + ci.def.def === mcaller && any(stacktrace(bt)) do sf + sf.file == fl && sf.line == ln + end + end +end