From 9e91b68a77ece4b85f8bf16f68404d711a6e687f Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 30 Dec 2025 20:18:38 -0500 Subject: [PATCH 01/34] update utf8proc to 2.11.3 (#60207) (cherry picked from commit 8101956110954d3d2acd0e20c3b59b3975d53cc7) --- deps/checksums/utf8proc | 4 ++-- deps/utf8proc.version | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deps/checksums/utf8proc b/deps/checksums/utf8proc index 2ab56bdbc3251..769514c34a243 100644 --- a/deps/checksums/utf8proc +++ b/deps/checksums/utf8proc @@ -1,2 +1,2 @@ -utf8proc-d7bf128df773c2a1a7242eb80e51e91a769fc985.tar.gz/md5/42a776162314cd5dfbec6aaa3e2af42d -utf8proc-d7bf128df773c2a1a7242eb80e51e91a769fc985.tar.gz/sha512/0bb54a5f296b5c7f480c45b8cf4de7e95b498106b5b165890539ec5861194baa6c9a45bff2566d695d2f4921c1086fbe8419e8e8db353a0517a76fc307829152 +utf8proc-e5e799221b45bbb90f5fdc5c69b6b8dfbf017e78.tar.gz/md5/749152abfd6122032b02e7fb484f5b64 +utf8proc-e5e799221b45bbb90f5fdc5c69b6b8dfbf017e78.tar.gz/sha512/717552acf99d5a9df54c1378749dc3e816a1d6ab6a66704325c3715b00096f891480456c7fa09bd97d32f08d392ed4ef5b7b65da401dd26804cb8431e6a04c07 diff --git a/deps/utf8proc.version b/deps/utf8proc.version index 3c05ad3a89e8d..d98ec9b0268b6 100644 --- a/deps/utf8proc.version +++ b/deps/utf8proc.version @@ -1,2 +1,2 @@ -UTF8PROC_BRANCH=v2.11.0 -UTF8PROC_SHA1=d7bf128df773c2a1a7242eb80e51e91a769fc985 +UTF8PROC_BRANCH=v2.11.3 +UTF8PROC_SHA1=e5e799221b45bbb90f5fdc5c69b6b8dfbf017e78 From 7dd088214596b8ff19e717fb4e936103ce4c89e0 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 3 Jan 2026 22:14:21 +0100 Subject: [PATCH 02/34] Fix many instances of `Core.Box` in Base. (#60515) (cherry picked from commit 42ad41c179e0b086d4190e8e185833a4d5001505) --- base/arrayshow.jl | 9 ++++- base/binaryplatforms.jl | 75 +++++++++++++++++++++-------------------- base/experimental.jl | 45 ++++++++++++++----------- base/file.jl | 74 ++++++++++++++++++++-------------------- base/loading.jl | 13 +++---- base/shell.jl | 56 ++++++++++++++++-------------- base/stacktraces.jl | 26 +++++++------- 7 files changed, 161 insertions(+), 137 deletions(-) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index cbdca7b2686c4..903fb4f6b68bc 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -295,7 +295,14 @@ function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Functio ii = idxs[i] ind = tailinds[i] if length(ind) > 10 - if ii == ind[firstindex(ind)+3] && all(d->idxs[d]==first(tailinds[d]),1:i-1) + all_first = true + for d = 1:i-1 + if idxs[d] != first(tailinds[d]) + all_first = false + break + end + end + if ii == ind[firstindex(ind)+3] && all_first for j=i+1:nd szj = length(axs[j+2]) indj = tailinds[j] diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 76aaf927b60f2..08cd5ce403b85 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -872,6 +872,42 @@ function get_csl_member(member::Symbol) return nothing end + +function _get_libgfortran_path() + # If CompilerSupportLibraries_jll is a stdlib, we can just directly ask for + # the path here, without checking `dllist()`: + libgfortran_path = get_csl_member(:libgfortran_path) + if libgfortran_path !== nothing + return libgfortran_path::String + end + + # Otherwise, look for it having already been loaded by something + libgfortran_paths = filter!(x -> occursin("libgfortran", x), Libdl.dllist()) + if !isempty(libgfortran_paths) + return first(libgfortran_paths)::String + end + + # One day, I hope to not be linking against libgfortran in base Julia + return nothing +end + +function _get_libstdcxx_handle() + # If CompilerSupportLibraries_jll is a stdlib, we can just directly open it + libstdcxx = get_csl_member(:libstdcxx) + if libstdcxx !== nothing + return nothing + end + + # Otherwise, look for it having already been loaded by something + libstdcxx_paths = filter!(x -> occursin("libstdc++", x), Libdl.dllist()) + if !isempty(libstdcxx_paths) + return Libdl.dlopen(first(libstdcxx_paths), Libdl.RTLD_NOLOAD)::Ptr{Cvoid} + end + + # One day, I hope to not be linking against libgfortran in base Julia + return nothing +end + """ detect_libgfortran_version() @@ -880,25 +916,7 @@ linked against (if any). Returns `nothing` if no libgfortran version dependence detected. """ function detect_libgfortran_version() - function get_libgfortran_path() - # If CompilerSupportLibraries_jll is a stdlib, we can just directly ask for - # the path here, without checking `dllist()`: - libgfortran_path = get_csl_member(:libgfortran_path) - if libgfortran_path !== nothing - return libgfortran_path::String - end - - # Otherwise, look for it having already been loaded by something - libgfortran_paths = filter!(x -> occursin("libgfortran", x), Libdl.dllist()) - if !isempty(libgfortran_paths) - return first(libgfortran_paths)::String - end - - # One day, I hope to not be linking against libgfortran in base Julia - return nothing - end - - libgfortran_path = get_libgfortran_path() + libgfortran_path = _get_libgfortran_path() name, version = parse_dl_name_version(libgfortran_path, os()) if version === nothing # Even though we complain about this, we allow it to continue in the hopes that @@ -922,25 +940,8 @@ it is linked against (if any). `max_minor_version` is the latest version in the 3.4 series of GLIBCXX where the search is performed. """ function detect_libstdcxx_version(max_minor_version::Int=30) - function get_libstdcxx_handle() - # If CompilerSupportLibraries_jll is a stdlib, we can just directly open it - libstdcxx = get_csl_member(:libstdcxx) - if libstdcxx !== nothing - return nothing - end - - # Otherwise, look for it having already been loaded by something - libstdcxx_paths = filter!(x -> occursin("libstdc++", x), Libdl.dllist()) - if !isempty(libstdcxx_paths) - return Libdl.dlopen(first(libstdcxx_paths), Libdl.RTLD_NOLOAD)::Ptr{Cvoid} - end - - # One day, I hope to not be linking against libgfortran in base Julia - return nothing - end - # Brute-force our way through GLIBCXX_* symbols to discover which version we're linked against - libstdcxx = get_libstdcxx_handle() + libstdcxx = _get_libstdcxx_handle() if libstdcxx !== nothing # Try all GLIBCXX versions down to GCC v4.8: diff --git a/base/experimental.jl b/base/experimental.jl index f43bdb2800b75..d4532faec0963 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -655,26 +655,7 @@ function wait_with_timeout(c::GenericCondition; first::Bool=false, timeout::Real timer = Timer(timeout) waiter_left = Threads.Atomic{Bool}(false) # start a task to wait on the timer - t = Task() do - try - wait(timer) - catch e - # if the timer was closed, the waiting task has been scheduled; do nothing - e isa EOFError && return - end - dosched = false - lock(c.lock) - # Confirm that the waiting task is still in the wait queue and remove it. If - # the task is not in the wait queue, it must have been notified already so we - # don't do anything here. - if !waiter_left[] && ct.queue === c.waitq - dosched = true - Base.list_deletefirst!(c.waitq, ct) - end - unlock(c.lock) - # send the waiting task a timeout - dosched && schedule(ct, :timed_out) - end + t = _wait_with_timeout_task(c, ct, timer, waiter_left) t.sticky = false Threads._spawn_set_thrpool(t, :interactive) schedule(t) @@ -695,4 +676,28 @@ function wait_with_timeout(c::GenericCondition; first::Bool=false, timeout::Real end end +function _wait_with_timeout_task(c::GenericCondition, ct::Task, timer::Timer, + waiter_left::Threads.Atomic{Bool}) + return Task() do + try + wait(timer) + catch e + # if the timer was closed, the waiting task has been scheduled; do nothing + e isa EOFError && return + end + dosched = false + lock(c.lock) + # Confirm that the waiting task is still in the wait queue and remove it. If + # the task is not in the wait queue, it must have been notified already so we + # don't do anything here. + if !waiter_left[] && ct.queue === c.waitq + dosched = true + Base.list_deletefirst!(c.waitq, ct) + end + unlock(c.lock) + # send the waiting task a timeout + dosched && schedule(ct, :timed_out) + end +end + end # module diff --git a/base/file.jl b/base/file.jl index 4b0b756a00ae1..f5e0ad2e9dc6f 100644 --- a/base/file.jl +++ b/base/file.jl @@ -666,18 +666,18 @@ function temp_cleanup_purge_prelocked(force::Bool) end function temp_cleanup_purge_all() - may_need_gc = false + may_need_gc = Ref(false) @lock TEMP_CLEANUP_LOCK filter!(TEMP_CLEANUP) do (path, asap) try ispath(path) || return false - may_need_gc = true + may_need_gc[] = true return true catch ex ex isa InterruptException && rethrow() return true end end - if may_need_gc + if may_need_gc[] # this is only usually required on Sys.iswindows(), but may as well do it everywhere GC.gc(true) end @@ -1187,43 +1187,45 @@ julia> (path, dirs, files) = first(itr) ``` """ function walkdir(path = pwd(); topdown=true, follow_symlinks=false, onerror=throw) - function _walkdir(chnl, path) - tryf(f, p) = try - f(p) - catch err - isa(err, IOError) || rethrow() - try - onerror(err) - catch err2 - close(chnl, err2) - end - return - end - entries = tryf(_readdirx, path) - entries === nothing && return - dirs = Vector{String}() - files = Vector{String}() - for entry in entries - # If we're not following symlinks, then treat all symlinks as files - if (!follow_symlinks && something(tryf(islink, entry), true)) || !something(tryf(isdir, entry), false) - push!(files, entry.name) - else - push!(dirs, entry.name) - end - end + return Channel{Tuple{String,Vector{String},Vector{String}}}(chnl -> + _walkdir(chnl, path, topdown, follow_symlinks, onerror)) +end - if topdown - push!(chnl, (path, dirs, files)) - end - for dir in dirs - _walkdir(chnl, joinpath(path, dir)) +function _walkdir(chnl, path, topdown, follow_symlinks, onerror) + tryf(f, p) = try + f(p) + catch err + isa(err, IOError) || rethrow() + try + onerror(err) + catch err2 + close(chnl, err2) + end + return end - if !topdown - push!(chnl, (path, dirs, files)) + entries = tryf(_readdirx, path) + entries === nothing && return + dirs = Vector{String}() + files = Vector{String}() + for entry in entries + # If we're not following symlinks, then treat all symlinks as files + if (!follow_symlinks && something(tryf(islink, entry), true)) || !something(tryf(isdir, entry), false) + push!(files, entry.name) + else + push!(dirs, entry.name) end - nothing end - return Channel{Tuple{String,Vector{String},Vector{String}}}(chnl -> _walkdir(chnl, path)) + + if topdown + push!(chnl, (path, dirs, files)) + end + for dir in dirs + _walkdir(chnl, joinpath(path, dir), topdown, follow_symlinks, onerror) + end + if !topdown + push!(chnl, (path, dirs, files)) + end + nothing end function unlink(p::AbstractString) diff --git a/base/loading.jl b/base/loading.jl index 7c44b68f57413..204608bc0b72e 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2696,7 +2696,7 @@ function __require_prelocked(pkg::PkgId, env) end set_pkgorigin_version_path(pkg, path) - parallel_precompile_attempted = false # being safe to avoid getting stuck in a precompilepkgs loop + parallel_precompile_attempted = Ref(false) # being safe to avoid getting stuck in a precompilepkgs loop reasons = Dict{String,Int}() # attempt to load the module file via the precompile cache locations if JLOptions().use_compiled_modules != 0 @@ -2739,8 +2739,8 @@ function __require_prelocked(pkg::PkgId, env) unlock(require_lock) try - if !generating_output() && !parallel_precompile_attempted && !disable_parallel_precompile && @isdefined(Precompilation) - parallel_precompile_attempted = true + if !generating_output() && !parallel_precompile_attempted[] && !disable_parallel_precompile && @isdefined(Precompilation) + parallel_precompile_attempted[] = true precompiled = Precompilation.precompilepkgs([pkg]; _from_loading=true, ignore_loaded=false) # prcompiled returns either nothing, indicating it needs serial precompile, # or the entry(ies) that it found would be best to load (possibly because it just created it) @@ -3359,9 +3359,10 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in ocachefile = cache_objects ? ocachefile_from_cachefile(cachefile) : nothing # append checksum for so to the end of the .ji file: - crc_so = UInt32(0) - if cache_objects - crc_so = open(_crc32c, tmppath_so, "r") + crc_so = if cache_objects + open(_crc32c, tmppath_so, "r") + else + UInt32(0) end # append extra crc to the end of the .ji file: diff --git a/base/shell.jl b/base/shell.jl index 68925cbd5d5af..09b91918f2634 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -244,34 +244,40 @@ function print_shell_escaped_posixly(io::IO, args::AbstractString...) first || print(io, ' ') # avoid printing quotes around simple enough strings # that any (reasonable) shell will definitely never consider them to be special - have_single::Bool = false - have_double::Bool = false - function isword(c::AbstractChar) - if '0' <= c <= '9' || 'a' <= c <= 'z' || 'A' <= c <= 'Z' - # word characters - elseif c == '_' || c == '/' || c == '+' || c == '-' || c == '.' - # other common characters - elseif c == '\'' - have_single = true - elseif c == '"' - have_double && return false # switch to single quoting - have_double = true - elseif !first && c == '=' - # equals is special if it is first (e.g. `env=val ./cmd`) - else - # anything else - return false - end - return true - end if isempty(arg) print(io, "''") - elseif all(isword, arg) - have_single && (arg = replace(arg, '\'' => "\\'")) - have_double && (arg = replace(arg, '"' => "\\\"")) - print(io, arg) else - print(io, '\'', replace(arg, '\'' => "'\\''"), '\'') + have_single = false + have_double = false + isword = true + for c in arg + if '0' <= c <= '9' || 'a' <= c <= 'z' || 'A' <= c <= 'Z' + # word characters + elseif c == '_' || c == '/' || c == '+' || c == '-' || c == '.' + # other common characters + elseif c == '\'' + have_single = true + elseif c == '"' + if have_double + isword = false + break # switch to single quoting + end + have_double = true + elseif !first && c == '=' + # equals is special if it is first (e.g. `env=val ./cmd`) + else + # anything else + isword = false + break + end + end + if isword + have_single && (arg = replace(arg, '\'' => "\\'")) + have_double && (arg = replace(arg, '"' => "\\\"")) + print(io, arg) + else + print(io, '\'', replace(arg, '\'' => "'\\''"), '\'') + end end first = false end diff --git a/base/stacktraces.jl b/base/stacktraces.jl index b095f1f687807..0e807adb92839 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -167,20 +167,22 @@ function lookup(ip::Base.InterpreterIP) if isempty(scopes) return [StackFrame(func, file, line, code, false, false, 0)] end - closure = let inlined::Bool = false, def = def - function closure_inner(lno) - if inlined - def = lno.method - def isa Union{Method,Core.CodeInstance,MethodInstance} || (def = nothing) - else - def = codeinfo - end - sf = StackFrame(IRShow.normalize_method_name(lno.method), lno.file, lno.line, def, false, inlined, 0) - inlined = true - return sf + res = Vector{StackFrame}(undef, length(scopes)) + inlined = false + def_local = def + for i in eachindex(scopes) + lno = scopes[i] + if inlined + def_local = lno.method + def_local isa Union{Method,Core.CodeInstance,MethodInstance} || (def_local = nothing) + else + def_local = codeinfo end + res[i] = StackFrame(IRShow.normalize_method_name(lno.method), lno.file, lno.line, + def_local, false, inlined, 0) + inlined = true end - return map(closure, scopes) + return res end """ From 34e04ab26a4041074aa066553ba1383ba6b28dd1 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 29 Dec 2025 13:51:39 +0100 Subject: [PATCH 03/34] Remove many `Core.Box` in stdlibs and Base. (#60490) (cherry picked from commit d1b898de63a14d1a104086393253bbe8e77fbbfe) --- base/array.jl | 5 +++-- base/errorshow.jl | 8 +++++--- base/loading.jl | 10 +++++----- base/module.jl | 12 +++++------ base/runtime_internals.jl | 6 +++--- base/show.jl | 8 ++++---- stdlib/FileWatching/src/FileWatching.jl | 12 +++++------ .../InteractiveUtils/src/InteractiveUtils.jl | 8 ++++---- stdlib/InteractiveUtils/src/macros.jl | 5 +++-- stdlib/LibGit2/src/LibGit2.jl | 20 ++++++++++--------- stdlib/Markdown/src/render/html.jl | 16 ++++++++------- stdlib/Markdown/src/render/latex.jl | 7 ++++--- .../src/render/terminal/formatting.jl | 3 ++- stdlib/Markdown/src/render/terminal/render.jl | 11 +++++----- stdlib/Serialization/src/Serialization.jl | 11 +++++----- 15 files changed, 75 insertions(+), 67 deletions(-) diff --git a/base/array.jl b/base/array.jl index 4dcf385c49666..7cefac20fb377 100644 --- a/base/array.jl +++ b/base/array.jl @@ -2949,10 +2949,11 @@ end function indcopy(sz::Dims, I::Tuple{Vararg{RangeIndex}}) n = length(I) - s = sz[n] + _s = sz[n] for i = n+1:length(sz) - s *= sz[i] + _s *= sz[i] end + s = _s dst::typeof(I) = ntuple(i-> _findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I) src::typeof(I) = ntuple(i-> I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I) dst, src diff --git a/base/errorshow.jl b/base/errorshow.jl index 33edb4cee92a4..69b67bf36953a 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -1294,9 +1294,11 @@ function UndefVarError_hint(io::IO, ex::UndefVarError) warned = _UndefVarError_warnfor(io, [Base], var) if !warned - modules_to_check = (m for m in Base.loaded_modules_order - if m !== Core && m !== Base && m !== Main && m !== scope) - warned |= _UndefVarError_warnfor(io, modules_to_check, var) + let scope = scope + modules_to_check = (m for m in Base.loaded_modules_order + if m !== Core && m !== Base && m !== Main && m !== scope) + warned |= _UndefVarError_warnfor(io, modules_to_check, var) + end end warned || _UndefVarError_warnfor(io, [Core, Main], var) diff --git a/base/loading.jl b/base/loading.jl index 204608bc0b72e..f115037e02ccd 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -186,7 +186,7 @@ const slug_chars = String(['A':'Z'; 'a':'z'; '0':'9']) function slug(x::UInt32, p::Int) sprint(sizehint=p) do io y = x - n = length(slug_chars) + n = UInt32(length(slug_chars)) for i = 1:p y, d = divrem(y, n) write(io, slug_chars[1+d]) @@ -1555,8 +1555,8 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi if length(entries) != 1 error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))") end - entry = first(entries)::Dict{String, Any} - uuid = entry["uuid"]::String + local entry = first(entries)::Dict{String, Any} + local uuid = entry["uuid"]::String deps′_expanded[dep_name] = uuid end return deps′_expanded @@ -2734,7 +2734,7 @@ function __require_prelocked(pkg::PkgId, env) m = _require_search_from_serialized(pkg, path, UInt128(0), true) m isa Module && return m - verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug + local verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug @logmsg verbosity "Precompiling $(repr("text/plain", pkg))$(list_reasons(reasons))" unlock(require_lock) @@ -2776,7 +2776,7 @@ function __require_prelocked(pkg::PkgId, env) @goto load_from_cache # the new cachefile will have the newest mtime so will come first in the search elseif isa(loaded, Exception) if precompilableerror(loaded) - verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug + local verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug @logmsg verbosity "Skipping precompilation due to precompilable error. Importing $(repr("text/plain", pkg))." exception=loaded else @warn "The call to compilecache failed to create a usable precompiled cache file for $(repr("text/plain", pkg))" exception=loaded diff --git a/base/module.jl b/base/module.jl index c21414179446e..cefd6c9eca2d4 100644 --- a/base/module.jl +++ b/base/module.jl @@ -12,12 +12,12 @@ end function eval_import_path(at::Module, from::Union{Module, Nothing}, path::Expr, keyword::String) isempty(path.args) && error("malformed import statement") - i::Int = 1 + i = RefValue(1) function next!() local v - i <= length(path.args) || error("invalid module path") - v = path.args[i] - i += 1 + i[] <= length(path.args) || error("invalid module path") + v = path.args[i[]] + i[] += 1 v isa Symbol || throw(TypeError(Symbol(keyword), "", Symbol, v)) v end @@ -36,7 +36,7 @@ function eval_import_path(at::Module, from::Union{Module, Nothing}, path::Expr, m = require(at, v) m isa Module || error("failed to load module $v") end - i > lastindex(path.args) && return m, nothing + i[] > lastindex(path.args) && return m, nothing v = next!() else # `.A.B.C`: strip off leading dots by following parent links @@ -48,7 +48,7 @@ function eval_import_path(at::Module, from::Union{Module, Nothing}, path::Expr, while true v === :. && error("invalid $keyword path: \".\" in identifier path") - i > lastindex(path.args) && break + i[] > lastindex(path.args) && break m = getglobal(m, v) m isa Module || error("invalid $keyword path: \"$v\" does not name a module") v = next!() diff --git a/base/runtime_internals.jl b/base/runtime_internals.jl index 08e3337a915dd..4553ba0546db9 100644 --- a/base/runtime_internals.jl +++ b/base/runtime_internals.jl @@ -1874,11 +1874,11 @@ end length(specs::MethodSpecializations) = count(Returns(true), specs) function length(mt::Core.MethodTable) - n = 0 + n = Ref(0) visit(mt) do m - n += 1 + n[] += 1 end - return n::Int + return n[] end isempty(mt::Core.MethodTable) = (mt.defs === nothing) diff --git a/base/show.jl b/base/show.jl index 1c3f270333f60..0701d4c50558b 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2568,11 +2568,11 @@ function type_depth_limit(str::String, n::Int; maxdepth = nothing) levelcount = Int[] # number of nodes at each level strwid = 0 st_0, st_backslash, st_squote, st_dquote = 0,1,2,4 - state::Int = st_0 - stateis(s) = (state & s) != 0 + state = Ref(st_0) + stateis(s) = (state[] & s) != 0 quoted() = stateis(st_squote) || stateis(st_dquote) - enter(s) = (state |= s) - leave(s) = (state &= ~s) + enter(s) = (state[] |= s) + leave(s) = (state[] &= ~s) for (i, c) in ANSIIterator(str) if c isa ANSIDelimiter depths[i] = depth diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index ddaf36dfd33a4..7ebb7d7ddb085 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -801,19 +801,19 @@ function poll_fd(s::Union{RawFD, Sys.iswindows() ? WindowsRawSocket : Union{}}, fdw = _FDWatcher(s, mask) local timer # we need this flag to explicitly track whether we call `close` already, to update the internal refcount correctly - timedout = false # TODO: make this atomic + timedout = Ref(false) # TODO: make this atomic try if timeout_s >= 0 # delay creating the timer until shortly before we start the poll wait timer = Timer(timeout_s) do t - timedout && return - timedout = true + timedout[] && return + timedout[] = true close(fdw, mask) end try while true events = _wait(fdw, mask) - if timedout || !events.timedout + if timedout[] || !events.timedout @lock fdw.notify fdw.events &= ~events.events return events end @@ -827,8 +827,8 @@ function poll_fd(s::Union{RawFD, Sys.iswindows() ? WindowsRawSocket : Union{}}, end finally if @isdefined(timer) - if !timedout - timedout = true + if !timedout[] + timedout[] = true close(timer) close(fdw, mask) end diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index 60e2016cf910b..e7327ef5be331 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -351,8 +351,7 @@ function report_bug(kind) BugReportingId = Base.PkgId( Base.UUID((0xbcf9a6e7_4020_453c,0xb88e_690564246bb8)), "BugReporting") # Check if the BugReporting package exists in the current environment - local BugReporting - if Base.locate_package(BugReportingId) === nothing + BugReporting = if Base.locate_package(BugReportingId) === nothing @info "Package `BugReporting` not found - attempting temporary installation" # Create a temporary environment and add BugReporting let Pkg = Base.require_stdlib(Base.PkgId( @@ -364,13 +363,14 @@ function report_bug(kind) Base.ACTIVE_PROJECT[] = nothing pkgspec = @invokelatest Pkg.PackageSpec(BugReportingId.name, BugReportingId.uuid) @invokelatest Pkg.add(pkgspec) - BugReporting = Base.require(BugReportingId) + _BugReporting = Base.require(BugReportingId) append!(empty!(LOAD_PATH), old_load_path) Base.ACTIVE_PROJECT[] = old_active_project + _BugReporting end end else - BugReporting = Base.require(BugReportingId) + Base.require(BugReportingId) end return @invokelatest BugReporting.make_interactive_report(kind, ARGS) end diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 9a749752ef2c7..290f05eb86730 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -388,10 +388,11 @@ function gen_call_with_extracted_types(__module__, fcn, ex0, kws = Expr[]; is_so if isa(ex0, Expr) && ex0.head === :(=) && isa(ex0.args[1], Symbol) return gen_call_with_extracted_types(__module__, fcn, ex0.args[2], kws; is_source_reflection, supports_binding_reflection, use_signature_tuple) end - where_params = nothing + _where_params = nothing if isa(ex0, Expr) - ex0, where_params = extract_where_parameters(ex0) + ex0, _where_params = extract_where_parameters(ex0) end + where_params = _where_params if isa(ex0, Expr) if ex0.head === :do && isexpr(get(ex0.args, 1, nothing), :call) # Normalize `f(args...) do ... end` calls to `f(do_anonymous_function, args...)` diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index 30d141be146d7..861aebb9247bd 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -451,13 +451,15 @@ function branch!(repo::GitRepo, branch_name::AbstractString, branch_ref = new_branch_ref end end + + branch_ref′ = branch_ref # Avoids boxing `branch_ref` try #TODO: what if branch tracks other then "origin" remote if !isempty(track) # setup tracking try with(GitConfig, repo) do cfg set!(cfg, "branch.$branch_name.remote", Consts.REMOTE_ORIGIN) - set!(cfg, "branch.$branch_name.merge", name(branch_ref)) + set!(cfg, "branch.$branch_name.merge", name(branch_ref′)) end catch @warn "Please provide remote tracking for branch '$branch_name' in '$(path(repo))'" @@ -466,15 +468,15 @@ function branch!(repo::GitRepo, branch_name::AbstractString, if set_head # checkout selected branch - with(peel(GitTree, branch_ref)) do btree + with(peel(GitTree, branch_ref′)) do btree checkout_tree(repo, btree) end # switch head to the branch - head!(repo, branch_ref) + head!(repo, branch_ref′) end finally - close(branch_ref) + close(branch_ref′) end return end @@ -509,13 +511,13 @@ function checkout!(repo::GitRepo, commit::AbstractString = ""; isempty(commit) && return # grab head name - head_name = Consts.HEAD_FILE + head_name = Ref(Consts.HEAD_FILE) try with(head(repo)) do head_ref - head_name = shortname(head_ref) + head_name[] = shortname(head_ref) # if it is HEAD use short OID instead - if head_name == Consts.HEAD_FILE - head_name = string(GitHash(head_ref)) + if head_name[] == Consts.HEAD_FILE + head_name[] = string(GitHash(head_ref)) end end catch @@ -530,7 +532,7 @@ function checkout!(repo::GitRepo, commit::AbstractString = ""; checkout_tree(repo, peeled, options = force ? CheckoutOptions(checkout_strategy = Consts.CHECKOUT_FORCE) : CheckoutOptions()) GitReference(repo, obj_oid, force=force, - msg="libgit2.checkout: moving from $head_name to $(obj_oid))") + msg="libgit2.checkout: moving from $(head_name[]) to $(obj_oid))") return nothing end diff --git a/stdlib/Markdown/src/render/html.jl b/stdlib/Markdown/src/render/html.jl index 829fa6c7bf986..f2daddec9e814 100644 --- a/stdlib/Markdown/src/render/html.jl +++ b/stdlib/Markdown/src/render/html.jl @@ -65,11 +65,12 @@ function html(io::IO, header::Header{l}) where l end end -function html(io::IO, code::Code) +function html(io::IO, code′::Code) + if code′.language == "styled" + code′ = Code("", String(styled(code′.code))) + end + code = code′ withtag(io, :pre) do - if code.language == "styled" - code = Code("", String(styled(code.code))) - end maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : [] withtag(io, :code, maybe_lang...) do htmlesc(io, code.code) @@ -136,10 +137,11 @@ function htmlinline(io::IO, content::Vector) end end -function htmlinline(io::IO, code::Code) - if code.language == "styled" - code = Code("", String(styled(code.code))) +function htmlinline(io::IO, code′::Code) + if code′.language == "styled" + code′ = Code("", String(styled(code′.code))) end + code = code′ withtag(io, :code) do htmlesc(io, code.code) end diff --git a/stdlib/Markdown/src/render/latex.jl b/stdlib/Markdown/src/render/latex.jl index fad0508ce0e59..1d166af42c627 100644 --- a/stdlib/Markdown/src/render/latex.jl +++ b/stdlib/Markdown/src/render/latex.jl @@ -32,10 +32,11 @@ function latex(io::IO, header::Header{l}) where l println(io) end -function latex(io::IO, code::Code) - if code.language == "styled" - code = Code("", String(styled(code.code))) +function latex(io::IO, code′::Code) + if code′.language == "styled" + code′ = Code("", String(styled(code′.code))) end + code = code′ occursin("\\end{verbatim}", code.code) && error("Cannot include \"\\end{verbatim}\" in a latex code block") wrapblock(io, "verbatim") do println(io, code.code) diff --git a/stdlib/Markdown/src/render/terminal/formatting.jl b/stdlib/Markdown/src/render/terminal/formatting.jl index c9dadfb5f3d94..09dff9e367631 100644 --- a/stdlib/Markdown/src/render/terminal/formatting.jl +++ b/stdlib/Markdown/src/render/terminal/formatting.jl @@ -17,12 +17,13 @@ function with_output_annotations(f::Function, io::AnnotIO, annots::Pair{Symbol, @nospecialize annots aio = if io isa AnnotatedIOBuffer io else io.io end start = position(aio) + 1 - f(io) + v = f(io) stop = position(aio) sortedindex = searchsortedlast(aio.annotations, (region=start:stop,), by=a -> a.region) for (i, annot) in enumerate(annots) insert!(aio.annotations, sortedindex + i, (start:stop, annot...)) end + return v end """ diff --git a/stdlib/Markdown/src/render/terminal/render.jl b/stdlib/Markdown/src/render/terminal/render.jl index a97d273131536..2d486afef3bfd 100644 --- a/stdlib/Markdown/src/render/terminal/render.jl +++ b/stdlib/Markdown/src/render/terminal/render.jl @@ -92,20 +92,19 @@ function term(io::AnnotIO, md::Header{l}, columns) where l face = Symbol("markdown_h$l") underline = _header_underlines[l] pre = ' '^margin - local line_width - with_output_annotations(io, :face => face) do io + line_width = with_output_annotations(io, :face => face) do io headline = annotprint(terminline, md.text) lines = wraplines(headline, columns - 4margin) for (i, line) in enumerate(lines) print(io, pre, line) i < length(lines) && println(io) end - line_width = if length(lines) == 1 - min(textwidth(lines[end]), columns) + if length(lines) == 1 + return min(textwidth(lines[end]), columns) elseif length(lines) > 1 - max(textwidth(lines[end]), div(columns, 3)+length(pre)) + return max(textwidth(lines[end]), div(columns, 3)+length(pre)) else - 0 + return 0 end end header_width = max(0, line_width) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index ee40ebdd4abad..6f4894dcc059f 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -1067,11 +1067,10 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) nospecializeinfer = false constprop = 0x00 purity = 0x0000 - local template_or_is_opaque, template - with(current_module => mod) do - template_or_is_opaque = deserialize(s) + template_or_is_opaque = with(current_module => mod) do + deserialize(s) end - if isa(template_or_is_opaque, Bool) + template = if isa(template_or_is_opaque, Bool) is_for_opaque_closure = template_or_is_opaque if format_version(s) >= 24 nospecializeinfer = deserialize(s)::Bool @@ -1085,10 +1084,10 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) purity = UInt16(deserialize(s)::UInt8) end with(current_module => mod) do - template = deserialize(s) + deserialize(s) end else - template = template_or_is_opaque + template_or_is_opaque end generator = deserialize(s) recursion_relation = nothing From 0fc1f943f68a915c38787e45b79feaa9be9694f9 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 7 Jan 2026 21:01:15 +0100 Subject: [PATCH 04/34] Avoid more `Core.Box` in Base (and Compiler) (#60547) Moving out closures into separate functions, using `@lock` instead of `lock() do`. (cherry picked from commit 915a892ba340153b6d77084cb5f3d19108ea7874) --- Compiler/src/ssair/passes.jl | 72 ++++++++------- Compiler/src/ssair/show.jl | 165 ++++++++++++++++++----------------- base/precompilation.jl | 30 ++++--- base/weakkeydict.jl | 2 +- 4 files changed, 144 insertions(+), 125 deletions(-) diff --git a/Compiler/src/ssair/passes.jl b/Compiler/src/ssair/passes.jl index f5a766ae04b0f..76449d2d8f73c 100644 --- a/Compiler/src/ssair/passes.jl +++ b/Compiler/src/ssair/passes.jl @@ -361,20 +361,25 @@ function already_inserted(compact::IncrementalCompact, old::OldSSAValue) already_inserted_ssa(compact, compact.idx-1)(0, old) end -function already_inserted_ssa(compact::IncrementalCompact, processed_idx::Int) - return function did_already_insert(phi_arg::Int, old::OldSSAValue) - id = old.id - if id <= length(compact.ir.stmts) - return id <= processed_idx - end - id -= length(compact.ir.stmts) - if id <= length(compact.ir.new_nodes) - return did_already_insert(phi_arg, OldSSAValue(compact.ir.new_nodes.info[id].pos)) - end - id -= length(compact.ir.new_nodes) - @assert id <= length(compact.pending_nodes) - return !(id in compact.pending_perm) +function _already_inserted_ssa(compact::IncrementalCompact, processed_idx::Int, + phi_arg::Int, old::OldSSAValue) + id = old.id + if id <= length(compact.ir.stmts) + return id <= processed_idx + end + id -= length(compact.ir.stmts) + if id <= length(compact.ir.new_nodes) + return _already_inserted_ssa(compact, processed_idx, phi_arg, + OldSSAValue(compact.ir.new_nodes.info[id].pos)) end + id -= length(compact.ir.new_nodes) + @assert id <= length(compact.pending_nodes) + return !(id in compact.pending_perm) +end + +function already_inserted_ssa(compact::IncrementalCompact, processed_idx::Int) + return (phi_arg::Int, old::OldSSAValue) -> + _already_inserted_ssa(compact, processed_idx, phi_arg, old) end function is_pending(compact::IncrementalCompact, old::OldSSAValue) @@ -1644,6 +1649,25 @@ function reachable_blocks(cfg::CFG, from_bb::Int, to_bb::Int) return visited end +function _update_finalizer_insert!(ir::IRCode, lazypostdomtree::LazyPostDomtree, + finalizer_idx::Int, insert_bb::Int, + insert_idx::Union{Int,Nothing}, x::Union{Int,SSAUse}) + defuse_idx = x isa SSAUse ? x.idx : x + defuse_idx == finalizer_idx && return insert_bb, insert_idx + defuse_bb = block_for_inst(ir, defuse_idx) + new_insert_bb = nearest_common_dominator(get!(lazypostdomtree), + insert_bb, defuse_bb) + if new_insert_bb == insert_bb && insert_idx !== nothing + insert_idx = max(insert_idx::Int, defuse_idx) + elseif new_insert_bb == defuse_bb + insert_idx = defuse_idx + else + insert_idx = nothing + end + insert_bb = new_insert_bb + return insert_bb, insert_idx +end + function try_resolve_finalizer!(ir::IRCode, alloc_idx::Int, finalizer_idx::Int, defuse::SSADefUse, inlining::InliningState, lazydomtree::LazyDomtree, lazypostdomtree::LazyPostDomtree, @nospecialize(info::CallInfo)) @@ -1665,24 +1689,12 @@ function try_resolve_finalizer!(ir::IRCode, alloc_idx::Int, finalizer_idx::Int, # Check #2: The insertion block for the finalizer is the post-dominator of all uses insert_bb::Int = finalizer_bb insert_idx::Union{Int,Nothing} = finalizer_idx - function note_defuse!(x::Union{Int,SSAUse}) - defuse_idx = x isa SSAUse ? x.idx : x - defuse_idx == finalizer_idx && return nothing - defuse_bb = block_for_inst(ir, defuse_idx) - new_insert_bb = nearest_common_dominator(get!(lazypostdomtree), - insert_bb, defuse_bb) - if new_insert_bb == insert_bb && insert_idx !== nothing - insert_idx = max(insert_idx::Int, defuse_idx) - elseif new_insert_bb == defuse_bb - insert_idx = defuse_idx - else - insert_idx = nothing - end - insert_bb = new_insert_bb - nothing + for x in defuse.uses + insert_bb, insert_idx = _update_finalizer_insert!(ir, lazypostdomtree, finalizer_idx, insert_bb, insert_idx, x) + end + for x in defuse.defs + insert_bb, insert_idx = _update_finalizer_insert!(ir, lazypostdomtree, finalizer_idx, insert_bb, insert_idx, x) end - foreach(note_defuse!, defuse.uses) - foreach(note_defuse!, defuse.defs) insert_bb != 0 || return nothing # verify post-dominator of all uses exists if !OptimizationParams(inlining.interp).assume_fatal_throw diff --git a/Compiler/src/ssair/show.jl b/Compiler/src/ssair/show.jl index 3331a0663450e..f7c3ac8888916 100644 --- a/Compiler/src/ssair/show.jl +++ b/Compiler/src/ssair/show.jl @@ -534,37 +534,33 @@ function DILineInfoPrinter(debuginfo, def, showtypes::Bool=false) started::Bool = false if !update_line_only && showtypes && !isa(frame.method, Symbol) && nctx != 1 print(io, linestart) - with_output_color(linecolor, io) do io - print(io, indent("│")) - print(io, "┌ invoke ", frame.method) - println(io) - end + printstyled(io, indent("│"), color=linecolor) + printstyled(io, "┌ invoke ", frame.method, color=linecolor) + println(io) started = true end print(io, linestart) - with_output_color(linecolor, io) do io - print(io, indent("│")) - push!(context, frame) - if update_line_only - update_line_only = false - else - context_depth[] += 1 - nctx != 1 && print(io, started ? "│" : "┌") - end - print(io, " @ ", frame.file) - if frame.line != typemax(frame.line) && frame.line != 0 - print(io, ":", frame.line) - end - print(io, " within `", method_name(frame), "`") - if collapse - method = method_name(frame) - while nctx < nframes - frame = DI[nframes - nctx] - method_name(frame) === method || break - nctx += 1 - push!(context, frame) - print(io, " @ ", frame.file, ":", frame.line) - end + printstyled(io, indent("│"), color=linecolor) + push!(context, frame) + if update_line_only + update_line_only = false + else + context_depth[] += 1 + nctx != 1 && printstyled(io, started ? "│" : "┌", color=linecolor) + end + printstyled(io, " @ ", frame.file, color=linecolor) + if frame.line != typemax(frame.line) && frame.line != 0 + printstyled(io, ":", frame.line, color=linecolor) + end + printstyled(io, " within `", method_name(frame), "`", color=linecolor) + if collapse + method = method_name(frame) + while nctx < nframes + frame = DI[nframes - nctx] + method_name(frame) === method || break + nctx += 1 + push!(context, frame) + printstyled(io, " @ ", frame.file, ":", frame.line, color=linecolor) end end println(io) @@ -681,6 +677,60 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, sptypes, used, cfg, bb_idx; pop_new_node!, only_after, config.bb_color, config.label_dynamic_calls) end +function _print_ir_indentation(io::IO, cfg::CFG, bb_idx::Int, max_bb_idx_size::Int, bb_color, + line_info_preprinter, idx::Int, i::Int; final::Bool=true) + # Compute BB guard rail + if bb_idx > length(cfg.blocks) + # If invariants are violated, print a special leader + linestart = " "^(max_bb_idx_size + 2) # not inside a basic block bracket + inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) + printstyled(io, "!!! ", "─"^max_bb_idx_size, color=bb_color) + else + bbrange = cfg.blocks[bb_idx].stmts + # Print line info update + linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=bb_color), context=io) + linestart *= " "^max_bb_idx_size + # idx == 0 means only indentation is printed, so we don't print linfos + # multiple times if the are new nodes + inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) + + if i == 1 && idx == first(bbrange) + bb_idx_str = string(bb_idx) + bb_pad = max_bb_idx_size - length(bb_idx_str) + bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" + printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=bb_color) + elseif final && idx == last(bbrange) # print separator + printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=bb_color) + else + printstyled(io, "│ ", " "^max_bb_idx_size, color=bb_color) + end + end + print(io, inlining_indent, " ") + return nothing +end + +function _print_ir_new_node(io::IO, node, code, sptypes::Vector{VarState}, used::BitSet, maxlength_idx::Int, + label_dynamic_calls::Bool, line_info_postprinter, cfg::CFG, bb_idx::Int, + max_bb_idx_size::Int, bb_color, line_info_preprinter, idx::Int, i::Int; final::Bool=true) + _print_ir_indentation(io, cfg, bb_idx, max_bb_idx_size, bb_color, line_info_preprinter, idx, i; final) + + node_idx, new_node_inst, new_node_type = node + @assert new_node_inst !== UNDEF # we filtered these out earlier + show_type = should_print_ssa_type(new_node_inst) + with_output_color(:green, io) do io′ + print_stmt(io′, node_idx, new_node_inst, code, sptypes, used, maxlength_idx, false, show_type, label_dynamic_calls) + end + + if new_node_type === UNDEF + # Try to be robust against errors + printstyled(io, "::#UNDEF", color=:red) + else + line_info_postprinter(io; type = new_node_type, used = node_idx in used, show_type, idx = node_idx) + end + println(io) + return nothing +end + function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, idx::Int, line_info_preprinter, line_info_postprinter, sptypes::Vector{VarState}, used::BitSet, cfg::CFG, bb_idx::Int; pop_new_node! = Returns(nothing), only_after::Bool=false, bb_color=:light_black, label_dynamic_calls::Bool=true) @@ -703,58 +753,11 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, end i = 1 - function print_indentation(final::Bool=true) - # Compute BB guard rail - if bb_idx > length(cfg.blocks) - # If invariants are violated, print a special leader - linestart = " "^(max_bb_idx_size + 2) # not inside a basic block bracket - inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) - printstyled(io, "!!! ", "─"^max_bb_idx_size, color=bb_color) - else - bbrange = cfg.blocks[bb_idx].stmts - # Print line info update - linestart = idx == first(bbrange) ? " " : sprint(io -> printstyled(io, "│ ", color=bb_color), context=io) - linestart *= " "^max_bb_idx_size - # idx == 0 means only indentation is printed, so we don't print linfos - # multiple times if the are new nodes - inlining_indent = line_info_preprinter(io, linestart, i == 1 ? idx : 0) - - if i == 1 && idx == first(bbrange) - bb_idx_str = string(bb_idx) - bb_pad = max_bb_idx_size - length(bb_idx_str) - bb_type = length(cfg.blocks[bb_idx].preds) <= 1 ? "─" : "┄" - printstyled(io, bb_idx_str, " ", bb_type, "─"^bb_pad, color=bb_color) - elseif final && idx == last(bbrange) # print separator - printstyled(io, "└", "─"^(1 + max_bb_idx_size), color=bb_color) - else - printstyled(io, "│ ", " "^max_bb_idx_size, color=bb_color) - end - end - print(io, inlining_indent, " ") - end - # first, print new nodes that are to be inserted before the current statement - function print_new_node(node; final::Bool=true) - print_indentation(final) - - node_idx, new_node_inst, new_node_type = node - @assert new_node_inst !== UNDEF # we filtered these out earlier - show_type = should_print_ssa_type(new_node_inst) - let maxlength_idx=maxlength_idx, show_type=show_type - with_output_color(:green, io) do io′ - print_stmt(io′, node_idx, new_node_inst, code, sptypes, used, maxlength_idx, false, show_type, label_dynamic_calls) - end - end - - if new_node_type === UNDEF # try to be robust against errors - printstyled(io, "::#UNDEF", color=:red) - else - line_info_postprinter(io; type = new_node_type, used = node_idx in used, show_type, idx = node_idx) - end - println(io) - end while (next = pop_new_node!(idx)) !== nothing - only_after || print_new_node(next; final=false) + only_after || _print_ir_new_node(io, next, code, sptypes, used, maxlength_idx, label_dynamic_calls, + line_info_postprinter, cfg, bb_idx, max_bb_idx_size, bb_color, + line_info_preprinter, idx, i; final=false) i += 1 end @@ -766,7 +769,7 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, # FIXME: `only_after` is hack so that we can call this function to print uncompacted # attach-after nodes when the current node has already been compated already if !only_after - print_indentation(next===nothing) + _print_ir_indentation(io, cfg, bb_idx, max_bb_idx_size, bb_color, line_info_preprinter, idx, i; final=next===nothing) if code isa CodeInfo stmt = statement_indices_to_labels(stmt, cfg) end @@ -786,7 +789,9 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, # finally, print new nodes that are to be inserted after the current statement while next !== nothing - print_new_node(next) + _print_ir_new_node(io, next, code, sptypes, used, maxlength_idx, label_dynamic_calls, + line_info_postprinter, cfg, bb_idx, max_bb_idx_size, bb_color, + line_info_preprinter, idx, i) i += 1 next = pop_new_node!(idx; attach_after=true) end diff --git a/base/precompilation.jl b/base/precompilation.jl index adecc50f6d1e4..f43fee770c94a 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -490,6 +490,21 @@ function precompilepkgs(pkgs::Union{Vector{String}, Vector{PkgId}}=String[]; IOContext{IO}(io), fancyprint, manifest, ignore_loaded) end +function _visit_indirect_deps!(direct_deps::Dict{PkgId, Vector{PkgId}}, visited::Set{PkgId}, + node::PkgId, all_deps::Set{PkgId}) + if node in visited + return + end + push!(visited, node) + for dep in get(Set{PkgId}, direct_deps, node) + if !(dep in all_deps) + push!(all_deps, dep) + _visit_indirect_deps!(direct_deps, visited, dep, all_deps) + end + end + return +end + function _precompilepkgs(pkgs::Union{Vector{String}, Vector{PkgId}}, internal_call::Bool, strict::Bool, @@ -626,25 +641,12 @@ function _precompilepkgs(pkgs::Union{Vector{String}, Vector{PkgId}}, # A package depends on an extension if it (indirectly) depends on all extension triggers function expand_indirect_dependencies(direct_deps) - function visit!(visited, node, all_deps) - if node in visited - return - end - push!(visited, node) - for dep in get(Set{Base.PkgId}, direct_deps, node) - if !(dep in all_deps) - push!(all_deps, dep) - visit!(visited, dep, all_deps) - end - end - end - local indirect_deps = Dict{Base.PkgId, Set{Base.PkgId}}() for package in keys(direct_deps) # Initialize a set to keep track of all dependencies for 'package' all_deps = Set{Base.PkgId}() visited = Set{Base.PkgId}() - visit!(visited, package, all_deps) + _visit_indirect_deps!(direct_deps, visited, package, all_deps) # Update direct_deps with the complete set of dependencies for 'package' indirect_deps[package] = all_deps end diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 1283dc9cbc8cb..e04f8cdd4a1f6 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -195,7 +195,7 @@ function length(t::WeakKeyDict) end function iterate(t::WeakKeyDict{K,V}, state...) where {K, V} - return lock(t) do + @lock t begin while true y = iterate(t.ht, state...) y === nothing && return nothing From 7928de94c9f934659e45a33db80a305f43d8a828 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 9 Jan 2026 14:35:26 +0100 Subject: [PATCH 05/34] avoid some more `Core.Box` in Base and SharedArrays (#60599) (cherry picked from commit f20e7549dc1e7a04849566cb80e0507969f848eb) --- base/loading.jl | 2 +- base/timing.jl | 15 +++++----- base/views.jl | 4 +-- stdlib/SharedArrays/src/SharedArrays.jl | 39 ++++++++++++------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index f115037e02ccd..11b965235f7d0 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2728,7 +2728,7 @@ function __require_prelocked(pkg::PkgId, env) if !generating_output(#=incremental=#false) project = active_project() # spawn off a new incremental pre-compile task for recursive `require` calls - loaded = let path = path, reasons = reasons + loaded = let path = path, reasons = reasons, parallel_precompile_attempted = parallel_precompile_attempted 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) diff --git a/base/timing.jl b/base/timing.jl index 22e4b5a0065bc..12e41491c80cf 100644 --- a/base/timing.jl +++ b/base/timing.jl @@ -220,30 +220,31 @@ function time_print(io::IO, elapsedtime, bytes=0, gctime=0, allocs=0, lock_confl print(io, timestr, " seconds") parens = bytes != 0 || allocs != 0 || gctime > 0 || lock_conflicts > 0 || compile_time > 0 parens && print(io, " (") - if bytes != 0 || allocs != 0 - allocs, ma = prettyprint_getunits(allocs, length(_cnt_units), Int64(1000)) + had_allocs = bytes != 0 || allocs != 0 + if had_allocs + allocs_scaled, ma = prettyprint_getunits(allocs, length(_cnt_units), Int64(1000)) if ma == 1 - print(io, Int(allocs), _cnt_units[ma], allocs==1 ? " allocation: " : " allocations: ") + print(io, Int(allocs_scaled), _cnt_units[ma], allocs_scaled==1 ? " allocation: " : " allocations: ") else - print(io, Ryu.writefixed(Float64(allocs), 2), _cnt_units[ma], " allocations: ") + print(io, Ryu.writefixed(Float64(allocs_scaled), 2), _cnt_units[ma], " allocations: ") end print(io, format_bytes(bytes)) end if gctime > 0 - if bytes != 0 || allocs != 0 + if had_allocs print(io, ", ") end print(io, Ryu.writefixed(Float64(100*gctime/elapsedtime), 2), "% gc time") end if lock_conflicts > 0 - if bytes != 0 || allocs != 0 || gctime > 0 + if had_allocs || gctime > 0 print(io, ", ") end plural = lock_conflicts == 1 ? "" : "s" print(io, lock_conflicts, " lock conflict$plural") end if compile_time > 0 - if bytes != 0 || allocs != 0 || gctime > 0 || lock_conflicts > 0 + if had_allocs || gctime > 0 || lock_conflicts > 0 print(io, ", ") end print(io, Ryu.writefixed(Float64(100*compile_time/elapsedtime), 2), "% compilation time") diff --git a/base/views.jl b/base/views.jl index d205b1b38dee4..fca7e7ced9027 100644 --- a/base/views.jl +++ b/base/views.jl @@ -58,8 +58,8 @@ function replace_ref_begin_end_!(__module__::Module, ex, withex, in_quote_contex temp_vars = Tuple{Int,Symbol}[] for j = 2:J n = nx === 0 ? ni : :($nx + $ni) - exj, used = replace_ref_begin_end_!(__module__, ref_ex.args[j], (:($firstindex($S,$n)),:($lastindex($S,$n))), in_quote_context, escs) - used_S |= used + exj, used_arg = replace_ref_begin_end_!(__module__, ref_ex.args[j], (:($firstindex($S,$n)),:($lastindex($S,$n))), in_quote_context, escs) + used_S |= used_arg ref_ex.args[j] = exj ni += 1 if need_temps diff --git a/stdlib/SharedArrays/src/SharedArrays.jl b/stdlib/SharedArrays/src/SharedArrays.jl index 6106bc9c3c81a..fdbfc989c8994 100644 --- a/stdlib/SharedArrays/src/SharedArrays.jl +++ b/stdlib/SharedArrays/src/SharedArrays.jl @@ -113,20 +113,21 @@ function SharedArray{T,N}(dims::Dims{N}; init=false, pids=Int[]) where {T,N} local shmmem_create_pid try # On OSX, the shm_seg_name length must be <= 31 characters (including the terminating NULL character) - shm_seg_name = "/jl$(lpad(string(getpid() % 10^6), 6, "0"))$(randstring(20))" + seg_name = "/jl$(lpad(string(getpid() % 10^6), 6, "0"))$(randstring(20))" + shm_seg_name = seg_name if onlocalhost shmmem_create_pid = myid() - s = shm_mmap_array(T, dims, shm_seg_name, JL_O_CREAT | JL_O_RDWR) + s = shm_mmap_array(T, dims, seg_name, JL_O_CREAT | JL_O_RDWR) else # The shared array is created on a remote machine shmmem_create_pid = pids[1] remotecall_fetch(pids[1]) do - shm_mmap_array(T, dims, shm_seg_name, JL_O_CREAT | JL_O_RDWR) + shm_mmap_array(T, dims, seg_name, JL_O_CREAT | JL_O_RDWR) nothing end end - func_mapshmem = () -> shm_mmap_array(T, dims, shm_seg_name, JL_O_RDWR) + func_mapshmem = () -> shm_mmap_array(T, dims, seg_name, JL_O_RDWR) refs = Vector{Future}(undef, length(pids)) for (i, p) in enumerate(pids) @@ -141,13 +142,13 @@ function SharedArray{T,N}(dims::Dims{N}; init=false, pids=Int[]) where {T,N} # All good, immediately unlink the segment. if (prod(dims) > 0) && (sizeof(T) > 0) if onlocalhost - rc = shm_unlink(shm_seg_name) + rc = shm_unlink(seg_name) else - rc = remotecall_fetch(shm_unlink, shmmem_create_pid, shm_seg_name) + rc = remotecall_fetch(shm_unlink, shmmem_create_pid, seg_name) end - systemerror("Error unlinking shmem segment " * shm_seg_name, rc != 0) + systemerror("Error unlinking shmem segment " * seg_name, rc != 0) end - S = SharedArray{T,N}(dims, pids, refs, shm_seg_name, s) + S = SharedArray{T,N}(dims, pids, refs, seg_name, s) initialize_shared_array(S, onlocalhost, init, pids) shm_seg_name = "" @@ -185,23 +186,21 @@ function SharedArray{T,N}(filename::AbstractString, dims::NTuple{N,Int}, offset: # If not supplied, determine the appropriate mode have_file = onlocalhost ? isfile(filename) : remotecall_fetch(isfile, pids[1], filename) - if mode === nothing - mode = have_file ? "r+" : "w+" - end - workermode = mode == "w+" ? "r+" : mode # workers don't truncate! + mode_val = mode === nothing ? (have_file ? "r+" : "w+") : mode + workermode = mode_val == "w+" ? "r+" : mode_val # workers don't truncate! # Ensure the file will be readable - if !(mode in ("r", "r+", "w+", "a+")) - throw(ArgumentError("mode must be readable, but $mode is not")) + if !(mode_val in ("r", "r+", "w+", "a+")) + throw(ArgumentError("mode must be readable, but $mode_val is not")) end if init !== false typeassert(init, Function) - if !(mode in ("r+", "w+", "a+")) - throw(ArgumentError("cannot initialize unwritable array (mode = $mode)")) + if !(mode_val in ("r+", "w+", "a+")) + throw(ArgumentError("cannot initialize unwritable array (mode = $mode_val)")) end end - if mode == "r" && !isfile(filename) - throw(ArgumentError("file $filename does not exist, but mode $mode cannot create it")) + if mode_val == "r" && !isfile(filename) + throw(ArgumentError("file $filename does not exist, but mode $mode_val cannot create it")) end # Create the file if it doesn't exist, map it if it does @@ -211,13 +210,13 @@ function SharedArray{T,N}(filename::AbstractString, dims::NTuple{N,Int}, offset: end s = Array{T}(undef, ntuple(d->0,N)) if onlocalhost - s = func_mmap(mode) + s = func_mmap(mode_val) refs[1] = remotecall(pids[1]) do func_mmap(workermode) end else refs[1] = remotecall_wait(pids[1]) do - func_mmap(mode) + func_mmap(mode_val) end end From 0fedb1ccac1de78560540731a192a59ef389d0cd Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 9 Jan 2026 15:50:20 +0100 Subject: [PATCH 06/34] bump StyledStrings to latest release-1.13 --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - stdlib/StyledStrings.version | 4 ++-- 5 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/md5 create mode 100644 deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/sha512 delete mode 100644 deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/md5 delete mode 100644 deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/sha512 diff --git a/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/md5 b/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/md5 new file mode 100644 index 0000000000000..6324ad7fdfe90 --- /dev/null +++ b/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/md5 @@ -0,0 +1 @@ +9ff35ff7277387d7895533f4c99de1ad diff --git a/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/sha512 b/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/sha512 new file mode 100644 index 0000000000000..115da6196c9eb --- /dev/null +++ b/deps/checksums/StyledStrings-24cd74a309a29dd0a240884c1ced9fef7f06ba64.tar.gz/sha512 @@ -0,0 +1 @@ +a8e233ea4203ce8cd6820279271f03b080515a45fcbcda14a634441d556da8260a2c9fcc7cfa3f0fea5196f16cc74b64e91644afedc11fa7d71c71425e15bfb0 diff --git a/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/md5 b/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/md5 deleted file mode 100644 index e58ba4519f3ff..0000000000000 --- a/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ad2e6ba06c98990865f808b26b8f148c diff --git a/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/sha512 b/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/sha512 deleted file mode 100644 index 8f7b0e2111bce..0000000000000 --- a/deps/checksums/StyledStrings-68bf7b1f83f334391dc05fda34f48267e04e2bd0.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -24e530c095f7838380adeb6f45349cf776df524a2fc721eb8b11411d25bc132a58c1048a89d630ba1ee66bf9a52cce9a0fbe2b4a76c33b11160c00ecb7a919a1 diff --git a/stdlib/StyledStrings.version b/stdlib/StyledStrings.version index b77e1a8cd9f59..54d26eb44a4ab 100644 --- a/stdlib/StyledStrings.version +++ b/stdlib/StyledStrings.version @@ -1,4 +1,4 @@ -STYLEDSTRINGS_BRANCH = main -STYLEDSTRINGS_SHA1 = 68bf7b1f83f334391dc05fda34f48267e04e2bd0 +STYLEDSTRINGS_BRANCH = release-1.13 +STYLEDSTRINGS_SHA1 = 24cd74a309a29dd0a240884c1ced9fef7f06ba64 STYLEDSTRINGS_GIT_URL := https://github.com/JuliaLang/StyledStrings.jl.git STYLEDSTRINGS_TAR_URL = https://api.github.com/repos/JuliaLang/StyledStrings.jl/tarball/$1 From 1e8985deca9e6071541ea7d36c5b5cf49ae3db24 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sat, 10 Jan 2026 16:25:08 -0500 Subject: [PATCH 07/34] =?UTF-8?q?=F0=9F=A4=96=20[backports-release-1.13]?= =?UTF-8?q?=20Bump=20Downloads=20stdlib=204e20d02=20=E2=86=92=20f72cd4d=20?= =?UTF-8?q?(#60615)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: KristofferC <1282691+KristofferC@users.noreply.github.com> --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/Downloads.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/md5 delete mode 100644 deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/sha512 create mode 100644 deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/md5 create mode 100644 deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/sha512 diff --git a/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/md5 b/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/md5 deleted file mode 100644 index 54152fc3afad5..0000000000000 --- a/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ffdec003d29b6a45229b1fc3358accd3 diff --git a/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/sha512 b/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/sha512 deleted file mode 100644 index a507712c72bdd..0000000000000 --- a/deps/checksums/Downloads-4e20d029c723199c0b8ea0e2418ff240d25ddaef.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f4d399f20b852a69503a939bbffee365efc9aa2202c8dbc3b3de63728e7183c8bcf922c8607bc29922737eb66f516c3f52f1a1898c4283c33bd856b38473dc5a diff --git a/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/md5 b/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/md5 new file mode 100644 index 0000000000000..4942dcba0de8b --- /dev/null +++ b/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/md5 @@ -0,0 +1 @@ +fb233f171b86bf48bbfc7fb6d62faf34 diff --git a/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/sha512 b/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/sha512 new file mode 100644 index 0000000000000..a520370e45343 --- /dev/null +++ b/deps/checksums/Downloads-f72cd4d87b424fc48e1137c1fd1fbcec18f49371.tar.gz/sha512 @@ -0,0 +1 @@ +213f43411aa21b420ef430aa4210ad8c7d993dd940b71ae7a2f7aec756c214d607e6861ce502c88aad5ba516abcdf420b4b16ba8514a27e4d91f38841cf165e4 diff --git a/stdlib/Downloads.version b/stdlib/Downloads.version index bf92107ba1816..b91672eebbf55 100644 --- a/stdlib/Downloads.version +++ b/stdlib/Downloads.version @@ -1,4 +1,4 @@ DOWNLOADS_BRANCH = master -DOWNLOADS_SHA1 = 4e20d029c723199c0b8ea0e2418ff240d25ddaef +DOWNLOADS_SHA1 = f72cd4d87b424fc48e1137c1fd1fbcec18f49371 DOWNLOADS_GIT_URL := https://github.com/JuliaLang/Downloads.jl.git DOWNLOADS_TAR_URL = https://api.github.com/repos/JuliaLang/Downloads.jl/tarball/$1 From 3fb442ecc706c078c09cfd1f7f27cae3b46d2110 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sat, 10 Jan 2026 16:25:12 -0500 Subject: [PATCH 08/34] =?UTF-8?q?=F0=9F=A4=96=20[backports-release-1.13]?= =?UTF-8?q?=20Bump=20Tar=20stdlib=209dd8ed1=20=E2=86=92=2010e4e96=20(#6061?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: KristofferC <1282691+KristofferC@users.noreply.github.com> --- .../Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/md5 | 1 + .../Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/sha512 | 1 + .../Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/md5 | 1 - .../Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/sha512 | 1 - stdlib/Tar.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/md5 create mode 100644 deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/sha512 delete mode 100644 deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/md5 delete mode 100644 deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/sha512 diff --git a/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/md5 b/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/md5 new file mode 100644 index 0000000000000..e7c9d7e636a90 --- /dev/null +++ b/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/md5 @@ -0,0 +1 @@ +e817cf442bba59b5eb51a28861d7dcda diff --git a/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/sha512 b/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/sha512 new file mode 100644 index 0000000000000..a2054c12c8a50 --- /dev/null +++ b/deps/checksums/Tar-10e4e964e372dc644c375e99c43d907067c45190.tar.gz/sha512 @@ -0,0 +1 @@ +1e61e3170cae3c538695c69b6386a198bad98b483ed559225faa1061dc7a1f912c6543f8fe2441c5d4e36ded0f59ab7d86e482e640693f25bba39fe5ee99f4f6 diff --git a/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/md5 b/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/md5 deleted file mode 100644 index fbf406449fb0b..0000000000000 --- a/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -158dbd6c1ac3e7e17673dcdb8682029c diff --git a/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/sha512 b/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/sha512 deleted file mode 100644 index f7612ac2001ac..0000000000000 --- a/deps/checksums/Tar-9dd8ed1b5f8503804de49da9272150dcc18ca7c7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -acd722496955cd6a8f1c7ccb1bd0766666b566cac91975b7a2fd0dcdc13e6638aa53beebf144a39e9c3f880818ba1e71ea8e60396d94fa333962fd4f707eb8c7 diff --git a/stdlib/Tar.version b/stdlib/Tar.version index ac1022efce7b5..f62e5752a7c39 100644 --- a/stdlib/Tar.version +++ b/stdlib/Tar.version @@ -1,4 +1,4 @@ TAR_BRANCH = master -TAR_SHA1 = 9dd8ed1b5f8503804de49da9272150dcc18ca7c7 +TAR_SHA1 = 10e4e964e372dc644c375e99c43d907067c45190 TAR_GIT_URL := https://github.com/JuliaIO/Tar.jl.git TAR_TAR_URL = https://api.github.com/repos/JuliaIO/Tar.jl/tarball/$1 From 1a8597cf3cb1556a751859c53c81fbf6c8c0a5bf Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:17:47 -0500 Subject: [PATCH 09/34] =?UTF-8?q?=F0=9F=A4=96=20[backports-release-1.13]?= =?UTF-8?q?=20Bump=20SparseArrays=20stdlib=2026c80c8=20=E2=86=92=206b7e9ef?= =?UTF-8?q?=20(#60700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: SparseArrays URL: https://github.com/JuliaSparse/SparseArrays.jl.git Stdlib branch: release-1.13 Julia branch: backports-release-1.13 Old commit: 26c80c8 New commit: 6b7e9ef Julia version: 1.13.0-beta1 SparseArrays version: 1.13.0 Bump invoked by: @dkarrasch Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaSparse/SparseArrays.jl/compare/26c80c8b45dc2dca92788332a40a99b6c360d05a...6b7e9ef30624f25d97bce047ad781a25bebe5551 ``` $ git log --oneline 26c80c8..6b7e9ef 6b7e9ef Backports to release v1.13 (#665) 0a37c0c Update CI workflow for Julia and checkout action (#659) 1216e80 Separate out tests for the GPL build and do not run them when GPL libs are not present (#658) 0f0cd32 Remove more bounds checks (#661) d53ae09 Fix generic sparse-dense multiplication (#663) ``` Co-authored-by: dkarrasch <26658441+dkarrasch@users.noreply.github.com> --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/SparseArrays.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/md5 delete mode 100644 deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/sha512 create mode 100644 deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/md5 create mode 100644 deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/md5 b/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/md5 deleted file mode 100644 index 64ee597144a75..0000000000000 --- a/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -4b7f1fbb158328c4337ef7bcf2bb81b9 diff --git a/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/sha512 b/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/sha512 deleted file mode 100644 index ecb23d19f89f6..0000000000000 --- a/deps/checksums/SparseArrays-26c80c8b45dc2dca92788332a40a99b6c360d05a.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -c9e32cfb5ba14bcbab391edf7a327c147d9e4169586c5d8e934e6bcf8d03e8741196f85dbdef05621a0af38e0c394c13f3336b03840bf3770ae6f999b4752e14 diff --git a/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/md5 b/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/md5 new file mode 100644 index 0000000000000..a7ac76aa09e8a --- /dev/null +++ b/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/md5 @@ -0,0 +1 @@ +44270a346f9ddd509cea805b9bc81156 diff --git a/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/sha512 b/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/sha512 new file mode 100644 index 0000000000000..fac4f9ef0e691 --- /dev/null +++ b/deps/checksums/SparseArrays-6b7e9ef30624f25d97bce047ad781a25bebe5551.tar.gz/sha512 @@ -0,0 +1 @@ +24997365906fb555362223b9ec49dfa1990d09a83685e4b149e34687377ec11616d97b38de99b9d750fd99ee4f62b3d6462790f0fd26c1dfd26a1ca341ef5658 diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 1cf516bb816fb..86daeecdabe21 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = release-1.13 -SPARSEARRAYS_SHA1 = 26c80c8b45dc2dca92788332a40a99b6c360d05a +SPARSEARRAYS_SHA1 = 6b7e9ef30624f25d97bce047ad781a25bebe5551 SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 From 4c1b9d9e9f8d9c6ec0c64dc015b8c800ff96a4bc Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 20 Jan 2026 21:59:19 +0100 Subject: [PATCH 10/34] [1.13] Backport #60718+#60746: Fix and test `jl_method_lookup_by_tt` (#60748) --- src/gf.c | 12 ++++++------ test/core.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/gf.c b/src/gf.c index 1d3a9636ddfa9..b18a791945578 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1926,7 +1926,7 @@ JL_DLLEXPORT jl_typemap_entry_t *jl_mt_find_cache_entry(jl_methcache_t *mc JL_PR return entry; } -static jl_method_instance_t *jl_mt_assoc_by_type(jl_methcache_t *mc JL_PROPAGATES_ROOT, jl_datatype_t *tt JL_MAYBE_UNROOTED, size_t world) +static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_methcache_t *mc JL_PROPAGATES_ROOT, jl_datatype_t *tt JL_MAYBE_UNROOTED, size_t world) { jl_typemap_entry_t *entry = jl_mt_find_cache_entry(mc, tt, world); if (entry) @@ -1943,11 +1943,11 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methcache_t *mc JL_PROPAGATE if (!mi) { size_t min_valid = 0; size_t max_valid = ~(size_t)0; - matc = _gf_invoke_lookup((jl_value_t*)tt, jl_method_table, world, 0, &min_valid, &max_valid); + matc = _gf_invoke_lookup((jl_value_t*)tt, mt, world, 0, &min_valid, &max_valid); if (matc) { jl_method_t *m = matc->method; jl_svec_t *env = matc->sparams; - mi = cache_method(jl_method_table, mc, &mc->cache, (jl_value_t*)mc, tt, m, world, min_valid, max_valid, env); + mi = cache_method(mt, mc, &mc->cache, (jl_value_t*)mc, tt, m, world, min_valid, max_valid, env); JL_GC_POP(); return mi; } @@ -3191,7 +3191,7 @@ JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world mt = (jl_methtable_t*) _mt; } jl_methcache_t *mc = mt->cache; - jl_method_instance_t *mi = jl_mt_assoc_by_type(mc, tt, world); + jl_method_instance_t *mi = jl_mt_assoc_by_type(mt, mc, tt, world); if (!mi) return jl_nothing; return (jl_value_t*) mi; @@ -3206,7 +3206,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t na if (entry) return entry->func.linfo; jl_tupletype_t *tt = arg_type_tuple(args[0], &args[1], nargs); - return jl_mt_assoc_by_type(mc, tt, world); + return jl_mt_assoc_by_type(jl_method_table, mc, tt, world); } // return a Vector{Any} of svecs, each describing a method match: @@ -4280,7 +4280,7 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t *F, jl_value_t assert(tt); // cache miss case jl_methcache_t *mc = jl_method_table->cache; - mfunc = jl_mt_assoc_by_type(mc, tt, world); + mfunc = jl_mt_assoc_by_type(jl_method_table, mc, tt, world); if (jl_options.malloc_log) jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation if (mfunc == NULL) { diff --git a/test/core.jl b/test/core.jl index c8922083cea53..54c49a4d64349 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8443,6 +8443,32 @@ let ms = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, Ba @test isempty(ms) end +# fresh module to ensure uncached methods +module OverlayMTTest + using Base.Experimental: @MethodTable, @overlay + @MethodTable(mt) + + function overlay_only end + @overlay mt overlay_only(x::Int) = x * 2 +end + +# #60702 & #60716: Overlay methods must be found without prior cache population +let world = Base.get_world_counter() + mi = Base.method_instance(OverlayMTTest.overlay_only, Tuple{Int}; + world, method_table=OverlayMTTest.mt) + @test mi isa Core.MethodInstance + @test mi.def.module === OverlayMTTest +end + +# #60712: Global-only methods must NOT be found via custom MT +let + @eval global_only_func(x::Int) = x + 1 + world = Base.get_world_counter() + mi = Base.method_instance(global_only_func, Tuple{Int}; + world, method_table=OverlayMTTest.mt) + @test mi === nothing +end + # precompilation let load_path = mktempdir() depot_path = mkdepottempdir() From 409957206720f1f31f21407a77d150f4107ab021 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 24 Jan 2026 11:15:47 +0100 Subject: [PATCH 11/34] [1.13] Fix `codeinfo_for_const` missing `nargs` and `isva` fields (#60788) Backport a fix from #59413 to unbreak `Compiler.inflate_ir!` with const-return IR. --- Compiler/src/typeinfer.jl | 2 ++ Compiler/test/ssair.jl | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/Compiler/src/typeinfer.jl b/Compiler/src/typeinfer.jl index e3b7ee1f4926c..c97cf8b7f62a5 100644 --- a/Compiler/src/typeinfer.jl +++ b/Compiler/src/typeinfer.jl @@ -1186,6 +1186,8 @@ function codeinfo_for_const(::AbstractInterpreter, mi::MethodInstance, worlds::W tree.min_world = first(worlds) tree.max_world = last(worlds) tree.edges = edges + tree.nargs = UInt(nargs) + tree.isva = method.isva set_inlineable!(tree, true) tree.parent = mi return tree diff --git a/Compiler/test/ssair.jl b/Compiler/test/ssair.jl index 7aca2b8977a4e..f8d8a14adf9d7 100644 --- a/Compiler/test/ssair.jl +++ b/Compiler/test/ssair.jl @@ -845,3 +845,16 @@ end let ir = Base.code_ircode(_worker_task57153, (), optimize_until="CC: COMPACT_2")[1].first @test findfirst(x->x==0, ir.cfg.blocks[1].preds) !== nothing end + +# issue #59413 - codeinfo_for_const should set nargs and isva +let + _const_return_func(@nospecialize(x)) = 42 + mi = Compiler.specialize_method(only(methods(_const_return_func)), Tuple{typeof(_const_return_func), Int}, Core.svec()) + worlds = Compiler.WorldRange(Base.get_world_counter(), Base.get_world_counter()) + ci = Compiler.codeinfo_for_const(Compiler.NativeInterpreter(), mi, worlds, Core.svec(), 42) + @test ci.nargs == 2 + @test ci.isva == false + # inflate_ir! should succeed now that nargs/isva are set + ir = Compiler.inflate_ir!(ci, mi) + @test ir isa Compiler.IRCode +end From 1bb37cec9924069d07799cd4c3635fd4e0f3e7c3 Mon Sep 17 00:00:00 2001 From: Nathan Zimmerberg <39104088+nhz2@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:08:05 -0500 Subject: [PATCH 12/34] Fix build with USE_SYSTEM_P7ZIP=1 (#60623) (cherry picked from commit 657273aebc81d289eaf888f5bcccd6a4e0fce44b) --- base/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/Makefile b/base/Makefile index eb36d6d0a4319..0f7767e0aef37 100644 --- a/base/Makefile +++ b/base/Makefile @@ -183,14 +183,14 @@ endif endef # libexec executables -symlink_p7zip: $(build_bindir)/7z$(EXE) +symlink_p7zip: $(build_private_libexecdir)/7z$(EXE) ifneq ($(USE_SYSTEM_P7ZIP),0) SYMLINK_SYSTEM_LIBRARIES += symlink_p7zip 7Z_PATH := $(shell which 7z$(EXE)) endif -$(build_bindir)/7z$(EXE): +$(build_private_libexecdir)/7z$(EXE): [ -e "$(7Z_PATH)" ] && \ rm -f "$@" && \ ln -sf "$(7Z_PATH)" "$@" From 3a10a01ecec2c5f95042cef8712306c12029380b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 14 Jan 2026 14:40:12 +0100 Subject: [PATCH 13/34] Preserve the scope across the exception handler (#60647) We store the previous scope in the eh_state and thus hide it from GC. This means we need to manually preserve that scope across the `try ... catch`, instead fo the new scope that we switch to. --------- Co-authored-by: Nathan Daly Co-authored-by: Keno Fischer (cherry picked from commit f22ae77a82ec9adb1182566bc1c2be3a58f0fca2) --- src/codegen.cpp | 9 +++++---- src/gc-interface.h | 7 +++++++ src/interpreter.c | 12 ++++++------ src/rtutils.c | 2 ++ src/task.c | 2 ++ test/scopedvalues.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b8e1061728127..19dfc6b3b9166 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6163,6 +6163,7 @@ static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr, int ssaval_result) Value *scope_ptr = get_scope_field(ctx); jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe).decorateInst( ctx.builder.CreateAlignedStore(scope_to_restore, scope_ptr, ctx.types().alignof_ptr)); + // NOTE: wb not needed here, due to store to current_task (see jl_gc_wb_current_task) } } else if (head == jl_pop_exception_sym) { @@ -9406,12 +9407,12 @@ static jl_llvm_functions_t Value *scope_ptr = get_scope_field(ctx); LoadInst *current_scope = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, scope_ptr, ctx.types().alignof_ptr); StoreInst *scope_store = ctx.builder.CreateAlignedStore(scope_boxed, scope_ptr, ctx.types().alignof_ptr); + // NOTE: wb not needed here, due to store to current_task (see jl_gc_wb_current_task) jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe).decorateInst(current_scope); jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe).decorateInst(scope_store); - // GC preserve the scope, since it is not rooted in the `jl_handler_t *` - // and may be removed from jl_current_task by any nested block and then - // replaced later - Value *scope_token = ctx.builder.CreateCall(prepare_call(gc_preserve_begin_func), {scope_boxed}); + // GC preserve the current_scope, since it is not rooted in the `jl_handler_t *`, + // the newly entered scope is preserved through the current_task. + Value *scope_token = ctx.builder.CreateCall(prepare_call(gc_preserve_begin_func), {current_scope}); ctx.scope_restore[cursor] = std::make_pair(scope_token, current_scope); } } diff --git a/src/gc-interface.h b/src/gc-interface.h index 5edcd4de98bb2..4df1f154455c3 100644 --- a/src/gc-interface.h +++ b/src/gc-interface.h @@ -244,6 +244,13 @@ STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT // can be used to annotate that a write barrier would be required were it not for this property // (as opposed to somebody just having forgotten to think about write barriers). STATIC_INLINE void jl_gc_wb_fresh(const void *parent JL_UNUSED, const void *ptr JL_UNUSED) JL_NOTSAFEPOINT {} +// As an optimization, the current_task is explicitly added to the remset while it is running. +// Upon deschedule, we conservatively move the write barrier into the young generation. +// This allows the omission of write barriers for all GC roots on the current task stack (JL_GC_PUSH_*), +// as well as the Task's explicit fields (but only for the current task). +// This function is a no-op that can be used to annotate that a write barrier would be required were +// it not for this property (as opposed to somebody just having forgotten to think about write barriers). +STATIC_INLINE void jl_gc_wb_current_task(const void *parent JL_UNUSED, const void *ptr JL_UNUSED) JL_NOTSAFEPOINT {} // Used to annotate that a write barrier would be required, but may be omitted because `ptr` // is known to be an old object. STATIC_INLINE void jl_gc_wb_knownold(const void *parent JL_UNUSED, const void *ptr JL_UNUSED) JL_NOTSAFEPOINT {} diff --git a/src/interpreter.c b/src/interpreter.c index 6c0ea1bc16ab1..df2cc7813d34e 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -539,12 +539,12 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, } s->locals[jl_source_nslots(s->src) + ip] = jl_box_ulong(jl_excstack_state(ct)); if (jl_enternode_scope(stmt)) { - jl_value_t *scope = eval_value(jl_enternode_scope(stmt), s); - // GC preserve the scope, since it is not rooted in the `jl_handler_t *` - // and may be removed from jl_current_task by any nested block and then - // replaced later - JL_GC_PUSH1(&scope); - ct->scope = scope; + jl_value_t *old_scope = ct->scope; // Identical to __eh.scope + // GC preserve the old_scope, since it is not rooted in the `jl_handler_t *`, + // the newly entered scope is preserved through the current_task. + JL_GC_PUSH1(&old_scope); + ct->scope = eval_value(jl_enternode_scope(stmt), s); + jl_gc_wb_current_task(ct, ct->scope); if (!jl_setjmp(__eh.eh_ctx, 0)) { ct->eh = &__eh; eval_body(stmts, s, next_ip, toplevel); diff --git a/src/rtutils.c b/src/rtutils.c index e73d0de6c69aa..7f0ac7a166edd 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -297,6 +297,7 @@ JL_DLLEXPORT void jl_eh_restore_state(jl_task_t *ct, jl_handler_t *eh) ct->eh = eh->prev; ct->gcstack = eh->gcstack; ct->scope = eh->scope; + jl_gc_wb_current_task(ct, ct->scope); small_arraylist_t *locks = &ptls->locks; int unlocks = locks->len > eh->locks_len; if (unlocks) { @@ -336,6 +337,7 @@ JL_DLLEXPORT void jl_eh_restore_state_noexcept(jl_task_t *ct, jl_handler_t *eh) { assert(ct->gcstack == eh->gcstack && "Incorrect GC usage under try catch"); ct->scope = eh->scope; + jl_gc_wb_current_task(ct, ct->scope); ct->eh = eh->prev; ct->ptls->defer_signal = eh->defer_signal; // optional, but certain try-finally (in stream.jl) may be slightly harder to write without this } diff --git a/src/task.c b/src/task.c index 0ef835de202bd..20c00009fac69 100644 --- a/src/task.c +++ b/src/task.c @@ -1140,6 +1140,7 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_value_t *start, jl_value_t *completion_fu jl_atomic_store_relaxed(&t->_isexception, 0); // Inherit scope from parent task t->scope = ct->scope; + jl_gc_wb_fresh(t, t->scope); // Fork task-local random state from parent jl_rng_split(t->rngState, ct->rngState); // there is no active exception handler available on this stack yet @@ -1603,6 +1604,7 @@ jl_task_t *jl_init_root_task(jl_ptls_t ptls, void *stack_lo, void *stack_hi) ct->donenotify = jl_nothing; jl_atomic_store_relaxed(&ct->_isexception, 0); ct->scope = jl_nothing; + jl_gc_wb_knownold(ct, ct->scope); ct->eh = NULL; ct->gcstack = NULL; ct->excstack = NULL; diff --git a/test/scopedvalues.jl b/test/scopedvalues.jl index 69d83e0a091c4..a7874f02f01c1 100644 --- a/test/scopedvalues.jl +++ b/test/scopedvalues.jl @@ -225,3 +225,46 @@ end end sf2() end + +using Base.ScopedValues: ScopedValue, with +@noinline function test_59483() + sv = ScopedValue([]) + ch = Channel{Bool}() + + # Spawn a child task, which inherits the parent's Scope + @noinline function inner_function() + # Block until the parent task has left the scope. + take!(ch) + # Now, per issue 59483, this task's scope is not rooted, except by the task itself. + + # Now switch to an inner scope, leaving the current scope possibly unrooted. + val = with(sv=>Any[2]) do + # Inside this new scope, when we perform GC, the parent scope can be freed. + # The fix for this issue made sure that the first scope in this task remains + # rooted. + GC.gc() + GC.gc() + sv[] + end + @test val == Any[2] + # Finally, we've returned to the original scope, but that could be a dangling + # pointer if the scope itself was freed by the above GCs. So these GCs could crash: + GC.gc() + GC.gc() + end + @noinline function spawn_inner() + # Set a new Scope in the parent task - this is the scope that could be freed. + with(sv=>Any[1]) do + return @async inner_function() + end + end + + # RUN THE TEST: + t = spawn_inner() + # Exit the scope, and let the child task proceed + put!(ch, true) + wait(t) +end +@testset "issue 59483" begin + test_59483() +end From a3972ac1234f7391650599a887c76b6e397597ca Mon Sep 17 00:00:00 2001 From: Yash Agarwal <144056431+Yashagarwal9798@users.noreply.github.com> Date: Wed, 14 Jan 2026 19:38:02 +0530 Subject: [PATCH 14/34] Fix @fastmath x^2 inlining regression for Float32 and Float16 (#60640) ## Summary This PR fixes the performance regression where `@fastmath x^2` for `Float32` was not being inlined to efficient LLVM code, unlike `Float64`. ## Problem As reported in #60639, `@fastmath x^2` for `Float32` was falling back to `power_by_squaring` instead of using the LLVM `powi` intrinsic. This resulted in: - Unnecessary function calls instead of inline multiplication - Potential type promotion to `Float64` - Suboptimal generated code compared to `Float64` Before this fix, `@code_llvm @fastmath Float32(1.5)^2` would show calls to `power_by_squaring`, while `Float64` correctly used the `llvm.powi` intrinsic. ## Solution Added the missing `pow_fast` methods for `Float32` and `Float16`: - `pow_fast(::Float32, ::Int32)` - uses `llvm.powi.f32.i32` intrinsic directly - `pow_fast(::Float32, ::Integer)` - wrapper that converts to `Int32` when safe, matching the `Float64` pattern - `pow_fast(::Float16, ::Integer)` - converts to `Float32`, computes, and converts back This mirrors the existing implementation for `Float64` which already used `llvm.powi.f64.i32`. ## Testing Added a regression test that verifies `@fastmath x^2` generates inline `fmul` instructions (not `power_by_squaring` calls) for `Float16`, `Float32`, and `Float64`. Fixes #60639 --------- Co-authored-by: Oscar Smith (cherry picked from commit f34d5f23a5c24ceff88b6e09638ff8e662292724) --- base/fastmath.jl | 7 ++++--- test/fastmath.jl | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index ed686fb92bf34..8bfbbf4e2e23b 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -297,12 +297,13 @@ exp10_fast(x::Union{Float32,Float64}) = Base.Math.exp10_fast(x) # builtins -@inline function pow_fast(x::Float64, y::Integer) +@inline function pow_fast(x::T, y::Integer) where T <: Base.IEEEFloat z = y % Int32 z == y ? pow_fast(x, z) : x^y end -pow_fast(x::Float32, y::Integer) = x^y -pow_fast(x::Float64, y::Int32) = ccall("llvm.powi.f64.i32", llvmcall, Float64, (Float64, Int32), x, y) +pow_fast(x::Float16, y::Int32) = ccall("llvm.powi", llvmcall, Float16, (Float16, Int32), x, y) +pow_fast(x::Float32, y::Int32) = ccall("llvm.powi", llvmcall, Float32, (Float32, Int32), x, y) +pow_fast(x::Float64, y::Int32) = ccall("llvm.powi", llvmcall, Float64, (Float64, Int32), x, y) pow_fast(x::FloatTypes, ::Val{p}) where {p} = pow_fast(x, p) # inlines already via llvm.powi @inline pow_fast(x, v::Val) = Base.literal_pow(^, x, v) diff --git a/test/fastmath.jl b/test/fastmath.jl index efca5b85c6642..d3d82f40f9f1a 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -303,6 +303,31 @@ end @test @fastmath (1 + 1 / n) ^ 4503599627370496 ≈ ℯ end +# Test that x^2 is inlined to fmul for all float types (issue #60639) +@testset "pow_fast inlining for literal powers" begin + for T in (Float16, Float32, Float64) + f(x) = @fastmath x^2 + llvm = sprint(code_llvm, f, (T,)) + # Should be inlined to fmul, not call power_by_squaring + @test occursin("fmul", llvm) + @test !occursin("power_by_squaring", llvm) + end +end + +# Test correctness of pow_fast for Float32/Float16 with various exponents (issue #60639) +@testset "pow_fast correctness" begin + for T in (Float16, Float32) + x = T(2.5) + # Exponents that fit in Int32 + @test (@fastmath x^2) ≈ x^2 + @test (@fastmath x^10) ≈ x^10 + @test (@fastmath x^(-3)) ≈ x^(-3) + # Exponents that don't fit in Int32 + big_exp = Int64(2)^40 + @test (@fastmath x^big_exp) ≈ x^big_exp + end +end + @testset "sincos fall-backs" begin struct FloatWrapper inner::Float64 From 3314ac7d7af557aac52a81d3babf6f2da1c30eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 14 Jan 2026 15:35:46 +0100 Subject: [PATCH 15/34] Fix JET warnings in `show(::IOBuffer, ::StackFrame)` (#60645) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gets rid of the following JET warnings (present on julia 1.13.0-beta1 with JET https://github.com/aviatesk/JET.jl/commit/377fa5303a5f532755ece84c65fd1878b8fc2ab6 (see https://github.com/aviatesk/JET.jl/issues/796 why I did not use a released version), no longer present with this patch applied onto julia 1.13.0-beta1) ```julia julia> @report_call Base.process_backtrace(Base.stacktrace(Base.backtrace())) [ Info: tracking Base ┌ Warning: skipping var"#sprint#423"(context, sizehint::Integer, ::typeof(sprint), f::Function, args...) @ Base strings/io.jl:102 to avoid parsing too much code └ @ Revise ~/.julia/packages/Revise/icvyF/src/packagedef.jl:1344 ═════ 3 possible errors found ═════ ┌ process_backtrace(t::Vector{Base.StackTraces.StackFrame}) @ Base ./errorshow.jl:1094 │┌ process_backtrace(tracecount::Vector{Any}) @ Base ./errorshow.jl:1100 ││┌ _backtrace_collapse_repeated_locations!(trace::Vector{Any}) @ Base ./errorshow.jl:1048 │││┌ sprint(f::typeof(show), args::Base.StackTraces.StackFrame) @ Base ./strings/io.jl:102 ││││┌ sprint(f::typeof(show), args::Base.StackTraces.StackFrame; context::Nothing, sizehint::Int64) @ Base ./strings/io.jl:109 │││││┌ show(io::IOBuffer, frame::Base.StackTraces.StackFrame) @ Base.StackTraces ./stacktraces.jl:331 ││││││┌ show_spec_linfo(io::IOBuffer, frame::Base.StackTraces.StackFrame) @ Base.StackTraces ./stacktraces.jl:282 │││││││┌ show_custom_spec_sig(io::IOBuffer, owner::Any, linfo::Core.CodeInstance, frame::Base.StackTraces.StackFrame) @ Base.StackTraces ./stacktraces.jl:298 ││││││││ no matching method found `show_spec_sig(::IOBuffer, ::Module, ::Any)` (1/2 union split): Base.StackTraces.show_spec_sig(io::IOBuffer, mi.def::Union{Method, Module}, mi.specTypes::Any) │││││││└──────────────────── ││││││┌ show_spec_linfo(io::IOBuffer, frame::Base.StackTraces.StackFrame) @ Base.StackTraces ./stacktraces.jl:286 │││││││┌ getproperty(x::Nothing, f::Symbol) @ Base ./Base_compiler.jl:57 ││││││││ invalid builtin function call: getfield(x::Nothing, f::Symbol) │││││││└──────────────────── ││││││┌ show_spec_linfo(io::IOBuffer, frame::Base.StackTraces.StackFrame) @ Base.StackTraces ./stacktraces.jl:286 │││││││ no matching method found `show_spec_sig(::IOBuffer, ::Nothing, ::Any)` (1/2 union split): Base.StackTraces.show_spec_sig(io::IOBuffer, def::Union{Nothing, Method}, (Base.StackTraces.frame_mi(frame::Base.StackTraces.StackFrame)::Union{Nothing, Core.MethodInstance}).specTypes::Any) ││││││└──────────────────── ``` It would be great to get this backported to 1.12 and 1.13. cc @fingolfin (cherry picked from commit 57d5fb1e653e812334697cee36c724ef1508e2bc) --- base/stacktraces.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 0e807adb92839..522db86acd226 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -285,7 +285,8 @@ function show_spec_linfo(io::IO, frame::StackFrame) else # Equivalent to the default implementation of `show_custom_spec_sig` # for `linfo isa CodeInstance`, but saves an extra dynamic dispatch. - show_spec_sig(io, def, frame_mi(frame).specTypes) + mi = frame_mi(frame)::MethodInstance + show_spec_sig(io, def::Method, mi.specTypes) end else m = linfo::Method @@ -297,7 +298,8 @@ end # Can be extended by compiler packages to customize backtrace display of custom code instance frames function show_custom_spec_sig(io::IO, @nospecialize(owner), linfo::CodeInstance, frame::StackFrame) mi = Base.get_ci_mi(linfo) - return show_spec_sig(io, mi.def, mi.specTypes) + m = mi.def::Method # the case ::Module is handled in show_spec_linfo + return show_spec_sig(io, m, mi.specTypes) end function show_spec_sig(io::IO, m::Method, @nospecialize(sig::Type)) From 8c85653ace2679ed6f67d0712a8b1876fff8a0f3 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Wed, 14 Jan 2026 17:42:43 -0300 Subject: [PATCH 16/34] Don't set the owner of the string needlessly. (#60601) This might cause double frees/use after frees. Found on the mimalloc PR (cherry picked from commit 06def894dc0281a9582ec9138960edf60fb262e8) --- src/gc-stock.c | 2 +- src/genericmemory.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gc-stock.c b/src/gc-stock.c index 59b3cd3c05ad5..9e0d2ab77190b 100644 --- a/src/gc-stock.c +++ b/src/gc-stock.c @@ -630,7 +630,7 @@ void jl_gc_reset_alloc_count(void) JL_NOTSAFEPOINT static void jl_gc_free_memory(jl_genericmemory_t *m, int isaligned) JL_NOTSAFEPOINT { assert(jl_is_genericmemory(m)); - assert(jl_genericmemory_how(m) == 1 || jl_genericmemory_how(m) == 2); + assert(jl_genericmemory_how(m) == 1); char *d = (char*)m->ptr; size_t freed_bytes = memory_block_usable_size(d, isaligned); assert(freed_bytes != 0); diff --git a/src/genericmemory.c b/src/genericmemory.c index ae45237433fcc..dc1c687d1d382 100644 --- a/src/genericmemory.c +++ b/src/genericmemory.c @@ -199,7 +199,6 @@ JL_DLLEXPORT jl_value_t *jl_genericmemory_to_string(jl_genericmemory_t *m, size_ size_t mlength = m->length; if (how != 0) { jl_value_t *o = jl_genericmemory_data_owner_field(m); - jl_genericmemory_data_owner_field(m) = NULL; if (how == 3 && // implies jl_is_string(o) ((mlength + sizeof(void*) + 1 <= GC_MAX_SZCLASS) == (len + sizeof(void*) + 1 <= GC_MAX_SZCLASS))) { if (jl_string_data(o)[len] != '\0') From d1e35de15ed795212790e524524e10a0a9cca26a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 15 Jan 2026 00:23:55 -0500 Subject: [PATCH 17/34] add wb_back on all task switch paths (#60617) Since this task's stack or scope field could have been modified after it was marked by an incremental collection (and not just for copy stacks), move the barrier back unconditionally here. --------- Co-authored-by: Valentin Churavy Co-authored-by: Jeff Bezanson (cherry picked from commit 14ca1abc7237fc586d71d8b1b2c5a2d08bc2276e) --- src/task.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/task.c b/src/task.c index 20c00009fac69..e4ce793735f0f 100644 --- a/src/task.c +++ b/src/task.c @@ -207,10 +207,6 @@ static void NOINLINE save_stack(jl_ptls_t ptls, jl_task_t *lastt, jl_task_t **pt lastt->ctx.copy_stack = nb; lastt->sticky = 1; memcpy_stack_a16((uint64_t*)buf, (uint64_t*)frame_addr, nb); - // this task's stack could have been modified after - // it was marked by an incremental collection - // move the barrier back instead of walking it again here - jl_gc_wb_back(lastt); } JL_NO_ASAN static void NOINLINE JL_NORETURN restore_stack(jl_ucontext_t *t, jl_ptls_t ptls, char *p) @@ -508,6 +504,12 @@ JL_NO_ASAN static void ctx_switch(jl_task_t *lastt) lastt->ctx.ctx = &lasttstate.ctx; } } + // this task's stack or scope field could have been modified after + // it was marked by an incremental collection + // move the barrier back instead of walking the shadow stack again here to check if that is required + // even if killed (dropping the stack) and just the scope field matters, + // let the gc figure that out next time it does a quick mark + jl_gc_wb_back(lastt); // set up global state for new task and clear global state for old task t->ptls = ptls; From 791a72ea40f6489e3756912b60392632b3c77f13 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 17 Jan 2026 20:03:05 +0100 Subject: [PATCH 18/34] Don't include NI tags when verifying external module data layouts. (#60720) We're currently excepting callers of `addExternalModule` to provide modules with a DL that contains NI tags: ``` ERROR: LoadError: LLVM error: Added modules have incompatible data layouts: e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32 (module) vs e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32-ni:10:11:12:13 (jit) ``` Doing so is invalid and asserts later during compilation: ``` Assertion failed: (Target.isCompatibleDataLayout(getDataLayout()) && "Can't create a MachineFunction using a Module with a " "Target-incompatible DataLayout attached\n"), function init, file /workspace/srcdir/llvm-project/llvm/lib/CodeGen/MachineFunction.cpp, line 248. ``` The NI tags are stripped during optimization, and modules passed to `addExternalModule` are expected to be optimized as they are passed straight to the JIT (as opposed to `addModule`), so we should make sure to use the correct data layout. (cherry picked from commit 3a884a72b0990f90e2601afb9f0d663f39ecafe9) --- src/jitlayers.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index eae266364932b..be1b943b8511f 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -2139,13 +2139,14 @@ void JuliaOJIT::addModule(orc::ThreadSafeModule TSM) Error JuliaOJIT::addExternalModule(orc::JITDylib &JD, orc::ThreadSafeModule TSM, bool ShouldOptimize) { if (auto Err = TSM.withModuleDo([&](Module &M) JL_NOTSAFEPOINT -> Error { + auto PostOptDL = TM->createDataLayout(); // excludes ni tags stripped by optzns if (M.getDataLayout().isDefault()) - M.setDataLayout(DL); - if (M.getDataLayout() != DL) + M.setDataLayout(PostOptDL); + if (M.getDataLayout() != PostOptDL) return make_error( "Added modules have incompatible data layouts: " + M.getDataLayout().getStringRepresentation() + " (module) vs " + - DL.getStringRepresentation() + " (jit)", + PostOptDL.getStringRepresentation() + " (jit)", inconvertibleErrorCode()); // OrcJIT requires that all modules / files have unique names: M.setModuleIdentifier((M.getModuleIdentifier() + Twine("-") + Twine(jl_atomic_fetch_add_relaxed(&jitcounter, 1))).str()); From cefa6260c1f4ca53a413c5b024dcbf286750557b Mon Sep 17 00:00:00 2001 From: William Moses Date: Mon, 19 Jan 2026 11:23:00 -0500 Subject: [PATCH 19/34] Revert "Revert "Enable getting non-boxed LLVM type from Julia Type" (#59492)" This reverts commit cfcd7d8a327457e4e121457e103989f0185d9dc8. (cherry picked from commit b180586ed356812f964ecd991cc6d30a5bbabbad) --- src/cgutils.cpp | 15 +++++++++++---- src/codegen-stubs.c | 2 ++ src/codegen.cpp | 4 ++-- src/jl_exported_funcs.inc | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 62f31e237f4b6..275b5fe5cf06e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -628,13 +628,13 @@ static unsigned convert_struct_offset(jl_codectx_t &ctx, Type *lty, unsigned byt static Type *_julia_struct_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed, bool llvmcall=false); -static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed) +static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl_value_t *jt, bool *isboxed, bool no_boxing) { // this function converts a Julia Type into the equivalent LLVM type if (isboxed) *isboxed = false; if (jt == (jl_value_t*)jl_bottom_type || jt == (jl_value_t*)jl_typeofbottom_type || jt == (jl_value_t*)jl_typeofbottom_type->super) return getVoidTy(ctxt); - if (jl_is_concrete_immutable(jt)) { + if (jl_is_concrete_immutable(jt) || no_boxing) { if (jl_datatype_nbits(jt) == 0) return getVoidTy(ctxt); Type *t = _julia_struct_to_llvm(ctx, ctxt, jt, isboxed); @@ -647,13 +647,20 @@ static Type *_julia_type_to_llvm(jl_codegen_params_t *ctx, LLVMContext &ctxt, jl static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed) { - return _julia_type_to_llvm(&ctx.emission_context, ctx.builder.getContext(), jt, isboxed); + return _julia_type_to_llvm(&ctx.emission_context, ctx.builder.getContext(), jt, isboxed, false); } extern "C" JL_DLLEXPORT_CODEGEN Type *jl_type_to_llvm_impl(jl_value_t *jt, LLVMContextRef ctxt, bool *isboxed) { - return _julia_type_to_llvm(NULL, *unwrap(ctxt), jt, isboxed); + return _julia_type_to_llvm(NULL, *unwrap(ctxt), jt, isboxed, false); +} + + +extern "C" JL_DLLEXPORT_CODEGEN +Type *jl_struct_to_llvm_impl(jl_value_t *jt, LLVMContextRef ctxt, bool *isboxed) +{ + return _julia_type_to_llvm(NULL, *unwrap(ctxt), jt, isboxed, true); } diff --git a/src/codegen-stubs.c b/src/codegen-stubs.c index dbb9ae2c3ee20..6d822fb974453 100644 --- a/src/codegen-stubs.c +++ b/src/codegen-stubs.c @@ -117,6 +117,8 @@ JL_DLLEXPORT LLVMOrcThreadSafeModuleRef jl_get_llvm_module_fallback(void *native JL_DLLEXPORT void *jl_type_to_llvm_fallback(jl_value_t *jt, LLVMContextRef llvmctxt, bool_t *isboxed) UNAVAILABLE +JL_DLLEXPORT void *jl_struct_to_llvm_fallback(jl_value_t *jt, LLVMContextRef llvmctxt, bool_t *isboxed) UNAVAILABLE + JL_DLLEXPORT jl_value_t *jl_get_libllvm_fallback(void) JL_NOTSAFEPOINT { return jl_nothing; diff --git a/src/codegen.cpp b/src/codegen.cpp index 19dfc6b3b9166..80b2a947bc8da 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7908,7 +7908,7 @@ static jl_returninfo_t get_specsig_function(jl_codegen_params_t ¶ms, Module } else if (!deserves_retbox(jlrettype)) { bool retboxed; - rt = _julia_type_to_llvm(¶ms, M->getContext(), jlrettype, &retboxed); + rt = _julia_type_to_llvm(¶ms, M->getContext(), jlrettype, &retboxed, /*noboxing*/false); assert(!retboxed); if (rt != getVoidTy(M->getContext()) && deserves_sret(jlrettype, rt)) { auto tracked = CountTrackedPointers(rt, true); @@ -7985,7 +7985,7 @@ static jl_returninfo_t get_specsig_function(jl_codegen_params_t ¶ms, Module if (is_uniquerep_Type(jt)) continue; isboxed = deserves_argbox(jt); - et = isboxed ? T_prjlvalue : _julia_type_to_llvm(¶ms, M->getContext(), jt, nullptr); + et = isboxed ? T_prjlvalue : _julia_type_to_llvm(¶ms, M->getContext(), jt, nullptr, /*noboxing*/false); if (type_is_ghost(et)) continue; } diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index c090d3fe253fe..aa9e30671588f 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -540,6 +540,7 @@ YY(jl_dump_fptr_asm) \ YY(jl_emit_native) \ YY(jl_get_function_id) \ + YY(jl_struct_to_llvm) \ YY(jl_type_to_llvm) \ YY(jl_getUnwindInfo) \ YY(jl_get_libllvm) \ From c0565dfbdafa0ed072061ed55b6d8788e85c4f1f Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Tue, 20 Jan 2026 08:15:37 -0800 Subject: [PATCH 20/34] Temporarily reintroduce a global type inference lock (#60689) (cherry picked from commit 23a98ffd193a0946636976bcd92af8f69853f8b6) --- doc/src/devdocs/locks.md | 1 + src/gf.c | 8 ++++++-- src/init.c | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index b5cbe68c46435..f2d3ea57d14df 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -100,6 +100,7 @@ exception frames, and taking/releasing locks. No Julia code may be called while holding a lock above this point. * `world_counter_lock` +* `jl_typeinf_lock` ### Level 7 diff --git a/src/gf.c b/src/gf.c index b18a791945578..42c41887680f5 100644 --- a/src/gf.c +++ b/src/gf.c @@ -400,6 +400,8 @@ static jl_code_instance_t *jl_method_inferred_with_abi(jl_method_instance_t *mi return NULL; } +jl_mutex_t jl_typeinf_lock; + // run type inference on lambda "mi" for given argument types. // returns the inferred source, and may cache the result in mi // if successful, also updates the mi argument to describe the validity of this src @@ -428,6 +430,7 @@ jl_code_instance_t *jl_type_infer(jl_method_instance_t *mi, size_t world, uint8_ return NULL; JL_TIMING(INFERENCE, INFERENCE); jl_value_t **fargs; + JL_GC_PUSH1(&ci); JL_GC_PUSHARGS(fargs, 5); fargs[0] = (jl_value_t*)jl_typeinf_func; fargs[1] = (jl_value_t*)mi; @@ -459,6 +462,7 @@ jl_code_instance_t *jl_type_infer(jl_method_instance_t *mi, size_t world, uint8_ // increase that limit, we'll need to // allocate another bit for the counter. ct->reentrant_timing += 0b10; + JL_LOCK(&jl_typeinf_lock); JL_TRY { ci = (jl_code_instance_t*)jl_apply(fargs, 5); } @@ -482,6 +486,7 @@ jl_code_instance_t *jl_type_infer(jl_method_instance_t *mi, size_t world, uint8_ abort(); #endif } + JL_UNLOCK(&jl_typeinf_lock); ct->world_age = last_age; ct->reentrant_timing -= 0b10; ct->ptls->in_pure_callback = last_pure; @@ -496,12 +501,11 @@ jl_code_instance_t *jl_type_infer(jl_method_instance_t *mi, size_t world, uint8_ // 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(); + JL_GC_POP(); #endif return ci; diff --git a/src/init.c b/src/init.c index bb26eed00e94b..0142365cad676 100644 --- a/src/init.c +++ b/src/init.c @@ -558,6 +558,7 @@ extern jl_mutex_t precomp_statement_out_lock; extern jl_mutex_t newly_inferred_mutex; extern jl_mutex_t global_roots_lock; extern jl_mutex_t profile_show_peek_cond_lock; +extern jl_mutex_t jl_typeinf_lock; static void restore_fp_env(void) { @@ -667,6 +668,7 @@ static void init_global_mutexes(void) { JL_MUTEX_INIT(&global_roots_lock, "global_roots_lock"); JL_MUTEX_INIT(&typecache_lock, "typecache_lock"); JL_MUTEX_INIT(&profile_show_peek_cond_lock, "profile_show_peek_cond_lock"); + JL_MUTEX_INIT(&jl_typeinf_lock, "jl_typeinf_lock"); } JL_DLLEXPORT void jl_init_(jl_image_buf_t sysimage) From 50f61d0d71758004423632cbf39db89936538aff Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Wed, 21 Jan 2026 02:44:19 -0300 Subject: [PATCH 21/34] llvm: Fix alloca alignment and type selection in AllocOpt (#60699) Inherit alignment from the original GC allocation with JL_SMALL_BYTE_ALIGNMENT as the minimum. Use alignment-sized integer chunks for the alloca type (matching emit_static_alloca) so SROA splits allocations into aligned pieces for better performance and vectorization. Also adds the missing setAlignment call in splitOnStack. Co-Authored-By: Claude Opus 4.5 --------- Co-authored-by: Claude Opus 4.5 (cherry picked from commit 54fde7e012e6883a5bc9acd964593c8b9c9b5c74) --- src/codegen.cpp | 8 ++-- src/llvm-alloc-opt.cpp | 37 +++++++++------ .../alloc-opt-gcframe-addrspaces.ll | 2 +- test/llvmpasses/alloc-opt-gcframe.ll | 9 ++-- test/llvmpasses/alloc-opt-pass.ll | 45 ++++++++++++++++--- 5 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 80b2a947bc8da..9dcf1264581c0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2132,9 +2132,11 @@ static AllocaInst *emit_static_alloca(jl_codectx_t &ctx, unsigned nb, Align alig // if it cannot find something better to do, which is terrible for performance. // However, if we emit this with an element size equal to the alignment, it will instead split it into aligned chunks // which is great for performance and vectorization. - if (alignTo(nb, align) == align.value()) // don't bother with making an array of length 1 - return emit_static_alloca(ctx, ctx.builder.getIntNTy(align.value() * 8), align); - return emit_static_alloca(ctx, ArrayType::get(ctx.builder.getIntNTy(align.value() * 8), alignTo(nb, align) / align.value()), align); + // Cap element size at 64 bits since not all backends support larger integers. + unsigned elsize = std::min(align.value(), (uint64_t)8); + if (alignTo(nb, elsize) == elsize) // don't bother with making an array of length 1 + return emit_static_alloca(ctx, ctx.builder.getIntNTy(elsize * 8), align); + return emit_static_alloca(ctx, ArrayType::get(ctx.builder.getIntNTy(elsize * 8), alignTo(nb, elsize) / elsize), align); } static AllocaInst *emit_static_roots(jl_codectx_t &ctx, unsigned nroots) diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 56bb1ab7c706b..9af5f6e04189c 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -678,11 +678,8 @@ void Optimizer::moveToStack(CallInst *orig_inst, size_t sz, bool has_ref, AllocF // The allocation does not escape or get used in a phi node so none of the derived // SSA from it are live when we run the allocation again. // It is now safe to promote the allocation to an entry block alloca. - size_t align = 1; - // TODO: This is overly conservative. May want to instead pass this as a - // parameter to the allocation function directly. - if (sz > 1) - align = MinAlign(JL_SMALL_BYTE_ALIGNMENT, NextPowerOf2(sz)); + // Inherit alignment from the original allocation, with GC alignment as minimum. + Align align(std::max((unsigned)orig_inst->getRetAlign().valueOrOne().value(), (unsigned)JL_SMALL_BYTE_ALIGNMENT)); // No debug info for prolog instructions IRBuilder<> prolog_builder(&F.getEntryBlock().front()); AllocaInst *buff; @@ -698,17 +695,21 @@ void Optimizer::moveToStack(CallInst *orig_inst, size_t sz, bool has_ref, AllocF const DataLayout &DL = F.getParent()->getDataLayout(); auto asize = ConstantInt::get(Type::getInt64Ty(prolog_builder.getContext()), sz / DL.getTypeAllocSize(pass.T_prjlvalue)); buff = prolog_builder.CreateAlloca(pass.T_prjlvalue, asize); - buff->setAlignment(Align(align)); + buff->setAlignment(align); ptr = cast(buff); } else { + // Use alignment-sized chunks so SROA splits the alloca into aligned pieces + // which is better for performance and vectorization (see emit_static_alloca). + // Cap element size at 64 bits since not all backends support larger integers. Type *buffty; - if (pass.DL->isLegalInteger(sz * 8)) - buffty = Type::getIntNTy(pass.getLLVMContext(), sz * 8); + unsigned elsize = std::min(align.value(), (uint64_t)8); + if (alignTo(sz, elsize) == elsize) + buffty = Type::getIntNTy(pass.getLLVMContext(), elsize * 8); else - buffty = ArrayType::get(Type::getInt8Ty(pass.getLLVMContext()), sz); + buffty = ArrayType::get(Type::getIntNTy(pass.getLLVMContext(), elsize * 8), alignTo(sz, elsize) / elsize); buff = prolog_builder.CreateAlloca(buffty); - buff->setAlignment(Align(align)); + buff->setAlignment(align); ptr = cast(buff); } insertLifetime(ptr, ConstantInt::get(Type::getInt64Ty(prolog_builder.getContext()), sz), orig_inst); @@ -978,6 +979,8 @@ void Optimizer::splitOnStack(CallInst *orig_inst) uint32_t size; }; SmallVector slots; + // Inherit alignment from the original allocation, with GC alignment as minimum. + Align align(std::max((unsigned)orig_inst->getRetAlign().valueOrOne().value(), (unsigned)JL_SMALL_BYTE_ALIGNMENT)); for (auto memop: use_info.memops) { auto offset = memop.first; auto &field = memop.second; @@ -993,12 +996,18 @@ void Optimizer::splitOnStack(CallInst *orig_inst) else if (field.elty && !field.multiloc) { allocty = field.elty; } - else if (pass.DL->isLegalInteger(field.size * 8)) { - allocty = Type::getIntNTy(pass.getLLVMContext(), field.size * 8); - } else { - allocty = ArrayType::get(Type::getInt8Ty(pass.getLLVMContext()), field.size); + else { + // Use alignment-sized chunks so SROA splits the alloca into aligned pieces + // which is better for performance and vectorization (see emit_static_alloca). + // Cap element size at 64 bits since not all backends support larger integers. + unsigned elsize = std::min(align.value(), (uint64_t)8); + if (alignTo(field.size, elsize) == elsize) + allocty = Type::getIntNTy(pass.getLLVMContext(), elsize * 8); + else + allocty = ArrayType::get(Type::getIntNTy(pass.getLLVMContext(), elsize * 8), alignTo(field.size, elsize) / elsize); } slot.slot = prolog_builder.CreateAlloca(allocty); + slot.slot->setAlignment(align); IRBuilder<> builder(orig_inst); insertLifetime(slot.slot, ConstantInt::get(Type::getInt64Ty(prolog_builder.getContext()), field.size), orig_inst); initializeAlloca(builder, slot.slot, use_info.allockind); diff --git a/test/llvmpasses/alloc-opt-gcframe-addrspaces.ll b/test/llvmpasses/alloc-opt-gcframe-addrspaces.ll index b96c9385e38eb..c66cb815ea8b9 100644 --- a/test/llvmpasses/alloc-opt-gcframe-addrspaces.ll +++ b/test/llvmpasses/alloc-opt-gcframe-addrspaces.ll @@ -16,7 +16,7 @@ declare {}* @julia.pointer_from_objref({} addrspace(11)*) ; CHECK-LABEL: @non_zero_addrspace -; OPAQUE: %var1 = alloca i32, align 8, addrspace(5) +; OPAQUE: %var1 = alloca i64, align 16, addrspace(5) ; OPAQUE: %1 = addrspacecast ptr addrspace(5) %var1 to ptr ; OPAQUE: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) %var1) diff --git a/test/llvmpasses/alloc-opt-gcframe.ll b/test/llvmpasses/alloc-opt-gcframe.ll index f53a4d5c01df7..44714b702d7bc 100644 --- a/test/llvmpasses/alloc-opt-gcframe.ll +++ b/test/llvmpasses/alloc-opt-gcframe.ll @@ -25,7 +25,8 @@ define {} addrspace(10)* @return_obj() { ; CHECK-LABEL: }{{$}} ; CHECK-LABEL: @return_load -; CHECK: alloca i64 +; When the element type is known (i64), splitOnStack preserves it +; CHECK: alloca i64, align 16 ; CHECK-NOT: @julia.gc_alloc_obj ; CHECK-NOT: @jl_gc_small_alloc ; OPAQUE: call void @llvm.lifetime.start{{.*}}(i64 8, ptr @@ -62,7 +63,7 @@ define void @ccall_obj(i8* %fptr) { ; CHECK-LABEL: }{{$}} ; CHECK-LABEL: @ccall_ptr -; CHECK: alloca i64 +; CHECK: alloca i64, align 16 ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj ; CHECK-NOT: @jl_gc_small_alloc @@ -105,7 +106,7 @@ define void @ccall_unknown_bundle(i8* %fptr) { ; CHECK-LABEL: }{{$}} ; CHECK-LABEL: @lifetime_branches -; CHECK: alloca i64 +; CHECK: alloca i64, align 16 ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK: L1: ; CHECK-NEXT: call void @llvm.lifetime.start{{.*}}(i64 8, @@ -166,7 +167,7 @@ define void @object_field({} addrspace(10)* %field) { ; CHECK-LABEL: }{{$}} ; CHECK-LABEL: @memcpy_opt -; CHECK: alloca [16 x i8], align 16 +; CHECK: alloca [2 x i64], align 16 ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj ; CHECK-NOT: @jl_gc_small_alloc diff --git a/test/llvmpasses/alloc-opt-pass.ll b/test/llvmpasses/alloc-opt-pass.ll index c6c279ae36fc6..97f998f7593ca 100644 --- a/test/llvmpasses/alloc-opt-pass.ll +++ b/test/llvmpasses/alloc-opt-pass.ll @@ -79,8 +79,9 @@ declare ptr addrspace(10) @external_function2() ; CHECK-LABEL: @legal_int_types -; CHECK: alloca [12 x i8] -; CHECK-NOT: alloca i96 +; Test that allocations use i64 chunks (capped at 64 bits for backend compatibility) +; A 12-byte allocation rounds up to 16 bytes, giving [2 x i64] +; CHECK: alloca [2 x i64], align 16 ; CHECK: call void @llvm.memset.p0.i64(ptr align 16 %var1, ; CHECK: ret void define void @legal_int_types() { @@ -151,11 +152,10 @@ define void @lifetime_no_preserve_end(ptr noalias nocapture noundef nonnull sret ; CHECK-LABEL: @initializers -; CHECK: alloca [1 x i8] -; CHECK-DAG: alloca [2 x i8] -; CHECK-DAG: alloca [3 x i8] -; CHECK-DAG: call void @llvm.memset.p0.i64(ptr align 1 %var1, -; CHECK-DAG: call void @llvm.memset.p0.i64(ptr align 4 %var7, +; Small allocations (1, 2, 3 bytes) all round up to 8 bytes, giving i64 +; CHECK-DAG: alloca i64, align 16 +; CHECK-DAG: call void @llvm.memset.p0.i64(ptr align 16 %var1, +; CHECK-DAG: call void @llvm.memset.p0.i64(ptr align 16 %var7, ; CHECK: ret void define void @initializers() { %pgcstack = call ptr @julia.get_pgcstack() @@ -268,6 +268,37 @@ define swiftcc i64 @"atomicrmw"(ptr nonnull swiftself "gcstack" %0) #0 { ret i64 %19 } +; Test that higher alignment from the original allocation is inherited +; 8 bytes with 32-byte alignment uses i64 (element size capped at 64 bits) +; CHECK-LABEL: @align_inherit +; CHECK: alloca i64, align 32 +; CHECK: ret void +define void @align_inherit() { + %pgcstack = call ptr @julia.get_pgcstack() + %ptls = call ptr @julia.ptls_states() + %ptls_i8 = bitcast ptr %ptls to ptr + %var1 = call align 32 ptr addrspace(10) @julia.gc_alloc_obj(ptr %ptls_i8, i64 8, ptr addrspace(10) @tag) + %var2 = addrspacecast ptr addrspace(10) %var1 to ptr addrspace(11) + %var3 = call ptr @julia.pointer_from_objref(ptr addrspace(11) %var2) + ret void +} +; CHECK-LABEL: }{{$}} + +; Test that 8-byte allocation uses i64 with GC alignment +; CHECK-LABEL: @legal_int_i64 +; CHECK: alloca i64, align 16 +; CHECK: ret void +define void @legal_int_i64() { + %pgcstack = call ptr @julia.get_pgcstack() + %ptls = call ptr @julia.ptls_states() + %ptls_i8 = bitcast ptr %ptls to ptr + %var1 = call ptr addrspace(10) @julia.gc_alloc_obj(ptr %ptls_i8, i64 8, ptr addrspace(10) @tag) + %var2 = addrspacecast ptr addrspace(10) %var1 to ptr addrspace(11) + %var3 = call ptr @julia.pointer_from_objref(ptr addrspace(11) %var2) + ret void +} +; CHECK-LABEL: }{{$}} + declare ptr @julia.ptls_states() declare ptr @julia.pointer_from_objref(ptr addrspace(11)) From 00737cac8356677e002e6c34e7ce39b60b044ea4 Mon Sep 17 00:00:00 2001 From: Mason Protter Date: Sat, 24 Jan 2026 14:44:56 +0100 Subject: [PATCH 22/34] Add optimizer support for `invoke(f, ::CodeInstance, args...)` (#60442) ~~(I wrote this with assistance from Gemini since I'm not very used to writing LLVM IR)~~ No longer using that code This is an attempt to fix https://github.com/JuliaLang/julia/issues/60441. After bumbling around a bit, it seems that the problem is that `invoke(f, ::CodeInstance, args...)` calls are not turned into `Expr(:invoke` statements in the IR, but remains as `:call`s to the `invoke` builtin which ends up going through the runtime. ~~There's probably a better way to do this, but the way I found was to just detect these builtin calls in the LLVM IR, and send them to `emit_invoke`.~~ I'm now detecting `InvokeCICallInfo`s in the inlining step of the optimizer and turning those into `Expr(:invoke`s. It appears to resolve the issue: ```julia using BenchmarkTools mysin(x::Float64) = sin(x) @assert mysin(1.0) == sin(1.0) const mysin_ci = Base.specialize_method(Base._which(Tuple{typeof(mysin), Float64})).cache ``` Before this PR: ```julia julia> @btime invoke(mysin, mysin_ci, x) setup=(x=rand()) 24.952 ns (2 allocations: 32 bytes) 0.7024964043721993 ``` After this PR: ```julia julia> @btime invoke(mysin, mysin_ci, x) setup=(x=rand()) 4.748 ns (0 allocations: 0 bytes) 0.32283046823183426 ``` (cherry picked from commit e1dda38c5151d5c31af584151f86c41779eaa6ad) --- Compiler/src/ssair/inlining.jl | 14 +++++++++++++- test/core.jl | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Compiler/src/ssair/inlining.jl b/Compiler/src/ssair/inlining.jl index 9ef8a993dc818..1007c6cec6449 100644 --- a/Compiler/src/ssair/inlining.jl +++ b/Compiler/src/ssair/inlining.jl @@ -1164,8 +1164,20 @@ end function handle_invoke_call!(todo::Vector{Pair{Int,Any}}, ir::IRCode, idx::Int, stmt::Expr, @nospecialize(info), flag::UInt32, sig::Signature, state::InliningState) + # InvokeCICallInfo indicates that `abstract_invoke` already analyzed the call + # and determined it is of the form `invoke(f, ::CodeInstance, args...)` + # where the argtypes and worldages are valid for the context, and the invoke + # pointer is set. Therefore, we can simply transform this into an + # `Expr(:invoke, ...)` + if info isa InvokeCICallInfo + stmt.head = :invoke + stmt.args = [info.edge, stmt.args[2], stmt.args[4:end]...] + # Transformed to :invoke, now handle it as such + handle_invoke_expr!(todo, ir, idx, stmt, info, flag, sig, state) + return nothing + end nspl = nsplit(info) - nspl == 0 && return nothing # e.g. InvokeCICallInfo + nspl == 0 && return nothing @assert nspl == 1 mresult = getsplit(info, 1) match = mresult.matches[1] diff --git a/test/core.jl b/test/core.jl index 54c49a4d64349..87b27fb5a6914 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8583,6 +8583,21 @@ f_invalidate_me() = 2 @test_throws ErrorException invoke(f_invoke_me, f_invoke_me_ci) @test_throws ErrorException f_call_me() +mysin(x::Float64) = sin(x) +@test mysin(1.0) == sin(1.0) +const mysin_ci = Base.specialize_method(Base._which(Tuple{typeof(mysin), Float64})).cache +mysin2(x::Float64) = invoke(mysin, mysin_ci, x) +@test mysin2(1.0) == sin(1.0) +@test any(1:3) do _ + @allocated(mysin2(rand())) == 0 +end +let this_world = Base.get_world_counter() + f(x) = invoke(mysin, mysin_ci, x) + @atomic mysin_ci.min_world = this_world + 10 + @test_throws ErrorException f(1.0) +end + + myfun57023a(::Type{T}) where {T} = (x = @ccall mycfun()::Ptr{T}; x) @test only(code_lowered(myfun57023a)).has_fcall myfun57023b(::Type{T}) where {T} = (x = @cfunction myfun57023a Ptr{T} (Ref{T},); x) From b6549ab6539565669f9113ffb4ffc1962dc9d50f Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 24 Jan 2026 10:32:55 -0500 Subject: [PATCH 23/34] bindings: Define behavior of `using` an ambiguous binding (#60804) We were missing handling for the case where the binding that we're using is ambiguous. There are two possible behaviors: 1. The ambiguous binding gets ignored for the purpose of resolution 2. The ambiguity poisons and the imported binding is also ambiguous Current behavior between these two depends on resolution order (which is bad and part of what the assert was complaining about). This decides that case #2 is the correct behavior and fixes #60659. (cherry picked from commit 0f275e3e8b43bed4062c33ddb615ae9aececd4c3) --- src/module.c | 5 ++++- test/core.jl | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/module.c b/src/module.c index 3ec8f5bd52782..faa6ae41b712d 100644 --- a/src/module.c +++ b/src/module.c @@ -104,7 +104,6 @@ static void update_implicit_resolution(struct implicit_search_resolution *to_upd return; } if (to_update->ultimate_kind == PARTITION_KIND_GUARD) { - assert(resolution.binding_or_const); to_update->ultimate_kind = resolution.ultimate_kind; to_update->binding_or_const = resolution.binding_or_const; to_update->debug_only_import_from = resolution.debug_only_import_from; @@ -310,6 +309,10 @@ struct implicit_search_resolution jl_resolve_implicit_import(jl_binding_t *b, mo imp_resolution.binding_or_const = tempbpart->restriction; imp_resolution.debug_only_ultimate_binding = tempb; imp_resolution.ultimate_kind = PARTITION_KIND_IMPLICIT_CONST; + } else if (kind == PARTITION_KIND_FAILED) { + imp_resolution.binding_or_const = NULL; + imp_resolution.debug_only_ultimate_binding = tempb; + imp_resolution.ultimate_kind = PARTITION_KIND_FAILED; } } imp_resolution.debug_only_import_from = imp; diff --git a/test/core.jl b/test/core.jl index 87b27fb5a6914..2702c34879523 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8687,3 +8687,17 @@ primitive type ByteString58434 (18 * 8) end @test Base.datatype_isbitsegal(Tuple{ByteString58434}) == false @test Base.datatype_haspadding(Tuple{ByteString58434}) == (length(Base.padding(Tuple{ByteString58434})) > 0) + +# #60659 - Behavior of using'd ambiguous bindings +module AmbiguousUsing60659 + using Test + module A + export X + module B; struct X; end; export X; end + module C; struct X; end; export X; end + using .B, .C + end + module D; struct X; end; export X; end + using .D, .A + @test_throws UndefVarError X +end From 3a047b7d1f685122e38e21394ef37b705fb9644a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 29 Jan 2026 12:14:06 +0100 Subject: [PATCH 24/34] compiler/ssair: preserve negative NewSSAValue (#60688) During incremental compaction a forwarded NewSSAValue with a negative id was treated like an SSAValue, producing SSAValue(-n) and tripping `renumber_ssa2` bounds checks. Only convert NewSSAValue to SSAValue when the id is positive, so new_new_nodes references remain valid. Fixes #57827. --- Compiler/src/ssair/ir.jl | 5 ++++- Compiler/test/irpasses.jl | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Compiler/src/ssair/ir.jl b/Compiler/src/ssair/ir.jl index 743e26cb230bb..1461bad65d1bc 100644 --- a/Compiler/src/ssair/ir.jl +++ b/Compiler/src/ssair/ir.jl @@ -1684,7 +1684,10 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr stmt = ssa_rename[stmt.id] end elseif isa(stmt, NewSSAValue) - stmt = SSAValue(stmt.id) + if stmt.id > 0 + # Negative ids reference new_new_nodes and must remain NewSSAValue. + stmt = SSAValue(stmt.id) + end else # Constant assign, replace uses of this ssa value with its result end diff --git a/Compiler/test/irpasses.jl b/Compiler/test/irpasses.jl index 86567440e9fb4..9b948f03578e0 100644 --- a/Compiler/test/irpasses.jl +++ b/Compiler/test/irpasses.jl @@ -2135,3 +2135,19 @@ let src = code_typed1((Vector{Any},)) do xs end @test count(iscall((src, Core.svec)), src.code) == 1 end + +# Negative NewSSAValue ids must be preserved during compaction +function f_57827(op, init, x) + v = op(init, x) + i = 0 + while i < 1 + v = op(v, x) + i += 1 + end + return v +end +let rf = (acc, x) -> ifelse(x > acc[1], (x,), (acc[1],)) + @test f_57827(rf, (0.0,), 1) === (1,) + ir = first(only(Base.code_ircode(f_57827, (typeof(rf), Tuple{Float64}, Int64); optimize_until="CC: SROA"))) + @test ir isa Compiler.IRCode +end From 3feb3be8909f71ad3b3b6632947ddb68be28ef96 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Thu, 29 Jan 2026 06:10:28 -0500 Subject: [PATCH 25/34] Fix typo in partially_inline! (#60854) Found by claude-code debugging a random zygote issue: https://github.com/SciML/NeuralPDE.jl/pull/1020#issuecomment-3799139274. `spvals` just doesn't exist within this function. This issue has apparently existed since Julia 1.6 --- base/meta.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/meta.jl b/base/meta.jl index fa07c9582cd0c..7bdae95b39b30 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -521,7 +521,7 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any}, end return x elseif head === :cfunction - @assert !isa(type_signature, UnionAll) || !isempty(spvals) + @assert !isa(type_signature, UnionAll) || !isempty(static_param_values) if !isa(x.args[2], QuoteNode) # very common no-op x.args[2] = _partially_inline!(x.args[2], slot_replacements, type_signature, static_param_values, slot_offset, From 06de0f3cf5df2a04b4334506f42fd7110cf7969f Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 29 Jan 2026 12:23:53 +0100 Subject: [PATCH 26/34] ssair: fix phi edge cleanup for current block (#60697) --- Compiler/src/ssair/ir.jl | 26 +++++++++++++++++++------- Compiler/test/ssair.jl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/Compiler/src/ssair/ir.jl b/Compiler/src/ssair/ir.jl index 1461bad65d1bc..df95bcf59b941 100644 --- a/Compiler/src/ssair/ir.jl +++ b/Compiler/src/ssair/ir.jl @@ -1382,8 +1382,19 @@ function kill_edge!(ir::IRCode, from::Int, to::Int, callback=nothing) kill_edge!(ir.cfg.blocks, from, to, callback) end -# N.B.: from and to are non-renamed indices -function kill_edge!(compact::IncrementalCompact, active_bb::Int, from::Int, to::Int) +@inline function compacted_stmt_range(compact::IncrementalCompact, bb::BasicBlock, active_bb::Int, to::Int) + to == active_bb && return StmtRange(first(bb.stmts), compact.result_idx - 1) + return bb.stmts +end + +""" + kill_edge_terminator!(compact::IncrementalCompact, active_bb::Int, from::Int, to::Int) + +Kill a CFG edge while compacting a terminator in `active_bb`. Assumes all PhiNode +block statements in `to` have already been processed, so the active BB may only +scan the compacted prefix when `to == active_bb`. `from` and `to` are non-renamed indices. +""" +function kill_edge_terminator!(compact::IncrementalCompact, active_bb::Int, from::Int, to::Int) # Note: We recursively kill as many edges as are obviously dead. (; bb_rename_pred, bb_rename_succ, result_bbs, domtree) = compact.cfg_transform preds = result_bbs[bb_rename_succ[to]].preds @@ -1399,7 +1410,7 @@ function kill_edge!(compact::IncrementalCompact, active_bb::Int, from::Int, to:: for succ in copy(to_succs) new_succ = findfirst(x::Int->x==succ, bb_rename_pred) new_succ === nothing && continue - kill_edge!(compact, active_bb, to, new_succ) + kill_edge_terminator!(compact, active_bb, to, new_succ) end empty!(preds) empty!(to_succs) @@ -1421,8 +1432,9 @@ function kill_edge!(compact::IncrementalCompact, active_bb::Int, from::Int, to:: # Remove this edge from all phi nodes in `to` block # NOTE: It is possible for `to` to contain only `nothing` statements, # so we must be careful to stop at its last statement - if to < active_bb - stmts = result_bbs[bb_rename_succ[to]].stmts + if to <= active_bb + bb = result_bbs[bb_rename_succ[to]] + stmts = compacted_stmt_range(compact, bb, active_bb, to) idx = first(stmts) while idx <= last(stmts) stmt = compact.result[idx][:stmt] @@ -1502,14 +1514,14 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr if cond ssa_rename[idx] = nothing result[result_idx][:stmt] = nothing - kill_edge!(compact, active_bb, active_bb, stmt.dest) + kill_edge_terminator!(compact, active_bb, active_bb, stmt.dest) # Don't increment result_idx => Drop this statement else label = bb_rename_succ[stmt.dest] @assert label > 0 ssa_rename[idx] = SSAValue(result_idx) result[result_idx][:stmt] = GotoNode(label) - kill_edge!(compact, active_bb, active_bb, active_bb+1) + kill_edge_terminator!(compact, active_bb, active_bb, active_bb+1) result_idx += 1 end else diff --git a/Compiler/test/ssair.jl b/Compiler/test/ssair.jl index f8d8a14adf9d7..ad001cf05aab0 100644 --- a/Compiler/test/ssair.jl +++ b/Compiler/test/ssair.jl @@ -109,6 +109,21 @@ let cfg = CFG(BasicBlock[ @test length(compact.cfg_transform.result_bbs) == 4 && 0 in compact.cfg_transform.result_bbs[3].preds end +# Test that removing a self-edge during compaction only scans compacted phi statements. +let code = Any[ + # Block 1 + Compiler.GotoNode(2), + # Block 2 + Core.PhiNode(Int32[1, 3], Any[1, 2]), + Compiler.GotoIfNot(true, 2), + # Block 3 + Compiler.ReturnNode(0), + ] + ir = make_ircode(code) + ir = Compiler.compact!(ir, true) + @test Compiler.verify_ir(ir) === nothing +end + # Issue #32579 - Optimizer bug involving type constraints function f32579(x::Int, b::Bool) if b @@ -858,3 +873,19 @@ let ir = Compiler.inflate_ir!(ci, mi) @test ir isa Compiler.IRCode end + +# Tests that CFG edge cleanup during compaction doesn't corrupt iteration codegen. +Trips_60660 = let + Ts = (Float64, Float32) + [(Ta, Tb, Tc) for Ta in Ts for Tb in Ts for Tc in Ts] +end +@test Trips_60660 == [ + (Float64, Float64, Float64), + (Float64, Float64, Float32), + (Float64, Float32, Float64), + (Float64, Float32, Float32), + (Float32, Float64, Float64), + (Float32, Float64, Float32), + (Float32, Float32, Float64), + (Float32, Float32, Float32), +] From 281b06d4874ec158efde69c77b800d598b99f348 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:44:31 +0900 Subject: [PATCH 27/34] inference: fix union split handling for custom lattices (#60857) `MustAlias` has `has_extended_unionsplit(::MustAliasLattice) === true` so it is treated as a target for union split, but `uniontypes` does not handle `MustAlias` specially, causing union split to fail for `MustAlias`. This issue is addressed by always applying `uniontypes` to the result of `widenconst(x)`. External custom lattice implementations could previously provide their own `uniontypes`, but it would be cleaner interface design if they just overload `widenconst` for their custom lattice elements so that it returns `Union`-type. --- Compiler/src/typeutils.jl | 5 +++-- Compiler/test/inference.jl | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Compiler/src/typeutils.jl b/Compiler/src/typeutils.jl index a4c50fc7bb098..06264f7bed57c 100644 --- a/Compiler/src/typeutils.jl +++ b/Compiler/src/typeutils.jl @@ -244,8 +244,9 @@ function _switchtupleunion(𝕃::AbstractLattice, t::Vector{Any}, i::Int, tunion _switchtupleunion(𝕃, t, i - 1, tunion, origt) end t[i] = origti - elseif has_extended_unionsplit(𝕃) && !isa(ti, Const) && !isvarargtype(ti) && isa(widenconst(ti), Union) - for ty in uniontypes(ti) + elseif (has_extended_unionsplit(𝕃) && !isa(ti, Const) && !isvarargtype(ti) && + (wty = widenconst(ti); isa(wty, Union))) + for ty in uniontypes(wty) t[i] = ty _switchtupleunion(𝕃, t, i - 1, tunion, origt) end diff --git a/Compiler/test/inference.jl b/Compiler/test/inference.jl index ccbcb06a631ba..f7101d4319351 100644 --- a/Compiler/test/inference.jl +++ b/Compiler/test/inference.jl @@ -2597,6 +2597,15 @@ end == Integer Val(isdefined(xxx.value, :x)) end == Val{true} +# Test union splitting for MustAlias +struct GetSomethingA; x::Union{Nothing,Int}; end +struct GetSomethingB; x::Int; end +getsomethingx(a::GetSomethingA) = something(a.x, 0) +getsomethingx(b::GetSomethingB) = b.x +@test Base.infer_return_type((Union{GetSomethingA,GetSomethingB},); interp=MustAliasInterpreter()) do x + getsomethingx(x) +end == Int + @testset "issue #56913: `BoundsError` in type inference" begin R = UnitRange{Int} @test Type{AbstractVector} == Base.infer_return_type(Base.promote_typeof, Tuple{R, R, Vector{Any}, Vararg{R}}) From a42e47bfcbd296170c03e4a3d843aef8f933512f Mon Sep 17 00:00:00 2001 From: rokke <66498307+rokke-git@users.noreply.github.com> Date: Wed, 28 Jan 2026 00:16:20 -0500 Subject: [PATCH 28/34] Merge pull request #60834 from rokke-git/patch-5 Test suite: switch to `httpbingo.julialang`, fall back to `httpbin.julialang` on failure (cherry picked from commit 5ab8db39c014dfcf1b53314932dddfea35ecb2c7) (cherry picked from commit e4cfa466a924b03fc102161c448251b2bfbe0d38) --- test/download_exec.jl | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/download_exec.jl b/test/download_exec.jl index 777fb6773c463..93af540dd70a1 100644 --- a/test/download_exec.jl +++ b/test/download_exec.jl @@ -5,22 +5,31 @@ module TestDownload using Test mktempdir() do temp_dir + url = try + download("https://httpbingo.julialang.org") + "https://httpbingo.julialang.org" + catch ex + bt = catch_backtrace() + @info "Looks like there is a problem with a JuliaLang mirror of httpbingo" + @info "Trying httpbin" exception=(ex,bt) + "https://httpbin.julialang.org/" + end # Download a file file = joinpath(temp_dir, "ip") - @test download("https://httpbin.julialang.org/ip", file) == file + @test download("$url/ip", file) == file @test isfile(file) @test !isempty(read(file)) ip = read(file, String) # Download an empty file empty_file = joinpath(temp_dir, "empty") - @test download("https://httpbin.julialang.org/status/200", empty_file) == empty_file + @test download("$url/status/200", empty_file) == empty_file @test isfile(empty_file) @test isempty(read(empty_file)) # Make sure that failed downloads do not leave files around missing_file = joinpath(temp_dir, "missing") - @test_throws Exception download("https://httpbin.julialang.org/status/404", missing_file) + @test_throws Exception download("$url/status/404", missing_file) @test !isfile(missing_file) # Use a TEST-NET (192.0.2.0/24) address which shouldn't be bound From 60cbee4f206fb0bdf5c7e12d1d03dfc8888f8567 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 23 Jan 2026 11:12:22 -0500 Subject: [PATCH 29/34] OpenBLAS: Update to 0.30.0 (#60789) (cherry picked from commit 2db36c1e81844c426c8a68331312283b3b53f627) --- deps/checksums/openblas | 134 +++++++++---------------------- deps/openblas.version | 8 +- stdlib/OpenBLAS_jll/Project.toml | 2 +- 3 files changed, 43 insertions(+), 101 deletions(-) diff --git a/deps/checksums/openblas b/deps/checksums/openblas index f1bcf3f322d8c..8b95dd1733274 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,96 +1,38 @@ -OpenBLAS.v0.3.29+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/227fc95ef10e30698aade797ebd8b685 -OpenBLAS.v0.3.29+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/49a932f0c1c2d1087d20a3de2940733ed6a944284e1cf2a384a7401c5ca6bd90a35e9679b4f19bac176923aa170427e7514a47fc16261413ee03a59bbb301bd0 -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/77acdfde5dc6f05629f3fb68a95b78f8 -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/f28187213eac2d481bc12263fe13fcb35f4771084bacaa42b0b149ac15cf89d033910519ecc5cada77915a48c95a2de3ea4a476c0c6bc3f154e7f2ceb4bf3ffd -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/4fb2bd80d3e4ad8ce04fa33c9a2aaa19 -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/8cc2aee3b351cc5c78e494efededdf98f65ce8942453bb3a55c90e0822ddcc07bc7716d0746bbc16701eca458b7a7aa933e9363f71bd56788c9fab36bd9bcf6d -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/3a3ef97dc80dec3d0debade503ca2232 -OpenBLAS.v0.3.29+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/53d707f9bf57c1a19279f0146e767d779280f922ef621b5f372cedc018efb2798adabbd762324819f342d0fd98ec17c68badc50da7b6e9aa3e57c3a3c045dab2 -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/463cb6b46091f4b4b4f2535b9f38f11d -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/5a5a7d5a7ca5e619d5af9bcbab7cfffcb4b7954005cb4a2d03f4cd0ef29c95707e830ad0b0303d694cace557cb1e9973c0244ae1f635249a313fb9f9cdfaacd9 -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/699ca0247ec7cccec0d9d2801b5a35a7 -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/3bb2926d2d2a43c280bb947063dd74b65194118edbd99df820bef56a546648ed903245e0947ebc31765ff43784b11349bf86cd592c78d143c0627d692162b344 -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/2ab069e5abd5014495b849bfbaabbd3a -OpenBLAS.v0.3.29+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/fd10e4ce326c524d97e69e50342ab63b8298c796faab8f4512772fbb9c4ae1ddc85d54643c868f3b2dc8084af974430e1f8751576bedfdc88af2ba0d2affba1a -OpenBLAS.v0.3.29+0.aarch64-unknown-freebsd-libgfortran4.tar.gz/md5/ce5d04e041e9447529ad8e043e45895c -OpenBLAS.v0.3.29+0.aarch64-unknown-freebsd-libgfortran4.tar.gz/sha512/eaf521d3957713e9d22b2c0b991f5eb846096891dc15bc42ad0817c32e6a1343617d28afe739dce0e39c185d022d3cdd44db2610635691990003b1b0a29f4657 -OpenBLAS.v0.3.29+0.aarch64-unknown-freebsd-libgfortran5.tar.gz/md5/00b3a4433f93a56fa8b0f17acc254865 -OpenBLAS.v0.3.29+0.aarch64-unknown-freebsd-libgfortran5.tar.gz/sha512/a9845380778ec15642d74a46dfa65f8a325929f8ec8d61915941f6e228bb1ed29310f86f20ec559fdc2d5dac98a780f71a1b3116676a34e18ee7c0cb86cb7124 -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/1be6fa7ef684733faab744fdec6c8dbd -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/7c7803a0484b8c8e343ff5049e52fe81b76e43f0aaca7a5ad0134079147d2311cb5b159738486dcdd7ec69eb42cb0eea738741401179499a53fead2fbd8dba3b -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/451dad687dd26a299e4a44db37a8db2a -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/ea73ee91896203566dd7510303c73d77189afec913ac1de3b7c7935dc2c460f87c83a8ddd272d9542b619e419b9392479f02540ef1c8d3daa528bf05aaf5c3f1 -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/07ca32f715981570f2e1a5ac6721e569 -OpenBLAS.v0.3.29+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/c6ece0dac375fd66a303ca6f503e46f78472a59dc13381e8462e3e9c29e133cbe87ee77f6144a80924ae286162620c4395f5217e4f9ba379a471409085950427 -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/49ac07fcdf0d7ce221051d089b408e05 -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/6c9c379473f1bb5f202ca183c6ef4d43b442c867e67712e6ec2936790c282143c1edae0a1385e366f729c952e02fca13604f6b51d778dabb28ca7be0f359281e -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/87e3dea9e115fbc9a0c7f64020c41f74 -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/63a37a9cc882562978460e1e0f603177921a64ece7d4050b0b7a584e05d80f58314e7f8e988ea5446945d7009620c4f746ce547fe7dcb77a0707d54fd830983e -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/8c85e7ce9bd702438c548bdae54f5c32 -OpenBLAS.v0.3.29+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/3dbaa326944d79688fa167c968a7e2660bf3b94c2e052755cc8b1ede853c02364edb7fa974880c37c60ee6e6f84c75848eb4d999c5c1e8881441191dbab056e2 -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/1be6fa7ef684733faab744fdec6c8dbd -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/7c7803a0484b8c8e343ff5049e52fe81b76e43f0aaca7a5ad0134079147d2311cb5b159738486dcdd7ec69eb42cb0eea738741401179499a53fead2fbd8dba3b -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/451dad687dd26a299e4a44db37a8db2a -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/ea73ee91896203566dd7510303c73d77189afec913ac1de3b7c7935dc2c460f87c83a8ddd272d9542b619e419b9392479f02540ef1c8d3daa528bf05aaf5c3f1 -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/07ca32f715981570f2e1a5ac6721e569 -OpenBLAS.v0.3.29+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/c6ece0dac375fd66a303ca6f503e46f78472a59dc13381e8462e3e9c29e133cbe87ee77f6144a80924ae286162620c4395f5217e4f9ba379a471409085950427 -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/49ac07fcdf0d7ce221051d089b408e05 -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/6c9c379473f1bb5f202ca183c6ef4d43b442c867e67712e6ec2936790c282143c1edae0a1385e366f729c952e02fca13604f6b51d778dabb28ca7be0f359281e -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/87e3dea9e115fbc9a0c7f64020c41f74 -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/63a37a9cc882562978460e1e0f603177921a64ece7d4050b0b7a584e05d80f58314e7f8e988ea5446945d7009620c4f746ce547fe7dcb77a0707d54fd830983e -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/8c85e7ce9bd702438c548bdae54f5c32 -OpenBLAS.v0.3.29+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/3dbaa326944d79688fa167c968a7e2660bf3b94c2e052755cc8b1ede853c02364edb7fa974880c37c60ee6e6f84c75848eb4d999c5c1e8881441191dbab056e2 -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran3.tar.gz/md5/86834236dee3db3affb38b8cdcf59681 -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/6731b4ea22a0f3d25f9d041e2baa6d66f1027dce49931a334a33711fc4c6de5da368274c9328618ed78158855c5d38524b917447d1aafb5c551934cf982505d2 -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran4.tar.gz/md5/c63c2fb1bda01456d99590e9aec3b45f -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/437c260499f4a28db9efb4bbdff31c0f675f3ccef1bd48fd2dfbb8c8897fc75608bd7247293bd3eae129b133cb05c3c8150dd19c243faa09b6506688f57c633a -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran5.tar.gz/md5/376567d56bf4314f8a4adcfc4d1baa66 -OpenBLAS.v0.3.29+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/c4952874b19af4fd0d5541999d07094f7e7e983124964405a4756b9adf619172b7128e11557e64a80bc4eadaf76c783609a75f25ccfc44fc4f181886a0c8ca18 -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran3.tar.gz/md5/8f7abbc6d5cefdbefb2b9499ec8874c9 -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran3.tar.gz/sha512/b8c39674df9400efecbe4ac740f0c3ef11a04dd852f31774d63db3ca6583a21c8e0a0b80aa4e7b82be7a8fa3de38892d4fbca34244acef7fb49e8ffc0e1eed09 -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran4.tar.gz/md5/6b0f0544fe45de9d2dea946c7f55cc40 -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran4.tar.gz/sha512/8c21df39a8ee99614ef0880706c1497d032f68dfc332cc5ee111f69bfc818db4896115a964f16115ac49b01b31713037c905792d9586dd05471efdb21dd0be88 -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran5.tar.gz/md5/aa343048c35c5227a4bcc37f25ddfacb -OpenBLAS.v0.3.29+0.i686-linux-musl-libgfortran5.tar.gz/sha512/af6c9d15d9d5a4901d228522d2e20da5276f1bf35d7f34648697ba7a39153a9152dc17f5f0d360593e733ef3e3317df29581cb86fdd9fe8d6e6093592a6240bb -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/8595dda5ee1f15b2070d8ac20077f389 -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/df7d7ad68b47f8865d01f6edd6ba44587c6563ebc4a1900f92210b5117fc7c581e6145f95e10fe7a3db48eda9805330073c8cbeec7eb8a19978ec33f2528cef8 -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/4e67905ab599f24327e9726f70d261cf -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/13ba78e98d7c2cda62a6ca9226365e90fa8a5404e4006ae5e49030b314b762a37d78977f14c72448c844e68a6b83ecd679c60362fde023c9052b9b8597d7775c -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/e78c5005d9ee57ab464fca86c6d6fff1 -OpenBLAS.v0.3.29+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/8ceb9527461136cd4f4d02f10c241f5e7070991f73c974389acedb1d9d7be4bade592bc021ba1001c5ac148ea580cf8355fb89c88438820bfa665bf3e72392fa -OpenBLAS.v0.3.29+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/421d93da4cfab0df79569e09dff1015b -OpenBLAS.v0.3.29+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/351174d948626ad36daf40c45672cd1ac40bbe4af25c28332fbea62a7ba89188a7d33836d327d31ce99b9a9334c6053366d33b58f588355c2818e332e46b34d0 -OpenBLAS.v0.3.29+0.riscv64-linux-gnu-libgfortran5.tar.gz/md5/34cc0b3260d9471bc8fb32005e3c5043 -OpenBLAS.v0.3.29+0.riscv64-linux-gnu-libgfortran5.tar.gz/sha512/5eec279c5eead55d099d8db4a75dd4a3f2bcbc8bb22b33884a89d678e4eebf87c6dece1aa4c24374d0162b35f376648a473c2d6d7866583e61016e37f4262820 -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/f921a0ad6ebf91f444cb8d927886e573 -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/5cc98edf9fa8ba8981ce78b2595fd27645c783561ff19d0fd25ecc927f63492437a4b9b80d5caf51ad619b7ca5d24cb43e153156921f9f03c64741014b686196 -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/0126b52c134954e63ab8f9197afebd7a -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/6d1e37009e6831a26f25bfd3e95dbcc841ee50a3f84dc4355d7fd528cd74a400138955558306345e986a732d0d1ef9294c4f5be457d05119a8e1e5851cc8ca20 -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/e8c7bd786672a9caf989dbe4fcef896a -OpenBLAS.v0.3.29+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/2e708fddfa8e5821d2e44bbc00a86df83b09cdfc0054d7c2bbb2a8de52ed80c95973e6602048335a60b54be1baeb617121b605644daf50579b2044d0c5766063 -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/b1efd957a2a63f814168bd318381812e -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/097a750b7f381089588498e52a2b07a67202bfd4bc2e38f5abbbeb372129e392fcd53beade2fa7cb60ef0038f2baf61d57fab40b5585806d3ddb1fcdad73bbe3 -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/c3560828f503962c6ae94135c4f00ac5 -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/1ad514172e51a5d3eb6fea03182e3eb9c6db99d9d11c430e3d8542a9ce0f5d6967e623b9c0951535b683210ce0b02460358c67520b06363594f6063f8f012396 -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/07a9c3050824bbc6a96efdb333fff0ea -OpenBLAS.v0.3.29+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/b737ab1fc8c5ffd1494804c59f8fd3e5d3d8a063a89fbbc29cbd75d43af233ddf77f63d0e514059164517f408ea340ffe95c020a7c696af8c52be3a7259922ab -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/9a4a828a1b58737c79eb170c94021c52 -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/785443a38cda87a63ee4268cdaa51bbc2c4662de27e0695cd7e21ffe55c3bddb1fa1a399edec39c3466f2ea0bd5ce727daca2eb381213059419c2e8371b5a733 -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/cd4afdd6f6ba06c7541e7124316802b3 -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/55796fdb52e1ac92750dfc2233d3feb37b53920b12024be605bf6c7322153c4dbeb650f16d6def4f0fac685733a04a1c4cacb1fc4e562a27a00b4f44484a4715 -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/8cd55ac7a7f0a7bda80b44171793718e -OpenBLAS.v0.3.29+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/728991a4c39d691abebac3ebbb2dbe093f3a4acd2d3aefb5c7c08bccf0dc1fd5aaa24de6367961d278d448b76a4ddacab36b7be15128f7ccec5049eab83828da -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/c2dda93a61e02812831b6a6e33f7d2ca -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/bd62e44f266b834c6dfab068841506a83eaf510eefbcf8896dfca36671321430293dc251885af108d94affc5b193919e0e29c965fef3ce6d994df37324aef013 -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/8cbd64d2ce4e3944e702696839a4ad3a -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/3621dfa5cf8bca62bb8f2a049acdc0ed4e02cb2b5585758e6e1173e61b3a5f0e1655a10f2feb2f0e70a098b00181d0b24dcd61e1205324d436b712f58e58df5d -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/476f1ebfb93baad6fac778fa00c4f99e -OpenBLAS.v0.3.29+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/06aa18da572b0904e5d8ec0823626d0af02a29224aba98efd43d8fbf4636d2625ece9f88f9a86d2e493f016c106f2ae71422191afc16dda2b26bbc81eb09d901 -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/8c55d04d9def74f6bc2cc0d03b764975 -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/d6196a339a263d80c05b94596ec5acfeff6e3ce93fafee348a864f760aa1239aa59ee294cab29fd730dcf7974ac6dcb230433184be093612bad3bc3edc067649 -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/8427f098a44457ba65b21a16439ee6c0 -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/4855321b2a16d55e1c6e830e33d0a199286002798c0f33c7f594a55626b5a502df94c172de4fd0a38ab6ba92f384abbbc3ef06123c3115a3f290f50a9d43ae9d -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/9d1636bb7500d9ba15ed703231f8def2 -OpenBLAS.v0.3.29+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/0b3530fd95e01d58b85157d7bb75e44ee7b2f0c5a912920ff0763f404e1ab28d16a624463f3f20241c7baea57e00fca3f896d6e0befb6a1c9e5ece4264b87e35 -openblas-8795fc7985635de1ecf674b87e2008a15097ffab.tar.gz/md5/095d293409140dd8eee500eb92372eb7 -openblas-8795fc7985635de1ecf674b87e2008a15097ffab.tar.gz/sha512/7b10d4c2bef68159e0a88fb6d4fd0ecca17b4c6394479e8f838f5078d9d5acef24c6bd44777d43c03859c952d4612d76b57aa0bff367b197920ea16eb3839144 +OpenBLAS.v0.3.30+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/6c5bec990a36d3bad7c05ca87ca155fe +OpenBLAS.v0.3.30+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/4df67c3b7cf117f8b92cf602f60ad0830320a9db0aa6359478fe7d816c15c8210c13a9871ab55f804aa5bf6a580ba8e95363807c11d750c518d9a694c8702caa +OpenBLAS.v0.3.30+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/03df691f8f1d13076311622868e4c8c8 +OpenBLAS.v0.3.30+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/dd7ebac53e7cf9c8192445c58fa43c36e50f3a1513cb48183b3f7ad4a45caf9d4116ec4a614267951c40bccb8eb7087faa5b98620f98f1127e79e15c2e561c55 +OpenBLAS.v0.3.30+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/0526550a9f4401a849928a27f092eb84 +OpenBLAS.v0.3.30+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/a208ca17369cfb8297d7808dcd72bdc77b46f4010ef8bab21fa4e29fdfd2dd61ca5b7bb536b905e7a5027895ff9becbe408c0e0f6ed7ab2ba5f25b146c2fdfc2 +OpenBLAS.v0.3.30+0.aarch64-unknown-freebsd-libgfortran5.tar.gz/md5/ff980856f1cdd8389b9d380957151c0f +OpenBLAS.v0.3.30+0.aarch64-unknown-freebsd-libgfortran5.tar.gz/sha512/acda9d2d6ad7237b4dd8e4d848ddf830f393cdb9f48e7ecc72478072a2c0338b38b204ad15f89551d5652f1ea122a44acf82245bb023d458b4a1ff2276b36951 +OpenBLAS.v0.3.30+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/0385a0d1dd426c0e05ce9d4deab0c6f0 +OpenBLAS.v0.3.30+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/d197a4d417f9ccb6dd95c193d8665c47828a05eea1496779a425d381bffdc45c3e95384e9acf7c07882a6a52df5f213e432c66d015e576c62b3a0a44b01a6941 +OpenBLAS.v0.3.30+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/51296df0302f7a97fe1783732b37f871 +OpenBLAS.v0.3.30+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/b14b283e0e29fee5d5547c06169245c74bdfd913803798ff673c9167a1c352a2452519ea79706ad0607c39d0477c6ccd84738079757a963906648077380e2f69 +OpenBLAS.v0.3.30+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/0385a0d1dd426c0e05ce9d4deab0c6f0 +OpenBLAS.v0.3.30+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/d197a4d417f9ccb6dd95c193d8665c47828a05eea1496779a425d381bffdc45c3e95384e9acf7c07882a6a52df5f213e432c66d015e576c62b3a0a44b01a6941 +OpenBLAS.v0.3.30+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/51296df0302f7a97fe1783732b37f871 +OpenBLAS.v0.3.30+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/b14b283e0e29fee5d5547c06169245c74bdfd913803798ff673c9167a1c352a2452519ea79706ad0607c39d0477c6ccd84738079757a963906648077380e2f69 +OpenBLAS.v0.3.30+0.i686-linux-gnu-libgfortran5.tar.gz/md5/21e7fa56ca21086513138169629ed5d0 +OpenBLAS.v0.3.30+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/6c4af23a40b5a77d3bf8f2cb3e2efaf57433fbd96a28786039a0437f382e333bc55e53728721e0a2f75216b7f5ad4f8ec8457c70193947715de41a61293d6d3b +OpenBLAS.v0.3.30+0.i686-linux-musl-libgfortran5.tar.gz/md5/f6cb4fe4316d7d724710894c68c1780a +OpenBLAS.v0.3.30+0.i686-linux-musl-libgfortran5.tar.gz/sha512/b84c6b7f9f6b1ed59e6b9873fa7e0b6534ee3383819e1fdba546e0bcb4c0c8c9cee27d911dbfa29f48da81064dc9e1b1fd417b0444988812e3ab275feecf845c +OpenBLAS.v0.3.30+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/c57ca51cb4728c758eb29ea11bdbdbd3 +OpenBLAS.v0.3.30+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/dea2d4dfa600af7b442dccfb0d71b740046d3c771e1cbbf8cefc9ff92efeed1007d5175055901d670aec0e894f53eda959d3072bbcd52d15535fe91395d2ed2d +OpenBLAS.v0.3.30+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/a3243ffcd2b6480576c1e190fa37f8d7 +OpenBLAS.v0.3.30+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/7b43d151be9098ff665826e107fbf168279fcbd4b5d92b638759ce1f90c063877d9692b259dc698dba964d7bb9cdab311dcb99711d72e7485841d20c3704c58b +OpenBLAS.v0.3.30+0.riscv64-linux-gnu-libgfortran5.tar.gz/md5/97660a61ad4ffd557c7590dffcff9589 +OpenBLAS.v0.3.30+0.riscv64-linux-gnu-libgfortran5.tar.gz/sha512/eec0daf12551bf2bb8e501460d68ab1b8f49e23ce4fdaf87b975e2e4c43c1dc43c46a392e1d604dca932eca141f10ef0b10368ed712d549b5b0c0620652da2da +OpenBLAS.v0.3.30+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/eb307877e90ea2ea22bcaad40386d9a1 +OpenBLAS.v0.3.30+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/426e02d8bda9497366e4e94408dc50281adb9af825d414ce58518213304183b3ff5cd31c1d8740c078c55ed690e43a21c99314e0fe2c74e90b649ca0856dd965 +OpenBLAS.v0.3.30+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/c0f6c467594e12938884cfe0cfad60e2 +OpenBLAS.v0.3.30+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/f127cc8f433661682e7e92dd13eb525edecbf69d05627c2fb29792b05e54a918598aefe93bf943501338201b55a2758f8e1cb6b9b75d8ed26394ff02ea2909f6 +OpenBLAS.v0.3.30+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/81530db3c46dd2276c57fb5bbf15e3c1 +OpenBLAS.v0.3.30+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/4217bae98cbf85a0a5ba1baf3ffe30b722939d5261eb1ffa21980268798ae550b3c7dcff36a0a4f74f74a8234556c6a0f51df3ab28385b6d7d7a502d5cf45159 +OpenBLAS.v0.3.30+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/add69a633d2e13a954d7cf194d7682b3 +OpenBLAS.v0.3.30+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/8838a6844335720b121ffd8ad5689242f625ddf12ae8859da9b1a1e12478062db3bcadd9922b87a3a4fadd23032cf2bb0cfb73e76c4fb11a5f2a17efcc935909 +OpenBLAS.v0.3.30+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/d74d70d858dd39879e062be63d37d5a8 +OpenBLAS.v0.3.30+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/c10e05c6f8265d1b32d573be439eeb19bc784870e8c4fc51329c9f524cb480a170c4a907dd4ac7d90747fccbe7fa5f12a7110b2ebc141e2cd1232fb68375d676 +openblas-993fad6aebbce34a97d3f8c34d6d79d35b64cc48.tar.gz/md5/9f6a5449c6fc9078fa4665ede7400ea8 +openblas-993fad6aebbce34a97d3f8c34d6d79d35b64cc48.tar.gz/sha512/30bd90408a4b4f4babea5e565fe9bf90839353ae8aa6475946e655e02e60fa311338f82c2579c3d9558111bef5f24baf5e6a52e6d64dba2a00a1a5411ef9f334 diff --git a/deps/openblas.version b/deps/openblas.version index f9729639c67ab..63de86fef5e13 100644 --- a/deps/openblas.version +++ b/deps/openblas.version @@ -3,9 +3,9 @@ OPENBLAS_JLL_NAME := OpenBLAS ## source build -OPENBLAS_VER := 0.3.29 -OPENBLAS_BRANCH=v0.3.29 -OPENBLAS_SHA1=8795fc7985635de1ecf674b87e2008a15097ffab +OPENBLAS_VER := 0.3.30 +OPENBLAS_BRANCH=v0.3.30 +OPENBLAS_SHA1=993fad6aebbce34a97d3f8c34d6d79d35b64cc48 # LAPACK, source-only -LAPACK_VER := 3.9.0 +LAPACK_VER := 3.12.1 diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index 8eafa2f2365c1..2dde60924a2ff 100644 --- a/stdlib/OpenBLAS_jll/Project.toml +++ b/stdlib/OpenBLAS_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenBLAS_jll" uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.29+0" +version = "0.3.30+0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" From 50febfa290db7f9e7b080e4c8bddf92e9f10c14c Mon Sep 17 00:00:00 2001 From: James Wrigley Date: Mon, 26 Jan 2026 17:41:54 +0100 Subject: [PATCH 30/34] Move precompilation during package loading behind `@invokelatest` (#60727) (cherry picked from commit 4d04bb6b3b1b879f4dbb918d194c5c939a1e7f3c) --- base/loading.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 11b965235f7d0..97200262be0bf 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2678,8 +2678,6 @@ function set_pkgorigin_version_path(pkg::PkgId, path::String) nothing end -# Unused -const PKG_PRECOMPILE_HOOK = Ref{Function}() disable_parallel_precompile::Bool = false # Returns `nothing` or the new(ish) module @@ -2741,7 +2739,10 @@ function __require_prelocked(pkg::PkgId, env) try if !generating_output() && !parallel_precompile_attempted[] && !disable_parallel_precompile && @isdefined(Precompilation) parallel_precompile_attempted[] = true - precompiled = Precompilation.precompilepkgs([pkg]; _from_loading=true, ignore_loaded=false) + # Note that we use @invokelatest here to avoid world + # age issues when printing, see: + # https://github.com/JuliaLang/julia/issues/60223 + precompiled = @invokelatest Precompilation.precompilepkgs([pkg]; _from_loading=true, ignore_loaded=false) # prcompiled returns either nothing, indicating it needs serial precompile, # or the entry(ies) that it found would be best to load (possibly because it just created it) # or an empty set of entries (indicating the precompile should be skipped) From 28b6dc0996d0c614bc47cb2c14252dd20a4f54a9 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 27 Jan 2026 22:43:12 +0100 Subject: [PATCH 31/34] Make `jl_reinit_foreign_type` idempotent even with asserts (#60827) That is, if it is called twice (e.g. because precompilation is disabled) with identical arguments, then this should not trigger an assertion. This should resolve https://github.com/oscar-system/GAP.jl/issues/1314 (cherry picked from commit 1708d99d98e1d0e5b3b277f74b6a10f2f675387d) --- src/datatype.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index ee947d2512064..c08e9f783eb7c 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1042,10 +1042,14 @@ JL_DLLEXPORT int jl_reinit_foreign_type(jl_datatype_t *dt, const jl_datatype_layout_t *layout = dt->layout; jl_fielddescdyn_t * desc = (jl_fielddescdyn_t *) ((char *)layout + sizeof(*layout)); - assert(!desc->markfunc); - assert(!desc->sweepfunc); - desc->markfunc = markfunc; - desc->sweepfunc = sweepfunc; + if (desc->markfunc != markfunc) { + assert(!desc->markfunc); + desc->markfunc = markfunc; + } + if (desc->sweepfunc != sweepfunc) { + assert(!desc->sweepfunc); + desc->sweepfunc = sweepfunc; + } return 1; } From 258881787f8d1cfd03c102bcfa9ad6fc16a91054 Mon Sep 17 00:00:00 2001 From: songjhaha Date: Thu, 29 Jan 2026 22:58:24 +0800 Subject: [PATCH 32/34] make sure `jl_exit_threaded_region` executed when `threading_run` finished or be interrupted (#60822) resolve https://github.com/JuliaLang/julia/issues/60797 Co-authored-by: songjhaha Co-authored-by: Ian Butterworth Co-authored-by: Chengyu Han (cherry picked from commit d8994dc15ca8f00cfef09e1a9890e268cde5ba2e) --- base/threadingconstructs.jl | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 4b2981a4a78ed..ab1ba40461af7 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -173,24 +173,27 @@ function threading_run(fun, static) n = threadpoolsize() tid_offset = threadpoolsize(:interactive) tasks = Vector{Task}(undef, n) - for i = 1:n - t = Task(() -> fun(i)) # pass in tid - t.sticky = static - if static - ccall(:jl_set_task_tid, Cint, (Any, Cint), t, tid_offset + i-1) - else - # TODO: this should be the current pool (except interactive) if there - # are ever more than two pools. - _result = ccall(:jl_set_task_threadpoolid, Cint, (Any, Int8), t, _sym_to_tpid(:default)) - @assert _result == 1 + try + for i = 1:n + t = Task(() -> fun(i)) # pass in tid + t.sticky = static + if static + ccall(:jl_set_task_tid, Cint, (Any, Cint), t, tid_offset + i-1) + else + # TODO: this should be the current pool (except interactive) if there + # are ever more than two pools. + _result = ccall(:jl_set_task_threadpoolid, Cint, (Any, Int8), t, _sym_to_tpid(:default)) + @assert _result == 1 + end + tasks[i] = t + schedule(t) end - tasks[i] = t - schedule(t) - end - for i = 1:n - Base._wait(tasks[i]) + for i = 1:n + Base._wait(tasks[i]) + end + finally + ccall(:jl_exit_threaded_region, Cvoid, ()) end - ccall(:jl_exit_threaded_region, Cvoid, ()) failed_tasks = filter!(istaskfailed, tasks) if !isempty(failed_tasks) throw(CompositeException(map(TaskFailedException, failed_tasks))) From ddd05b52e771bad069684fe92c8788ee3934c29a Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 30 Jan 2026 10:31:37 -0500 Subject: [PATCH 33/34] OpenSSL: Update to 3.5.5 (#60875) (cherry picked from commit 99a8a7af1c77325e61b49b75f6ee207a6e0e3d40) --- deps/checksums/openssl | 76 ++++++++++++++--------------- deps/openssl.version | 2 +- stdlib/OpenSSL_jll/Project.toml | 2 +- stdlib/OpenSSL_jll/test/runtests.jl | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/deps/checksums/openssl b/deps/checksums/openssl index 1dee209bb0c5f..b5b845be03756 100644 --- a/deps/checksums/openssl +++ b/deps/checksums/openssl @@ -1,38 +1,38 @@ -OpenSSL.v3.5.4+0.aarch64-apple-darwin.tar.gz/md5/d3a74c8ea6a26b89b250ea72d4df09f4 -OpenSSL.v3.5.4+0.aarch64-apple-darwin.tar.gz/sha512/6586b7c070409be5a4a8c2b436f78d43d5e007698721478919b10247b8ba72fe591f22432b366e21f63d1d9e0f59e0bf708726b13e8e76cf46b83dfd9c6290e2 -OpenSSL.v3.5.4+0.aarch64-linux-gnu.tar.gz/md5/a63078615f652e9c8802ee4f157ce670 -OpenSSL.v3.5.4+0.aarch64-linux-gnu.tar.gz/sha512/bfb1810bf33e8428d32f9f454cb48c1ec1aff1b8cadb92e7042f053791e27b49b28676d7843b13c1837e44916553b34fcc2f6dc891b7a9ef691a249de384a17e -OpenSSL.v3.5.4+0.aarch64-linux-musl.tar.gz/md5/f5cdb3a716692ca6f3ab704eb54d2af3 -OpenSSL.v3.5.4+0.aarch64-linux-musl.tar.gz/sha512/1734abca858d554d4e8b46d494e3a41e99726b53ff9534dd85ea47e3c576c5da354940245b73d1d31fb6cc14ca50dd331385da8b7328a97d19d0592414c36835 -OpenSSL.v3.5.4+0.aarch64-unknown-freebsd.tar.gz/md5/812279eb91f01e35a39d77f77ab54a1d -OpenSSL.v3.5.4+0.aarch64-unknown-freebsd.tar.gz/sha512/17a1e1fa314c8c766e957b2adbb6bbe3bcd20e81df5a5d6280f8013821774cd447076757bb9eb436a39e31ba4921ccea25f02c4adf3784945a740fbe4192a1f0 -OpenSSL.v3.5.4+0.armv6l-linux-gnueabihf.tar.gz/md5/07bfc3d49e4085e3bf286bf0f89c9771 -OpenSSL.v3.5.4+0.armv6l-linux-gnueabihf.tar.gz/sha512/1d1e93735f208f7704259ddb1bc791d8e79f57d962b8e3ea4888aee1cb42c5726800310137a2d0a3b26e78cc7f419e3410894716932cceae549acd4aaa632ac5 -OpenSSL.v3.5.4+0.armv6l-linux-musleabihf.tar.gz/md5/0e7f6a4fc89cc7917a63f514eee960fc -OpenSSL.v3.5.4+0.armv6l-linux-musleabihf.tar.gz/sha512/2124ae606fbc3d9b60fa092241f2ca228e666758b24a043104791a7b58f8a9d1bb657918b2be67f70175ace25e336996e047ce1eb34f1ce02c95412ea657e515 -OpenSSL.v3.5.4+0.armv7l-linux-gnueabihf.tar.gz/md5/e8d8e328f953f0ed4cbc010bb760b165 -OpenSSL.v3.5.4+0.armv7l-linux-gnueabihf.tar.gz/sha512/07a80f5c370d1e61d16031bc32fd0ff2605de09afd1bcb60e4da2237e595c09336103f37d0d9d972849e6e0a4190e83f29360cbd646967f3d8aaac1bd9330e62 -OpenSSL.v3.5.4+0.armv7l-linux-musleabihf.tar.gz/md5/fb14accd074b1527dab887f6481b5e2a -OpenSSL.v3.5.4+0.armv7l-linux-musleabihf.tar.gz/sha512/366d70e849d8d7e809b8d204b8446c8b190dd87d34ac09dc5c5631dbaa6b470dc554f908e90b4346947a93d570a127d3acb4e48a6372ce0c7d8fdb52d9591e2a -OpenSSL.v3.5.4+0.i686-linux-gnu.tar.gz/md5/f8debcbb53d95da043b1105b8299202e -OpenSSL.v3.5.4+0.i686-linux-gnu.tar.gz/sha512/4c619a87cb37a2d67d7940a50b1b7b2aec2d7bdfddbadd7310a52058494026bcbd1459c09dc1e9db7f2969093070a1110e0c592c671cdc1a084737e8edb106a1 -OpenSSL.v3.5.4+0.i686-linux-musl.tar.gz/md5/ee85ed549ebd79c4fe0a02cc6f408cfc -OpenSSL.v3.5.4+0.i686-linux-musl.tar.gz/sha512/e89e76e2c375fbabbf7d9195e3212f77fd929ff4089eab2662988033a2232eaf842783079d254b01e80e82aa8bea7507ea6ffacb74c029a8c107255ff9d3502e -OpenSSL.v3.5.4+0.i686-w64-mingw32.tar.gz/md5/20f9847da4ea3a42de7a69441c68cb77 -OpenSSL.v3.5.4+0.i686-w64-mingw32.tar.gz/sha512/d88556fa5ce1164bc5890077a387d30dec4d454d1e35b743cdc562e594f872c01270fa447ced0fe8b0a6a6d1589e117576510b8d8d8abab9f0b85cc2b12232c0 -OpenSSL.v3.5.4+0.powerpc64le-linux-gnu.tar.gz/md5/cd3a9bfcc9c2ac35c363cd629303e025 -OpenSSL.v3.5.4+0.powerpc64le-linux-gnu.tar.gz/sha512/107f7a3c640c4105ed66a002020b4aa397cbd31af4305f485676b90d0a8c53ba9aae4721dfeb3406b109413e8313cc2a1fadba5786780c7af0ee5bc14e01dec0 -OpenSSL.v3.5.4+0.riscv64-linux-gnu.tar.gz/md5/4d1eb41a393b36a1ca39d52113991861 -OpenSSL.v3.5.4+0.riscv64-linux-gnu.tar.gz/sha512/ad896b5623d746b09866d378b9f05f515aa34d5f874f57fc76329df8630bced8d6d7576dd5ae79248347bbca98b035b941773692ba27a1c899fd5500e01b6432 -OpenSSL.v3.5.4+0.x86_64-apple-darwin.tar.gz/md5/37b748664516d632886aab07cabaeb96 -OpenSSL.v3.5.4+0.x86_64-apple-darwin.tar.gz/sha512/49f24b13906cf4538d56b562f26c9641ed5d64e05cc176dc4c461ff9e238828c216e0e396527c7403fd8672b313bc59839a767ab530222878191b1dc01f9c39d -OpenSSL.v3.5.4+0.x86_64-linux-gnu.tar.gz/md5/c3cf2b5c53332edd6755beabde9ec7ca -OpenSSL.v3.5.4+0.x86_64-linux-gnu.tar.gz/sha512/dab8ff0ca15785d8023a8e3b770d72761191fdf1f1f3525e4ddf10104c6a8905e089f6e888a24bf6717bc944f1ba498e4af68724d8af32393c147c59de309fbc -OpenSSL.v3.5.4+0.x86_64-linux-musl.tar.gz/md5/fa61e1bd29a34b58971224715929fe21 -OpenSSL.v3.5.4+0.x86_64-linux-musl.tar.gz/sha512/22d00cae28d3e63fac59518423cfbb76eb82bc18b72f42c89b60b37e346b19affabe01feb8c0b785b3cb88110356efb576ffe74ff5af00fc9c9f1669711e3faf -OpenSSL.v3.5.4+0.x86_64-unknown-freebsd.tar.gz/md5/ac3b835042008fe1229d5822b89a0ff2 -OpenSSL.v3.5.4+0.x86_64-unknown-freebsd.tar.gz/sha512/bf70b67488571b53bca8bb695da5206f401c759cb290b8007b0175bb262cff22d2145fc8e4690b7a1b819593a5de3a94beed6484fbbbf5a5ae03161ed2a866e9 -OpenSSL.v3.5.4+0.x86_64-w64-mingw32.tar.gz/md5/0ca1bc12a96a1b80217b780e4eda1d10 -OpenSSL.v3.5.4+0.x86_64-w64-mingw32.tar.gz/sha512/b9b98e9b1b1942b1141cb21166548a81cbd336c62ec335905fcf2aad536b16d90d68d160714a376dc70159e17063588893276b345d67833ccf5f28d2ccd32551 -openssl-3.5.4.tar.gz/md5/570a7ab371147b6ba72c6d0fed93131f -openssl-3.5.4.tar.gz/sha512/365aca6f2e59b5c8261fba683425d177874cf6024b0d216ca309112b879c1f4e8da78617e23c3c95d0b4a26b83ecd0d8348038b999d30e597d19f466c4761227 +OpenSSL.v3.5.5+0.aarch64-apple-darwin.tar.gz/md5/3e85d14e914bdfc2fcd5996fc9d0ca83 +OpenSSL.v3.5.5+0.aarch64-apple-darwin.tar.gz/sha512/ee55bd985dc963cdb800e467802c87ad77e98c20742d1814d8dd1734f7ead6659a8d4479aab11928d55ae107700d61b56028f3637a5da5d29939777b37b7fadf +OpenSSL.v3.5.5+0.aarch64-linux-gnu.tar.gz/md5/61365a7cefe1bb47a4e8580543c09251 +OpenSSL.v3.5.5+0.aarch64-linux-gnu.tar.gz/sha512/22d63e9914efc45837fade3d5c718292ceda91883a769012149b7ae3dd62bb429506cd2e1268ef9299aa1e2be7bad6a066252eed2b090949c741807eedfd06c4 +OpenSSL.v3.5.5+0.aarch64-linux-musl.tar.gz/md5/ca703b451cae0ce2dd3c604bb8581138 +OpenSSL.v3.5.5+0.aarch64-linux-musl.tar.gz/sha512/18cd00183197f590bf83f98160ff4b9d9ac6a6b3d1e24b120a99880a38420c983c2445415b48b223d067f32b132897e7ea0bea068f6db0338306436fdd641fd6 +OpenSSL.v3.5.5+0.aarch64-unknown-freebsd.tar.gz/md5/5326c283ba0147215fc510b7c5e136e4 +OpenSSL.v3.5.5+0.aarch64-unknown-freebsd.tar.gz/sha512/e1108f972c4ec61c364d5147473bb61d05a9489a6120eada5cd9832dca1b2fd255b9dbc52cf7220fd6ffda0d7b11bbf5be30fbee3cb57515339e00857d352dc5 +OpenSSL.v3.5.5+0.armv6l-linux-gnueabihf.tar.gz/md5/6577d25986630c6e35c58b966eb3a279 +OpenSSL.v3.5.5+0.armv6l-linux-gnueabihf.tar.gz/sha512/2c4bb52230cb7371122200f850d9acd29f354039fb3a5645d9307b4c3d3814a20c5a251c3e5e95fbd65916b1267ff5208baa78456a0f8b2f9fcdf85ea2b14842 +OpenSSL.v3.5.5+0.armv6l-linux-musleabihf.tar.gz/md5/5d9a74129a58ce60f50c72f89f88e310 +OpenSSL.v3.5.5+0.armv6l-linux-musleabihf.tar.gz/sha512/cad21ef05ae92d09733702ff3386b76270ad73e3a17ea1924ced424ebc2ea03a693233dea714cb73c7692d4c5bce620310da1e648cc9d48908cbd6659f979815 +OpenSSL.v3.5.5+0.armv7l-linux-gnueabihf.tar.gz/md5/1e59ac71e2116ad1094631b155986b08 +OpenSSL.v3.5.5+0.armv7l-linux-gnueabihf.tar.gz/sha512/46cbc560c5133f04b8cf22cf90f12721fe5f362caf204cda9cbc16f31afe09f709b60c5fd44e3f8183a87cea872530121367de45fccce6b1e0a44b25ba2a4bee +OpenSSL.v3.5.5+0.armv7l-linux-musleabihf.tar.gz/md5/05514d5cb8d72eb9243c0fee476bd0e4 +OpenSSL.v3.5.5+0.armv7l-linux-musleabihf.tar.gz/sha512/a9cbd1e998a474b07b1b4063a5d18ce94ab7e85efda8252e90c19d155c052d163ecac668193a989e074fd30d76a0556640ed1d44e8a10b15db185bd6997c3852 +OpenSSL.v3.5.5+0.i686-linux-gnu.tar.gz/md5/8cb0fffc358ba235e414ebbd4f1b55e9 +OpenSSL.v3.5.5+0.i686-linux-gnu.tar.gz/sha512/497f932b7eca620879e23566a5365a79f5ae07156443d75600bdc37a0b30389940a58ddc970d001c6975f33c7e8a8306a33a9d57e79c481b39c7663ab201dc49 +OpenSSL.v3.5.5+0.i686-linux-musl.tar.gz/md5/5d85b8d8444d3806a98592b368c6f634 +OpenSSL.v3.5.5+0.i686-linux-musl.tar.gz/sha512/73bb41adc4c9ade661fe5c3c46427d3a8f2dfdda4e03bfae8327841cafcbfc7fa0d43d3861d31ac3e4665cb2d649ea63b5ad689e5dc333b2a506431e30a2d848 +OpenSSL.v3.5.5+0.i686-w64-mingw32.tar.gz/md5/2348e844002ec92d3aaa2f64b3e38afe +OpenSSL.v3.5.5+0.i686-w64-mingw32.tar.gz/sha512/22d8751fc260ffe5ae791da693397c18a5a04bfe6ff02f393c21d61a32f1cbe9e2ebd4b24e47bb8d1268c2488a5b3b2376a167533f17f30914643b9d5eb83a33 +OpenSSL.v3.5.5+0.powerpc64le-linux-gnu.tar.gz/md5/d7c6857200115cdce55879e7c6290949 +OpenSSL.v3.5.5+0.powerpc64le-linux-gnu.tar.gz/sha512/5765d169b5cae5c289a5e99d98b453a1dab14290d9b63569ffcc23831011e12dc4a07fdbe706c7c24a152bd22f50da7b9a2c0b1f7517f768ff73ac3e272f1538 +OpenSSL.v3.5.5+0.riscv64-linux-gnu.tar.gz/md5/847aa34e773a665bcd23aeb36bdd8b87 +OpenSSL.v3.5.5+0.riscv64-linux-gnu.tar.gz/sha512/18f07ae414459ad60735413a5a1d478ab17db4701e837145fe527f8dfd6b784e94a531761f033f729e7802e9da4d66b04376c09edb0bdbf318f313afb1f51255 +OpenSSL.v3.5.5+0.x86_64-apple-darwin.tar.gz/md5/e5128cf634e5be415682ebda7e9554f1 +OpenSSL.v3.5.5+0.x86_64-apple-darwin.tar.gz/sha512/e9160a54fa5630f3a0a8a8903f936e5c17bea46f4461c76100724ff69771bd0f0b5049ea85c5f14e64b712780968b2d891332f6a7be7b071fdcf1fd9a01b4514 +OpenSSL.v3.5.5+0.x86_64-linux-gnu.tar.gz/md5/2a7426c4b3ef4465a8d693e2015c41e2 +OpenSSL.v3.5.5+0.x86_64-linux-gnu.tar.gz/sha512/b44f5f83790488becdd2facefa6733d563512e7bb2d8577fbf96b9e7cd15fd1435673132426f3cf622c6dcc13b1f5446f425cc469ba58370fc61e44c5f2a7c64 +OpenSSL.v3.5.5+0.x86_64-linux-musl.tar.gz/md5/bc9665bd295312d0fa61dbb73f235c0b +OpenSSL.v3.5.5+0.x86_64-linux-musl.tar.gz/sha512/567305a42092e315c23d7861ebf0a7ec4e82d1ced148473efa7604e4edbd0a5356fa9fcde1f114c71c7ffc5931576b3666310b3323901a4b342ede638d3a70fd +OpenSSL.v3.5.5+0.x86_64-unknown-freebsd.tar.gz/md5/e34e24575c54e27b48ed7f9b6b850961 +OpenSSL.v3.5.5+0.x86_64-unknown-freebsd.tar.gz/sha512/b9e9e55f6efe24a2982018d2419ce710059330cc2963c0ebe141b140b6321fddc61c492ad4b107c63ac78ca88f1223cf9ff3206de13d6c3001defc5f0ad3e115 +OpenSSL.v3.5.5+0.x86_64-w64-mingw32.tar.gz/md5/4d92cbff78e60e4ada0ad817b02f9c7d +OpenSSL.v3.5.5+0.x86_64-w64-mingw32.tar.gz/sha512/c4d4f250ef874229475e505b21ad51160e30cdaf1744d80dc3e4e7d68f2d7ae11a91a8c5e87c3300c89d98324c73968a18f01e2e8fd3c55467e97d5d2099c94b +openssl-3.5.5.tar.gz/md5/9c86d929c3d1067e2c88239d7d1ce81b +openssl-3.5.5.tar.gz/sha512/7cf0eb91bac175f7fe0adcafef457790d43fe7f98e2d4bef681c2fd5ca365e1fa5b562c645a60ab602365adedf9d91c074624eea66d3d7e155639fc50d5861ec diff --git a/deps/openssl.version b/deps/openssl.version index a5239226ef862..2770afb6abf63 100644 --- a/deps/openssl.version +++ b/deps/openssl.version @@ -3,4 +3,4 @@ OPENSSL_JLL_NAME := OpenSSL ## source build -OPENSSL_VER := 3.5.4 +OPENSSL_VER := 3.5.5 diff --git a/stdlib/OpenSSL_jll/Project.toml b/stdlib/OpenSSL_jll/Project.toml index ac024da2f9a02..5af0f93cfd89a 100644 --- a/stdlib/OpenSSL_jll/Project.toml +++ b/stdlib/OpenSSL_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenSSL_jll" uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "3.5.4+0" +version = "3.5.5+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/OpenSSL_jll/test/runtests.jl b/stdlib/OpenSSL_jll/test/runtests.jl index 6c4cfc1184b87..19609014140d1 100644 --- a/stdlib/OpenSSL_jll/test/runtests.jl +++ b/stdlib/OpenSSL_jll/test/runtests.jl @@ -6,5 +6,5 @@ using Test, Libdl, OpenSSL_jll major = ccall((:OPENSSL_version_major, libcrypto), Cuint, ()) minor = ccall((:OPENSSL_version_minor, libcrypto), Cuint, ()) patch = ccall((:OPENSSL_version_patch, libcrypto), Cuint, ()) - @test VersionNumber(major, minor, patch) == v"3.5.4" + @test VersionNumber(major, minor, patch) == v"3.5.5" end From 4b9d0fda6f0f9171686eac19408b27b9d5ccb051 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Sun, 1 Feb 2026 16:30:02 -0500 Subject: [PATCH 34/34] Artifacts stdlib: Add `TOML` and `Pkg` as test dependencies (#60891) Because `TOML` is used in the tests: https://github.com/JuliaLang/julia/blob/b51d41ac753f46a3529f47fe3c6638895cf97c6d/stdlib/Artifacts/test/runtests.jl#L6-L6 Noticed in PkgEval ([log](https://s3.amazonaws.com/julialang-reports/nanosoldier/pkgeval/by_hash/a6a3237_vs_63406df/Artifacts.primary.log)) (cherry picked from commit ed71c106d23a8cfa0be3b8af0cb7ddb34e18b79d) --- stdlib/Artifacts/Project.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/Artifacts/Project.toml b/stdlib/Artifacts/Project.toml index c4e5cc031375c..217617a1e28b5 100644 --- a/stdlib/Artifacts/Project.toml +++ b/stdlib/Artifacts/Project.toml @@ -3,7 +3,9 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" version = "1.11.0" [extras] +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Test", "Pkg", "TOML"]