From b65a9cc801ff4f836f2b250da548cfb732d0410e Mon Sep 17 00:00:00 2001 From: Michael Persico Date: Thu, 9 Jan 2025 21:24:04 -0500 Subject: [PATCH 01/18] Fix devcontainer definition (#57006) (cherry picked from commit b80dd58346a9644d18c52d1cf0e949c62d9e281b) --- .devcontainer/Dockerfile | 3 --- .devcontainer/devcontainer.json | 16 ++++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index a688be130711c..0000000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM julia:latest - -RUN apt-get update && apt-get install -y build-essential libatomic1 python gfortran perl wget m4 cmake pkg-config git diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a3747ca019694..455f8bea3e952 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,12 @@ { - "extensions": [ - "julialang.language-julia", - "ms-vscode.cpptools" - ], - - "dockerFile": "Dockerfile" + "image": "docker.io/library/julia:latest", + "customizations": { + "vscode": { + "extensions": [ + "julialang.language-julia", + "ms-vscode.cpptools" + ] + } + }, + "onCreateCommand": "apt-get update && apt-get install -y build-essential libatomic1 python3 gfortran perl wget m4 cmake pkg-config git" } From 078105dfd3b70b255fa71d903abae79d88b2f279 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 15 Sep 2025 20:33:37 -0400 Subject: [PATCH 02/18] codegen: mark write barrier field load as volatile (#59559) This is as an alternative to changing all allocation functions to mutating all memory and returning an aliasing pointer. This operates usually late in the pipeline, so either should not make much difference, but I think it should suffice to mark this volatile to prevent any de-duplication of this load, and this should also be most conservative for GC but more liberal for other optimizations. Fixes #59547 Produced with dubious help by Claude. (cherry picked from commit 218f691d16edbda33647d2b938b882a7ac08f057) --- test/llvmpasses/gc-writebarrier-volatile.ll | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/llvmpasses/gc-writebarrier-volatile.ll diff --git a/test/llvmpasses/gc-writebarrier-volatile.ll b/test/llvmpasses/gc-writebarrier-volatile.ll new file mode 100644 index 0000000000000..c4bfafdb670f8 --- /dev/null +++ b/test/llvmpasses/gc-writebarrier-volatile.ll @@ -0,0 +1,41 @@ +; This file is a part of Julia. License is MIT: https://julialang.org/license + +; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame,FinalLowerGC,gvn)' -S %s | FileCheck %s + +; Test for issue #59547: Ensure write barrier GC tag loads are volatile +; This test verifies that the LateLowerGCFrame pass marks GC tag loads as volatile +; to prevent GVN from incorrectly constant-folding them, which would eliminate +; necessary write barrier checks. + +@tag = external addrspace(10) global {}, align 16 + +declare void @julia.write_barrier({} addrspace(10)*, {} addrspace(10)*) +declare {}*** @julia.get_pgcstack() +declare {} addrspace(10)* @julia.gc_alloc_obj({}**, i64, {} addrspace(10)*) + +; Test that write barrier expansion produces volatile GC tag loads +; CHECK-LABEL: @test_writebarrier_volatile_tags +define {} addrspace(10)* @test_writebarrier_volatile_tags() { +top: + %pgcstack = call {}*** @julia.get_pgcstack() + %current_task = bitcast {}*** %pgcstack to {}** + %parent = call {} addrspace(10)* @julia.gc_alloc_obj({}** %current_task, i64 8, {} addrspace(10)* @tag) + %child = call {} addrspace(10)* @julia.gc_alloc_obj({}** %current_task, i64 8, {} addrspace(10)* @tag) + call void @julia.write_barrier({} addrspace(10)* %parent, {} addrspace(10)* %child) + ret {} addrspace(10)* %parent + +; The critical test: GC tag loads must be volatile to prevent constant folding +; CHECK: load atomic volatile i64, ptr {{.*}} unordered, align 8, {{.*}}!tbaa +; CHECK: and i64 {{.*}}, 3 +; CHECK: icmp eq i64 {{.*}}, 3 +; CHECK: br i1 {{.*}}, label %may_trigger_wb, label + +; CHECK: may_trigger_wb: +; CHECK: load atomic volatile i64, ptr {{.*}} unordered, align 8, {{.*}}!tbaa +; CHECK: and i64 {{.*}}, 1 +; CHECK: icmp eq i64 {{.*}}, 0 +; CHECK: br i1 {{.*}}, label %trigger_wb, label + +; CHECK: trigger_wb: +; CHECK: call void @ijl_gc_queue_root(ptr {{.*}}) +} From 85886aa4a4e191aba1966b59e51298906937f577 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Mon, 22 Sep 2025 14:33:31 -0400 Subject: [PATCH 03/18] Remove GPL libraries from the Julia build for binary-dist target (#59627) Currently we support removing GPL dependencies in the full source build. This will also remove the GPL dependencies from the binary-dist target when built with JLLs. I almost feel like it would be simpler to have a new SuiteSparse_NOGPL_jll package. Then in the default build, things stay as they are. In the no gpl build use the new JLL. In the no GPL build, if someone then tries to use a GPL SuiteSparse library, a warning can be printed asking them to get a different build of Julia. @DilumAluthge @andreasnoack @giordano Thoughts? Co-authored-by: Viral B. Shah (cherry picked from commit 441ebf958477aad68158b7d600c30278b2644d8c) --- stdlib/Makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index d478d2ad4c188..5a67f581f709e 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -15,6 +15,8 @@ include $(JULIAHOME)/deps/*.version VERSDIR := v$(shell cut -d. -f1-2 < $(JULIAHOME)/VERSION) DIRS := $(build_datarootdir)/julia/stdlib/$(VERSDIR) $(build_prefix)/manifest/$(VERSDIR) +LIBDIR := $(build_datarootdir)/lib/julia + $(foreach dir,$(DIRS),$(eval $(call dir_target,$(dir)))) JLLS = DSFMT GMP CURL LIBGIT2 LLVM LIBSSH2 LIBUV MBEDTLS MPFR NGHTTP2 \ @@ -61,8 +63,19 @@ $(foreach module, $(STDLIBS), $(eval $(call symlink_target,$$(JULIAHOME)/stdlib/ STDLIBS_LINK_TARGETS := $(addprefix $(build_datarootdir)/julia/stdlib/$(VERSDIR)/,$(STDLIBS)) +remove-gpl-libs: +ifeq ($(USE_GPL_LIBS),0) + @echo Removing GPL libs... + -rm -f $(LIBDIR)/libcholmod* + -rm -f $(LIBDIR)/libklu_cholmod* + -rm -f $(LIBDIR)/librbio* + -rm -f $(LIBDIR)/libspqr* + -rm -f $(LIBDIR)/libumfpack* +endif + getall get: $(addprefix get-, $(STDLIBS_EXT) $(JLL_NAMES)) -install: version-check $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS) + +install: version-check $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS) remove-gpl-libs version-check: $(addprefix version-check-, $(STDLIBS_EXT)) uninstall: $(addprefix uninstall-, $(STDLIBS_EXT)) extstdlibclean: From 546c7121ed7f48674290a7bb9813712df74a7fbf Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Sat, 4 Oct 2025 17:29:53 -0400 Subject: [PATCH 04/18] also redirect JL_STDERR etc. when redirecting to devnull (#55958) (cherry picked from commit bcbe9fe969eaddc3231e06b7169f6b5946a28a18) --- base/stream.jl | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/base/stream.jl b/base/stream.jl index a31469af27e53..2435c3b1b186c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1249,7 +1249,15 @@ function _redirect_io_libc(stream, unix_fd::Int) -10 - unix_fd, Libc._get_osfhandle(posix_fd)) end end - dup(posix_fd, RawFD(unix_fd)) + GC.@preserve stream dup(posix_fd, RawFD(unix_fd)) + nothing +end +function _redirect_io_cglobal(handle::Union{LibuvStream, IOStream, Nothing}, unix_fd::Int) + c_sym = unix_fd == 0 ? cglobal(:jl_uv_stdin, Ptr{Cvoid}) : + unix_fd == 1 ? cglobal(:jl_uv_stdout, Ptr{Cvoid}) : + unix_fd == 2 ? cglobal(:jl_uv_stderr, Ptr{Cvoid}) : + C_NULL + c_sym == C_NULL || unsafe_store!(c_sym, handle === nothing ? Ptr{Cvoid}(unix_fd) : handle.handle) nothing end function _redirect_io_global(io, unix_fd::Int) @@ -1260,11 +1268,7 @@ function _redirect_io_global(io, unix_fd::Int) end function (f::RedirectStdStream)(handle::Union{LibuvStream, IOStream}) _redirect_io_libc(handle, f.unix_fd) - c_sym = f.unix_fd == 0 ? cglobal(:jl_uv_stdin, Ptr{Cvoid}) : - f.unix_fd == 1 ? cglobal(:jl_uv_stdout, Ptr{Cvoid}) : - f.unix_fd == 2 ? cglobal(:jl_uv_stderr, Ptr{Cvoid}) : - C_NULL - c_sym == C_NULL || unsafe_store!(c_sym, handle.handle) + _redirect_io_cglobal(handle, f.unix_fd) _redirect_io_global(handle, f.unix_fd) return handle end @@ -1273,6 +1277,7 @@ function (f::RedirectStdStream)(::DevNull) handle = open(nulldev, write=f.writable) _redirect_io_libc(handle, f.unix_fd) close(handle) # handle has been dup'ed in _redirect_io_libc + _redirect_io_cglobal(nothing, f.unix_fd) _redirect_io_global(devnull, f.unix_fd) return devnull end From f12b9f6b036c0f11bb3f026cef0b01251a5674f7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Oct 2025 17:08:38 -0400 Subject: [PATCH 05/18] [REPL] Do not corrupt input when using numbered_prompt! mode (#59730) Fix the unbounded possible corruption of the user input by reverting to a non-scoped begin instead of let. ```julia julia> ex = Base.remove_linenums!(:(using A; using B; using C)); REPL.Numbered.get_usings!([], ex) 2-element Vector{Any}: :(using A) :(using C) julia> ex quote using B end ``` (cherry picked from commit 05c07e18c3ef2226bc81cb8f22cd1dc2df1defc3) --- stdlib/REPL/src/REPL.jl | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index cb91d38d0cadd..0442002a4b508 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1690,25 +1690,10 @@ function repl_eval_counter(hp) end function out_transform(@nospecialize(x), n::Ref{Int}) - return Expr(:toplevel, get_usings!([], x)..., quote - let __temp_val_a72df459 = $x - $capture_result($n, __temp_val_a72df459) - __temp_val_a72df459 - end - end) -end - -function get_usings!(usings, ex) - ex isa Expr || return usings - # get all `using` and `import` statements which are at the top level - for (i, arg) in enumerate(ex.args) - if Base.isexpr(arg, :toplevel) - get_usings!(usings, arg) - elseif Base.isexpr(arg, [:using, :import]) - push!(usings, popat!(ex.args, i)) - end - end - return usings + return Expr(:block, # avoid line numbers or scope that would leak into the output and change the meaning of x + :(local __temp_val_a72df459 = $x), + Expr(:call, capture_result, n, :__temp_val_a72df459), + :__temp_val_a72df459) end function capture_result(n::Ref{Int}, @nospecialize(x)) From 8dd1e2db1e11e73d0d9a841cc9850d417179534d Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Tue, 7 Oct 2025 09:11:05 -0400 Subject: [PATCH 06/18] Revert "Restrict COFF to a single thread when symbol count is high (#50874)" (#59736) This reverts commit eb4416b16b8a865376da5c76451a4d60516e2c4a. As of LLVM 16, we automatically emit: ``` .drectve `-exclude-symbols:""` ``` which mitigates this issue where it is supported by the linker (GCC 11+ and LLD 14+ are tested working) PackageCompiler on Windows now ships GCC 14 (https://github.com/JuliaLang/PackageCompiler.jl/pull/1012), so we should no longer need this workaround that can make a 15-minute sysimage compilation take an hour+ (cherry picked from commit 1cba9c292c6bad490cca49cd52e333632a3fab91) --- src/aotcompile.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 94fe3e65c4d6e..2755ffcb2cf48 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -715,7 +715,6 @@ static FunctionInfo getFunctionWeight(const Function &F) } struct ModuleInfo { - Triple triple; size_t globals; size_t funcs; size_t bbs; @@ -726,7 +725,6 @@ struct ModuleInfo { ModuleInfo compute_module_info(Module &M) { ModuleInfo info; - info.triple = Triple(M.getTargetTriple()); info.globals = 0; info.funcs = 0; info.bbs = 0; @@ -1519,12 +1517,6 @@ static unsigned compute_image_thread_count(const ModuleInfo &info) { #endif if (jl_is_timing_passes) // LLVM isn't thread safe when timing the passes https://github.com/llvm/llvm-project/issues/44417 return 1; - // COFF has limits on external symbols (even hidden) up to 65536. We reserve the last few - // for any of our other symbols that we insert during compilation. - if (info.triple.isOSBinFormatCOFF() && info.globals > 64000) { - LLVM_DEBUG(dbgs() << "COFF is restricted to a single thread for large images\n"); - return 1; - } // This is not overridable because empty modules do occasionally appear, but they'll be very small and thus exit early to // known easy behavior. Plus they really don't warrant multiple threads if (info.weight < 1000) { From d27fc6078f72de06931b0b2390c6f127d61b6451 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Thu, 13 Nov 2025 15:39:29 +0100 Subject: [PATCH 07/18] Fix removal of GPL libs (#60100) `$(build_datarootdir)/lib/julia` doesn't exist, libraries are in `$(build_private_libdir)`. See https://github.com/JuliaLang/julia/pull/59627/files#r2510807584. (cherry picked from commit bf7e52b42efc64ebad5c1b89e5d6b26814cdcf74) --- stdlib/Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 5a67f581f709e..8705f8438bd0f 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -15,7 +15,6 @@ include $(JULIAHOME)/deps/*.version VERSDIR := v$(shell cut -d. -f1-2 < $(JULIAHOME)/VERSION) DIRS := $(build_datarootdir)/julia/stdlib/$(VERSDIR) $(build_prefix)/manifest/$(VERSDIR) -LIBDIR := $(build_datarootdir)/lib/julia $(foreach dir,$(DIRS),$(eval $(call dir_target,$(dir)))) @@ -66,11 +65,11 @@ STDLIBS_LINK_TARGETS := $(addprefix $(build_datarootdir)/julia/stdlib/$(VERSDIR) remove-gpl-libs: ifeq ($(USE_GPL_LIBS),0) @echo Removing GPL libs... - -rm -f $(LIBDIR)/libcholmod* - -rm -f $(LIBDIR)/libklu_cholmod* - -rm -f $(LIBDIR)/librbio* - -rm -f $(LIBDIR)/libspqr* - -rm -f $(LIBDIR)/libumfpack* + -rm -f $(build_private_libdir)/libcholmod* + -rm -f $(build_private_libdir)/libklu_cholmod* + -rm -f $(build_private_libdir)/librbio* + -rm -f $(build_private_libdir)/libspqr* + -rm -f $(build_private_libdir)/libumfpack* endif getall get: $(addprefix get-, $(STDLIBS_EXT) $(JLL_NAMES)) From 6109d8c8d7145f0d5e60ef1e86403b4e861d7dbd Mon Sep 17 00:00:00 2001 From: deroulers Date: Thu, 13 Nov 2025 17:56:33 +0100 Subject: [PATCH 08/18] Remove precompile-time tempfiles from TEMP_CLEANUP (#60106) When starting julia, `Base.Filesystem.TEMP_CLEANUP` should be empty, but is being left with these two files. The proposed fix is to set up temporary files created by function `generate_precompile_statements` in `contrib/generate_precompile.jl` to have no automatic cleanup. This won't do harm since they will be removed by the cleanup of the temporary directory created by the call to `mktempdir` in function `generate_precompile_statements` (see the call `rm(tmpdir, recursive=true)` in `base/file.jl`). These should be removed by the atexit hook, but we didn't run `Base.__init__` or `Base.Filesystem.__postinit__` hooks to re-register this cleanup handler in the sys.so generation process (only in sysbase.so). To test this issue, one can do: `$ mkdir $TMPDIR/JuliaBuild` `$ OLDTMPDIR=$TMPDIR` `$ export TMPDIR=$TMPDIR/JuliaBuild` `$ cd ` `$ ` `$ strings usr/lib/julia/sys.dylib|less # shows that the temp. dir. JuliaBuild is hardcoded in the binaries` `$ TMPDIR=$OLDTMPDIR` `$ chmod u-x $TMPDIR/JuliaBuild` `$ # should try to use $TMPDIR/JuliaBuild which is now inaccessible` Without the fix, the last step triggers the infinite loop of ``Failed to clean up temporary path''. With the fix, one can see that the binaries (`usr/lib/julia/sys.dylib`) do not contain the temp. dir. anymore, and the infinite loop of errors is not triggered. Or simply by observing that `./julia -E 'Base.Filesystem.TEMP_CLEANUP'` is not empty. Fix #60078 (cherry picked from commit 1eea4b63334013aa1f2347b45c1a0772f108bdb0) --- contrib/generate_precompile.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 43b6f89712d2b..2fcbf905b05b5 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -315,8 +315,8 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe uuid = "$pkguuid" """) touch(joinpath(pkgpath, "Manifest.toml")) - tmp_prec = tempname(prec_path) - tmp_proc = tempname(prec_path) + tmp_prec = tempname(prec_path; cleanup=false) + tmp_proc = tempname(prec_path; cleanup=false) s = """ pushfirst!(DEPOT_PATH, $(repr(joinpath(prec_path,"depot")))); Base.PRECOMPILE_TRACE_COMPILE[] = $(repr(tmp_prec)); From 62544df111ca0f3f45758c6120c750c39db6ceb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= <765740+giordano@users.noreply.github.com> Date: Sat, 29 Nov 2025 08:00:21 +0000 Subject: [PATCH 09/18] Correct version in which at-lock was exported (#60279) It was exported in v1.7, not v1.10: #39588 (cherry picked from commit 1067db80b96cafb9da6864afbfdd9d6e27665c33) --- base/lock.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/lock.jl b/base/lock.jl index 1d63e51f08b15..9335c3dbad2f1 100644 --- a/base/lock.jl +++ b/base/lock.jl @@ -263,7 +263,7 @@ This is similar to using [`lock`](@ref) with a `do` block, but avoids creating a and thus can improve the performance. !!! compat - `@lock` was added in Julia 1.3, and exported in Julia 1.10. + `@lock` was added in Julia 1.3, and exported in Julia 1.7. """ macro lock(l, expr) quote From 67643b7eb57a1b002d330b20a4df93b7ff2e4d77 Mon Sep 17 00:00:00 2001 From: Eddie Groshev Date: Tue, 9 Dec 2025 23:33:24 -0800 Subject: [PATCH 10/18] Logging: define isless between Integer and LogLevel (#60330) (cherry picked from commit 5ee081631674166af22f3677d50c2fd56a2ccf48) --- base/logging/logging.jl | 2 ++ stdlib/Logging/test/runtests.jl | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/base/logging/logging.jl b/base/logging/logging.jl index cf0c89b46f07f..5149aa69ed1f3 100644 --- a/base/logging/logging.jl +++ b/base/logging/logging.jl @@ -129,6 +129,8 @@ end LogLevel(level::LogLevel) = level isless(a::LogLevel, b::LogLevel) = isless(a.level, b.level) +isless(a::LogLevel, b::Integer) = isless(a.level, b) +isless(a::Integer, b::LogLevel) = isless(a, b.level) +(level::LogLevel, inc::Integer) = LogLevel(level.level+inc) -(level::LogLevel, inc::Integer) = LogLevel(level.level-inc) convert(::Type{LogLevel}, level::Integer) = LogLevel(level) diff --git a/stdlib/Logging/test/runtests.jl b/stdlib/Logging/test/runtests.jl index 7250fc62d058e..b27ca0439b806 100644 --- a/stdlib/Logging/test/runtests.jl +++ b/stdlib/Logging/test/runtests.jl @@ -19,6 +19,13 @@ macro customlog(exs...) Base.CoreLogging.logmsg_code((Base.CoreLogging.@_sourcei @test :handle_message in names(Logging, all=true) # non-exported public function end +@testset "LogLevel compatibility with integers" begin + @test Logging.Debug + 1000 == Logging.Info + @test Logging.Warn - 1000 == Logging.Info + @test Logging.Info < 500 + @test 500 < Logging.Warn +end + @testset "ConsoleLogger" begin # First pass log limiting @test min_enabled_level(ConsoleLogger(devnull, Logging.Debug)) == Logging.Debug From 47abd3557aac0c1d6cfc8fea814ea61b3486c349 Mon Sep 17 00:00:00 2001 From: William Moses Date: Wed, 14 Jan 2026 16:53:44 -0600 Subject: [PATCH 11/18] 1.11: add getter for global variable pointer matching jlvalue (#60684) --- src/aotcompile.cpp | 9 +++++++++ src/codegen-stubs.c | 1 + src/jl_exported_funcs.inc | 1 + src/julia_internal.h | 1 + 4 files changed, 12 insertions(+) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 2755ffcb2cf48..ffb5d528ae704 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -115,6 +115,15 @@ void jl_get_llvm_gvs_impl(void *native_code, arraylist_t *gvs) memcpy(gvs->items, data->jl_value_to_llvm.data(), gvs->len * sizeof(void*)); } +extern "C" JL_DLLEXPORT_CODEGEN +void jl_get_llvm_gvs_globals_impl(void *native_code, arraylist_t *gvs) +{ + // map a memory location (jl_value_t or jl_binding_t) to a GlobalVariable + jl_native_code_desc_t *data = (jl_native_code_desc_t*)native_code; + arraylist_grow(gvs, data->jl_sysimg_gvars.size()); + memcpy(gvs->items, data->jl_sysimg_gvars.data(), gvs->len * sizeof(void*)); +} + extern "C" JL_DLLEXPORT_CODEGEN void jl_get_llvm_external_fns_impl(void *native_code, arraylist_t *external_fns) { diff --git a/src/codegen-stubs.c b/src/codegen-stubs.c index e81c66a8d5d44..7dfe469e8dff4 100644 --- a/src/codegen-stubs.c +++ b/src/codegen-stubs.c @@ -14,6 +14,7 @@ JL_DLLEXPORT void jl_dump_native_fallback(void *native_code, const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *asm_fname, ios_t *z, ios_t *s) UNAVAILABLE JL_DLLEXPORT void jl_get_llvm_gvs_fallback(void *native_code, arraylist_t *gvs) UNAVAILABLE +JL_DLLEXPORT void jl_get_llvm_gvs_globals_fallback(void *native_code, arraylist_t *gvs) UNAVAILABLE JL_DLLEXPORT void jl_get_llvm_external_fns_fallback(void *native_code, arraylist_t *gvs) UNAVAILABLE JL_DLLEXPORT void jl_extern_c_fallback(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index e5a4f55a069ee..442720c784623 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -531,6 +531,7 @@ YY(jl_get_LLVM_VERSION) \ YY(jl_dump_native) \ YY(jl_get_llvm_gvs) \ + YY(jl_get_llvm_gvs_globals) \ YY(jl_get_llvm_external_fns) \ YY(jl_dump_function_asm) \ YY(jl_LLVMCreateDisasm) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index dff769e7e0f66..7ba1b6e7e8b63 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1738,6 +1738,7 @@ JL_DLLIMPORT void jl_dump_native(void *native_code, const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *asm_fname, ios_t *z, ios_t *s, jl_emission_params_t *params); JL_DLLIMPORT void jl_get_llvm_gvs(void *native_code, arraylist_t *gvs); +JL_DLLIMPORT void jl_get_llvm_gvs_globals(void *native_code, arraylist_t *gvs); JL_DLLIMPORT void jl_get_llvm_external_fns(void *native_code, arraylist_t *gvs); JL_DLLIMPORT void jl_get_function_id(void *native_code, jl_code_instance_t *ncode, int32_t *func_idx, int32_t *specfunc_idx); From 4b23da6286def305664ff31b6f186efd48b9418d Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Fri, 16 Jan 2026 15:17:17 -0500 Subject: [PATCH 12/18] Drop test `test/llvmpasses/gc-writebarrier-volatile.ll` This removes the test file `test/llvmpasses/gc-writebarrier-volatile.ll`, which is an llvmpasses test that was added in PR https://github.com/JuliaLang/julia/pull/59559. PR https://github.com/JuliaLang/julia/pull/59559 (commit https://github.com/JuliaLang/julia/commit/218f691d16edbda33647d2b938b882a7ac08f057) is being backported to Julia 1.11 in commit https://github.com/JuliaLang/julia/pull/60692/commits/078105dfd3b70b255fa71d903abae79d88b2f279. The test doesn't work on Julia 1.11, because Julia 1.11 uses an older LLVM version than Julia master. Therefore, this commit drops the test. The remainder of the backport commit (https://github.com/JuliaLang/julia/pull/60692/commits/078105dfd3b70b255fa71d903abae79d88b2f279) is left unmodified. --- test/llvmpasses/gc-writebarrier-volatile.ll | 41 --------------------- 1 file changed, 41 deletions(-) delete mode 100644 test/llvmpasses/gc-writebarrier-volatile.ll diff --git a/test/llvmpasses/gc-writebarrier-volatile.ll b/test/llvmpasses/gc-writebarrier-volatile.ll deleted file mode 100644 index c4bfafdb670f8..0000000000000 --- a/test/llvmpasses/gc-writebarrier-volatile.ll +++ /dev/null @@ -1,41 +0,0 @@ -; This file is a part of Julia. License is MIT: https://julialang.org/license - -; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame,FinalLowerGC,gvn)' -S %s | FileCheck %s - -; Test for issue #59547: Ensure write barrier GC tag loads are volatile -; This test verifies that the LateLowerGCFrame pass marks GC tag loads as volatile -; to prevent GVN from incorrectly constant-folding them, which would eliminate -; necessary write barrier checks. - -@tag = external addrspace(10) global {}, align 16 - -declare void @julia.write_barrier({} addrspace(10)*, {} addrspace(10)*) -declare {}*** @julia.get_pgcstack() -declare {} addrspace(10)* @julia.gc_alloc_obj({}**, i64, {} addrspace(10)*) - -; Test that write barrier expansion produces volatile GC tag loads -; CHECK-LABEL: @test_writebarrier_volatile_tags -define {} addrspace(10)* @test_writebarrier_volatile_tags() { -top: - %pgcstack = call {}*** @julia.get_pgcstack() - %current_task = bitcast {}*** %pgcstack to {}** - %parent = call {} addrspace(10)* @julia.gc_alloc_obj({}** %current_task, i64 8, {} addrspace(10)* @tag) - %child = call {} addrspace(10)* @julia.gc_alloc_obj({}** %current_task, i64 8, {} addrspace(10)* @tag) - call void @julia.write_barrier({} addrspace(10)* %parent, {} addrspace(10)* %child) - ret {} addrspace(10)* %parent - -; The critical test: GC tag loads must be volatile to prevent constant folding -; CHECK: load atomic volatile i64, ptr {{.*}} unordered, align 8, {{.*}}!tbaa -; CHECK: and i64 {{.*}}, 3 -; CHECK: icmp eq i64 {{.*}}, 3 -; CHECK: br i1 {{.*}}, label %may_trigger_wb, label - -; CHECK: may_trigger_wb: -; CHECK: load atomic volatile i64, ptr {{.*}} unordered, align 8, {{.*}}!tbaa -; CHECK: and i64 {{.*}}, 1 -; CHECK: icmp eq i64 {{.*}}, 0 -; CHECK: br i1 {{.*}}, label %trigger_wb, label - -; CHECK: trigger_wb: -; CHECK: call void @ijl_gc_queue_root(ptr {{.*}}) -} From 35bec7e4537b3a145195659d89727196f21afd97 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Fri, 16 Jan 2026 15:26:08 -0500 Subject: [PATCH 13/18] CI: Update external GitHub Actions, and pin all external actions to a full-length commit hash --- .github/workflows/LabelCheck.yml | 2 +- .github/workflows/Typos.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/LabelCheck.yml b/.github/workflows/LabelCheck.yml index 194b0c92065c9..84bdb74150e6c 100644 --- a/.github/workflows/LabelCheck.yml +++ b/.github/workflows/LabelCheck.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 2 steps: - - uses: yogevbd/enforce-label-action@2.2.2 + - uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2 with: # REQUIRED_LABELS_ANY: "bug,enhancement,skip-changelog" # REQUIRED_LABELS_ANY_DESCRIPTION: "Select at least one label ['bug','enhancement','skip-changelog']" diff --git a/.github/workflows/Typos.yml b/.github/workflows/Typos.yml index da5a6a550abe8..67a05f23ef58d 100644 --- a/.github/workflows/Typos.yml +++ b/.github/workflows/Typos.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 5 steps: - name: Checkout the JuliaLang/julia repository - uses: actions/checkout@v4 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Check spelling with typos From 29b3528ccea64ce7f978089e4411bdcadf955128 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 15 Jan 2026 00:23:55 -0500 Subject: [PATCH 14/18] 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 0934f83e20a88..46e16e8795672 100644 --- a/src/task.c +++ b/src/task.c @@ -227,10 +227,6 @@ static void NOINLINE save_stack(jl_ptls_t ptls, jl_task_t *lastt, jl_task_t **pt lastt->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_task_t *t, jl_ptls_t ptls, char *p) @@ -493,6 +489,12 @@ JL_NO_ASAN static void ctx_switch(jl_task_t *lastt) #endif *pt = NULL; // can't fail after here: clear the gc-root for the target task now } + // 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 a36ed76324a015ac73a011af2ab4a7c9dd7ea9f0 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 20 Jan 2026 19:20:15 +0100 Subject: [PATCH 15/18] [1.11] Backport #60718+#60746: Fix and test `jl_method_lookup_by_tt` (#60750) I'm only backporting this because I know we're doing another 1.11 release anyway. This fixes bugs with GPUCompiler.jl that would otherwise require expensive workarounds for every GPU kernel launch. --- src/gf.c | 2 +- test/compiler/contextual.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/gf.c b/src/gf.c index 8c660cb744fcf..5235479ac3cc3 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1503,7 +1503,7 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt 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_nothing, world, &min_valid, &max_valid); + matc = _gf_invoke_lookup((jl_value_t*)tt, (jl_value_t*)mt, world, &min_valid, &max_valid); if (matc) { jl_method_t *m = matc->method; jl_svec_t *env = matc->sparams; diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index bbcf7b0dfb959..7f25a922ff4fa 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -150,6 +150,32 @@ methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, OverlayModule.mt, methods = Base._methods_by_ftype(Tuple{typeof(sin), Int}, OverlayModule.mt, 1, Base.get_world_counter()) @test isempty(methods) +# 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 load_path = mktempdir() From 9747c77696b4660f963ecdaa43b86e24e2e3f75f Mon Sep 17 00:00:00 2001 From: William Moses Date: Wed, 21 Jan 2026 16:00:33 -0500 Subject: [PATCH 16/18] [1.11] [LLVMAllocOpt] Preserve metadata lowering an alloca (#60776) Backport of https://github.com/JuliaLang/julia/pull/60695 particularly --- src/llvm-alloc-opt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index c343912b385f9..428be4e47b88a 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -681,6 +681,7 @@ void Optimizer::moveToStack(CallInst *orig_inst, size_t sz, bool has_ref, AllocF IRBuilder<> builder(orig_inst); initializeAlloca(builder, buff, allockind); } + buff->copyMetadata(*orig_inst); Instruction *new_inst = cast(prolog_builder.CreateBitCast(ptr, JuliaType::get_pjlvalue_ty(prolog_builder.getContext(), buff->getType()->getPointerAddressSpace()))); new_inst->takeName(orig_inst); From f91cd5f385787cc81c09da234d0cfe60cd3f62ab Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:01:23 -0500 Subject: [PATCH 17/18] =?UTF-8?q?=F0=9F=A4=96=20[backports-release-1.11]?= =?UTF-8?q?=20Bump=20SparseArrays=20stdlib=202420351=20=E2=86=92=20e4ffd9f?= =?UTF-8?q?=20(#60774)?= 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.11 Julia branch: backports-release-1.11 Old commit: 2420351 New commit: e4ffd9f Julia version: 1.11.8 SparseArrays version: 1.11.0 (Does not match) Bump invoked by: @dkarrasch Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaSparse/SparseArrays.jl/compare/242035184c0d539bdb5e64bf26eb7726b123db14...e4ffd9f08f891103cf59f2ad32fcf38d75812f86 ``` $ git log --oneline 2420351..e4ffd9f e4ffd9f Backports to v1.11 (#670) 1da3028 Separate out tests for the GPL build and do not run them when GPL libs are not present (#658) ``` 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-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/md5 delete mode 100644 deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/sha512 create mode 100644 deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/md5 create mode 100644 deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/md5 b/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/md5 deleted file mode 100644 index 2f95a7d6f3947..0000000000000 --- a/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -eb9ce9d568c5ff313c09c4f2caf26d13 diff --git a/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/sha512 b/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/sha512 deleted file mode 100644 index c55bbe86e3e24..0000000000000 --- a/deps/checksums/SparseArrays-242035184c0d539bdb5e64bf26eb7726b123db14.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -fbd3876eab248aee95b34e09fff4366db42fd2e1692e063ef8362256dccbc9b1548ea8f3106065e7310834edbe0ed176466ad2bb64a91af3386d0e9d0db1f929 diff --git a/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/md5 b/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/md5 new file mode 100644 index 0000000000000..8a07a9862643c --- /dev/null +++ b/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/md5 @@ -0,0 +1 @@ +3ae2eebb167edd93aa2b67aef56f1764 diff --git a/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/sha512 b/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/sha512 new file mode 100644 index 0000000000000..4781a7c699523 --- /dev/null +++ b/deps/checksums/SparseArrays-e4ffd9f08f891103cf59f2ad32fcf38d75812f86.tar.gz/sha512 @@ -0,0 +1 @@ +bb8e24a95e84e59aa296b5b3d584e35dddf6cace926afb919c03c5d560aefbb7f6ad1442d0b2bf104212c62d8f578f5fb4e2c6dfdea196a0fae9bdf61527d8fa diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 41c5d6b42479d..44a339e4c63a5 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = release-1.11 -SPARSEARRAYS_SHA1 = 242035184c0d539bdb5e64bf26eb7726b123db14 +SPARSEARRAYS_SHA1 = e4ffd9f08f891103cf59f2ad32fcf38d75812f86 SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 From e29b8e66122e9c4f37510388533cf1637618523b Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 22 Jan 2026 03:45:39 +0530 Subject: [PATCH 18/18] [backports-release-1.11] Fix namespace of `IOError` in `random_seed` (#59689) This PR addresses an issue with `IOError` not being exported from `Base` and therefore being unavailable within `Random` if not fully qualified. I'm not entirely certain which branch to make this PR to: `release-1.11` or `backports-release-1.11`. Please change the target branch to the appropriate one if necessary. --- stdlib/Random/src/RNGs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index 2ea2fb3a684df..6c8fc684d8e53 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -287,7 +287,7 @@ function random_seed() # almost surely always getting distinct seeds, while having them printed reasonably tersely return rand(RandomDevice(), UInt128) catch ex - ex isa IOError || rethrow() + ex isa Base.IOError || rethrow() @warn "Entropy pool not available to seed RNG; using ad-hoc entropy sources." return Libc.rand() end