From 76761961a0d04f610f695255c95804b076d566a4 Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Tue, 16 Jul 2024 00:46:25 +0800 Subject: [PATCH 001/206] `mkpath` always returns the original path (#54857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #54826 related performance test code: ```julia using BenchmarkTools using Base: IOError function checkmode(mode::Integer) if !(0 <= mode <= 511) throw(ArgumentError("Mode must be between 0 and 511 = 0o777")) end mode end function mkpath(path::AbstractString; mode::Integer = 0o777) dir = dirname(path) # stop recursion for `""`, `"/"`, or existed dir (path == dir || isdir(path)) && return path mkpath(dir, mode = checkmode(mode)) try # cases like `mkpath("x/")` will cause an error if `isdir(path)` is skipped # the error will not be rethrowed, but it may be slower, and thus we avoid it in advance isdir(path) || mkdir(path, mode = mode) catch err # If there is a problem with making the directory, but the directory # does in fact exist, then ignore the error. Else re-throw it. if !isa(err, IOError) || !isdir(path) rethrow() end end return path end function mkpath_2(path::AbstractString; mode::Integer = 0o777) dir = dirname(path) # stop recursion for `""` and `"/"` or existed dir (path == dir || isdir(path)) && return path mkpath_2(dir, mode = checkmode(mode)) try mkdir(path, mode = mode) catch err # If there is a problem with making the directory, but the directory # does in fact exist, then ignore the error. Else re-throw it. if !isa(err, IOError) || !isdir(path) rethrow() end end return path end versioninfo() display(@benchmark begin rm("A", recursive=true, force=true); mkpath("A/B/C/D/") end) display(@benchmark begin rm("A", recursive=true, force=true); mkpath_2("A/B/C/D/") end) ``` output: ``` Julia Version 1.10.4 Commit 48d4fd48430 (2024-06-04 10:41 UTC) Build Info: Official https://julialang.org/ release Platform Info: OS: macOS (x86_64-apple-darwin22.4.0) CPU: 16 × Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-15.0.7 (ORCJIT, skylake) Threads: 1 default, 0 interactive, 1 GC (on 16 virtual cores) Environment: JULIA_EDITOR = code JULIA_NUM_THREADS = BenchmarkTools.Trial: 8683 samples with 1 evaluation. Range (min … max): 473.972 μs … 18.867 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 519.704 μs ┊ GC (median): 0.00% Time (mean ± σ): 571.261 μs ± 378.851 μs ┊ GC (mean ± σ): 0.00% ± 0.00% ▂█▇▄▁ ▃███████▇▅▄▄▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 474 μs Histogram: frequency by time 961 μs < Memory estimate: 5.98 KiB, allocs estimate: 65. BenchmarkTools.Trial: 6531 samples with 1 evaluation. Range (min … max): 588.122 μs … 17.449 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 660.071 μs ┊ GC (median): 0.00% Time (mean ± σ): 760.333 μs ± 615.759 μs ┊ GC (mean ± σ): 0.00% ± 0.00% ██▆▄▃▁▁ ▁ ██████████▆▇█▇▆▆▅▅▅▄▁▄▁▄▄▃▄▃▁▃▃▁▃▁▁▁▄▁▁▁▁▁▁▁▃▃▁▁▁▃▁▁▃▁▁▁▁▅▅▄▇ █ 588 μs Histogram: log(frequency) by time 4.2 ms < Memory estimate: 5.63 KiB, allocs estimate: 72. ``` --- base/file.jl | 16 ++++++++++------ test/file.jl | 7 ++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/base/file.jl b/base/file.jl index 727b97abd36f1..e1b8e8a748fae 100644 --- a/base/file.jl +++ b/base/file.jl @@ -230,15 +230,19 @@ julia> mkpath("intermediate_dir/actually_a_directory.txt") # creates two directo julia> isdir("intermediate_dir/actually_a_directory.txt") true +julia> mkpath("my/test/dir/") # returns the original `path` +"my/test/dir/" ``` """ function mkpath(path::AbstractString; mode::Integer = 0o777) - isdirpath(path) && (path = dirname(path)) - dir = dirname(path) - (path == dir || isdir(path)) && return path - mkpath(dir, mode = checkmode(mode)) + parent = dirname(path) + # stop recursion for `""`, `"/"`, or existing dir + (path == parent || isdir(path)) && return path + mkpath(parent, mode = checkmode(mode)) try - mkdir(path, mode = mode) + # The `isdir` check could be omitted, then `mkdir` will throw an error in cases like `x/`. + # Although the error will not be rethrown, we avoid it in advance for performance reasons. + isdir(path) || mkdir(path, mode = mode) catch err # If there is a problem with making the directory, but the directory # does in fact exist, then ignore the error. Else re-throw it. @@ -246,7 +250,7 @@ function mkpath(path::AbstractString; mode::Integer = 0o777) rethrow() end end - path + return path end # Files that were requested to be deleted but can't be by the current process diff --git a/test/file.jl b/test/file.jl index 8c5c3ebc4b74b..b88595981261e 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1491,7 +1491,7 @@ mktempdir() do dir @test isfile(name1) @test isfile(name2) namedir = joinpath(dir, "chalk") - namepath = joinpath(dir, "chalk","cheese","fresh") + namepath = joinpath(dir, "chalk", "cheese", "fresh") @test !ispath(namedir) @test mkdir(namedir) == namedir @test isdir(namedir) @@ -1500,7 +1500,12 @@ mktempdir() do dir @test isdir(namepath) @test mkpath(namepath) == namepath @test isdir(namepath) + # issue 54826 + namepath_dirpath = joinpath(dir, "x", "y", "z", "") + @test mkpath(namepath_dirpath) == namepath_dirpath end +@test mkpath("") == "" +@test mkpath("/") == "/" # issue #30588 @test realpath(".") == realpath(pwd()) From d49a3c74c97c9ca9ef711d644a3f2b1c02b38d63 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:25:48 -0300 Subject: [PATCH 002/206] use jl_gc_alloc inside jl_alloc_string (#55098) --- src/array.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/array.c b/src/array.c index 2d36d458d3f4c..f0051ec17565a 100644 --- a/src/array.c +++ b/src/array.c @@ -304,22 +304,8 @@ JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len) jl_task_t *ct = jl_current_task; jl_value_t *s; jl_ptls_t ptls = ct->ptls; - const size_t allocsz = sz + sizeof(jl_taggedvalue_t); - if (sz <= GC_MAX_SZCLASS) { - int pool_id = jl_gc_szclass_align8(allocsz); - jl_gc_pool_t *p = &ptls->gc_tls.heap.norm_pools[pool_id]; - int osize = jl_gc_sizeclasses[pool_id]; - // We call `jl_gc_pool_alloc_noinline` instead of `jl_gc_pool_alloc` to avoid double-counting in - // the Allocations Profiler. (See https://github.com/JuliaLang/julia/pull/43868 for more details.) - s = jl_gc_pool_alloc_noinline(ptls, (char*)p - (char*)ptls, osize); - } - else { - if (allocsz < sz) // overflow in adding offs, size was "negative" - jl_throw(jl_memory_exception); - s = jl_gc_big_alloc_noinline(ptls, allocsz); - } + s = (jl_value_t*)jl_gc_alloc(ptls, sz, jl_string_type); jl_set_typetagof(s, jl_string_tag, 0); - maybe_record_alloc_to_profile(s, len, jl_string_type); *(size_t*)s = len; jl_string_data(s)[len] = 0; return s; From d3ce49999e15e1b63d7bdbe0271618b8e4df85dc Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:28:37 -0400 Subject: [PATCH 003/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=20046df8ce4=20to=20d801e4545=20(#55128)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Pkg URL: https://github.com/JuliaLang/Pkg.jl.git Stdlib branch: master Julia branch: master Old commit: 046df8ce4 New commit: d801e4545 Julia version: 1.12.0-DEV Pkg version: 1.12.0 Bump invoked by: @IanButterworth Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Pkg.jl/compare/046df8ce407659cfaccc647265a6e57bfb02e056...d801e4545f548ab9061a018bf19db1944c711607 ``` $ git log --oneline 046df8ce4..d801e4545 d801e4545 fix artifact printing quiet rule (#3951) ``` Co-authored-by: Dilum Aluthge --- .../Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/md5 | 1 - .../Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/sha512 | 1 - .../Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 | 1 + .../Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 create mode 100644 deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 diff --git a/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/md5 b/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/md5 deleted file mode 100644 index 099cd0640b2e2..0000000000000 --- a/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -4dd51346715552c50b186d26a01a793c diff --git a/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/sha512 b/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/sha512 deleted file mode 100644 index ba39942f95ecc..0000000000000 --- a/deps/checksums/Pkg-046df8ce407659cfaccc647265a6e57bfb02e056.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -27fa365879bc42d1e9e41c077a2826350994de59a93f72c276b4b2a2b21495ffc0785b3f5c72ac054f7b6d8765b5e51f36792af2661e4989c422159cec600144 diff --git a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 new file mode 100644 index 0000000000000..a5bfcea5f0408 --- /dev/null +++ b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 @@ -0,0 +1 @@ +68d6fc78830e9d3f736cae1a727247ac diff --git a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 new file mode 100644 index 0000000000000..b671340cbc147 --- /dev/null +++ b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 @@ -0,0 +1 @@ +00319914e123e0deb59a8235b6509953550c25e5e8a2957fe30f5f07b16db4dddfc0b41fbfcaa3b36d869d98514a9d2890105b0bd4b5d66c928408a51892b968 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 9d6c9ddaca2ba..9a762a16d22d7 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 046df8ce407659cfaccc647265a6e57bfb02e056 +PKG_SHA1 = d801e4545f548ab9061a018bf19db1944c711607 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From f8bec455396d81c3a13bc63e0ffdb1d3eb1788a4 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Mon, 15 Jul 2024 19:20:23 -0300 Subject: [PATCH 004/206] Simplify sweeping of big values (#54936) Simplifies the layout of the doubly linked list of big objects to make it a bit more canonical: let's just store a pointer to the previous element, instead of storing a "pointer to the next element of the previous element". This should make the implementation a bit easier to understand without incurring any memory overhead. I ran the serial and multithreaded benchmarks from GCBenchmarks and this seems fairly close to performance neutral on my machine. We also ran our internal benchmarks on it at RAI and it looks fine from a correctness and performance point of view. --------- Co-authored-by: Kiran Pamnany --- src/gc-debug.c | 8 +-- src/gc-tls.h | 4 +- src/gc.c | 161 +++++++++++++++++++++++-------------------------- src/gc.h | 35 +++++++---- 4 files changed, 106 insertions(+), 102 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index cbf8c89918d01..62be5c0eab554 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -134,7 +134,7 @@ static void clear_mark(int bits) } bigval_t *v; for (int i = 0; i < gc_n_threads; i++) { - v = gc_all_tls_states[i]->gc_tls.heap.big_objects; + v = gc_all_tls_states[i]->gc_tls.heap.young_generation_of_bigvals; while (v != NULL) { void *gcv = &v->header; if (!gc_verifying) @@ -144,7 +144,7 @@ static void clear_mark(int bits) } } - v = big_objects_marked; + v = oldest_generation_of_bigvals; while (v != NULL) { void *gcv = &v->header; if (!gc_verifying) @@ -992,7 +992,7 @@ void gc_stats_big_obj(void) size_t nused=0, nbytes=0, nused_old=0, nbytes_old=0; for (int t_i = 0; t_i < gc_n_threads; t_i++) { jl_ptls_t ptls2 = gc_all_tls_states[t_i]; - bigval_t *v = ptls2->gc_tls.heap.big_objects; + bigval_t *v = ptls2->gc_tls.heap.young_generation_of_bigvals; while (v != NULL) { if (gc_marked(v->bits.gc)) { nused++; @@ -1000,7 +1000,7 @@ void gc_stats_big_obj(void) } v = v->next; } - v = big_objects_marked; + v = oldest_generation_of_bigvals; while (v != NULL) { if (gc_marked(v->bits.gc)) { nused_old++; diff --git a/src/gc-tls.h b/src/gc-tls.h index 629ce53fbc886..8911653330f56 100644 --- a/src/gc-tls.h +++ b/src/gc-tls.h @@ -31,8 +31,8 @@ typedef struct { struct _mallocarray_t *mallocarrays; struct _mallocarray_t *mafreelist; - // variables for tracking big objects - struct _bigval_t *big_objects; + // variable for tracking young (i.e. not in `GC_OLD_MARKED`/last generation) large objects + struct _bigval_t *young_generation_of_bigvals; // lower bound of the number of pointers inside remembered values int remset_nptr; diff --git a/src/gc.c b/src/gc.c index 6493cc3e1bae4..9ae3145e59c01 100644 --- a/src/gc.c +++ b/src/gc.c @@ -35,6 +35,8 @@ uv_cond_t gc_threads_cond; uv_sem_t gc_sweep_assists_needed; // Mutex used to coordinate entry of GC threads in the mark loop uv_mutex_t gc_queue_observer_lock; +// Tag for sentinel nodes in bigval list +uintptr_t gc_bigval_sentinel_tag; // Linked list of callback functions @@ -151,7 +153,6 @@ JL_DLLEXPORT void jl_gc_set_cb_notify_gc_pressure(jl_gc_cb_notify_gc_pressure_t // is going to realloc the buffer (of its own list) or accessing the // list of another thread static jl_mutex_t finalizers_lock; -static uv_mutex_t gc_cache_lock; // mutex for gc-heap-snapshot. jl_mutex_t heapsnapshot_lock; @@ -204,8 +205,8 @@ JL_DLLEXPORT uintptr_t jl_get_buff_tag(void) JL_NOTSAFEPOINT return jl_buff_tag; } -// List of marked big objects. Not per-thread. Accessed only by master thread. -bigval_t *big_objects_marked = NULL; +// List of big objects in oldest generation (`GC_OLD_MARKED`). Not per-thread. Accessed only by master thread. +bigval_t *oldest_generation_of_bigvals = NULL; // -- Finalization -- // `ptls->finalizers` and `finalizer_list_marked` might have tagged pointers. @@ -722,60 +723,25 @@ static int64_t t_start = 0; // Time GC starts; static int64_t last_trim_maxrss = 0; #endif -static void gc_sync_cache_nolock(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) JL_NOTSAFEPOINT +static void gc_sync_cache(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) JL_NOTSAFEPOINT { - const int nbig = gc_cache->nbig_obj; - for (int i = 0; i < nbig; i++) { - void *ptr = gc_cache->big_obj[i]; - bigval_t *hdr = (bigval_t*)gc_ptr_clear_tag(ptr, 1); - gc_big_object_unlink(hdr); - if (gc_ptr_tag(ptr, 1)) { - gc_big_object_link(hdr, &ptls->gc_tls.heap.big_objects); - } - else { - // Move hdr from `big_objects` list to `big_objects_marked list` - gc_big_object_link(hdr, &big_objects_marked); - } - } - gc_cache->nbig_obj = 0; perm_scanned_bytes += gc_cache->perm_scanned_bytes; scanned_bytes += gc_cache->scanned_bytes; gc_cache->perm_scanned_bytes = 0; gc_cache->scanned_bytes = 0; } -static void gc_sync_cache(jl_ptls_t ptls) JL_NOTSAFEPOINT -{ - uv_mutex_lock(&gc_cache_lock); - gc_sync_cache_nolock(ptls, &ptls->gc_tls.gc_cache); - uv_mutex_unlock(&gc_cache_lock); -} - // No other threads can be running marking at the same time -static void gc_sync_all_caches_nolock(jl_ptls_t ptls) +static void gc_sync_all_caches(jl_ptls_t ptls) { assert(gc_n_threads); for (int t_i = 0; t_i < gc_n_threads; t_i++) { jl_ptls_t ptls2 = gc_all_tls_states[t_i]; if (ptls2 != NULL) - gc_sync_cache_nolock(ptls, &ptls2->gc_tls.gc_cache); + gc_sync_cache(ptls, &ptls2->gc_tls.gc_cache); } } -STATIC_INLINE void gc_queue_big_marked(jl_ptls_t ptls, bigval_t *hdr, - int toyoung) JL_NOTSAFEPOINT -{ - const int nentry = sizeof(ptls->gc_tls.gc_cache.big_obj) / sizeof(void*); - size_t nobj = ptls->gc_tls.gc_cache.nbig_obj; - if (__unlikely(nobj >= nentry)) { - gc_sync_cache(ptls); - nobj = 0; - } - uintptr_t v = (uintptr_t)hdr; - ptls->gc_tls.gc_cache.big_obj[nobj] = (void*)(toyoung ? (v | 1) : v); - ptls->gc_tls.gc_cache.nbig_obj = nobj + 1; -} - // Atomically set the mark bit for object and return whether it was previously unmarked FORCE_INLINE int gc_try_setmark_tag(jl_taggedvalue_t *o, uint8_t mark_mode) JL_NOTSAFEPOINT { @@ -812,16 +778,14 @@ STATIC_INLINE void gc_setmark_big(jl_ptls_t ptls, jl_taggedvalue_t *o, bigval_t *hdr = bigval_header(o); if (mark_mode == GC_OLD_MARKED) { ptls->gc_tls.gc_cache.perm_scanned_bytes += hdr->sz; - gc_queue_big_marked(ptls, hdr, 0); } else { ptls->gc_tls.gc_cache.scanned_bytes += hdr->sz; - // We can't easily tell if the object is old or being promoted - // from the gc bits but if the `age` is `0` then the object - // must be already on a young list. if (mark_reset_age) { + assert(jl_atomic_load(&gc_n_threads_marking) == 0); // `mark_reset_age` is only used during single-threaded marking // Reset the object as if it was just allocated - gc_queue_big_marked(ptls, hdr, 1); + gc_big_object_unlink(hdr); + gc_big_object_link(ptls->gc_tls.heap.young_generation_of_bigvals, hdr); } } } @@ -1003,7 +967,7 @@ STATIC_INLINE jl_value_t *jl_gc_big_alloc_inner(jl_ptls_t ptls, size_t sz) memset(v, 0xee, allocsz); #endif v->sz = allocsz; - gc_big_object_link(v, &ptls->gc_tls.heap.big_objects); + gc_big_object_link(ptls->gc_tls.heap.young_generation_of_bigvals, v); return jl_valueof(&v->header); } @@ -1023,62 +987,86 @@ jl_value_t *jl_gc_big_alloc_noinline(jl_ptls_t ptls, size_t sz) { return jl_gc_big_alloc_inner(ptls, sz); } -// Sweep list rooted at *pv, removing and freeing any unmarked objects. -// Return pointer to last `next` field in the culled list. -static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) JL_NOTSAFEPOINT +FORCE_INLINE void sweep_unlink_and_free(bigval_t *v) JL_NOTSAFEPOINT +{ + gc_big_object_unlink(v); + gc_num.freed += v->sz; + jl_atomic_store_relaxed(&gc_heap_stats.heap_size, jl_atomic_load_relaxed(&gc_heap_stats.heap_size) - v->sz); +#ifdef MEMDEBUG + memset(v, 0xbb, v->sz); +#endif + gc_invoke_callbacks(jl_gc_cb_notify_external_free_t, gc_cblist_notify_external_free, (v)); + jl_free_aligned(v); +} + +static bigval_t *sweep_list_of_young_bigvals(bigval_t *young) JL_NOTSAFEPOINT { - bigval_t *v = *pv; + bigval_t *last_node = young; + bigval_t *v = young->next; // skip the sentinel + bigval_t *old = oldest_generation_of_bigvals; + int sweep_full = current_sweep_full; // don't load the global in the hot loop while (v != NULL) { bigval_t *nxt = v->next; int bits = v->bits.gc; int old_bits = bits; if (gc_marked(bits)) { - pv = &v->next; if (sweep_full || bits == GC_MARKED) { bits = GC_OLD; + last_node = v; + } + else { // `bits == GC_OLD_MARKED` + assert(bits == GC_OLD_MARKED); + // reached oldest generation, move from young list to old list + gc_big_object_unlink(v); + gc_big_object_link(old, v); } v->bits.gc = bits; } else { - // Remove v from list and free it - *pv = nxt; - if (nxt) - nxt->prev = pv; - gc_num.freed += v->sz; - jl_atomic_store_relaxed(&gc_heap_stats.heap_size, - jl_atomic_load_relaxed(&gc_heap_stats.heap_size) - (v->sz)); -#ifdef MEMDEBUG - memset(v, 0xbb, v->sz); -#endif - gc_invoke_callbacks(jl_gc_cb_notify_external_free_t, - gc_cblist_notify_external_free, (v)); - jl_free_aligned(v); + sweep_unlink_and_free(v); } gc_time_count_big(old_bits, bits); v = nxt; } - return pv; + return last_node; +} + +static void sweep_list_of_oldest_bigvals(bigval_t *young) JL_NOTSAFEPOINT +{ + bigval_t *v = oldest_generation_of_bigvals->next; // skip the sentinel + while (v != NULL) { + bigval_t *nxt = v->next; + assert(v->bits.gc == GC_OLD_MARKED); + v->bits.gc = GC_OLD; + gc_time_count_big(GC_OLD_MARKED, GC_OLD); + v = nxt; + } } -static void sweep_big(jl_ptls_t ptls, int sweep_full) JL_NOTSAFEPOINT +static void sweep_big(jl_ptls_t ptls) JL_NOTSAFEPOINT { gc_time_big_start(); assert(gc_n_threads); + bigval_t *last_node_in_my_list = NULL; for (int i = 0; i < gc_n_threads; i++) { jl_ptls_t ptls2 = gc_all_tls_states[i]; - if (ptls2 != NULL) - sweep_big_list(sweep_full, &ptls2->gc_tls.heap.big_objects); + if (ptls2 != NULL) { + bigval_t *last_node = sweep_list_of_young_bigvals(ptls2->gc_tls.heap.young_generation_of_bigvals); + if (ptls == ptls2) { + last_node_in_my_list = last_node; + } + } } - if (sweep_full) { - bigval_t **last_next = sweep_big_list(sweep_full, &big_objects_marked); - // Move all survivors from big_objects_marked list to the big_objects list of this thread. - if (ptls->gc_tls.heap.big_objects) - ptls->gc_tls.heap.big_objects->prev = last_next; - *last_next = ptls->gc_tls.heap.big_objects; - ptls->gc_tls.heap.big_objects = big_objects_marked; - if (ptls->gc_tls.heap.big_objects) - ptls->gc_tls.heap.big_objects->prev = &ptls->gc_tls.heap.big_objects; - big_objects_marked = NULL; + if (current_sweep_full) { + sweep_list_of_oldest_bigvals(ptls->gc_tls.heap.young_generation_of_bigvals); + // move all nodes in `oldest_generation_of_bigvals` to my list of bigvals + assert(last_node_in_my_list != NULL); + assert(last_node_in_my_list->next == NULL); + last_node_in_my_list->next = oldest_generation_of_bigvals->next; // skip the sentinel + if (oldest_generation_of_bigvals->next != NULL) { + oldest_generation_of_bigvals->next->prev = last_node_in_my_list; + } + oldest_generation_of_bigvals->next = NULL; } gc_time_big_end(); } @@ -1527,7 +1515,7 @@ static void gc_sweep_other(jl_ptls_t ptls, int sweep_full) JL_NOTSAFEPOINT sweep_stack_pools(); gc_sweep_foreign_objs(); sweep_malloced_memory(); - sweep_big(ptls, sweep_full); + sweep_big(ptls); jl_engine_sweep(gc_all_tls_states); } @@ -3536,7 +3524,7 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection) // marking is over // Flush everything in mark cache - gc_sync_all_caches_nolock(ptls); + gc_sync_all_caches(ptls); gc_verify(ptls); @@ -3928,7 +3916,9 @@ void jl_init_thread_heap(jl_ptls_t ptls) small_arraylist_new(&heap->free_stacks[i], 0); heap->mallocarrays = NULL; heap->mafreelist = NULL; - heap->big_objects = NULL; + heap->young_generation_of_bigvals = (bigval_t*)calloc_s(sizeof(bigval_t)); // sentinel + assert(gc_bigval_sentinel_tag != 0); // make sure the sentinel is initialized + heap->young_generation_of_bigvals->header = gc_bigval_sentinel_tag; arraylist_new(&heap->remset, 0); arraylist_new(&ptls->finalizers, 0); arraylist_new(&ptls->gc_tls.sweep_objs, 0); @@ -3936,7 +3926,6 @@ void jl_init_thread_heap(jl_ptls_t ptls) jl_gc_mark_cache_t *gc_cache = &ptls->gc_tls.gc_cache; gc_cache->perm_scanned_bytes = 0; gc_cache->scanned_bytes = 0; - gc_cache->nbig_obj = 0; // Initialize GC mark-queue jl_gc_markqueue_t *mq = &ptls->gc_tls.mark_queue; @@ -3974,12 +3963,16 @@ void jl_gc_init(void) JL_MUTEX_INIT(&heapsnapshot_lock, "heapsnapshot_lock"); JL_MUTEX_INIT(&finalizers_lock, "finalizers_lock"); uv_mutex_init(&page_profile_lock); - uv_mutex_init(&gc_cache_lock); uv_mutex_init(&gc_perm_lock); uv_mutex_init(&gc_threads_lock); uv_cond_init(&gc_threads_cond); uv_sem_init(&gc_sweep_assists_needed, 0); uv_mutex_init(&gc_queue_observer_lock); + void *_addr = (void*)calloc_s(1); // dummy allocation to get the sentinel tag + uintptr_t addr = (uintptr_t)_addr; + gc_bigval_sentinel_tag = addr; + oldest_generation_of_bigvals = (bigval_t*)calloc_s(sizeof(bigval_t)); // sentinel + oldest_generation_of_bigvals->header = gc_bigval_sentinel_tag; jl_gc_init_page(); jl_gc_debug_init(); diff --git a/src/gc.h b/src/gc.h index 109aeea593581..c9803fa883414 100644 --- a/src/gc.h +++ b/src/gc.h @@ -122,9 +122,11 @@ typedef struct _jl_gc_chunk_t { // layout for big (>2k) objects +extern uintptr_t gc_bigval_sentinel_tag; + JL_EXTENSION typedef struct _bigval_t { struct _bigval_t *next; - struct _bigval_t **prev; // pointer to the next field of the prev entry + struct _bigval_t *prev; size_t sz; #ifdef _P64 // Add padding so that the value is 64-byte aligned // (8 pointers of 8 bytes each) - (4 other pointers in struct) @@ -440,7 +442,7 @@ STATIC_INLINE unsigned ffs_u32(uint32_t bitvec) #endif extern jl_gc_num_t gc_num; -extern bigval_t *big_objects_marked; +extern bigval_t *oldest_generation_of_bigvals; extern arraylist_t finalizer_list_marked; extern arraylist_t to_finalize; extern int64_t buffered_pages; @@ -539,21 +541,30 @@ STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT NOINLINE uintptr_t gc_get_stack_ptr(void); -STATIC_INLINE void gc_big_object_unlink(const bigval_t *hdr) JL_NOTSAFEPOINT +FORCE_INLINE void gc_big_object_unlink(const bigval_t *node) JL_NOTSAFEPOINT { - *hdr->prev = hdr->next; - if (hdr->next) { - hdr->next->prev = hdr->prev; + assert(node != oldest_generation_of_bigvals); + assert(node->header != gc_bigval_sentinel_tag); + assert(node->prev != NULL); + if (node->next != NULL) { + node->next->prev = node->prev; } + node->prev->next = node->next; } -STATIC_INLINE void gc_big_object_link(bigval_t *hdr, bigval_t **list) JL_NOTSAFEPOINT +FORCE_INLINE void gc_big_object_link(bigval_t *sentinel_node, bigval_t *node) JL_NOTSAFEPOINT { - hdr->next = *list; - hdr->prev = list; - if (*list) - (*list)->prev = &hdr->next; - *list = hdr; + assert(sentinel_node != NULL); + assert(sentinel_node->header == gc_bigval_sentinel_tag); + assert(sentinel_node->prev == NULL); + assert(node->header != gc_bigval_sentinel_tag); + // a new node gets linked in at the head of the list + node->next = sentinel_node->next; + node->prev = sentinel_node; + if (sentinel_node->next != NULL) { + sentinel_node->next->prev = node; + } + sentinel_node->next = node; } extern uv_mutex_t gc_threads_lock; From 17668e945380049c84934e92b622c61bfcb897c5 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Mon, 15 Jul 2024 23:42:14 -0300 Subject: [PATCH 005/206] delete some unused fields of jl_gc_mark_cache_t (#55138) They should have been deleted in https://github.com/JuliaLang/julia/pull/54936, but were not. --- src/gc-tls.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/gc-tls.h b/src/gc-tls.h index 8911653330f56..8b8ccd6ad6c27 100644 --- a/src/gc-tls.h +++ b/src/gc-tls.h @@ -69,17 +69,6 @@ typedef struct { size_t perm_scanned_bytes; // thread local increment of `scanned_bytes` size_t scanned_bytes; - // Number of queued big objects (<= 1024) - size_t nbig_obj; - // Array of queued big objects to be moved between the young list - // and the old list. - // A set low bit means that the object should be moved from the old list - // to the young list (`mark_reset_age`). - // Objects can only be put into this list when the mark bit is flipped to - // `1` (atomically). Combining with the sync after marking, - // this makes sure that a single objects can only appear once in - // the lists (the mark bit cannot be flipped to `0` without sweeping) - void *big_obj[1024]; } jl_gc_mark_cache_t; typedef struct { From 7b0a189152af99431136e7e2e9393bab68a552e5 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Tue, 16 Jul 2024 00:26:47 -0500 Subject: [PATCH 006/206] Fix typo in code comment (#55133) --- base/public.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/public.jl b/base/public.jl index 460d3bc536383..dce1223124856 100644 --- a/base/public.jl +++ b/base/public.jl @@ -66,7 +66,7 @@ public ispublic, remove_linenums!, -# Opperators +# Operators operator_associativity, operator_precedence, isbinaryoperator, From d02bfebc3bdd70b6975b4b30e2f1b60684920e71 Mon Sep 17 00:00:00 2001 From: Christian Guinard <28689358+christiangnrd@users.noreply.github.com> Date: Tue, 16 Jul 2024 07:22:46 -0300 Subject: [PATCH 007/206] REPL: Remove hard-coded prompt strings in favour of pre-existing constants (#55109) --- stdlib/REPL/docs/src/index.md | 2 +- stdlib/REPL/src/Pkg_beforeload.jl | 2 +- stdlib/REPL/src/REPL.jl | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 42a9666088ac1..6250fc84dc6b2 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -50,7 +50,7 @@ julia> ans In Julia mode, the REPL supports something called *prompt pasting*. This activates when pasting text that starts with `julia> ` into the REPL. In that case, only expressions starting with `julia> ` (as -well as the other REPL mode prompts: `shell> `, `help?> `, `pkg>` ) are parsed, but others are +well as the other REPL mode prompts: `shell> `, `help?> `, `pkg> ` ) are parsed, but others are removed. This makes it possible to paste a chunk of text that has been copied from a REPL session without having to scrub away prompts and outputs. This feature is enabled by default but can be disabled or enabled at will with `REPL.enable_promptpaste(::Bool)`. If it is enabled, you can try it diff --git a/stdlib/REPL/src/Pkg_beforeload.jl b/stdlib/REPL/src/Pkg_beforeload.jl index 56c4e2562f7e6..2051e11711b0f 100644 --- a/stdlib/REPL/src/Pkg_beforeload.jl +++ b/stdlib/REPL/src/Pkg_beforeload.jl @@ -125,5 +125,5 @@ function Pkg_promptf() end end # Note no handling of Pkg.offline, as the Pkg version does here - return "$(prefix)pkg> " + return "$(prefix)$(PKG_PROMPT)" end diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 6eb22b2360f3c..2d364931bc253 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1257,7 +1257,7 @@ function setup_interface( on_enter = return_callback) # Setup help mode - help_mode = Prompt(contextual_prompt(repl, "help?> "), + help_mode = Prompt(contextual_prompt(repl, HELP_PROMPT), prompt_prefix = hascolor ? repl.help_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", @@ -1354,8 +1354,8 @@ function setup_interface( shell_prompt_len = length(SHELL_PROMPT) help_prompt_len = length(HELP_PROMPT) - jl_prompt_regex = r"^In \[[0-9]+\]: |^(?:\(.+\) )?julia> " - pkg_prompt_regex = r"^(?:\(.+\) )?pkg> " + jl_prompt_regex = Regex("^In \\[[0-9]+\\]: |^(?:\\(.+\\) )?$JULIA_PROMPT") + pkg_prompt_regex = Regex("^(?:\\(.+\\) )?$PKG_PROMPT") # Canonicalize user keymap input if isa(extra_repl_keymap, Dict) @@ -1769,7 +1769,7 @@ function run_frontend(repl::StreamREPL, backend::REPLBackendRef) if have_color print(repl.stream,repl.prompt_color) end - print(repl.stream, "julia> ") + print(repl.stream, JULIA_PROMPT) if have_color print(repl.stream, input_color(repl)) end From 742e7d998e6ceebdf84c24ff81f52d76787bdcb8 Mon Sep 17 00:00:00 2001 From: Adriano Meligrana <68152031+Tortar@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:43:25 +0200 Subject: [PATCH 008/206] Convert message in timing macros before printing (#55122) --- base/timing.jl | 6 ++++-- test/misc.jl | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/base/timing.jl b/base/timing.jl index 7e5891e2a3954..5fefd75c15852 100644 --- a/base/timing.jl +++ b/base/timing.jl @@ -315,7 +315,8 @@ macro time(msg, ex) quote local ret = @timed $(esc(ex)) local _msg = $(esc(msg)) - time_print(stdout, ret.time*1e9, ret.gcstats.allocd, ret.gcstats.total_time, gc_alloc_count(ret.gcstats), ret.lock_conflicts, ret.compile_time*1e9, ret.recompile_time*1e9, true; msg=_msg) + local _msg_str = _msg === nothing ? _msg : string(_msg) + time_print(stdout, ret.time*1e9, ret.gcstats.allocd, ret.gcstats.total_time, gc_alloc_count(ret.gcstats), ret.lock_conflicts, ret.compile_time*1e9, ret.recompile_time*1e9, true; msg=_msg_str) ret.value end end @@ -387,7 +388,8 @@ macro timev(msg, ex) quote local ret = @timed $(esc(ex)) local _msg = $(esc(msg)) - timev_print(ret.time*1e9, ret.gcstats, ret.lock_conflicts, (ret.compile_time*1e9, ret.recompile_time*1e9); msg=_msg) + local _msg_str = _msg === nothing ? _msg : string(_msg) + timev_print(ret.time*1e9, ret.gcstats, ret.lock_conflicts, (ret.compile_time*1e9, ret.recompile_time*1e9); msg=_msg_str) ret.value end end diff --git a/test/misc.jl b/test/misc.jl index 10a25fa1c5ff6..3ad58a96a0bbd 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -321,25 +321,34 @@ v11801, t11801 = @timed sin(1) @test names(@__MODULE__, all = true) == names_before_timing redirect_stdout(devnull) do # suppress time prints + # Accepted @time argument formats @test @time true @test @time "message" true +@test @time 1 true let msg = "message" @test @time msg true end let foo() = "message" @test @time foo() true end +let foo() = 1 + @test @time foo() true +end # Accepted @timev argument formats @test @timev true @test @timev "message" true +@test @timev 1 true let msg = "message" @test @timev msg true end let foo() = "message" @test @timev foo() true end +let foo() = 1 + @test @timev foo() true +end # @showtime @test @showtime true From 0945b9d7740855c82a09fed42fbf6bc561e02c77 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Tue, 16 Jul 2024 06:35:52 -0500 Subject: [PATCH 009/206] Replace some occurrences of iteration over 1:length with more idiomatic structures (mostly eachindex) (#55137) Base should be a model for the ecosystem, and `eachindex(x)` is better than `1:length(x)` in almost all cases. I've updated many, but certainly not all examples. This is mostly a NFC, but also fixes #55136. --- base/abstractarray.jl | 8 ++++---- base/errorshow.jl | 10 +++++----- base/expr.jl | 2 +- base/intfuncs.jl | 2 +- base/loading.jl | 9 ++++----- base/multidimensional.jl | 2 +- base/reflection.jl | 2 +- base/show.jl | 10 +++++----- base/tuple.jl | 6 +++--- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index a9adae86b9ef2..f32a1b9d6d40b 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1659,10 +1659,10 @@ typed_vcat(::Type{T}) where {T} = Vector{T}() typed_hcat(::Type{T}) where {T} = Vector{T}() ## cat: special cases -vcat(X::T...) where {T} = T[ X[i] for i=1:length(X) ] -vcat(X::T...) where {T<:Number} = T[ X[i] for i=1:length(X) ] -hcat(X::T...) where {T} = T[ X[j] for i=1:1, j=1:length(X) ] -hcat(X::T...) where {T<:Number} = T[ X[j] for i=1:1, j=1:length(X) ] +vcat(X::T...) where {T} = T[ X[i] for i=eachindex(X) ] +vcat(X::T...) where {T<:Number} = T[ X[i] for i=eachindex(X) ] +hcat(X::T...) where {T} = T[ X[j] for i=1:1, j=eachindex(X) ] +hcat(X::T...) where {T<:Number} = T[ X[j] for i=1:1, j=eachindex(X) ] vcat(X::Number...) = hvcat_fill!(Vector{promote_typeof(X...)}(undef, length(X)), X) hcat(X::Number...) = hvcat_fill!(Matrix{promote_typeof(X...)}(undef, 1,length(X)), X) diff --git a/base/errorshow.jl b/base/errorshow.jl index a75f2f54b156d..fc9fc5c2aac32 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -196,7 +196,7 @@ function showerror(io::IO, ex::CanonicalIndexError) print(io, "CanonicalIndexError: ", ex.func, " not defined for ", ex.type) end -typesof(@nospecialize args...) = Tuple{Any[ Core.Typeof(args[i]) for i in 1:length(args) ]...} +typesof(@nospecialize args...) = Tuple{Any[Core.Typeof(arg) for arg in args]...} function print_with_compare(io::IO, @nospecialize(a::DataType), @nospecialize(b::DataType), color::Symbol) if a.name === b.name @@ -273,7 +273,7 @@ function showerror(io::IO, ex::MethodError) arg_types_param = arg_types_param[3:end] san_arg_types_param = san_arg_types_param[3:end] keys = kwt.parameters[1]::Tuple - kwargs = Any[(keys[i], fieldtype(kwt, i)) for i in 1:length(keys)] + kwargs = Any[(keys[i], fieldtype(kwt, i)) for i in eachindex(keys)] arg_types = rewrap_unionall(Tuple{arg_types_param...}, arg_types) end if f === Base.convert && length(arg_types_param) == 2 && !is_arg_types @@ -694,7 +694,7 @@ function show_reduced_backtrace(io::IO, t::Vector) push!(repeated_cycle, (0,0,0)) # repeated_cycle is never empty frame_counter = 1 - for i in 1:length(displayed_stackframes) + for i in eachindex(displayed_stackframes) (frame, n) = displayed_stackframes[i] print_stackframe(io, frame_counter, frame, n, ndigits_max, STACKTRACE_FIXEDCOLORS, STACKTRACE_MODULECOLORS) @@ -871,7 +871,7 @@ end function _collapse_repeated_frames(trace) kept_frames = trues(length(trace)) last_frame = nothing - for i in 1:length(trace) + for i in eachindex(trace) frame::StackFrame, _ = trace[i] if last_frame !== nothing && frame.file == last_frame.file && frame.line == last_frame.line #= @@ -916,7 +916,7 @@ function _collapse_repeated_frames(trace) end if length(last_params) > length(params) issame = true - for i = 1:length(params) + for i = eachindex(params) issame &= params[i] == last_params[i] end if issame diff --git a/base/expr.jl b/base/expr.jl index a58ae62c21a5f..8f84883fa2623 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -65,7 +65,7 @@ function copy_exprs(@nospecialize(x)) end return x end -copy_exprargs(x::Array{Any,1}) = Any[copy_exprs(@inbounds x[i]) for i in 1:length(x)] +copy_exprargs(x::Array{Any,1}) = Any[copy_exprs(@inbounds x[i]) for i in eachindex(x)] @eval exprarray(head::Symbol, arg::Array{Any,1}) = $(Expr(:new, :Expr, :head, :arg)) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 6df5b2c36124b..13ac4c9bfaf48 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -978,7 +978,7 @@ end Return an array with element type `T` (default `Int`) of the digits of `n` in the given base, optionally padded with zeros to a specified size. More significant digits are at -higher indices, such that `n == sum(digits[k]*base^(k-1) for k=1:length(digits))`. +higher indices, such that `n == sum(digits[k]*base^(k-1) for k in eachindex(digits))`. See also [`ndigits`](@ref), [`digits!`](@ref), and for base 2 also [`bitstring`](@ref), [`count_ones`](@ref). diff --git a/base/loading.jl b/base/loading.jl index 20946969f0238..bd985e431e497 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1214,7 +1214,7 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No t_comp_before = cumulative_compile_time_ns() end - for i in 1:length(depmods) + for i in eachindex(depmods) dep = depmods[i] dep isa Module && continue _, depkey, depbuild_id = dep::Tuple{String, PkgId, UInt128} @@ -1706,8 +1706,7 @@ function compilecache_path(pkg::PkgId; end staledeps, _, _ = staledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128} # finish checking staledeps module graph - for i in 1:length(staledeps) - dep = staledeps[i] + for dep in staledeps dep isa Module && continue modpath, modkey, modbuild_id = dep::Tuple{String, PkgId, UInt128} modpaths = find_all_in_cache_path(modkey) @@ -1897,7 +1896,7 @@ end try staledeps, ocachefile, newbuild_id = staledeps::Tuple{Vector{Any}, Union{Nothing, String}, UInt128} # finish checking staledeps module graph - for i in 1:length(staledeps) + for i in eachindex(staledeps) dep = staledeps[i] dep isa Module && continue modpath, modkey, modbuild_id = dep::Tuple{String, PkgId, UInt128} @@ -1929,7 +1928,7 @@ end end # finish loading module graph into staledeps # TODO: call all start_loading calls (in reverse order) before calling any _include_from_serialized, since start_loading will drop the loading lock - for i in 1:length(staledeps) + for i in eachindex(staledeps) dep = staledeps[i] dep isa Module && continue modpath, modkey, modbuild_id, modcachepath, modstaledeps, modocachepath = dep::Tuple{String, PkgId, UInt128, String, Vector{Any}, Union{Nothing, String}} diff --git a/base/multidimensional.jl b/base/multidimensional.jl index b4625c12620e3..bd3641db4999c 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1674,7 +1674,7 @@ function checkdims_perm(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, perm) wh length(perm) == N || throw(ArgumentError("expected permutation of size $N, but length(perm)=$(length(perm))")) isperm(perm) || throw(ArgumentError("input is not a permutation")) indsP = axes(P) - for i = 1:length(perm) + for i in eachindex(perm) indsP[i] == indsB[perm[i]] || throw(DimensionMismatch("destination tensor of incorrect size")) end nothing diff --git a/base/reflection.jl b/base/reflection.jl index 0af40a2e481a0..7f9772e5ec976 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -2425,7 +2425,7 @@ function hasmethod(f, t, kwnames::Tuple{Vararg{Symbol}}; world::UInt=get_world_c for kw in kws endswith(String(kw), "...") && return true end - kwnames = Symbol[kwnames[i] for i in 1:length(kwnames)] + kwnames = collect(kwnames) return issubset(kwnames, kws) end diff --git a/base/show.jl b/base/show.jl index 8db2826a2088c..cd8107f8c6125 100644 --- a/base/show.jl +++ b/base/show.jl @@ -681,7 +681,7 @@ function show_can_elide(p::TypeVar, wheres::Vector, elide::Int, env::SimpleVecto has_typevar(v.lb, p) && return false has_typevar(v.ub, p) && return false end - for i = 1:length(env) + for i = eachindex(env) i == skip && continue has_typevar(env[i], p) && return false end @@ -1188,7 +1188,7 @@ end function show_at_namedtuple(io::IO, syms::Tuple, types::DataType) first = true - for i in 1:length(syms) + for i in eachindex(syms) if !first print(io, ", ") end @@ -2382,7 +2382,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In if get(io, beginsym, false) print(io, '(') ind = indent + indent_width - for i = 1:length(ex.args) + for i = eachindex(ex.args) if i > 1 # if there was only a comment before the first semicolon, the expression would get parsed as a NamedTuple if !(i == 2 && ex.args[1] isa LineNumberNode) @@ -2904,7 +2904,7 @@ function dump(io::IOContext, x::SimpleVector, n::Int, indent) end print(io, "SimpleVector") if n > 0 - for i = 1:length(x) + for i in eachindex(x) println(io) print(io, indent, " ", i, ": ") if isassigned(x,i) @@ -3021,7 +3021,7 @@ function dump(io::IOContext, x::DataType, n::Int, indent) end fields = fieldnames(x) fieldtypes = datatype_fieldtypes(x) - for idx in 1:length(fields) + for idx in eachindex(fields) println(io) print(io, indent, " ") is_mut && isconst(x, idx) && print(io, "const ") diff --git a/base/tuple.jl b/base/tuple.jl index cc22ea75c041c..fc213410cfd7c 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -503,7 +503,7 @@ end _findfirst_rec(f, i::Int, ::Tuple{}) = nothing _findfirst_rec(f, i::Int, t::Tuple) = (@inline; f(first(t)) ? i : _findfirst_rec(f, i+1, tail(t))) function _findfirst_loop(f::Function, t) - for i in 1:length(t) + for i in eachindex(t) f(t[i]) && return i end return nothing @@ -537,7 +537,7 @@ function _isequal(t1::Tuple{Any,Vararg{Any}}, t2::Tuple{Any,Vararg{Any}}) return isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2)) end function _isequal(t1::Any32, t2::Any32) - for i = 1:length(t1) + for i in eachindex(t1, t2) if !isequal(t1[i], t2[i]) return false end @@ -568,7 +568,7 @@ function _eq_missing(t1::Tuple, t2::Tuple) end function _eq(t1::Any32, t2::Any32) anymissing = false - for i = 1:length(t1) + for i in eachindex(t1, t2) eq = (t1[i] == t2[i]) if ismissing(eq) anymissing = true From 2efcfd9829a898965978199c1fef9f831824f196 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Tue, 16 Jul 2024 21:47:18 +0200 Subject: [PATCH 010/206] Update the aarch64 devdocs to reflect the current state of its support (#55141) The devdocs here reflect a time when aarch64 was much less well supported, it also reference Cudadrv which has been archived for years --- doc/src/devdocs/build/arm.md | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/doc/src/devdocs/build/arm.md b/doc/src/devdocs/build/arm.md index 747ee25d22a04..df9ede07d270f 100644 --- a/doc/src/devdocs/build/arm.md +++ b/doc/src/devdocs/build/arm.md @@ -55,18 +55,9 @@ due to unsupported inline assembly. In that case, add `MCPU=armv7-a` to ## AArch64 (ARMv8) -Julia has been successfully built on the following ARMv8 devices: +Julia is expected to work and build on ARMv8 cpus. One should follow the general [build instructions](https://github.com/JuliaLang/julia/blob/master/README.md). Julia expects to have around 8GB of ram or swap enabled to build itself. -* [nVidia Jetson TX1 & TX2](https://www.nvidia.com/object/embedded-systems-dev-kits-modules.html); -* [X-Gene 1](https://www.apm.com/products/data-center/x-gene-family/x-gene/); -* [Overdrive 3000](https://softiron.com/products/overdrive-3000/); -* [Cavium ThunderX](https://www.cavium.com/ThunderX_ARM_Processors.html) on [packet.net](https://www.packet.net). - -Compilation on `ARMv8-A` requires that `Make.user` is configured as follows: - -``` -MCPU=armv8-a -``` +### Known issues Starting from Julia v1.10, [JITLink](https://llvm.org/docs/JITLink.html) is automatically enabled on this architecture for all operating systems when linking to LLVM 15 or later versions. Due to a [bug in LLVM memory manager](https://github.com/llvm/llvm-project/issues/63236), non-trivial workloads may generate too many memory mappings that on Linux can exceed the limit of memory mappings (`mmap`) set in the file `/proc/sys/vm/max_map_count`, resulting in an error like @@ -77,21 +68,3 @@ Should this happen, ask your system administrator to increase the limit of memor ``` sysctl -w vm.max_map_count=262144 ``` - -### nVidia Jetson TX2 - -Julia builds and runs on the [nVidia Jetson TX2](https://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) -platform with minimal configuration changes. - -After configuring `Make.user` as per the `AArch64` instructions in this document, -follow the general [build instructions](https://github.com/JuliaLang/julia/blob/master/README.md). -The majority of the build dependencies specified in the instructions are installed by -the default configuration flashed by [Jetpack 3.0](https://developer.nvidia.com/embedded/jetpack). The remaining tools can be installed by issuing the following command: - -``` -sudo apt-get install gfortran wget cmake -``` - -A full parallel build, including LLVM, -will complete in around two hours. All tests pass and CUDA functionality is available -through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). From 946301c108f6718018f7ef616e65af6ee52a47da Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:00:06 -0300 Subject: [PATCH 011/206] create separate function to spawn GC threads (#55108) Third-party GCs (e.g. MMTk) will probably have their own function to spawn GC threads. --- src/gc.c | 20 ++++++++++++++++++++ src/gc.h | 1 + src/init.c | 2 ++ src/julia_internal.h | 3 ++- src/threading.c | 26 ++++++++------------------ src/threading.h | 2 ++ 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/gc.c b/src/gc.c index 9ae3145e59c01..dbfd2d341cc69 100644 --- a/src/gc.c +++ b/src/gc.c @@ -3957,6 +3957,26 @@ void jl_free_thread_gc_state(jl_ptls_t ptls) arraylist_free(&mq->reclaim_set); } +void jl_start_gc_threads(void) +{ + int nthreads = jl_atomic_load_relaxed(&jl_n_threads); + int ngcthreads = jl_n_gcthreads; + int nmutator_threads = nthreads - ngcthreads; + uv_thread_t uvtid; + for (int i = nmutator_threads; i < nthreads; ++i) { + jl_threadarg_t *t = (jl_threadarg_t *)malloc_s(sizeof(jl_threadarg_t)); // ownership will be passed to the thread + t->tid = i; + t->barrier = &thread_init_done; + if (i == nthreads - 1 && jl_n_sweepthreads == 1) { + uv_thread_create(&uvtid, jl_concurrent_gc_threadfun, t); + } + else { + uv_thread_create(&uvtid, jl_parallel_gc_threadfun, t); + } + uv_thread_detach(&uvtid); + } +} + // System-wide initializations void jl_gc_init(void) { diff --git a/src/gc.h b/src/gc.h index c9803fa883414..b49f81a5a0c5a 100644 --- a/src/gc.h +++ b/src/gc.h @@ -572,6 +572,7 @@ extern uv_cond_t gc_threads_cond; extern uv_sem_t gc_sweep_assists_needed; extern _Atomic(int) gc_n_threads_marking; extern _Atomic(int) gc_n_threads_sweeping; +extern uv_barrier_t thread_init_done; void gc_mark_queue_all_roots(jl_ptls_t ptls, jl_gc_markqueue_t *mq); void gc_mark_finlist_(jl_gc_markqueue_t *mq, jl_value_t *fl_parent, jl_value_t **fl_begin, jl_value_t **fl_end) JL_NOTSAFEPOINT; void gc_mark_finlist(jl_gc_markqueue_t *mq, arraylist_t *list, size_t start) JL_NOTSAFEPOINT; diff --git a/src/init.c b/src/init.c index d2a9c625e871c..4362c33ccad0f 100644 --- a/src/init.c +++ b/src/init.c @@ -885,6 +885,8 @@ static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_ post_image_load_hooks(); } jl_start_threads(); + jl_start_gc_threads(); + uv_barrier_wait(&thread_init_done); jl_gc_enable(1); diff --git a/src/julia_internal.h b/src/julia_internal.h index 7187bfde5b6d8..3d9a693261feb 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -960,9 +960,10 @@ extern JL_DLLEXPORT ssize_t jl_tls_offset; extern JL_DLLEXPORT const int jl_tls_elf_support; void jl_init_threading(void); void jl_start_threads(void); -extern uv_mutex_t safepoint_lock; +void jl_start_gc_threads(void); // Whether the GC is running +extern uv_mutex_t safepoint_lock; extern char *jl_safepoint_pages; STATIC_INLINE int jl_addr_is_safepoint(uintptr_t addr) { diff --git a/src/threading.c b/src/threading.c index 6b2e62b299bb6..0c4e1ccf70eb0 100644 --- a/src/threading.c +++ b/src/threading.c @@ -761,7 +761,7 @@ void jl_init_threading(void) gc_first_tid = nthreads + nthreadsi; } -static uv_barrier_t thread_init_done; +uv_barrier_t thread_init_done; void jl_start_threads(void) { @@ -800,30 +800,20 @@ void jl_start_threads(void) uv_barrier_init(&thread_init_done, nthreads); // GC/System threads need to be after the worker threads. - int nworker_threads = nthreads - ngcthreads; + int nmutator_threads = nthreads - ngcthreads; - for (i = 1; i < nthreads; ++i) { + for (i = 1; i < nmutator_threads; ++i) { jl_threadarg_t *t = (jl_threadarg_t *)malloc_s(sizeof(jl_threadarg_t)); // ownership will be passed to the thread t->tid = i; t->barrier = &thread_init_done; - if (i < nworker_threads) { - uv_thread_create(&uvtid, jl_threadfun, t); - if (exclusive) { - mask[i] = 1; - uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize); - mask[i] = 0; - } - } - else if (i == nthreads - 1 && jl_n_sweepthreads == 1) { - uv_thread_create(&uvtid, jl_concurrent_gc_threadfun, t); - } - else { - uv_thread_create(&uvtid, jl_parallel_gc_threadfun, t); + uv_thread_create(&uvtid, jl_threadfun, t); + if (exclusive) { + mask[i] = 1; + uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize); + mask[i] = 0; } uv_thread_detach(&uvtid); } - - uv_barrier_wait(&thread_init_done); } _Atomic(unsigned) _threadedregion; // keep track of whether to prioritize IO or threading diff --git a/src/threading.h b/src/threading.h index 260ecffa30dd5..cb26537699713 100644 --- a/src/threading.h +++ b/src/threading.h @@ -12,6 +12,8 @@ extern "C" { #define PROFILE_JL_THREADING 0 +extern uv_barrier_t thread_init_done; + extern _Atomic(jl_ptls_t*) jl_all_tls_states JL_GLOBALLY_ROOTED; /* thread local storage */ typedef struct _jl_threadarg_t { From 1c7ce01376bde8a961b6ffd03282d5f6edd0358e Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:39:29 +0900 Subject: [PATCH 012/206] inference: add basic support for `:globaldecl` expressions (#55144) Following up #54773. Required for external abstract interpreters that may run inference on arbitrary top-level thunks. --- base/compiler/abstractinterpretation.jl | 2 ++ base/compiler/validation.jl | 1 + stdlib/REPL/test/replcompletions.jl | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 4c3286c7e2737..f34b1e716a271 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2705,6 +2705,8 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp elseif ehead === :gc_preserve_end || ehead === :leave || ehead === :pop_exception || ehead === :global || ehead === :popaliasscope return RTEffects(Nothing, Union{}, Effects(EFFECTS_TOTAL; effect_free=EFFECT_FREE_GLOBALLY)) + elseif ehead === :globaldecl + return RTEffects(Nothing, Any, EFFECTS_UNKNOWN) elseif ehead === :thunk return RTEffects(Any, Any, EFFECTS_UNKNOWN) end diff --git a/base/compiler/validation.jl b/base/compiler/validation.jl index ba8e86eeb042c..a9f2f1eebe1b5 100644 --- a/base/compiler/validation.jl +++ b/base/compiler/validation.jl @@ -22,6 +22,7 @@ const VALID_EXPR_HEADS = IdDict{Symbol,UnitRange{Int}}( :copyast => 1:1, :meta => 0:typemax(Int), :global => 1:1, + :globaldecl => 2:2, :foreigncall => 5:typemax(Int), # name, RT, AT, nreq, (cconv, effects), args..., roots... :cfunction => 5:5, :isdefined => 1:2, diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 0b8989a2b88dc..15e3de2668ba1 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -2391,3 +2391,8 @@ let (c, r, res) = test_complete_context("const xxx = Base.si", Main) @test res @test "sin" ∈ c end + +let (c, r, res) = test_complete_context("global xxx::Number = Base.", Main) + @test res + @test "pi" ∈ c +end From b049f93d7df22fb5b7708866e030b1774a02d7c4 Mon Sep 17 00:00:00 2001 From: lgeissbauer-btig <87755201+lgeissbauer-btig@users.noreply.github.com> Date: Wed, 17 Jul 2024 00:35:45 -0400 Subject: [PATCH 013/206] don't throw EOFError from sleep (#54955) --- base/asyncevent.jl | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/base/asyncevent.jl b/base/asyncevent.jl index 3c782be10e194..c6cb3d3fa73bb 100644 --- a/base/asyncevent.jl +++ b/base/asyncevent.jl @@ -127,8 +127,11 @@ function _trywait(t::Union{Timer, AsyncCondition}) t isa Timer || Core.Intrinsics.atomic_fence(:acquire_release) else if !isopen(t) - close(t) # wait for the close to complete - return false + set = t.set + if !set + close(t) # wait for the close to complete + return false + end end iolock_begin() set = t.set @@ -151,7 +154,7 @@ function _trywait(t::Union{Timer, AsyncCondition}) end iolock_end() end - @atomic :monotonic t.set = false + @atomic :monotonic t.set = false # if there are multiple waiters, an unspecified number may short-circuit past here return set end @@ -161,14 +164,14 @@ function wait(t::Union{Timer, AsyncCondition}) end -isopen(t::Union{Timer, AsyncCondition}) = t.isopen && t.handle != C_NULL +isopen(t::Union{Timer, AsyncCondition}) = @atomic :acquire t.isopen function close(t::Union{Timer, AsyncCondition}) - t.handle == C_NULL && return # short-circuit path + t.handle == C_NULL && !t.isopen && return # short-circuit path, :monotonic iolock_begin() if t.handle != C_NULL if t.isopen - @atomic :monotonic t.isopen = false + @atomic :release t.isopen = false ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t) end # implement _trywait here without the auto-reset function, just waiting for the final close signal @@ -186,6 +189,8 @@ function close(t::Union{Timer, AsyncCondition}) unlock(t.cond) unpreserve_handle(t) end + elseif t.isopen + @atomic :release t.isopen = false end iolock_end() nothing @@ -198,8 +203,8 @@ function uvfinalize(t::Union{Timer, AsyncCondition}) if t.handle != C_NULL disassociate_julia_struct(t.handle) # not going to call the usual close hooks anymore if t.isopen - @atomic :monotonic t.isopen = false - ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t.handle) + @atomic :release t.isopen = false + ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t.handle) # this will call Libc.free end @atomic :monotonic t.handle = C_NULL notify(t.cond, false) @@ -214,8 +219,10 @@ end function _uv_hook_close(t::Union{Timer, AsyncCondition}) lock(t.cond) try - @atomic :monotonic t.isopen = false - Libc.free(@atomicswap :monotonic t.handle = C_NULL) + handle = t.handle + @atomic :release t.isopen = false + @atomic :monotonic t.handle = C_NULL + Libc.free(handle) notify(t.cond, false) finally unlock(t.cond) @@ -243,7 +250,7 @@ function uv_timercb(handle::Ptr{Cvoid}) if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Cvoid},), t) == 0 # timer is stopped now if t.isopen - @atomic :monotonic t.isopen = false + @atomic :release t.isopen = false ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t) end end From 7c9a4658bcb39329a80279e8456bbac58ec9e94f Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:39:27 +0900 Subject: [PATCH 014/206] =?UTF-8?q?LinearAlgebra:=20use=20`=E2=89=88`=20in?= =?UTF-8?q?stead=20of=20`=3D=3D`=20for=20`tr`=20tests=20in=20symmetric.jl?= =?UTF-8?q?=20(#55143)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After investigating JuliaLang/julia#54090, I found that the issue was not caused by the effects of `checksquare`, but by the use of the `@simd` macro within `tr(::Matrix)`: https://github.com/JuliaLang/julia/blob/0945b9d7740855c82a09fed42fbf6bc561e02c77/stdlib/LinearAlgebra/src/dense.jl#L373-L380 While simply removing the `@simd` macro was considered, the strict left-to-right summation without `@simd` otherwise is not necessarily more accurate, so I concluded that the problem lies in the test code, which tests the (strict) equality of two different `tr` execution results. I have modified the test code to use `≈` instead of `==`. - fixes #54090 --- stdlib/LinearAlgebra/test/symmetric.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index 414b4ad5dd722..89e9ca0d6a51d 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -223,8 +223,8 @@ end @testset "linalg unary ops" begin @testset "tr" begin - @test tr(asym) == tr(Symmetric(asym)) - @test tr(aherm) == tr(Hermitian(aherm)) + @test tr(asym) ≈ tr(Symmetric(asym)) + @test tr(aherm) ≈ tr(Hermitian(aherm)) end @testset "isposdef[!]" begin From 695b22b427025fea7bf026457a6e2fe5f211d06b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 18 Jul 2024 11:16:55 -0500 Subject: [PATCH 015/206] Improve static compilabilaty of Printf (#55149) This makes small tweaks to "compiler hints" in Printf to reduce the number of runtime dispatches. For example, on `master` calling ``` prnt(a::AbstractString, b::AbstractFloat, c::Union{AbstractChar,AbstractString}) = @printf("%5s %12.5e %c\n", a, b, c) ``` results in 4 runtime-dispatches, whereas on this branch there is just 1 (which comes from not knowing the type of `Main.stdout`). This also removes a number of manual `@inline` annotations. These are on fairly large `fmt` methods, many of which have loops; forcing inlining seems likely to bloat the code without much benefit. --- stdlib/Printf/src/Printf.jl | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 9b636d1180598..fd38b3ebd3573 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -297,11 +297,11 @@ end @inline function rmdynamic(spec::Spec{T}, args, argp) where {T} zero, width, precision = spec.zero, spec.width, spec.precision if spec.dynamic_width - width = args[argp] + width = args[argp]::Integer argp += 1 end if spec.dynamic_precision - precision = args[argp] + precision = args[argp]::Integer if zero && T <: Ints && precision > 0 zero = false end @@ -310,12 +310,12 @@ end (Spec{T}(spec.leftalign, spec.plus, spec.space, zero, spec.hash, width, precision, false, false), argp) end -@inline function fmt(buf, pos, args, argp, spec::Spec{T}) where {T} +Base.@constprop :aggressive function fmt(buf, pos, args, argp, spec::Spec{T}) where {T} spec, argp = rmdynamic(spec, args, argp) (fmt(buf, pos, args[argp], spec), argp+1) end -@inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Chars} +function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Chars} leftalign, width = spec.leftalign, spec.width c = Char(first(arg)) w = textwidth(c) @@ -336,7 +336,7 @@ end end # strings -@inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Strings} +function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Strings} leftalign, hash, width, prec = spec.leftalign, spec.hash, spec.width, spec.precision str = string(arg) slen = textwidth(str)::Int + (hash ? arg isa AbstractString ? 2 : 1 : 0) @@ -383,7 +383,7 @@ toint(x::Rational) = Integer(x) fmt(buf, pos, arg::AbstractFloat, spec::Spec{T}) where {T <: Ints} = fmt(buf, pos, arg, floatfmt(spec)) -@inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Ints} +function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Ints} leftalign, plus, space, zero, hash, width, prec = spec.leftalign, spec.plus, spec.space, spec.zero, spec.hash, spec.width, spec.precision bs = base(T) @@ -497,7 +497,7 @@ _snprintf(ptr, siz, str, arg) = # seems like a dangerous thing to do. const __BIG_FLOAT_MAX__ = 8192 -@inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Floats} +function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Floats} leftalign, plus, space, zero, hash, width, prec = spec.leftalign, spec.plus, spec.space, spec.zero, spec.hash, spec.width, spec.precision x = tofloat(arg) @@ -931,7 +931,8 @@ for more details on C `printf` support. """ function format end -function format(io::IO, f::Format, args...) # => Nothing +# Since it will specialize on `f`, which has a Tuple-type often of length(args), we might as well specialize on `args` too. +function format(io::IO, f::Format, args::Vararg{Any,N}) where N # => Nothing f.numarguments == length(args) || argmismatch(f.numarguments, length(args)) buf = Base.StringVector(computelen(f.substringranges, f.formats, args)) pos = format(buf, 1, f, args...) @@ -939,7 +940,7 @@ function format(io::IO, f::Format, args...) # => Nothing return end -function format(f::Format, args...) # => String +function format(f::Format, args::Vararg{Any,N}) where N # => String f.numarguments == length(args) || argmismatch(f.numarguments, length(args)) buf = Base.StringVector(computelen(f.substringranges, f.formats, args)) pos = format(buf, 1, f, args...) From 45e10cd8c3b750c1e7fe0132a53f1e8bf0e2b6e5 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:39:15 -0300 Subject: [PATCH 016/206] NFC: encapsulate write barrier fast path emission into a single function (#55156) Third-party GCs (e.g. MMTk) will have their own write barrier fast path logic (e.g. may use different bit patterns to define what are young & old objects, etc.). Let's encapsulate the write-barrier fast emission code into a single function to make more explicit what parts of the `late-gc-lowering` code must be re-implemented when porting these third-party GCs into Julia. --- src/llvm-late-gc-lowering.cpp | 104 ++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 59886a134fd4e..65b8cdc5c7c05 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -352,6 +352,7 @@ struct LateLowerGCFrame: private JuliaPassContext { void PlaceGCFrameStore(State &S, unsigned R, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame, Instruction *InsertBefore); void PlaceGCFrameStores(State &S, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame); void PlaceRootsAndUpdateCalls(SmallVectorImpl &Colors, State &S, std::map>); + void CleanupWriteBarriers(Function &F, State *S, const SmallVector &WriteBarriers, bool *CFGModified); bool CleanupIR(Function &F, State *S, bool *CFGModified); void NoteUseChain(State &S, BBState &BBS, User *TheUser); SmallVector GetPHIRefinements(PHINode *phi, State &S); @@ -2320,6 +2321,59 @@ MDNode *createMutableTBAAAccessTag(MDNode *Tag) { return MDBuilder(Tag->getContext()).createMutableTBAAAccessTag(Tag); } +void LateLowerGCFrame::CleanupWriteBarriers(Function &F, State *S, const SmallVector &WriteBarriers, bool *CFGModified) { + auto T_size = F.getParent()->getDataLayout().getIntPtrType(F.getContext()); + for (auto CI : WriteBarriers) { + auto parent = CI->getArgOperand(0); + if (std::all_of(CI->op_begin() + 1, CI->op_end(), + [parent, &S](Value *child) { return parent == child || IsPermRooted(child, S); })) { + CI->eraseFromParent(); + continue; + } + if (CFGModified) { + *CFGModified = true; + } + auto DebugInfoMeta = F.getParent()->getModuleFlag("julia.debug_level"); + int debug_info = 1; + if (DebugInfoMeta != nullptr) { + debug_info = cast(cast(DebugInfoMeta)->getValue())->getZExtValue(); + } + + IRBuilder<> builder(CI); + builder.SetCurrentDebugLocation(CI->getDebugLoc()); + auto parBits = builder.CreateAnd(EmitLoadTag(builder, T_size, parent), GC_OLD_MARKED); + setName(parBits, "parent_bits", debug_info); + auto parOldMarked = builder.CreateICmpEQ(parBits, ConstantInt::get(T_size, GC_OLD_MARKED)); + setName(parOldMarked, "parent_old_marked", debug_info); + auto mayTrigTerm = SplitBlockAndInsertIfThen(parOldMarked, CI, false); + builder.SetInsertPoint(mayTrigTerm); + setName(mayTrigTerm->getParent(), "may_trigger_wb", debug_info); + Value *anyChldNotMarked = NULL; + for (unsigned i = 1; i < CI->arg_size(); i++) { + Value *child = CI->getArgOperand(i); + Value *chldBit = builder.CreateAnd(EmitLoadTag(builder, T_size, child), GC_MARKED); + setName(chldBit, "child_bit", debug_info); + Value *chldNotMarked = builder.CreateICmpEQ(chldBit, ConstantInt::get(T_size, 0),"child_not_marked"); + setName(chldNotMarked, "child_not_marked", debug_info); + anyChldNotMarked = anyChldNotMarked ? builder.CreateOr(anyChldNotMarked, chldNotMarked) : chldNotMarked; + } + assert(anyChldNotMarked); // handled by all_of test above + MDBuilder MDB(parent->getContext()); + SmallVector Weights{1, 9}; + auto trigTerm = SplitBlockAndInsertIfThen(anyChldNotMarked, mayTrigTerm, false, + MDB.createBranchWeights(Weights)); + setName(trigTerm->getParent(), "trigger_wb", debug_info); + builder.SetInsertPoint(trigTerm); + if (CI->getCalledOperand() == write_barrier_func) { + builder.CreateCall(getOrDeclare(jl_intrinsics::queueGCRoot), parent); + } + else { + assert(false); + } + CI->eraseFromParent(); + } +} + bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { auto T_int32 = Type::getInt32Ty(F.getContext()); auto T_size = F.getParent()->getDataLayout().getIntPtrType(F.getContext()); @@ -2565,55 +2619,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) { ChangesMade = true; } } - for (auto CI : write_barriers) { - auto parent = CI->getArgOperand(0); - if (std::all_of(CI->op_begin() + 1, CI->op_end(), - [parent, &S](Value *child) { return parent == child || IsPermRooted(child, S); })) { - CI->eraseFromParent(); - continue; - } - if (CFGModified) { - *CFGModified = true; - } - auto DebugInfoMeta = F.getParent()->getModuleFlag("julia.debug_level"); - int debug_info = 1; - if (DebugInfoMeta != nullptr) { - debug_info = cast(cast(DebugInfoMeta)->getValue())->getZExtValue(); - } - - IRBuilder<> builder(CI); - builder.SetCurrentDebugLocation(CI->getDebugLoc()); - auto parBits = builder.CreateAnd(EmitLoadTag(builder, T_size, parent), GC_OLD_MARKED); - setName(parBits, "parent_bits", debug_info); - auto parOldMarked = builder.CreateICmpEQ(parBits, ConstantInt::get(T_size, GC_OLD_MARKED)); - setName(parOldMarked, "parent_old_marked", debug_info); - auto mayTrigTerm = SplitBlockAndInsertIfThen(parOldMarked, CI, false); - builder.SetInsertPoint(mayTrigTerm); - setName(mayTrigTerm->getParent(), "may_trigger_wb", debug_info); - Value *anyChldNotMarked = NULL; - for (unsigned i = 1; i < CI->arg_size(); i++) { - Value *child = CI->getArgOperand(i); - Value *chldBit = builder.CreateAnd(EmitLoadTag(builder, T_size, child), GC_MARKED); - setName(chldBit, "child_bit", debug_info); - Value *chldNotMarked = builder.CreateICmpEQ(chldBit, ConstantInt::get(T_size, 0),"child_not_marked"); - setName(chldNotMarked, "child_not_marked", debug_info); - anyChldNotMarked = anyChldNotMarked ? builder.CreateOr(anyChldNotMarked, chldNotMarked) : chldNotMarked; - } - assert(anyChldNotMarked); // handled by all_of test above - MDBuilder MDB(parent->getContext()); - SmallVector Weights{1, 9}; - auto trigTerm = SplitBlockAndInsertIfThen(anyChldNotMarked, mayTrigTerm, false, - MDB.createBranchWeights(Weights)); - setName(trigTerm->getParent(), "trigger_wb", debug_info); - builder.SetInsertPoint(trigTerm); - if (CI->getCalledOperand() == write_barrier_func) { - builder.CreateCall(getOrDeclare(jl_intrinsics::queueGCRoot), parent); - } - else { - assert(false); - } - CI->eraseFromParent(); - } + CleanupWriteBarriers(F, S, write_barriers, CFGModified); if (maxframeargs == 0 && Frame) { Frame->eraseFromParent(); } From 1fc9fe1219d602bba82e14dc2ad999d072de236f Mon Sep 17 00:00:00 2001 From: Lucas C Wilcox Date: Thu, 18 Jul 2024 11:57:17 -0700 Subject: [PATCH 017/206] Make warn missed transformations pass optional (#54871) This makes the `WarnMissedTransformationsPass` compiler pass optional and off by default. --- src/jitlayers.h | 6 ++++-- src/pipeline.cpp | 10 +++++++--- test/misc.jl | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/jitlayers.h b/src/jitlayers.h index 393e6d81e418d..1eea3692aec71 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -90,6 +90,7 @@ struct OptimizationOptions { bool enable_vector_pipeline; bool remove_ni; bool cleanup; + bool warn_missed_transformations; static constexpr OptimizationOptions defaults( bool lower_intrinsics=true, @@ -103,12 +104,13 @@ struct OptimizationOptions { bool enable_loop_optimizations=true, bool enable_vector_pipeline=true, bool remove_ni=true, - bool cleanup=true) { + bool cleanup=true, + bool warn_missed_transformations=false) { return {lower_intrinsics, dump_native, external_use, llvm_only, always_inline, enable_early_simplifications, enable_early_optimizations, enable_scalar_optimizations, enable_loop_optimizations, enable_vector_pipeline, - remove_ni, cleanup}; + remove_ni, cleanup, warn_missed_transformations}; } }; diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 7704336045ad9..f0dde6aa59a40 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -609,7 +609,8 @@ static void buildPipeline(ModulePassManager &MPM, PassBuilder *PB, OptimizationL if (O.getSpeedupLevel() >= 2) { buildVectorPipeline(FPM, PB, O, options); } - FPM.addPass(WarnMissedTransformationsPass()); + if (options.warn_missed_transformations) + FPM.addPass(WarnMissedTransformationsPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } buildIntrinsicLoweringPipeline(MPM, PB, O, options); @@ -632,6 +633,7 @@ struct PipelineConfig { int enable_vector_pipeline; int remove_ni; int cleanup; + int warn_missed_transformations; }; extern "C" JL_DLLEXPORT_CODEGEN void jl_build_newpm_pipeline_impl(void *MPM, void *PB, PipelineConfig* config) JL_NOTSAFEPOINT @@ -672,7 +674,8 @@ extern "C" JL_DLLEXPORT_CODEGEN void jl_build_newpm_pipeline_impl(void *MPM, voi !!config->enable_loop_optimizations, !!config->enable_vector_pipeline, !!config->remove_ni, - !!config->cleanup}); + !!config->cleanup, + !!config->warn_missed_transformations}); } #undef JULIA_PASS @@ -870,7 +873,8 @@ static Optional> parseJuliaPip OPTION(lower_intrinsics), OPTION(dump_native), OPTION(external_use), - OPTION(llvm_only) + OPTION(llvm_only), + OPTION(warn_missed_transformations) #undef OPTION }; while (!name.empty()) { diff --git a/test/misc.jl b/test/misc.jl index 3ad58a96a0bbd..5d11cf889858e 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1557,3 +1557,23 @@ end @testset "Base.Libc docstrings" begin @test isempty(Docs.undocumented_names(Libc)) end + +@testset "Silenced missed transformations" begin + # Ensure the WarnMissedTransformationsPass is not on by default + src = """ + @noinline iteration(i) = (@show(i); return nothing) + @eval function loop_unroll_full_fail(N) + for i in 1:N + iteration(i) + \$(Expr(:loopinfo, (Symbol("llvm.loop.unroll.full"), 1))) + end + end + loop_unroll_full_fail(3) + """ + out_err = mktemp() do _, f + run(`$(Base.julia_cmd()) -e "$src"`, devnull, devnull, f) + seekstart(f) + read(f, String) + end + @test !occursin("loop not unrolled", out_err) +end From d56323189b32f1d4327a84fccdb273e60be2e973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nero=20Blackstone=E2=80=8B?= Date: Fri, 19 Jul 2024 03:07:35 +0800 Subject: [PATCH 018/206] Add `Base.Broadcast.BroadcastFunction` to docs (#54820) --- doc/src/base/arrays.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index b01540d35def4..ccfb23715c476 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -79,6 +79,7 @@ to operate on arrays, you should use `sin.(a)` to vectorize via `broadcast`. Base.broadcast Base.Broadcast.broadcast! Base.@__dot__ +Base.Broadcast.BroadcastFunction ``` For specializing broadcast on custom types, see From d4362e43d1affa5ea9e8d3afffd54155bfefc7b6 Mon Sep 17 00:00:00 2001 From: Simeon David Schaub Date: Thu, 18 Jul 2024 22:53:31 +0200 Subject: [PATCH 019/206] merge unions of vararg tuples (#55123) Normalize unions such as `Union{Tuple{}, Tuple{T}, Tuple{T, T, Vararg{T}}` to `Tuple{Vararg{T}}`. This should make certain sutyping queries more precise. fixes #54746 --- src/jltypes.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ test/core.jl | 8 ++++++++ 2 files changed, 56 insertions(+) diff --git a/src/jltypes.c b/src/jltypes.c index 78ecb9231df7e..b8a81f94a7931 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -594,6 +594,52 @@ static int simple_subtype(jl_value_t *a, jl_value_t *b, int hasfree, int isUnion return 0; } +// merge Union{Tuple{}, Tuple{T}, Tuple{T, T, Vararg{T}}} into Tuple{Vararg{T}} +// assumes temp is already sorted by number of type parameters +STATIC_INLINE void merge_vararg_unions(jl_value_t **temp, size_t nt) +{ + for (size_t i = nt-1; i > 0; i--) { + // match types of form Tuple{T, ..., Vararg{T}} + jl_value_t *tt = temp[i]; + if (!(tt && jl_is_tuple_type(tt))) continue; + size_t nfields = jl_nparams(tt); + if (nfields <= 1) continue; + jl_value_t *va = jl_tparam(tt, nfields-1); + if (jl_vararg_kind(va) != JL_VARARG_UNBOUND) continue; + jl_value_t *t = jl_unwrap_vararg(va); + for (size_t j = 0; j < nfields-1; j++) + if (!jl_egal(jl_tparam(tt, j), t)) goto outer_loop; + + // look for Tuple{T, T, ...} then Tuple{T, ...}, etc + size_t min_elements = nfields-1; + for (long j = i-1; j >= 0; j--) { + jl_value_t *ttj = temp[j]; + if (!jl_is_tuple_type(ttj)) break; + size_t nfieldsj = jl_nparams(ttj); + if (nfieldsj >= min_elements) continue; + if (nfieldsj != min_elements-1) break; + for (size_t k = 0; k < nfieldsj; k++) + if (!jl_egal(jl_tparam(ttj, k), t)) goto inner_loop; + + temp[j] = NULL; + min_elements--; + inner_loop: + continue; + } + + if (min_elements == nfields-1) continue; + jl_value_t** params; + JL_GC_PUSHARGS(params, min_elements+1); + for (size_t j = 0; j < min_elements; j++) + params[j] = t; + params[min_elements] = va; + temp[i] = jl_apply_type((jl_value_t*)jl_tuple_type, params, min_elements+1); + JL_GC_POP(); + outer_loop: + continue; + } +} + JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) { if (n == 0) @@ -625,6 +671,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) } } isort_union(temp, nt); + merge_vararg_unions(temp, nt); jl_value_t **ptu = &temp[nt]; *ptu = jl_bottom_type; int k; @@ -730,6 +777,7 @@ jl_value_t *simple_union(jl_value_t *a, jl_value_t *b) } } isort_union(temp, nt); + merge_vararg_unions(temp, nt); temp[nt] = jl_bottom_type; size_t k; for (k = nt; k-- > 0; ) { diff --git a/test/core.jl b/test/core.jl index 8b0328659ae39..3a3f6e6d1b6cd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8253,3 +8253,11 @@ let load_path = mktempdir() end end end + +# merging va tuple unions +@test Tuple === Union{Tuple{},Tuple{Any,Vararg}} +@test Tuple{Any,Vararg} === Union{Tuple{Any},Tuple{Any,Any,Vararg}} +@test Core.Compiler.return_type(Base.front, Tuple{Tuple{Int,Vararg{Int}}}) === Tuple{Vararg{Int}} +@test Tuple{Vararg{Int}} === Union{Tuple{Int}, Tuple{}, Tuple{Int, Int, Vararg{Int}}} +@test (Tuple{Vararg{T}} where T) === (Union{Tuple{T, T, Vararg{T}}, Tuple{}, Tuple{T}} where T) +@test_broken (Tuple{Vararg{T}} where T) === Union{Tuple{T, T, Vararg{T}} where T, Tuple{}, Tuple{T} where T} From 0e6d7972c62eb1dedaf00ea9b966a0060e2effb8 Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Fri, 19 Jul 2024 01:22:28 +0200 Subject: [PATCH 020/206] Clean up some docs issues (#55139) - #55055: Remove incorrect BoundsError mention from iterate(string) docs. - #54686: Document the else keyword in the try/catch docs. Closes #55055. Closes #54686. --- base/docs/basedocs.jl | 14 ++++++++++++++ base/strings/basic.jl | 5 ++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 19bafbe3de3a4..37804d1d9a380 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1050,6 +1050,17 @@ exception object to the given variable within the `catch` block. The power of the `try`/`catch` construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions. +A `try/catch` block can also have an `else` clause that executes only if no exception occurred: +```julia +try + a_dangerous_operation() +catch + @warn "The operation failed." +else + @info "The operation succeeded." +end +``` + A `try` or `try`/`catch` block can also have a [`finally`](@ref) clause that executes at the end, regardless of whether an exception occurred. For example, this can be used to guarantee that an opened file is closed: @@ -1064,6 +1075,9 @@ finally end ``` (`finally` can also be used without a `catch` block.) + +!!! compat "Julia 1.8" + Else clauses require at least Julia 1.8. """ kw"try", kw"catch" diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 2d5f0cea26e36..bf11199143c1e 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -146,9 +146,8 @@ Stacktrace: Return a tuple of the character in `s` at index `i` with the index of the start of the following character in `s`. This is the key method that allows strings to -be iterated, yielding a sequences of characters. If `i` is out of bounds in `s` -then a bounds error is raised. The `iterate` function, as part of the iteration -protocol may assume that `i` is the start of a character in `s`. +be iterated, yielding a sequences of characters. The `iterate` function, as part +of the iteration protocol may assume that `i` is the start of a character in `s`. See also [`getindex`](@ref), [`checkbounds`](@ref). """ From b451a1c6c3e78ce1d3c93a890ef8da697ec9b760 Mon Sep 17 00:00:00 2001 From: Cameron Pfiffer Date: Fri, 19 Jul 2024 08:00:56 -0700 Subject: [PATCH 021/206] Very minor doc correction (#55173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a period to the logging docs. That's it 👍🏼 --- base/logging/logging.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/logging/logging.jl b/base/logging/logging.jl index 7124ffe25abf2..c50f581db89ba 100644 --- a/base/logging/logging.jl +++ b/base/logging/logging.jl @@ -60,7 +60,7 @@ function min_enabled_level end catch_exceptions(logger) Return `true` if the logger should catch exceptions which happen during log -record construction. By default, messages are caught +record construction. By default, messages are caught. By default all exceptions are caught to prevent log message generation from crashing the program. This lets users confidently toggle little-used From 500288c33c75440e0f01fd7745e9c86559e71631 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 19 Jul 2024 14:59:51 -0400 Subject: [PATCH 022/206] Profile: make profile listener init a separate function (#55167) I noticed this was an unrelated change in https://github.com/JuliaLang/julia/pull/55047 so I thought I'd separate it out --- base/Base.jl | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index e92fa9efbd387..a8685aa8cc52c 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -614,6 +614,25 @@ function profile_printing_listener(cond::Base.AsyncCondition) nothing end +function start_profile_listener() + cond = Base.AsyncCondition() + Base.uv_unref(cond.handle) + t = errormonitor(Threads.@spawn(profile_printing_listener(cond))) + atexit() do + # destroy this callback when exiting + ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), C_NULL) + # this will prompt any ongoing or pending event to flush also + close(cond) + # error-propagation is not needed, since the errormonitor will handle printing that better + _wait(t) + end + finalizer(cond) do c + # if something goes south, still make sure we aren't keeping a reference in C to this + ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), C_NULL) + end + ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), cond.handle) +end + function __init__() # Base library init global _atexit_hooks_finished = false @@ -636,22 +655,7 @@ function __init__() # Profiling helper @static if !Sys.iswindows() # triggering a profile via signals is not implemented on windows - cond = Base.AsyncCondition() - Base.uv_unref(cond.handle) - t = errormonitor(Threads.@spawn(profile_printing_listener(cond))) - atexit() do - # destroy this callback when exiting - ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), C_NULL) - # this will prompt any ongoing or pending event to flush also - close(cond) - # error-propagation is not needed, since the errormonitor will handle printing that better - _wait(t) - end - finalizer(cond) do c - # if something goes south, still make sure we aren't keeping a reference in C to this - ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), C_NULL) - end - ccall(:jl_set_peek_cond, Cvoid, (Ptr{Cvoid},), cond.handle) + start_profile_listener() end _require_world_age[] = get_world_counter() # Prevent spawned Julia process from getting stuck waiting on Tracy to connect. From 3290904379766c37796016180993c19c34c8c31a Mon Sep 17 00:00:00 2001 From: mikmoore <95002244+mikmoore@users.noreply.github.com> Date: Fri, 19 Jul 2024 18:09:17 -0600 Subject: [PATCH 023/206] Compat for `Base.@nospecializeinfer` (#55178) This macro was added in v1.10 but was missing a compat notice. --- base/expr.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/expr.jl b/base/expr.jl index 8f84883fa2623..7d723c3f940d7 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -850,6 +850,9 @@ while it can not infer the concrete return type of it. Without the `@nospecializeinfer`, `f([1.0])` would infer the return type of `g` as `Float64`, indicating that inference ran for `g(::Vector{Float64})` despite the prohibition on specialized code generation. + +!!! compat "Julia 1.10" + Using `Base.@nospecializeinfer` requires Julia version 1.10. """ macro nospecializeinfer(ex) esc(isa(ex, Expr) ? pushmeta!(ex, :nospecializeinfer) : ex) From 04af4460e6863c5bf4e5c5e01a389d5fb39e56d4 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sat, 20 Jul 2024 23:01:59 +0530 Subject: [PATCH 024/206] Update README.md (#55183) Remove external resources to avoid cluttering the landing page. --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 535d969cb6662..50487c56064d2 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,8 @@ New developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md) helpful to start contributing to the Julia codebase. -### External Resources +### Learning Julia -- [**StackOverflow**](https://stackoverflow.com/questions/tagged/julia-lang) -- [**Twitter**](https://twitter.com/JuliaLanguage) - [**Learning resources**](https://julialang.org/learning/) ## Binary Installation From 680c7e3869a0d9da494bdface2efe058c2987b98 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 21 Jul 2024 04:27:41 +0530 Subject: [PATCH 025/206] Update stable version number in Readme to v1.10.4 (#55186) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50487c56064d2..bd9e9b9c0bd02 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ and then use the command prompt to change into the resulting julia directory. By Julia. However, most users should use the [most recent stable version](https://github.com/JuliaLang/julia/releases) of Julia. You can get this version by running: - git checkout v1.10.3 + git checkout v1.10.4 To build the `julia` executable, run `make` from within the julia directory. From 43df7fb6722a18f1e4f9a4649be664b23af6a0d5 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sun, 21 Jul 2024 18:41:13 -0400 Subject: [PATCH 026/206] compat notice for a[begin] indexing (#55197) `a[begin]` indexing was added by #35779 in Julia 1.6, so this feature needs a compat notice in the docstring. --- base/docs/basedocs.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 37804d1d9a380..ad9c2e67fa917 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1386,7 +1386,11 @@ Usually `begin` will not be necessary, since keywords such as [`function`](@ref) implicitly begin blocks of code. See also [`;`](@ref). `begin` may also be used when indexing to represent the first index of a -collection or the first index of a dimension of an array. +collection or the first index of a dimension of an array. For example, +`a[begin]` is the first element of an array `a`. + +!!! compat "Julia 1.6" + Use of `begin` as an index requires Julia 1.6 or later. # Examples ```jldoctest From 775c0da5904728c8571616f01ad3c6f3869d87b1 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Mon, 22 Jul 2024 00:41:47 +0100 Subject: [PATCH 027/206] Remove assumption in gc that MAX_ALIGN can only be as high as 8 (#55195) Split out from #54848 where this is necessary as `MAX_ALIGN` is now 16 on x86. Similar change to #34554. --- src/julia_internal.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/julia_internal.h b/src/julia_internal.h index 3d9a693261feb..19fb851686338 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -405,7 +405,7 @@ static const int jl_gc_sizeclasses[] = { #ifdef GC_SMALL_PAGE #ifdef _P64 # define JL_GC_N_POOLS 39 -#elif MAX_ALIGN == 8 +#elif MAX_ALIGN > 4 # define JL_GC_N_POOLS 40 #else # define JL_GC_N_POOLS 41 @@ -413,7 +413,7 @@ static const int jl_gc_sizeclasses[] = { #else #ifdef _P64 # define JL_GC_N_POOLS 49 -#elif MAX_ALIGN == 8 +#elif MAX_ALIGN > 4 # define JL_GC_N_POOLS 50 #else # define JL_GC_N_POOLS 51 @@ -428,7 +428,7 @@ STATIC_INLINE int jl_gc_alignment(size_t sz) JL_NOTSAFEPOINT #ifdef _P64 (void)sz; return 16; -#elif MAX_ALIGN == 8 +#elif MAX_ALIGN > 4 return sz <= 4 ? 8 : 16; #else // szclass 8 @@ -460,7 +460,7 @@ STATIC_INLINE uint8_t JL_CONST_FUNC jl_gc_szclass(unsigned sz) JL_NOTSAFEPOINT if (sz <= 8) return 0; const int N = 0; -#elif MAX_ALIGN == 8 +#elif MAX_ALIGN > 4 if (sz <= 8) return (sz >= 4 ? 1 : 0); const int N = 1; @@ -478,7 +478,7 @@ STATIC_INLINE uint8_t JL_CONST_FUNC jl_gc_szclass_align8(unsigned sz) JL_NOTSAFE if (sz >= 16 && sz <= 152) { #ifdef _P64 const int N = 0; -#elif MAX_ALIGN == 8 +#elif MAX_ALIGN > 4 const int N = 1; #else const int N = 2; From a1e0f5d921c97d279efac769fa30dbc02c06d7b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Thi=C3=A9baut?= Date: Mon, 22 Jul 2024 03:06:47 +0200 Subject: [PATCH 028/206] Preserve Git objects from being garbage collected (#55142) This issue has been discussed [here](https://discourse.julialang.org/t/preserve-against-garbage-collection-in-libgit2/117095). In most cases, thanks to the specialization of `Base.unsafe_convert`, it is sufficient to replace `obj.ptr` by `obj` in `ccalls` to fix the issue. In other cases, for example when a pointer to an internal string is returned, the code has to be wrapped in `GC.https://github.com/preserve obj begin ... end` block. All `LibGit2` tests run successfully. I have left a few `FIXME` comments where I have doubts about the code, notably with `Ptr{Ptr{Cvoid}}` arguments. --- stdlib/LibGit2/src/blame.jl | 4 +- stdlib/LibGit2/src/blob.jl | 8 ++-- stdlib/LibGit2/src/commit.jl | 22 +++++----- stdlib/LibGit2/src/config.jl | 38 +++++++++--------- stdlib/LibGit2/src/diff.jl | 26 ++++++------ stdlib/LibGit2/src/index.jl | 20 ++++----- stdlib/LibGit2/src/merge.jl | 28 +++++++------ stdlib/LibGit2/src/oid.jl | 6 +-- stdlib/LibGit2/src/rebase.jl | 14 +++---- stdlib/LibGit2/src/reference.jl | 40 +++++++++--------- stdlib/LibGit2/src/remote.jl | 62 +++++++++++++++------------- stdlib/LibGit2/src/repository.jl | 69 ++++++++++++++++++-------------- stdlib/LibGit2/src/signature.jl | 3 +- stdlib/LibGit2/src/status.jl | 6 +-- stdlib/LibGit2/src/tag.jl | 6 +-- stdlib/LibGit2/src/tree.jl | 16 ++++---- stdlib/LibGit2/src/types.jl | 8 ++-- stdlib/LibGit2/src/walker.jl | 12 +++--- 18 files changed, 208 insertions(+), 180 deletions(-) diff --git a/stdlib/LibGit2/src/blame.jl b/stdlib/LibGit2/src/blame.jl index 89071ea9c6f79..e441189bdd423 100644 --- a/stdlib/LibGit2/src/blame.jl +++ b/stdlib/LibGit2/src/blame.jl @@ -13,7 +13,7 @@ function GitBlame(repo::GitRepo, path::AbstractString; options::BlameOptions=Bla blame_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_blame_file, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Ptr{BlameOptions}), - blame_ptr_ptr, repo.ptr, path, Ref(options)) + blame_ptr_ptr, repo, path, Ref(options)) return GitBlame(repo, blame_ptr_ptr[]) end @@ -27,7 +27,7 @@ that function later. """ function counthunks(blame::GitBlame) ensure_initialized() - return ccall((:git_blame_get_hunk_count, libgit2), Int32, (Ptr{Cvoid},), blame.ptr) + return ccall((:git_blame_get_hunk_count, libgit2), Int32, (Ptr{Cvoid},), blame) end function Base.getindex(blame::GitBlame, i::Integer) diff --git a/stdlib/LibGit2/src/blob.jl b/stdlib/LibGit2/src/blob.jl index 1941989b5f529..af1a16574b51e 100644 --- a/stdlib/LibGit2/src/blob.jl +++ b/stdlib/LibGit2/src/blob.jl @@ -2,7 +2,7 @@ function Base.length(blob::GitBlob) ensure_initialized() - return ccall((:git_blob_rawsize, libgit2), Int64, (Ptr{Cvoid},), blob.ptr) + return ccall((:git_blob_rawsize, libgit2), Int64, (Ptr{Cvoid},), blob) end """ @@ -20,7 +20,7 @@ is binary and not valid Unicode. """ function rawcontent(blob::GitBlob) ensure_initialized() - ptr = ccall((:git_blob_rawcontent, libgit2), Ptr{UInt8}, (Ptr{Cvoid},), blob.ptr) + ptr = ccall((:git_blob_rawcontent, libgit2), Ptr{UInt8}, (Ptr{Cvoid},), blob) copy(unsafe_wrap(Array, ptr, (length(blob),), own = false)) end @@ -47,7 +47,7 @@ the first 8000 bytes. """ function isbinary(blob::GitBlob) ensure_initialized() - bin_flag = ccall((:git_blob_is_binary, libgit2), Cint, (Ptr{Cvoid},), blob.ptr) + bin_flag = ccall((:git_blob_is_binary, libgit2), Cint, (Ptr{Cvoid},), blob) return bin_flag == 1 end @@ -69,7 +69,7 @@ function addblob!(repo::GitRepo, path::AbstractString) id_ref = Ref{GitHash}() @check ccall((:git_blob_create_from_disk, libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring), - id_ref, repo.ptr, path) + id_ref, repo, path) return id_ref[] end diff --git a/stdlib/LibGit2/src/commit.jl b/stdlib/LibGit2/src/commit.jl index ceb56ee45d3b7..d76a31791e4c4 100644 --- a/stdlib/LibGit2/src/commit.jl +++ b/stdlib/LibGit2/src/commit.jl @@ -73,16 +73,18 @@ function commit(repo::GitRepo, ensure_initialized() commit_id_ptr = Ref(GitHash()) nparents = length(parents) - parentptrs = Ptr{Cvoid}[c.ptr for c in parents] - @check ccall((:git_commit_create, libgit2), Cint, - (Ptr{GitHash}, Ptr{Cvoid}, Ptr{UInt8}, - Ptr{SignatureStruct}, Ptr{SignatureStruct}, - Ptr{UInt8}, Ptr{UInt8}, Ptr{Cvoid}, - Csize_t, Ptr{Ptr{Cvoid}}), - commit_id_ptr, repo.ptr, isempty(refname) ? C_NULL : refname, - author.ptr, committer.ptr, - C_NULL, msg, tree.ptr, - nparents, nparents > 0 ? parentptrs : C_NULL) + GC.@preserve parents begin + parentptrs = Ptr{Cvoid}[c.ptr for c in parents] + @check ccall((:git_commit_create, libgit2), Cint, + (Ptr{GitHash}, Ptr{Cvoid}, Ptr{UInt8}, + Ptr{SignatureStruct}, Ptr{SignatureStruct}, + Ptr{UInt8}, Ptr{UInt8}, Ptr{Cvoid}, + Csize_t, Ptr{Ptr{Cvoid}}), + commit_id_ptr, repo, isempty(refname) ? C_NULL : refname, + author, committer, + C_NULL, msg, tree, + nparents, nparents > 0 ? parentptrs : C_NULL) + end return commit_id_ptr[] end diff --git a/stdlib/LibGit2/src/config.jl b/stdlib/LibGit2/src/config.jl index affe881abde08..0bee705259ca6 100644 --- a/stdlib/LibGit2/src/config.jl +++ b/stdlib/LibGit2/src/config.jl @@ -35,7 +35,7 @@ function GitConfig(repo::GitRepo) ensure_initialized() cfg_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_config, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), cfg_ptr_ptr, repo.ptr) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), cfg_ptr_ptr, repo) return GitConfig(repo, cfg_ptr_ptr[]) end @@ -58,7 +58,7 @@ function GitConfig(level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_DEFAULT) try @check ccall((:git_config_open_level, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), - glb_cfg_ptr_ptr, cfg.ptr, Cint(level)) + glb_cfg_ptr_ptr, cfg, Cint(level)) cfg = GitConfig(glb_cfg_ptr_ptr[]) finally close(tmpcfg) @@ -91,13 +91,13 @@ function addfile(cfg::GitConfig, path::AbstractString, ensure_initialized() @static if LibGit2.VERSION >= v"0.27.0" @check ccall((:git_config_add_file_ondisk, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Cstring, Cint, Ptr{Cvoid}, Cint), - cfg.ptr, path, Cint(level), isa(repo, GitRepo) ? repo.ptr : C_NULL, Cint(force)) + (Ptr{Cvoid}, Cstring, Cint, Ptr{Cvoid}, Cint), + cfg, path, Cint(level), isa(repo, GitRepo) ? repo : C_NULL, Cint(force)) else repo === nothing || error("repo argument is not supported in this version of LibGit2") @check ccall((:git_config_add_file_ondisk, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Cstring, Cint, Cint), - cfg.ptr, path, Cint(level), Cint(force)) + (Ptr{Cvoid}, Cstring, Cint, Cint), + cfg, path, Cint(level), Cint(force)) end end @@ -105,7 +105,7 @@ function get(::Type{<:AbstractString}, c::GitConfig, name::AbstractString) ensure_initialized() buf_ref = Ref(Buffer()) @check ccall((:git_config_get_string_buf, libgit2), Cint, - (Ptr{Buffer}, Ptr{Cvoid}, Cstring), buf_ref, c.ptr, name) + (Ptr{Buffer}, Ptr{Cvoid}, Cstring), buf_ref, c, name) buf = buf_ref[] str = unsafe_string(buf.ptr, buf.size) free(buf_ref) @@ -116,7 +116,7 @@ function get(::Type{Bool}, c::GitConfig, name::AbstractString) ensure_initialized() val_ptr = Ref(Cint(0)) @check ccall((:git_config_get_bool, libgit2), Cint, - (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) + (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c, name) return Bool(val_ptr[]) end @@ -124,7 +124,7 @@ function get(::Type{Int32}, c::GitConfig, name::AbstractString) ensure_initialized() val_ptr = Ref(Cint(0)) @check ccall((:git_config_get_int32, libgit2), Cint, - (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) + (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c, name) return val_ptr[] end @@ -132,7 +132,7 @@ function get(::Type{Int64}, c::GitConfig, name::AbstractString) ensure_initialized() val_ptr = Ref(Cintmax_t(0)) @check ccall((:git_config_get_int64, libgit2), Cint, - (Ptr{Cintmax_t}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) + (Ptr{Cintmax_t}, Ptr{Cvoid}, Cstring), val_ptr, c, name) return val_ptr[] end @@ -165,33 +165,33 @@ end function set!(c::GitConfig, name::AbstractString, value::AbstractString) ensure_initialized() @check ccall((:git_config_set_string, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cstring), c.ptr, name, value) + (Ptr{Cvoid}, Cstring, Cstring), c, name, value) end function set!(c::GitConfig, name::AbstractString, value::Bool) ensure_initialized() bval = Int32(value) @check ccall((:git_config_set_bool, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cint), c.ptr, name, bval) + (Ptr{Cvoid}, Cstring, Cint), c, name, bval) end function set!(c::GitConfig, name::AbstractString, value::Int32) ensure_initialized() @check ccall((:git_config_set_int32, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cint), c.ptr, name, value) + (Ptr{Cvoid}, Cstring, Cint), c, name, value) end function set!(c::GitConfig, name::AbstractString, value::Int64) ensure_initialized() @check ccall((:git_config_set_int64, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cintmax_t), c.ptr, name, value) + (Ptr{Cvoid}, Cstring, Cintmax_t), c, name, value) end function GitConfigIter(cfg::GitConfig) ensure_initialized() ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_iterator_new, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), ci_ptr, cfg.ptr) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), ci_ptr, cfg) return GitConfigIter(ci_ptr[]) end @@ -200,7 +200,7 @@ function GitConfigIter(cfg::GitConfig, name::AbstractString) ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_multivar_iterator_new, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), - ci_ptr, cfg.ptr, name, C_NULL) + ci_ptr, cfg, name, C_NULL) return GitConfigIter(ci_ptr[]) end @@ -209,7 +209,7 @@ function GitConfigIter(cfg::GitConfig, name::AbstractString, value::Regex) ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_multivar_iterator_new, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), - ci_ptr, cfg.ptr, name, value.pattern) + ci_ptr, cfg, name, value.pattern) return GitConfigIter(ci_ptr[]) end @@ -218,7 +218,7 @@ function GitConfigIter(cfg::GitConfig, name::Regex) ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_iterator_glob_new, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), - ci_ptr, cfg.ptr, name.pattern) + ci_ptr, cfg, name.pattern) return GitConfigIter(ci_ptr[]) end @@ -226,7 +226,7 @@ function Base.iterate(ci::GitConfigIter, state=nothing) ensure_initialized() entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) err = ccall((:git_config_next, libgit2), Cint, - (Ptr{Ptr{ConfigEntry}}, Ptr{Cvoid}), entry_ptr_ptr, ci.ptr) + (Ptr{Ptr{ConfigEntry}}, Ptr{Cvoid}), entry_ptr_ptr, ci) if err == Cint(Error.GIT_OK) return (unsafe_load(entry_ptr_ptr[]), nothing) elseif err == Cint(Error.ITEROVER) diff --git a/stdlib/LibGit2/src/diff.jl b/stdlib/LibGit2/src/diff.jl index 044c6331dc1f1..a3f2cafe62e96 100644 --- a/stdlib/LibGit2/src/diff.jl +++ b/stdlib/LibGit2/src/diff.jl @@ -29,11 +29,11 @@ function diff_tree(repo::GitRepo, tree::GitTree, pathspecs::AbstractString=""; c if cached @check ccall((:git_diff_tree_to_index, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{DiffOptionsStruct}), - diff_ptr_ptr, repo.ptr, tree.ptr, C_NULL, isempty(pathspecs) ? C_NULL : pathspecs) + diff_ptr_ptr, repo, tree, C_NULL, isempty(pathspecs) ? C_NULL : pathspecs) else @check ccall((:git_diff_tree_to_workdir_with_index, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{DiffOptionsStruct}), - diff_ptr_ptr, repo.ptr, tree.ptr, isempty(pathspecs) ? C_NULL : pathspecs) + diff_ptr_ptr, repo, tree, isempty(pathspecs) ? C_NULL : pathspecs) end return GitDiff(repo, diff_ptr_ptr[]) end @@ -53,7 +53,7 @@ function diff_tree(repo::GitRepo, oldtree::GitTree, newtree::GitTree) diff_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_diff_tree_to_tree, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{DiffOptionsStruct}), - diff_ptr_ptr, repo.ptr, oldtree.ptr, newtree.ptr, C_NULL) + diff_ptr_ptr, repo, oldtree, newtree, C_NULL) return GitDiff(repo, diff_ptr_ptr[]) end @@ -69,7 +69,7 @@ function GitDiffStats(diff::GitDiff) diff_stat_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_diff_get_stats, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), - diff_stat_ptr_ptr, diff.ptr) + diff_stat_ptr_ptr, diff) return GitDiffStats(diff.owner, diff_stat_ptr_ptr[]) end @@ -83,7 +83,7 @@ are to be included or not). """ function files_changed(diff_stat::GitDiffStats) ensure_initialized() - return ccall((:git_diff_stats_files_changed, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) + return ccall((:git_diff_stats_files_changed, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat) end """ @@ -96,7 +96,7 @@ are to be included or not). """ function insertions(diff_stat::GitDiffStats) ensure_initialized() - return ccall((:git_diff_stats_insertions, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) + return ccall((:git_diff_stats_insertions, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat) end """ @@ -109,12 +109,12 @@ are to be included or not). """ function deletions(diff_stat::GitDiffStats) ensure_initialized() - return ccall((:git_diff_stats_deletions, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) + return ccall((:git_diff_stats_deletions, libgit2), Csize_t, (Ptr{Cvoid},), diff_stat) end function count(diff::GitDiff) ensure_initialized() - return ccall((:git_diff_num_deltas, libgit2), Cint, (Ptr{Cvoid},), diff.ptr) + return ccall((:git_diff_num_deltas, libgit2), Cint, (Ptr{Cvoid},), diff) end function Base.getindex(diff::GitDiff, i::Integer) @@ -122,10 +122,12 @@ function Base.getindex(diff::GitDiff, i::Integer) throw(BoundsError(diff, (i,))) end ensure_initialized() - delta_ptr = ccall((:git_diff_get_delta, libgit2), - Ptr{DiffDelta}, - (Ptr{Cvoid}, Csize_t), diff.ptr, i-1) - return unsafe_load(delta_ptr) + GC.@preserve diff begin # preserve `diff` object until return of `unsafe_load` + delta_ptr = ccall((:git_diff_get_delta, libgit2), + Ptr{DiffDelta}, + (Ptr{Cvoid}, Csize_t), diff, i-1) + return unsafe_load(delta_ptr) + end end function Base.show(io::IO, diff_stat::GitDiffStats) diff --git a/stdlib/LibGit2/src/index.jl b/stdlib/LibGit2/src/index.jl index 15e04d16b5756..81e8e75d59585 100644 --- a/stdlib/LibGit2/src/index.jl +++ b/stdlib/LibGit2/src/index.jl @@ -9,7 +9,7 @@ function GitIndex(repo::GitRepo) ensure_initialized() idx_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_index, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), idx_ptr_ptr, repo.ptr) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), idx_ptr_ptr, repo) return GitIndex(repo, idx_ptr_ptr[]) end @@ -25,7 +25,7 @@ has changed since the last time it was loaded into `idx`. """ function read!(idx::GitIndex, force::Bool = false) ensure_initialized() - @check ccall((:git_index_read, libgit2), Cint, (Ptr{Cvoid}, Cint), idx.ptr, Cint(force)) + @check ccall((:git_index_read, libgit2), Cint, (Ptr{Cvoid}, Cint), idx, Cint(force)) return idx end @@ -36,7 +36,7 @@ Write the state of index `idx` to disk using a file lock. """ function write!(idx::GitIndex) ensure_initialized() - @check ccall((:git_index_write, libgit2), Cint, (Ptr{Cvoid},), idx.ptr) + @check ccall((:git_index_write, libgit2), Cint, (Ptr{Cvoid},), idx) return idx end @@ -52,7 +52,7 @@ function write_tree!(idx::GitIndex) ensure_initialized() oid_ptr = Ref(GitHash()) @check ccall((:git_index_write_tree, libgit2), Cint, - (Ptr{GitHash}, Ptr{Cvoid}), oid_ptr, idx.ptr) + (Ptr{GitHash}, Ptr{Cvoid}), oid_ptr, idx) return oid_ptr[] end @@ -74,7 +74,7 @@ Read the tree `tree` (or the tree pointed to by `treehash` in the repository own function read_tree!(idx::GitIndex, tree::GitTree) ensure_initialized() @check ccall((:git_index_read_tree, libgit2), Cint, - (Ptr{Cvoid}, Ptr{Cvoid}), idx.ptr, tree.ptr) + (Ptr{Cvoid}, Ptr{Cvoid}), idx, tree) end read_tree!(idx::GitIndex, hash::AbstractGitHash) = read_tree!(idx, GitTree(repository(idx), hash)) @@ -106,7 +106,7 @@ function add!(idx::GitIndex, files::AbstractString...; ensure_initialized() @check ccall((:git_index_add_all, libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Cuint, Ptr{Cvoid}, Ptr{Cvoid}), - idx.ptr, collect(files), flags, C_NULL, C_NULL) + idx, collect(files), flags, C_NULL, C_NULL) end """ @@ -122,7 +122,7 @@ function update!(idx::GitIndex, files::AbstractString...) ensure_initialized() @check ccall((:git_index_update_all, libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{Cvoid}, Ptr{Cvoid}), - idx.ptr, collect(files), C_NULL, C_NULL) + idx, collect(files), C_NULL, C_NULL) end """ @@ -136,7 +136,7 @@ function remove!(idx::GitIndex, files::AbstractString...) ensure_initialized() @check ccall((:git_index_remove_all, libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{Cvoid}, Ptr{Cvoid}), - idx.ptr, collect(files), C_NULL, C_NULL) + idx, collect(files), C_NULL, C_NULL) end function add!(repo::GitRepo, files::AbstractString...; @@ -173,7 +173,7 @@ end function count(idx::GitIndex) ensure_initialized() - return ccall((:git_index_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), idx.ptr) + return ccall((:git_index_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), idx) end function Base.getindex(idx::GitIndex, i::Integer) @@ -192,7 +192,7 @@ function Base.findall(path::String, idx::GitIndex) ensure_initialized() pos_ref = Ref{Csize_t}(0) ret = ccall((:git_index_find, libgit2), Cint, - (Ref{Csize_t}, Ptr{Cvoid}, Cstring), pos_ref, idx.ptr, path) + (Ref{Csize_t}, Ptr{Cvoid}, Cstring), pos_ref, idx, path) ret == Cint(Error.ENOTFOUND) && return nothing return pos_ref[]+1 end diff --git a/stdlib/LibGit2/src/merge.jl b/stdlib/LibGit2/src/merge.jl index 7c946315fdd86..8bd8d1e4b64e9 100644 --- a/stdlib/LibGit2/src/merge.jl +++ b/stdlib/LibGit2/src/merge.jl @@ -18,7 +18,7 @@ function GitAnnotated(repo::GitRepo, commit_id::GitHash) ann_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}), - ann_ptr_ptr, repo.ptr, Ref(commit_id)) + ann_ptr_ptr, repo, Ref(commit_id)) return GitAnnotated(repo, ann_ptr_ptr[]) end @@ -27,7 +27,7 @@ function GitAnnotated(repo::GitRepo, ref::GitReference) ann_ref_ref = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_from_ref, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}), - ann_ref_ref, repo.ptr, ref.ptr) + ann_ref_ref, repo, ref) return GitAnnotated(repo, ann_ref_ref[]) end @@ -36,7 +36,7 @@ function GitAnnotated(repo::GitRepo, fh::FetchHead) ann_ref_ref = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_from_fetchhead, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring, Ptr{GitHash}), - ann_ref_ref, repo.ptr, fh.name, fh.url, Ref(fh.oid)) + ann_ref_ref, repo, fh.name, fh.url, Ref(fh.oid)) return GitAnnotated(repo, ann_ref_ref[]) end @@ -88,9 +88,11 @@ function merge_analysis(repo::GitRepo, anns::Vector{GitAnnotated}) preference = Ref{Cint}(0) anns_ref = Ref(Base.map(a->a.ptr, anns), 1) anns_size = Csize_t(length(anns)) - @check ccall((:git_merge_analysis, libgit2), Cint, - (Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, Csize_t), - analysis, preference, repo.ptr, anns_ref, anns_size) + GC.@preserve anns begin + @check ccall((:git_merge_analysis, libgit2), Cint, + (Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, Csize_t), + analysis, preference, repo, anns_ref, anns_size) + end return analysis[], preference[] end @@ -147,11 +149,13 @@ function merge!(repo::GitRepo, anns::Vector{GitAnnotated}; checkout_opts::CheckoutOptions = CheckoutOptions()) ensure_initialized() anns_size = Csize_t(length(anns)) - @check ccall((:git_merge, libgit2), Cint, - (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, Csize_t, - Ptr{MergeOptions}, Ptr{CheckoutOptions}), - repo.ptr, Base.map(x->x.ptr, anns), anns_size, - Ref(merge_opts), Ref(checkout_opts)) + GC.@preserve anns begin + @check ccall((:git_merge, libgit2), Cint, + (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, Csize_t, + Ptr{MergeOptions}, Ptr{CheckoutOptions}), + repo, Base.map(x->x.ptr, anns), anns_size, + Ref(merge_opts), Ref(checkout_opts)) + end @info "Review and commit merged changes" return true end @@ -263,7 +267,7 @@ function merge_base(repo::GitRepo, one::AbstractString, two::AbstractString) moid = try @check ccall((:git_merge_base, libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Ptr{GitHash}, Ptr{GitHash}), - moid_ptr, repo.ptr, oid1_ptr, oid2_ptr) + moid_ptr, repo, oid1_ptr, oid2_ptr) moid_ptr[] catch e GitHash() diff --git a/stdlib/LibGit2/src/oid.jl b/stdlib/LibGit2/src/oid.jl index be4944791f55c..fae0d3737a429 100644 --- a/stdlib/LibGit2/src/oid.jl +++ b/stdlib/LibGit2/src/oid.jl @@ -133,7 +133,7 @@ function GitHash(repo::GitRepo, ref_name::AbstractString) oid_ptr = Ref(GitHash()) @check ccall((:git_reference_name_to_id, libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring), - oid_ptr, repo.ptr, ref_name) + oid_ptr, repo, ref_name) return oid_ptr[] end @@ -144,7 +144,7 @@ Get the identifier (`GitHash`) of `obj`. """ function GitHash(obj::GitObject) ensure_initialized() - GitHash(ccall((:git_object_id, libgit2), Ptr{UInt8}, (Ptr{Cvoid},), obj.ptr)) + GitHash(ccall((:git_object_id, libgit2), Ptr{UInt8}, (Ptr{Cvoid},), obj)) end ==(obj1::GitObject, obj2::GitObject) = GitHash(obj1) == GitHash(obj2) @@ -160,7 +160,7 @@ function GitShortHash(obj::GitObject) ensure_initialized() buf_ref = Ref(Buffer()) @check ccall((:git_object_short_id, libgit2), Cint, - (Ptr{Buffer},Ptr{Cvoid}), buf_ref, obj.ptr) + (Ptr{Buffer},Ptr{Cvoid}), buf_ref, obj) sid = GitShortHash(buf_ref[]) free(buf_ref) return sid diff --git a/stdlib/LibGit2/src/rebase.jl b/stdlib/LibGit2/src/rebase.jl index b36c2f3f475cf..e4abf5a85cc92 100644 --- a/stdlib/LibGit2/src/rebase.jl +++ b/stdlib/LibGit2/src/rebase.jl @@ -8,14 +8,14 @@ function GitRebase(repo::GitRepo, branch::GitAnnotated, upstream::GitAnnotated; @check ccall((:git_rebase_init, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{RebaseOptions}), - rebase_ptr_ptr, repo.ptr, branch.ptr, upstream.ptr, - onto === nothing ? C_NULL : onto.ptr, Ref(opts)) + rebase_ptr_ptr, repo, branch, upstream, + onto === nothing ? C_NULL : onto, Ref(opts)) return GitRebase(repo, rebase_ptr_ptr[]) end function count(rb::GitRebase) ensure_initialized() - return ccall((:git_rebase_operation_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), rb.ptr) + return ccall((:git_rebase_operation_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), rb) end """ @@ -28,7 +28,7 @@ has not yet been called or iteration over `rb` has not yet begun), return """ function current(rb::GitRebase) ensure_initialized() - return ccall((:git_rebase_operation_current, libgit2), Csize_t, (Ptr{Cvoid},), rb.ptr) + return ccall((:git_rebase_operation_current, libgit2), Csize_t, (Ptr{Cvoid},), rb) end function Base.getindex(rb::GitRebase, i::Integer) @@ -80,7 +80,7 @@ function commit(rb::GitRebase, sig::GitSignature) try @check ccall((:git_rebase_commit, libgit2), Error.Code, (Ptr{GitHash}, Ptr{Cvoid}, Ptr{SignatureStruct}, Ptr{SignatureStruct}, Ptr{UInt8}, Ptr{UInt8}), - oid_ptr, rb.ptr, C_NULL, sig.ptr, C_NULL, C_NULL) + oid_ptr, rb, C_NULL, sig, C_NULL, C_NULL) catch err # TODO: return current HEAD instead err isa GitError && err.code === Error.EAPPLIED && return nothing @@ -101,7 +101,7 @@ rebase had completed), and `-1` for other errors. function abort(rb::GitRebase) ensure_initialized() return ccall((:git_rebase_abort, libgit2), Csize_t, - (Ptr{Cvoid},), rb.ptr) + (Ptr{Cvoid},), rb) end """ @@ -115,5 +115,5 @@ function finish(rb::GitRebase, sig::GitSignature) ensure_initialized() return ccall((:git_rebase_finish, libgit2), Csize_t, (Ptr{Cvoid}, Ptr{SignatureStruct}), - rb.ptr, sig.ptr) + rb, sig) end diff --git a/stdlib/LibGit2/src/reference.jl b/stdlib/LibGit2/src/reference.jl index 9f849ed01a00f..8a9bc5cf1a6de 100644 --- a/stdlib/LibGit2/src/reference.jl +++ b/stdlib/LibGit2/src/reference.jl @@ -5,7 +5,7 @@ function GitReference(repo::GitRepo, refname::AbstractString) ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), - ref_ptr_ptr, repo.ptr, refname) + ref_ptr_ptr, repo, refname) return GitReference(repo, ref_ptr_ptr[]) end @@ -15,7 +15,7 @@ function GitReference(repo::GitRepo, obj_oid::GitHash, refname::AbstractString = ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_create, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{UInt8}, Ptr{GitHash}, Cint, Cstring), - ref_ptr_ptr, repo.ptr, refname, Ref(obj_oid), Cint(force), + ref_ptr_ptr, repo, refname, Ref(obj_oid), Cint(force), isempty(msg) ? C_NULL : msg) return GitReference(repo, ref_ptr_ptr[]) end @@ -29,7 +29,7 @@ to this branch will have no parents. function isorphan(repo::GitRepo) ensure_initialized() r = @check ccall((:git_repository_head_unborn, libgit2), Cint, - (Ptr{Cvoid},), repo.ptr) + (Ptr{Cvoid},), repo) r != 0 end @@ -42,7 +42,7 @@ function head(repo::GitRepo) ensure_initialized() head_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_head, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), head_ptr_ptr, repo.ptr) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), head_ptr_ptr, repo) return GitReference(repo, head_ptr_ptr[]) end @@ -68,7 +68,7 @@ function shortname(ref::GitReference) isempty(ref) && return "" ensure_initialized() GC.@preserve ref begin - name_ptr = ccall((:git_reference_shorthand, libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) + name_ptr = ccall((:git_reference_shorthand, libgit2), Cstring, (Ptr{Cvoid},), ref) name_ptr == C_NULL && return "" name = unsafe_string(name_ptr) end @@ -85,7 +85,7 @@ Return a `Cint` corresponding to the type of `ref`: """ function reftype(ref::GitReference) ensure_initialized() - return ccall((:git_reference_type, libgit2), Cint, (Ptr{Cvoid},), ref.ptr) + return ccall((:git_reference_type, libgit2), Cint, (Ptr{Cvoid},), ref) end """ @@ -139,7 +139,7 @@ function ishead(ref::GitReference) isempty(ref) && return false ensure_initialized() err = ccall((:git_branch_is_head, libgit2), Cint, - (Ptr{Cvoid},), ref.ptr) + (Ptr{Cvoid},), ref) return err == 1 end @@ -147,7 +147,7 @@ function isbranch(ref::GitReference) isempty(ref) && return false ensure_initialized() err = ccall((:git_reference_is_branch, libgit2), Cint, - (Ptr{Cvoid},), ref.ptr) + (Ptr{Cvoid},), ref) return err == 1 end @@ -155,7 +155,7 @@ function istag(ref::GitReference) isempty(ref) && return false ensure_initialized() err = ccall((:git_reference_is_tag, libgit2), Cint, - (Ptr{Cvoid},), ref.ptr) + (Ptr{Cvoid},), ref) return err == 1 end @@ -163,7 +163,7 @@ function isremote(ref::GitReference) isempty(ref) && return false ensure_initialized() err = ccall((:git_reference_is_remote, libgit2), Cint, - (Ptr{Cvoid},), ref.ptr) + (Ptr{Cvoid},), ref) return err == 1 end @@ -200,7 +200,7 @@ function peel(::Type{T}, ref::GitReference) where T<:GitObject ensure_initialized() obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_peel, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), obj_ptr_ptr, ref.ptr, Consts.OBJECT(T)) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), obj_ptr_ptr, ref, Consts.OBJECT(T)) return T(ref.owner, obj_ptr_ptr[]) end peel(ref::GitReference) = peel(GitObject, ref) @@ -214,7 +214,7 @@ function ref_list(repo::GitRepo) ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_reference_list, libgit2), Cint, - (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo.ptr) + (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res @@ -237,7 +237,7 @@ function create_branch(repo::GitRepo, ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_branch_create, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Cint), - ref_ptr_ptr, repo.ptr, bname, commit_obj.ptr, Cint(force)) + ref_ptr_ptr, repo, bname, commit_obj, Cint(force)) return GitReference(repo, ref_ptr_ptr[]) end @@ -248,7 +248,7 @@ Delete the branch pointed to by `branch`. """ function delete_branch(branch::GitReference) ensure_initialized() - @check ccall((:git_branch_delete, libgit2), Cint, (Ptr{Cvoid},), branch.ptr) + @check ccall((:git_branch_delete, libgit2), Cint, (Ptr{Cvoid},), branch) end """ @@ -260,7 +260,7 @@ function head!(repo::GitRepo, ref::GitReference) ensure_initialized() ref_name = name(ref) @check ccall((:git_repository_set_head, libgit2), Cint, - (Ptr{Cvoid}, Cstring), repo.ptr, ref_name) + (Ptr{Cvoid}, Cstring), repo, ref_name) return ref end @@ -282,7 +282,7 @@ function lookup_branch(repo::GitRepo, branch_type = remote ? Consts.BRANCH_REMOTE : Consts.BRANCH_LOCAL err = ccall((:git_branch_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{UInt8}, Cint), - ref_ptr_ptr, repo.ptr, branch_name, branch_type) + ref_ptr_ptr, repo, branch_name, branch_type) if err != Int(Error.GIT_OK) if err == Int(Error.ENOTFOUND) return nothing @@ -308,7 +308,7 @@ function upstream(ref::GitReference) ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) err = ccall((:git_branch_upstream, libgit2), Cint, - (Ref{Ptr{Cvoid}}, Ptr{Cvoid},), ref_ptr_ptr, ref.ptr) + (Ref{Ptr{Cvoid}}, Ptr{Cvoid},), ref_ptr_ptr, ref) if err != Int(Error.GIT_OK) if err == Int(Error.ENOTFOUND) return nothing @@ -328,7 +328,7 @@ function target!(ref::GitReference, new_oid::GitHash; msg::AbstractString="") ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_set_target, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Cstring), - ref_ptr_ptr, ref.ptr, Ref(new_oid), isempty(msg) ? C_NULL : msg) + ref_ptr_ptr, ref, Ref(new_oid), isempty(msg) ? C_NULL : msg) return GitReference(ref.owner, ref_ptr_ptr[]) end @@ -336,7 +336,7 @@ function GitBranchIter(repo::GitRepo, flags::Cint=Cint(Consts.BRANCH_LOCAL)) ensure_initialized() bi_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_branch_iterator_new, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), bi_ptr, repo.ptr, flags) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), bi_ptr, repo, flags) return GitBranchIter(repo, bi_ptr[]) end @@ -346,7 +346,7 @@ function Base.iterate(bi::GitBranchIter, state=nothing) btype = Ref{Cint}() err = ccall((:git_branch_next, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cint}, Ptr{Cvoid}), - ref_ptr_ptr, btype, bi.ptr) + ref_ptr_ptr, btype, bi) if err == Cint(Error.GIT_OK) return ((GitReference(bi.owner, ref_ptr_ptr[]), btype[]), nothing) elseif err == Cint(Error.ITEROVER) diff --git a/stdlib/LibGit2/src/remote.jl b/stdlib/LibGit2/src/remote.jl index 07afecebfd373..5081eff56dd46 100644 --- a/stdlib/LibGit2/src/remote.jl +++ b/stdlib/LibGit2/src/remote.jl @@ -16,7 +16,7 @@ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractStr rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), - rmt_ptr_ptr, repo.ptr, rmt_name, rmt_url) + rmt_ptr_ptr, repo, rmt_name, rmt_url) return GitRemote(repo, rmt_ptr_ptr[]) end @@ -39,7 +39,7 @@ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractStr rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create_with_fetchspec, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring, Cstring), - rmt_ptr_ptr, repo.ptr, rmt_name, rmt_url, fetch_spec) + rmt_ptr_ptr, repo, rmt_name, rmt_url, fetch_spec) return GitRemote(repo, rmt_ptr_ptr[]) end @@ -59,7 +59,7 @@ function GitRemoteAnon(repo::GitRepo, url::AbstractString) rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create_anonymous, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), - rmt_ptr_ptr, repo.ptr, url) + rmt_ptr_ptr, repo, url) return GitRemote(repo, rmt_ptr_ptr[]) end @@ -95,7 +95,7 @@ function lookup_remote(repo::GitRepo, remote_name::AbstractString) rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) err = ccall((:git_remote_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), - rmt_ptr_ptr, repo.ptr, remote_name) + rmt_ptr_ptr, repo, remote_name) if err == Int(Error.GIT_OK) return GitRemote(repo, rmt_ptr_ptr[]) elseif err == Int(Error.ENOTFOUND) @@ -110,7 +110,7 @@ function get(::Type{GitRemote}, repo::GitRepo, rmt_name::AbstractString) rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), - rmt_ptr_ptr, repo.ptr, rmt_name) + rmt_ptr_ptr, repo, rmt_name) return GitRemote(repo, rmt_ptr_ptr[]) end @@ -133,9 +133,11 @@ julia> LibGit2.url(remote) """ function url(rmt::GitRemote) ensure_initialized() - url_ptr = ccall((:git_remote_url, libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) - url_ptr == C_NULL && return "" - return unsafe_string(url_ptr) + GC.@preserve rmt begin # preserve `rmt` object until return of `unsafe_string` + url_ptr = ccall((:git_remote_url, libgit2), Cstring, (Ptr{Cvoid},), rmt) + url_ptr == C_NULL && return "" + return unsafe_string(url_ptr) + end end """ @@ -157,9 +159,11 @@ julia> LibGit2.push_url(LibGit2.get(LibGit2.GitRemote, repo, "origin")) """ function push_url(rmt::GitRemote) ensure_initialized() - url_ptr = ccall((:git_remote_pushurl, libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) - url_ptr == C_NULL && return "" - return unsafe_string(url_ptr) + GC.@preserve rmt begin # preserve `rmt` object until return of `unsafe_string` + url_ptr = ccall((:git_remote_pushurl, libgit2), Cstring, (Ptr{Cvoid},), rmt) + url_ptr == C_NULL && return "" + return unsafe_string(url_ptr) + end end """ @@ -183,9 +187,11 @@ julia> name(remote) """ function name(rmt::GitRemote) ensure_initialized() - name_ptr = ccall((:git_remote_name, libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) - name_ptr == C_NULL && return "" - return unsafe_string(name_ptr) + GC.@preserve rmt begin # preserve `rmt` object until return of `unsafe_string` + name_ptr = ccall((:git_remote_name, libgit2), Cstring, (Ptr{Cvoid},), rmt) + name_ptr == C_NULL && return "" + return unsafe_string(name_ptr) + end end """ @@ -208,7 +214,7 @@ function fetch_refspecs(rmt::GitRemote) ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_fetch_refspecs, libgit2), Cint, - (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt.ptr) + (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res @@ -238,7 +244,7 @@ function push_refspecs(rmt::GitRemote) ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_push_refspecs, libgit2), Cint, - (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt.ptr) + (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res @@ -261,7 +267,7 @@ String["+refs/heads/*:refs/remotes/upstream/*"] function add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) ensure_initialized() @check ccall((:git_remote_add_fetch, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, + (Ptr{Cvoid}, Cstring, Cstring), repo, name(rmt), fetch_spec) end @@ -290,7 +296,7 @@ String["refs/heads/master"] function add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) ensure_initialized() @check ccall((:git_remote_add_push, libgit2), Cint, - (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, + (Ptr{Cvoid}, Cstring, Cstring), repo, name(rmt), push_spec) end @@ -311,7 +317,7 @@ function fetch(rmt::GitRemote, refspecs::Vector{<:AbstractString}; msg = "libgit2.fetch: $msg" @check ccall((:git_remote_fetch, libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{FetchOptions}, Cstring), - rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options), msg) + rmt, isempty(refspecs) ? C_NULL : refspecs, Ref(options), msg) end """ @@ -336,7 +342,7 @@ function push(rmt::GitRemote, refspecs::Vector{<:AbstractString}; ensure_initialized() @check ccall((:git_remote_push, libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{PushOptions}), - rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options)) + rmt, isempty(refspecs) ? C_NULL : refspecs, Ref(options)) end """ @@ -348,7 +354,7 @@ function remote_delete(repo::GitRepo, remote_name::AbstractString) ensure_initialized() @check ccall((:git_remote_delete, libgit2), Cint, (Ptr{Cvoid}, Cstring), - repo.ptr, remote_name) + repo, remote_name) end Base.show(io::IO, rmt::GitRemote) = print(io, "GitRemote:\nRemote name: ", name(rmt), " url: ", url(rmt)) @@ -367,7 +373,7 @@ function set_remote_fetch_url(repo::GitRepo, remote_name::AbstractString, url::A ensure_initialized() @check ccall((:git_remote_set_url, libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), - repo.ptr, remote_name, url) + repo, remote_name, url) end function set_remote_fetch_url(path::AbstractString, remote_name::AbstractString, url::AbstractString) @@ -390,7 +396,7 @@ function set_remote_push_url(repo::GitRepo, remote_name::AbstractString, url::Ab ensure_initialized() @check ccall((:git_remote_set_pushurl, libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), - repo.ptr, remote_name, url) + repo, remote_name, url) end function set_remote_push_url(path::AbstractString, remote_name::AbstractString, url::AbstractString) @@ -432,7 +438,7 @@ function connect(rmt::GitRemote, direction::Consts.GIT_DIRECTION, callbacks::RemoteCallbacks) @check ccall((:git_remote_connect, libgit2), Cint, (Ptr{Cvoid}, Cint, Ref{RemoteCallbacks}, Ptr{Cvoid}, Ptr{Cvoid}), - rmt.ptr, direction, callbacks, C_NULL, C_NULL) + rmt, direction, callbacks, C_NULL, C_NULL) return rmt end @@ -442,7 +448,7 @@ end Check whether the remote is connected """ function connected(rmt::GitRemote) - return ccall((:git_remote_connected, libgit2), Cint, (Ptr{Cvoid},), rmt.ptr) != 0 + return ccall((:git_remote_connected, libgit2), Cint, (Ptr{Cvoid},), rmt) != 0 end """ @@ -451,7 +457,7 @@ end Close the connection to the remote. """ function disconnect(rmt::GitRemote) - @check ccall((:git_remote_disconnect, libgit2), Cint, (Ptr{Cvoid},), rmt.ptr) + @check ccall((:git_remote_disconnect, libgit2), Cint, (Ptr{Cvoid},), rmt) return end @@ -465,7 +471,7 @@ This function must only be called after connecting (See [`connect`](@ref)). function default_branch(rmt::GitRemote) buf_ref = Ref(Buffer()) @check ccall((:git_remote_default_branch, libgit2), Cint, - (Ptr{Buffer}, Ptr{Cvoid}), buf_ref, rmt.ptr) + (Ptr{Buffer}, Ptr{Cvoid}), buf_ref, rmt) buf = buf_ref[] str = unsafe_string(buf.ptr, buf.size) free(buf_ref) @@ -484,7 +490,7 @@ function ls(rmt::GitRemote) head_refs = Ref{Ptr{Ptr{_GitRemoteHead}}}() @check ccall((:git_remote_ls, libgit2), Cint, (Ptr{Ptr{Ptr{_GitRemoteHead}}}, Ptr{Csize_t}, Ptr{Cvoid}), - head_refs, nheads, rmt.ptr) + head_refs, nheads, rmt) head_ptr = head_refs[] return [GitRemoteHead(unsafe_load(unsafe_load(head_ptr, i))) for i in 1:nheads[]] diff --git a/stdlib/LibGit2/src/repository.jl b/stdlib/LibGit2/src/repository.jl index 8297ae92a6a00..192a6870f639b 100644 --- a/stdlib/LibGit2/src/repository.jl +++ b/stdlib/LibGit2/src/repository.jl @@ -32,7 +32,7 @@ end function cleanup(r::GitRepo) if r.ptr != C_NULL ensure_initialized() - @check ccall((:git_repository__cleanup, libgit2), Cint, (Ptr{Cvoid},), r.ptr) + @check ccall((:git_repository__cleanup, libgit2), Cint, (Ptr{Cvoid},), r) end end @@ -97,7 +97,7 @@ tree, and no tracking information for remote branches or configurations is prese function isbare(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL - return ccall((:git_repository_is_bare, libgit2), Cint, (Ptr{Cvoid},), repo.ptr) == 1 + return ccall((:git_repository_is_bare, libgit2), Cint, (Ptr{Cvoid},), repo) == 1 end """ @@ -109,7 +109,7 @@ Determine if `repo` is detached - that is, whether its HEAD points to a commit function isattached(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL - ccall((:git_repository_head_detached, libgit2), Cint, (Ptr{Cvoid},), repo.ptr) != 1 + ccall((:git_repository_head_detached, libgit2), Cint, (Ptr{Cvoid},), repo) != 1 end @doc """ @@ -140,13 +140,20 @@ function (::Type{T})(repo::GitRepo, spec::AbstractString) where T<:GitObject obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @assert repo.ptr != C_NULL @check ccall((:git_revparse_single, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), obj_ptr_ptr, repo.ptr, spec) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), obj_ptr_ptr, repo, spec) + obj_ptr = obj_ptr_ptr[] # check object is of correct type if T != GitObject && T != GitUnknownObject - t = Consts.OBJECT(obj_ptr_ptr[]) - t == Consts.OBJECT(T) || throw(GitError(Error.Object, Error.ERROR, "Expected object of type $T, received object of type $(objtype(t))")) + t = Consts.OBJECT(obj_ptr) + if t != Consts.OBJECT(T) + if obj_ptr != C_NULL + # free result + ccall((:git_object_free, libgit2), Cvoid, (Ptr{Cvoid},), obj_ptr) + end + throw(GitError(Error.Object, Error.ERROR, "Expected object of type $T, received object of type $(objtype(t))")) + end end - return T(repo, obj_ptr_ptr[]) + return T(repo, obj_ptr) end function (::Type{T})(repo::GitRepo, oid::GitHash) where T<:GitObject @@ -157,7 +164,7 @@ function (::Type{T})(repo::GitRepo, oid::GitHash) where T<:GitObject @assert repo.ptr != C_NULL @check ccall((:git_object_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Consts.OBJECT), - obj_ptr_ptr, repo.ptr, oid_ptr, Consts.OBJECT(T)) + obj_ptr_ptr, repo, oid_ptr, Consts.OBJECT(T)) return T(repo, obj_ptr_ptr[]) end @@ -169,7 +176,7 @@ function (::Type{T})(repo::GitRepo, oid::GitShortHash) where T<:GitObject @assert repo.ptr != C_NULL @check ccall((:git_object_lookup_prefix, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Csize_t, Consts.OBJECT), - obj_ptr_ptr, repo.ptr, oid_ptr, oid.len, Consts.OBJECT(T)) + obj_ptr_ptr, repo, oid_ptr, oid.len, Consts.OBJECT(T)) return T(repo, obj_ptr_ptr[]) end @@ -190,8 +197,10 @@ See also [`workdir`](@ref), [`path`](@ref). function gitdir(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL - return unsafe_string(ccall((:git_repository_path, libgit2), Cstring, - (Ptr{Cvoid},), repo.ptr)) + GC.@preserve repo begin + return unsafe_string(ccall((:git_repository_path, libgit2), Cstring, + (Ptr{Cvoid},), repo)) + end end """ @@ -211,10 +220,12 @@ See also [`gitdir`](@ref), [`path`](@ref). function workdir(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL - sptr = ccall((:git_repository_workdir, libgit2), Cstring, - (Ptr{Cvoid},), repo.ptr) - sptr == C_NULL && throw(GitError(Error.Object, Error.ERROR, "No working directory found.")) - return unsafe_string(sptr) + GC.@preserve repo begin + sptr = ccall((:git_repository_workdir, libgit2), Cstring, + (Ptr{Cvoid},), repo) + sptr == C_NULL && throw(GitError(Error.Object, Error.ERROR, "No working directory found.")) + return unsafe_string(sptr) + end end """ @@ -256,7 +267,7 @@ function peel(::Type{T}, obj::GitObject) where T<:GitObject new_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_object_peel, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), new_ptr_ptr, obj.ptr, Consts.OBJECT(T)) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), new_ptr_ptr, obj, Consts.OBJECT(T)) return T(obj.owner, new_ptr_ptr[]) end @@ -287,7 +298,7 @@ function GitDescribeResult(committish::GitObject; result_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_describe_commit, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{DescribeOptions}), - result_ptr_ptr, committish.ptr, Ref(options)) + result_ptr_ptr, committish, Ref(options)) return GitDescribeResult(committish.owner, result_ptr_ptr[]) end @@ -314,7 +325,7 @@ function GitDescribeResult(repo::GitRepo; options::DescribeOptions=DescribeOptio @assert repo.ptr != C_NULL @check ccall((:git_describe_workdir, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{DescribeOptions}), - result_ptr_ptr, repo.ptr, Ref(options)) + result_ptr_ptr, repo, Ref(options)) return GitDescribeResult(repo, result_ptr_ptr[]) end @@ -331,7 +342,7 @@ function format(result::GitDescribeResult; options::DescribeFormatOptions=Descri buf_ref = Ref(Buffer()) @check ccall((:git_describe_format, libgit2), Cint, (Ptr{Buffer}, Ptr{Cvoid}, Ptr{DescribeFormatOptions}), - buf_ref, result.ptr, Ref(options)) + buf_ref, result, Ref(options)) buf = buf_ref[] str = unsafe_string(buf.ptr, buf.size) free(buf_ref) @@ -357,7 +368,7 @@ function checkout_tree(repo::GitRepo, obj::GitObject; @assert repo.ptr != C_NULL @check ccall((:git_checkout_tree, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CheckoutOptions}), - repo.ptr, obj.ptr, Ref(options)) + repo, obj, Ref(options)) end """ @@ -373,8 +384,8 @@ function checkout_index(repo::GitRepo, idx::Union{GitIndex, Nothing} = nothing; @assert repo.ptr != C_NULL @check ccall((:git_checkout_index, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CheckoutOptions}), - repo.ptr, - idx === nothing ? C_NULL : idx.ptr, + repo, + idx === nothing ? C_NULL : idx, Ref(options)) end @@ -393,7 +404,7 @@ function checkout_head(repo::GitRepo; options::CheckoutOptions = CheckoutOptions @assert repo.ptr != C_NULL @check ccall((:git_checkout_head, libgit2), Cint, (Ptr{Cvoid}, Ptr{CheckoutOptions}), - repo.ptr, Ref(options)) + repo, Ref(options)) end """ @@ -412,7 +423,7 @@ function cherrypick(repo::GitRepo, commit::GitCommit; options::CherrypickOptions @assert repo.ptr != C_NULL @check ccall((:git_cherrypick, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CherrypickOptions}), - repo.ptr, commit.ptr, Ref(options)) + repo, commit, Ref(options)) end """Updates some entries, determined by the `pathspecs`, in the index from the target commit tree.""" @@ -421,8 +432,8 @@ function reset!(repo::GitRepo, obj::Union{GitObject, Nothing}, pathspecs::Abstra @assert repo.ptr != C_NULL @check ccall((:git_reset_default, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{StrArrayStruct}), - repo.ptr, - obj === nothing ? C_NULL : obj.ptr, + repo, + obj === nothing ? C_NULL : obj, collect(pathspecs)) return head_oid(repo) end @@ -434,7 +445,7 @@ function reset!(repo::GitRepo, obj::GitObject, mode::Cint; @assert repo.ptr != C_NULL @check ccall((:git_reset, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cint, Ptr{CheckoutOptions}), - repo.ptr, obj.ptr, mode, Ref(checkout_opts)) + repo, obj, mode, Ref(checkout_opts)) return head_oid(repo) end @@ -492,7 +503,7 @@ function fetchheads(repo::GitRepo) @assert repo.ptr != C_NULL @check ccall((:git_repository_fetchhead_foreach, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Any), - repo.ptr, ffcb, fh) + repo, ffcb, fh) return fh end @@ -506,7 +517,7 @@ function remotes(repo::GitRepo) sa_ref = Ref(StrArrayStruct()) @assert repo.ptr != C_NULL @check ccall((:git_remote_list, libgit2), Cint, - (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo.ptr) + (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo) res = convert(Vector{String}, sa_ref[]) free(sa_ref) return res diff --git a/stdlib/LibGit2/src/signature.jl b/stdlib/LibGit2/src/signature.jl index 85e62cd8c2b7e..17013121db9ad 100644 --- a/stdlib/LibGit2/src/signature.jl +++ b/stdlib/LibGit2/src/signature.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license function Signature(ptr::Ptr{SignatureStruct}) + @assert ptr != C_NULL sig = unsafe_load(ptr)::SignatureStruct name = unsafe_string(sig.name) email = unsafe_string(sig.email) @@ -67,6 +68,6 @@ function default_signature(repo::GitRepo) ensure_initialized() sig_ptr_ptr = Ref{Ptr{SignatureStruct}}(C_NULL) @check ccall((:git_signature_default, libgit2), Cint, - (Ptr{Ptr{SignatureStruct}}, Ptr{Cvoid}), sig_ptr_ptr, repo.ptr) + (Ptr{Ptr{SignatureStruct}}, Ptr{Cvoid}), sig_ptr_ptr, repo) return GitSignature(sig_ptr_ptr[]) end diff --git a/stdlib/LibGit2/src/status.jl b/stdlib/LibGit2/src/status.jl index c1cb2fb1c5a9c..c048e68c2b2bc 100644 --- a/stdlib/LibGit2/src/status.jl +++ b/stdlib/LibGit2/src/status.jl @@ -14,14 +14,14 @@ function GitStatus(repo::GitRepo; status_opts=StatusOptions()) stat_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_status_list_new, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{StatusOptions}), - stat_ptr_ptr, repo.ptr, Ref(status_opts)) + stat_ptr_ptr, repo, Ref(status_opts)) return GitStatus(repo, stat_ptr_ptr[]) end function Base.length(status::GitStatus) ensure_initialized() return Int(ccall((:git_status_list_entrycount, libgit2), Csize_t, - (Ptr{Ptr{Cvoid}},), status.ptr)) + (Ptr{Cvoid},), status)) end function Base.getindex(status::GitStatus, i::Integer) @@ -51,7 +51,7 @@ function status(repo::GitRepo, path::String) status_ptr = Ref{Cuint}(0) ret = ccall((:git_status_file, libgit2), Cint, (Ref{Cuint}, Ptr{Cvoid}, Cstring), - status_ptr, repo.ptr, path) + status_ptr, repo, path) (ret == Cint(Error.ENOTFOUND) || ret == Cint(Error.EAMBIGUOUS)) && return nothing return status_ptr[] end diff --git a/stdlib/LibGit2/src/tag.jl b/stdlib/LibGit2/src/tag.jl index 0e3d2b398a835..bbb0c97a484ec 100644 --- a/stdlib/LibGit2/src/tag.jl +++ b/stdlib/LibGit2/src/tag.jl @@ -9,7 +9,7 @@ function tag_list(repo::GitRepo) ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_tag_list, libgit2), Cint, - (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo.ptr) + (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res @@ -23,7 +23,7 @@ Remove the git tag `tag` from the repository `repo`. function tag_delete(repo::GitRepo, tag::AbstractString) ensure_initialized() @check ccall((:git_tag_delete, libgit2), Cint, - (Ptr{Cvoid}, Cstring), repo.ptr, tag) + (Ptr{Cvoid}, Cstring), repo, tag) end """ @@ -48,7 +48,7 @@ function tag_create(repo::GitRepo, tag::AbstractString, commit::Union{AbstractSt ensure_initialized() @check ccall((:git_tag_create, libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{SignatureStruct}, Cstring, Cint), - oid_ptr, repo.ptr, tag, commit_obj.ptr, git_sig.ptr, msg, Cint(force)) + oid_ptr, repo, tag, commit_obj, git_sig, msg, Cint(force)) end end return oid_ptr[] diff --git a/stdlib/LibGit2/src/tree.jl b/stdlib/LibGit2/src/tree.jl index 1aeeec96ea778..4c507aaba8e48 100644 --- a/stdlib/LibGit2/src/tree.jl +++ b/stdlib/LibGit2/src/tree.jl @@ -37,7 +37,7 @@ function treewalk(f, tree::GitTree, post::Bool = false) end, Cint, (Cstring, Ptr{Cvoid}, Ref{Vector{Any}})) err = ccall((:git_tree_walk, libgit2), Cint, (Ptr{Cvoid}, Cint, Ptr{Cvoid}, Any), - tree.ptr, post, cbf, payload) + tree, post, cbf, payload) if err < 0 err_class, _ = Error.last_error() if err_class != Error.Callback @@ -58,8 +58,10 @@ Return the filename of the object on disk to which `te` refers. """ function filename(te::GitTreeEntry) ensure_initialized() - str = ccall((:git_tree_entry_name, libgit2), Cstring, (Ptr{Cvoid},), te.ptr) - str != C_NULL && return unsafe_string(str) + GC.@preserve te begin + str = ccall((:git_tree_entry_name, libgit2), Cstring, (Ptr{Cvoid},), te.ptr) + str != C_NULL && return unsafe_string(str) + end return nothing end @@ -70,7 +72,7 @@ Return the UNIX filemode of the object on disk to which `te` refers as an intege """ function filemode(te::GitTreeEntry) ensure_initialized() - return ccall((:git_tree_entry_filemode, libgit2), Cint, (Ptr{Cvoid},), te.ptr) + return ccall((:git_tree_entry_filemode, libgit2), Cint, (Ptr{Cvoid},), te) end """ @@ -81,7 +83,7 @@ one of the types which [`objtype`](@ref) returns, e.g. a `GitTree` or `GitBlob`. """ function entrytype(te::GitTreeEntry) ensure_initialized() - otype = ccall((:git_tree_entry_type, libgit2), Cint, (Ptr{Cvoid},), te.ptr) + otype = ccall((:git_tree_entry_type, libgit2), Cint, (Ptr{Cvoid},), te) return objtype(Consts.OBJECT(otype)) end @@ -101,7 +103,7 @@ end function count(tree::GitTree) ensure_initialized() - return ccall((:git_tree_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), tree.ptr) + return ccall((:git_tree_entrycount, libgit2), Csize_t, (Ptr{Cvoid},), tree) end function Base.getindex(tree::GitTree, i::Integer) @@ -111,7 +113,7 @@ function Base.getindex(tree::GitTree, i::Integer) ensure_initialized() te_ptr = ccall((:git_tree_entry_byindex, libgit2), Ptr{Cvoid}, - (Ptr{Cvoid}, Csize_t), tree.ptr, i-1) + (Ptr{Cvoid}, Csize_t), tree, i-1) return GitTreeEntry(tree, te_ptr, false) end diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index b0b463c69e2f1..7a4ad37a68ca5 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -1057,7 +1057,6 @@ for (typ, owntyp, sup, cname) in Tuple{Symbol,Any,Symbol,Symbol}[ return obj end end - @eval Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::$typ) = x.ptr else @eval mutable struct $typ <: $sup owner::$owntyp @@ -1072,17 +1071,17 @@ for (typ, owntyp, sup, cname) in Tuple{Symbol,Any,Symbol,Symbol}[ return obj end end - @eval Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::$typ) = x.ptr if isa(owntyp, Expr) && owntyp.args[1] === :Union && owntyp.args[3] === :Nothing @eval begin $typ(ptr::Ptr{Cvoid}, fin::Bool=true) = $typ(nothing, ptr, fin) end end end + @eval Base.unsafe_convert(::Type{Ptr{Cvoid}}, obj::$typ) = obj.ptr @eval function Base.close(obj::$typ) if obj.ptr != C_NULL ensure_initialized() - ccall(($(string(cname, :_free)), libgit2), Cvoid, (Ptr{Cvoid},), obj.ptr) + ccall(($(string(cname, :_free)), libgit2), Cvoid, (Ptr{Cvoid},), obj) obj.ptr = C_NULL if Threads.atomic_sub!(REFCOUNT, 1) == 1 # will the last finalizer please turn out the lights? @@ -1116,10 +1115,11 @@ end function Base.close(obj::GitSignature) if obj.ptr != C_NULL ensure_initialized() - ccall((:git_signature_free, libgit2), Cvoid, (Ptr{SignatureStruct},), obj.ptr) + ccall((:git_signature_free, libgit2), Cvoid, (Ptr{SignatureStruct},), obj) obj.ptr = C_NULL end end +Base.unsafe_convert(::Type{Ptr{SignatureStruct}}, obj::GitSignature) = obj.ptr # Structure has the same layout as SignatureStruct mutable struct Signature diff --git a/stdlib/LibGit2/src/walker.jl b/stdlib/LibGit2/src/walker.jl index e43687b014226..239009a014c1e 100644 --- a/stdlib/LibGit2/src/walker.jl +++ b/stdlib/LibGit2/src/walker.jl @@ -22,7 +22,7 @@ function GitRevWalker(repo::GitRepo) ensure_initialized() w_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_revwalk_new, libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), w_ptr, repo.ptr) + (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), w_ptr, repo) return GitRevWalker(repo, w_ptr[]) end @@ -30,7 +30,7 @@ function Base.iterate(w::GitRevWalker, state=nothing) ensure_initialized() id_ptr = Ref(GitHash()) err = ccall((:git_revwalk_next, libgit2), Cint, - (Ptr{GitHash}, Ptr{Cvoid}), id_ptr, w.ptr) + (Ptr{GitHash}, Ptr{Cvoid}), id_ptr, w) if err == Cint(Error.GIT_OK) return (id_ptr[], nothing) elseif err == Cint(Error.ITEROVER) @@ -51,7 +51,7 @@ during the walk. """ function push_head!(w::GitRevWalker) ensure_initialized() - @check ccall((:git_revwalk_push_head, libgit2), Cint, (Ptr{Cvoid},), w.ptr) + @check ccall((:git_revwalk_push_head, libgit2), Cint, (Ptr{Cvoid},), w) return w end @@ -64,20 +64,20 @@ of that year as `cid` and then passing the resulting `w` to [`LibGit2.map`](@ref """ function push!(w::GitRevWalker, cid::GitHash) ensure_initialized() - @check ccall((:git_revwalk_push, libgit2), Cint, (Ptr{Cvoid}, Ptr{GitHash}), w.ptr, Ref(cid)) + @check ccall((:git_revwalk_push, libgit2), Cint, (Ptr{Cvoid}, Ptr{GitHash}), w, Ref(cid)) return w end function push!(w::GitRevWalker, range::AbstractString) ensure_initialized() - @check ccall((:git_revwalk_push_range, libgit2), Cint, (Ptr{Cvoid}, Ptr{UInt8}), w.ptr, range) + @check ccall((:git_revwalk_push_range, libgit2), Cint, (Ptr{Cvoid}, Ptr{UInt8}), w, range) return w end function Base.sort!(w::GitRevWalker; by::Cint = Consts.SORT_NONE, rev::Bool=false) ensure_initialized() rev && (by |= Consts.SORT_REVERSE) - @check ccall((:git_revwalk_sorting, libgit2), Cint, (Ptr{Cvoid}, Cint), w.ptr, by) + @check ccall((:git_revwalk_sorting, libgit2), Cint, (Ptr{Cvoid}, Cint), w, by) return w end From e621c74d52e095d740cede89e4e9da82d4f737a9 Mon Sep 17 00:00:00 2001 From: Timothy Date: Mon, 22 Jul 2024 18:54:37 +0800 Subject: [PATCH 029/206] Fix potential underrun with annotation merging (#54917) Fixes #54860, see the commit message for more details. The added test serves as a MWE of the original bug report. --- base/strings/annotated.jl | 1 + test/strings/annotated.jl | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/base/strings/annotated.jl b/base/strings/annotated.jl index 75e1dec570ff4..f077c577237d0 100644 --- a/base/strings/annotated.jl +++ b/base/strings/annotated.jl @@ -593,6 +593,7 @@ function _insert_annotations!(io::AnnotatedIOBuffer, annotations::Vector{Tuple{U for i in reverse(axes(annotations, 1)) annot = annotations[i] first(first(annot)) == 1 || continue + i <= length(io.annotations) || continue if last(annot) == last(last(io.annotations)) valid_run = true for runlen in 1:i diff --git a/test/strings/annotated.jl b/test/strings/annotated.jl index da76f0f020531..b7f55e97a3c8d 100644 --- a/test/strings/annotated.jl +++ b/test/strings/annotated.jl @@ -213,6 +213,12 @@ end @test write(aio2, Base.AnnotatedChar('c', [:b => 2, :c => 3, :d => 4])) == 1 @test Base.annotations(aio2) == [(1:2, :a => 1), (1:3, :b => 2), (3:3, :c => 3), (3:3, :d => 4)] end + let aio2 = Base.AnnotatedIOBuffer() + @test write(aio2, Base.AnnotatedChar('a', [:b => 1])) == 1 + @test write(aio2, Base.AnnotatedChar('b', [:a => 1, :b => 1])) == 1 + @test read(seekstart(aio2), Base.AnnotatedString) == + Base.AnnotatedString("ab", [(1:1, :b => 1), (2:2, :a => 1), (2:2, :b => 1)]) + end # Working through an IOContext aio = Base.AnnotatedIOBuffer() wrapio = IOContext(aio) From 5fae0ff4d00e5a637736bbbe10ab08f25134d8ea Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:52:01 -0400 Subject: [PATCH 030/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=20d801e4545=20to=206b4394914=20(#55205)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Pkg URL: https://github.com/JuliaLang/Pkg.jl.git Stdlib branch: master Julia branch: master Old commit: d801e4545 New commit: 6b4394914 Julia version: 1.12.0-DEV Pkg version: 1.12.0 Bump invoked by: @IanButterworth Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Pkg.jl/compare/d801e4545f548ab9061a018bf19db1944c711607...6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b ``` $ git log --oneline d801e4545..6b4394914 6b4394914 Use more internal Pkg.add api to bypass auto-registry-install (#3941) 6002a29de Pkg.test: document that coverage can be a string (#3957) 77f0225b8 don't use `get_extension` to bridge REPLExt to REPLMode (#3959) e6880bc9d add clarifying comment about source_path being the package root (#3956) b1b4df8d8 Fix codeblock language and prompt in Pkg.status() docstring (#3955) ``` Co-authored-by: Dilum Aluthge --- .../Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 | 1 + .../Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 | 1 + .../Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 | 1 - .../Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 create mode 100644 deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 diff --git a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 new file mode 100644 index 0000000000000..d86d2b6e8882f --- /dev/null +++ b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 @@ -0,0 +1 @@ +e17ce4624b0df926d63ff5259ba5632e diff --git a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 new file mode 100644 index 0000000000000..011650a167629 --- /dev/null +++ b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 @@ -0,0 +1 @@ +d02efe5a6f0a8bbc51f272170c37a0d1492c5b513b4d4b7566226247ddff1836144b0490ad4b443983f7a7133e77b7c631e8e22eebe82fb63f697f57223c1f4b diff --git a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 deleted file mode 100644 index a5bfcea5f0408..0000000000000 --- a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -68d6fc78830e9d3f736cae1a727247ac diff --git a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 b/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 deleted file mode 100644 index b671340cbc147..0000000000000 --- a/deps/checksums/Pkg-d801e4545f548ab9061a018bf19db1944c711607.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -00319914e123e0deb59a8235b6509953550c25e5e8a2957fe30f5f07b16db4dddfc0b41fbfcaa3b36d869d98514a9d2890105b0bd4b5d66c928408a51892b968 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 9a762a16d22d7..4490665878b4d 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = d801e4545f548ab9061a018bf19db1944c711607 +PKG_SHA1 = 6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From b79856e7a84b7c945590cafae74efbeaf4d9d8f9 Mon Sep 17 00:00:00 2001 From: James Wrigley Date: Mon, 22 Jul 2024 18:47:20 +0200 Subject: [PATCH 031/206] Allowing disabling the default prompt suffix in `Base.getpass()` (#53614) By default `Base.getpass()` will append `: ` to the prompt, but sometimes that's undesirable, so now there's a `with_suffix` keyword argument to disable it. For context, my use-case is showing SSH prompts received from a server verbatim to the user. I did attempt to write a test for this but it would've required a lot of refactoring since `getpass()` is pretty hardcoded to expect input from `stdin` :\ An alternative design would be to have a `suffix=": "` argument instead, but I couldn't think of a good usecase for a user putting the prompt suffix in a separate argument instead of `message` itself. --------- Co-authored-by: Matt Bauman --- base/util.jl | 26 ++++-- contrib/generate_precompile.jl | 2 - stdlib/LibGit2/test/libgit2-tests.jl | 110 +----------------------- test/secretbuffer.jl | 29 +++++++ test/testhelpers/ChallengePrompts.jl | 123 +++++++++++++++++++++++++++ test/testhelpers/FakePTYs.jl | 1 - 6 files changed, 177 insertions(+), 114 deletions(-) create mode 100644 test/testhelpers/ChallengePrompts.jl diff --git a/base/util.jl b/base/util.jl index e9883650abc77..95d62c4a16e1d 100644 --- a/base/util.jl +++ b/base/util.jl @@ -271,15 +271,29 @@ function securezero! end unsafe_securezero!(p::Ptr{Cvoid}, len::Integer=1) = Ptr{Cvoid}(unsafe_securezero!(Ptr{UInt8}(p), len)) """ - Base.getpass(message::AbstractString) -> Base.SecretBuffer + Base.getpass(message::AbstractString; with_suffix::Bool=true) -> Base.SecretBuffer Display a message and wait for the user to input a secret, returning an `IO` -object containing the secret. +object containing the secret. If `with_suffix` is `true` (the default), the +suffix `": "` will be appended to `message`. !!! info "Windows" Note that on Windows, the secret might be displayed as it is typed; see `Base.winprompt` for securely retrieving username/password pairs from a graphical interface. + +!!! compat "Julia 1.12" + The `with_suffix` keyword argument requires at least Julia 1.12. + +# Examples + +```julia-repl +julia> Base.getpass("Secret") +Secret: SecretBuffer("*******") + +julia> Base.getpass("Secret> "; with_suffix=false) +Secret> SecretBuffer("*******") +``` """ function getpass end @@ -339,11 +353,13 @@ function with_raw_tty(f::Function, input::TTY) end end -function getpass(input::TTY, output::IO, prompt::AbstractString) +function getpass(input::TTY, output::IO, prompt::AbstractString; with_suffix::Bool=true) input === stdin || throw(ArgumentError("getpass only works for stdin")) with_raw_tty(stdin) do - print(output, prompt, ": ") + print(output, prompt) + with_suffix && print(output, ": ") flush(output) + s = SecretBuffer() plen = 0 while true @@ -364,7 +380,7 @@ end # allow new getpass methods to be defined if stdin has been # redirected to some custom stream, e.g. in IJulia. -getpass(prompt::AbstractString) = getpass(stdin, stdout, prompt) +getpass(prompt::AbstractString; with_suffix::Bool=true) = getpass(stdin, stdout, prompt; with_suffix) """ prompt(message; default="") -> Union{String, Nothing} diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 1152e20d16842..2a0e4faff7f1c 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -12,8 +12,6 @@ Sys.__init_build() if !isdefined(Base, :uv_eventloop) Base.reinit_stdio() end -Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl")) -import .FakePTYs: open_fake_pty using Base.Meta ## Debugging options diff --git a/stdlib/LibGit2/test/libgit2-tests.jl b/stdlib/LibGit2/test/libgit2-tests.jl index c5abca15ca719..72ca1019ff9e0 100644 --- a/stdlib/LibGit2/test/libgit2-tests.jl +++ b/stdlib/LibGit2/test/libgit2-tests.jl @@ -8,113 +8,11 @@ using Test using Random, Serialization, Sockets const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") -isdefined(Main, :FakePTYs) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "FakePTYs.jl")) -import .Main.FakePTYs: with_fake_pty - -const timeout = 60 - -function challenge_prompt(code::Expr, challenges) - input_code = tempname() - open(input_code, "w") do fp - serialize(fp, code) - end - output_file = tempname() - torun = """ - import LibGit2 - using Serialization - result = open($(repr(input_code))) do fp - eval(deserialize(fp)) - end - open($(repr(output_file)), "w") do fp - serialize(fp, result) - end""" - cmd = `$(Base.julia_cmd()) --startup-file=no -e $torun` - try - challenge_prompt(cmd, challenges) - return open(output_file, "r") do fp - deserialize(fp) - end - finally - isfile(output_file) && rm(output_file) - isfile(input_code) && rm(input_code) - end - return nothing -end +isdefined(Main, :ChallengePrompts) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "ChallengePrompts.jl")) +using .Main.ChallengePrompts: challenge_prompt as basic_challenge_prompt -function challenge_prompt(cmd::Cmd, challenges) - function format_output(output) - str = read(seekstart(output), String) - isempty(str) && return "" - return "Process output found:\n\"\"\"\n$str\n\"\"\"" - end - out = IOBuffer() - with_fake_pty() do pts, ptm - p = run(detach(cmd), pts, pts, pts, wait=false) # getpass uses stderr by default - Base.close_stdio(pts) - - # Kill the process if it takes too long. Typically occurs when process is waiting - # for input. - timer = Channel{Symbol}(1) - watcher = @async begin - waited = 0 - while waited < timeout && process_running(p) - sleep(1) - waited += 1 - end - - if process_running(p) - kill(p) - put!(timer, :timeout) - elseif success(p) - put!(timer, :success) - else - put!(timer, :failure) - end - - # SIGKILL stubborn processes - if process_running(p) - sleep(3) - process_running(p) && kill(p, Base.SIGKILL) - end - wait(p) - end - - wroteall = false - try - for (challenge, response) in challenges - write(out, readuntil(ptm, challenge, keep=true)) - if !isopen(ptm) - error("Could not locate challenge: \"$challenge\". ", - format_output(out)) - end - write(ptm, response) - end - wroteall = true - - # Capture output from process until `pts` is closed - write(out, ptm) - catch ex - if !(wroteall && ex isa Base.IOError && ex.code == Base.UV_EIO) - # ignore EIO from `ptm` after `pts` dies - error("Process failed possibly waiting for a response. ", - format_output(out)) - end - end - - status = fetch(timer) - close(ptm) - if status !== :success - if status === :timeout - error("Process timed out possibly waiting for a response. ", - format_output(out)) - else - error("Failed process. ", format_output(out), "\n", p) - end - end - wait(watcher) - end - nothing -end +challenge_prompt(code::Expr, challenges) = basic_challenge_prompt(code, challenges; pkgs=["LibGit2"]) +challenge_prompt(cmd::Cmd, challenges) = basic_challenge_prompt(cmd, challenges) const LIBGIT2_MIN_VER = v"1.0.0" const LIBGIT2_HELPER_PATH = joinpath(@__DIR__, "libgit2-helpers.jl") diff --git a/test/secretbuffer.jl b/test/secretbuffer.jl index 29e28ded8da72..703552570745c 100644 --- a/test/secretbuffer.jl +++ b/test/secretbuffer.jl @@ -1,5 +1,9 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") +isdefined(Main, :ChallengePrompts) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "ChallengePrompts.jl")) +using .Main.ChallengePrompts: challenge_prompt + using Base: SecretBuffer, SecretBuffer!, shred!, isshredded using Test, Random @@ -170,4 +174,29 @@ using Test, Random @test read(s5) == read(s6) == codeunits(str) shred!(s5); shred!(s6) end + + if !Sys.iswindows() + @testset "getpass" begin + v1, s1 = challenge_prompt(:(s=Base.getpass("LPAwVZM8D4I"); (read(s), Base.shred!(s))), ["LPAwVZM8D4I: " => "too many secrets\n"]) + s2 = SecretBuffer("too many secrets") + @test s1 isa SecretBuffer + @test isshredded(s1) + @test v1 == read(s2) == codeunits("too many secrets") + shred!(s1); shred!(s2) + + v3, s3 = challenge_prompt(:(s=Base.getpass("LPAwVZM8D4I> ", with_suffix=false); (read(s), Base.shred!(s))), ["LPAwVZM8D4I> " => "frperg\n"]) + s4 = SecretBuffer("frperg") + @test s3 isa SecretBuffer + @test isshredded(s3) + @test v3 == read(s4) == codeunits("frperg") + shred!(s3); shred!(s4) + + v5, s5 = challenge_prompt(:(s=Base.getpass("LPAwVZM8D4I> ", with_suffix=true); (read(s), Base.shred!(s))), ["LPAwVZM8D4I> : " => "frperg\n"]) + s6 = SecretBuffer("frperg") + @test s5 isa SecretBuffer + @test isshredded(s5) + @test v5 == read(s6) == codeunits("frperg") + shred!(s5); shred!(s6) + end + end end diff --git a/test/testhelpers/ChallengePrompts.jl b/test/testhelpers/ChallengePrompts.jl new file mode 100644 index 0000000000000..10dd1553afbbd --- /dev/null +++ b/test/testhelpers/ChallengePrompts.jl @@ -0,0 +1,123 @@ +module ChallengePrompts + +include("FakePTYs.jl") +using .FakePTYs: with_fake_pty +using Serialization: serialize, deserialize + +const timeout = 60 + +""" + challenge_prompt(code::Expr, challenges; pkgs=[]) + +Execute the passed code in a separate process, looking for +the passed prompts and responding as defined in the pairs of +(prompt, response) in the collection of challenges. + +Optionally `import` the given `pkgs`. + +Returns the value of the last expression. +""" +function challenge_prompt(code::Expr, challenges; pkgs=[]) + input_code = tempname() + open(input_code, "w") do fp + serialize(fp, code) + end + output_file = tempname() + torun = """ + $(isempty(pkgs) ? "" : string("import ", join(pkgs, ", "))) + using Serialization + result = open($(repr(input_code))) do fp + eval(deserialize(fp)) + end + open($(repr(output_file)), "w") do fp + serialize(fp, result) + end""" + cmd = `$(Base.julia_cmd()) --startup-file=no -e $torun` + try + challenge_prompt(cmd, challenges) + return open(output_file, "r") do fp + deserialize(fp) + end + finally + isfile(output_file) && rm(output_file) + isfile(input_code) && rm(input_code) + end + return nothing +end + +function challenge_prompt(cmd::Cmd, challenges) + function format_output(output) + str = read(seekstart(output), String) + isempty(str) && return "" + return "Process output found:\n\"\"\"\n$str\n\"\"\"" + end + out = IOBuffer() + with_fake_pty() do pts, ptm + p = run(detach(cmd), pts, pts, pts, wait=false) # getpass uses stderr by default + Base.close_stdio(pts) + + # Kill the process if it takes too long. Typically occurs when process is waiting + # for input. + timer = Channel{Symbol}(1) + watcher = @async begin + waited = 0 + while waited < timeout && process_running(p) + sleep(1) + waited += 1 + end + + if process_running(p) + kill(p) + put!(timer, :timeout) + elseif success(p) + put!(timer, :success) + else + put!(timer, :failure) + end + + # SIGKILL stubborn processes + if process_running(p) + sleep(3) + process_running(p) && kill(p, Base.SIGKILL) + end + wait(p) + end + + wroteall = false + try + for (challenge, response) in challenges + write(out, readuntil(ptm, challenge, keep=true)) + if !isopen(ptm) + error("Could not locate challenge: \"$challenge\". ", + format_output(out)) + end + write(ptm, response) + end + wroteall = true + + # Capture output from process until `pts` is closed + write(out, ptm) + catch ex + if !(wroteall && ex isa Base.IOError && ex.code == Base.UV_EIO) + # ignore EIO from `ptm` after `pts` dies + error("Process failed possibly waiting for a response. ", + format_output(out)) + end + end + + status = fetch(timer) + close(ptm) + if status !== :success + if status === :timeout + error("Process timed out possibly waiting for a response. ", + format_output(out)) + else + error("Failed process. ", format_output(out), "\n", p) + end + end + wait(watcher) + end + nothing +end + +end diff --git a/test/testhelpers/FakePTYs.jl b/test/testhelpers/FakePTYs.jl index c592699440ee0..c4dfe416de85a 100644 --- a/test/testhelpers/FakePTYs.jl +++ b/test/testhelpers/FakePTYs.jl @@ -1,5 +1,4 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license - module FakePTYs if Sys.iswindows() From 06467eb35c463dd4b957efc27651925edb3de35a Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 22 Jul 2024 18:02:29 -0400 Subject: [PATCH 032/206] correction to compat notice for a[begin] (#55209) Correction to #55197: `a[begin]` indexing was added in Julia 1.4 (#33946), not in Julia 1.6 (which just changed the implementation in #35779). My bad. --- base/docs/basedocs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index ad9c2e67fa917..635f1765627fa 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1389,8 +1389,8 @@ implicitly begin blocks of code. See also [`;`](@ref). collection or the first index of a dimension of an array. For example, `a[begin]` is the first element of an array `a`. -!!! compat "Julia 1.6" - Use of `begin` as an index requires Julia 1.6 or later. +!!! compat "Julia 1.4" + Use of `begin` as an index requires Julia 1.4 or later. # Examples ```jldoctest From b75c133b109332416381da81cade23e3479178a7 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:01:56 -0300 Subject: [PATCH 033/206] macOS: print stackoverflow warning if the overflow happened inside GC (#55211) See discussion in https://github.com/JuliaLang/julia/issues/55192. I'm not sure how easy it is to recover from a stack overflow inside the GC (or whether we should even try to do it), but we should at least print a stack overflow warning here IMO. --- src/signals-mach.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/signals-mach.c b/src/signals-mach.c index ad5788ea237e6..129cb8afb542f 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -294,10 +294,13 @@ static void segv_handler(int sig, siginfo_t *info, void *context) jl_task_t *ct = jl_get_current_task(); jl_ptls_t ptls = ct == NULL ? NULL : ct->ptls; jl_call_in_state(ptls, (host_thread_state_t*)jl_to_bt_context(context), &jl_sig_throw); + return; } - else { - sigdie_handler(sig, info, context); + jl_task_t *ct = jl_get_current_task(); + if ((sig != SIGBUS || info->si_code == BUS_ADRERR) && is_addr_on_stack(ct, info->si_addr)) { // stack overflow and not a BUS_ADRALN (alignment error) + stack_overflow_warning(); } + sigdie_handler(sig, info, context); } // n.b. mach_exc_server expects us to define this symbol locally From 6b08e80bd1217c5c2eb6c89604c21faa5b2a156f Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 22 Jul 2024 21:43:43 -0400 Subject: [PATCH 034/206] document mutable struct const fields (#55203) Introduced in https://github.com/JuliaLang/julia/pull/43305 --- base/docs/basedocs.jl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 635f1765627fa..00e4a0afb5c0e 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1451,8 +1451,20 @@ kw"struct" mutable struct `mutable struct` is similar to [`struct`](@ref), but additionally allows the -fields of the type to be set after construction. See the manual section on -[Composite Types](@ref) for more information. +fields of the type to be set after construction. + +Individual fields of a mutable struct can be marked as `const` to make them immutable: + +```julia +mutable struct Baz + a::Int + const b::Float64 +end +``` +!!! compat "Julia 1.8" + The `const` keyword for fields of mutable structs requires at least Julia 1.8. + +See the manual section on [Composite Types](@ref) for more information. """ kw"mutable struct" From 7ed506875149eb3cc8af149371527f6fc53c9fb8 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 23 Jul 2024 08:55:47 -0400 Subject: [PATCH 035/206] Profile: add threadpool names to `Profile.print` (#54994) --- base/threadingconstructs.jl | 18 ++++++++++++++++++ stdlib/Profile/src/Profile.jl | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 7212cb664f37e..479bcd80c586d 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -93,6 +93,24 @@ function threadpool(tid = threadid()) return _tpid_to_sym(tpid) end +""" + Threads.threadpooldescription(tid = threadid()) -> String + +Returns the specified thread's threadpool name with extended description where appropriate. +""" +function threadpooldescription(tid = threadid()) + threadpool_name = threadpool(tid) + if threadpool_name == :foreign + # TODO: extend tls to include a field to add a description to a foreign thread and make this more general + n_others = nthreads(:interactive) + nthreads(:default) + # Assumes GC threads come first in the foreign thread pool + if tid > n_others && tid <= n_others + ngcthreads() + return "foreign: gc" + end + end + return string(threadpool_name) +end + """ Threads.nthreadpools() -> Int diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 062b608b25c59..0a1f709a2ac60 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -280,7 +280,7 @@ function print(io::IO, nl = length(threadids) > 1 ? "\n" : "" printstyled(io, "Task $(Base.repr(taskid))$nl"; bold=true, color=Base.debug_color()) for threadid in threadids - printstyled(io, " Thread $threadid "; bold=true, color=Base.info_color()) + printstyled(io, " Thread $threadid ($(Threads.threadpooldescription(threadid))) "; bold=true, color=Base.info_color()) nosamples = print_group(io, data, lidict, pf, format, threadid, taskid, true) nosamples && (any_nosamples = true) println(io) @@ -296,7 +296,7 @@ function print(io::IO, any_nosamples = true else nl = length(taskids) > 1 ? "\n" : "" - printstyled(io, "Thread $threadid$nl"; bold=true, color=Base.info_color()) + printstyled(io, "Thread $threadid ($(Threads.threadpooldescription(threadid)))$nl"; bold=true, color=Base.info_color()) for taskid in taskids printstyled(io, " Task $(Base.repr(taskid)) "; bold=true, color=Base.debug_color()) nosamples = print_group(io, data, lidict, pf, format, threadid, taskid, true) @@ -320,7 +320,7 @@ function print(io::IO, threadids = intersect(get_thread_ids(data), threads) isempty(threadids) && (any_nosamples = true) for threadid in threadids - printstyled(io, "Thread $threadid "; bold=true, color=Base.info_color()) + printstyled(io, "Thread $threadid ($(Threads.threadpooldescription(threadid))) "; bold=true, color=Base.info_color()) nosamples = print_group(io, data, lidict, pf, format, threadid, tasks, true) nosamples && (any_nosamples = true) println(io) From fe207c5d29b2b2413e32be7fc7b029758dc1842c Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:31:52 -0300 Subject: [PATCH 036/206] NFC: rename pool_alloc to make the naming a bit more compatible with other GC impls (#55207) Other GC implementations may not want to necessarily segregate small objects into object pools (e.g. may just want to allocate everything with Libc malloc). Let's rename `pool_alloc` to `small_alloc` to make it a bit more general in the sense that although we're exposing different allocation functions, we make no mention to the fact that they're using object pools under the hood. --- src/gc.c | 20 ++++++++++---------- src/jl_exported_funcs.inc | 2 +- src/julia_internal.h | 6 +++--- src/llvm-final-gc-lowering.cpp | 6 +++--- src/llvm-pass-helpers.cpp | 14 +++++++------- src/llvm-pass-helpers.h | 4 ++-- test/compiler/codegen.jl | 16 ++++++++-------- test/llvmpasses/alloc-opt-gcframe.ll | 18 +++++++++--------- test/llvmpasses/alloc-opt-pipeline.jl | 2 +- test/llvmpasses/final-lower-gc.ll | 2 +- test/llvmpasses/julia-licm-fail.ll | 2 +- test/llvmpasses/julia-licm-missed.ll | 2 +- test/llvmpasses/julia-licm.ll | 2 +- test/llvmpasses/pipeline-o0.jl | 2 +- 14 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/gc.c b/src/gc.c index dbfd2d341cc69..a82ad615d8c2b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1248,7 +1248,7 @@ pagetable_t alloc_map; static NOINLINE jl_taggedvalue_t *gc_add_page(jl_gc_pool_t *p) JL_NOTSAFEPOINT { // Do not pass in `ptls` as argument. This slows down the fast path - // in pool_alloc significantly + // in small_alloc significantly jl_ptls_t ptls = jl_current_task->ptls; jl_gc_pagemeta_t *pg = jl_gc_alloc_page(); pg->osize = p->osize; @@ -1262,13 +1262,13 @@ static NOINLINE jl_taggedvalue_t *gc_add_page(jl_gc_pool_t *p) JL_NOTSAFEPOINT } // Size includes the tag and the tag is not cleared!! -STATIC_INLINE jl_value_t *jl_gc_pool_alloc_inner(jl_ptls_t ptls, int pool_offset, +STATIC_INLINE jl_value_t *jl_gc_small_alloc_inner(jl_ptls_t ptls, int offset, int osize) { // Use the pool offset instead of the pool address as the argument // to workaround a llvm bug. // Ref https://llvm.org/bugs/show_bug.cgi?id=27190 - jl_gc_pool_t *p = (jl_gc_pool_t*)((char*)ptls + pool_offset); + jl_gc_pool_t *p = (jl_gc_pool_t*)((char*)ptls + offset); assert(jl_atomic_load_relaxed(&ptls->gc_state) == 0); #ifdef MEMDEBUG return jl_gc_big_alloc(ptls, osize, NULL); @@ -1319,19 +1319,19 @@ STATIC_INLINE jl_value_t *jl_gc_pool_alloc_inner(jl_ptls_t ptls, int pool_offset return jl_valueof(v); } -// Instrumented version of jl_gc_pool_alloc_inner, called into by LLVM-generated code. -JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, int osize, jl_value_t* type) +// Instrumented version of jl_gc_small_alloc_inner, called into by LLVM-generated code. +JL_DLLEXPORT jl_value_t *jl_gc_small_alloc(jl_ptls_t ptls, int offset, int osize, jl_value_t* type) { - jl_value_t *val = jl_gc_pool_alloc_inner(ptls, pool_offset, osize); + jl_value_t *val = jl_gc_small_alloc_inner(ptls, offset, osize); maybe_record_alloc_to_profile(val, osize, (jl_datatype_t*)type); return val; } -// This wrapper exists only to prevent `jl_gc_pool_alloc_inner` from being inlined into -// its callers. We provide an external-facing interface for callers, and inline `jl_gc_pool_alloc_inner` +// This wrapper exists only to prevent `jl_gc_small_alloc_inner` from being inlined into +// its callers. We provide an external-facing interface for callers, and inline `jl_gc_small_alloc_inner` // into this. (See https://github.com/JuliaLang/julia/pull/43868 for more details.) -jl_value_t *jl_gc_pool_alloc_noinline(jl_ptls_t ptls, int pool_offset, int osize) { - return jl_gc_pool_alloc_inner(ptls, pool_offset, osize); +jl_value_t *jl_gc_small_alloc_noinline(jl_ptls_t ptls, int offset, int osize) { + return jl_gc_small_alloc_inner(ptls, offset, osize); } int jl_gc_classify_pools(size_t sz, int *osize) diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 3ec18b5b56c4f..246b666f942c1 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -168,7 +168,7 @@ XX(jl_gc_new_weakref) \ XX(jl_gc_new_weakref_th) \ XX(jl_gc_num) \ - XX(jl_gc_pool_alloc) \ + XX(jl_gc_small_alloc) \ XX(jl_gc_queue_multiroot) \ XX(jl_gc_queue_root) \ XX(jl_gc_safepoint) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index 19fb851686338..22c5cdb9a445f 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -346,7 +346,7 @@ extern _Atomic(jl_typemap_entry_t*) call_cache[N_CALL_CACHE] JL_GLOBALLY_ROOTED; JL_DLLEXPORT extern int jl_lineno; JL_DLLEXPORT extern const char *jl_filename; -jl_value_t *jl_gc_pool_alloc_noinline(jl_ptls_t ptls, int pool_offset, +jl_value_t *jl_gc_small_alloc_noinline(jl_ptls_t ptls, int offset, int osize); jl_value_t *jl_gc_big_alloc_noinline(jl_ptls_t ptls, size_t allocsz); JL_DLLEXPORT int jl_gc_classify_pools(size_t sz, int *osize) JL_NOTSAFEPOINT; @@ -504,9 +504,9 @@ STATIC_INLINE jl_value_t *jl_gc_alloc_(jl_ptls_t ptls, size_t sz, void *ty) int pool_id = jl_gc_szclass(allocsz); jl_gc_pool_t *p = &ptls->gc_tls.heap.norm_pools[pool_id]; int osize = jl_gc_sizeclasses[pool_id]; - // We call `jl_gc_pool_alloc_noinline` instead of `jl_gc_pool_alloc` to avoid double-counting in + // We call `jl_gc_small_alloc_noinline` instead of `jl_gc_small_alloc` to avoid double-counting in // the Allocations Profiler. (See https://github.com/JuliaLang/julia/pull/43868 for more details.) - v = jl_gc_pool_alloc_noinline(ptls, (char*)p - (char*)ptls, osize); + v = jl_gc_small_alloc_noinline(ptls, (char*)p - (char*)ptls, osize); } else { if (allocsz < sz) // overflow in adding offs, size was "negative" diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp index 1b0aaf505fb57..fe32e6d09a856 100644 --- a/src/llvm-final-gc-lowering.cpp +++ b/src/llvm-final-gc-lowering.cpp @@ -43,7 +43,7 @@ struct FinalLowerGC: private JuliaPassContext { private: Function *queueRootFunc; - Function *poolAllocFunc; + Function *smallAllocFunc; Function *bigAllocFunc; Function *allocTypedFunc; Instruction *pgcstack; @@ -202,7 +202,7 @@ void FinalLowerGC::lowerGCAllocBytes(CallInst *target, Function &F) else { auto pool_offs = ConstantInt::get(Type::getInt32Ty(F.getContext()), offset); auto pool_osize = ConstantInt::get(Type::getInt32Ty(F.getContext()), osize); - newI = builder.CreateCall(poolAllocFunc, { ptls, pool_offs, pool_osize, type }); + newI = builder.CreateCall(smallAllocFunc, { ptls, pool_offs, pool_osize, type }); if (sz > 0) derefBytes = sz; } @@ -238,7 +238,7 @@ bool FinalLowerGC::runOnFunction(Function &F) } LLVM_DEBUG(dbgs() << "FINAL GC LOWERING: Processing function " << F.getName() << "\n"); queueRootFunc = getOrDeclare(jl_well_known::GCQueueRoot); - poolAllocFunc = getOrDeclare(jl_well_known::GCPoolAlloc); + smallAllocFunc = getOrDeclare(jl_well_known::GCSmallAlloc); bigAllocFunc = getOrDeclare(jl_well_known::GCBigAlloc); allocTypedFunc = getOrDeclare(jl_well_known::GCAllocTyped); T_size = F.getParent()->getDataLayout().getIntPtrType(F.getContext()); diff --git a/src/llvm-pass-helpers.cpp b/src/llvm-pass-helpers.cpp index 0f498973671ec..cc6c73161968d 100644 --- a/src/llvm-pass-helpers.cpp +++ b/src/llvm-pass-helpers.cpp @@ -259,7 +259,7 @@ namespace jl_intrinsics { namespace jl_well_known { static const char *GC_BIG_ALLOC_NAME = XSTR(jl_gc_big_alloc); - static const char *GC_POOL_ALLOC_NAME = XSTR(jl_gc_pool_alloc); + static const char *GC_SMALL_ALLOC_NAME = XSTR(jl_gc_small_alloc); static const char *GC_QUEUE_ROOT_NAME = XSTR(jl_gc_queue_root); static const char *GC_ALLOC_TYPED_NAME = XSTR(jl_gc_alloc_typed); @@ -281,20 +281,20 @@ namespace jl_well_known { return addGCAllocAttributes(bigAllocFunc); }); - const WellKnownFunctionDescription GCPoolAlloc( - GC_POOL_ALLOC_NAME, + const WellKnownFunctionDescription GCSmallAlloc( + GC_SMALL_ALLOC_NAME, [](Type *T_size) { auto &ctx = T_size->getContext(); auto T_prjlvalue = JuliaType::get_prjlvalue_ty(ctx); - auto poolAllocFunc = Function::Create( + auto smallAllocFunc = Function::Create( FunctionType::get( T_prjlvalue, { PointerType::get(ctx, 0), Type::getInt32Ty(ctx), Type::getInt32Ty(ctx), T_size }, false), Function::ExternalLinkage, - GC_POOL_ALLOC_NAME); - poolAllocFunc->addFnAttr(Attribute::getWithAllocSizeArgs(ctx, 2, None)); - return addGCAllocAttributes(poolAllocFunc); + GC_SMALL_ALLOC_NAME); + smallAllocFunc->addFnAttr(Attribute::getWithAllocSizeArgs(ctx, 2, None)); + return addGCAllocAttributes(smallAllocFunc); }); const WellKnownFunctionDescription GCQueueRoot( diff --git a/src/llvm-pass-helpers.h b/src/llvm-pass-helpers.h index d0ac7faa01d2c..d46f1f46634e6 100644 --- a/src/llvm-pass-helpers.h +++ b/src/llvm-pass-helpers.h @@ -147,8 +147,8 @@ namespace jl_well_known { // `jl_gc_big_alloc`: allocates bytes. extern const WellKnownFunctionDescription GCBigAlloc; - // `jl_gc_pool_alloc`: allocates bytes. - extern const WellKnownFunctionDescription GCPoolAlloc; + // `jl_gc_small_alloc`: allocates bytes. + extern const WellKnownFunctionDescription GCSmallAlloc; // `jl_gc_queue_root`: queues a GC root. extern const WellKnownFunctionDescription GCQueueRoot; diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 529ee7b611448..3d719cbc244e4 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -222,18 +222,18 @@ if opt_level > 0 @test occursin("call i32 @memcmp(", compare_large_struct_ir) || occursin("call i32 @bcmp(", compare_large_struct_ir) @test !occursin("%gcframe", compare_large_struct_ir) - @test occursin("jl_gc_pool_alloc", get_llvm(MutableStruct, Tuple{})) + @test occursin("jl_gc_small_alloc", get_llvm(MutableStruct, Tuple{})) breakpoint_mutable_ir = get_llvm(breakpoint_mutable, Tuple{MutableStruct}) @test !occursin("%gcframe", breakpoint_mutable_ir) - @test !occursin("jl_gc_pool_alloc", breakpoint_mutable_ir) + @test !occursin("jl_gc_small_alloc", breakpoint_mutable_ir) breakpoint_badref_ir = get_llvm(breakpoint_badref, Tuple{MutableStruct}) @test !occursin("%gcframe", breakpoint_badref_ir) - @test !occursin("jl_gc_pool_alloc", breakpoint_badref_ir) + @test !occursin("jl_gc_small_alloc", breakpoint_badref_ir) breakpoint_ptrstruct_ir = get_llvm(breakpoint_ptrstruct, Tuple{RealStruct}) @test !occursin("%gcframe", breakpoint_ptrstruct_ir) - @test !occursin("jl_gc_pool_alloc", breakpoint_ptrstruct_ir) + @test !occursin("jl_gc_small_alloc", breakpoint_ptrstruct_ir) end function two_breakpoint(a::Float64) @@ -251,17 +251,17 @@ end if opt_level > 0 breakpoint_f64_ir = get_llvm((a)->ccall(:jl_breakpoint, Cvoid, (Ref{Float64},), a), Tuple{Float64}) - @test !occursin("jl_gc_pool_alloc", breakpoint_f64_ir) + @test !occursin("jl_gc_small_alloc", breakpoint_f64_ir) breakpoint_any_ir = get_llvm((a)->ccall(:jl_breakpoint, Cvoid, (Ref{Any},), a), Tuple{Float64}) - @test occursin("jl_gc_pool_alloc", breakpoint_any_ir) + @test occursin("jl_gc_small_alloc", breakpoint_any_ir) two_breakpoint_ir = get_llvm(two_breakpoint, Tuple{Float64}) - @test !occursin("jl_gc_pool_alloc", two_breakpoint_ir) + @test !occursin("jl_gc_small_alloc", two_breakpoint_ir) @test occursin("llvm.lifetime.end", two_breakpoint_ir) @test load_dummy_ref(1234) === 1234 load_dummy_ref_ir = get_llvm(load_dummy_ref, Tuple{Int}) - @test !occursin("jl_gc_pool_alloc", load_dummy_ref_ir) + @test !occursin("jl_gc_small_alloc", load_dummy_ref_ir) # Hopefully this is reliable enough. LLVM should be able to optimize this to a direct return. @test occursin("ret $Iptr %\"x::$(Int)\"", load_dummy_ref_ir) end diff --git a/test/llvmpasses/alloc-opt-gcframe.ll b/test/llvmpasses/alloc-opt-gcframe.ll index 3eaa0a871d029..e8644899f0914 100644 --- a/test/llvmpasses/alloc-opt-gcframe.ll +++ b/test/llvmpasses/alloc-opt-gcframe.ll @@ -12,7 +12,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; OPAQUE: %current_task = getelementptr inbounds ptr, ptr %gcstack, i64 -12 ; OPAQUE: [[ptls_field:%.*]] = getelementptr inbounds ptr, ptr %current_task, i64 16 ; OPAQUE-NEXT: [[ptls_load:%.*]] = load ptr, ptr [[ptls_field]], align 8, !tbaa !0 -; OPAQUE-NEXT: %v = call noalias nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr addrspace(10) @ijl_gc_pool_alloc(ptr [[ptls_load]], i32 [[SIZE_T:[0-9]+]], i32 16, i64 {{.*}} @tag {{.*}}) +; OPAQUE-NEXT: %v = call noalias nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr addrspace(10) @ijl_gc_small_alloc(ptr [[ptls_load]], i32 [[SIZE_T:[0-9]+]], i32 16, i64 {{.*}} @tag {{.*}}) ; OPAQUE: store atomic ptr addrspace(10) @tag, ptr addrspace(10) {{.*}} unordered, align 8, !tbaa !4 define {} addrspace(10)* @return_obj() { @@ -27,7 +27,7 @@ define {} addrspace(10)* @return_obj() { ; CHECK-LABEL: @return_load ; CHECK: alloca i64 ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK-NOT: @jl_gc_pool_alloc +; CHECK-NOT: @jl_gc_small_alloc ; OPAQUE: call void @llvm.lifetime.start{{.*}}(i64 8, ptr ; CHECK-NOT: @tag ; CHECK-NOT: @llvm.lifetime.end @@ -48,7 +48,7 @@ define i64 @return_load(i64 %i) { ; CHECK-LABEL: @ccall_obj ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK: @ijl_gc_pool_alloc +; CHECK: @ijl_gc_small_alloc ; OPAQUE: store atomic ptr addrspace(10) @tag, ptr addrspace(10) {{.*}} unordered, align 8, !tbaa !4 define void @ccall_obj(i8* %fptr) { %pgcstack = call {}*** @julia.get_pgcstack() @@ -65,7 +65,7 @@ define void @ccall_obj(i8* %fptr) { ; CHECK: alloca i64 ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK-NOT: @jl_gc_pool_alloc +; CHECK-NOT: @jl_gc_small_alloc ; OPAQUE: call void @llvm.lifetime.start{{.*}}(i64 8, ptr ; OPAQUE: %f = bitcast ptr %fptr to ptr ; Currently the GC frame lowering pass strips away all operand bundles @@ -88,7 +88,7 @@ define void @ccall_ptr(i8* %fptr) { ; CHECK-LABEL: @ccall_unknown_bundle ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK: @ijl_gc_pool_alloc +; CHECK: @ijl_gc_small_alloc ; OPAQUE: store atomic ptr addrspace(10) @tag, ptr addrspace(10) {{.*}} unordered, align 8, !tbaa !4 define void @ccall_unknown_bundle(i8* %fptr) { %pgcstack = call {}*** @julia.get_pgcstack() @@ -151,7 +151,7 @@ L3: ; CHECK-LABEL: @object_field ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK-NOT: @jl_gc_pool_alloc +; CHECK-NOT: @jl_gc_small_alloc ; CHECK-NOT: store {} addrspace(10)* @tag, {} addrspace(10)* addrspace(10)* {{.*}}, align 8, !tbaa !4 define void @object_field({} addrspace(10)* %field) { %pgcstack = call {}*** @julia.get_pgcstack() @@ -169,7 +169,7 @@ define void @object_field({} addrspace(10)* %field) { ; CHECK: alloca [16 x i8], align 16 ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK-NOT: @jl_gc_pool_alloc +; CHECK-NOT: @jl_gc_small_alloc ; OPAQUE: call void @llvm.memcpy.p0.p0.i64 define void @memcpy_opt(i8* %v22) { top: @@ -187,7 +187,7 @@ top: ; CHECK-LABEL: @preserve_opt ; OPAQUE: call ptr @julia.get_pgcstack() ; CHECK-NOT: @julia.gc_alloc_obj -; CHECK-NOT: @jl_gc_pool_alloc +; CHECK-NOT: @jl_gc_small_alloc ; CHECK-NOT: @llvm.lifetime.end ; CHECK: @external_function define void @preserve_opt(i8* %v22) { @@ -238,7 +238,7 @@ L3: } ; CHECK-LABEL: }{{$}} -; OPAQUE: declare noalias nonnull ptr addrspace(10) @ijl_gc_pool_alloc(ptr, +; OPAQUE: declare noalias nonnull ptr addrspace(10) @ijl_gc_small_alloc(ptr, ; OPAQUE: declare noalias nonnull ptr addrspace(10) @ijl_gc_big_alloc(ptr, declare void @external_function() declare {}*** @julia.get_pgcstack() diff --git a/test/llvmpasses/alloc-opt-pipeline.jl b/test/llvmpasses/alloc-opt-pipeline.jl index 9437913e4054b..e84348ec4a8c6 100644 --- a/test/llvmpasses/alloc-opt-pipeline.jl +++ b/test/llvmpasses/alloc-opt-pipeline.jl @@ -17,7 +17,7 @@ end # CHECK-LABEL: @julia_haszerolayout # CHECK: top: -# CHECK-NOT: @jl_gc_pool_alloc +# CHECK-NOT: @jl_gc_small_alloc # CHECK: extractelement # CHECK: ret i8 emit(haszerolayout, NTuple{32,VecElement{UInt8}}) diff --git a/test/llvmpasses/final-lower-gc.ll b/test/llvmpasses/final-lower-gc.ll index 705e57af94b7d..f8e123fdc6aea 100644 --- a/test/llvmpasses/final-lower-gc.ll +++ b/test/llvmpasses/final-lower-gc.ll @@ -58,7 +58,7 @@ top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %ptls_i8 = bitcast {}*** %ptls to i8* -; OPAQUE: %v = call noalias nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr addrspace(10) @ijl_gc_pool_alloc +; OPAQUE: %v = call noalias nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr addrspace(10) @ijl_gc_small_alloc %v = call {} addrspace(10)* @julia.gc_alloc_bytes(i8* %ptls_i8, i64 8, i64 12341234) %0 = bitcast {} addrspace(10)* %v to {} addrspace(10)* addrspace(10)* %1 = getelementptr {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %0, i64 -1 diff --git a/test/llvmpasses/julia-licm-fail.ll b/test/llvmpasses/julia-licm-fail.ll index 4b39a8f85050b..76ce19af96e94 100644 --- a/test/llvmpasses/julia-licm-fail.ll +++ b/test/llvmpasses/julia-licm-fail.ll @@ -73,7 +73,7 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 declare void @ijl_gc_queue_root({} addrspace(10)*) #3 ; Function Attrs: allocsize(1) -declare noalias nonnull {} addrspace(10)* @ijl_gc_pool_alloc(i8*, i32, i32, i8*) #1 +declare noalias nonnull {} addrspace(10)* @ijl_gc_small_alloc(i8*, i32, i32, i8*) #1 ; Function Attrs: allocsize(1) declare noalias nonnull {} addrspace(10)* @ijl_gc_big_alloc(i8*, i64) #1 diff --git a/test/llvmpasses/julia-licm-missed.ll b/test/llvmpasses/julia-licm-missed.ll index 3d4c9112c857b..37a547c9861b7 100644 --- a/test/llvmpasses/julia-licm-missed.ll +++ b/test/llvmpasses/julia-licm-missed.ll @@ -86,7 +86,7 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 declare void @ijl_gc_queue_root({} addrspace(10)*) #3 ; Function Attrs: allocsize(1) -declare noalias nonnull {} addrspace(10)* @ijl_gc_pool_alloc(i8*, i32, i32, i8*) #1 +declare noalias nonnull {} addrspace(10)* @ijl_gc_small_alloc(i8*, i32, i32, i8*) #1 ; Function Attrs: allocsize(1) declare noalias nonnull {} addrspace(10)* @ijl_gc_big_alloc(i8*, i64) #1 diff --git a/test/llvmpasses/julia-licm.ll b/test/llvmpasses/julia-licm.ll index 84c990140ce10..732b62788f13c 100644 --- a/test/llvmpasses/julia-licm.ll +++ b/test/llvmpasses/julia-licm.ll @@ -152,7 +152,7 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 declare void @ijl_gc_queue_root({} addrspace(10)*) #3 ; Function Attrs: allocsize(1) -declare noalias nonnull {} addrspace(10)* @ijl_gc_pool_alloc(i8*, i32, i32, i8*) #1 +declare noalias nonnull {} addrspace(10)* @ijl_gc_small_alloc(i8*, i32, i32, i8*) #1 ; Function Attrs: allocsize(1) declare noalias nonnull {} addrspace(10)* @ijl_gc_big_alloc(i8*, i64) #1 diff --git a/test/llvmpasses/pipeline-o0.jl b/test/llvmpasses/pipeline-o0.jl index 1075d126c59ca..5dab675f2b547 100644 --- a/test/llvmpasses/pipeline-o0.jl +++ b/test/llvmpasses/pipeline-o0.jl @@ -10,7 +10,7 @@ include(joinpath("..", "testhelpers", "llvmpasses.jl")) # CHECK-LABEL: @julia_simple # CHECK-NOT: julia.get_pgcstack # CHECK-NOT: julia.gc_alloc_obj -# CHECK: ijl_gc_pool_alloc +# CHECK: ijl_gc_small_alloc # COM: we want something vaguely along the lines of asm load from the fs register -> allocate bytes function simple() Ref(0) From d68befdc0d3479cc3cb8cce64aa8c380253d2f5d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 23 Jul 2024 11:51:41 -0400 Subject: [PATCH 037/206] Make Core.TypeofUnion use the type method table (#55188) Ensures that adding or examining the methods of Type{Union{}} in the method table returns the correct results. Fixes #55187 --- src/jltypes.c | 7 +++++-- test/reflection.jl | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index b8a81f94a7931..10b8bc937939e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3581,8 +3581,11 @@ void jl_init_types(void) JL_GC_DISABLED jl_emptysvec, 0, 0, 4); // all Kinds share the Type method table (not the nonfunction one) - jl_unionall_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt = - jl_type_type_mt; + jl_unionall_type->name->mt = + jl_uniontype_type->name->mt = + jl_datatype_type->name->mt = + jl_typeofbottom_type->name->mt = + jl_type_type_mt; jl_intrinsic_type = jl_new_primitivetype((jl_value_t*)jl_symbol("IntrinsicFunction"), core, jl_builtin_type, jl_emptysvec, 32); diff --git a/test/reflection.jl b/test/reflection.jl index 895da80e03c75..ef940b034a2e1 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1296,3 +1296,5 @@ end @test Base.infer_return_type(code_lowered, (Any,)) == Vector{Core.CodeInfo} @test Base.infer_return_type(code_lowered, (Any,Any)) == Vector{Core.CodeInfo} + +@test methods(Union{}) == Any[m.method for m in Base._methods_by_ftype(Tuple{Core.TypeofBottom, Vararg}, 1, Base.get_world_counter())] # issue #55187 From fe597c1e60f4984bff2f76ac7ae6702e2e151a18 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 23 Jul 2024 11:52:17 -0400 Subject: [PATCH 038/206] compress jit debuginfo for easy memory savings (#55180) In some ad-hoc testing, I had JIT about 19 MB of code and data, which generated about 170 MB of debuginfo alongside it, and that debuginfo then compressed to about 50 MB with this change, which simply compresses the ObjectFile until it is actually required (which it very rarely is needed). --- src/debug-registry.h | 22 +++++++---- src/debuginfo.cpp | 57 ++++++++++++++++++++------- src/debuginfo.h | 1 + src/jitlayers.cpp | 93 ++++++++++++++++---------------------------- src/jitlayers.h | 3 +- 5 files changed, 94 insertions(+), 82 deletions(-) diff --git a/src/debug-registry.h b/src/debug-registry.h index f30049eb5b210..85a94245ce6aa 100644 --- a/src/debug-registry.h +++ b/src/debug-registry.h @@ -99,18 +99,26 @@ class JITDebugInfoRegistry }; private: - struct ObjectInfo { - const llvm::object::ObjectFile *object = nullptr; - size_t SectionSize = 0; - ptrdiff_t slide = 0; - llvm::object::SectionRef Section{}; - llvm::DIContext *context = nullptr; + struct LazyObjectInfo { + SmallVector data; + size_t uncompressedsize; + std::unique_ptr object; + std::unique_ptr context; + LazyObjectInfo() = delete; + }; + + struct SectionInfo { + LazyObjectInfo *object; + size_t SectionSize; + ptrdiff_t slide; + uint64_t SectionIndex; + SectionInfo() = delete; }; template using rev_map = std::map>; - typedef rev_map objectmap_t; + typedef rev_map objectmap_t; typedef rev_map objfilemap_t; objectmap_t objectmap{}; diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 5cb7401a036d4..84550811072fe 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -335,8 +336,12 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object, #endif // defined(_OS_X86_64_) #endif // defined(_OS_WINDOWS_) + SmallVector packed; + compression::zlib::compress(ArrayRef((uint8_t*)Object.getData().data(), Object.getData().size()), packed, compression::zlib::DefaultCompression); + jl_jit_add_bytes(packed.size()); + auto ObjectCopy = new LazyObjectInfo{packed, Object.getData().size()}; // intentionally leaked so that we don't need to ref-count it, intentionally copied so that we exact-size the allocation (since no shrink_to_fit function) auto symbols = object::computeSymbolSizes(Object); - bool first = true; + bool hassection = false; for (const auto &sym_size : symbols) { const object::SymbolRef &sym_iter = sym_size.first; object::SymbolRef::Type SymbolType = cantFail(sym_iter.getType()); @@ -385,17 +390,17 @@ void JITDebugInfoRegistry::registerJITObject(const object::ObjectFile &Object, jl_profile_atomic([&]() JL_NOTSAFEPOINT { if (mi) linfomap[Addr] = std::make_pair(Size, mi); - if (first) { - objectmap[SectionLoadAddr] = {&Object, - (size_t)SectionSize, - (ptrdiff_t)(SectionAddr - SectionLoadAddr), - *Section, - nullptr, - }; - first = false; - } + hassection = true; + objectmap.insert(std::pair{SectionLoadAddr, SectionInfo{ + ObjectCopy, + (size_t)SectionSize, + (ptrdiff_t)(SectionAddr - SectionLoadAddr), + Section->getIndex() + }}); }); } + if (!hassection) // clang-sa demands that we do this to fool cplusplus.NewDeleteLeaks + delete ObjectCopy; } void jl_register_jit_object(const object::ObjectFile &Object, @@ -1213,11 +1218,33 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, auto fit = objmap.lower_bound(fptr); if (fit != objmap.end() && fptr < fit->first + fit->second.SectionSize) { *slide = fit->second.slide; - *Section = fit->second.Section; - if (context) { - if (fit->second.context == nullptr) - fit->second.context = DWARFContext::create(*fit->second.object).release(); - *context = fit->second.context; + auto lazyobject = fit->second.object; + if (!lazyobject->object && !lazyobject->data.empty()) { + if (lazyobject->uncompressedsize) { + SmallVector unpacked; + Error E = compression::zlib::decompress(lazyobject->data, unpacked, lazyobject->uncompressedsize); + if (E) + lazyobject->data.clear(); + else + lazyobject->data = std::move(unpacked); + jl_jit_add_bytes(lazyobject->data.size() - lazyobject->uncompressedsize); + lazyobject->uncompressedsize = 0; + } + if (!lazyobject->data.empty()) { + auto obj = object::ObjectFile::createObjectFile(MemoryBufferRef(StringRef((const char*)lazyobject->data.data(), lazyobject->data.size()), "jit.o")); + if (obj) + lazyobject->object = std::move(*obj); + else + lazyobject->data.clear(); + } + } + if (lazyobject->object) { + *Section = *std::next(lazyobject->object->section_begin(), fit->second.SectionIndex); + if (context) { + if (lazyobject->context == nullptr) + lazyobject->context = DWARFContext::create(*lazyobject->object); + *context = lazyobject->context.get(); + } } found = 1; } diff --git a/src/debuginfo.h b/src/debuginfo.h index 5b5cdcb82d534..6cd7528910765 100644 --- a/src/debuginfo.h +++ b/src/debuginfo.h @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license // Declarations for debuginfo.cpp +void jl_jit_add_bytes(size_t bytes) JL_NOTSAFEPOINT; int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide, llvm::object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT; diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 6c40f4230ab69..487e6a0462500 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -684,22 +684,19 @@ struct JITObjectInfo { class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin { std::mutex PluginMutex; std::map> PendingObjs; - // Resources from distinct `MaterializationResponsibility`s can get merged - // after emission, so we can have multiple debug objects per resource key. - std::map, 0>> RegisteredObjs; public: void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx, MemoryBufferRef InputObject) override { - // Keeping around a full copy of the input object file (and re-parsing it) is - // wasteful, but for now, this lets us reuse the existing debuginfo.cpp code. - // Should look into just directly pulling out all the information required in - // a JITLink pass and just keeping the required tables/DWARF sections around - // (perhaps using the LLVM DebuggerSupportPlugin as a reference). auto NewBuffer = MemoryBuffer::getMemBufferCopy(InputObject.getBuffer(), G.getName()); + // Re-parsing the InputObject is wasteful, but for now, this lets us + // reuse the existing debuginfo.cpp code. Should look into just + // directly pulling out all the information required in a JITLink pass + // and just keeping the required tables/DWARF sections around (perhaps + // using the LLVM DebuggerSupportPlugin as a reference). auto NewObj = cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef())); @@ -733,13 +730,8 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin { }; jl_register_jit_object(*NewInfo->Object, getLoadAddress, nullptr); - } - - cantFail(MR.withResourceKeyDo([&](ResourceKey K) { - std::lock_guard lock(PluginMutex); - RegisteredObjs[K].push_back(std::move(PendingObjs[&MR])); PendingObjs.erase(&MR); - })); + } return Error::success(); } @@ -750,32 +742,23 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin { PendingObjs.erase(&MR); return Error::success(); } + #if JL_LLVM_VERSION >= 160000 Error notifyRemovingResources(JITDylib &JD, orc::ResourceKey K) override #else - Error notifyRemovingResources(ResourceKey K) override + Error notifyRemovingResources(orc::ResourceKey K) override #endif { - std::lock_guard lock(PluginMutex); - RegisteredObjs.erase(K); - // TODO: If we ever unload code, need to notify debuginfo registry. return Error::success(); } #if JL_LLVM_VERSION >= 160000 - void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override + void notifyTransferringResources(JITDylib &JD, orc::ResourceKey DstKey, + orc::ResourceKey SrcKey) override {} #else - void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override + void notifyTransferringResources(orc::ResourceKey DstKey, + orc::ResourceKey SrcKey) override {} #endif - { - std::lock_guard lock(PluginMutex); - auto SrcIt = RegisteredObjs.find(SrcKey); - if (SrcIt != RegisteredObjs.end()) { - for (std::unique_ptr &Info : SrcIt->second) - RegisteredObjs[DstKey].push_back(std::move(Info)); - RegisteredObjs.erase(SrcIt); - } - } void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &, jitlink::PassConfiguration &PassConfig) override @@ -815,12 +798,12 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin { class JLMemoryUsagePlugin : public ObjectLinkingLayer::Plugin { private: - std::atomic &total_size; + std::atomic &jit_bytes_size; public: - JLMemoryUsagePlugin(std::atomic &total_size) - : total_size(total_size) {} + JLMemoryUsagePlugin(std::atomic &jit_bytes_size) + : jit_bytes_size(jit_bytes_size) {} Error notifyFailed(orc::MaterializationResponsibility &MR) override { return Error::success(); @@ -869,7 +852,7 @@ class JLMemoryUsagePlugin : public ObjectLinkingLayer::Plugin { } (void) code_size; (void) data_size; - this->total_size.fetch_add(graph_size, std::memory_order_relaxed); + this->jit_bytes_size.fetch_add(graph_size, std::memory_order_relaxed); jl_timing_counter_inc(JL_TIMING_COUNTER_JITSize, graph_size); jl_timing_counter_inc(JL_TIMING_COUNTER_JITCodeSize, code_size); jl_timing_counter_inc(JL_TIMING_COUNTER_JITDataSize, data_size); @@ -985,24 +968,7 @@ void registerRTDyldJITObject(const object::ObjectFile &Object, const RuntimeDyld::LoadedObjectInfo &L, const std::shared_ptr &MemMgr) { - auto SavedObject = L.getObjectForDebug(Object).takeBinary(); - // If the debug object is unavailable, save (a copy of) the original object - // for our backtraces. - // This copy seems unfortunate, but there doesn't seem to be a way to take - // ownership of the original buffer. - if (!SavedObject.first) { - auto NewBuffer = - MemoryBuffer::getMemBufferCopy(Object.getData(), Object.getFileName()); - auto NewObj = - cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef())); - SavedObject = std::make_pair(std::move(NewObj), std::move(NewBuffer)); - } - const object::ObjectFile *DebugObj = SavedObject.first.release(); - SavedObject.second.release(); - StringMap loadedSections; - // Use the original Object, not the DebugObject, as this is used for the - // RuntimeDyld::LoadedObjectInfo lookup. for (const object::SectionRef &lSection : Object.sections()) { auto sName = lSection.getName(); if (sName) { @@ -1019,7 +985,9 @@ void registerRTDyldJITObject(const object::ObjectFile &Object, return L.getSectionLoadAddress(search->second); }; - jl_register_jit_object(*DebugObj, getLoadAddress, + auto DebugObject = L.getObjectForDebug(Object); // ELF requires us to make a copy to mutate the header with the section load addresses. On other platforms this is a no-op. + jl_register_jit_object(DebugObject.getBinary() ? *DebugObject.getBinary() : Object, + getLoadAddress, #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) [MemMgr](void *p) { return lookupWriteAddressFor(MemMgr.get(), p); } #else @@ -1630,7 +1598,7 @@ JuliaOJIT::JuliaOJIT() ES, std::move(ehRegistrar))); ObjectLayer.addPlugin(std::make_unique()); - ObjectLayer.addPlugin(std::make_unique(total_size)); + ObjectLayer.addPlugin(std::make_unique(jit_bytes_size)); #else ObjectLayer.setNotifyLoaded( [this](orc::MaterializationResponsibility &MR, @@ -2042,19 +2010,20 @@ std::string JuliaOJIT::getMangledName(const GlobalValue *GV) return getMangledName(GV->getName()); } -#ifdef JL_USE_JITLINK size_t JuliaOJIT::getTotalBytes() const { - return total_size.load(std::memory_order_relaxed); + auto bytes = jit_bytes_size.load(std::memory_order_relaxed); +#ifndef JL_USE_JITLINK + size_t getRTDyldMemoryManagerTotalBytes(RTDyldMemoryManager *mm) JL_NOTSAFEPOINT; + bytes += getRTDyldMemoryManagerTotalBytes(MemMgr.get()); +#endif + return bytes; } -#else -size_t getRTDyldMemoryManagerTotalBytes(RTDyldMemoryManager *mm) JL_NOTSAFEPOINT; -size_t JuliaOJIT::getTotalBytes() const +void JuliaOJIT::addBytes(size_t bytes) { - return getRTDyldMemoryManagerTotalBytes(MemMgr.get()); + jit_bytes_size.fetch_add(bytes, std::memory_order_relaxed); } -#endif void JuliaOJIT::printTimers() { @@ -2339,3 +2308,9 @@ size_t jl_jit_total_bytes_impl(void) { return jl_ExecutionEngine->getTotalBytes(); } + +// API for adding bytes to record being owned by the JIT +void jl_jit_add_bytes(size_t bytes) +{ + jl_ExecutionEngine->addBytes(bytes); +} diff --git a/src/jitlayers.h b/src/jitlayers.h index 1eea3692aec71..101f5714abd11 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -559,6 +559,7 @@ class JuliaOJIT { TargetIRAnalysis getTargetIRAnalysis() const JL_NOTSAFEPOINT; size_t getTotalBytes() const JL_NOTSAFEPOINT; + void addBytes(size_t bytes) JL_NOTSAFEPOINT; void printTimers() JL_NOTSAFEPOINT; jl_locked_stream &get_dump_emitted_mi_name_stream() JL_NOTSAFEPOINT { @@ -605,10 +606,10 @@ class JuliaOJIT { ResourcePool> ContextPool; + std::atomic jit_bytes_size{0}; #ifndef JL_USE_JITLINK const std::shared_ptr MemMgr; #else - std::atomic total_size{0}; const std::unique_ptr MemMgr; #endif ObjLayerT ObjectLayer; From fc17b1456aeb42b75f61e96f19887327d35a0c19 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 23 Jul 2024 21:07:46 +0200 Subject: [PATCH 039/206] change back an `eachindex` to `1:length` where it made more sense (#55221) Ref https://github.com/JuliaLang/julia/pull/55137/files/53345774673eecabc0aa015fb9e228c256bdff73#diff-abc81972c168887f1ef7dcd20d5faa41849209524dab40b8d42f7ead3dc84c46 --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 13ac4c9bfaf48..c73ef68551266 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -978,7 +978,7 @@ end Return an array with element type `T` (default `Int`) of the digits of `n` in the given base, optionally padded with zeros to a specified size. More significant digits are at -higher indices, such that `n == sum(digits[k]*base^(k-1) for k in eachindex(digits))`. +higher indices, such that `n == sum(digits[k]*base^(k-1) for k in 1:length(digits))`. See also [`ndigits`](@ref), [`digits!`](@ref), and for base 2 also [`bitstring`](@ref), [`count_ones`](@ref). From 59074fa70d1edcbce45e9569ae2fef3d0aa3bc90 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 23 Jul 2024 21:15:42 +0200 Subject: [PATCH 040/206] Artifacts: use a different way of getting the UUID of a module (#55218) --- stdlib/Artifacts/src/Artifacts.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index bd44369655ae4..bfc884cc30634 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -545,10 +545,10 @@ function jointail(dir, tail) end function _artifact_str(__module__, artifacts_toml, name, path_tail, artifact_dict, hash, platform, @nospecialize(lazyartifacts)) - moduleroot = Base.moduleroot(__module__) - if haskey(Base.module_keys, moduleroot) + pkg = Base.PkgId(__module__) + if pkg.uuid !== nothing # Process overrides for this UUID, if we know what it is - process_overrides(artifact_dict, Base.module_keys[moduleroot].uuid) + process_overrides(artifact_dict, pkg.uuid) end # If the artifact exists, we're in the happy path and we can immediately From 00557473caba11ea08f0e5afe7bb6fefa838cbc4 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Wed, 24 Jul 2024 00:13:08 -0300 Subject: [PATCH 041/206] remove a bunch of 'skip GC threads' checks since they now have tasks (#55160) GC threads now have tasks (since https://github.com/JuliaLang/julia/pull/53815). --- src/gc-stacks.c | 8 -------- src/gc.h | 10 ++++++++++ src/stackwalk.c | 11 ++++++++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/gc-stacks.c b/src/gc-stacks.c index c9d2b188f8836..2f6075b56b8ef 100644 --- a/src/gc-stacks.c +++ b/src/gc-stacks.c @@ -332,10 +332,6 @@ JL_DLLEXPORT jl_array_t *jl_live_tasks(void) size_t l = 0; // l is not reset on restart, so we keep getting more aggressive at making a big enough list everything it fails restart: for (size_t i = 0; i < nthreads; i++) { - // skip GC threads since they don't have tasks - if (gc_first_tid <= i && i < gc_first_tid + jl_n_gcthreads) { - continue; - } jl_ptls_t ptls2 = allstates[i]; if (ptls2 == NULL) continue; @@ -349,10 +345,6 @@ JL_DLLEXPORT jl_array_t *jl_live_tasks(void) allstates = jl_atomic_load_relaxed(&jl_all_tls_states); size_t j = 0; for (size_t i = 0; i < nthreads; i++) { - // skip GC threads since they don't have tasks - if (gc_first_tid <= i && i < gc_first_tid + jl_n_gcthreads) { - continue; - } jl_ptls_t ptls2 = allstates[i]; if (ptls2 == NULL) continue; diff --git a/src/gc.h b/src/gc.h index b49f81a5a0c5a..6ab1b4f816f2e 100644 --- a/src/gc.h +++ b/src/gc.h @@ -478,6 +478,16 @@ STATIC_INLINE int gc_is_parallel_collector_thread(int tid) JL_NOTSAFEPOINT return tid >= gc_first_tid && tid <= gc_last_parallel_collector_thread_id(); } +STATIC_INLINE int gc_is_concurrent_collector_thread(int tid) JL_NOTSAFEPOINT +{ + if (jl_n_sweepthreads == 0) { + return 0; + } + int last_parallel_collector_thread_id = gc_last_parallel_collector_thread_id(); + int concurrent_collector_thread_id = last_parallel_collector_thread_id + 1; + return tid == concurrent_collector_thread_id; +} + STATIC_INLINE int gc_random_parallel_collector_thread_id(jl_ptls_t ptls) JL_NOTSAFEPOINT { assert(jl_n_markthreads > 0); diff --git a/src/stackwalk.c b/src/stackwalk.c index 3dcb310c14d51..d6bed827e19ae 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -5,6 +5,7 @@ utilities for walking the stack and looking up information about code addresses */ #include +#include "gc.h" #include "julia.h" #include "julia_internal.h" #include "threading.h" @@ -1215,11 +1216,15 @@ JL_DLLEXPORT void jl_print_task_backtraces(int show_done) JL_NOTSAFEPOINT size_t nthreads = jl_atomic_load_acquire(&jl_n_threads); jl_ptls_t *allstates = jl_atomic_load_relaxed(&jl_all_tls_states); for (size_t i = 0; i < nthreads; i++) { - // skip GC threads since they don't have tasks - if (gc_first_tid <= i && i < gc_first_tid + jl_n_gcthreads) { + jl_ptls_t ptls2 = allstates[i]; + if (gc_is_parallel_collector_thread(i)) { + jl_safe_printf("==== Skipping backtrace for parallel GC thread %zu\n", i + 1); + continue; + } + if (gc_is_concurrent_collector_thread(i)) { + jl_safe_printf("==== Skipping backtrace for concurrent GC thread %zu\n", i + 1); continue; } - jl_ptls_t ptls2 = allstates[i]; if (ptls2 == NULL) { continue; } From 24cfe6e2cc779c2b2d05dae3d2dce1da1424970a Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:36:54 +0900 Subject: [PATCH 042/206] inference: refine branched `Conditional` types (#55216) Separated from JuliaLang/julia#40880. This subtle adjustment allows for more accurate type inference in the following kind of cases: ```julia function condition_object_update2(x) cond = x isa Int if cond # `cond` is known to be `Const(true)` within this branch return !cond ? nothing : x # ::Int else return cond ? nothing : 1 # ::Int end end @test Base.infer_return_type(condition_object_update2, (Any,)) == Int ``` Also cleans up typelattice.jl a bit. --- base/compiler/abstractinterpretation.jl | 60 +++++++++++------ base/compiler/typelattice.jl | 23 ------- test/compiler/inference.jl | 87 ++++++++++++------------- 3 files changed, 82 insertions(+), 88 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index f34b1e716a271..d441d994034a5 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -3067,7 +3067,7 @@ end @inline function abstract_eval_basic_statement(interp::AbstractInterpreter, @nospecialize(stmt), pc_vartable::VarTable, frame::InferenceState) if isa(stmt, NewvarNode) - changes = StateUpdate(stmt.slot, VarState(Bottom, true), pc_vartable, false) + changes = StateUpdate(stmt.slot, VarState(Bottom, true), false) return BasicStmtChange(changes, nothing, Union{}) elseif !isa(stmt, Expr) (; rt, exct) = abstract_eval_statement(interp, stmt, pc_vartable, frame) @@ -3082,7 +3082,7 @@ end end lhs = stmt.args[1] if isa(lhs, SlotNumber) - changes = StateUpdate(lhs, VarState(rt, false), pc_vartable, false) + changes = StateUpdate(lhs, VarState(rt, false), false) elseif isa(lhs, GlobalRef) handle_global_assignment!(interp, frame, lhs, rt) elseif !isa(lhs, SSAValue) @@ -3092,7 +3092,7 @@ end elseif hd === :method fname = stmt.args[1] if isa(fname, SlotNumber) - changes = StateUpdate(fname, VarState(Any, false), pc_vartable, false) + changes = StateUpdate(fname, VarState(Any, false), false) end return BasicStmtChange(changes, nothing, Union{}) elseif (hd === :code_coverage_effect || ( @@ -3242,7 +3242,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) @goto branch elseif isa(stmt, GotoIfNot) condx = stmt.cond - condxslot = ssa_def_slot(condx, frame) + condslot = ssa_def_slot(condx, frame) condt = abstract_eval_value(interp, condx, currstate, frame) if condt === Bottom ssavaluetypes[currpc] = Bottom @@ -3250,10 +3250,10 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) @goto find_next_bb end orig_condt = condt - if !(isa(condt, Const) || isa(condt, Conditional)) && isa(condxslot, SlotNumber) + if !(isa(condt, Const) || isa(condt, Conditional)) && isa(condslot, SlotNumber) # if this non-`Conditional` object is a slot, we form and propagate # the conditional constraint on it - condt = Conditional(condxslot, Const(true), Const(false)) + condt = Conditional(condslot, Const(true), Const(false)) end condval = maybe_extract_const_bool(condt) nothrow = (condval !== nothing) || ⊑(𝕃ᵢ, orig_condt, Bool) @@ -3299,21 +3299,31 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) # We continue with the true branch, but process the false # branch here. if isa(condt, Conditional) - else_change = conditional_change(𝕃ᵢ, currstate, condt.elsetype, condt.slot) + else_change = conditional_change(𝕃ᵢ, currstate, condt, #=then_or_else=#false) if else_change !== nothing - false_vartable = stoverwrite1!(copy(currstate), else_change) + elsestate = copy(currstate) + stoverwrite1!(elsestate, else_change) + elseif condslot isa SlotNumber + elsestate = copy(currstate) else - false_vartable = currstate + elsestate = currstate end - changed = update_bbstate!(𝕃ᵢ, frame, falsebb, false_vartable) - then_change = conditional_change(𝕃ᵢ, currstate, condt.thentype, condt.slot) + if condslot isa SlotNumber # refine the type of this conditional object itself for this else branch + stoverwrite1!(elsestate, condition_object_change(currstate, condt, condslot, #=then_or_else=#false)) + end + else_changed = update_bbstate!(𝕃ᵢ, frame, falsebb, elsestate) + then_change = conditional_change(𝕃ᵢ, currstate, condt, #=then_or_else=#true) + thenstate = currstate if then_change !== nothing - stoverwrite1!(currstate, then_change) + stoverwrite1!(thenstate, then_change) + end + if condslot isa SlotNumber # refine the type of this conditional object itself for this then branch + stoverwrite1!(thenstate, condition_object_change(currstate, condt, condslot, #=then_or_else=#true)) end else - changed = update_bbstate!(𝕃ᵢ, frame, falsebb, currstate) + else_changed = update_bbstate!(𝕃ᵢ, frame, falsebb, currstate) end - if changed + if else_changed handle_control_backedge!(interp, frame, currpc, stmt.dest) push!(W, falsebb) end @@ -3412,13 +3422,14 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) nothing end -function conditional_change(𝕃ᵢ::AbstractLattice, state::VarTable, @nospecialize(typ), slot::Int) - vtype = state[slot] +function conditional_change(𝕃ᵢ::AbstractLattice, currstate::VarTable, condt::Conditional, then_or_else::Bool) + vtype = currstate[condt.slot] oldtyp = vtype.typ - if iskindtype(typ) + newtyp = then_or_else ? condt.thentype : condt.elsetype + if iskindtype(newtyp) # this code path corresponds to the special handling for `isa(x, iskindtype)` check # implemented within `abstract_call_builtin` - elseif ⊑(𝕃ᵢ, ignorelimited(typ), ignorelimited(oldtyp)) + elseif ⊑(𝕃ᵢ, ignorelimited(newtyp), ignorelimited(oldtyp)) # approximate test for `typ ∩ oldtyp` being better than `oldtyp` # since we probably formed these types with `typesubstract`, # the comparison is likely simple @@ -3428,9 +3439,18 @@ function conditional_change(𝕃ᵢ::AbstractLattice, state::VarTable, @nospecia if oldtyp isa LimitedAccuracy # typ is better unlimited, but we may still need to compute the tmeet with the limit # "causes" since we ignored those in the comparison - typ = tmerge(𝕃ᵢ, typ, LimitedAccuracy(Bottom, oldtyp.causes)) + newtyp = tmerge(𝕃ᵢ, newtyp, LimitedAccuracy(Bottom, oldtyp.causes)) end - return StateUpdate(SlotNumber(slot), VarState(typ, vtype.undef), state, true) + return StateUpdate(SlotNumber(condt.slot), VarState(newtyp, vtype.undef), true) +end + +function condition_object_change(currstate::VarTable, condt::Conditional, + condslot::SlotNumber, then_or_else::Bool) + vtype = currstate[slot_id(condslot)] + newcondt = Conditional(condt.slot, + then_or_else ? condt.thentype : Union{}, + then_or_else ? Union{} : condt.elsetype) + return StateUpdate(condslot, VarState(newcondt, vtype.undef), false) end # make as much progress on `frame` as possible (by handling cycles) diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 5987c30be2b91..52f4a6922328c 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -159,7 +159,6 @@ end struct StateUpdate var::SlotNumber vtype::VarState - state::VarTable conditional::Bool end @@ -724,28 +723,6 @@ function invalidate_slotwrapper(vt::VarState, changeid::Int, ignore_conditional: return nothing end -function stupdate!(lattice::AbstractLattice, state::VarTable, changes::StateUpdate) - changed = false - changeid = slot_id(changes.var) - for i = 1:length(state) - if i == changeid - newtype = changes.vtype - else - newtype = changes.state[i] - end - invalidated = invalidate_slotwrapper(newtype, changeid, changes.conditional) - if invalidated !== nothing - newtype = invalidated - end - oldtype = state[i] - if schanged(lattice, newtype, oldtype) - state[i] = smerge(lattice, oldtype, newtype) - changed = true - end - end - return changed -end - function stupdate!(lattice::AbstractLattice, state::VarTable, changes::VarTable) changed = false for i = 1:length(state) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 8b0c6669ffb89..ed7b177a1e99d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2151,78 +2151,75 @@ end @testset "branching on conditional object" begin # simple - @test Base.return_types((Union{Nothing,Int},)) do a + @test Base.infer_return_type((Union{Nothing,Int},)) do a b = a === nothing return b ? 0 : a # ::Int - end == Any[Int] + end == Int # can use multiple times (as far as the subject of condition hasn't changed) - @test Base.return_types((Union{Nothing,Int},)) do a + @test Base.infer_return_type((Union{Nothing,Int},)) do a b = a === nothing c = b ? 0 : a # c::Int d = !b ? a : 0 # d::Int return c, d # ::Tuple{Int,Int} - end == Any[Tuple{Int,Int}] + end == Tuple{Int,Int} # should invalidate old constraint when the subject of condition has changed - @test Base.return_types((Union{Nothing,Int},)) do a + @test Base.infer_return_type((Union{Nothing,Int},)) do a cond = a === nothing r1 = cond ? 0 : a # r1::Int a = 0 r2 = cond ? a : 1 # r2::Int, not r2::Union{Nothing,Int} return r1, r2 # ::Tuple{Int,Int} - end == Any[Tuple{Int,Int}] + end == Tuple{Int,Int} end # https://github.com/JuliaLang/julia/issues/42090#issuecomment-911824851 # `PartialStruct` shouldn't wrap `Conditional` -let M = Module() - @eval M begin - struct BePartialStruct - val::Int - cond - end - end - - rt = @eval M begin - Base.return_types((Union{Nothing,Int},)) do a - cond = a === nothing - obj = $(Expr(:new, M.BePartialStruct, 42, :cond)) - r1 = getfield(obj, :cond) ? 0 : a # r1::Union{Nothing,Int}, not r1::Int (because PartialStruct doesn't wrap Conditional) - a = $(gensym(:anyvar))::Any - r2 = getfield(obj, :cond) ? a : nothing # r2::Any, not r2::Const(nothing) (we don't need to worry about constraint invalidation here) - return r1, r2 # ::Tuple{Union{Nothing,Int},Any} - end |> only - end - @test rt == Tuple{Union{Nothing,Int},Any} +struct BePartialStruct + val::Int + cond +end +@test Tuple{Union{Nothing,Int},Any} == @eval Base.infer_return_type((Union{Nothing,Int},)) do a + cond = a === nothing + obj = $(Expr(:new, BePartialStruct, 42, :cond)) + r1 = getfield(obj, :cond) ? 0 : a # r1::Union{Nothing,Int}, not r1::Int (because PartialStruct doesn't wrap Conditional) + a = $(gensym(:anyvar))::Any + r2 = getfield(obj, :cond) ? a : nothing # r2::Any, not r2::Const(nothing) (we don't need to worry about constraint invalidation here) + return r1, r2 # ::Tuple{Union{Nothing,Int},Any} end # make sure we never form nested `Conditional` (https://github.com/JuliaLang/julia/issues/46207) -@test Base.return_types((Any,)) do a +@test Base.infer_return_type((Any,)) do a c = isa(a, Integer) 42 === c ? :a : "b" -end |> only === String -@test Base.return_types((Any,)) do a +end == String +@test Base.infer_return_type((Any,)) do a c = isa(a, Integer) c === 42 ? :a : "b" -end |> only === String +end == String -@testset "conditional constraint propagation from non-`Conditional` object" begin - @test Base.return_types((Bool,)) do b - if b - return !b ? nothing : 1 # ::Int - else - return 0 - end - end == Any[Int] - - @test Base.return_types((Any,)) do b - if b - return b # ::Bool - else - return nothing - end - end == Any[Union{Bool,Nothing}] +function condition_object_update1(cond) + if cond # `cond` is known to be `Const(true)` within this branch + return !cond ? nothing : 1 # ::Int + else + return cond ? nothing : 1 # ::Int + end +end +function condition_object_update2(x) + cond = x isa Int + if cond # `cond` is known to be `Const(true)` within this branch + return !cond ? nothing : x # ::Int + else + return cond ? nothing : 1 # ::Int + end +end +@testset "state update for condition object" begin + # refine the type of condition object into constant boolean values on branching + @test Base.infer_return_type(condition_object_update1, (Bool,)) == Int + @test Base.infer_return_type(condition_object_update1, (Any,)) == Int + # refine even when their original type is `Conditional` + @test Base.infer_return_type(condition_object_update2, (Any,)) == Int end @testset "`from_interprocedural!`: translate inter-procedural information" begin From ef19235df8ef505e21d70e9d81fe5f03fe1c333f Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:17:30 -0400 Subject: [PATCH 043/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Tar=20stdlib=20from=2081888a3=20to=201114260=20(#54670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Tar URL: https://github.com/JuliaIO/Tar.jl.git Stdlib branch: master Julia branch: master Old commit: 81888a3 New commit: 1114260 Julia version: 1.12.0-DEV Tar version: 1.10.0(Does not match) Bump invoked by: @StefanKarpinski Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaIO/Tar.jl/compare/81888a33704b233a2ad6f82f84456a1dd82c87f0...1114260f5c7a7b59441acadca2411fa227bb8a3b ``` $ git log --oneline 81888a3..1114260 1114260 Accept other string types for all string arguments (fix #179) (#180) a2e39d6 Bump julia-actions/cache from 1 to 2 (#178) 152d12e Bump julia-actions/setup-julia from 1 to 2 (#177) 5012536 Fix Codecov (#176) 9b5460b Add `public` declarations using `eval` (#175) 4e9d73a Add docstring for Tar module (#173) 38a4bf4 Bump codecov/codecov-action from 3 to 4 (#172) 166deb3 [CI] Switch to `julia-actions/cache` (#171) d0085d8 Hardcode doc edit backlink (#164) 7e83ed7 [NFC] fix some wonky formatting (#168) 6269b5b Bump actions/checkout from 3 to 4 (#163) ``` Co-authored-by: Dilum Aluthge --- .../Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/md5 | 1 + .../Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/sha512 | 1 + .../Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/md5 | 1 - .../Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/sha512 | 1 - stdlib/Tar.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/md5 create mode 100644 deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/sha512 delete mode 100644 deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/md5 delete mode 100644 deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/sha512 diff --git a/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/md5 b/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/md5 new file mode 100644 index 0000000000000..3c7510a592760 --- /dev/null +++ b/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/md5 @@ -0,0 +1 @@ +1d606dfc60d2af892009213650169129 diff --git a/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/sha512 b/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/sha512 new file mode 100644 index 0000000000000..ec49e695cbb3a --- /dev/null +++ b/deps/checksums/Tar-1114260f5c7a7b59441acadca2411fa227bb8a3b.tar.gz/sha512 @@ -0,0 +1 @@ +6e60d74d00ffc2e1a5a9c13f59b3e3fc4360e641b9f0e3e4797c8b524288e779397bd56a8e57f47d5a06d1e6f359c86917164ec7f6e0ac3d6e876dfa09d2b0c8 diff --git a/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/md5 b/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/md5 deleted file mode 100644 index 921ffb0a2561e..0000000000000 --- a/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b3d21b3f38cd106e64fa9d058d095651 diff --git a/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/sha512 b/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/sha512 deleted file mode 100644 index cbf6ad4952258..0000000000000 --- a/deps/checksums/Tar-81888a33704b233a2ad6f82f84456a1dd82c87f0.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -61bd3555de7a2cec265ae72d58b4635f84ec75b993b9dab2dc5be64375b6057972a2786337f90742ad3b91c57f5008372a3a4f8a5b589e2cf4d5cd1a8056e03c diff --git a/stdlib/Tar.version b/stdlib/Tar.version index f1c361eff972e..2403cd1c7c635 100644 --- a/stdlib/Tar.version +++ b/stdlib/Tar.version @@ -1,4 +1,4 @@ TAR_BRANCH = master -TAR_SHA1 = 81888a33704b233a2ad6f82f84456a1dd82c87f0 +TAR_SHA1 = 1114260f5c7a7b59441acadca2411fa227bb8a3b TAR_GIT_URL := https://github.com/JuliaIO/Tar.jl.git TAR_TAR_URL = https://api.github.com/repos/JuliaIO/Tar.jl/tarball/$1 From e478e12bd1fb27334dbfdcdd83db3b0c4715b294 Mon Sep 17 00:00:00 2001 From: Sukera <11753998+Seelengrab@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:56:04 +0200 Subject: [PATCH 044/206] Fix racecondition in UUIDs tests (#55215) By removing the direct reliance on `time()` for individual calls to these two, we can remove a race condition in the testsuite. Fixes #55190 --------- Co-authored-by: Sukera --- stdlib/UUIDs/src/UUIDs.jl | 26 +++++++++++++++++--------- stdlib/UUIDs/test/runtests.jl | 19 ++++++++++++++++--- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/stdlib/UUIDs/src/UUIDs.jl b/stdlib/UUIDs/src/UUIDs.jl index 500f2767e8e96..e3f5f812ef6e2 100644 --- a/stdlib/UUIDs/src/UUIDs.jl +++ b/stdlib/UUIDs/src/UUIDs.jl @@ -39,7 +39,7 @@ const namespace_x500 = UUID(0x6ba7b8149dad11d180b400c04fd430c8) # 6ba7b814-9dad- uuid1([rng::AbstractRNG]) -> UUID Generates a version 1 (time-based) universally unique identifier (UUID), as specified -by RFC 4122. Note that the Node ID is randomly generated (does not identify the host) +by [RFC 4122](https://www.ietf.org/rfc/rfc4122). Note that the Node ID is randomly generated (does not identify the host) according to section 4.5 of the RFC. The default rng used by `uuid1` is not `Random.default_rng()` and every invocation of `uuid1()` without @@ -62,6 +62,13 @@ UUID("cfc395e8-590f-11e8-1f13-43a2532b2fa8") ``` """ function uuid1(rng::AbstractRNG=Random.RandomDevice()) + # 0x01b21dd213814000 is the number of 100 nanosecond intervals + # between the UUID epoch and Unix epoch + timestamp = round(UInt64, time() * 1e7) + 0x01b21dd213814000 + _build_uuid1(rng, timestamp) +end + +function _build_uuid1(rng::AbstractRNG, timestamp::UInt64) u = rand(rng, UInt128) # mask off clock sequence and node @@ -70,9 +77,6 @@ function uuid1(rng::AbstractRNG=Random.RandomDevice()) # set the unicast/multicast bit and version u |= 0x00000000000010000000010000000000 - # 0x01b21dd213814000 is the number of 100 nanosecond intervals - # between the UUID epoch and Unix epoch - timestamp = round(UInt64, time() * 1e7) + 0x01b21dd213814000 ts_low = timestamp & typemax(UInt32) ts_mid = (timestamp >> 32) & typemax(UInt16) ts_hi = (timestamp >> 48) & 0x0fff @@ -81,14 +85,14 @@ function uuid1(rng::AbstractRNG=Random.RandomDevice()) u |= UInt128(ts_mid) << 80 u |= UInt128(ts_hi) << 64 - UUID(u) + return UUID(u) end """ uuid4([rng::AbstractRNG]) -> UUID Generates a version 4 (random or pseudo-random) universally unique identifier (UUID), -as specified by RFC 4122. +as specified by [RFC 4122](https://www.ietf.org/rfc/rfc4122). The default rng used by `uuid4` is not `Random.default_rng()` and every invocation of `uuid4()` without an argument should be expected to return a unique identifier. Importantly, the outputs of @@ -161,7 +165,7 @@ end uuid7([rng::AbstractRNG]) -> UUID Generates a version 7 (random or pseudo-random) universally unique identifier (UUID), -as specified by RFC 9652. +as specified by [RFC 9652](https://www.rfc-editor.org/rfc/rfc9562). The default rng used by `uuid7` is not `Random.default_rng()` and every invocation of `uuid7()` without an argument should be expected to return a unique identifier. Importantly, the outputs of @@ -183,14 +187,18 @@ UUID("019026ca-e086-772a-9638-f7b8557cd282") ``` """ function uuid7(rng::AbstractRNG=Random.RandomDevice()) + # current time in ms, rounded to an Integer + timestamp = round(UInt128, time() * 1e3) + _build_uuid7(rng, timestamp) +end + +function _build_uuid7(rng::AbstractRNG, timestamp::UInt128) bytes = rand(rng, UInt128) # make space for the timestamp bytes &= 0x0000000000000fff3fffffffffffffff # version & variant bytes |= 0x00000000000070008000000000000000 - # current time in ms, rounded to an Integer - timestamp = round(UInt128, time() * 1e3) bytes |= timestamp << UInt128(80) return UUID(bytes) diff --git a/stdlib/UUIDs/test/runtests.jl b/stdlib/UUIDs/test/runtests.jl index f9d8516554580..c6da441076ea8 100644 --- a/stdlib/UUIDs/test/runtests.jl +++ b/stdlib/UUIDs/test/runtests.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test, UUIDs, Random - +using UUIDs: _build_uuid1, _build_uuid7 # results similar to Python builtin uuid # To reproduce the sequence @@ -56,9 +56,22 @@ end @test u7 == UUID(UInt128(u7)) end -@testset "uuid4 & uuid7 RNG stability" begin +@testset "Passing an RNG" begin + rng = Xoshiro(0) + @test uuid1(rng) isa UUID + @test uuid4(rng) isa UUID + @test uuid7(rng) isa UUID +end + +@testset "uuid1, uuid4 & uuid7 RNG stability" begin @test uuid4(Xoshiro(0)) == uuid4(Xoshiro(0)) - @test uuid7(Xoshiro(0)) == uuid7(Xoshiro(0)) + + time_uuid1 = rand(UInt64) + time_uuid7 = rand(UInt128) + + # we need to go through the internal function to test RNG stability + @test _build_uuid1(Xoshiro(0), time_uuid1) == _build_uuid1(Xoshiro(0), time_uuid1) + @test _build_uuid7(Xoshiro(0), time_uuid7) == _build_uuid7(Xoshiro(0), time_uuid7) end @testset "Rejection of invalid UUID strings" begin From c6d079c27b99cdf681f7d59b4dca08291f2811c9 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:19:07 +0200 Subject: [PATCH 045/206] mark `Lockable` as exported and update HISTORY.md for Lockable not being exported in v1.11 (#54595) companion to https://github.com/JuliaLang/julia/pull/54612. As mentioned there, in https://github.com/JuliaLang/julia/pull/54590 we originally intended to export Lockable. This does so for v1.12, and also updates the HISTORY.md for the fact that Lockable was not exported in v1.11 to match #54612. --- HISTORY.md | 2 +- NEWS.md | 1 + base/exports.jl | 1 + test/misc.jl | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 12433ea5976fc..bf59f6da9659a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -74,7 +74,7 @@ Multi-threading changes ----------------------- * `Threads.@threads` now supports the `:greedy` scheduler, intended for non-uniform workloads ([#52096]). -* A new exported struct `Lockable{T, L<:AbstractLock}` makes it easy to bundle a resource and its lock together ([#52898]). +* A new public (but unexported) struct `Base.Lockable{T, L<:AbstractLock}` makes it easy to bundle a resource and its lock together ([#52898]). Build system changes -------------------- diff --git a/NEWS.md b/NEWS.md index a29fe2d43ab39..a84ecdd9ead1a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -94,6 +94,7 @@ New library features * `tempname` can now take a suffix string to allow the file name to include a suffix and include that suffix in the uniquing checking ([#53474]) * `RegexMatch` objects can now be used to construct `NamedTuple`s and `Dict`s ([#50988]) +* `Lockable` is now exported ([#54595]) Standard library changes ------------------------ diff --git a/base/exports.jl b/base/exports.jl index 5564cdbe9bff2..1f0ccdf6b8c36 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -58,6 +58,7 @@ export IOBuffer, IOStream, LinRange, + Lockable, Irrational, LazyString, Matrix, diff --git a/test/misc.jl b/test/misc.jl index 5d11cf889858e..87605d685fb3e 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -132,7 +132,7 @@ end # Lockable{T, L<:AbstractLock} using Base: Lockable let - @test_broken Base.isexported(Base, :Lockable) + @test Base.isexported(Base, :Lockable) lockable = Lockable(Dict("foo" => "hello"), ReentrantLock()) # note field access is non-public @test lockable.value["foo"] == "hello" From f4a022ca1a252660313d639aede896fa49050b15 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Wed, 24 Jul 2024 15:44:07 -0400 Subject: [PATCH 046/206] Better error message in _check_mutable (#55088) Improve error message when trying to finalize a non-mutable object. This would have saved me an hour of debugging... A web search doesn't bring up useful results, pointing mostly to the change of argument order in `finalizer` some time ago. --- base/gcutils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gcutils.jl b/base/gcutils.jl index 7aea7f222d7fd..84a184537ffc0 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -38,7 +38,7 @@ WeakRef # Used by `Base.finalizer` to validate mutability of an object being finalized. function _check_mutable(@nospecialize(o)) @noinline if !ismutable(o) - error("objects of type ", typeof(o), " cannot be finalized") + error("objects of type ", typeof(o), " cannot be finalized because they are not mutable") end end From 9dd49c056f7b95ccbac85de44ed123f34f419c5f Mon Sep 17 00:00:00 2001 From: Timothy Date: Thu, 25 Jul 2024 03:58:24 +0800 Subject: [PATCH 047/206] Apply syntax highlighting to Exprs in REPL (#54446) Large exprs (such as those produced by @macroexpand) can be hard to read and interpret. This is a problem made easier by JuliaSyntaxHighlighting, and with it we can easily apply syntax highlighting when showing exprs. Normally this would be implemented in Base's show method for Exprs, however since JuliaSyntaxHighlighting is a stdlib we must look elsewhere, and REPL seems like a sensible place. To ensure that the IOContext of the REPL IO is properly respected, we change the show invocation within the REPL display method to use show_repl which falls back to just calling show, as before. We then add a show_repl(::IO, ::MIME"text/plain", ::Expr) specialisation, which prints expressions with syntax highlighting. --- doc/Manifest.toml | 2 +- stdlib/Manifest.toml | 2 +- stdlib/REPL/Project.toml | 1 + stdlib/REPL/src/REPL.jl | 10 +++++++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/Manifest.toml b/doc/Manifest.toml index 7b8bd47d42a47..c0f8b693bd1ac 100644 --- a/doc/Manifest.toml +++ b/doc/Manifest.toml @@ -219,7 +219,7 @@ uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" version = "1.11.0" [[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] +deps = ["InteractiveUtils", "JuliaSyntaxHighlighting", "Markdown", "Sockets", "StyledStrings", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" version = "1.11.0" diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index a9f02da6692a6..c9d2086432a85 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -194,7 +194,7 @@ uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" version = "1.11.0" [[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] +deps = ["InteractiveUtils", "JuliaSyntaxHighlighting", "Markdown", "Sockets", "StyledStrings", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" version = "1.11.0" diff --git a/stdlib/REPL/Project.toml b/stdlib/REPL/Project.toml index e07bbf07a2a76..f60a6a4766093 100644 --- a/stdlib/REPL/Project.toml +++ b/stdlib/REPL/Project.toml @@ -4,6 +4,7 @@ version = "1.11.0" [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +JuliaSyntaxHighlighting = "dc6e5ff7-fb65-4e79-a425-ec3bc9c03011" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 2d364931bc253..50e11ee4bee36 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -101,6 +101,7 @@ function __init__() end using Base.Meta, Sockets, StyledStrings +using JuliaSyntaxHighlighting import InteractiveUtils export @@ -507,13 +508,20 @@ function display(d::REPLDisplay, mime::MIME"text/plain", x) # this can override the :limit property set initially io = foldl(IOContext, d.repl.options.iocontext, init=io) end - show(io, mime, x[]) + show_repl(io, mime, x[]) println(io) end return nothing end + display(d::REPLDisplay, x) = display(d, MIME("text/plain"), x) +show_repl(io::IO, mime::MIME"text/plain", x) = show(io, mime, x) + +show_repl(io::IO, ::MIME"text/plain", ex::Expr) = + print(io, JuliaSyntaxHighlighting.highlight( + sprint(show, ex, context=IOContext(io, :color => false)))) + function print_response(repl::AbstractREPL, response, show_value::Bool, have_color::Bool) repl.waserror = response[2] with_repl_linfo(repl) do io From 04ef6c232f97bd8085723e527b507ba202754859 Mon Sep 17 00:00:00 2001 From: Ashlin Harris <90787010+AshlinHarris@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:36:26 -0400 Subject: [PATCH 048/206] Right arrow autocompletes at line end (#54983) This commit adds a REPL feature: autocompletion when the right arrow key is pressed at the end of a line (The current behavior is to do nothing). This new effect only occurs when: - the cursor is at the end of the buffer, - there is only one possible completion, and - more than 1 character is in the buffer. In this situation, the right arrow key behaves like ``. Otherwise, the right arrow key behaves as normal. The feature was requested in #54539 and seems intuitive to me. One useful side effect is that, by requiring that the cursor be at the end of the line, it offers a way to avoid autcompletes within words, which I assume are almost never helpful (For example, if I type "show" in the REPL, move the cursor onto the 'o' and press ``, I end up with "showow"). One potential drawback is that the autocomplete could occur when a user who simply wants to move the cursor to the end of the line holds down the right arrow. --- stdlib/REPL/src/LineEdit.jl | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 7b127a343a98c..28764e63b83bf 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -741,7 +741,26 @@ function edit_move_right(buf::IOBuffer) end return false end -edit_move_right(s::PromptState) = edit_move_right(s.input_buffer) ? refresh_line(s) : false +function edit_move_right(m::MIState) + s = state(m) + buf = s.input_buffer + if edit_move_right(s.input_buffer) + refresh_line(s) + return true + else + completions, partial, should_complete = complete_line(s.p.complete, s, m.active_module) + if should_complete && eof(buf) && length(completions) == 1 && length(partial) > 1 + # Replace word by completion + prev_pos = position(s) + push_undo(s) + edit_splice!(s, (prev_pos - sizeof(partial)) => prev_pos, completions[1]) + refresh_line(state(s)) + return true + else + return false + end + end +end function edit_move_word_right(s::PromptState) if !eof(s.input_buffer) From 462d7f4c4cb2d4a13a1e056b39cb3ea84fb5082d Mon Sep 17 00:00:00 2001 From: Timothy Date: Thu, 25 Jul 2024 04:39:49 +0800 Subject: [PATCH 049/206] Fix annotated join with non-concrete eltype iters (#54919) As raised in , when the eltype of an iterator is non-concrete, `_isannotated` will return false. To properly check such cases, we need to see if any of the elements of the iterator are annotated. This is a bit of an interesting case, since: - Most of the time it shouldn't be hit, we can reasonably expect most iterables to infer as producing concrete types - The eltype of the iterator is (generally) known at compile-time, and so in any case other than the ambiguous non-concrete one, this check remains able to be done at compile-time. With this change, join always preserves annotations. The compromise made is that iterators with non-concrete eltypes can result in join inferring a union return type (i.e. type instability with non-concrete iterators), but that doesn't seem too bad to me (I don't see how we could be completely type stable without concrete types here). --- base/strings/io.jl | 16 ++++++++++++---- test/strings/annotated.jl | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 9204310129729..46353ff6f7c29 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -354,12 +354,20 @@ function join(io::IO, iterator, delim="") end function _join_preserve_annotations(iterator, args...) - if _isannotated(eltype(iterator)) || any(_isannotated, args) + if isconcretetype(eltype(iterator)) && !_isannotated(eltype(iterator)) && !any(_isannotated, args) + sprint(join, iterator, args...) + else io = AnnotatedIOBuffer() join(io, iterator, args...) - read(seekstart(io), AnnotatedString{String}) - else - sprint(join, iterator, args...) + # If we know (from compile time information, or dynamically in the case + # of iterators with a non-concrete eltype), that the result is annotated + # in nature, we extract an `AnnotatedString`, otherwise we just extract + # a plain `String` from `io`. + if isconcretetype(eltype(iterator)) || !isempty(io.annotations) + read(seekstart(io), AnnotatedString{String}) + else + String(take!(io.io)) + end end end diff --git a/test/strings/annotated.jl b/test/strings/annotated.jl index b7f55e97a3c8d..e985c0b421a51 100644 --- a/test/strings/annotated.jl +++ b/test/strings/annotated.jl @@ -101,6 +101,8 @@ end [(1:4, :label => 5), (5:5, :label => 2), (6:9, :label => 5)]) + @test join((String(str1), str1), ' ') == + Base.AnnotatedString("test test", [(6:9, :label => 5)]) @test repeat(str1, 2) == Base.AnnotatedString("testtest", [(1:8, :label => 5)]) @test repeat(str2, 2) == Base.AnnotatedString("casecase", [(2:3, :label => "oomph"), (6:7, :label => "oomph")]) From c0f7df13415e79dd818eed3818bb19c7a7f39dfa Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Wed, 24 Jul 2024 22:47:51 +0200 Subject: [PATCH 050/206] include the doc strings of `.=`, `.`, `->`, `::` into the docs (#55046) --- doc/src/base/base.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index d7e7fff7cbda7..1d611684d28e2 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -102,6 +102,10 @@ where ; = ?: +.= +. +-> +:: ``` ## Standard Modules From a3cbb1813d7be793d4736c9b6bf08c796edbad6b Mon Sep 17 00:00:00 2001 From: Zentrik Date: Wed, 24 Jul 2024 21:52:03 +0100 Subject: [PATCH 051/206] Fix spurious unused function warning when compiling crc32 with clang and ifunc support (#53897) Clang incorrectly warns functions only used through ifuncs are unused, https://github.com/llvm/llvm-project/issues/63957. --- src/crc32c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/crc32c.c b/src/crc32c.c index 1d667b3dbf656..50d2acc603359 100644 --- a/src/crc32c.c +++ b/src/crc32c.c @@ -178,6 +178,9 @@ JL_DLLEXPORT uint32_t jl_crc32c(uint32_t crc, const char *buf, size_t len) return crc32c_sse42(crc, buf, len); } # else +#if defined(JL_CRC32C_USE_IFUNC) && defined(_COMPILER_CLANG_) +JL_UNUSED +#endif static crc32c_func_t crc32c_dispatch(void) { // When used in ifunc, we cannot call external functions (i.e. jl_cpuid) From 8d5b751a53a6335909c8eca8c2cf98b496c4f9f0 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 24 Jul 2024 15:50:17 -0700 Subject: [PATCH 052/206] Add NVTX instrumentation (#54873) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow profiling with Nsight Systems. To try it out, add ``` WITH_NVTX=1 ``` to `Make.user` --------- Co-authored-by: Mosè Giordano --- Make.inc | 8 +++++ deps/Makefile | 6 +++- .../md5 | 1 + .../sha512 | 1 + deps/nvtx.mk | 31 +++++++++++++++++ deps/nvtx.version | 4 +++ src/timing.c | 34 ++++++++++++++++++- src/timing.h | 31 ++++++++++++++++- 8 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/md5 create mode 100644 deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/sha512 create mode 100644 deps/nvtx.mk create mode 100644 deps/nvtx.version diff --git a/Make.inc b/Make.inc index 8a16701db5264..2b15c01926db8 100644 --- a/Make.inc +++ b/Make.inc @@ -92,6 +92,9 @@ WITH_DTRACE := 0 # Enable ITTAPI integration WITH_ITTAPI := 0 +# Enable NVTX integration +WITH_NVTX := 0 + # Enable Tracy support WITH_TRACY := 0 WITH_TRACY_CALLSTACKS := 0 @@ -808,6 +811,11 @@ JCXXFLAGS += -DUSE_TIMING_COUNTS JCFLAGS += -DUSE_TIMING_COUNTS endif +ifeq ($(WITH_NVTX), 1) +JCXXFLAGS += -DUSE_NVTX +JCFLAGS += -DUSE_NVTX +endif + # =========================================================================== # Select the cpu architecture to target, or automatically detects the user's compiler diff --git a/deps/Makefile b/deps/Makefile index a6e5bce0d4e04..83493981a40b4 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -171,6 +171,9 @@ ifeq ($(WITH_ITTAPI),1) DEP_LIBS += ittapi endif +ifeq ($(WITH_NVTX),1) +DEP_LIBS += nvtx +endif # Only compile standalone LAPACK if we are not using OpenBLAS. # OpenBLAS otherwise compiles LAPACK as part of its build. @@ -194,7 +197,7 @@ DEP_LIBS_STAGED := $(DEP_LIBS) DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ - sanitizers libsuitesparse lld libtracyclient ittapi JuliaSyntax + sanitizers libsuitesparse lld libtracyclient ittapi nvtx JuliaSyntax DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) @@ -231,6 +234,7 @@ getall: $(addprefix get-, $(DEP_LIBS_ALL)) include $(SRCDIR)/csl.mk include $(SRCDIR)/sanitizers.mk include $(SRCDIR)/ittapi.mk +include $(SRCDIR)/nvtx.mk include $(SRCDIR)/llvm.mk include $(SRCDIR)/libuv.mk include $(SRCDIR)/pcre.mk diff --git a/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/md5 b/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/md5 new file mode 100644 index 0000000000000..a834d041324c4 --- /dev/null +++ b/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/md5 @@ -0,0 +1 @@ +c866a3ff71f0640c47cda5d31f76c8e0 diff --git a/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/sha512 b/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/sha512 new file mode 100644 index 0000000000000..31eafabe3a66b --- /dev/null +++ b/deps/checksums/nvtx-733fb419540bc1d152bc682d2ca066c7bb79da29.tar.gz/sha512 @@ -0,0 +1 @@ +a2db523b0068cb727db7e3a2210578f6d1de46493c5e3a9114ad961ed1553d10b646d11486fe4f987e43a9e2ea289d1923a63861f5fc56cada94bcf0b96b7dc8 diff --git a/deps/nvtx.mk b/deps/nvtx.mk new file mode 100644 index 0000000000000..c4d4db2deba65 --- /dev/null +++ b/deps/nvtx.mk @@ -0,0 +1,31 @@ +## nvtx ## +include $(SRCDIR)/nvtx.version + +NVTX_GIT_URL := https://github.com/NVIDIA/NVTX.git +NVTX_TAR_URL = https://api.github.com/repos/NVIDIA/NVTX/tarball/$1 +$(eval $(call git-external,nvtx,NVTX,,,$(SRCCACHE))) + +$(BUILDDIR)/$(NVTX_SRC_DIR)/build-configured: $(SRCCACHE)/$(NVTX_SRC_DIR)/source-extracted + mkdir -p $(dir $@) + echo 1 > $@ + +$(BUILDDIR)/$(NVTX_SRC_DIR)/build-compiled: $(BUILDDIR)/$(NVTX_SRC_DIR)/build-configured + echo 1 > $@ + +define NVTX_INSTALL + cp -a $(SRCCACHE)/$(NVTX_SRC_DIR)/c/include $2/$$(build_includedir)/ +endef + +$(eval $(call staged-install, \ + nvtx,$(NVTX_SRC_DIR), \ + NVTX_INSTALL,,,)) + +get-nvtx: $(NVTX_SRC_FILE) +extract-nvtx: $(SRCCACHE)/$(NVTX_SRC_DIR)/source-extracted +configure-nvtx: $(BUILDDIR)/$(NVTX_SRC_DIR)/build-configured +compile-nvtx: $(BUILDDIR)/$(NVTX_SRC_DIR)/build-compiled +fastcheck-nvtx: #none +check-nvtx: #none + +clean-nvtx: + -rm -f $(BUILDDIR)/$(NVTX_SRC_DIR)/build-compiled diff --git a/deps/nvtx.version b/deps/nvtx.version new file mode 100644 index 0000000000000..e26c55cae095e --- /dev/null +++ b/deps/nvtx.version @@ -0,0 +1,4 @@ +# -*- makefile -*- +## source build +NVTX_BRANCH=dev +NVTX_SHA1=733fb419540bc1d152bc682d2ca066c7bb79da29 diff --git a/src/timing.c b/src/timing.c index 590e52b8d523d..265e50ad3dd74 100644 --- a/src/timing.c +++ b/src/timing.c @@ -6,7 +6,7 @@ #include "options.h" #include "stdio.h" -#if defined(USE_TRACY) || defined(USE_ITTAPI) +#if defined(USE_TRACY) || defined(USE_ITTAPI) || defined(USE_NVTX) #define DISABLE_FREQUENT_EVENTS #endif @@ -49,6 +49,10 @@ static arraylist_t jl_timing_ittapi_events; static jl_mutex_t jl_timing_ittapi_events_lock; #endif //USE_ITTAPI +#ifdef USE_NVTX +static nvtxDomainHandle_t jl_timing_nvtx_domain; +#endif + #ifdef USE_TIMING_COUNTS static int cmp_counts_events(const void *a, const void *b) { jl_timing_counts_event_t *event_a = *(jl_timing_counts_event_t **)a; @@ -139,6 +143,13 @@ void jl_init_timing(void) qsort(jl_timing_subsystems, JL_TIMING_SUBSYSTEM_LAST, sizeof(const char *), indirect_strcmp); +#ifdef USE_NVTX + jl_timing_nvtx_domain = nvtxDomainCreateA("julia"); + for (int i = 0; i < JL_TIMING_SUBSYSTEM_LAST; i++) { + nvtxDomainNameCategoryA(jl_timing_nvtx_domain, i + 1, jl_timing_subsystems[i]); + } +#endif + int i __attribute__((unused)) = 0; #ifdef USE_ITTAPI i = 0; @@ -317,6 +328,25 @@ JL_DLLEXPORT jl_timing_event_t *_jl_timing_event_create(const char *subsystem, c event->ittapi_event = _jl_timing_ittapi_event_create(name); #endif // USE_ITTAPI +#ifdef USE_NVTX + nvtxEventAttributes_t nvtx_attrs = {0}; + nvtx_attrs.version = NVTX_VERSION; + nvtx_attrs.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; + + nvtxStringHandle_t nvtx_message = nvtxDomainRegisterStringA(jl_timing_nvtx_domain, name); + nvtx_attrs.messageType = NVTX_MESSAGE_TYPE_REGISTERED; + nvtx_attrs.message.registered = nvtx_message; + + // 0 is the default (unnamed) category + nvtx_attrs.category = maybe_subsystem == JL_TIMING_SUBSYSTEM_LAST ? 0 : maybe_subsystem+1; + + // simple Knuth hash to get nice colors + nvtx_attrs.colorType = NVTX_COLOR_ARGB; + nvtx_attrs.color = (nvtx_attrs.category * 2654435769) >> 8; + + event->nvtx_attrs = nvtx_attrs; +#endif // USE_NVTX + #ifdef USE_TRACY event->tracy_srcloc.name = name; event->tracy_srcloc.function = function; @@ -347,6 +377,7 @@ JL_DLLEXPORT void _jl_timing_block_start(jl_timing_block_t *block) { uint64_t t = cycleclock(); (void)t; _COUNTS_START(&block->counts_ctx, t); _ITTAPI_START(block); + _NVTX_START(block); _TRACY_START(block); jl_timing_block_t **prevp = &jl_current_task->ptls->timing_stack; @@ -362,6 +393,7 @@ JL_DLLEXPORT void _jl_timing_block_end(jl_timing_block_t *block) { if (block->is_running) { uint64_t t = cycleclock(); (void)t; _ITTAPI_STOP(block); + _NVTX_STOP(block); _TRACY_STOP(block->tracy_ctx); _COUNTS_STOP(block, t); diff --git a/src/timing.h b/src/timing.h index 1cc82b67e2b6a..61118cc3b41ab 100644 --- a/src/timing.h +++ b/src/timing.h @@ -66,7 +66,7 @@ JL_DLLEXPORT void _jl_timing_block_end(jl_timing_block_t *cur_block); #define HAVE_TIMING_SUPPORT #endif -#if defined( USE_TRACY ) || defined( USE_ITTAPI ) || defined( USE_TIMING_COUNTS ) +#if defined( USE_TRACY ) || defined( USE_ITTAPI ) || defined( USE_NVTX ) || defined( USE_TIMING_COUNTS ) #define ENABLE_TIMINGS #endif @@ -115,6 +115,12 @@ typedef struct ___tracy_source_location_data TracySrcLocData; #include #endif +#ifdef USE_NVTX +#pragma GCC visibility push(default) +#include +#pragma GCC visibility pop +#endif + #ifdef __cplusplus extern "C" { #endif @@ -276,6 +282,20 @@ typedef struct _jl_timing_counts_t { #define _ITTAPI_STOP(block) #endif + +#ifdef USE_NVTX +#define _NVTX_EVENT_MEMBER nvtxEventAttributes_t nvtx_attrs; +#define _NVTX_BLOCK_MEMBER nvtxRangeId_t nvtx_rangeid; +#define _NVTX_START(block) (block)->nvtx_rangeid = nvtxDomainRangeStartEx(jl_timing_nvtx_domain, &(block)->event->nvtx_attrs) +#define _NVTX_STOP(block) nvtxDomainRangeEnd(jl_timing_nvtx_domain, (block)->nvtx_rangeid) +#else +#define _NVTX_EVENT_MEMBER +#define _NVTX_BLOCK_MEMBER +#define _NVTX_START(block) +#define _NVTX_STOP(block) +#endif + + /** * Top-level jl_timing implementation **/ @@ -292,6 +312,7 @@ extern const char *jl_timing_subsystems[(int)JL_TIMING_SUBSYSTEM_LAST]; struct _jl_timing_event_t { // typedef in julia.h _TRACY_EVENT_MEMBER _ITTAPI_EVENT_MEMBER + _NVTX_EVENT_MEMBER _COUNTS_EVENT_MEMBER int subsystem; @@ -310,6 +331,7 @@ struct _jl_timing_block_t { // typedef in julia.h _TRACY_BLOCK_MEMBER _ITTAPI_BLOCK_MEMBER + _NVTX_BLOCK_MEMBER _COUNTS_BLOCK_MEMBER uint8_t is_running; @@ -362,6 +384,12 @@ STATIC_INLINE void _jl_timing_suspend_destroy(jl_timing_suspend_t *suspend) JL_N #define _ITTAPI_COUNTER_MEMBER #endif +#ifdef USE_NVTX +#define _NVTX_COUNTER_MEMBER void * __nvtx_null; +#else +#define _NVTX_COUNTER_MEMBER +#endif + #ifdef USE_TRACY # define _TRACY_COUNTER_MEMBER jl_tracy_counter_t tracy_counter; # else @@ -376,6 +404,7 @@ STATIC_INLINE void _jl_timing_suspend_destroy(jl_timing_suspend_t *suspend) JL_N typedef struct { _ITTAPI_COUNTER_MEMBER + _NVTX_COUNTER_MEMBER _TRACY_COUNTER_MEMBER _COUNTS_MEMBER } jl_timing_counter_t; From 9b604c415c6399259af9f4acb9414a6e8236f7a6 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:05:34 -0300 Subject: [PATCH 053/206] NFC: remove unused gc_get_stack_ptr function (#55234) --- src/gc.c | 6 ------ src/gc.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/gc.c b/src/gc.c index a82ad615d8c2b..3db7843f50782 100644 --- a/src/gc.c +++ b/src/gc.c @@ -218,12 +218,6 @@ arraylist_t finalizer_list_marked; arraylist_t to_finalize; JL_DLLEXPORT _Atomic(int) jl_gc_have_pending_finalizers = 0; - -NOINLINE uintptr_t gc_get_stack_ptr(void) -{ - return (uintptr_t)jl_get_frame_addr(); -} - void jl_gc_wait_for_the_world(jl_ptls_t* gc_all_tls_states, int gc_n_threads); // malloc wrappers, aligned allocation diff --git a/src/gc.h b/src/gc.h index 6ab1b4f816f2e..9ac8a0abb65b9 100644 --- a/src/gc.h +++ b/src/gc.h @@ -549,8 +549,6 @@ STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT return (void*)(((uintptr_t)v) & ~mask); } -NOINLINE uintptr_t gc_get_stack_ptr(void); - FORCE_INLINE void gc_big_object_unlink(const bigval_t *node) JL_NOTSAFEPOINT { assert(node != oldest_generation_of_bigvals); From 4864a1be268f35edfd157abc77093d85454c52b3 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:23:20 -0300 Subject: [PATCH 054/206] add an assertion to ensure we're not cleaning-up GC state for GC threads (#55233) GC threads should never hit this branch. --- src/gc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gc.c b/src/gc.c index 3db7843f50782..f5c527d22115d 100644 --- a/src/gc.c +++ b/src/gc.c @@ -3709,8 +3709,9 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection) } // free empty GC state for threads that have exited if (jl_atomic_load_relaxed(&ptls2->current_task) == NULL) { - if (gc_is_parallel_collector_thread(t_i)) - continue; + // GC threads should never exit + assert(!gc_is_parallel_collector_thread(t_i)); + assert(!gc_is_concurrent_collector_thread(t_i)); jl_thread_heap_t *heap = &ptls2->gc_tls.heap; if (heap->weak_refs.len == 0) small_arraylist_free(&heap->weak_refs); From 1ece299e4a1ebf9410099d2442c8dd2a19f9f615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Ara=C3=BAjo?= Date: Thu, 25 Jul 2024 10:02:50 +0200 Subject: [PATCH 055/206] [docs] change docstring to match code (#55013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docstring of `LinearAlgebra.reflectorApply!` is incorrect. It says the function is applying `(I - τ*[1; x] * [1; x]')*A`, but in reality it is applying `(I - conj(τ)*[1; x[2:end]]*[1; x[2:end]]')*A`. You can check that by looking at the code, or running for example ```julia using LinearAlgebra T=ComplexF64;d=5; τ=randn(T);x=randn(T,d);A=randn(T,d,d); (I - conj(τ)*[1; x[2:end]]*[1; x[2:end]]')*A LinearAlgebra.reflectorApply!(x,τ,A) ``` --- stdlib/LinearAlgebra/src/generic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index bdd11dc822ef3..f60016125d2e9 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1676,7 +1676,7 @@ end """ reflectorApply!(x, τ, A) -Multiplies `A` in-place by a Householder reflection on the left. It is equivalent to `A .= (I - τ*[1; x] * [1; x]')*A`. +Multiplies `A` in-place by a Householder reflection on the left. It is equivalent to `A .= (I - conj(τ)*[1; x[2:end]]*[1; x[2:end]]')*A`. """ @inline function reflectorApply!(x::AbstractVector, τ::Number, A::AbstractVecOrMat) require_one_based_indexing(x) From 0ffbae80ea1537fc000283ecdb96618c0e855648 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:42:25 -0400 Subject: [PATCH 056/206] TOML: Make `Dates` a type parameter (#55017) This will allow us to resolve the `Dates` at compile-time eventually. It also fixes `TOML.Parser()` to return Dates types again. --- base/loading.jl | 10 +++++--- base/toml_parser.jl | 39 +++++++++++++++++-------------- stdlib/REPL/src/Pkg_beforeload.jl | 4 +++- stdlib/TOML/src/TOML.jl | 22 +++++++---------- stdlib/TOML/test/values.jl | 15 ++++++++++++ 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index bd985e431e497..a768be286c83d 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -264,11 +264,15 @@ const LOADING_CACHE = Ref{Union{LoadingCache, Nothing}}(nothing) LoadingCache() = LoadingCache(load_path(), Dict(), Dict(), Dict(), Set(), Dict(), Dict(), Dict()) -struct TOMLCache - p::TOML.Parser +struct TOMLCache{Dates} + p::TOML.Parser{Dates} d::Dict{String, CachedTOMLDict} end -const TOML_CACHE = TOMLCache(TOML.Parser(), Dict{String, Dict{String, Any}}()) +TOMLCache(p::TOML.Parser) = TOMLCache(p, Dict{String, CachedTOMLDict}()) +# TODO: Delete this converting constructor once Pkg stops using it +TOMLCache(p::TOML.Parser, d::Dict{String, Dict{String, Any}}) = TOMLCache(p, convert(Dict{String, CachedTOMLDict}, d)) + +const TOML_CACHE = TOMLCache(TOML.Parser{nothing}()) parsed_toml(project_file::AbstractString) = parsed_toml(project_file, TOML_CACHE, require_lock) function parsed_toml(project_file::AbstractString, toml_cache::TOMLCache, toml_lock::ReentrantLock) diff --git a/base/toml_parser.jl b/base/toml_parser.jl index d50ca3b423c26..cc1455f61928b 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -38,7 +38,7 @@ const TOMLDict = Dict{String, Any} # Parser # ########## -mutable struct Parser +mutable struct Parser{Dates} str::String # 1 character look ahead current_char::Char @@ -86,12 +86,12 @@ mutable struct Parser filepath::Union{String, Nothing} # Optionally populate with the Dates stdlib to change the type of Date types returned - Dates::Union{Module, Nothing} + Dates::Union{Module, Nothing} # TODO: remove once Pkg is updated end -function Parser(str::String; filepath=nothing) +function Parser{Dates}(str::String; filepath=nothing) where {Dates} root = TOMLDict() - l = Parser( + l = Parser{Dates}( str, # str EOF_CHAR, # current_char firstindex(str), # pos @@ -112,6 +112,7 @@ function Parser(str::String; filepath=nothing) startup(l) return l end + function startup(l::Parser) # Populate our one character look-ahead c = eat_char(l) @@ -122,8 +123,10 @@ function startup(l::Parser) end end -Parser() = Parser("") -Parser(io::IO) = Parser(read(io, String)) +Parser{Dates}() where {Dates} = Parser{Dates}("") +Parser{Dates}(io::IO) where {Dates} = Parser{Dates}(read(io, String)) + +# Parser(...) will be defined by TOML stdlib function reinit!(p::Parser, str::String; filepath::Union{Nothing, String}=nothing) p.str = str @@ -1021,11 +1024,11 @@ function parse_datetime(l) return try_return_datetime(l, year, month, day, h, m, s, ms) end -function try_return_datetime(p, year, month, day, h, m, s, ms) - Dates = p.Dates - if Dates !== nothing +function try_return_datetime(p::Parser{Dates}, year, month, day, h, m, s, ms) where Dates + if Dates !== nothing || p.Dates !== nothing + mod = Dates !== nothing ? Dates : p.Dates try - return Dates.DateTime(year, month, day, h, m, s, ms) + return mod.DateTime(year, month, day, h, m, s, ms) catch ex ex isa ArgumentError && return ParserError(ErrParsingDateTime) rethrow() @@ -1035,11 +1038,11 @@ function try_return_datetime(p, year, month, day, h, m, s, ms) end end -function try_return_date(p, year, month, day) - Dates = p.Dates - if Dates !== nothing +function try_return_date(p::Parser{Dates}, year, month, day) where Dates + if Dates !== nothing || p.Dates !== nothing + mod = Dates !== nothing ? Dates : p.Dates try - return Dates.Date(year, month, day) + return mod.Date(year, month, day) catch ex ex isa ArgumentError && return ParserError(ErrParsingDateTime) rethrow() @@ -1058,11 +1061,11 @@ function parse_local_time(l::Parser) return try_return_time(l, h, m, s, ms) end -function try_return_time(p, h, m, s, ms) - Dates = p.Dates - if Dates !== nothing +function try_return_time(p::Parser{Dates}, h, m, s, ms) where Dates + if Dates !== nothing || p.Dates !== nothing + mod = Dates !== nothing ? Dates : p.Dates try - return Dates.Time(h, m, s, ms) + return mod.Time(h, m, s, ms) catch ex ex isa ArgumentError && return ParserError(ErrParsingDateTime) rethrow() diff --git a/stdlib/REPL/src/Pkg_beforeload.jl b/stdlib/REPL/src/Pkg_beforeload.jl index 2051e11711b0f..ebd0cd255ce19 100644 --- a/stdlib/REPL/src/Pkg_beforeload.jl +++ b/stdlib/REPL/src/Pkg_beforeload.jl @@ -71,7 +71,9 @@ end function projname(project_file::String) if isfile(project_file) name = try - p = Base.TOML.Parser() + # The `nothing` here means that this TOML parser does not return proper Dates.jl + # objects - but that's OK since we're just checking the name here. + p = Base.TOML.Parser{nothing}() Base.TOML.reinit!(p, read(project_file, String); filepath=project_file) proj = Base.TOML.parse(p) get(proj, "name", nothing) diff --git a/stdlib/TOML/src/TOML.jl b/stdlib/TOML/src/TOML.jl index 7414b5dc686f4..94d2808c0bc24 100644 --- a/stdlib/TOML/src/TOML.jl +++ b/stdlib/TOML/src/TOML.jl @@ -38,16 +38,10 @@ performance if a larger number of small files are parsed. """ const Parser = Internals.Parser -""" - DTParser() - -Constructor for a TOML `Parser` which returns date and time objects from Dates. -""" -function DTParser(args...; kwargs...) - parser = Parser(args...; kwargs...) - parser.Dates = Dates - return parser -end +# Dates-enabled constructors +Parser() = Parser{Dates}() +Parser(io::IO) = Parser{Dates}(io) +Parser(str::String; filepath=nothing) = Parser{Dates}(str; filepath) """ parsefile(f::AbstractString) @@ -59,7 +53,7 @@ Parse file `f` and return the resulting table (dictionary). Throw a See also [`TOML.tryparsefile`](@ref). """ parsefile(f::AbstractString) = - Internals.parse(DTParser(readstring(f); filepath=abspath(f))) + Internals.parse(Parser(readstring(f); filepath=abspath(f))) parsefile(p::Parser, f::AbstractString) = Internals.parse(Internals.reinit!(p, readstring(f); filepath=abspath(f))) @@ -73,7 +67,7 @@ Parse file `f` and return the resulting table (dictionary). Return a See also [`TOML.parsefile`](@ref). """ tryparsefile(f::AbstractString) = - Internals.tryparse(DTParser(readstring(f); filepath=abspath(f))) + Internals.tryparse(Parser(readstring(f); filepath=abspath(f))) tryparsefile(p::Parser, f::AbstractString) = Internals.tryparse(Internals.reinit!(p, readstring(f); filepath=abspath(f))) @@ -87,7 +81,7 @@ Throw a [`ParserError`](@ref) upon failure. See also [`TOML.tryparse`](@ref). """ parse(str::AbstractString) = - Internals.parse(DTParser(String(str))) + Internals.parse(Parser(String(str))) parse(p::Parser, str::AbstractString) = Internals.parse(Internals.reinit!(p, String(str))) parse(io::IO) = parse(read(io, String)) @@ -103,7 +97,7 @@ Return a [`ParserError`](@ref) upon failure. See also [`TOML.parse`](@ref). """ tryparse(str::AbstractString) = - Internals.tryparse(DTParser(String(str))) + Internals.tryparse(Parser(String(str))) tryparse(p::Parser, str::AbstractString) = Internals.tryparse(Internals.reinit!(p, String(str))) tryparse(io::IO) = tryparse(read(io, String)) diff --git a/stdlib/TOML/test/values.jl b/stdlib/TOML/test/values.jl index be2ed3acce5b5..4fc49d47fc98d 100644 --- a/stdlib/TOML/test/values.jl +++ b/stdlib/TOML/test/values.jl @@ -4,16 +4,31 @@ using Test using TOML using TOML: Internals +# Construct an explicit Parser to test the "cached" version of parsing +const test_parser = TOML.Parser() + function testval(s, v) f = "foo = $s" + # First, test with the standard entrypoint parsed = TOML.parse(f)["foo"] return isequal(v, parsed) && typeof(v) == typeof(parsed) + (!isequal(v, parsed) || typeof(v) != typeof(parsed)) && return false + # Next, test with the "cached" (explicit Parser) entrypoint + parsed = TOML.parse(test_parser, f)["foo"] + (!isequal(v, parsed) || typeof(v) != typeof(parsed)) && return false + return true end function failval(s, v) f = "foo = $s" + # First, test with the standard entrypoint err = TOML.tryparse(f); return err isa TOML.Internals.ParserError && err.type == v + (!isa(err, TOML.Internals.ParserError) || err.type != v) && return false + # Next, test with the "cached" (explicit Parser) entrypoint + err = TOML.tryparse(test_parser, f); + (!isa(err, TOML.Internals.ParserError) || err.type != v) && return false + return true end @testset "Numbers" begin From ae483c352273af392e1dd6bd2cb3b044ffa46111 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:48:10 -0400 Subject: [PATCH 057/206] Fix a bug in `stack`'s DimensionMismatch error message (#54033) `stack` does not require that the inner iterator defines `axes`, but the code to assemble an error message assumed this. Found here: https://discourse.julialang.org/t/reduce-hcat-is-type-unstable/112800/3 --- base/abstractarray.jl | 2 +- test/abstractarray.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index f32a1b9d6d40b..8d60a2443ba47 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -3007,7 +3007,7 @@ end @inline function _stack_size_check(x, ax1::Tuple) if _iterator_axes(x) != ax1 uax1 = map(UnitRange, ax1) - uaxN = map(UnitRange, axes(x)) + uaxN = map(UnitRange, _iterator_axes(x)) throw(DimensionMismatch( LazyString("stack expects uniform slices, got axes(x) == ", uaxN, " while first had ", uax1))) end diff --git a/test/abstractarray.jl b/test/abstractarray.jl index ae530261527f7..8efe2e64b606c 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1784,6 +1784,9 @@ end @test_throws ArgumentError stack([1:3, 4:6]; dims=3) @test_throws ArgumentError stack(abs2, 1:3; dims=2) + @test stack(["hello", "world"]) isa Matrix{Char} + @test_throws DimensionMismatch stack(["hello", "world!"]) # had a bug in error printing + # Empty @test_throws ArgumentError stack(()) @test_throws ArgumentError stack([]) From 0bb650ccbf93bd8be6f3a903666059342c7f9349 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 25 Jul 2024 06:32:54 -0400 Subject: [PATCH 058/206] [REPL] improve quality of precompile script (#55210) This rewrites the REPL precompile script to no longer rely upon ugly hacks for a cross-process copy and instead supports doing the precompile wholly within in the current process. --- base/Base.jl | 2 +- base/client.jl | 137 ++++++---- base/docs/Docs.jl | 3 +- base/loading.jl | 5 - base/show.jl | 2 +- base/task.jl | 4 +- stdlib/REPL/src/LineEdit.jl | 2 +- stdlib/REPL/src/REPL.jl | 9 +- stdlib/REPL/src/REPLCompletions.jl | 5 +- .../REPL/src/TerminalMenus/TerminalMenus.jl | 2 +- stdlib/REPL/src/Terminals.jl | 2 - stdlib/REPL/src/docview.jl | 4 +- stdlib/REPL/src/precompile.jl | 255 +++++++----------- stdlib/REPL/test/repl.jl | 2 +- test/ambiguous.jl | 5 +- test/testhelpers/FakePTYs.jl | 10 +- 16 files changed, 197 insertions(+), 252 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index a8685aa8cc52c..a47a3a5c6459d 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -224,7 +224,7 @@ delete_method(which(Pair{Any,Any}, (Any, Any))) end # The REPL stdlib hooks into Base using this Ref -const REPL_MODULE_REF = Ref{Module}() +const REPL_MODULE_REF = Ref{Module}(Base) include("checked.jl") using .Checked diff --git a/base/client.jl b/base/client.jl index f6b83ecd0f4a0..7fc40d7906879 100644 --- a/base/client.jl +++ b/base/client.jl @@ -416,78 +416,97 @@ function load_REPL() end global active_repl +global active_repl_backend = nothing + +function run_fallback_repl(interactive::Bool) + let input = stdin + if isa(input, File) || isa(input, IOStream) + # for files, we can slurp in the whole thing at once + ex = parse_input_line(read(input, String)) + if Meta.isexpr(ex, :toplevel) + # if we get back a list of statements, eval them sequentially + # as if we had parsed them sequentially + for stmt in ex.args + eval_user_input(stderr, stmt, true) + end + body = ex.args + else + eval_user_input(stderr, ex, true) + end + else + while !eof(input) + if interactive + print("julia> ") + flush(stdout) + end + try + line = "" + ex = nothing + while !eof(input) + line *= readline(input, keep=true) + ex = parse_input_line(line) + if !(isa(ex, Expr) && ex.head === :incomplete) + break + end + end + eval_user_input(stderr, ex, true) + catch err + isa(err, InterruptException) ? print("\n\n") : rethrow() + end + end + end + end + nothing +end + +function run_std_repl(REPL::Module, quiet::Bool, banner::Symbol, history_file::Bool) + term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb") + term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr) + banner == :no || REPL.banner(term, short=banner==:short) + if term.term_type == "dumb" + repl = REPL.BasicREPL(term) + quiet || @warn "Terminal not fully functional" + else + repl = REPL.LineEditREPL(term, get(stdout, :color, false), true) + repl.history_file = history_file + end + # Make sure any displays pushed in .julia/config/startup.jl ends up above the + # REPLDisplay + d = REPL.REPLDisplay(repl) + last_active_repl = @isdefined(active_repl) ? active_repl : nothing + last_active_repl_backend = active_repl_backend + global active_repl = repl + pushdisplay(d) + try + global active_repl = repl + _atreplinit(repl) + REPL.run_repl(repl, backend->(global active_repl_backend = backend)) + finally + popdisplay(d) + active_repl = last_active_repl + active_repl_backend = last_active_repl_backend + end + nothing +end # run the requested sort of evaluation loop on stdio function run_main_repl(interactive::Bool, quiet::Bool, banner::Symbol, history_file::Bool) fallback_repl = parse(Bool, get(ENV, "JULIA_FALLBACK_REPL", "false")) if !fallback_repl && interactive load_InteractiveUtils() - if !isassigned(REPL_MODULE_REF) + REPL = REPL_MODULE_REF[] + if REPL === Base load_REPL() end end - # TODO cleanup REPL_MODULE_REF - if !fallback_repl && interactive && isassigned(REPL_MODULE_REF) - invokelatest(REPL_MODULE_REF[]) do REPL - term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb") - term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr) - banner == :no || REPL.banner(term, short=banner==:short) - if term.term_type == "dumb" - repl = REPL.BasicREPL(term) - quiet || @warn "Terminal not fully functional" - else - repl = REPL.LineEditREPL(term, get(stdout, :color, false), true) - repl.history_file = history_file - end - global active_repl = repl - # Make sure any displays pushed in .julia/config/startup.jl ends up above the - # REPLDisplay - pushdisplay(REPL.REPLDisplay(repl)) - _atreplinit(repl) - REPL.run_repl(repl, backend->(global active_repl_backend = backend)) - end + REPL = REPL_MODULE_REF[] + if !fallback_repl && interactive && REPL !== Base + invokelatest(run_std_repl, REPL, quiet, banner, history_file) else - # otherwise provide a simple fallback if !fallback_repl && interactive && !quiet @warn "REPL provider not available: using basic fallback" LOAD_PATH=join(Base.LOAD_PATH, Sys.iswindows() ? ';' : ':') end - let input = stdin - if isa(input, File) || isa(input, IOStream) - # for files, we can slurp in the whole thing at once - ex = parse_input_line(read(input, String)) - if Meta.isexpr(ex, :toplevel) - # if we get back a list of statements, eval them sequentially - # as if we had parsed them sequentially - for stmt in ex.args - eval_user_input(stderr, stmt, true) - end - body = ex.args - else - eval_user_input(stderr, ex, true) - end - else - while !eof(input) - if interactive - print("julia> ") - flush(stdout) - end - try - line = "" - ex = nothing - while !eof(input) - line *= readline(input, keep=true) - ex = parse_input_line(line) - if !(isa(ex, Expr) && ex.head === :incomplete) - break - end - end - eval_user_input(stderr, ex, true) - catch err - isa(err, InterruptException) ? print("\n\n") : rethrow() - end - end - end - end + run_fallback_repl(interactive) end nothing end diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index b7a17f2e3ee70..1327a1f795d4f 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -610,9 +610,8 @@ function docm(source::LineNumberNode, mod::Module, ex) @nospecialize ex if isexpr(ex, :->) && length(ex.args) > 1 return docm(source, mod, ex.args...) - elseif isassigned(Base.REPL_MODULE_REF) + elseif (REPL = Base.REPL_MODULE_REF[]) !== Base # TODO: this is a shim to continue to allow `@doc` for looking up docstrings - REPL = Base.REPL_MODULE_REF[] return invokelatest(REPL.lookup_doc, ex) else return simple_lookup_doc(ex) diff --git a/base/loading.jl b/base/loading.jl index a768be286c83d..fa46819c5731c 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1125,13 +1125,8 @@ function cache_file_entry(pkg::PkgId) uuid === nothing ? pkg.name : package_slug(uuid) end -# for use during running the REPL precompilation subprocess script, given we don't -# want it to pick up caches that already exist for other optimization levels -const ignore_compiled_cache = PkgId[] - function find_all_in_cache_path(pkg::PkgId, DEPOT_PATH::typeof(DEPOT_PATH)=DEPOT_PATH) paths = String[] - pkg in ignore_compiled_cache && return paths entrypath, entryfile = cache_file_entry(pkg) for path in DEPOT_PATH path = joinpath(path, entrypath) diff --git a/base/show.jl b/base/show.jl index cd8107f8c6125..c1ad45af5cc83 100644 --- a/base/show.jl +++ b/base/show.jl @@ -514,8 +514,8 @@ function _show_default(io::IO, @nospecialize(x)) end function active_module() - isassigned(REPL_MODULE_REF) || return Main REPL = REPL_MODULE_REF[] + REPL === Base && return Main return invokelatest(REPL.active_module)::Module end diff --git a/base/task.jl b/base/task.jl index cd06f0acd7f7d..4f7b1ea979a94 100644 --- a/base/task.jl +++ b/base/task.jl @@ -834,7 +834,7 @@ function task_done_hook(t::Task) end if err && !handled && Threads.threadid() == 1 - if isa(result, InterruptException) && isdefined(Base, :active_repl_backend) && + if isa(result, InterruptException) && active_repl_backend !== nothing && active_repl_backend.backend_task._state === task_state_runnable && isempty(Workqueue) && active_repl_backend.in_eval throwto(active_repl_backend.backend_task, result) # this terminates the task @@ -849,7 +849,7 @@ function task_done_hook(t::Task) # the exception to the REPL task since the current task is done. # issue #19467 if Threads.threadid() == 1 && - isa(e, InterruptException) && isdefined(Base, :active_repl_backend) && + isa(e, InterruptException) && active_repl_backend !== nothing && active_repl_backend.backend_task._state === task_state_runnable && isempty(Workqueue) && active_repl_backend.in_eval throwto(active_repl_backend.backend_task, e) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 28764e63b83bf..1f6a782a23397 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -3,7 +3,7 @@ module LineEdit import ..REPL -using REPL: AbstractREPL, Options +using ..REPL: AbstractREPL, Options using ..Terminals import ..Terminals: raw!, width, height, clear_line, beep diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 50e11ee4bee36..558f6ed9cab6f 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -128,7 +128,7 @@ include("options.jl") include("LineEdit.jl") using .LineEdit -import ..LineEdit: +import .LineEdit: CompletionProvider, HistoryProvider, add_history, @@ -760,6 +760,7 @@ struct LatexCompletions <: CompletionProvider end function active_module() # this method is also called from Base isdefined(Base, :active_repl) || return Main + Base.active_repl === nothing && return Main return active_module(Base.active_repl::AbstractREPL) end active_module((; mistate)::LineEditREPL) = mistate === nothing ? Main : mistate.active_module @@ -1801,7 +1802,7 @@ module Numbered using ..REPL -__current_ast_transforms() = isdefined(Base, :active_repl_backend) ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms +__current_ast_transforms() = Base.active_repl_backend !== nothing ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms function repl_eval_counter(hp) return length(hp.history) - hp.start_idx @@ -1863,13 +1864,13 @@ end function __current_ast_transforms(backend) if backend === nothing - isdefined(Base, :active_repl_backend) ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms + Base.active_repl_backend !== nothing ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms else backend.ast_transforms end end -function numbered_prompt!(repl::LineEditREPL=Base.active_repl, backend=nothing) +function numbered_prompt!(repl::LineEditREPL=Base.active_repl::LineEditREPL, backend=nothing) n = Ref{Int}(0) set_prompt(repl, n) set_output_prefix(repl, n) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index db8045cde906a..bc8006ec2ed5d 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -295,7 +295,10 @@ function maybe_spawn_cache_PATH() @lock PATH_cache_lock begin PATH_cache_task isa Task && !istaskdone(PATH_cache_task) && return time() < next_cache_update && return - PATH_cache_task = Threads.@spawn REPLCompletions.cache_PATH() + PATH_cache_task = Threads.@spawn begin + REPLCompletions.cache_PATH() + @lock PATH_cache_lock PATH_cache_task = nothing # release memory when done + end Base.errormonitor(PATH_cache_task) end end diff --git a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl index 9fcddef2fd484..ffbe32575fea1 100644 --- a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl +++ b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl @@ -2,7 +2,7 @@ module TerminalMenus -using REPL: REPL +using ..REPL: REPL function default_terminal(; in::IO=stdin, out::IO=stdout, err::IO=stderr) return REPL.Terminals.TTYTerminal( diff --git a/stdlib/REPL/src/Terminals.jl b/stdlib/REPL/src/Terminals.jl index 821ed224f1829..4f3e99f1d206c 100644 --- a/stdlib/REPL/src/Terminals.jl +++ b/stdlib/REPL/src/Terminals.jl @@ -118,10 +118,8 @@ cmove_line_up(t::UnixTerminal, n) = (cmove_up(t, n); cmove_col(t, 1)) cmove_line_down(t::UnixTerminal, n) = (cmove_down(t, n); cmove_col(t, 1)) cmove_col(t::UnixTerminal, n) = (write(t.out_stream, '\r'); n > 1 && cmove_right(t, n-1)) -const is_precompiling = Ref(false) if Sys.iswindows() function raw!(t::TTYTerminal,raw::Bool) - is_precompiling[] && return true check_open(t.in_stream) if Base.ispty(t.in_stream) run((raw ? `stty raw -echo onlcr -ocrnl opost` : `stty sane`), diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index feeeecbd97165..63a3601dbbae9 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -13,8 +13,6 @@ using Base: with_output_color, mapany, isdeprecated, isexported using Base.Filesystem: _readdirx -import REPL - using InteractiveUtils: subtypes using Unicode: normalize @@ -475,7 +473,7 @@ repl_corrections(s) = repl_corrections(stdout, s) # inverse of latex_symbols Dict, lazily created as needed const symbols_latex = Dict{String,String}() function symbol_latex(s::String) - if isempty(symbols_latex) && isassigned(Base.REPL_MODULE_REF) + if isempty(symbols_latex) for (k,v) in Iterators.flatten((REPLCompletions.latex_symbols, REPLCompletions.emoji_symbols)) symbols_latex[v] = k diff --git a/stdlib/REPL/src/precompile.jl b/stdlib/REPL/src/precompile.jl index b55f825e6a423..7a4044b7f4c6d 100644 --- a/stdlib/REPL/src/precompile.jl +++ b/stdlib/REPL/src/precompile.jl @@ -1,15 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license module Precompile -# Can't use this during incremental: `@eval Module() begin`` import ..REPL -# Prepare this staging area with all the loaded packages available -for (_pkgid, _mod) in Base.loaded_modules - if !(_pkgid.name in ("Main", "Core", "Base", "REPL")) - eval(:(const $(Symbol(_mod)) = $_mod)) - end -end # Ugly hack for our cache file to not have a dependency edge on the FakePTYs file. Base._track_dependencies[] = false @@ -19,93 +12,72 @@ try finally Base._track_dependencies[] = true end -using Base.Meta - -import Markdown -import StyledStrings - -## Debugging options -# Disable parallel precompiles generation by setting `false` -const PARALLEL_PRECOMPILATION = true - -# View the code sent to the repl by setting this to `stdout` -const debug_output = devnull # or stdout - -CTRL_C = '\x03' -CTRL_D = '\x04' -CTRL_R = '\x12' -UP_ARROW = "\e[A" -DOWN_ARROW = "\e[B" - -repl_script = """ -2+2 -print("") -printstyled("a", "b") -display([1]) -display([1 2; 3 4]) -foo(x) = 1 -@time @eval foo(1) -; pwd -$CTRL_C -$CTRL_R$CTRL_C# -? reinterpret -using Ra\t$CTRL_C -\\alpha\t$CTRL_C -\e[200~paste here ;)\e[201~"$CTRL_C -$UP_ARROW$DOWN_ARROW$CTRL_C -123\b\b\b$CTRL_C -\b\b$CTRL_C -f(x) = x03 -f(1,2) -[][1] -Base.Iterators.minimum -cd("complete_path\t\t$CTRL_C -""" - -julia_exepath() = joinpath(Sys.BINDIR, Base.julia_exename()) - -const JULIA_PROMPT = "julia> " -const PKG_PROMPT = "pkg> " -const SHELL_PROMPT = "shell> " -const HELP_PROMPT = "help?> " -blackhole = Sys.isunix() ? "/dev/null" : "nul" -procenv = Dict{String,Any}( - "JULIA_HISTORY" => blackhole, - "JULIA_PROJECT" => nothing, # remove from environment - "JULIA_LOAD_PATH" => "@stdlib", - "JULIA_DEPOT_PATH" => Sys.iswindows() ? ";" : ":", - "TERM" => "", - "JULIA_FALLBACK_REPL" => "0") # Turn REPL.jl on in subprocess - -generate_precompile_statements() = try - # Extract the precompile statements from the precompile file - statements_step = Channel{String}(Inf) - - step = @async mktemp() do precompile_file, precompile_file_h - # Collect statements from running a REPL process and replaying our REPL script - touch(precompile_file) - pts, ptm = open_fake_pty() - # we don't want existing REPL caches to be used so ignore them - setup_cmd = """ - push!(Base.ignore_compiled_cache, Base.PkgId(Base.UUID("3fa0cd96-eef1-5676-8a61-b3b8758bbffb"), "REPL")) - import REPL - REPL.Terminals.is_precompiling[] = true - """ - p = run( - addenv(```$(julia_exepath()) -O0 --trace-compile=$precompile_file - --cpu-target=native --startup-file=no --compiled-modules=existing - --color=yes -i -e "$setup_cmd"```, procenv), - pts, pts, pts; wait=false - ) - Base.close_stdio(pts) - # Prepare a background process to copy output from process until `pts` is closed +let + ## Debugging options + # View the code sent to the repl by setting this to `stdout` + debug_output = devnull # or stdout + + CTRL_C = '\x03' + CTRL_D = '\x04' + CTRL_R = '\x12' + UP_ARROW = "\e[A" + DOWN_ARROW = "\e[B" + + repl_script = """ + 2+2 + print("") + printstyled("a", "b") + display([1]) + display([1 2; 3 4]) + foo(x) = 1 + @time @eval foo(1) + ; pwd + $CTRL_C + $CTRL_R$CTRL_C# + ? reinterpret + using Ra\t$CTRL_C + \\alpha\t$CTRL_C + \e[200~paste here ;)\e[201~"$CTRL_C + $UP_ARROW$DOWN_ARROW$CTRL_C + 123\b\b\b$CTRL_C + \b\b$CTRL_C + f(x) = x03 + f(1,2) + [][1] + Base.Iterators.minimum + cd("complete_path\t\t$CTRL_C + println("done") + """ + + JULIA_PROMPT = "julia> " + PKG_PROMPT = "pkg> " + SHELL_PROMPT = "shell> " + HELP_PROMPT = "help?> " + + blackhole = Sys.isunix() ? "/dev/null" : "nul" + + withenv("JULIA_HISTORY" => blackhole, + "JULIA_PROJECT" => nothing, # remove from environment + "JULIA_LOAD_PATH" => "@stdlib", + "JULIA_DEPOT_PATH" => Sys.iswindows() ? ";" : ":", + "TERM" => "", + "JULIA_FALLBACK_REPL" => "0" # Make sure REPL.jl is turned on + ) do + rawpts, ptm = open_fake_pty() + pts = open(rawpts)::Base.TTY + if Sys.iswindows() + pts.ispty = false + else + # workaround libuv bug where it leaks pts + Base._fd(pts) == rawpts || Base.close_stdio(rawpts) + end + # Prepare a background process to copy output from `ptm` until `pts` is closed output_copy = Base.BufferStream() tee = @async try while !eof(ptm) l = readavailable(ptm) write(debug_output, l) - Sys.iswindows() && (sleep(0.1); yield(); yield()) # workaround hang - probably a libuv issue? write(output_copy, l) end write(debug_output, "\n#### EOF ####\n") @@ -118,9 +90,30 @@ generate_precompile_statements() = try close(ptm) end Base.errormonitor(tee) - repl_inputter = @async begin - # wait for the definitive prompt before start writing to the TTY - readuntil(output_copy, JULIA_PROMPT) + orig_stdin = stdin + orig_stdout = stdout + orig_stderr = stderr + repltask = @task try + Base.run_std_repl(REPL, false, :yes, true) + finally + redirect_stderr(isopen(orig_stderr) ? orig_stderr : devnull) + redirect_stdout(isopen(orig_stdout) ? orig_stdout : devnull) + close(pts) + end + try + Base.REPL_MODULE_REF[] = REPL + redirect_stdin(pts) + redirect_stdout(pts) + redirect_stderr(pts) + REPL.print_qualified_access_warning(Base.Iterators, Base, :minimum) # trigger the warning while stderr is suppressed + try + schedule(repltask) + # wait for the definitive prompt before start writing to the TTY + readuntil(output_copy, JULIA_PROMPT) + finally + redirect_stderr(isopen(orig_stderr) ? orig_stderr : devnull) + end + write(debug_output, "\n#### REPL STARTED ####\n") sleep(0.1) readavailable(output_copy) # Input our script @@ -152,77 +145,21 @@ generate_precompile_statements() = try end write(debug_output, "\n#### COMPLETED - Closing REPL ####\n") write(ptm, "$CTRL_D") - wait(tee) - success(p) || Base.pipeline_error(p) - close(ptm) - write(debug_output, "\n#### FINISHED ####\n") - end - Base.errormonitor(repl_inputter) - - n_step = 0 - precompile_copy = Base.BufferStream() - buffer_reader = @async for statement in eachline(precompile_copy) - push!(statements_step, statement) - n_step += 1 - end - - open(precompile_file, "r") do io - while true - # We need to always call eof(io) for bytesavailable(io) to work - eof(io) && istaskdone(repl_inputter) && eof(io) && break - if bytesavailable(io) == 0 - sleep(0.1) - continue - end - write(precompile_copy, readavailable(io)) - end - end - close(precompile_copy) - wait(buffer_reader) - return :ok - end - !PARALLEL_PRECOMPILATION && wait(step) - bind(statements_step, step) - - # Make statements unique - statements = Set{String}() - # Execute the precompile statements - for statement in statements_step - # Main should be completely clean - occursin("Main.", statement) && continue - Base.in!(statement, statements) && continue - try - ps = Meta.parse(statement) - if !isexpr(ps, :call) - # these are typically comments - @debug "skipping statement because it does not parse as an expression" statement - delete!(statements, statement) - continue - end - popfirst!(ps.args) # precompile(...) - ps.head = :tuple - # println(ps) - ps = eval(ps) - if !precompile(ps...) - @warn "Failed to precompile expression" form=statement _module=nothing _file=nothing _line=0 - end - catch ex - # See #28808 - @warn "Failed to precompile expression" form=statement exception=ex _module=nothing _file=nothing _line=0 + wait(repltask) + finally + close(pts) + redirect_stdin(isopen(orig_stdin) ? orig_stdin : devnull) + redirect_stdout(isopen(orig_stdout) ? orig_stdout : devnull) end + wait(tee) end - - fetch(step) == :ok || throw("Collecting precompiles failed: $(c.excp)") - return nothing -finally - GC.gc(true); GC.gc(false); # reduce memory footprint + write(debug_output, "\n#### FINISHED ####\n") + nothing end -generate_precompile_statements() - -precompile(Tuple{typeof(getproperty), REPL.REPLBackend, Symbol}) -precompile(Tuple{typeof(Base.take!), Base.Channel{Function}}) -precompile(Tuple{typeof(Base.put!), Base.Channel{Function}, Function}) -precompile(Tuple{typeof(Core.kwcall), NamedTuple{names, T} where T<:Tuple where names, typeof(REPL.LineEdit.complete_line), REPL.LineEdit.EmptyCompletionProvider, Any}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Any, Int}) +precompile(Tuple{typeof(Base.delete!), Base.Set{Any}, String}) +precompile(Tuple{typeof(Base.:(==)), Char, String}) +precompile(Tuple{typeof(Base.reseteof), Base.TTY}) end # Precompile diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 6427440c9d39e..05db88fa0d8ac 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -9,7 +9,7 @@ using Markdown empty!(Base.Experimental._hint_handlers) # unregister error hints so they can be tested separately -@test isassigned(Base.REPL_MODULE_REF) +@test Base.REPL_MODULE_REF[] === REPL const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test") isdefined(Main, :FakePTYs) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "FakePTYs.jl")) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 748660cc9c981..d6f69f21bcdce 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -97,10 +97,7 @@ ambig(x::Union{Char, Int16}) = 's' # Automatic detection of ambiguities -const allowed_undefineds = Set([ - GlobalRef(Base, :active_repl), - GlobalRef(Base, :active_repl_backend), -]) +const allowed_undefineds = Set([]) let Distributed = get(Base.loaded_modules, Base.PkgId(Base.UUID("8ba89e20-285c-5b6f-9357-94700520ee1b"), "Distributed"), diff --git a/test/testhelpers/FakePTYs.jl b/test/testhelpers/FakePTYs.jl index c4dfe416de85a..56ce6dc7d3a49 100644 --- a/test/testhelpers/FakePTYs.jl +++ b/test/testhelpers/FakePTYs.jl @@ -23,10 +23,7 @@ function open_fake_pty() close(pts) pts = fds # convert pts handle to a TTY - #fds = pts.handle - #pts.status = Base.StatusClosed - #pts.handle = C_NULL - #pts = Base.TTY(fds, Base.StatusOpen) + #pts = open(fds)::Base.TTY else O_RDWR = Base.Filesystem.JL_O_RDWR O_NOCTTY = Base.Filesystem.JL_O_NOCTTY @@ -43,8 +40,9 @@ function open_fake_pty() pts = RawFD(fds) # pts = fdio(fds, true) - # pts = Base.Filesystem.File(RawFD(fds)) - # pts = Base.TTY(RawFD(fds); readable = false) + # pts = Base.Filesystem.File(pts) + # pts = Base.TTY(pts) + # pts = Base.open(pts) ptm = Base.TTY(RawFD(fdm)) end return pts, ptm From 72d3a16b0690cc6a9ee6c6a143d81fe90c33659a Mon Sep 17 00:00:00 2001 From: Timothy Date: Thu, 25 Jul 2024 20:16:28 +0800 Subject: [PATCH 059/206] Bump the JuliaSyntaxHighlighting stdlib (#55121) This includes the JuliaSyntax token to AST conversion, as well as project housekeeping improvements. ``` a463611 * Add custom IDs to docs sections 42f5f9d * Use UInt for offset in highlight context 0123b35 * Bump stdlib version to 1.12 85764f8 * Rename *_parenthetical faces to *_parentheses a12a86a * Add CI and TagBot 92342c6 * Document internals, and build docs 1b53359 * Add docstrings for internal variables and funcs 75e32b2 * Add a .gitignore file a4805ce * Add a compat bound for StyledStrings ad47d6e * Begin fleshing out docs 30b16bd * Add example usage to readme 3592132 * Fix viewing of regions ending in multi-codepoint 8ffcf53 * Add basic precompilation statements 3aaed79 * Improve parse-tree based highlighting 16da615 * Warn about the potential for changes to highlights f3e6efd * Use the parse tree ``` --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/JuliaSyntaxHighlighting.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/md5 delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/sha512 create mode 100644 deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 create mode 100644 deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 diff --git a/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/md5 deleted file mode 100644 index 5e99f7453cfe2..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -08230d0801fda3c81927d558452215e4 diff --git a/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/sha512 deleted file mode 100644 index 16d15cdef3104..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -0386841dcf30ee53f7f95dd3206e1208482507d157aa09739873de2a56e5ca3d7bbf27eccd9f4ed81c1c0fea229673475f6454fe94df0ff960563ca4c29ed36c diff --git a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 new file mode 100644 index 0000000000000..47635275f0364 --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 @@ -0,0 +1 @@ +5f8e876204d20c02b8139e61c78caf44 diff --git a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 new file mode 100644 index 0000000000000..d353acb42a5ce --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 @@ -0,0 +1 @@ +e701477f0f7210854603e9d10758e2ecd47c1afb0f4ae6eca07cd64490cef74bbea5f3792f40b754dabbeea03bda2df07072c635b63e5f8a3f7ebb6f3f03fdf0 diff --git a/stdlib/JuliaSyntaxHighlighting.version b/stdlib/JuliaSyntaxHighlighting.version index 4a819d056e70e..705f16c785a39 100644 --- a/stdlib/JuliaSyntaxHighlighting.version +++ b/stdlib/JuliaSyntaxHighlighting.version @@ -1,4 +1,4 @@ JULIASYNTAXHIGHLIGHTING_BRANCH = main -JULIASYNTAXHIGHLIGHTING_SHA1 = 4110caaf4fcdf0c614fd3ecd7c5bf589ca82ac63 +JULIASYNTAXHIGHLIGHTING_SHA1 = a463611e715c9ec546ac8463c38b6890d892e0c8 JULIASYNTAXHIGHLIGHTING_GIT_URL := https://github.com/julialang/JuliaSyntaxHighlighting.jl.git JULIASYNTAXHIGHLIGHTING_TAR_URL = https://api.github.com/repos/julialang/JuliaSyntaxHighlighting.jl/tarball/$1 From bcd9cce3bc6c79d755bea80de911ce11952bc011 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Thu, 25 Jul 2024 08:53:05 -0500 Subject: [PATCH 060/206] Fix `fd(::IOStream)` returning an integer (#55080) As suggested by @halleysfifthinc in https://github.com/JuliaLang/julia/pull/54855#issuecomment-2214751886 --------- Co-authored-by: Max Horn --- NEWS.md | 1 + base/iostream.jl | 11 ++++++----- test/iostream.jl | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index a84ecdd9ead1a..b842012bfc33b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -100,6 +100,7 @@ Standard library changes ------------------------ * `gcdx(0, 0)` now returns `(0, 0, 0)` instead of `(0, 1, 0)` ([#40989]). +* `fd` returns a `RawFD` instead of an `Int` ([#55080]). #### StyledStrings diff --git a/base/iostream.jl b/base/iostream.jl index 40cf385acdd48..762f881cfbecb 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -47,17 +47,18 @@ macro _lock_ios(s, expr) end """ - fd(stream) + fd(stream) -> RawFD Return the file descriptor backing the stream or file. Note that this function only applies to synchronous `File`'s and `IOStream`'s not to any of the asynchronous streams. -File descriptors should typically be represented as [`RawFD`](@ref) objects, rather -than as `Int`s, to ensure that they are properly interpreted by Julia functions. +`RawFD` objects can be passed directly to other languages via the `ccall` interface. -Note that `RawFD` objects can be passed directly to other languages via the `ccall` interface. +!!! compat "Julia 1.12" + Prior to 1.12, this function returned an `Int` instead of a `RawFD`. You may use + `RawFD(fd(x))` to produce a `RawFD` in all Julia versions. """ -fd(s::IOStream) = Int(ccall(:jl_ios_fd, Clong, (Ptr{Cvoid},), s.ios)) +fd(s::IOStream) = RawFD(ccall(:jl_ios_fd, Clong, (Ptr{Cvoid},), s.ios)) stat(s::IOStream) = stat(fd(s)) diff --git a/test/iostream.jl b/test/iostream.jl index 4ba2423f0f558..13d01e61bbf8c 100644 --- a/test/iostream.jl +++ b/test/iostream.jl @@ -190,3 +190,7 @@ end @test all(T -> T <: Union{UInt, Int}, Base.return_types(unsafe_write, (IO, Ptr{UInt8}, UInt))) @test all(T -> T === Bool, Base.return_types(eof, (IO,))) end + +@testset "fd" begin + @test open(fd, tempname(), "w") isa RawFD +end From c14fe35e3be69b3df96d141cce186980f4b106d5 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 25 Jul 2024 23:11:55 +0900 Subject: [PATCH 061/206] inference: backward constraint propagation from call signatures (#55229) This PR implements another (limited) backward analysis pass in abstract interpretation; it exploits signatures of matching methods and refines types of slots. Here are couple of examples where these changes will improve the accuracy: > generic function example ```julia addint(a::Int, b::Int) = a + b @test Base.infer_return_type((Any,Any,)) do a, b c = addint(a, b) return a, b, c # now the compiler understands `a::Int`, `b::Int` end == Tuple{Int,Int,Int} ``` > `typeassert` example ```julia @test Base.infer_return_type((Any,)) do a a::Int return a # now the compiler understands `a::Int` end == Int ``` Unlike `Conditional` constrained type propagation, this type refinement information isn't encoded within any lattice element, but rather they are propagated within the newly added field `frame.curr_stmt_change` of `frame::InferenceState`. For now this commit exploits refinement information available from call signatures of generic functions and `typeassert`. --- - closes https://github.com/JuliaLang/julia/issues/37866 - fixes https://github.com/JuliaLang/julia/issues/38274 - closes #55115 --- base/compiler/abstractinterpretation.jl | 166 ++++++++++++++++++------ base/compiler/abstractlattice.jl | 4 + base/compiler/stmtinfo.jl | 6 + base/compiler/typelattice.jl | 4 +- test/compiler/inference.jl | 104 +++++++++++++++ 5 files changed, 243 insertions(+), 41 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index d441d994034a5..88c3324668869 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1,5 +1,11 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +struct SlotRefinement + slot::SlotNumber + typ::Any + SlotRefinement(slot::SlotNumber, @nospecialize(typ)) = new(slot, typ) +end + # See if the inference result of the current statement's result value might affect # the final answer for the method (aside from optimization potential and exceptions). # To do that, we need to check both for slot assignment and SSA usage. @@ -39,6 +45,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), multiple_matches = napplicable > 1 fargs = arginfo.fargs all_effects = EFFECTS_TOTAL + slotrefinements = nothing # keeps refinement information on slot types obtained from call signature for i in 1:napplicable match = applicable[i]::MethodMatch @@ -177,11 +184,16 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), # there is unanalyzed candidate, widen type and effects to the top rettype = excttype = Any all_effects = Effects() - elseif isa(matches, MethodMatches) ? (!matches.fullmatch || any_ambig(matches)) : - (!all(matches.fullmatches) || any_ambig(matches)) - # Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature. - all_effects = Effects(all_effects; nothrow=false) - excttype = tmerge(𝕃ₚ, excttype, MethodError) + else + if (matches isa MethodMatches ? (!matches.fullmatch || any_ambig(matches)) : + (!all(matches.fullmatches) || any_ambig(matches))) + # Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature. + all_effects = Effects(all_effects; nothrow=false) + excttype = tmerge(𝕃ₚ, excttype, MethodError) + end + if sv isa InferenceState && fargs !== nothing + slotrefinements = collect_slot_refinements(𝕃ᵢ, applicable, argtypes, fargs, sv) + end end rettype = from_interprocedural!(interp, rettype, sv, arginfo, conditionals) @@ -213,7 +225,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), # and avoid keeping track of a more complex result type. rettype = Any end - add_call_backedges!(interp, rettype, all_effects, edges, matches, atype, sv) + any_slot_refined = slotrefinements !== nothing + add_call_backedges!(interp, rettype, all_effects, any_slot_refined, edges, matches, atype, sv) if isa(sv, InferenceState) # TODO (#48913) implement a proper recursion handling for irinterp: # This works just because currently the `:terminate` condition guarantees that @@ -227,7 +240,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end end - return CallMeta(rettype, excttype, all_effects, info) + return CallMeta(rettype, excttype, all_effects, info, slotrefinements) end struct FailedMethodMatch @@ -492,8 +505,37 @@ function conditional_argtype(𝕃ᵢ::AbstractLattice, @nospecialize(rt), @nospe end end -function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype), all_effects::Effects, - edges::Vector{MethodInstance}, matches::Union{MethodMatches,UnionSplitMethodMatches}, @nospecialize(atype), +function collect_slot_refinements(𝕃ᵢ::AbstractLattice, applicable::Vector{Any}, + argtypes::Vector{Any}, fargs::Vector{Any}, sv::InferenceState) + ⊏, ⊔ = strictpartialorder(𝕃ᵢ), join(𝕃ᵢ) + slotrefinements = nothing + for i = 1:length(fargs) + fargᵢ = fargs[i] + if fargᵢ isa SlotNumber + fidx = slot_id(fargᵢ) + argt = widenslotwrapper(argtypes[i]) + if isvarargtype(argt) + argt = unwrapva(argt) + end + sigt = Bottom + for j = 1:length(applicable) + match = applicable[j]::MethodMatch + sigt = sigt ⊔ fieldtype(match.spec_types, i) + end + if sigt ⊏ argt # i.e. signature type is strictly more specific than the type of the argument slot + if slotrefinements === nothing + slotrefinements = fill!(Vector{Any}(undef, length(sv.slottypes)), nothing) + end + slotrefinements[fidx] = sigt + end + end + end + return slotrefinements +end + +function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype), + all_effects::Effects, any_slot_refined::Bool, edges::Vector{MethodInstance}, + matches::Union{MethodMatches,UnionSplitMethodMatches}, @nospecialize(atype), sv::AbsIntState) # don't bother to add backedges when both type and effects information are already # maximized to the top since a new method couldn't refine or widen them anyway @@ -503,7 +545,9 @@ function add_call_backedges!(interp::AbstractInterpreter, @nospecialize(rettype) if !isoverlayed(method_table(interp)) all_effects = Effects(all_effects; nonoverlayed=ALWAYS_FALSE) end - all_effects === Effects() && return nothing + if all_effects === Effects() && !any_slot_refined + return nothing + end end for edge in edges add_backedge!(sv, edge) @@ -1794,7 +1838,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs @nospecialize f la = length(argtypes) 𝕃ᵢ = typeinf_lattice(interp) - ⊑ᵢ = ⊑(𝕃ᵢ) + ⊑, ⊏, ⊔, ⊓ = partialorder(𝕃ᵢ), strictpartialorder(𝕃ᵢ), join(𝕃ᵢ), meet(𝕃ᵢ) if has_conditional(𝕃ᵢ, sv) && f === Core.ifelse && fargs isa Vector{Any} && la == 4 cnd = argtypes[2] if isa(cnd, Conditional) @@ -1809,12 +1853,12 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs a = ssa_def_slot(fargs[3], sv) b = ssa_def_slot(fargs[4], sv) if isa(a, SlotNumber) && cnd.slot == slot_id(a) - tx = (cnd.thentype ⊑ᵢ tx ? cnd.thentype : tmeet(𝕃ᵢ, tx, widenconst(cnd.thentype))) + tx = (cnd.thentype ⊑ tx ? cnd.thentype : tx ⊓ widenconst(cnd.thentype)) end if isa(b, SlotNumber) && cnd.slot == slot_id(b) - ty = (cnd.elsetype ⊑ᵢ ty ? cnd.elsetype : tmeet(𝕃ᵢ, ty, widenconst(cnd.elsetype))) + ty = (cnd.elsetype ⊑ ty ? cnd.elsetype : ty ⊓ widenconst(cnd.elsetype)) end - return tmerge(𝕃ᵢ, tx, ty) + return tx ⊔ ty end end end @@ -1939,13 +1983,13 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs cnd = isdefined_tfunc(𝕃ᵢ, ty, fld) if isa(cnd, Const) if cnd.val::Bool - thentype = tmerge(thentype, ty) + thentype = thentype ⊔ ty else - elsetype = tmerge(elsetype, ty) + elsetype = elsetype ⊔ ty end else - thentype = tmerge(thentype, ty) - elsetype = tmerge(elsetype, ty) + thentype = thentype ⊔ ty + elsetype = elsetype ⊔ ty end end return Conditional(a, thentype, elsetype) @@ -1970,8 +2014,8 @@ function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{An elseif na == 3 a2 = argtypes[2] a3 = argtypes[3] - ⊑ᵢ = ⊑(typeinf_lattice(interp)) - nothrow = a2 ⊑ᵢ TypeVar && (a3 ⊑ᵢ Type || a3 ⊑ᵢ TypeVar) + ⊑ = partialorder(typeinf_lattice(interp)) + nothrow = a2 ⊑ TypeVar && (a3 ⊑ Type || a3 ⊑ TypeVar) else return CallMeta(Bottom, Any, EFFECTS_THROWS, NoCallInfo()) end @@ -2003,7 +2047,8 @@ function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{An return CallMeta(ret, Any, Effects(EFFECTS_TOTAL; nothrow), call.info) end -function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, si::StmtInfo, sv::AbsIntState) +function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::StmtInfo, sv::AbsIntState) + argtypes = arginfo.argtypes ft′ = argtype_by_index(argtypes, 2) ft = widenconst(ft′) ft === Bottom && return CallMeta(Bottom, Any, EFFECTS_THROWS, NoCallInfo()) @@ -2034,6 +2079,7 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn res = nothing sig = match.spec_types argtypes′ = invoke_rewrite(argtypes) + fargs = arginfo.fargs fargs′ = fargs === nothing ? nothing : invoke_rewrite(fargs) arginfo = ArgInfo(fargs′, argtypes′) # # typeintersect might have narrowed signature, but the accuracy gain doesn't seem worth the cost involved with the lattice comparisons @@ -2122,7 +2168,17 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), exct = builtin_exct(𝕃ᵢ, f, argtypes, rt) end pushfirst!(argtypes, ft) - return CallMeta(rt, exct, effects, NoCallInfo()) + refinements = nothing + if sv isa InferenceState && f === typeassert + # perform very limited back-propagation of invariants after this type assertion + if rt !== Bottom && isa(fargs, Vector{Any}) + farg2 = fargs[2] + if farg2 isa SlotNumber + refinements = SlotRefinement(farg2, rt) + end + end + end + return CallMeta(rt, exct, effects, NoCallInfo(), refinements) elseif isa(f, Core.OpaqueClosure) # calling an OpaqueClosure about which we have no information returns no information return CallMeta(typeof(f).parameters[2], Any, Effects(), NoCallInfo()) @@ -2412,10 +2468,14 @@ function collect_argtypes(interp::AbstractInterpreter, ea::Vector{Any}, vtypes:: end struct RTEffects - rt - exct + rt::Any + exct::Any effects::Effects - RTEffects(@nospecialize(rt), @nospecialize(exct), effects::Effects) = new(rt, exct, effects) + refinements # ::Union{Nothing,SlotRefinement,Vector{Any}} + function RTEffects(rt, exct, effects::Effects, refinements=nothing) + @nospecialize rt exct refinements + return new(rt, exct, effects, refinements) + end end function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, sv::InferenceState) @@ -2437,8 +2497,8 @@ function abstract_eval_call(interp::AbstractInterpreter, e::Expr, vtypes::Union{ return RTEffects(Bottom, Any, Effects()) end arginfo = ArgInfo(ea, argtypes) - (; rt, exct, effects) = abstract_call(interp, arginfo, sv) - return RTEffects(rt, exct, effects) + (; rt, exct, effects, refinements) = abstract_call(interp, arginfo, sv) + return RTEffects(rt, exct, effects, refinements) end function abstract_eval_new(interp::AbstractInterpreter, e::Expr, vtypes::Union{VarTable,Nothing}, @@ -2780,9 +2840,9 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), rt = old_rt === NOT_FOUND ? rt : tmerge(typeinf_lattice(interp), old_rt, rt) return RTEffects(rt, Union{}, EFFECTS_TOTAL) end - (; rt, exct, effects) = abstract_eval_special_value(interp, e, vtypes, sv) + (; rt, exct, effects, refinements) = abstract_eval_special_value(interp, e, vtypes, sv) else - (; rt, exct, effects) = abstract_eval_statement_expr(interp, e, vtypes, sv) + (; rt, exct, effects, refinements) = abstract_eval_statement_expr(interp, e, vtypes, sv) if effects.noub === NOUB_IF_NOINBOUNDS if has_curr_ssaflag(sv, IR_FLAG_INBOUNDS) effects = Effects(effects; noub=ALWAYS_FALSE) @@ -2812,7 +2872,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), set_curr_ssaflag!(sv, flags_for_effects(effects), IR_FLAGS_EFFECTS) merge_effects!(interp, sv, effects) - return RTEffects(rt, exct, effects) + return RTEffects(rt, exct, effects, refinements) end function override_effects(effects::Effects, override::EffectsOverride) @@ -3009,13 +3069,13 @@ end fields = copy(rt.fields) local anyrefine = false 𝕃 = typeinf_lattice(info.interp) + ⊏ = strictpartialorder(𝕃) for i in 1:length(fields) a = fields[i] a = isvarargtype(a) ? a : widenreturn_noslotwrapper(𝕃, a, info) if !anyrefine # TODO: consider adding && const_prop_profitable(a) here? - anyrefine = has_extended_info(a) || - ⊏(𝕃, a, fieldtype(rt.typ, i)) + anyrefine = has_extended_info(a) || a ⊏ fieldtype(rt.typ, i) end fields[i] = a end @@ -3061,7 +3121,12 @@ struct BasicStmtChange rt::Any # extended lattice element or `nothing` - `nothing` if this statement may not be used as an SSA Value exct::Any # TODO effects::Effects - BasicStmtChange(changes::Union{Nothing,StateUpdate}, @nospecialize(rt), @nospecialize(exct)) = new(changes, rt, exct) + refinements # ::Union{Nothing,SlotRefinement,Vector{Any}} + function BasicStmtChange(changes::Union{Nothing,StateUpdate}, rt::Any, exct::Any, + refinements=nothing) + @nospecialize rt exct refinements + return new(changes, rt, exct, refinements) + end end @inline function abstract_eval_basic_statement(interp::AbstractInterpreter, @@ -3076,9 +3141,9 @@ end changes = nothing hd = stmt.head if hd === :(=) - (; rt, exct) = abstract_eval_statement(interp, stmt.args[2], pc_vartable, frame) + (; rt, exct, refinements) = abstract_eval_statement(interp, stmt.args[2], pc_vartable, frame) if rt === Bottom - return BasicStmtChange(nothing, Bottom, exct) + return BasicStmtChange(nothing, Bottom, exct, refinements) end lhs = stmt.args[1] if isa(lhs, SlotNumber) @@ -3088,7 +3153,7 @@ end elseif !isa(lhs, SSAValue) merge_effects!(interp, frame, EFFECTS_UNKNOWN) end - return BasicStmtChange(changes, rt, exct) + return BasicStmtChange(changes, rt, exct, refinements) elseif hd === :method fname = stmt.args[1] if isa(fname, SlotNumber) @@ -3100,8 +3165,8 @@ end is_meta_expr(stmt))) return BasicStmtChange(nothing, Nothing, Bottom) else - (; rt, exct) = abstract_eval_statement(interp, stmt, pc_vartable, frame) - return BasicStmtChange(nothing, rt, exct) + (; rt, exct, refinements) = abstract_eval_statement(interp, stmt, pc_vartable, frame) + return BasicStmtChange(nothing, rt, exct, refinements) end end @@ -3363,7 +3428,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) # Fall through terminator - treat as regular stmt end # Process non control-flow statements - (; changes, rt, exct) = abstract_eval_basic_statement(interp, + (; changes, rt, exct, refinements) = abstract_eval_basic_statement(interp, stmt, currstate, frame) if !has_curr_ssaflag(frame, IR_FLAG_NOTHROW) if exct !== Union{} @@ -3384,6 +3449,15 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) if changes !== nothing stoverwrite1!(currstate, changes) end + if refinements isa SlotRefinement + apply_refinement!(𝕃ᵢ, refinements.slot, refinements.typ, currstate, changes) + elseif refinements isa Vector{Any} + for i = 1:length(refinements) + newtyp = refinements[i] + newtyp === nothing && continue + apply_refinement!(𝕃ᵢ, SlotNumber(i), newtyp, currstate, changes) + end + end if rt === nothing ssavaluetypes[currpc] = Any continue @@ -3422,6 +3496,20 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) nothing end +function apply_refinement!(𝕃ᵢ::AbstractLattice, slot::SlotNumber, @nospecialize(newtyp), + currstate::VarTable, currchanges::Union{Nothing,StateUpdate}) + if currchanges !== nothing && currchanges.var == slot + return # type propagation from statement (like assignment) should have the precedence + end + vtype = currstate[slot_id(slot)] + oldtyp = vtype.typ + ⊏ = strictpartialorder(𝕃ᵢ) + if newtyp ⊏ oldtyp + stmtupdate = StateUpdate(slot, VarState(newtyp, vtype.undef), false) + stoverwrite1!(currstate, stmtupdate) + end +end + function conditional_change(𝕃ᵢ::AbstractLattice, currstate::VarTable, condt::Conditional, then_or_else::Bool) vtype = currstate[condt.slot] oldtyp = vtype.typ diff --git a/base/compiler/abstractlattice.jl b/base/compiler/abstractlattice.jl index 0102a59667c1e..645c865d085b3 100644 --- a/base/compiler/abstractlattice.jl +++ b/base/compiler/abstractlattice.jl @@ -288,9 +288,13 @@ has_extended_unionsplit(::JLTypeLattice) = false ⊑(𝕃::AbstractLattice) = (@nospecialize(a), @nospecialize(b)) -> ⊑(𝕃, a, b) ⊏(𝕃::AbstractLattice) = (@nospecialize(a), @nospecialize(b)) -> ⊏(𝕃, a, b) ⋤(𝕃::AbstractLattice) = (@nospecialize(a), @nospecialize(b)) -> ⋤(𝕃, a, b) +tmerge(𝕃::AbstractLattice) = (@nospecialize(a), @nospecialize(b)) -> tmerge(𝕃, a, b) +tmeet(𝕃::AbstractLattice) = (@nospecialize(a), @nospecialize(b)) -> tmeet(𝕃, a, b) partialorder(𝕃::AbstractLattice) = ⊑(𝕃) strictpartialorder(𝕃::AbstractLattice) = ⊏(𝕃) strictneqpartialorder(𝕃::AbstractLattice) = ⋤(𝕃) +join(𝕃::AbstractLattice) = tmerge(𝕃) +meet(𝕃::AbstractLattice) = tmeet(𝕃) # Fallbacks for external packages using these methods const fallback_lattice = InferenceLattice(BaseInferenceLattice.instance) diff --git a/base/compiler/stmtinfo.jl b/base/compiler/stmtinfo.jl index 25f5bb894eaa9..69d2ac7ae45a0 100644 --- a/base/compiler/stmtinfo.jl +++ b/base/compiler/stmtinfo.jl @@ -13,6 +13,12 @@ struct CallMeta exct::Any effects::Effects info::CallInfo + refinements # ::Union{Nothing,SlotRefinement,Vector{Any}} + function CallMeta(rt::Any, exct::Any, effects::Effects, info::CallInfo, + refinements=nothing) + @nospecialize rt exct info + return new(rt, exct, effects, info, refinements) + end end struct NoCallInfo <: CallInfo end diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 52f4a6922328c..1be76f7d8bea3 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -393,8 +393,8 @@ ignorelimited(typ::LimitedAccuracy) = typ.typ # ============= @nospecializeinfer function ⊑(lattice::InferenceLattice, @nospecialize(a), @nospecialize(b)) - r = ⊑(widenlattice(lattice), ignorelimited(a), ignorelimited(b)) - r || return false + ⊑(widenlattice(lattice), ignorelimited(a), ignorelimited(b)) || return false + isa(b, LimitedAccuracy) || return true # We've found that ignorelimited(a) ⊑ ignorelimited(b). diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index ed7b177a1e99d..2c149b1abf21d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4200,6 +4200,110 @@ end end end == [Union{Some{Float64}, Some{Int}, Some{UInt8}}] +@testset "constraint back-propagation from typeassert" begin + @test Base.infer_return_type((Any,)) do a + typeassert(a, Int) + return a + end == Int + + @test Base.infer_return_type((Any,Bool)) do a, b + if b + typeassert(a, Int64) + else + typeassert(a, Int32) + end + return a + end == Union{Int32,Int64} +end + +callsig_backprop_basic(::Int) = nothing +callsig_backprop_unionsplit(::Int32) = nothing +callsig_backprop_unionsplit(::Int64) = nothing +callsig_backprop_multi(::Int32, ::Int64) = nothing +callsig_backprop_any(::Any) = nothing +callsig_backprop_lhs(::Int) = nothing +callsig_backprop_bailout(::Val{0}) = 0 +callsig_backprop_bailout(::Val{1}) = undefvar # undefvar::Any triggers `bail_out_call` +callsig_backprop_bailout(::Val{2}) = 2 +callsig_backprop_addinteger(a::Integer, b::Integer) = a + b # results in too many matching methods and triggers `bail_out_call`) +@test Base.infer_return_type(callsig_backprop_addinteger) == Any +let effects = Base.infer_effects(callsig_backprop_addinteger) + @test !Core.Compiler.is_consistent(effects) + @test !Core.Compiler.is_effect_free(effects) + @test !Core.Compiler.is_nothrow(effects) + @test !Core.Compiler.is_terminates(effects) +end +callsig_backprop_anti(::Any) = :any +callsig_backprop_anti(::Int) = :int + +@testset "constraint back-propagation from call signature" begin + # basic case + @test Base.infer_return_type(a->(callsig_backprop_basic(a); return a), (Any,)) == Int + + # union-split case + @test Base.infer_return_type(a->(callsig_backprop_unionsplit(a); return a), (Any,)) == Union{Int32,Int64} + + # multiple arguments updates + @test Base.infer_return_type((Any,Any)) do a, b + callsig_backprop_multi(a, b) + return a, b + end == Tuple{Int32,Int64} + + # refinement should happen only when it's worthwhile + @test Base.infer_return_type(a->(callsig_backprop_any(a); return a), (Integer,)) == Integer + + # state update on lhs slot (assignment effect should have the precedence) + @test Base.infer_return_type((Any,)) do a + a = callsig_backprop_lhs(a) + return a + end == Nothing + + # make sure to throw away an intermediate refinement information when we bail out early + # (inference would bail out on `callsig_backprop_bailout(::Val{1})`) + @test Base.infer_return_type(a->(callsig_backprop_bailout(a); return a), (Any,)) == Any + + # if we see all the matching methods, we don't need to throw away refinement information + # even if it's caught by `bail_out_call` check + @test Base.infer_return_type((Any,Any)) do a, b + callsig_backprop_addinteger(a, b) + return a, b + end == Tuple{Integer,Integer} + + # anti case + @test Base.infer_return_type((Any,)) do x + callsig_backprop_anti(x) + return x + end == Any +end + +# make sure to add backedges when we use call signature constraint +function callsig_backprop_invalidation_outer(a) + callsig_backprop_invalidation_inner!(a) + return a +end +@eval callsig_backprop_invalidation_inner!(::Int) = $(gensym(:undefvar)) # ::Any +@test Base.infer_return_type((Any,)) do a + callsig_backprop_invalidation_outer(a) +end == Int +# new definition of `callsig_backprop_invalidation_inner!` should invalidate `callsig_backprop_invalidation_outer` +# (even if the previous return type is annotated as `Any`) +@eval callsig_backprop_invalidation_inner!(::Nothing) = $(gensym(:undefvar)) # ::Any +@test Base.infer_return_type((Any,)) do a + # since inference will bail out at the first matched `_inner!` and so call signature constraint won't be available + callsig_backprop_invalidation_outer(a) +end ≠ Int + +# https://github.com/JuliaLang/julia/issues/37866 +function issue37866(v::Vector{Union{Nothing,Float64}}) + for x in v + if x > 5.0 + return x # x > 5.0 is MethodError for Nothing so can assume ::Float64 + end + end + return 0.0 +end +@test Base.infer_return_type(issue37866, (Vector{Union{Nothing,Float64}},)) == Float64 + # make sure inference on a recursive call graph with nested `Type`s terminates # https://github.com/JuliaLang/julia/issues/40336 f40336(@nospecialize(t)) = f40336(Type{t}) From 442f9d54bda6c0d523e667e19f474b509a3ee90a Mon Sep 17 00:00:00 2001 From: James Wrigley Date: Thu, 25 Jul 2024 16:13:39 +0200 Subject: [PATCH 062/206] Make `Base.depwarn()` public (#55212) There's a few reasons for making it public: - It's already mentioned in the manual (#54211). - It's the easiest way to deprecate a function that shouldn't be used anymore at all. - It's already widely used in the ecosystem: https://juliahub.com/ui/Search?type=code&q=Base.depwarn( I also moved the `@deprecate` docs into a new `Managing deprecations` section because I felt it should go together with `Base.depwarn()`. Might be worth backporting to 1.11? --- base/deprecated.jl | 26 +++++++++++++++++++++++--- base/public.jl | 3 ++- doc/src/base/base.md | 5 +++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index b478995522a58..096ceb311fce3 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -119,9 +119,7 @@ export __has_internal_change # and of exporting the function. # # For more complex cases, move the body of the deprecated method in this file, -# and call depwarn() directly from inside it. The symbol depwarn() expects is -# the name of the function, which is used to ensure that the deprecation warning -# is only printed the first time for each call place. +# and call depwarn() directly from inside it. """ @deprecate old new [export_old=true] @@ -131,6 +129,8 @@ with the specified signature in the process. To prevent `old` from being exported, set `export_old` to `false`. +See also [`Base.depwarn()`](@ref). + !!! compat "Julia 1.5" As of Julia 1.5, functions defined by `@deprecate` do not print warning when `julia` is run without the `--depwarn=yes` flag set, as the default value of `--depwarn` option @@ -227,6 +227,26 @@ macro deprecate(old, new, export_old=true) end end +""" + Base.depwarn(msg::String, funcsym::Symbol; force=false) + +Print `msg` as a deprecation warning. The symbol `funcsym` should be the name +of the calling function, which is used to ensure that the deprecation warning is +only printed the first time for each call place. Set `force=true` to force the +warning to always be shown, even if Julia was started with `--depwarn=no` (the +default). + +See also [`@deprecate`](@ref). + +# Examples +```julia +function deprecated_func() + Base.depwarn("Don't use `deprecated_func()`!", :deprecated_func) + + 1 + 1 +end +``` +""" @nospecializeinfer function depwarn(msg, funcsym; force::Bool=false) @nospecialize # N.B. With this use of `@invokelatest`, we're preventing the addition of backedges from diff --git a/base/public.jl b/base/public.jl index dce1223124856..c11c76c13053c 100644 --- a/base/public.jl +++ b/base/public.jl @@ -112,4 +112,5 @@ public # misc notnothing, runtests, - text_colors + text_colors, + depwarn diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 1d611684d28e2..946f917682814 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -311,7 +311,12 @@ Base.@simd Base.@polly Base.@generated Base.@assume_effects +``` + +## Managing deprecations +```@docs Base.@deprecate +Base.depwarn ``` ## Missing Values From 8e5ca0b2bc5563b25ded0ce301cc0419668aa936 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Thu, 25 Jul 2024 15:38:14 +0100 Subject: [PATCH 063/206] Document `Task(f, n)` API (#55184) Fixes https://github.com/JuliaLang/julia/issues/55005 and helps work around issues discussed in https://github.com/JuliaLang/julia/issues/54998. --- base/docs/basedocs.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 00e4a0afb5c0e..dd4c8d64e7d4e 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1835,12 +1835,15 @@ Stacktrace: DomainError """ - Task(func) + Task(func[, reserved_stack::Int]) Create a `Task` (i.e. coroutine) to execute the given function `func` (which must be callable with no arguments). The task exits when this function returns. The task will run in the "world age" from the parent at construction when [`schedule`](@ref)d. +The optional `reserved_stack` argument specifies the size of the stack available +for this task, in bytes. The default, `0`, uses the system-dependent stack size default. + !!! warning By default tasks will have the sticky bit set to true `t.sticky`. This models the historic default for [`@async`](@ref). Sticky tasks can only be run on the worker thread From 116d42be2f258048cb84756c14fc6e3adbb6b66d Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 25 Jul 2024 20:30:34 +0530 Subject: [PATCH 064/206] LinearAlgebra: Do not specialize arguments in check_A_mul_B!_sizes (#55176) --- stdlib/LinearAlgebra/src/bidiag.jl | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 04d54911d88aa..ddfc6af60ef75 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -541,10 +541,7 @@ function rmul!(B::Bidiagonal, D::Diagonal) return B end -function check_A_mul_B!_sizes(C, A, B) - mA, nA = size(A) - mB, nB = size(B) - mC, nC = size(C) +@noinline function check_A_mul_B!_sizes((mC, nC)::NTuple{2,Integer}, (mA, nA)::NTuple{2,Integer}, (mB, nB)::NTuple{2,Integer}) if mA != mC throw(DimensionMismatch(lazy"first dimension of A, $mA, and first dimension of output C, $mC, must match")) elseif nA != mB @@ -573,7 +570,7 @@ _mul!(C::AbstractMatrix, A::BiTriSym, B::TriSym, _add::MulAddMul) = _mul!(C::AbstractMatrix, A::BiTriSym, B::Bidiagonal, _add::MulAddMul) = _bibimul!(C, A, B, _add) function _bibimul!(C, A, B, _add) - check_A_mul_B!_sizes(C, A, B) + check_A_mul_B!_sizes(size(C), size(A), size(B)) n = size(A,1) n <= 3 && return mul!(C, Array(A), Array(B), _add.alpha, _add.beta) # We use `_rmul_or_fill!` instead of `_modify!` here since using @@ -631,7 +628,7 @@ end function _mul!(C::AbstractMatrix, A::BiTriSym, B::Diagonal, _add::MulAddMul) require_one_based_indexing(C) - check_A_mul_B!_sizes(C, A, B) + check_A_mul_B!_sizes(size(C), size(A), size(B)) n = size(A,1) iszero(n) && return C n <= 3 && return mul!(C, Array(A), Array(B), _add.alpha, _add.beta) @@ -697,7 +694,7 @@ end function _mul!(C::AbstractMatrix, A::AbstractMatrix, B::TriSym, _add::MulAddMul) require_one_based_indexing(C, A) - check_A_mul_B!_sizes(C, A, B) + check_A_mul_B!_sizes(size(C), size(A), size(B)) iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta) n = size(A,1) m = size(B,2) @@ -732,7 +729,7 @@ end function _mul!(C::AbstractMatrix, A::AbstractMatrix, B::Bidiagonal, _add::MulAddMul) require_one_based_indexing(C, A) - check_A_mul_B!_sizes(C, A, B) + check_A_mul_B!_sizes(size(C), size(A), size(B)) iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta) if size(A, 1) <= 3 || size(B, 2) <= 1 return mul!(C, Array(A), Array(B), _add.alpha, _add.beta) @@ -762,7 +759,7 @@ _mul!(C::AbstractMatrix, A::Diagonal, B::TriSym, _add::MulAddMul) = _dibimul!(C, A, B, _add) function _dibimul!(C, A, B, _add) require_one_based_indexing(C) - check_A_mul_B!_sizes(C, A, B) + check_A_mul_B!_sizes(size(C), size(A), size(B)) n = size(A,1) n <= 3 && return mul!(C, Array(A), Array(B), _add.alpha, _add.beta) _rmul_or_fill!(C, _add.beta) # see the same use above From 157d4ee376cd44e42fb2c2c05886254f41b9d29b Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 25 Jul 2024 19:13:02 +0200 Subject: [PATCH 065/206] fix at-main docstring to not code quote a compat box (#55242) --- base/client.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/client.jl b/base/client.jl index 7fc40d7906879..aa0739eaed0fe 100644 --- a/base/client.jl +++ b/base/client.jl @@ -632,10 +632,10 @@ module MyApp end const main = MyApp.main # `julia` Will *NOT* execute MyApp.main unless there is a separate `@main` annotation in `Main` +``` !!! compat "Julia 1.11" This macro is new in Julia 1.11. At present, the precise semantics of `@main` are still subject to change. -``` """ macro main(args...) if !isempty(args) From 4ab567fd2b713384f3b542188bb90d1238a71b39 Mon Sep 17 00:00:00 2001 From: Steve Kelly Date: Thu, 25 Jul 2024 20:42:28 +0200 Subject: [PATCH 066/206] Add -Wformat-security to build (#53546) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enhances some printing security: > At present, this warns about calls to printf and scanf functions where > the format string is not a string literal and there are no format arguments, > as in printf (foo);. This may be a security hole if the format string came > from untrusted input and contains ‘%n’. (This is currently a subset of what > -Wformat-nonliteral warns about, but in future warnings may be added to > -Wformat-security that are not included in -Wformat-nonliteral.) --- Make.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Make.inc b/Make.inc index 2b15c01926db8..43d33e358dc4b 100644 --- a/Make.inc +++ b/Make.inc @@ -495,7 +495,7 @@ MACOSX_VERSION_MIN := 11.0 endif endif -JCFLAGS_COMMON := -std=gnu11 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 +JCFLAGS_COMMON := -std=gnu11 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -Wformat -Wformat-security JCFLAGS_CLANG := $(JCFLAGS_COMMON) JCFLAGS_GCC := $(JCFLAGS_COMMON) -fno-gnu-unique @@ -504,7 +504,7 @@ JCPPFLAGS_COMMON := -fasynchronous-unwind-tables JCPPFLAGS_CLANG := $(JCPPFLAGS_COMMON) -mllvm -enable-tail-merge=0 JCPPFLAGS_GCC := $(JCPPFLAGS_COMMON) -fno-tree-tail-merge -JCXXFLAGS_COMMON := -pipe $(fPIC) -fno-rtti -std=c++17 +JCXXFLAGS_COMMON := -pipe $(fPIC) -fno-rtti -std=c++17 -Wformat -Wformat-security JCXXFLAGS_CLANG := $(JCXXFLAGS_COMMON) -pedantic JCXXFLAGS_GCC := $(JCXXFLAGS_COMMON) -fno-gnu-unique From b99e411a5501f51f54309eef751f982db5b045dd Mon Sep 17 00:00:00 2001 From: stahta01 Date: Thu, 25 Jul 2024 14:45:33 -0400 Subject: [PATCH 067/206] [CYGWIN] [BUILD] deps/blastrampoline: Fix build with USE_BINARYBUILDER_BLASTRAMPOLINE=0 (#49938) Error: ``` cp: cannot stat 'libblastrampoline.dll': No such file or directory ``` Build commands: ``` cd ~/devel/julia && \ git clean -ffxd --exclude=srccache --exclude=scratch && \ [[ -d "./usr-staging" ]] && rm -rf "./usr-staging" ; \ [[ -d "./usr" ]] && rm -rf "./usr" ; \ [[ -d "./deps/srccache/blastrampoline.git" ]] && rm -rf "./deps/srccache/blastrampoline.git" ; \ [[ -d "./deps/scratch/blastrampoline" ]] && rm -rf "./deps/scratch/blastrampoline" ; \ [[ -d "./deps/scratch/SuiteSparse-5.10.1" ]] && rm -rf "./deps/scratch/SuiteSparse-5.10.1" ; \ git checkout master && \ git log -1 --format=oneline && \ echo 'XC_HOST = x86_64-w64-mingw32' > Make.user && \ echo 'DEPS_GIT = 1' >> Make.user && \ echo 'USE_BINARYBUILDER_BLASTRAMPOLINE = 0' >> Make.user && \ echo 'USE_BINARYBUILDER_LIBSUITESPARSE = 0' >> Make.user && \ make -C deps install-csl && \ cp /usr/x86_64-w64-mingw32/sys-root/mingw/lib/libmsvcrt.a ./usr/lib/libmsvcrt.a && \ make all --jobs=1 2>&1 | tee ../julia-master-blastrampoline-all-build.log && echo -ne '\007' ``` Tim S. --- deps/blastrampoline.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deps/blastrampoline.mk b/deps/blastrampoline.mk index bd1cb65c6ae2d..cfa28a4d8b88f 100644 --- a/deps/blastrampoline.mk +++ b/deps/blastrampoline.mk @@ -16,16 +16,16 @@ $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-configured: $(BUILDDIR)/$(BLASTRAMPO BLASTRAMPOLINE_BUILD_ROOT := $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/src $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-compiled: $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-configured cd $(dir $@)/src && $(MAKE) $(BLASTRAMPOLINE_BUILD_OPTS) -ifeq ($(OS), WINNT) - # Windows doesn't like soft link, use hard link - cd $(BLASTRAMPOLINE_BUILD_ROOT)/build/ && \ - cp -f --dereference --link libblastrampoline.dll libblastrampoline.dll -endif echo 1 > $@ define BLASTRAMPOLINE_INSTALL $(MAKE) -C $(BLASTRAMPOLINE_BUILD_ROOT) install $(BLASTRAMPOLINE_BUILD_OPTS) DESTDIR="$2" endef +ifeq ($(OS), WINNT) +# Windows doesn't like soft link, use hard link to copy file without version suffix +BLASTRAMPOLINE_INSTALL += && cd $2$$(build_prefix)/bin && \ +$$(WIN_MAKE_HARD_LINK) libblastrampoline-*.dll libblastrampoline.dll +endif $(eval $(call staged-install, \ blastrampoline,$(BLASTRAMPOLINE_SRC_DIR), \ BLASTRAMPOLINE_INSTALL,, \ From 1129e8276b76f9a9b80858c786e47b8f82f9a2cb Mon Sep 17 00:00:00 2001 From: Orestis Ousoultzoglou Date: Fri, 26 Jul 2024 00:13:04 +0300 Subject: [PATCH 068/206] Insert hlines in show with MD objects (#55116) Fixes #54486. --- stdlib/Markdown/Project.toml | 2 +- .../Markdown/src/render/terminal/formatting.jl | 14 ++++++++++++++ stdlib/Markdown/src/render/terminal/render.jl | 5 ++++- stdlib/Markdown/test/runtests.jl | 9 ++++++++- stdlib/REPL/src/docview.jl | 16 +--------------- stdlib/REPL/test/docview.jl | 7 ------- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/stdlib/Markdown/Project.toml b/stdlib/Markdown/Project.toml index e2edcdefea537..a48a3d1f0b345 100644 --- a/stdlib/Markdown/Project.toml +++ b/stdlib/Markdown/Project.toml @@ -4,8 +4,8 @@ version = "1.11.0" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" -StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" JuliaSyntaxHighlighting = "dc6e5ff7-fb65-4e79-a425-ec3bc9c03011" +StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/stdlib/Markdown/src/render/terminal/formatting.jl b/stdlib/Markdown/src/render/terminal/formatting.jl index 009fd2eb3af18..3274483801c77 100644 --- a/stdlib/Markdown/src/render/terminal/formatting.jl +++ b/stdlib/Markdown/src/render/terminal/formatting.jl @@ -66,3 +66,17 @@ function wraplines(content::Union{Annot, SubString{<:Annot}}, width::Integer = 8 end lines end + +# Print horizontal lines between each docstring if there are multiple docs +function insert_hlines(docs) + if !isa(docs, MD) || !haskey(docs.meta, :results) || isempty(docs.meta[:results]) + return docs + end + docs = docs::MD + v = Any[] + for (n, doc) in enumerate(docs.content) + push!(v, doc) + n == length(docs.content) || push!(v, HorizontalRule()) + end + return MD(v) +end diff --git a/stdlib/Markdown/src/render/terminal/render.jl b/stdlib/Markdown/src/render/terminal/render.jl index 16cf413639b00..619b2c8b8ef4a 100644 --- a/stdlib/Markdown/src/render/terminal/render.jl +++ b/stdlib/Markdown/src/render/terminal/render.jl @@ -13,7 +13,10 @@ function term(io::IO, content::Vector, cols) term(io, content[end], cols) end -term(io::IO, md::MD, columns = cols(io)) = term(io, md.content, columns) +function term(io::IO, md::MD, columns = cols(io)) + md = insert_hlines(md) + return term(io, md.content, columns) +end function term(io::IO, md::Paragraph, columns) lines = wraplines(annotprint(terminline, md.content), columns-2margin) diff --git a/stdlib/Markdown/test/runtests.jl b/stdlib/Markdown/test/runtests.jl index a3026683ad1e7..ffdb735f3b7cd 100644 --- a/stdlib/Markdown/test/runtests.jl +++ b/stdlib/Markdown/test/runtests.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test, Markdown, StyledStrings -import Markdown: MD, Paragraph, Header, Italic, Bold, LineBreak, plain, term, html, rst, Table, Code, LaTeX, Footnote +import Markdown: MD, Paragraph, Header, Italic, Bold, LineBreak, insert_hlines, plain, term, html, rst, Table, Code, LaTeX, Footnote import Base: show # Basics @@ -1301,3 +1301,10 @@ end @testset "Docstrings" begin @test isempty(Docs.undocumented_names(Markdown)) end + +@testset "Non-Markdown" begin + # https://github.com/JuliaLang/julia/issues/37765 + @test isa(insert_hlines(Text("foo")), Text) + # https://github.com/JuliaLang/julia/issues/37757 + @test insert_hlines(nothing) === nothing +end diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 63a3601dbbae9..5086aa0c9485c 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -23,7 +23,7 @@ using Unicode: normalize function helpmode(io::IO, line::AbstractString, mod::Module=Main) internal_accesses = Set{Pair{Module,Symbol}}() quote - docs = $REPL.insert_hlines($(REPL._helpmode(io, line, mod, internal_accesses))) + docs = $Markdown.insert_hlines($(REPL._helpmode(io, line, mod, internal_accesses))) $REPL.insert_internal_warning(docs, $internal_accesses) end end @@ -76,20 +76,6 @@ function _helpmode(io::IO, line::AbstractString, mod::Module=Main, internal_acce end _helpmode(line::AbstractString, mod::Module=Main) = _helpmode(stdout, line, mod) -# Print horizontal lines between each docstring if there are multiple docs -function insert_hlines(docs) - if !isa(docs, Markdown.MD) || !haskey(docs.meta, :results) || isempty(docs.meta[:results]) - return docs - end - docs = docs::Markdown.MD - v = Any[] - for (n, doc) in enumerate(docs.content) - push!(v, doc) - n == length(docs.content) || push!(v, Markdown.HorizontalRule()) - end - return Markdown.MD(v) -end - function formatdoc(d::DocStr) buffer = IOBuffer() for part in d.text diff --git a/stdlib/REPL/test/docview.jl b/stdlib/REPL/test/docview.jl index 123ff820bc939..6b374ed7f0149 100644 --- a/stdlib/REPL/test/docview.jl +++ b/stdlib/REPL/test/docview.jl @@ -28,13 +28,6 @@ end @test occursin("Couldn't find 'mutable s'", str) end -@testset "Non-Markdown" begin - # https://github.com/JuliaLang/julia/issues/37765 - @test isa(REPL.insert_hlines(Markdown.Text("foo")), Markdown.Text) - # https://github.com/JuliaLang/julia/issues/37757 - @test REPL.insert_hlines(nothing) === nothing -end - @testset "Check @var_str also completes to var\"\" in REPL.doc_completions()" begin checks = ["var", "raw", "r"] symbols = "@" .* checks .* "_str" From bbb4403f589ff695713ba6da4d745ca944e58044 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:35:51 -0300 Subject: [PATCH 069/206] refactor mallocarray_t to reflect it should carry jl_genericmemory_t (#55237) Seems like this `mallocarray_t` container is only carrying objects of type `jl_genericmemory_t` after the memory work. Let's: * Rename the container type to `mallocmemory_t`. * Make the payload type a bit more strict to ensure a bit more type safety (i.e. change the `a` field from `jl_value_t *` to `jl_genericmemory_t *`). * Add a comment to indicate the pointer tagging in the lowest bit of the payload. --- src/gc-debug.c | 2 +- src/gc-tls.h | 4 ++-- src/gc.c | 12 ++++++------ src/gc.h | 11 +++++------ 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index 62be5c0eab554..bb70daebbf0e6 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -1009,7 +1009,7 @@ void gc_stats_big_obj(void) v = v->next; } - mallocarray_t *ma = ptls2->gc_tls.heap.mallocarrays; + mallocmemory_t *ma = ptls2->gc_tls.heap.mallocarrays; while (ma != NULL) { if (gc_marked(jl_astaggedvalue(ma->a)->bits.gc)) { nused++; diff --git a/src/gc-tls.h b/src/gc-tls.h index 8b8ccd6ad6c27..9e4b09404db84 100644 --- a/src/gc-tls.h +++ b/src/gc-tls.h @@ -28,8 +28,8 @@ typedef struct { small_arraylist_t live_tasks; // variables for tracking malloc'd arrays - struct _mallocarray_t *mallocarrays; - struct _mallocarray_t *mafreelist; + struct _mallocmemory_t *mallocarrays; + struct _mallocmemory_t *mafreelist; // variable for tracking young (i.e. not in `GC_OLD_MARKED`/last generation) large objects struct _bigval_t *young_generation_of_bigvals; diff --git a/src/gc.c b/src/gc.c index f5c527d22115d..9f57bf3c6b944 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1069,15 +1069,15 @@ static void sweep_big(jl_ptls_t ptls) JL_NOTSAFEPOINT void jl_gc_track_malloced_genericmemory(jl_ptls_t ptls, jl_genericmemory_t *m, int isaligned){ // This is **NOT** a GC safe point. - mallocarray_t *ma; + mallocmemory_t *ma; if (ptls->gc_tls.heap.mafreelist == NULL) { - ma = (mallocarray_t*)malloc_s(sizeof(mallocarray_t)); + ma = (mallocmemory_t*)malloc_s(sizeof(mallocmemory_t)); } else { ma = ptls->gc_tls.heap.mafreelist; ptls->gc_tls.heap.mafreelist = ma->next; } - ma->a = (jl_value_t*)((uintptr_t)m | !!isaligned); + ma->a = (jl_genericmemory_t*)((uintptr_t)m | !!isaligned); ma->next = ptls->gc_tls.heap.mallocarrays; ptls->gc_tls.heap.mallocarrays = ma; } @@ -1193,10 +1193,10 @@ static void sweep_malloced_memory(void) JL_NOTSAFEPOINT for (int t_i = 0; t_i < gc_n_threads; t_i++) { jl_ptls_t ptls2 = gc_all_tls_states[t_i]; if (ptls2 != NULL) { - mallocarray_t *ma = ptls2->gc_tls.heap.mallocarrays; - mallocarray_t **pma = &ptls2->gc_tls.heap.mallocarrays; + mallocmemory_t *ma = ptls2->gc_tls.heap.mallocarrays; + mallocmemory_t **pma = &ptls2->gc_tls.heap.mallocarrays; while (ma != NULL) { - mallocarray_t *nxt = ma->next; + mallocmemory_t *nxt = ma->next; jl_value_t *a = (jl_value_t*)((uintptr_t)ma->a & ~1); int bits = jl_astaggedvalue(a)->bits.gc; if (gc_marked(bits)) { diff --git a/src/gc.h b/src/gc.h index 9ac8a0abb65b9..e22ded0ec6740 100644 --- a/src/gc.h +++ b/src/gc.h @@ -145,12 +145,11 @@ JL_EXTENSION typedef struct _bigval_t { // must be 64-byte aligned here, in 32 & 64 bit modes } bigval_t; -// data structure for tracking malloc'd arrays and genericmemory. - -typedef struct _mallocarray_t { - jl_value_t *a; - struct _mallocarray_t *next; -} mallocarray_t; +// data structure for tracking malloc'd genericmemory. +typedef struct _mallocmemory_t { + jl_genericmemory_t *a; // lowest bit is tagged if this is aligned memory + struct _mallocmemory_t *next; +} mallocmemory_t; // pool page metadata typedef struct _jl_gc_pagemeta_t { From deda8b5b8f64d9e8aca6272859e85f3d4de2b221 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 25 Jul 2024 18:57:50 -0700 Subject: [PATCH 070/206] Initial support for FreeBSD AArch64 (#55089) Much of this is based on the work of Val Packett in PR 28171; she is included as a co-author of these changes. Co-Authored-By: Val Packett --- Make.inc | 18 +++++++++++++++++- deps/llvm.mk | 1 + src/processor_arm.cpp | 13 +++++++++++-- src/signal-handling.c | 2 ++ src/signals-unix.c | 15 +++++++++++++++ src/stackwalk.c | 31 ++++++++++++++++++++++++++++++- 6 files changed, 76 insertions(+), 4 deletions(-) diff --git a/Make.inc b/Make.inc index 43d33e358dc4b..d9a131b4d8a98 100644 --- a/Make.inc +++ b/Make.inc @@ -948,6 +948,15 @@ BINARY:=64 MARCH= endif +# Allow Clang to use CRC instructions (only applicable on AArch64) +ifneq (,$(findstring aarch64,$(ARCH))) +ifeq ($(USECLANG),1) +ifeq (,$(MARCH)) +JCFLAGS += -mcrc +endif +endif +endif + # If we are running on powerpc64 or ppc64, fail out dramatically ifneq (,$(filter $(ARCH), powerpc64 ppc64)) $(error Big-endian PPC64 is not supported, to ignore this error, set ARCH=ppc64le) @@ -1392,9 +1401,16 @@ OSLIBS += -lelf -lkvm -lrt -lpthread -latomic # make it loaded first to # prevent from linking to outdated system libs. # See #21788 +# TODO: Determine whether the condition here on AArch64 (added in #55089) should actually +# be `ifneq ($(USE_BINARYBUILDER),0)`. We vendor a correctly versioned libgcc_s when using +# BinaryBuilder which we want to link in early as noted above, but it could be the case +# that without BinaryBuilder, regardless of architecture, we need to delay linking libgcc_s +# to avoid getting the system one. +ifeq (,$(findstring aarch64,$(ARCH))) OSLIBS += -lgcc_s +endif -OSLIBS += -Wl,--export-dynamic -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ +OSLIBS += -Wl,--export-dynamic -Wl,--undefined-version -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ $(NO_WHOLE_ARCHIVE) endif diff --git a/deps/llvm.mk b/deps/llvm.mk index 592736fe4a149..7ead1dab1d925 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -94,6 +94,7 @@ LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING="$(LLVM_TARGETS)" -DCMAKE_BUILD_TYP LLVM_CMAKE += -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="$(LLVM_EXPERIMENTAL_TARGETS)" LLVM_CMAKE += -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_HOST_TRIPLE="$(or $(XC_HOST),$(BUILD_MACHINE))" LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=ON -DZLIB_LIBRARY="$(build_prefix)/lib" +LLVM_CMAKE += -DLLVM_ENABLE_ZSTD=OFF LLVM_CMAKE += -DCOMPILER_RT_ENABLE_IOS=OFF -DCOMPILER_RT_ENABLE_WATCHOS=OFF -DCOMPILER_RT_ENABLE_TVOS=OFF ifeq ($(USE_POLLY_ACC),1) LLVM_CMAKE += -DPOLLY_ENABLE_GPGPU_CODEGEN=ON diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index 0d9ed43a23a58..b9ad5e68111e5 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -11,7 +11,7 @@ // This nesting is required to allow compilation on musl #define USE_DYN_GETAUXVAL -#if defined(_OS_LINUX_) && defined(_CPU_AARCH64_) +#if (defined(_OS_LINUX_) || defined(_OS_FREEBSD_)) && defined(_CPU_AARCH64_) # undef USE_DYN_GETAUXVAL # include #elif defined(__GLIBC_PREREQ) @@ -737,7 +737,16 @@ static NOINLINE std::pair> _get_host_cpu() # define AT_HWCAP2 26 #endif -#if defined(USE_DYN_GETAUXVAL) +#if defined(_OS_FREEBSD_) +static inline unsigned long jl_getauxval(unsigned long type) +{ + unsigned long val; + if (elf_aux_info((int)type, &val, sizeof(val)) != 0) { + return 0; + } + return val; +} +#elif defined(USE_DYN_GETAUXVAL) static unsigned long getauxval_procfs(unsigned long type) { int fd = open("/proc/self/auxv", O_RDONLY); diff --git a/src/signal-handling.c b/src/signal-handling.c index 3b8d98fbee588..febf05b653662 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -340,6 +340,8 @@ static uintptr_t jl_get_pc_from_ctx(const void *_ctx) return ((CONTEXT*)_ctx)->Rip; #elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) return ((ucontext_t*)_ctx)->uc_mcontext.pc; +#elif defined(_OS_FREEBSD_) && defined(_CPU_AARCH64_) + return ((ucontext_t*)_ctx)->uc_mcontext.mc_gpregs.gp_elr; #elif defined(_OS_LINUX_) && defined(_CPU_ARM_) return ((ucontext_t*)_ctx)->uc_mcontext.arm_pc; #else diff --git a/src/signals-unix.c b/src/signals-unix.c index eedc5f0aae94a..aa4d1626a4305 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -85,6 +85,9 @@ static inline __attribute__((unused)) uintptr_t jl_get_rsp_from_ctx(const void * #elif defined(_OS_FREEBSD_) && defined(_CPU_X86_64_) const ucontext_t *ctx = (const ucontext_t*)_ctx; return ctx->uc_mcontext.mc_rsp; +#elif defined(_OS_FREEBSD_) && defined(_CPU_AARCH64_) + const ucontext_t *ctx = (const ucontext_t*)_ctx; + return ctx->uc_mcontext.mc_gpregs.gp_sp; #elif defined(_OS_OPENBSD_) && defined(_CPU_X86_64_) const struct sigcontext *ctx = (const struct sigcontext *)_ctx; return ctx->sc_rsp; @@ -160,6 +163,11 @@ JL_NO_ASAN static void jl_call_in_ctx(jl_ptls_t ptls, void (*fptr)(void), int si ctx->uc_mcontext.sp = rsp; ctx->uc_mcontext.regs[29] = 0; // Clear link register (x29) ctx->uc_mcontext.pc = (uintptr_t)fptr; +#elif defined(_OS_FREEBSD_) && defined(_CPU_AARCH64_) + ucontext_t *ctx = (ucontext_t*)_ctx; + ctx->uc_mcontext.mc_gpregs.gp_sp = rsp; + ctx->uc_mcontext.mc_gpregs.gp_x[29] = 0; // Clear link register (x29) + ctx->uc_mcontext.mc_gpregs.gp_elr = (uintptr_t)fptr; #elif defined(_OS_LINUX_) && defined(_CPU_ARM_) ucontext_t *ctx = (ucontext_t*)_ctx; uintptr_t target = (uintptr_t)fptr; @@ -350,6 +358,13 @@ int is_write_fault(void *context) { ucontext_t *ctx = (ucontext_t*)context; return exc_reg_is_write_fault(ctx->uc_mcontext.mc_err); } +#elif defined(_OS_FREEBSD_) && defined(_CPU_AARCH64_) +// FreeBSD seems not to expose a means of accessing ESR via `ucontext_t` on AArch64. +// TODO: Is there an alternative approach that can be taken? ESR may become accessible +// in a future release though. +int is_write_fault(void *context) { + return 0; +} #elif defined(_OS_OPENBSD_) && defined(_CPU_X86_64_) int is_write_fault(void *context) { struct sigcontext *ctx = (struct sigcontext *)context; diff --git a/src/stackwalk.c b/src/stackwalk.c index d6bed827e19ae..7e4a04f6b77e4 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -1137,9 +1137,10 @@ static void jl_rec_backtrace(jl_task_t *t) JL_NOTSAFEPOINT (void)mctx; (void)c; #endif - #elif defined(_OS_FREEBSD_) && defined(_CPU_X86_64_) + #elif defined(_OS_FREEBSD_) sigjmp_buf *mctx = &t->ctx.ctx.uc_mcontext; mcontext_t *mc = &c.uc_mcontext; + #if defined(_CPU_X86_64_) // https://github.com/freebsd/freebsd-src/blob/releng/13.1/lib/libc/amd64/gen/_setjmp.S mc->mc_rip = ((long*)mctx)[0]; mc->mc_rbx = ((long*)mctx)[1]; @@ -1150,6 +1151,34 @@ static void jl_rec_backtrace(jl_task_t *t) JL_NOTSAFEPOINT mc->mc_r14 = ((long*)mctx)[6]; mc->mc_r15 = ((long*)mctx)[7]; context = &c; + #elif defined(_CPU_AARCH64_) + mc->mc_gpregs.gp_x[19] = ((long*)mctx)[0]; + mc->mc_gpregs.gp_x[20] = ((long*)mctx)[1]; + mc->mc_gpregs.gp_x[21] = ((long*)mctx)[2]; + mc->mc_gpregs.gp_x[22] = ((long*)mctx)[3]; + mc->mc_gpregs.gp_x[23] = ((long*)mctx)[4]; + mc->mc_gpregs.gp_x[24] = ((long*)mctx)[5]; + mc->mc_gpregs.gp_x[25] = ((long*)mctx)[6]; + mc->mc_gpregs.gp_x[26] = ((long*)mctx)[7]; + mc->mc_gpregs.gp_x[27] = ((long*)mctx)[8]; + mc->mc_gpregs.gp_x[28] = ((long*)mctx)[9]; + mc->mc_gpregs.gp_x[29] = ((long*)mctx)[10]; + mc->mc_gpregs.gp_lr = ((long*)mctx)[11]; + mc->mc_gpregs.gp_sp = ((long*)mctx)[12]; + mc->mc_fpregs.fp_q[7] = ((long*)mctx)[13]; + mc->mc_fpregs.fp_q[8] = ((long*)mctx)[14]; + mc->mc_fpregs.fp_q[9] = ((long*)mctx)[15]; + mc->mc_fpregs.fp_q[10] = ((long*)mctx)[16]; + mc->mc_fpregs.fp_q[11] = ((long*)mctx)[17]; + mc->mc_fpregs.fp_q[12] = ((long*)mctx)[18]; + mc->mc_fpregs.fp_q[13] = ((long*)mctx)[19]; + mc->mc_fpregs.fp_q[14] = ((long*)mctx)[20]; + context = &c; + #else + #pragma message("jl_rec_backtrace not defined for ASM/SETJMP on unknown freebsd") + (void)mctx; + (void)c; + #endif #else #pragma message("jl_rec_backtrace not defined for ASM/SETJMP on unknown system") (void)c; From 523cb395b253d4312bdb30c42d835baba2f073e4 Mon Sep 17 00:00:00 2001 From: Christian Guinard <28689358+christiangnrd@users.noreply.github.com> Date: Fri, 26 Jul 2024 00:05:00 -0300 Subject: [PATCH 071/206] Move `JuliaSyntaxHighlighting` changes from HISTORY to NEWS (#55246) This reflects the removal of JuliaSyntaxHighlighting from the 1.11 release, in light of it first being used within the stdlib in the development version (1.12). --- HISTORY.md | 6 ------ NEWS.md | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index bf59f6da9659a..66f856143711c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -128,12 +128,6 @@ Standard library changes * The new `@styled_str` string macro provides a convenient way of creating a `AnnotatedString` with various faces or other attributes applied ([#49586]). -#### JuliaSyntaxHighlighting - -* A new standard library for applying syntax highlighting to Julia code, this - uses `JuliaSyntax` and `StyledStrings` to implement a `highlight` function - that creates an `AnnotatedString` with syntax highlighting applied. - #### Package Manager #### LinearAlgebra diff --git a/NEWS.md b/NEWS.md index b842012bfc33b..c98fa6b862b67 100644 --- a/NEWS.md +++ b/NEWS.md @@ -106,6 +106,10 @@ Standard library changes #### JuliaSyntaxHighlighting +* A new standard library for applying syntax highlighting to Julia code, this + uses `JuliaSyntax` and `StyledStrings` to implement a `highlight` function + that creates an `AnnotatedString` with syntax highlighting applied. + #### Package Manager #### LinearAlgebra From 5c27d4cfb3e7c6013f23af5a8ef7ba5908208c9d Mon Sep 17 00:00:00 2001 From: Adrian Hill Date: Fri, 26 Jul 2024 07:48:24 +0200 Subject: [PATCH 072/206] Update ModernJuliaWorkflows URL (#55254) Use our shiny new URL [modernjuliaworkflows.org](https://modernjuliaworkflows.org/). [Thanks a lot](https://github.com/JuliaLang/julia/pull/55036#issuecomment-2211068320) @ViralBShah! --- doc/src/manual/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index e34d5543389c1..2c69aabbda192 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -56,4 +56,4 @@ search: begin disable_sigint reenable_sigint begin...end denotes a block of code. ``` -If you already know Julia a bit, you might want to peek ahead at [Performance Tips](@ref man-performance-tips) and [Workflow Tips](@ref man-workflow-tips), or check out the comprehensive [ModernJuliaWorkflows](https://modernjuliaworkflows.github.io/) blog. +If you already know Julia a bit, you might want to peek ahead at [Performance Tips](@ref man-performance-tips) and [Workflow Tips](@ref man-workflow-tips), or check out the comprehensive [ModernJuliaWorkflows](https://modernjuliaworkflows.org/) blog. From 5650a13fd18d029259df49558702b182d51ca85b Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Fri, 26 Jul 2024 05:45:23 -0400 Subject: [PATCH 073/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=206b4394914=20to=20e4a6723bf=20(#55258)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Pkg URL: https://github.com/JuliaLang/Pkg.jl.git Stdlib branch: master Julia branch: master Old commit: 6b4394914 New commit: e4a6723bf Julia version: 1.12.0-DEV Pkg version: 1.12.0 Bump invoked by: @IanButterworth Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Pkg.jl/compare/6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b...e4a6723bf3074764ff9266e5e13dfea501431b33 ``` $ git log --oneline 6b4394914..e4a6723bf e4a6723bf Use `Base.TOML.Parser{Dates}` for TOML parsing w/ Dates support (#3938) 8c1f45d98 Append bundled depots to places where we empty it during tests (#3807) 2fdfabaf5 Test fixes (#3972) 34bb51ece fix bad depot path setting (#3971) 3715685b9 fix suggestions threshold for printing (#3968) 3f81d6c4d feat: add JULIA_PKG_GC_AUTO env var (#3642) fad26d7f2 check `project_file` isa String (#3967) 8875120ad fix not hardcoding "Project.toml" when fixing up extensions in manifest (#3851) 90d42a1b0 Make manifest usage log errors non-fatal (#3962) ``` Co-authored-by: Dilum Aluthge --- .../Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 | 1 - .../Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 | 1 - .../Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 | 1 + .../Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 create mode 100644 deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 diff --git a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 deleted file mode 100644 index d86d2b6e8882f..0000000000000 --- a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e17ce4624b0df926d63ff5259ba5632e diff --git a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 b/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 deleted file mode 100644 index 011650a167629..0000000000000 --- a/deps/checksums/Pkg-6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -d02efe5a6f0a8bbc51f272170c37a0d1492c5b513b4d4b7566226247ddff1836144b0490ad4b443983f7a7133e77b7c631e8e22eebe82fb63f697f57223c1f4b diff --git a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 new file mode 100644 index 0000000000000..9151d83645ac6 --- /dev/null +++ b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 @@ -0,0 +1 @@ +e42b7400acc62aa5987dca1be49290ae diff --git a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 new file mode 100644 index 0000000000000..5498d9f6a3069 --- /dev/null +++ b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 @@ -0,0 +1 @@ +71dd216051496210416db6a3489f9a934eb21ba59054fa921758e588450c6b1450f7771c8796d7b78ae3e481e0d730ad1bf48573dd2ec39975a840f9cc33114a diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 4490665878b4d..7742b41441528 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 6b43949143662f7d5b72e5e4fcbae19bf0f5ff7b +PKG_SHA1 = e4a6723bf3074764ff9266e5e13dfea501431b33 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From 42a8efff5a6b96394a36af541cf8a7a4725632fb Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Fri, 26 Jul 2024 06:02:57 -0500 Subject: [PATCH 074/206] Deprecate buggy `stat(::Integer)` method (#55250) Precursor to #54855 --- base/deprecated.jl | 6 ++++++ base/stat.jl | 1 - test/file.jl | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 096ceb311fce3..f88a53526aa37 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -526,3 +526,9 @@ end @deprecate invpermute!!(a, p::AbstractVector{<:Integer}) invpermute!(a, p) false # END 1.11 deprecations + +# BEGIN 1.12 deprecations + +@deprecate stat(fd::Integer) stat(RawFD(fd)) + +# END 1.12 deprecations diff --git a/base/stat.jl b/base/stat.jl index b17fd54cb1d64..29edf010b7815 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -189,7 +189,6 @@ lstat(path::AbstractString) = @stat_call jl_lstat Cstring path if RawFD !== OS_HANDLE global stat(fd::RawFD) = stat(Libc._get_osfhandle(fd)) end -stat(fd::Integer) = stat(RawFD(fd)) """ stat(file) diff --git a/test/file.jl b/test/file.jl index b88595981261e..f82b2a0fd8f39 100644 --- a/test/file.jl +++ b/test/file.jl @@ -442,8 +442,7 @@ end for pth in ("afile", joinpath("afile", "not_file"), SubString(joinpath(dir, "afile")), - Base.RawFD(-1), - -1) + Base.RawFD(-1)) test_stat_error(stat, pth) test_stat_error(lstat, pth) end From a07031ad6fac1e3cd07f8cec28d65f0442921d42 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:25:54 -0300 Subject: [PATCH 075/206] Fix MEMPROFILE (#55236) Should fix https://github.com/JuliaLang/julia/issues/46724. Example output: ``` 8 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 16 : 1857/ 725307 objects ( 89% old), 709 pages, 29 kB, 11340 kB waste 24 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 32 : 55025/ 922866 objects ( 96% old), 1806 pages, 1719 kB, 28841 kB waste 40 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 48 : 31668/ 199826 objects ( 97% old), 586 pages, 1484 kB, 9338 kB waste 56 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 64 : 32767/ 118320 objects ( 94% old), 464 pages, 2047 kB, 7311 kB waste 72 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 80 : 13711/ 19584 objects ( 95% old), 96 pages, 1071 kB, 1486 kB waste 88 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 96 : 4893/ 8500 objects ( 95% old), 50 pages, 458 kB, 781 kB waste 104 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 112 : 3513/ 6132 objects ( 99% old), 42 pages, 384 kB, 670 kB waste 120 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 128 : 3890/ 4572 objects ( 90% old), 36 pages, 486 kB, 532 kB waste 136 : 0/ 0 objects ( 0% old), 0 pages, 0 kB, 0 kB waste 144 : 387/ 12656 objects ( 94% old), 112 pages, 54 kB, 1789 kB waste 160 : 553/ 1836 objects ( 96% old), 18 pages, 86 kB, 284 kB waste 176 : 463/ 1395 objects ( 99% old), 15 pages, 79 kB, 239 kB waste 192 : 170/ 765 objects ( 96% old), 9 pages, 31 kB, 142 kB waste 208 : 137/ 468 objects ( 82% old), 6 pages, 27 kB, 91 kB waste 224 : 6180/ 6497 objects ( 99% old), 89 pages, 1351 kB, 1423 kB waste 240 : 93/ 544 objects (100% old), 8 pages, 21 kB, 128 kB waste 256 : 310/ 693 objects ( 98% old), 11 pages, 77 kB, 175 kB waste 272 : 196/ 360 objects ( 91% old), 6 pages, 52 kB, 91 kB waste 288 : 817/ 1120 objects ( 92% old), 20 pages, 229 kB, 301 kB waste 304 : 67/ 265 objects (100% old), 5 pages, 19 kB, 80 kB waste 336 : 133/ 480 objects ( 99% old), 10 pages, 43 kB, 159 kB waste 368 : 238/ 572 objects ( 97% old), 13 pages, 85 kB, 205 kB waste 400 : 91/ 360 objects (100% old), 9 pages, 35 kB, 144 kB waste 448 : 127/ 432 objects ( 96% old), 12 pages, 55 kB, 189 kB waste 496 : 110/ 330 objects ( 99% old), 10 pages, 53 kB, 159 kB waste 544 : 150/ 330 objects ( 98% old), 11 pages, 79 kB, 174 kB waste 576 : 45/ 168 objects (100% old), 6 pages, 25 kB, 96 kB waste 624 : 61/ 182 objects (100% old), 7 pages, 37 kB, 112 kB waste 672 : 49/ 144 objects (100% old), 6 pages, 32 kB, 96 kB waste 736 : 63/ 198 objects ( 93% old), 9 pages, 45 kB, 141 kB waste 816 : 63/ 180 objects ( 98% old), 9 pages, 50 kB, 143 kB waste 896 : 61/ 126 objects (100% old), 7 pages, 53 kB, 112 kB waste 1008 : 59/ 128 objects ( 89% old), 8 pages, 58 kB, 122 kB waste 1088 : 67/ 120 objects ( 91% old), 8 pages, 71 kB, 121 kB waste 1168 : 22/ 70 objects (100% old), 5 pages, 25 kB, 80 kB waste 1248 : 23/ 78 objects (100% old), 6 pages, 28 kB, 96 kB waste 1360 : 36/ 72 objects ( 97% old), 6 pages, 47 kB, 94 kB waste 1488 : 27/ 66 objects (100% old), 6 pages, 39 kB, 96 kB waste 1632 : 22/ 50 objects (100% old), 5 pages, 35 kB, 80 kB waste 1808 : 18/ 54 objects (100% old), 6 pages, 31 kB, 96 kB waste 2032 : 26/ 72 objects (100% old), 9 pages, 51 kB, 144 kB waste 772 kB (82% old) in 167 large objects (82% old) ``` --- src/gc-debug.c | 175 ++++++++++++++++++++++++++++--------------------- src/options.h | 4 +- 2 files changed, 102 insertions(+), 77 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index bb70daebbf0e6..a7699cc3d0168 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -917,113 +917,138 @@ void jl_gc_debug_init(void) // GC summary stats #ifdef MEMPROFILE -// TODO repair this and possibly merge with `gc_count_pool` -static size_t pool_stats(jl_gc_pool_t *p, size_t *pwaste, size_t *np, - size_t *pnold) + +typedef struct _gc_memprofile_stat_t { + size_t nfree; // for pool only + size_t npgs; // for pool only + size_t nused; + size_t nbytes_used; + size_t nused_old; + size_t nbytes_used_old; +} gc_memprofile_stat_t; + +void gc_stats_all_pool(void) { - jl_taggedvalue_t *halfpages = p->newpages; - size_t osize = p->osize; - size_t nused=0, nfree=0, npgs=0, nold=0; - - if (halfpages != NULL) { - npgs++; - char *v = gc_page_data(halfpages) + GC_PAGE_OFFSET; - char *lim = (char*)halfpages - 1; - int i = 0; - while (v <= lim) { - if (!gc_marked(((jl_taggedvalue_t*)v)->bits.gc)) { - nfree++; + gc_memprofile_stat_t stat[JL_GC_N_POOLS]; + memset(stat, 0, sizeof(stat)); + for (int t_i = 0; t_i < gc_n_threads; t_i++) { + jl_ptls_t ptls2 = gc_all_tls_states[t_i]; + if (ptls2 == NULL) { + continue; + } + jl_gc_page_stack_t *pgstk = &ptls2->gc_tls.page_metadata_allocd; + jl_gc_pagemeta_t *pg = jl_atomic_load_relaxed(&pgstk->bottom); + while (pg != NULL) { + assert(gc_alloc_map_is_set(pg->data)); + int pool_n = pg->pool_n; + jl_gc_pool_t *p = &ptls2->gc_tls.heap.norm_pools[pool_n]; + char *data = pg->data; + // compute the start of the data area in this page + jl_taggedvalue_t *v0 = (jl_taggedvalue_t*)(data + GC_PAGE_OFFSET); + // compute the limit of valid data in this page + char *lim = data + GC_PAGE_SZ - pg->osize; + char *lim_newpages = data + GC_PAGE_SZ; + if (gc_page_data((char*)p->newpages - 1) == data) { + lim_newpages = (char*)p->newpages; } - else { - nused++; - if (((jl_taggedvalue_t*)v)->bits.gc == GC_OLD_MARKED) { - nold++; + char *v = (char*)v0; + gc_memprofile_stat_t *stat_n = &stat[pool_n]; + while (v <= lim) { + uint8_t bits = ((jl_taggedvalue_t*)v)->bits.gc; + if (!gc_marked(bits) || (char*)v >= lim_newpages) { + stat_n->nfree++; + } + else { + if (gc_old(bits)) { + assert(bits == GC_OLD_MARKED); + stat_n->nused_old++; + stat_n->nbytes_used_old += pg->osize; + } + else { + stat_n->nused++; + stat_n->nbytes_used += pg->osize; + } } + v = v + pg->osize; } - v = v + osize; - i++; + stat_n->npgs++; + pg = pg->next; } - // only the first page is allocated on - } - *pwaste = npgs * GC_PAGE_SZ - (nused * p->osize); - *np = npgs; - *pnold = nold; - if (npgs != 0) { - jl_safe_printf("%4d : %7lld/%7lld objects (%3lld%% old), %5lld pages, %5lld kB, %5lld kB waste\n", - p->osize, - (long long)nused, - (long long)(nused + nfree), - (long long)(nused ? (nold * 100) / nused : 0), - (long long)npgs, - (long long)((nused * p->osize) / 1024), - (long long)(*pwaste / 1024)); } - return nused*p->osize; -} - -void gc_stats_all_pool(void) -{ - size_t nb=0, w, tw=0, no=0, tp=0, nold=0, noldbytes=0, np, nol; for (int i = 0; i < JL_GC_N_POOLS; i++) { - for (int t_i = 0; t_i < gc_n_threads; t_i++) { - jl_ptls_t ptls2 = gc_all_tls_states[t_i]; - size_t b = pool_stats(&ptls2->gc_tls.heap.norm_pools[i], &w, &np, &nol); - nb += b; - no += (b / ptls2->gc_tls.heap.norm_pools[i].osize); - tw += w; - tp += np; - nold += nol; - noldbytes += nol * ptls2->gc_tls.heap.norm_pools[i].osize; - } + jl_ptls_t ptls = jl_current_task->ptls; + jl_gc_pool_t *p = &ptls->gc_tls.heap.norm_pools[i]; + gc_memprofile_stat_t *s = &stat[i]; + jl_safe_printf("%4d : %7lld/%7lld objects (%3lld%% old), %5lld pages, %5lld kB, %5lld kB waste\n", + p->osize, + (long long)(s->nused + s->nused_old), + (long long)(s->nused + s->nused_old + s->nfree), + (long long)((s->nused + s->nused_old) ? (s->nused_old * 100) / (s->nused + s->nused_old) : 0), + (long long)s->npgs, + (long long)(((s->nused + s->nused_old) * p->osize) / 1024), + (long long)((GC_PAGE_SZ * s->npgs - s->nused * p->osize) / 1024)); } - jl_safe_printf("%lld objects (%lld%% old), %lld kB (%lld%% old) total allocated, " - "%lld total fragments (%lld%% overhead), in %lld pages\n", - (long long)no, - (long long)(no ? (nold * 100) / no : 0), - (long long)(nb / 1024), - (long long)(nb ? (noldbytes * 100) / nb : 0), - (long long)tw, - (long long)(nb ? (tw * 100) / nb : 0), - (long long)tp); } void gc_stats_big_obj(void) { - size_t nused=0, nbytes=0, nused_old=0, nbytes_old=0; + gc_memprofile_stat_t stat; + memset(&stat, 0, sizeof(stat)); for (int t_i = 0; t_i < gc_n_threads; t_i++) { jl_ptls_t ptls2 = gc_all_tls_states[t_i]; + if (ptls2 == NULL) { + continue; + } bigval_t *v = ptls2->gc_tls.heap.young_generation_of_bigvals; + v = v->next; // skip the sentinel while (v != NULL) { if (gc_marked(v->bits.gc)) { - nused++; - nbytes += v->sz & ~3; + if (gc_old(v->bits.gc)) { + assert(v->bits.gc == GC_OLD_MARKED); + stat.nused_old++; + stat.nbytes_used_old += v->sz; + } + else { + stat.nused++; + stat.nbytes_used += v->sz; + } } v = v->next; } v = oldest_generation_of_bigvals; + v = v->next; // skip the sentinel while (v != NULL) { - if (gc_marked(v->bits.gc)) { - nused_old++; - nbytes_old += v->sz & ~3; - } + assert(v->bits.gc == GC_OLD_MARKED); + stat.nused_old++; + stat.nbytes_used_old += v->sz; v = v->next; } mallocmemory_t *ma = ptls2->gc_tls.heap.mallocarrays; while (ma != NULL) { - if (gc_marked(jl_astaggedvalue(ma->a)->bits.gc)) { - nused++; - nbytes += jl_genericmemory_nbytes((jl_genericmemory_t*)ma->a); + uint8_t bits =jl_astaggedvalue(ma->a)->bits.gc; + if (gc_marked(bits)) { + jl_genericmemory_t *m = (jl_genericmemory_t*)ma->a; + m = (jl_genericmemory_t*)((uintptr_t)m & ~(uintptr_t)1); + size_t sz = jl_genericmemory_nbytes(m); + if (gc_old(bits)) { + assert(bits == GC_OLD_MARKED); + stat.nused_old++; + stat.nbytes_used_old += sz; + } + else { + stat.nused++; + stat.nbytes_used += sz; + } } ma = ma->next; } } - jl_safe_printf("%lld kB (%lld%% old) in %lld large objects (%lld%% old)\n", - (long long)((nbytes + nbytes_old) / 1024), - (long long)(nbytes + nbytes_old ? (nbytes_old * 100) / (nbytes + nbytes_old) : 0), - (long long)(nused + nused_old), - (long long)(nused + nused_old ? (nused_old * 100) / (nused + nused_old) : 0)); + (long long)((stat.nbytes_used + stat.nbytes_used_old) / 1024), + (long long)(stat.nbytes_used + stat.nbytes_used_old ? (stat.nbytes_used_old * 100) / (stat.nbytes_used + stat.nbytes_used_old) : 0), + (long long)(stat.nused + stat.nused_old), + (long long)(stat.nused + stat.nused_old ? (stat.nused_old * 100) / (stat.nused + stat.nused_old) : 0)); } #endif //MEMPROFILE diff --git a/src/options.h b/src/options.h index 58a7868093175..5da9bf2b1a740 100644 --- a/src/options.h +++ b/src/options.h @@ -68,8 +68,8 @@ // GC_FINAL_STATS prints total GC stats at exit // #define GC_FINAL_STATS -// MEMPROFILE prints pool summary statistics after every GC -//#define MEMPROFILE +// MEMPROFILE prints pool and large objects summary statistics after every GC +// #define MEMPROFILE // GC_TIME prints time taken by each phase of GC // #define GC_TIME From 1dee0006c453874a1f8965d55a27befc2620f253 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Fri, 26 Jul 2024 14:30:46 +0100 Subject: [PATCH 076/206] Add BOLT Makefile (#54107) This uses LLVM's BOLT to optimize libLLVM, libjulia-internal and libjulia-codegen. This improves the allinference benchmarks by about 10% largely due to the optimization of libjulia-internal. The example in issue https://github.com/JuliaLang/julia/issues/45395 which stresses LLVM significantly more also sees a ~10% improvement. We see a 20% improvement on ```julia @time for i in 1:100000000 string(i) end ``` When building corecompiler.ji: BOLT gives about a 16% improvement PGO+LTO gives about a 21% improvement PGO+LTO+BOLT gives about a 23% improvement This only requires a single build of LLVM and theoretically none if we change the binary builder script (i.e. we build with relocations and the `-fno-reorder-blocks-and-partition` and then we can use BOLT to get binaries with no relocations and reordered blocks and then ship both binaries?) compared to the 2 in PGO. Also, this theoretically can improve performance of a PGO+LTO build by a couple %. The only reproducible test problem I see is that the BOLT, PGO+LTO and PGO+LTO+BOLT builds all cause `readelf` to emit warnings as part of the `osutils` tests. ``` readelf: Warning: Unrecognised form: 0x22 readelf: Warning: DIE has locviews without loclist readelf: Warning: Unrecognised form: 0x23 readelf: Warning: DIE at offset 0x227399 refers to abbreviation number 14754 which does not exist readelf: Warning: Bogus end-of-siblings marker detected at offset 212aa9 in .debug_info section readelf: Warning: Bogus end-of-siblings marker detected at offset 212ab0 in .debug_info section readelf: Warning: Further warnings about bogus end-of-sibling markers suppressed ``` The unrecognised form warnings seem to be a bug in binutils, https://sourceware.org/bugzilla/show_bug.cgi?id=28981. `DIE at offset` warning I believe was fixed in binutils 2.36, https://sourceware.org/bugzilla/show_bug.cgi?id=26808, but `ld -v` says I have 2.38. I assume these are all benign. I also don't see them on CI here https://buildkite.com/julialang/julia-buildkite/builds/1507#018f00e7-0737-4a42-bcd9-d4061dc8c93e so could just be a local issue. --- Make.inc | 13 +- contrib/bolt/.gitignore | 10 + contrib/bolt/Makefile | 134 +++++++++++++ contrib/bolt/README.md | 17 ++ contrib/pgo-lto-bolt/.gitignore | 14 ++ contrib/pgo-lto-bolt/Makefile | 185 ++++++++++++++++++ contrib/pgo-lto-bolt/README.md | 18 ++ deps/BOLT.mk | 118 +++++++++++ deps/BOLT.version | 11 ++ deps/Makefile | 1 + .../md5 | 1 + .../sha512 | 1 + deps/llvm.mk | 5 +- src/Makefile | 4 +- 14 files changed, 525 insertions(+), 7 deletions(-) create mode 100644 contrib/bolt/.gitignore create mode 100644 contrib/bolt/Makefile create mode 100644 contrib/bolt/README.md create mode 100644 contrib/pgo-lto-bolt/.gitignore create mode 100644 contrib/pgo-lto-bolt/Makefile create mode 100644 contrib/pgo-lto-bolt/README.md create mode 100644 deps/BOLT.mk create mode 100644 deps/BOLT.version create mode 100644 deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/md5 create mode 100644 deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/sha512 diff --git a/Make.inc b/Make.inc index d9a131b4d8a98..0da638cfab52e 100644 --- a/Make.inc +++ b/Make.inc @@ -516,6 +516,11 @@ SHIPFLAGS_COMMON := -O3 SHIPFLAGS_CLANG := $(SHIPFLAGS_COMMON) -g SHIPFLAGS_GCC := $(SHIPFLAGS_COMMON) -ggdb2 -falign-functions +BOLT_LDFLAGS := + +BOLT_CFLAGS_GCC := +BOLT_CFLAGS_CLANG := + ifeq ($(OS), Darwin) JCPPFLAGS_CLANG += -D_LARGEFILE_SOURCE -D_DARWIN_USE_64_BIT_INODE=1 endif @@ -532,7 +537,8 @@ JCFLAGS := $(JCFLAGS_GCC) JCPPFLAGS := $(JCPPFLAGS_GCC) JCXXFLAGS := $(JCXXFLAGS_GCC) DEBUGFLAGS := $(DEBUGFLAGS_GCC) -SHIPFLAGS := $(SHIPFLAGS_GCC) +SHIPFLAGS := $(SHIPFLAGS_GCC) $(BOLT_CFLAGS_GCC) +BOLT_CFLAGS := $(BOLT_CFLAGS_GCC) endif ifeq ($(USECLANG),1) @@ -542,7 +548,8 @@ JCFLAGS := $(JCFLAGS_CLANG) JCPPFLAGS := $(JCPPFLAGS_CLANG) JCXXFLAGS := $(JCXXFLAGS_CLANG) DEBUGFLAGS := $(DEBUGFLAGS_CLANG) -SHIPFLAGS := $(SHIPFLAGS_CLANG) +SHIPFLAGS := $(SHIPFLAGS_CLANG) $(BOLT_CFLAGS_CLANG) +BOLT_CFLAGS := $(BOLT_CFLAGS_CLANG) ifeq ($(OS), Darwin) CC += -mmacosx-version-min=$(MACOSX_VERSION_MIN) @@ -1295,7 +1302,7 @@ CSL_NEXT_GLIBCXX_VERSION=GLIBCXX_3\.4\.33|GLIBCXX_3\.5\.|GLIBCXX_4\. # Note: we explicitly _do not_ define `CSL` here, since it requires some more # advanced techniques to decide whether it should be installed from a BB source # or not. See `deps/csl.mk` for more detail. -BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT +BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT BOLT define SET_BB_DEFAULT # First, check to see if BB is disabled on a global setting ifeq ($$(USE_BINARYBUILDER),0) diff --git a/contrib/bolt/.gitignore b/contrib/bolt/.gitignore new file mode 100644 index 0000000000000..921d429130268 --- /dev/null +++ b/contrib/bolt/.gitignore @@ -0,0 +1,10 @@ +profiles-bolt* +optimized.build +toolchain + +bolt +bolt_instrument +merge_data +copy_originals +stage0 +stage1 diff --git a/contrib/bolt/Makefile b/contrib/bolt/Makefile new file mode 100644 index 0000000000000..2e911fcbcdc68 --- /dev/null +++ b/contrib/bolt/Makefile @@ -0,0 +1,134 @@ +.PHONY: clean clean_profiles restore_originals + +# Settings taken from https://github.com/rust-lang/rust/blob/master/src/tools/opt-dist/src/bolt.rs +BOLT_ARGS := +# Reorder basic blocks within functions +BOLT_ARGS += -reorder-blocks=ext-tsp +# Reorder functions within the binary +BOLT_ARGS += -reorder-functions=cdsort +# Split function code into hot and code regions +BOLT_ARGS += -split-functions +# Split as many basic blocks as possible +BOLT_ARGS += -split-all-cold +# Move jump tables to a separate section +BOLT_ARGS += -jump-tables=move +# Use regular size pages for code alignment +BOLT_ARGS += -no-huge-pages +# Fold functions with identical code +BOLT_ARGS += -icf=1 +# Split using best available strategy (three-way splitting, Cache-Directed Sort) +# Disabled for libjulia-internal till https://github.com/llvm/llvm-project/issues/89508 is fixed +# BOLT_ARGS += -split-strategy=cdsplit +# Update DWARF debug info in the final binary +BOLT_ARGS += -update-debug-sections +# Print optimization statistics +BOLT_ARGS += -dyno-stats +# BOLT doesn't fully support computed gotos, https://github.com/llvm/llvm-project/issues/89117 +# Use escaped regex as the name BOLT recognises is often a bit different, e.g. apply_cl/1(*2) +# This doesn't actually seem to do anything, the actual mitigation is not using --use-old-text +# which we do in the bolt target +BOLT_ARGS += -skip-funcs=.\*apply_cl.\* + +# -fno-reorder-blocks-and-partition is needed on gcc >= 8. +BOLT_FLAGS := $\ + "BOLT_CFLAGS_GCC+=-fno-reorder-blocks-and-partition" $\ + "BOLT_LDFLAGS=-Wl,--emit-relocs" + +STAGE0_BUILD:=$(CURDIR)/toolchain +STAGE1_BUILD:=$(CURDIR)/optimized.build + +STAGE0_BINARIES:=$(STAGE0_BUILD)/usr/bin/ + +PROFILE_DIR:=$(CURDIR)/profiles-bolt +JULIA_ROOT:=$(CURDIR)/../.. + +LLVM_BOLT:=$(STAGE0_BINARIES)llvm-bolt +LLVM_MERGEFDATA:=$(STAGE0_BINARIES)merge-fdata + +# If you add new files to optimize, you need to add BOLT_LDFLAGS and BOLT_CFLAGS to the build of your new file. +SYMLINKS_TO_OPTIMIZE := libLLVM.so libjulia-internal.so libjulia-codegen.so +FILES_TO_OPTIMIZE := $(shell for file in $(SYMLINKS_TO_OPTIMIZE); do readlink $(STAGE1_BUILD)/usr/lib/$$file; done) + +AFTER_INSTRUMENT_MESSAGE:='Run `make finish_stage1` to finish off the build. $\ + You can now optionally collect more profiling data by running Julia with an appropriate workload, $\ + if you wish, run `make clean_profiles` before doing so to remove any profiling data generated by `make finish_stage1`. $\ + You should end up with some data in $(PROFILE_DIR). Afterwards run `make merge_data && make bolt`. $\ + +$(STAGE0_BUILD) $(STAGE1_BUILD): + $(MAKE) -C $(JULIA_ROOT) O=$@ configure + +stage0: | $(STAGE0_BUILD) + $(MAKE) -C $(STAGE0_BUILD)/deps install-BOLT && \ + touch $@ + +# Build with our custom flags, binary builder doesn't use them so we need to build LLVM for now. +# We manually skip package image creation so that we can profile it +$(STAGE1_BUILD): stage0 +stage1: export USE_BINARYBUILDER_LLVM=0 +stage1: | $(STAGE1_BUILD) + $(MAKE) -C $(STAGE1_BUILD) $(BOLT_FLAGS) julia-src-release julia-symlink julia-libccalltest \ + julia-libccalllazyfoo julia-libccalllazybar julia-libllvmcalltest && \ + touch $@ + +copy_originals: stage1 + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE1_BUILD)/usr/lib/$$file; \ + cp $$abs_file "$$abs_file.original"; \ + done && \ + touch $@ + +# I don't think there's any particular reason to have -no-huge-pages here, perhaps slightly more accurate profile data +# as the final build uses -no-huge-pages +bolt_instrument: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE1_BUILD)/usr/lib/$$file; \ + $(LLVM_BOLT) "$$abs_file.original" -o $$abs_file --instrument --instrumentation-file-append-pid --instrumentation-file="$(PROFILE_DIR)/$$file-prof" -no-huge-pages; \ + mkdir -p $$(dirname "$(PROFILE_DIR)/$$file-prof"); \ + printf "\n"; \ + done && \ + touch $@ + @echo $(AFTER_INSTRUMENT_MESSAGE) + +# We don't want to rebuild julia-src as then we lose the bolt instrumentation +# So we have to manually build the sysimage and package image +finish_stage1: stage1 + $(MAKE) -C $(STAGE1_BUILD) julia-base-cache && \ + $(MAKE) -C $(STAGE1_BUILD) -f sysimage.mk sysimg-release && \ + $(MAKE) -C $(STAGE1_BUILD) -f pkgimage.mk release + +merge_data: bolt_instrument + for file in $(FILES_TO_OPTIMIZE); do \ + profiles=$(PROFILE_DIR)/$$file-prof.*.fdata; \ + $(LLVM_MERGEFDATA) $$profiles > "$(PROFILE_DIR)/$$file-prof.merged.fdata"; \ + done && \ + touch $@ + +# The --use-old-text saves about 16 MiB of libLLVM.so size. +# However, the rust folk found it succeeds very non-deterministically for them. +# It tries to reuse old text segments to reduce binary size +# BOLT doesn't fully support computed gotos https://github.com/llvm/llvm-project/issues/89117, so we cannot use --use-old-text on libjulia-internal +# That flag saves less than 1 MiB for libjulia-internal so oh well. +bolt: merge_data + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE1_BUILD)/usr/lib/$$file; \ + $(LLVM_BOLT) "$$abs_file.original" -data "$(PROFILE_DIR)/$$file-prof.merged.fdata" -o $$abs_file $(BOLT_ARGS) $$(if [ "$$file" != $(shell readlink $(STAGE1_BUILD)/usr/lib/libjulia-internal.so) ]; then echo "--use-old-text -split-strategy=cdsplit"; fi); \ + done && \ + touch $@ + +clean_profiles: + rm -rf $(PROFILE_DIR) + +clean: + rm -f stage0 stage1 bolt copy_originals merge_data bolt_instrument + +restore_originals: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE1_BUILD)/usr/lib/$$file; \ + cp -P "$$abs_file.original" $$abs_file; \ + done + +delete_originals: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE1_BUILD)/usr/lib/$$file; \ + rm "$$abs_file.original"; \ + done diff --git a/contrib/bolt/README.md b/contrib/bolt/README.md new file mode 100644 index 0000000000000..8680939ef6276 --- /dev/null +++ b/contrib/bolt/README.md @@ -0,0 +1,17 @@ +BOLT only works on x86_64 and arch64 on Linux. + +DO NOT STRIP THE RESULTING .so FILES, https://github.com/llvm/llvm-project/issues/56738. +If you really need to, try adding `-use-gnu-stack` to `BOLT_ARGS`. + +To build a BOLT-optimized version of Julia run the following commands (`cd` into this directory first) +```bash +make stage1 +make copy_originals +make bolt_instrument +make finish_stage1 +make merge_data +make bolt +``` +After these commands finish, the optimized version of Julia will be built in the `optimized.build` directory. + +This doesn't align the code to support huge pages as it doesn't seem that we do that currently, this decreases the size of the .so files by 2-4mb. diff --git a/contrib/pgo-lto-bolt/.gitignore b/contrib/pgo-lto-bolt/.gitignore new file mode 100644 index 0000000000000..1b29279acc0da --- /dev/null +++ b/contrib/pgo-lto-bolt/.gitignore @@ -0,0 +1,14 @@ +stage0* +stage1* +stage2* +bolt +bolt_instrument +merge_data +copy_originals + +profiles +profiles-bolt + +toolchain +pgo-instrumented.build +optimized.build diff --git a/contrib/pgo-lto-bolt/Makefile b/contrib/pgo-lto-bolt/Makefile new file mode 100644 index 0000000000000..6787b3bc4e919 --- /dev/null +++ b/contrib/pgo-lto-bolt/Makefile @@ -0,0 +1,185 @@ +.PHONY: clean clean_profiles restore_originals + +# See the makefiles in contrib/bolt and contrib/pgo-lto for more information. + +# Settings taken from https://github.com/rust-lang/rust/blob/master/src/tools/opt-dist/src/bolt.rs +BOLT_ARGS := +# Reorder basic blocks within functions +BOLT_ARGS += -reorder-blocks=ext-tsp +# Reorder functions within the binary +BOLT_ARGS += -reorder-functions=cdsort +# Split function code into hot and code regions +BOLT_ARGS += -split-functions +# Split as many basic blocks as possible +BOLT_ARGS += -split-all-cold +# Move jump tables to a separate section +BOLT_ARGS += -jump-tables=move +# Use regular size pages for code alignment +BOLT_ARGS += -no-huge-pages +# Fold functions with identical code +BOLT_ARGS += -icf=1 +# Split using best available strategy (three-way splitting, Cache-Directed Sort) +# Disabled for libjulia-internal till https://github.com/llvm/llvm-project/issues/89508 is fixed +# BOLT_ARGS += -split-strategy=cdsplit +# Update DWARF debug info in the final binary +BOLT_ARGS += -update-debug-sections +# Print optimization statistics +BOLT_ARGS += -dyno-stats +# BOLT doesn't fully support computed gotos, https://github.com/llvm/llvm-project/issues/89117 +# Use escaped regex as the name BOLT recognises is often a bit different, e.g. apply_cl/1(*2) +# This doesn't actually seem to do anything, the actual mitigation is not using --use-old-text +# which we do in the bolt target +BOLT_ARGS += -skip-funcs=.\*apply_cl.\* + +# -fno-reorder-blocks-and-partition is needed on gcc >= 8. +BOLT_FLAGS := $\ + "BOLT_CFLAGS_GCC+=-fno-reorder-blocks-and-partition" $\ + "BOLT_LDFLAGS=-Wl,--emit-relocs" + +STAGE0_BUILD:=$(CURDIR)/toolchain +STAGE1_BUILD:=$(CURDIR)/pgo-instrumented.build +STAGE2_BUILD:=$(CURDIR)/optimized.build + +STAGE0_BINARIES:=$(STAGE0_BUILD)/usr/bin/ +STAGE0_TOOLS:=$(STAGE0_BUILD)/usr/tools/ + +BOLT_PROFILE_DIR:=$(CURDIR)/profiles-bolt +PGO_PROFILE_DIR:=$(CURDIR)/profiles +PGO_PROFILE_FILE:=$(PGO_PROFILE_DIR)/merged.prof +PGO_PROFRAW_FILES:=$(wildcard $(PGO_PROFILE_DIR)/*.profraw) +JULIA_ROOT:=$(CURDIR)/../.. + +LLVM_BOLT:=$(STAGE0_BINARIES)llvm-bolt +LLVM_MERGEFDATA:=$(STAGE0_BINARIES)merge-fdata +LLVM_CXXFILT:=$(STAGE0_TOOLS)llvm-cxxfilt +LLVM_PROFDATA:=$(STAGE0_TOOLS)llvm-profdata +LLVM_OBJCOPY:=$(STAGE0_TOOLS)llvm-objcopy + +# If you add new files to optimize, you need to add BOLT_LDFLAGS and BOLT_CFLAGS to the build of your new file. +SYMLINKS_TO_OPTIMIZE := libLLVM.so libjulia-internal.so libjulia-codegen.so +FILES_TO_OPTIMIZE := $(shell for file in $(SYMLINKS_TO_OPTIMIZE); do readlink $(STAGE1_BUILD)/usr/lib/$$file; done) + +AFTER_INSTRUMENT_MESSAGE:='Run `make finish_stage2` to finish off the build. $\ + You can now optionally collect more profiling data by running Julia with an appropriate workload, $\ + if you wish, run `make clean_profiles` before doing so to remove any profiling data generated by `make finish_stage2`. $\ + You should end up with some data in $(BOLT_PROFILE_DIR). Afterwards run `make merge_data && make bolt`. $\ + +# When building a single libLLVM.so we need to increase -vp-counters-per-site +# significantly +COUNTERS_PER_SITE:=6 +# Note: profile counters are not atomic by default, https://discourse.llvm.org/t/profile-guided-optimization-pgo-related-questions-and-suggestions/75232/5 + +AFTER_STAGE1_MESSAGE:='You can now optionally collect more profiling data for use in PGO by running Julia $\ + with an appropriate workload. If you wish, run `make clean_profiles` before doing so to remove any profiling data $\ + generated by building Julia. You should end up with about 15MB of data in $(PGO_PROFILE_DIR). $\ + Note that running extensive scripts may result in counter overflows, which can be detected by running $\ + `make top`. Afterwards run `make stage2`.' + +TOOLCHAIN_FLAGS = $\ + "CC=$(STAGE0_TOOLS)clang" $\ + "CXX=$(STAGE0_TOOLS)clang++" $\ + "LD=$(STAGE0_TOOLS)ld.lld" $\ + "AR=$(STAGE0_TOOLS)llvm-ar" $\ + "RANLIB=$(STAGE0_TOOLS)llvm-ranlib" $\ + "CFLAGS+=$(PGO_CFLAGS)" $\ + "CXXFLAGS+=$(PGO_CXXFLAGS)" $\ + "LDFLAGS+=$(PGO_LDFLAGS)" + +$(STAGE0_BUILD) $(STAGE1_BUILD) $(STAGE2_BUILD): + $(MAKE) -C $(JULIA_ROOT) O=$@ configure + +stage0: export USE_BINARYBUILDER_LLVM=1 +stage0: | $(STAGE0_BUILD) + # Turn [cd]tors into init/fini_array sections in libclang_rt, since lld + # doesn't do that, and otherwise the profile constructor is not executed + $(MAKE) -C $(STAGE0_BUILD)/deps install-clang install-llvm install-lld install-llvm-tools install-BOLT && \ + find $< -name 'libclang_rt.profile-*.a' -exec $(LLVM_OBJCOPY) --rename-section .ctors=.init_array --rename-section .dtors=.fini_array {} + && \ + touch $@ + +$(STAGE1_BUILD): stage0 +stage1: PGO_CFLAGS:=-fprofile-generate=$(PGO_PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) +stage1: PGO_CXXFLAGS:=-fprofile-generate=$(PGO_PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) +stage1: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-generate=$(PGO_PROFILE_DIR) +stage1: export USE_BINARYBUILDER_LLVM=0 +stage1: | $(STAGE1_BUILD) + $(MAKE) -C $(STAGE1_BUILD) $(TOOLCHAIN_FLAGS) && touch $@ + @echo $(AFTER_STAGE1_MESSAGE) + +stage2: PGO_CFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) +stage2: PGO_CXXFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) +stage2: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-use=$(PGO_PROFILE_FILE) -Wl,--icf=safe +stage2: export USE_BINARYBUILDER_LLVM=0 +stage2: $(PGO_PROFILE_FILE) | $(STAGE2_BUILD) + $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) $(BOLT_FLAGS) julia-src-release julia-symlink julia-libccalltest \ + julia-libccalllazyfoo julia-libccalllazybar julia-libllvmcalltest && \ + touch $@ + +copy_originals: stage2 + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE2_BUILD)/usr/lib/$$file; \ + cp $$abs_file "$$abs_file.original"; \ + done && \ + touch $@ + +# I don't think there's any particular reason to have -no-huge-pages here, perhaps slightly more accurate profile data +# as the final build uses -no-huge-pages +bolt_instrument: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE2_BUILD)/usr/lib/$$file; \ + $(LLVM_BOLT) "$$abs_file.original" -o $$abs_file --instrument --instrumentation-file-append-pid --instrumentation-file="$(BOLT_PROFILE_DIR)/$$file-prof" -no-huge-pages; \ + mkdir -p $$(dirname "$(BOLT_PROFILE_DIR)/$$file-prof"); \ + printf "\n"; \ + done && \ + touch $@ + @echo $(AFTER_INSTRUMENT_MESSAGE) + +# We don't want to rebuild julia-src as then we lose the bolt instrumentation +# So we have to manually build the sysimage and package image +finish_stage2: stage2 + $(MAKE) -C $(STAGE2_BUILD) julia-base-cache && \ + $(MAKE) -C $(STAGE2_BUILD) -f sysimage.mk sysimg-release && \ + $(MAKE) -C $(STAGE2_BUILD) -f pkgimage.mk release + +merge_data: bolt_instrument + for file in $(FILES_TO_OPTIMIZE); do \ + profiles=$(BOLT_PROFILE_DIR)/$$file-prof.*.fdata; \ + $(LLVM_MERGEFDATA) $$profiles > "$(BOLT_PROFILE_DIR)/$$file-prof.merged.fdata"; \ + done && \ + touch $@ + +# The --use-old-text saves about 16 MiB of libLLVM.so size. +# However, the rust folk found it succeeds very non-deterministically for them. +# It tries to reuse old text segments to reduce binary size +# BOLT doesn't fully support computed gotos https://github.com/llvm/llvm-project/issues/89117, so we cannot use --use-old-text on libjulia-internal +# That flag saves less than 1 MiB for libjulia-internal so oh well. +bolt: merge_data + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE2_BUILD)/usr/lib/$$file; \ + $(LLVM_BOLT) "$$abs_file.original" -data "$(BOLT_PROFILE_DIR)/$$file-prof.merged.fdata" -o $$abs_file $(BOLT_ARGS) $$(if [ "$$file" != $(shell readlink $(STAGE2_BUILD)/usr/lib/libjulia-internal.so) ]; then echo "--use-old-text -split-strategy=cdsplit"; fi); \ + done && \ + touch $@ + +clean_profiles: + rm -rf $(PGO_PROFILE_DIR) $(BOLT_PROFILE_DIR) + +clean: + rm -f stage0 stage1 stage2 $(PGO_PROFILE_FILE) bolt copy_originals merge_data bolt_instrument + +restore_originals: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE2_BUILD)/usr/lib/$$file; \ + cp -P "$$abs_file.original" $$abs_file; \ + done + +delete_originals: copy_originals + for file in $(FILES_TO_OPTIMIZE); do \ + abs_file=$(STAGE2_BUILD)/usr/lib/$$file; \ + rm "$$abs_file.original"; \ + done + +$(PGO_PROFILE_FILE): stage1 $(PGO_PROFRAW_FILES) + $(LLVM_PROFDATA) merge -output=$@ $(PGO_PROFRAW_FILES) + +# show top 50 functions +top: $(PGO_PROFILE_FILE) + $(LLVM_PROFDATA) show --topn=50 $< | $(LLVM_CXXFILT) diff --git a/contrib/pgo-lto-bolt/README.md b/contrib/pgo-lto-bolt/README.md new file mode 100644 index 0000000000000..ab574907c292f --- /dev/null +++ b/contrib/pgo-lto-bolt/README.md @@ -0,0 +1,18 @@ +BOLT only works on x86_64 and arch64 on Linux. + +DO NOT STRIP THE RESULTING .so FILES, https://github.com/llvm/llvm-project/issues/56738. +If you really need to, try adding `-use-gnu-stack` to `BOLT_ARGS`. + +To build a PGO+LTO+BOLT version of Julia run the following commands (`cd` into this directory first) +```bash +make stage1 +make stage2 +make copy_originals +make bolt_instrument +make finish_stage2 +make merge_data +make bolt +``` +After these commands finish, the optimized version of Julia will be built in the `optimized.build` directory. + +This doesn't align the code to support huge pages as it doesn't seem that we do that currently, this decreases the size of the .so files by 2-4mb. diff --git a/deps/BOLT.mk b/deps/BOLT.mk new file mode 100644 index 0000000000000..70c5d03c762ec --- /dev/null +++ b/deps/BOLT.mk @@ -0,0 +1,118 @@ +## BOLT ## +include $(SRCDIR)/BOLT.version + +ifneq ($(USE_BINARYBUILDER_BOLT), 1) +BOLT_GIT_URL:=https://github.com/llvm/llvm-project.git +BOLT_TAR_URL=https://api.github.com/repos/llvm/llvm-project/tarball/$1 +$(eval $(call git-external,BOLT,BOLT,CMakeLists.txt,,$(SRCCACHE))) + +BOLT_BUILDDIR := $(BUILDDIR)/$(BOLT_SRC_DIR)/build + +LLVM_ENABLE_PROJECTS := bolt + +LLVM_CFLAGS := +LLVM_CXXFLAGS := +LLVM_CPPFLAGS := +LLVM_LDFLAGS := +LLVM_CMAKE := + +LLVM_CMAKE += -DLLVM_ENABLE_PROJECTS="$(LLVM_ENABLE_PROJECTS)" + +# Otherwise LLVM will translate \\ to / on mingw +LLVM_CMAKE += -DLLVM_WINDOWS_PREFER_FORWARD_SLASH=False + +# Allow adding LLVM specific flags +LLVM_CFLAGS += $(CFLAGS) +LLVM_CXXFLAGS += $(CXXFLAGS) +LLVM_CXXFLAGS += $(LLVM_CXXFLAGS) +LLVM_CPPFLAGS += $(CPPFLAGS) +LLVM_LDFLAGS += $(LDFLAGS) +LLVM_LDFLAGS += $(LLVM_LDFLAGS) +LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING=host -DCMAKE_BUILD_TYPE=Release +LLVM_CMAKE += -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_HOST_TRIPLE="$(or $(XC_HOST),$(BUILD_MACHINE))" +LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=ON -DZLIB_LIBRARY="$(build_prefix)/lib" + +LLVM_CMAKE += -DLLVM_BINDINGS_LIST="" -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_INCLUDE_DOCS=Off -DLLVM_ENABLE_TERMINFO=Off -DHAVE_LIBEDIT=Off + +ifeq ($(OS), WINNT) +LLVM_CPPFLAGS += -D__USING_SJLJ_EXCEPTIONS__ -D__CRT__NO_INLINE +endif # OS == WINNT +ifneq ($(HOSTCC),$(CC)) +LLVM_CMAKE += -DCROSS_TOOLCHAIN_FLAGS_NATIVE="-DCMAKE_C_COMPILER=$$(which $(HOSTCC));-DCMAKE_CXX_COMPILER=$$(which $(HOSTCXX))" + +# Defaults to off when crosscompiling, starting from LLVM 18 +LLVM_CMAKE += -DBOLT_ENABLE_RUNTIME=ON +endif +ifeq ($(OS), emscripten) +LLVM_CMAKE += -DCMAKE_TOOLCHAIN_FILE=$(EMSCRIPTEN)/cmake/Modules/Platform/Emscripten.cmake -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_THREADS=OFF -DLLVM_BUILD_UTILS=OFF +endif # OS == emscripten + +ifneq (,$(filter $(ARCH), powerpc64le ppc64le)) +ifeq (${USECLANG},0) +LLVM_CXXFLAGS += -mminimal-toc +endif +endif + +ifeq ($(fPIC),) +LLVM_CMAKE += -DLLVM_ENABLE_PIC=OFF +endif + +LLVM_CMAKE += -DCMAKE_C_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CFLAGS)" \ + -DCMAKE_CXX_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CXXFLAGS)" +ifeq ($(OS),Darwin) +# Explicitly use the default for -mmacosx-version-min=10.9 and later +LLVM_CMAKE += -DLLVM_ENABLE_LIBCXX=ON +endif + +LLVM_CMAKE += -DCMAKE_EXE_LINKER_FLAGS="$(LLVM_LDFLAGS)" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(LLVM_LDFLAGS)" + +ifeq ($(USE_SYSTEM_ZLIB), 0) +$(BOLT_BUILDDIR)/build-configured: | $(build_prefix)/manifest/zlib +endif + +$(BOLT_BUILDDIR)/build-configured: $(SRCCACHE)/$(BOLT_SRC_DIR)/source-extracted + mkdir -p $(dir $@) + cd $(dir $@) && \ + $(CMAKE) $(SRCCACHE)/$(BOLT_SRC_DIR)/llvm $(CMAKE_GENERATOR_COMMAND) $(CMAKE_COMMON) $(LLVM_CMAKE) \ + || { echo '*** To install a newer version of cmake, run contrib/download_cmake.sh ***' && false; } + echo 1 > $@ + +$(BOLT_BUILDDIR)/build-compiled: $(BOLT_BUILDDIR)/build-configured + cd $(BOLT_BUILDDIR) && \ + $(if $(filter $(CMAKE_GENERATOR),make), \ + $(MAKE), \ + $(CMAKE) --build . --target bolt) + echo 1 > $@ + +$(BOLT_BUILDDIR)/build-checked: $(BOLT_BUILDDIR)/build-compiled +ifeq ($(OS),$(BUILD_OS)) + cd $(BOLT_BUILDDIR) && \ + $(CMAKE) --build . --target check-bolt +endif + echo 1 > $@ + +BOLT_INSTALL = \ + cd $1 && mkdir -p $2$$(build_depsbindir) && \ + $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P tools/bolt/cmake_install.cmake + +$(eval $(call staged-install, \ + bolt,$$(BOLT_SRC_DIR)/build, \ + BOLT_INSTALL,,,)) + +clean-bolt: + -rm -f $(BOLT_BUILDDIR)/build-configured $(BOLT_BUILDDIR)/build-compiled + -$(MAKE) -C $(BOLT_BUILDDIR) clean + +get-bolt: $(BOLT_SRC_FILE) +extract-bolt: $(SRCCACHE)/$(BOLT_SRC_DIR)/source-extracted +configure-bolt: $(BOLT_BUILDDIR)/build-configured +compile-bolt: $(BOLT_BUILDDIR)/build-compiled +fastcheck-bolt: #none +check-bolt: $(BOLT_BUILDDIR)/build-checked + +else # USE_BINARYBUILDER_BOLT + +$(eval $(call bb-install,BOLT,BOLT,false,true)) + +endif # USE_BINARYBUILDER_BOLT diff --git a/deps/BOLT.version b/deps/BOLT.version new file mode 100644 index 0000000000000..6a785041e163f --- /dev/null +++ b/deps/BOLT.version @@ -0,0 +1,11 @@ +# -*- makefile -*- + +BOLT_VER := 18.1.4 +BOLT_JLL_VER := 18.1.4+0 + +## jll artifact +BOLT_JLL_NAME := BOLT + +## source build +BOLT_BRANCH=llvmorg-$(BOLT_VER) +BOLT_SHA1=e6c3289804a67ea0bb6a86fadbe454dd93b8d855 diff --git a/deps/Makefile b/deps/Makefile index 83493981a40b4..2f9050f448d67 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -231,6 +231,7 @@ distcleanall: $(addprefix distclean-, $(DEP_LIBS_ALL)) rm -rf $(build_prefix) getall: $(addprefix get-, $(DEP_LIBS_ALL)) +include $(SRCDIR)/BOLT.mk include $(SRCDIR)/csl.mk include $(SRCDIR)/sanitizers.mk include $(SRCDIR)/ittapi.mk diff --git a/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/md5 b/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/md5 new file mode 100644 index 0000000000000..62e63ff3174d6 --- /dev/null +++ b/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/md5 @@ -0,0 +1 @@ +c12540d5889cef05bc87183a4ce5a54c diff --git a/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/sha512 b/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/sha512 new file mode 100644 index 0000000000000..0635e180ac9a5 --- /dev/null +++ b/deps/checksums/BOLT.v18.1.4+0.x86_64-linux-gnu-cxx11.tar.gz/sha512 @@ -0,0 +1 @@ +61cc7cc42b925f37502eed0d31eafadbfdc24a9ebc892c9b8d96a27b004cbccf2e5da7face5c8d9c9db57fac1b5cf662d890a67337436c5d4aa3373256638ab1 diff --git a/deps/llvm.mk b/deps/llvm.mk index 7ead1dab1d925..5e73c18f53289 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -86,10 +86,11 @@ endif LLVM_CMAKE += -DLLVM_WINDOWS_PREFER_FORWARD_SLASH=False # Allow adding LLVM specific flags -LLVM_CFLAGS += $(CFLAGS) -LLVM_CXXFLAGS += $(CXXFLAGS) +LLVM_CFLAGS += $(CFLAGS) $(BOLT_CFLAGS) +LLVM_CXXFLAGS += $(CXXFLAGS) $(BOLT_CFLAGS) LLVM_CPPFLAGS += $(CPPFLAGS) LLVM_LDFLAGS += $(LDFLAGS) +LLVM_LDFLAGS += $(BOLT_LDFLAGS) LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING="$(LLVM_TARGETS)" -DCMAKE_BUILD_TYPE="$(LLVM_CMAKE_BUILDTYPE)" LLVM_CMAKE += -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="$(LLVM_EXPERIMENTAL_TARGETS)" LLVM_CMAKE += -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_HOST_TRIPLE="$(or $(XC_HOST),$(BUILD_MACHINE))" diff --git a/src/Makefile b/src/Makefile index e29c56a6cba9c..4da44a8cc8d81 100644 --- a/src/Makefile +++ b/src/Makefile @@ -391,7 +391,7 @@ $(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in $(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(OBJS) $(BUILDDIR)/flisp/libflisp.a $(BUILDDIR)/support/libsupport.a $(LIBUV) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(SHIPFLAGS) $(OBJS) $(RPATH_LIB) -o $@ \ - $(JLDFLAGS) $(JLIBLDFLAGS) $(RT_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-internal.$(JL_MAJOR_SHLIB_EXT))) + $(JLDFLAGS) $(BOLT_LDFLAGS) $(JLIBLDFLAGS) $(RT_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-internal.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-internal.$(SHLIB_EXT) $@ $(DSYMUTIL) $@ @@ -419,7 +419,7 @@ libjulia-internal-debug libjulia-internal-release: $(PUBLIC_HEADER_TARGETS) $(build_shlibdir)/libjulia-codegen.$(JL_MAJOR_MINOR_SHLIB_EXT): $(BUILDDIR)/julia.expmap $(CODEGEN_OBJS) $(BUILDDIR)/support/libsupport.a $(build_shlibdir)/libjulia-internal.$(JL_MAJOR_MINOR_SHLIB_EXT) @$(call PRINT_LINK, $(CXXLD) $(call IMPLIB_FLAGS,$@) $(JCXXFLAGS) $(JL_CXXFLAGS) $(CXXLDFLAGS) $(SHIPFLAGS) $(CODEGEN_OBJS) $(RPATH_LIB) -o $@ \ - $(JLDFLAGS) $(JLIBLDFLAGS) $(CG_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-codegen.$(JL_MAJOR_SHLIB_EXT))) + $(JLDFLAGS) $(BOLT_LDFLAGS) $(JLIBLDFLAGS) $(CG_RELEASE_LIBS) $(call SONAME_FLAGS,libjulia-codegen.$(JL_MAJOR_SHLIB_EXT))) @$(INSTALL_NAME_CMD)libjulia-codegen.$(SHLIB_EXT) $@ $(DSYMUTIL) $@ From c49f4aaee97883bd8fa65ab133870a6fb698ad17 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Fri, 26 Jul 2024 11:57:52 -0400 Subject: [PATCH 077/206] == docs: strengthen link between hashing and equality (#55135) ref #55134. --- base/operators.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index 4a9daf21c4be5..dc3c01e5645cc 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -111,9 +111,10 @@ Use [`isequal`](@ref) or [`===`](@ref) to always get a `Bool` result. New numeric types should implement this function for two arguments of the new type, and handle comparison to other types via promotion rules where possible. -[`isequal`](@ref) falls back to `==`, so new methods of `==` will be used by the -[`Dict`](@ref) type to compare keys. If your type will be used as a dictionary key, it -should therefore also implement [`hash`](@ref). +Equality and hashing are intimately related; two values that are considered [`isequal`](@ref) **must** +have the same [`hash`](@ref) and by default `isequal` falls back to `==`. If a type customizes the behavior of `==` and/or [`isequal`](@ref), +then [`hash`](@ref) must be similarly implemented to ensure `isequal` and `hash` agree. `Set`s, `Dict`s, and many other internal +implementations assume that this invariant holds. If some type defines `==`, [`isequal`](@ref), and [`isless`](@ref) then it should also implement [`<`](@ref) to ensure consistency of comparisons. From cdd599c320db051005d9581fc09ba6da0693c7f5 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Fri, 26 Jul 2024 18:00:14 -0300 Subject: [PATCH 078/206] split a lock currently used for symtab + GC pages + perm alloc (#55257) Seems fairly odd to have a single lock protecting the symbol table, GC pages and the permanent allocator -- three parts of the codebase which have little interconnection. Let's create a lock for each. --- src/gc-pages.c | 12 +++++++----- src/gc.c | 3 ++- src/gc.h | 2 ++ src/init.c | 3 +++ src/julia_internal.h | 4 +--- src/symbol.c | 9 +++++---- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/gc-pages.c b/src/gc-pages.c index 698cf84c3cfb6..971dbe92d7fac 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -9,6 +9,8 @@ extern "C" { #endif +uv_mutex_t gc_pages_lock; + JL_DLLEXPORT uint64_t jl_get_pg_size(void) { return GC_PAGE_SZ; @@ -67,7 +69,7 @@ char *jl_gc_try_alloc_pages_(int pg_cnt) JL_NOTSAFEPOINT // more chunks (or other allocations). The final page count is recorded // and will be used as the starting count next time. If the page count is // smaller `MIN_BLOCK_PG_ALLOC` a `jl_memory_exception` is thrown. -// Assumes `gc_perm_lock` is acquired, the lock is released before the +// Assumes `gc_pages_lock` is acquired, the lock is released before the // exception is thrown. char *jl_gc_try_alloc_pages(void) JL_NOTSAFEPOINT { @@ -87,7 +89,7 @@ char *jl_gc_try_alloc_pages(void) JL_NOTSAFEPOINT block_pg_cnt = pg_cnt = min_block_pg_alloc; } else { - uv_mutex_unlock(&gc_perm_lock); + uv_mutex_unlock(&gc_pages_lock); jl_throw(jl_memory_exception); } } @@ -127,11 +129,11 @@ NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) JL_NOTSAFEPOINT goto exit; } - uv_mutex_lock(&gc_perm_lock); + uv_mutex_lock(&gc_pages_lock); // another thread may have allocated a large block while we were waiting... meta = pop_lf_back(&global_page_pool_clean); if (meta != NULL) { - uv_mutex_unlock(&gc_perm_lock); + uv_mutex_unlock(&gc_pages_lock); gc_alloc_map_set(meta->data, GC_PAGE_ALLOCATED); goto exit; } @@ -149,7 +151,7 @@ NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) JL_NOTSAFEPOINT push_lf_back(&global_page_pool_clean, pg); } } - uv_mutex_unlock(&gc_perm_lock); + uv_mutex_unlock(&gc_pages_lock); exit: #ifdef _OS_WINDOWS_ VirtualAlloc(meta->data, GC_PAGE_SZ, MEM_COMMIT, PAGE_READWRITE); diff --git a/src/gc.c b/src/gc.c index 9f57bf3c6b944..3ab0aa4b1bf1b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -3979,6 +3979,7 @@ void jl_gc_init(void) JL_MUTEX_INIT(&finalizers_lock, "finalizers_lock"); uv_mutex_init(&page_profile_lock); uv_mutex_init(&gc_perm_lock); + uv_mutex_init(&gc_pages_lock); uv_mutex_init(&gc_threads_lock); uv_cond_init(&gc_threads_cond); uv_sem_init(&gc_sweep_assists_needed, 0); @@ -4244,7 +4245,7 @@ STATIC_INLINE void *gc_try_perm_alloc_pool(size_t sz, unsigned align, unsigned o } // **NOT** a safepoint -void *jl_gc_perm_alloc_nolock(size_t sz, int zero, unsigned align, unsigned offset) +void *jl_gc_perm_alloc_nolock(size_t sz, int zero, unsigned align, unsigned offset) JL_NOTSAFEPOINT { // The caller should have acquired `gc_perm_lock` assert(align < GC_PERM_POOL_LIMIT); diff --git a/src/gc.h b/src/gc.h index e22ded0ec6740..0d8421912dbc7 100644 --- a/src/gc.h +++ b/src/gc.h @@ -574,6 +574,7 @@ FORCE_INLINE void gc_big_object_link(bigval_t *sentinel_node, bigval_t *node) JL sentinel_node->next = node; } +extern uv_mutex_t gc_perm_lock; extern uv_mutex_t gc_threads_lock; extern uv_cond_t gc_threads_cond; extern uv_sem_t gc_sweep_assists_needed; @@ -593,6 +594,7 @@ void jl_gc_debug_init(void); // GC pages +extern uv_mutex_t gc_pages_lock; void jl_gc_init_page(void) JL_NOTSAFEPOINT; NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) JL_NOTSAFEPOINT; void jl_gc_free_page(jl_gc_pagemeta_t *p) JL_NOTSAFEPOINT; diff --git a/src/init.c b/src/init.c index 4362c33ccad0f..eff786b564e54 100644 --- a/src/init.c +++ b/src/init.c @@ -746,6 +746,9 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) // Make sure we finalize the tls callback before starting any threads. (void)jl_get_pgcstack(); + // initialize symbol-table lock + uv_mutex_init(&symtab_lock); + // initialize backtraces jl_init_profile_lock(); #ifdef _OS_WINDOWS_ diff --git a/src/julia_internal.h b/src/julia_internal.h index 22c5cdb9a445f..392fe8fd9a1fb 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -350,9 +350,6 @@ jl_value_t *jl_gc_small_alloc_noinline(jl_ptls_t ptls, int offset, int osize); jl_value_t *jl_gc_big_alloc_noinline(jl_ptls_t ptls, size_t allocsz); JL_DLLEXPORT int jl_gc_classify_pools(size_t sz, int *osize) JL_NOTSAFEPOINT; -extern uv_mutex_t gc_perm_lock; -void *jl_gc_perm_alloc_nolock(size_t sz, int zero, - unsigned align, unsigned offset) JL_NOTSAFEPOINT; JL_DLLEXPORT void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, unsigned offset) JL_NOTSAFEPOINT; void gc_sweep_sysimg(void); @@ -1699,6 +1696,7 @@ void jl_write_malloc_log(void); # define jl_unreachable() ((void)jl_assume(0)) #endif +extern uv_mutex_t symtab_lock; jl_sym_t *_jl_symbol(const char *str, size_t len) JL_NOTSAFEPOINT; // Tools for locally disabling spurious compiler warnings diff --git a/src/symbol.c b/src/symbol.c index b488a0cc77065..ef2c11e0842e8 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -15,6 +15,7 @@ extern "C" { #endif +uv_mutex_t symtab_lock; static _Atomic(jl_sym_t*) symtab = NULL; #define MAX_SYM_LEN ((size_t)INTPTR_MAX - sizeof(jl_taggedvalue_t) - sizeof(jl_sym_t) - 1) @@ -35,7 +36,7 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) JL_NOTSAFEPOINT { jl_sym_t *sym; size_t nb = symbol_nbytes(len); - jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0, sizeof(void*), 0); + jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc(nb, 0, sizeof(void*), 0); sym = (jl_sym_t*)jl_valueof(tag); // set to old marked so that we won't look at it in the GC or write barrier. jl_set_typetagof(sym, jl_symbol_tag, GC_OLD_MARKED); @@ -86,15 +87,15 @@ jl_sym_t *_jl_symbol(const char *str, size_t len) JL_NOTSAFEPOINT // (or throw) _Atomic(jl_sym_t*) *slot; jl_sym_t *node = symtab_lookup(&symtab, str, len, &slot); if (node == NULL) { - uv_mutex_lock(&gc_perm_lock); + uv_mutex_lock(&symtab_lock); // Someone might have updated it, check and look up again if (jl_atomic_load_relaxed(slot) != NULL && (node = symtab_lookup(slot, str, len, &slot))) { - uv_mutex_unlock(&gc_perm_lock); + uv_mutex_unlock(&symtab_lock); return node; } node = mk_symbol(str, len); jl_atomic_store_release(slot, node); - uv_mutex_unlock(&gc_perm_lock); + uv_mutex_unlock(&symtab_lock); } return node; } From 8a7e23d29b19ebf5755b7c448731360f239dee9a Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 26 Jul 2024 20:03:53 -0700 Subject: [PATCH 079/206] Make `jl_*affinity` tests more portable (#55261) Changes made: - Use 0 for the thread ID to ensure it's always valid. The function expects `0 <= tid < jl_n_threads` so 1 is incorrect if `jl_n_threads` is 1. - After retrieving the affinity mask with `jl_getaffinity`, pass that same mask back to `jl_setaffinity`. This ensures that the mask is always valid. Using a mask of all ones results in `EINVAL` on FreeBSD. Based on the discussion in #53402, this change may also fix Windows, so I've tried reenabling it here. - To check whether `jl_getaffinity` actually did something, we can check that the mask is no longer all zeros after the call. Fixes #54817 --- test/threads.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/threads.jl b/test/threads.jl index 24da56e2b89fd..7b4558091022b 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -357,12 +357,12 @@ end @testset "jl_*affinity" begin cpumasksize = @ccall uv_cpumask_size()::Cint - if !Sys.iswindows() && cpumasksize > 0 # otherwise affinities are not supported on the platform (UV_ENOTSUP) - mask = zeros(Cchar, cpumasksize); + if cpumasksize > 0 # otherwise affinities are not supported on the platform (UV_ENOTSUP) jl_getaffinity = (tid, mask, cpumasksize) -> ccall(:jl_getaffinity, Int32, (Int16, Ptr{Cchar}, Int32), tid, mask, cpumasksize) jl_setaffinity = (tid, mask, cpumasksize) -> ccall(:jl_setaffinity, Int32, (Int16, Ptr{Cchar}, Int32), tid, mask, cpumasksize) - @test jl_getaffinity(1, mask, cpumasksize) == 0 - fill!(mask, 1) - @test jl_setaffinity(1, mask, cpumasksize) == 0 + mask = zeros(Cchar, cpumasksize) + @test jl_getaffinity(0, mask, cpumasksize) == 0 + @test !all(iszero, mask) + @test jl_setaffinity(0, mask, cpumasksize) == 0 end end From 9d112fb40000bc7b3a70b39f83edcc12fe95e117 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sat, 27 Jul 2024 16:25:14 +0100 Subject: [PATCH 080/206] Update download_cmake.sh to cmake 3.30.1 (#55275) --- contrib/download_cmake.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contrib/download_cmake.sh b/contrib/download_cmake.sh index 1deeb08ddded2..5cf3c579ed052 100755 --- a/contrib/download_cmake.sh +++ b/contrib/download_cmake.sh @@ -8,17 +8,17 @@ mkdir -p "$(dirname "$0")"/../deps/scratch cd "$(dirname "$0")"/../deps/scratch CMAKE_VERSION_MAJOR=3 -CMAKE_VERSION_MINOR=19 -CMAKE_VERSION_PATCH=3 +CMAKE_VERSION_MINOR=30 +CMAKE_VERSION_PATCH=1 CMAKE_VERSION_MAJMIN=$CMAKE_VERSION_MAJOR.$CMAKE_VERSION_MINOR CMAKE_VERSION=$CMAKE_VERSION_MAJMIN.$CMAKE_VERSION_PATCH # listed at https://cmake.org/files/v$CMAKE_VERSION_MAJMIN/cmake-$CMAKE_VERSION-SHA-256.txt # for the files cmake-$CMAKE_VERSION-macos-universal.tar.gz # cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz and cmake-$CMAKE_VERSION-Linux-aarch64.tar.gz -CMAKE_SHA256_DARWIN=a6b79ad05f89241a05797510e650354d74ff72cc988981cdd1eb2b3b2bda66ac -CMAKE_SHA256_LINUX_X86_64=c18b65697e9679e5c88dccede08c323cd3d3730648e59048047bba82097e0ffc -CMAKE_SHA256_LINUX_AARCH64=66e507c97ffb586d7ca6567890808b792c8eb004b645706df6fbf27826a395a2 +CMAKE_SHA256_DARWIN=51e12618829b811bba6f033ee8f39f6192da1b6abb20d82a7899d5134e879a4c +CMAKE_SHA256_LINUX_X86_64=ac31f077ef3378641fa25a3cb980d21b2f083982d3149a8f2eb9154f2b53696b +CMAKE_SHA256_LINUX_AARCH64=ad234996f8750f11d7bd0d17b03f55c434816adf1f1671aab9e8bab21a43286a PLATFORM="$(uname)-$(uname -m)" case $PLATFORM in @@ -28,12 +28,12 @@ case $PLATFORM in echo "$CMAKE_SHA256_DARWIN $FULLNAME.tar.gz" | shasum -a 256 -c - CMAKE_EXTRACTED_PATH=$FULLNAME/CMake.app/Contents/bin/cmake;; Linux-x86_64) - FULLNAME=cmake-$CMAKE_VERSION-$PLATFORM + FULLNAME=cmake-$CMAKE_VERSION-linux-x86_64 ../tools/jldownload https://cmake.org/files/v$CMAKE_VERSION_MAJMIN/$FULLNAME.tar.gz echo "$CMAKE_SHA256_LINUX_X86_64 $FULLNAME.tar.gz" | sha256sum -c - CMAKE_EXTRACTED_PATH=$FULLNAME/bin/cmake;; Linux-aarch64) - FULLNAME=cmake-$CMAKE_VERSION-$PLATFORM + FULLNAME=cmake-$CMAKE_VERSION-linux-aarch64 ../tools/jldownload https://cmake.org/files/v$CMAKE_VERSION_MAJMIN/$FULLNAME.tar.gz echo "$CMAKE_SHA256_LINUX_AARCH64 $FULLNAME.tar.gz" | sha256sum -c - CMAKE_EXTRACTED_PATH=$FULLNAME/bin/cmake;; From 197295c84aab217bffde01a4339f1d0e8e95fb98 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 28 Jul 2024 17:35:28 +0530 Subject: [PATCH 081/206] Restrict binary ops for Diagonal and Symmetric to Number eltypes (#55251) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `(::Diagonal) + (::Symmetric)` and analogous methods were specialized in https://github.com/JuliaLang/julia/pull/35333 to return a `Symmetric`, but these only work if the `Diagonal` is also symmetric. This typically holds for arrays of numbers, but may not hold for block-diagonal and other types for which symmetry isn't guaranteed. This PR restricts the methods to arrays of `Number`s. Fixes, e.g.: ```julia julia> using StaticArrays, LinearAlgebra julia> D = Diagonal(fill(SMatrix{2,2}(1:4), 2)) 2×2 Diagonal{SMatrix{2, 2, Int64, 4}, Vector{SMatrix{2, 2, Int64, 4}}}: [1 3; 2 4] ⋅ ⋅ [1 3; 2 4] julia> S = Symmetric(D) 2×2 Symmetric{AbstractMatrix, Diagonal{SMatrix{2, 2, Int64, 4}, Vector{SMatrix{2, 2, Int64, 4}}}}: [1 3; 3 4] ⋅ ⋅ [1 3; 3 4] julia> S + D 2×2 Symmetric{AbstractMatrix, Diagonal{SMatrix{2, 2, Int64, 4}, Vector{SMatrix{2, 2, Int64, 4}}}}: [2 6; 6 8] ⋅ ⋅ [2 6; 6 8] julia> S[1,1] + D[1,1] 2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2): 2 6 5 8 julia> (S + D)[1,1] == S[1,1] + D[1,1] false ``` After this, ```julia julia> S + D 2×2 Matrix{AbstractMatrix{Int64}}: [2 6; 5 8] [0 0; 0 0] [0 0; 0 0] [2 6; 5 8] ``` Even with `Number`s as elements, there might be an issue with `NaN`s along the diagonal as `!issymmetric(NaN)`, but that may be a different PR. --- stdlib/LinearAlgebra/src/diagonal.jl | 4 ++-- stdlib/LinearAlgebra/test/diagonal.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index b3826a2aa7f82..ff8350d8ddeb1 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -268,10 +268,10 @@ end (-)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag - Db.diag) for f in (:+, :-) - @eval function $f(D::Diagonal, S::Symmetric) + @eval function $f(D::Diagonal{<:Number}, S::Symmetric) return Symmetric($f(D, S.data), sym_uplo(S.uplo)) end - @eval function $f(S::Symmetric, D::Diagonal) + @eval function $f(S::Symmetric, D::Diagonal{<:Number}) return Symmetric($f(S.data, D), sym_uplo(S.uplo)) end @eval function $f(D::Diagonal{<:Real}, H::Hermitian) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 1a3b8d4fd0ea7..e1fc9afa5ad2e 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -1335,4 +1335,16 @@ end end end +@testset "+/- with block Symmetric/Hermitian" begin + for p in ([1 2; 3 4], [1 2+im; 2-im 4+2im]) + m = SizedArrays.SizedArray{(2,2)}(p) + D = Diagonal(fill(m, 2)) + for T in (Symmetric, Hermitian) + S = T(fill(m, 2, 2)) + @test D + S == Array(D) + Array(S) + @test S + D == Array(S) + Array(D) + end + end +end + end # module TestDiagonal From 7de15ba07178c02560ecbfebda98bc811758dd6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 28 Jul 2024 20:59:57 +0100 Subject: [PATCH 082/206] [CI] Run whitespace check on GitHub Actions and annotate source code (#55281) There some advantages in running this on GitHub Actions (GHA) rather than Buildkite (BK): * on GHA this task takes ~10 seconds, on BK it takes ~1 minute (job setup on BK takes way too long) * since for this task we can use GitHub-hosted runners (which come with Julia preinstalled), we can spare BK runners from running this job. Admittedly it's very marginal saving, but better than nothing when the queue gets long * using GHA allows us to easily add source code annotations in PR overviews, which make it easier to quickly spot the line to fix from the GitHub web interface. This would be doable also on BK, but slightly more annoying. As [an example](https://github.com/giordano/julia/commit/a7725e47e245fcefd60ed02a2e492ed5a0af13e9): ![image](https://github.com/user-attachments/assets/8a459a61-8953-4590-980e-ff156a62701f) If this PR is accepted, I'll remove the corresponding job from BK. --------- Co-authored-by: Dilum Aluthge --- .github/workflows/Whitespace.yml | 23 +++++++++++++++++++++++ contrib/check-whitespace.jl | 8 ++++++++ 2 files changed, 31 insertions(+) create mode 100644 .github/workflows/Whitespace.yml diff --git a/.github/workflows/Whitespace.yml b/.github/workflows/Whitespace.yml new file mode 100644 index 0000000000000..5706f6148dc33 --- /dev/null +++ b/.github/workflows/Whitespace.yml @@ -0,0 +1,23 @@ +name: Whitespace + +permissions: {} + +on: + push: + branches: + - master + pull_request: + +jobs: + whitespace: + name: Check whitespace + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - name: Checkout the JuliaLang/julia repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false + - name: Check whitespace + run: | + contrib/check-whitespace.jl diff --git a/contrib/check-whitespace.jl b/contrib/check-whitespace.jl index e178ec8a02a38..fd3106587fb0d 100755 --- a/contrib/check-whitespace.jl +++ b/contrib/check-whitespace.jl @@ -18,6 +18,8 @@ const patterns = split(""" *Makefile """) +const is_gha = something(tryparse(Bool, get(ENV, "GITHUB_ACTIONS", "false")), false) + # Note: `git ls-files` gives `/` as a path separator on Windows, # so we just use `/` for all platforms. allow_tabs(path) = @@ -63,8 +65,14 @@ function check_whitespace() for (path, lineno, msg) in sort!(collect(errors)) if lineno == 0 println(stderr, "$path -- $msg") + if is_gha + println(stdout, "::warning title=Whitespace check,file=", path, "::", msg) + end else println(stderr, "$path:$lineno -- $msg") + if is_gha + println(stdout, "::warning title=Whitespace check,file=", path, ",line=", lineno, "::", msg) + end end end exit(1) From 079b69e124e5cb3756b190c7b2853deb7c6d1955 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Sun, 28 Jul 2024 17:26:41 -0400 Subject: [PATCH 083/206] CI: Use Dependabot to update GitHub Actions in this repo, and pin all external GitHub Actions to full-length commit hashes (#55283) --- .github/dependabot.yml | 11 +++++++++++ .github/workflows/LabelCheck.yml | 2 +- .github/workflows/Typos.yml | 4 ++-- .github/workflows/cffconvert.yml | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..2ad7fdc1efa0a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 100 + labels: + - "dependencies" + - "github-actions" + - "domain:ci" diff --git a/.github/workflows/LabelCheck.yml b/.github/workflows/LabelCheck.yml index 0ff56f4b9dfdc..c966e478e3fe0 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..6c9eeacc21800 100644 --- a/.github/workflows/Typos.yml +++ b/.github/workflows/Typos.yml @@ -11,11 +11,11 @@ jobs: timeout-minutes: 5 steps: - name: Checkout the JuliaLang/julia repository - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - name: Check spelling with typos - #uses: crate-ci/typos@master + #uses: crate-ci/typos@c7af4712eda24dd1ef54bd8212973888489eb0ce # v1.23.5 env: GH_TOKEN: "${{ github.token }}" run: | diff --git a/.github/workflows/cffconvert.yml b/.github/workflows/cffconvert.yml index 751476865ae4c..4c9debb246f3f 100644 --- a/.github/workflows/cffconvert.yml +++ b/.github/workflows/cffconvert.yml @@ -23,11 +23,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out a copy of the repository - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - name: Check whether the citation metadata from CITATION.cff is valid - uses: citation-file-format/cffconvert-github-action@2.0.0 + uses: citation-file-format/cffconvert-github-action@4cf11baa70a673bfdf9dad0acc7ee33b3f4b6084 # 2.0.0 with: args: "--validate" From 5da94687084f46d7b7366aa55b0c75dcc6d5157f Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 29 Jul 2024 00:07:43 -0400 Subject: [PATCH 084/206] use iszero in isinteger(::AbstractFloat) (#55276) This is a very slight tweak to the implementation of `isinteger(::AbstractFloat)` to use `iszero` rather than `== 0`. It shouldn't make any difference with any of the built-in floating-point types, but `iszero` might conceivably be faster for some user-defined types. I also added a comment to indicate why it's using `iszero(x - trunc(x))` rather than `x == trunc(x)` (due to non-finite values); this code dates back to #14569 in Julia 0.5. --------- Co-authored-by: Sukera <11753998+Seelengrab@users.noreply.github.com> --- base/floatfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index a2a0f60bcf399..67e7899b4107c 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -42,7 +42,7 @@ it is the minimum of `maxintfloat(T)` and [`typemax(S)`](@ref). maxintfloat(::Type{S}, ::Type{T}) where {S<:AbstractFloat, T<:Integer} = min(maxintfloat(S), S(typemax(T))) maxintfloat() = maxintfloat(Float64) -isinteger(x::AbstractFloat) = (x - trunc(x) == 0) +isinteger(x::AbstractFloat) = iszero(x - trunc(x)) # note: x == trunc(x) would be incorrect for x=Inf # See rounding.jl for docstring. From 4dfce5d5a5efcb87ebe92b2c8e943a0870c2eae9 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:47:33 +0900 Subject: [PATCH 085/206] adjust the name and remarks of const prop heuristics (#55260) `const_prop_entry_heuristics` currently checks the return type only, so I have given it a name that reflects this and adjusted the remarks accordingly. There are no changes to the basic behavior of inference. --- base/compiler/abstractinterpretation.jl | 27 +++++++++++++------------ test/compiler/inference.jl | 8 ++++---- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 88c3324668869..3b658534b5d35 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1034,12 +1034,12 @@ function maybe_get_const_prop_profitable(interp::AbstractInterpreter, match::MethodMatch, sv::AbsIntState) method = match.method force = force_const_prop(interp, f, method) - if !const_prop_entry_heuristic(interp, result, si, sv, force) - # N.B. remarks are emitted within `const_prop_entry_heuristic` + if !const_prop_rettype_heuristic(interp, result, si, sv, force) + # N.B. remarks are emitted within `const_prop_rettype_heuristic` return nothing end if !const_prop_argument_heuristic(interp, arginfo, sv) - add_remark!(interp, sv, "[constprop] Disabled by argument and rettype heuristics") + add_remark!(interp, sv, "[constprop] Disabled by argument heuristics") return nothing end all_overridden = is_all_overridden(interp, arginfo, sv) @@ -1061,28 +1061,28 @@ function maybe_get_const_prop_profitable(interp::AbstractInterpreter, return mi end -function const_prop_entry_heuristic(interp::AbstractInterpreter, result::MethodCallResult, - si::StmtInfo, sv::AbsIntState, force::Bool) - if result.rt isa LimitedAccuracy +function const_prop_rettype_heuristic(interp::AbstractInterpreter, result::MethodCallResult, + si::StmtInfo, sv::AbsIntState, force::Bool) + rt = result.rt + if rt isa LimitedAccuracy # optimizations like inlining are disabled for limited frames, # thus there won't be much benefit in constant-prop' here # N.B. don't allow forced constprop' for safety (xref #52763) - add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (limited accuracy)") + add_remark!(interp, sv, "[constprop] Disabled by rettype heuristic (limited accuracy)") return false elseif force return true elseif call_result_unused(si) && result.edgecycle - add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (edgecycle with unused result)") + add_remark!(interp, sv, "[constprop] Disabled by rettype heuristic (edgecycle with unused result)") return false end # check if this return type is improvable (i.e. whether it's possible that with more # information, we might get a more precise type) - rt = result.rt if isa(rt, Type) # could always be improved to `Const`, `PartialStruct` or just a more precise type, # unless we're already at `Bottom` if rt === Bottom - add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (erroneous result)") + add_remark!(interp, sv, "[constprop] Disabled by rettype heuristic (erroneous result)") return false end return true @@ -1091,14 +1091,15 @@ function const_prop_entry_heuristic(interp::AbstractInterpreter, result::MethodC return true elseif isa(rt, Const) if is_nothrow(result.effects) - add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (nothrow const)") + add_remark!(interp, sv, "[constprop] Disabled by rettype heuristic (nothrow const)") return false end # Could still be improved to Bottom (or at least could see the effects improved) return true + else + add_remark!(interp, sv, "[constprop] Disabled by rettype heuristic (unimprovable result)") + return false end - add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (unimprovable result)") - return false end # determines heuristically whether if constant propagation can be worthwhile diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 2c149b1abf21d..8b6da828af54d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5052,13 +5052,13 @@ g() = empty_nt_values(Base.inferencebarrier(Tuple{})) # to terminate the call. @newinterp RecurseInterpreter let CC = Core.Compiler - function CC.const_prop_entry_heuristic(interp::RecurseInterpreter, result::CC.MethodCallResult, - si::CC.StmtInfo, sv::CC.AbsIntState, force::Bool) + function CC.const_prop_rettype_heuristic(interp::RecurseInterpreter, result::CC.MethodCallResult, + si::CC.StmtInfo, sv::CC.AbsIntState, force::Bool) if result.rt isa CC.LimitedAccuracy return force # allow forced constprop to recurse into unresolved cycles end - return @invoke CC.const_prop_entry_heuristic(interp::CC.AbstractInterpreter, result::CC.MethodCallResult, - si::CC.StmtInfo, sv::CC.AbsIntState, force::Bool) + return @invoke CC.const_prop_rettype_heuristic(interp::CC.AbstractInterpreter, result::CC.MethodCallResult, + si::CC.StmtInfo, sv::CC.AbsIntState, force::Bool) end end Base.@constprop :aggressive type_level_recurse1(x...) = x[1] == 2 ? 1 : (length(x) > 100 ? x : type_level_recurse2(x[1] + 1, x..., x...)) From 427824ef4189c8d8a6dbad266a7e1d7f2a71eafc Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 30 Jul 2024 02:02:58 +0900 Subject: [PATCH 086/206] refactoring on SROA passes (#55262) All changes are cosmetic and do not change the basic functionality: - Added the interface type to the callbacks received by `simple_walker` to clarify which objects are passed as callbacks to `simple_walker`. - Replaced ambiguous names like `idx` with more descriptive ones like `defidx` to make the algorithm easier to understand. --- base/compiler/ssair/passes.jl | 157 +++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 69 deletions(-) diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index 6b29c9b2fe949..33cda9bf27d20 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -79,7 +79,7 @@ end function find_curblock(domtree::DomTree, allblocks::BitSet, curblock::Int) # TODO: This can be much faster by looking at current level and only # searching for those blocks in a sorted order - while !(curblock in allblocks) && curblock !== 0 + while curblock ∉ allblocks && curblock ≠ 0 curblock = domtree.idoms_bb[curblock] end return curblock @@ -190,18 +190,21 @@ function collect_leaves(compact::IncrementalCompact, @nospecialize(val), @nospec return walk_to_defs(compact, val, typeconstraint, predecessors, 𝕃ₒ) end -function trivial_walker(@nospecialize(pi), @nospecialize(idx)) - return nothing -end +abstract type WalkerCallback end -function pi_walker(@nospecialize(pi), @nospecialize(idx)) - if isa(pi, PiNode) - return LiftedValue(pi.val) +struct TrivialWalker <: WalkerCallback end +(::TrivialWalker)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) = nothing + +struct PiWalker <: WalkerCallback end +function (::PiWalker)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) + if isa(def, PiNode) + return LiftedValue(def.val) end return nothing end -function simple_walk(compact::IncrementalCompact, @nospecialize(defssa#=::AnySSAValue=#), callback=trivial_walker) +function simple_walk(compact::IncrementalCompact, @nospecialize(defssa::AnySSAValue), + walker_callback::WalkerCallback=TrivialWalker()) while true if isa(defssa, OldSSAValue) if already_inserted(compact, defssa) @@ -218,7 +221,7 @@ function simple_walk(compact::IncrementalCompact, @nospecialize(defssa#=::AnySSA end def = compact[defssa][:stmt] if isa(def, AnySSAValue) - callback(def, defssa) + walker_callback(def, defssa) if isa(def, SSAValue) is_old(compact, defssa) && (def = OldSSAValue(def.id)) end @@ -226,7 +229,7 @@ function simple_walk(compact::IncrementalCompact, @nospecialize(defssa#=::AnySSA elseif isa(def, Union{PhiNode, PhiCNode, GlobalRef}) return defssa else - new_def = callback(def, defssa) + new_def = walker_callback(def, defssa) if new_def === nothing return defssa end @@ -241,16 +244,21 @@ function simple_walk(compact::IncrementalCompact, @nospecialize(defssa#=::AnySSA end end -function simple_walk_constraint(compact::IncrementalCompact, @nospecialize(defssa#=::AnySSAValue=#), - @nospecialize(typeconstraint)) - callback = function (@nospecialize(pi), @nospecialize(idx)) - if isa(pi, PiNode) - typeconstraint = typeintersect(typeconstraint, widenconst(pi.typ)) - return LiftedValue(pi.val) - end - return nothing +mutable struct TypeConstrainingWalker <: WalkerCallback + typeconstraint::Any + TypeConstrainingWalker(@nospecialize(typeconstraint::Any)) = new(typeconstraint) +end +function (walker_callback::TypeConstrainingWalker)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) + if isa(def, PiNode) + walker_callback.typeconstraint = + typeintersect(walker_callback.typeconstraint, widenconst(def.typ)) + return LiftedValue(def.val) end - def = simple_walk(compact, defssa, callback) + return nothing +end +function simple_walk_constraint(compact::IncrementalCompact, @nospecialize(val::AnySSAValue), + @nospecialize(typeconstraint)) + def = simple_walk(compact, val, TypeConstrainingWalker(typeconstraint)) return Pair{Any, Any}(def, typeconstraint) end @@ -638,15 +646,17 @@ end struct SkipToken end; const SKIP_TOKEN = SkipToken() -function lifted_value(compact::IncrementalCompact, @nospecialize(old_node_ssa#=::AnySSAValue=#), @nospecialize(old_value), - lifted_philikes::Vector{LiftedPhilike}, lifted_leaves::Union{LiftedLeaves, LiftedDefs}, reverse_mapping::IdDict{AnySSAValue, Int}, - walker_callback) +function lifted_value(compact::IncrementalCompact, @nospecialize(old_node_ssa::AnySSAValue), + @nospecialize(old_value), lifted_philikes::Vector{LiftedPhilike}, + lifted_leaves::Union{LiftedLeaves, LiftedDefs}, + reverse_mapping::IdDict{AnySSAValue, Int}, + walker_callback::WalkerCallback) val = old_value if is_old(compact, old_node_ssa) && isa(val, SSAValue) val = OldSSAValue(val.id) end if isa(val, AnySSAValue) - val = simple_walk(compact, val, def_walker(lifted_leaves, reverse_mapping, walker_callback)) + val = simple_walk(compact, val, LiftedLeaveWalker(lifted_leaves, reverse_mapping, walker_callback)) end if val in keys(lifted_leaves) lifted_val = lifted_leaves[val] @@ -656,7 +666,7 @@ function lifted_value(compact::IncrementalCompact, @nospecialize(old_node_ssa#=: lifted_val === nothing && return UNDEF_TOKEN val = lifted_val.val if isa(val, AnySSAValue) - val = simple_walk(compact, val, pi_walker) + val = simple_walk(compact, val, PiWalker()) end return val elseif isa(val, AnySSAValue) && val in keys(reverse_mapping) @@ -673,7 +683,7 @@ function is_old(compact, @nospecialize(old_node_ssa)) return true end -struct PhiNest{C} +struct PhiNest{C<:WalkerCallback} visited_philikes::Vector{AnySSAValue} lifted_philikes::Vector{LiftedPhilike} lifted_leaves::Union{LiftedLeaves, LiftedDefs} @@ -743,20 +753,29 @@ function finish_phi_nest!(compact::IncrementalCompact, nest::PhiNest) end end -function def_walker(lifted_leaves::Union{LiftedLeaves, LiftedDefs}, reverse_mapping::IdDict{AnySSAValue, Int}, walker_callback) - function (@nospecialize(walk_def), @nospecialize(defssa)) - if (defssa in keys(lifted_leaves)) || (isa(defssa, AnySSAValue) && defssa in keys(reverse_mapping)) - return nothing - end - isa(walk_def, PiNode) && return LiftedValue(walk_def.val) - return walker_callback(walk_def, defssa) +struct LiftedLeaveWalker{C<:WalkerCallback} <: WalkerCallback + lifted_leaves::Union{LiftedLeaves, LiftedDefs} + reverse_mapping::IdDict{AnySSAValue, Int} + inner_walker_callback::C + function LiftedLeaveWalker(@nospecialize(lifted_leaves::Union{LiftedLeaves, LiftedDefs}), + @nospecialize(reverse_mapping::IdDict{AnySSAValue, Int}), + inner_walker_callback::C) where C<:WalkerCallback + return new{C}(lifted_leaves, reverse_mapping, inner_walker_callback) end end +function (walker_callback::LiftedLeaveWalker)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) + (; lifted_leaves, reverse_mapping, inner_walker_callback) = walker_callback + if defssa in keys(lifted_leaves) || defssa in keys(reverse_mapping) + return nothing + end + isa(def, PiNode) && return LiftedValue(def.val) + return inner_walker_callback(def, defssa) +end function perform_lifting!(compact::IncrementalCompact, visited_philikes::Vector{AnySSAValue}, @nospecialize(cache_key), @nospecialize(result_t), lifted_leaves::Union{LiftedLeaves, LiftedDefs}, @nospecialize(stmt_val), - lazydomtree::Union{LazyDomtree,Nothing}, walker_callback = trivial_walker) + lazydomtree::Union{LazyDomtree,Nothing}, walker_callback::WalkerCallback = TrivialWalker()) reverse_mapping = IdDict{AnySSAValue, Int}() for id in 1:length(visited_philikes) reverse_mapping[visited_philikes[id]] = id @@ -839,7 +858,7 @@ function perform_lifting!(compact::IncrementalCompact, # Fixup the stmt itself if isa(stmt_val, Union{SSAValue, OldSSAValue}) - stmt_val = simple_walk(compact, stmt_val, def_walker(lifted_leaves, reverse_mapping, walker_callback)) + stmt_val = simple_walk(compact, stmt_val, LiftedLeaveWalker(lifted_leaves, reverse_mapping, walker_callback)) end if stmt_val in keys(lifted_leaves) @@ -948,6 +967,17 @@ function keyvalue_predecessors(@nospecialize(key), 𝕃ₒ::AbstractLattice) end end +struct KeyValueWalker <: WalkerCallback + compact::IncrementalCompact +end +function (walker_callback::KeyValueWalker)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) + if is_known_invoke_or_call(def, Core.OptimizedGenerics.KeyValue.set, walker_callback.compact) + @assert length(def.args) in (5, 6) + return LiftedValue(def.args[end-2]) + end + return nothing +end + function lift_keyvalue_get!(compact::IncrementalCompact, idx::Int, stmt::Expr, 𝕃ₒ::AbstractLattice) collection = stmt.args[end-1] key = stmt.args[end] @@ -964,16 +994,9 @@ function lift_keyvalue_get!(compact::IncrementalCompact, idx::Int, stmt::Expr, result_t = tmerge(𝕃ₒ, result_t, argextype(v.val, compact)) end - function keyvalue_walker(@nospecialize(def), _) - if is_known_invoke_or_call(def, Core.OptimizedGenerics.KeyValue.set, compact) - @assert length(def.args) in (5, 6) - return LiftedValue(def.args[end-2]) - end - return nothing - end (lifted_val, nest) = perform_lifting!(compact, visited_philikes, key, result_t, lifted_leaves, collection, nothing, - keyvalue_walker) + KeyValueWalker(compact)) compact[idx] = lifted_val === nothing ? nothing : Expr(:call, GlobalRef(Core, :tuple), lifted_val.val) finish_phi_nest!(compact, nest) @@ -1139,13 +1162,11 @@ end # which can be very large sometimes, and program counters in question are often very sparse const SPCSet = IdSet{Int} -struct IntermediaryCollector +struct IntermediaryCollector <: WalkerCallback intermediaries::SPCSet end -function (this::IntermediaryCollector)(@nospecialize(pi), @nospecialize(ssa)) - if !isa(pi, Expr) - push!(this.intermediaries, ssa.id) - end +function (walker_callback::IntermediaryCollector)(@nospecialize(def), @nospecialize(defssa::AnySSAValue)) + isa(def, Expr) || push!(walker_callback.intermediaries, defssa.id) return nothing end @@ -1242,7 +1263,7 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing) update_scope_mapping!(scope_mapping, bb+1, bbs) end # check whether this statement is `getfield` / `setfield!` (or other "interesting" statement) - is_setfield = is_isdefined = is_finalizer = is_keyvalue_get = false + is_setfield = is_isdefined = is_finalizer = false field_ordering = :unspecified if is_known_call(stmt, setfield!, compact) 4 <= length(stmt.args) <= 5 || continue @@ -1371,8 +1392,7 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing) if ismutabletypename(struct_typ_name) isa(val, SSAValue) || continue let intermediaries = SPCSet() - callback = IntermediaryCollector(intermediaries) - def = simple_walk(compact, val, callback) + def = simple_walk(compact, val, IntermediaryCollector(intermediaries)) # Mutable stuff here isa(def, SSAValue) || continue if defuses === nothing @@ -1680,7 +1700,7 @@ end function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse}}, used_ssas::Vector{Int}, lazydomtree::LazyDomtree, inlining::Union{Nothing, InliningState}) 𝕃ₒ = inlining === nothing ? SimpleInferenceLattice.instance : optimizer_lattice(inlining.interp) lazypostdomtree = LazyPostDomtree(ir) - for (idx, (intermediaries, defuse)) in defuses + for (defidx, (intermediaries, defuse)) in defuses intermediaries = collect(intermediaries) # Check if there are any uses we did not account for. If so, the variable # escapes and we cannot eliminate the allocation. This works, because we're guaranteed @@ -1688,16 +1708,15 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # show up in the nuses_total count. nleaves = length(defuse.uses) + length(defuse.defs) nuses = 0 - for idx in intermediaries - nuses += used_ssas[idx] + for iidx in intermediaries + nuses += used_ssas[iidx] end - nuses_total = used_ssas[idx] + nuses - length(intermediaries) + nuses_total = used_ssas[defidx] + nuses - length(intermediaries) nleaves == nuses_total || continue # Find the type for this allocation - defexpr = ir[SSAValue(idx)][:stmt] + defexpr = ir[SSAValue(defidx)][:stmt] isexpr(defexpr, :new) || continue - newidx = idx - typ = unwrap_unionall(ir.stmts[newidx][:type]) + typ = unwrap_unionall(ir.stmts[defidx][:type]) # Could still end up here if we tried to setfield! on an immutable, which would # error at runtime, but is not illegal to have in the IR. typ = widenconst(typ) @@ -1713,7 +1732,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse end end if finalizer_idx !== nothing && inlining !== nothing - try_resolve_finalizer!(ir, idx, finalizer_idx, defuse, inlining, + try_resolve_finalizer!(ir, defidx, finalizer_idx, defuse, inlining, lazydomtree, lazypostdomtree, ir[SSAValue(finalizer_idx)][:info]) continue end @@ -1752,11 +1771,11 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # but we should come up with semantics for well defined semantics # for uninitialized fields first. ndefuse = length(fielddefuse) - blocks = Vector{Tuple{#=phiblocks=# Vector{Int}, #=allblocks=# BitSet}}(undef, ndefuse) + blocks = Vector{Tuple{#=phiblocks=#Vector{Int},#=allblocks=#BitSet}}(undef, ndefuse) for fidx in 1:ndefuse du = fielddefuse[fidx] isempty(du.uses) && continue - push!(du.defs, newidx) + push!(du.defs, defidx) ldu = compute_live_ins(ir.cfg, du) if isempty(ldu.live_in_bbs) phiblocks = Int[] @@ -1769,7 +1788,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse for i = 1:length(du.uses) use = du.uses[i] if use.kind === :isdefined - if has_safe_def(ir, get!(lazydomtree), allblocks, du, newidx, use.idx) + if has_safe_def(ir, get!(lazydomtree), allblocks, du, defidx, use.idx) ir[SSAValue(use.idx)][:stmt] = true else all_eliminated = false @@ -1782,7 +1801,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse continue end end - has_safe_def(ir, get!(lazydomtree), allblocks, du, newidx, use.idx) || @goto skip + has_safe_def(ir, get!(lazydomtree), allblocks, du, defidx, use.idx) || @goto skip end else # always have some definition at the allocation site for i = 1:length(du.uses) @@ -1849,19 +1868,19 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # all "usages" (i.e. `getfield` and `isdefined` calls) are eliminated, # now eliminate "definitions" (i.e. `setfield!`) calls # (NOTE the allocation itself will be eliminated by DCE pass later) - for idx in du.defs - idx == newidx && continue # this is allocation + for didx in du.defs + didx == defidx && continue # this is allocation # verify this statement won't throw, otherwise it can't be eliminated safely - ssa = SSAValue(idx) - if is_nothrow(ir, ssa) - ir[ssa][:stmt] = nothing + setfield_ssa = SSAValue(didx) + if is_nothrow(ir, setfield_ssa) + ir[setfield_ssa][:stmt] = nothing else # We can't eliminate this statement, because it might still # throw an error, but we can mark it as effect-free since we # know we have removed all uses of the mutable allocation. # As a result, if we ever do prove nothrow, we can delete # this statement then. - add_flag!(ir[ssa], IR_FLAG_EFFECT_FREE) + add_flag!(ir[setfield_ssa], IR_FLAG_EFFECT_FREE) end end end @@ -1870,7 +1889,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # this means all ccall preserves have been replaced with forwarded loads # so we can potentially eliminate the allocation, otherwise we must preserve # the whole allocation. - push!(intermediaries, newidx) + push!(intermediaries, defidx) end # Insert the new preserves for (useidx, new_preserves) in preserve_uses From 1119f125094c3b944ba728dd73788941050620e8 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Mon, 29 Jul 2024 20:03:17 +0100 Subject: [PATCH 087/206] Revert "Deps: after configuring CMake project, use `cmake --build`, not `make` (#54538)" (#55285) Fixes #55284. --- deps/ittapi.mk | 2 +- deps/libgit2.mk | 4 ++-- deps/libssh2.mk | 4 ++-- deps/libsuitesparse.mk | 6 +++--- deps/libtracyclient.mk | 4 +++- deps/llvm.mk | 4 +++- deps/mbedtls.mk | 4 ++-- deps/unwind.mk | 2 +- deps/zlib.mk | 2 +- 9 files changed, 18 insertions(+), 14 deletions(-) diff --git a/deps/ittapi.mk b/deps/ittapi.mk index 505b7c8c28c64..b62b981a34ddb 100644 --- a/deps/ittapi.mk +++ b/deps/ittapi.mk @@ -14,7 +14,7 @@ $(BUILDDIR)/$(ITTAPI_SRC_DIR)/build-configured: $(SRCCACHE)/$(ITTAPI_SRC_DIR)/so echo 1 > $@ $(BUILDDIR)/$(ITTAPI_SRC_DIR)/build-compiled: $(BUILDDIR)/$(ITTAPI_SRC_DIR)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) echo 1 > $@ define ITTAPI_INSTALL diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 162ad9fc513dd..b65ac022885a3 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -51,12 +51,12 @@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: $(LIBGIT2_SRC_PATH)/source-extr echo 1 > $@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-compiled: $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) echo 1 > $@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-checked: $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-compiled ifeq ($(OS),$(BUILD_OS)) - $(CMAKE) --build $(dir $@) test + $(MAKE) -C $(dir $@) test endif echo 1 > $@ diff --git a/deps/libssh2.mk b/deps/libssh2.mk index 54d40dabbce1e..c293d8309d2bc 100644 --- a/deps/libssh2.mk +++ b/deps/libssh2.mk @@ -49,12 +49,12 @@ $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-configured: $(LIBSSH2_SRC_PATH)/source-extr echo 1 > $@ $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-compiled: $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) echo 1 > $@ $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-checked: $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-compiled ifeq ($(OS),$(BUILD_OS)) - $(CMAKE) --build $(dir $@) test + $(MAKE) -C $(dir $@) test endif echo 1 > $@ diff --git a/deps/libsuitesparse.mk b/deps/libsuitesparse.mk index c014686b1866e..d840a7b298e17 100644 --- a/deps/libsuitesparse.mk +++ b/deps/libsuitesparse.mk @@ -59,8 +59,8 @@ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: | $(build_prefix)/ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-patched cd $(dir $<) && $(CMAKE) . $(LIBSUITESPARSE_CMAKE_FLAGS) - $(CMAKE) --build $(dir $<) - $(CMAKE) --install $(dir $<) + $(MAKE) -C $(dir $<) + $(MAKE) -C $(dir $<) install echo 1 > $@ ifeq ($(OS),WINNT) @@ -70,7 +70,7 @@ LIBSUITESPARSE_SHLIB_ENV:=LD_LIBRARY_PATH="$(build_shlibdir)" endif $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-checked: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled for PROJ in $(shell echo $(subst ;, ,$(LIBSUITESPARSE_PROJECTS))); do \ - $(LIBSUITESPARSE_SHLIB_ENV) $(CMAKE) --build $(dir $<)$${PROJ} default $(LIBSUITESPARSE_MFLAGS) || exit 1; \ + $(LIBSUITESPARSE_SHLIB_ENV) $(MAKE) -C $(dir $<)$${PROJ} default $(LIBSUITESPARSE_MFLAGS) || exit 1; \ done echo 1 > $@ diff --git a/deps/libtracyclient.mk b/deps/libtracyclient.mk index 814f336584e98..92d6bee4caea6 100644 --- a/deps/libtracyclient.mk +++ b/deps/libtracyclient.mk @@ -55,7 +55,9 @@ $(LIBTRACYCLIENT_BUILDDIR)/build-configured: $(LIBTRACYCLIENT_BUILDDIR)/libTracy $(LIBTRACYCLIENT_BUILDDIR)/build-compiled: $(LIBTRACYCLIENT_BUILDDIR)/build-configured cd $(LIBTRACYCLIENT_BUILDDIR) && \ - $(CMAKE) --build . + $(if $(filter $(CMAKE_GENERATOR),make), \ + $(MAKE), \ + $(CMAKE) --build .) echo 1 > $@ $(eval $(call staged-install, \ diff --git a/deps/llvm.mk b/deps/llvm.mk index 5e73c18f53289..eddf9b60e38c7 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -270,7 +270,9 @@ $(LLVM_BUILDDIR_withtype)/build-configured: $(SRCCACHE)/$(LLVM_SRC_DIR)/source-e $(LLVM_BUILDDIR_withtype)/build-compiled: $(LLVM_BUILDDIR_withtype)/build-configured cd $(LLVM_BUILDDIR_withtype) && \ - $(CMAKE) --build . + $(if $(filter $(CMAKE_GENERATOR),make), \ + $(MAKE), \ + $(CMAKE) --build .) echo 1 > $@ $(LLVM_BUILDDIR_withtype)/build-checked: $(LLVM_BUILDDIR_withtype)/build-compiled diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index 79f6dadf1d383..39cf817d70658 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -39,12 +39,12 @@ $(BUILDDIR)/$(MBEDTLS_SRC)/build-configured: $(SRCCACHE)/$(MBEDTLS_SRC)/source-e echo 1 > $@ $(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled: $(BUILDDIR)/$(MBEDTLS_SRC)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) echo 1 > $@ $(BUILDDIR)/$(MBEDTLS_SRC)/build-checked: $(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled ifeq ($(OS),$(BUILD_OS)) - $(CMAKE) --build $(dir $@) test + $(MAKE) -C $(dir $@) test endif echo 1 > $@ diff --git a/deps/unwind.mk b/deps/unwind.mk index 0bfaca574f5e6..501ea6b8aedcc 100644 --- a/deps/unwind.mk +++ b/deps/unwind.mk @@ -121,7 +121,7 @@ $(BUILDDIR)/llvmunwind-$(LLVMUNWIND_VER)/build-configured: $(SRCCACHE)/llvmunwin echo 1 > $@ $(BUILDDIR)/llvmunwind-$(LLVMUNWIND_VER)/build-compiled: $(BUILDDIR)/llvmunwind-$(LLVMUNWIND_VER)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) echo 1 > $@ $(eval $(call staged-install, \ diff --git a/deps/zlib.mk b/deps/zlib.mk index 95168b115ef31..5548a0791f4d2 100644 --- a/deps/zlib.mk +++ b/deps/zlib.mk @@ -14,7 +14,7 @@ $(BUILDDIR)/$(ZLIB_SRC_DIR)/build-configured: $(SRCCACHE)/$(ZLIB_SRC_DIR)/source echo 1 > $@ $(BUILDDIR)/$(ZLIB_SRC_DIR)/build-compiled: $(BUILDDIR)/$(ZLIB_SRC_DIR)/build-configured - $(CMAKE) --build $(dir $<) + $(MAKE) -C $(dir $<) $(MAKE_COMMON) echo 1 > $@ $(eval $(call staged-install, \ From 34cd6103aa68bf07766cdccdc284940091692fe5 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Tue, 30 Jul 2024 05:08:28 +0800 Subject: [PATCH 088/206] specificity: ensure fast-path in `sub/eq_msp` handle missing `UnionAll` wrapper correctly. (#54736) --- src/subtype.c | 60 ++++++++++++++++++++++++++++++++++++++++++--- test/specificity.jl | 11 +++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 3340abfc4bafc..e503b49811503 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -4730,6 +4730,56 @@ JL_DLLEXPORT jl_value_t *jl_widen_diagonal(jl_value_t *t, jl_unionall_t *ua) } // specificity comparison +static int count_missing_wrap(jl_value_t *x, jl_typeenv_t *env) +{ + if (!jl_has_free_typevars(x)) + return 0; + jl_typeenv_t *wrapped = NULL; + int count = 0; + for (jl_typeenv_t *env2 = env; env2 != NULL; env2 = env2->prev) { + int need_wrap = 0; + for (jl_typeenv_t *env3 = wrapped; env3 != NULL && need_wrap == 0; env3 = env3->prev) { + if (env3->var == env2->var) + need_wrap = -1; + else if (jl_has_typevar(env3->var->lb, env2->var) || jl_has_typevar(env3->var->ub, env2->var)) + need_wrap = 1; + } + need_wrap = need_wrap == 0 ? jl_has_typevar(x, env2->var) : + need_wrap == -1 ? 0 : 1; + if (need_wrap) { + count++; + jl_typeenv_t *newenv = (jl_typeenv_t*)alloca(sizeof(jl_typeenv_t)); + newenv->var = env2->var; + newenv->val = NULL; + newenv->prev = wrapped; + wrapped = newenv; + } + } + return count; +} + +static int obvious_subtype_msp(jl_value_t *x, jl_value_t *y, jl_value_t *y0, int *subtype, int wrapx, int wrapy) +{ + if (wrapx != 0 || wrapy != 0) { + int wrap_count = wrapx - wrapy; + while (wrap_count > 0 && jl_is_unionall(y)) + { + y = ((jl_unionall_t*)y)->body; + wrap_count--; + } + while (wrap_count < 0 && jl_is_unionall(x)) + { + x = ((jl_unionall_t*)x)->body; + wrap_count++; + } + if (wrap_count > 0) { + if (obvious_subtype(jl_unwrap_unionall(x), y, y0, subtype) && !*subtype) + return 1; + return 0; + } + } + return obvious_subtype(x, y, y0, subtype); +} static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0, jl_typeenv_t *env) { @@ -4752,12 +4802,14 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0, a = b; b = temp; } + int wrapa = count_missing_wrap(a, env); + int wrapb = count_missing_wrap(b, env); // first check if a <: b has an obvious answer int subtype_ab = 2; if (b == (jl_value_t*)jl_any_type || a == jl_bottom_type) { subtype_ab = 1; } - else if (obvious_subtype(a, b, b0, &subtype_ab)) { + else if (obvious_subtype_msp(a, b, b0, &subtype_ab, wrapa, wrapb)) { #ifdef NDEBUG if (subtype_ab == 0) return 0; @@ -4771,7 +4823,7 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0, if (a == (jl_value_t*)jl_any_type || b == jl_bottom_type) { subtype_ba = 1; } - else if (obvious_subtype(b, a, a0, &subtype_ba)) { + else if (obvious_subtype_msp(b, a, a0, &subtype_ba, wrapb, wrapa)) { #ifdef NDEBUG if (subtype_ba == 0) return 0; @@ -4836,7 +4888,9 @@ static int sub_msp(jl_value_t *x, jl_value_t *y, jl_value_t *y0, jl_typeenv_t *e return 1; } int obvious_sub = 2; - if (obvious_subtype(x, y, y0, &obvious_sub)) { + int wrapx = count_missing_wrap(x, env); + int wrapy = count_missing_wrap(y, env); + if (obvious_subtype_msp(x, y, y0, &obvious_sub, wrapx, wrapy)) { #ifdef NDEBUG return obvious_sub; #endif diff --git a/test/specificity.jl b/test/specificity.jl index 816a59f63e193..13688036c2047 100644 --- a/test/specificity.jl +++ b/test/specificity.jl @@ -316,3 +316,14 @@ end @test args_morespecific(Tuple{typeof(Union{}), Any}, Tuple{Any, Type{Union{}}}) @test args_morespecific(Tuple{Type{Union{}}, Type{Union{}}, Any}, Tuple{Type{Union{}}, Any, Type{Union{}}}) @test args_morespecific(Tuple{Type{Union{}}, Type{Union{}}, Any, Type{Union{}}}, Tuple{Type{Union{}}, Any, Type{Union{}}, Type{Union{}}}) + +# requires assertions enabled +let root = NTuple + N = root.var + T = root.body.var + x1 = root.body.body + x2 = Dict{T,Tuple{N}} + A = UnionAll(N, UnionAll(T, Tuple{Union{x1, x2}})) + B = Tuple{Union{UnionAll(N, UnionAll(T, x1)), UnionAll(N, UnionAll(T, x2))}} + @ccall jl_type_morespecific_no_subtype(A::Any, B::Any)::Cint +end From 9be0976f1a740dcae9f31f3405422c56baa66dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 29 Jul 2024 22:26:14 +0100 Subject: [PATCH 089/206] Add PGO/LTO/BOLT Makefiles to NEWS.md and HISTORY.md (#55282) Ref: https://github.com/JuliaLang/julia/pull/54107#issuecomment-2252826710. If accepted, I'll add the NEWS.md entry for PGO/LTO in the release-1.11 branch too. --- HISTORY.md | 3 +++ NEWS.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 66f856143711c..7fb01c7e9a0e9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -79,6 +79,8 @@ Multi-threading changes Build system changes -------------------- +* There is a new `Makefile` to build Julia and LLVM using the profile-guided and link-time optimizations (PGO and LTO) strategies, see `contrib/pgo-lto/Makefile` ([#45641]). + New library functions --------------------- @@ -414,6 +416,7 @@ Deprecated or removed [#44247]: https://github.com/JuliaLang/julia/issues/44247 [#45164]: https://github.com/JuliaLang/julia/issues/45164 [#45396]: https://github.com/JuliaLang/julia/issues/45396 +[#45641]: https://github.com/JuliaLang/julia/issues/45641 [#45962]: https://github.com/JuliaLang/julia/issues/45962 [#46196]: https://github.com/JuliaLang/julia/issues/46196 [#46372]: https://github.com/JuliaLang/julia/issues/46372 diff --git a/NEWS.md b/NEWS.md index c98fa6b862b67..d09581e87e4b5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -63,6 +63,8 @@ Multi-threading changes Build system changes -------------------- +* There are new `Makefile`s to build Julia and LLVM using the Binary Optimization and Layout Tool (BOLT), see `contrib/bolt` and `contrib/pgo-lto-bolt` ([#54107]). + New library functions --------------------- From 20b3af3bb06e145607e5736acdcafb6d6b14341c Mon Sep 17 00:00:00 2001 From: Zentrik Date: Mon, 29 Jul 2024 22:52:53 +0100 Subject: [PATCH 090/206] Patch curl so that it builds without BinaryBuilder (#55290) Also removes nss flag as NSS seems to have been removed from curl and I think the flag was dropped in https://github.com/curl/curl/pull/11459/files. Fixes #55286. --- deps/curl.mk | 12 ++++++++++-- deps/patches/curl-8.6.0-build.patch | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 deps/patches/curl-8.6.0-build.patch diff --git a/deps/curl.mk b/deps/curl.mk index 444334b581fed..ae2830c3cd4f2 100644 --- a/deps/curl.mk +++ b/deps/curl.mk @@ -37,7 +37,7 @@ checksum-curl: $(SRCCACHE)/curl-$(CURL_VER).tar.bz2 # Disable....almost everything CURL_CONFIGURE_FLAGS := $(CONFIGURE_COMMON) \ --without-gnutls --without-libidn2 --without-librtmp \ - --without-nss --without-libpsl --without-libgsasl --without-fish-functions-dir \ + --without-libpsl --without-libgsasl --without-fish-functions-dir \ --disable-ares --disable-manual --disable-ldap --disable-ldaps --disable-static \ --without-gssapi --without-brotli # A few things we actually enable @@ -57,7 +57,15 @@ CURL_TLS_CONFIGURE_FLAGS := --with-mbedtls=$(build_prefix) endif CURL_CONFIGURE_FLAGS += $(CURL_TLS_CONFIGURE_FLAGS) -$(BUILDDIR)/curl-$(CURL_VER)/build-configured: $(SRCCACHE)/curl-$(CURL_VER)/source-extracted +$(SRCCACHE)/curl-$(CURL_VER)/curl-8.6.0-build.patch-applied: $(SRCCACHE)/curl-$(CURL_VER)/source-extracted + cd $(dir $@) && \ + patch -p1 -f < $(SRCDIR)/patches/curl-8.6.0-build.patch + echo 1 > $@ + +$(SRCCACHE)/curl-$(CURL_VER)/source-patched: $(SRCCACHE)/curl-$(CURL_VER)/curl-8.6.0-build.patch-applied + echo 1 > $@ + +$(BUILDDIR)/curl-$(CURL_VER)/build-configured: $(SRCCACHE)/curl-$(CURL_VER)/source-patched mkdir -p $(dir $@) cd $(dir $@) && \ $(dir $<)/configure $(CURL_CONFIGURE_FLAGS) \ diff --git a/deps/patches/curl-8.6.0-build.patch b/deps/patches/curl-8.6.0-build.patch new file mode 100644 index 0000000000000..827b02808d505 --- /dev/null +++ b/deps/patches/curl-8.6.0-build.patch @@ -0,0 +1,23 @@ +From 5cc2b016c36aaf5a08e2feb7c068fca5bb0a8052 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 5 Feb 2024 15:22:08 +0100 +Subject: [PATCH] md4: include strdup.h for the memdup proto + +Reported-by: Erik Schnetter +Fixes #12849 +Closes #12863 +--- + lib/md4.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/md4.c b/lib/md4.c +index 067c211e420afd..58dd1166cf924f 100644 +--- a/lib/md4.c ++++ b/lib/md4.c +@@ -28,6 +28,7 @@ + + #include + ++#include "strdup.h" + #include "curl_md4.h" + #include "warnless.h" From f979ee99544f850664efc44d4b2c8c35f5a3155c Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Tue, 30 Jul 2024 07:29:18 +0800 Subject: [PATCH 091/206] Fix `sum(bc::Broadcasted; dims = 1, init = 0)` (#43736) This PR make `has_fast_linear_indexing` rely on `IndexStyle`/`ndims` to fix `mapreduce` for `Broadcasted` with `dim > 1`. Before: ```julia julia> a = randn(100,100); julia> bc = Broadcast.instantiate(Base.broadcasted(+,a,a)); julia> sum(bc,dims = 1,init = 0.0) == sum(collect(bc), dims = 1) ERROR: MethodError: no method matching LinearIndices(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}, typeof(+), Tuple{Matrix{Float64}, Matrix{Float64}}}) ``` After: ```julia julia> sum(bc,dims = 1,init = 0.0) == sum(collect(bc), dims = 1) true ``` This should extend the optimized fallback to more `AbstractArray`. (e.g. `SubArray`) Test added. --- base/reducedim.jl | 7 ++----- test/broadcast.jl | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/base/reducedim.jl b/base/reducedim.jl index 1d74fb0d498a5..4ab786804ff4c 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -196,11 +196,8 @@ end ## generic (map)reduction -has_fast_linear_indexing(a::AbstractArrayOrBroadcasted) = false -has_fast_linear_indexing(a::Array) = true -has_fast_linear_indexing(::Union{Number,Ref,AbstractChar}) = true # 0d objects, for Broadcasted -has_fast_linear_indexing(bc::Broadcast.Broadcasted) = - all(has_fast_linear_indexing, bc.args) +has_fast_linear_indexing(a::AbstractArrayOrBroadcasted) = IndexStyle(a) === IndexLinear() +has_fast_linear_indexing(a::AbstractVector) = true function check_reducedims(R, A) # Check whether R has compatible dimensions w.r.t. A for reduction diff --git a/test/broadcast.jl b/test/broadcast.jl index e4309bf81419f..b2232258744ac 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -979,6 +979,10 @@ end @test sum(bc, dims=1, init=0) == [5] bc = Broadcast.instantiate(Broadcast.broadcasted(*, ['a','b'], 'c')) @test prod(bc, dims=1, init="") == ["acbc"] + + a = rand(-10:10,32,4); b = rand(-10:10,32,4) + bc = Broadcast.instantiate(Broadcast.broadcasted(+,a,b)) + @test sum(bc; dims = 1, init = 0.0) == sum(collect(bc); dims = 1, init = 0.0) end # treat Pair as scalar: From fb6b7904b7bfd7b22d4b1b6779cced428e940ca0 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Tue, 30 Jul 2024 08:04:09 +0800 Subject: [PATCH 092/206] typeintersect: fix bounds merging during inner `intersect_all` (#55299) This PR reverts the optimization from 748149efb3b43e732eab8e9e4276e0ee2bcfa65b (part of #48167), while keeping the fix for merging occurs_inv/occurs_cov, as that optimzation makes no sense especially when typevar occurs both inside and outside the inner intersection. Close #55206 --- src/subtype.c | 190 ++++++++++++++---------------------------------- test/subtype.jl | 43 +++++++++-- 2 files changed, 92 insertions(+), 141 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index e503b49811503..6f6520c5df980 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -65,7 +65,6 @@ typedef struct jl_varbinding_t { jl_value_t *lb; jl_value_t *ub; int8_t right; // whether this variable came from the right side of `A <: B` - int8_t occurs; // occurs in any position int8_t occurs_inv; // occurs in invariant position int8_t occurs_cov; // # of occurrences in covariant position int8_t concrete; // 1 if another variable has a constraint forcing this one to be concrete @@ -179,7 +178,7 @@ static int current_env_length(jl_stenv_t *e) typedef struct { int8_t *buf; int rdepth; - int8_t _space[32]; // == 8 * 4 + int8_t _space[24]; // == 8 * 3 jl_gcframe_t gcframe; jl_value_t *roots[24]; // == 8 * 3 } jl_savedenv_t; @@ -208,7 +207,6 @@ static void re_save_env(jl_stenv_t *e, jl_savedenv_t *se, int root) roots[i++] = v->ub; roots[i++] = (jl_value_t*)v->innervars; } - se->buf[j++] = v->occurs; se->buf[j++] = v->occurs_inv; se->buf[j++] = v->occurs_cov; se->buf[j++] = v->max_offset; @@ -243,7 +241,7 @@ static void alloc_env(jl_stenv_t *e, jl_savedenv_t *se, int root) ct->gcstack = &se->gcframe; } } - se->buf = (len > 8 ? (int8_t*)malloc_s(len * 4) : se->_space); + se->buf = (len > 8 ? (int8_t*)malloc_s(len * 3) : se->_space); #ifdef __clang_gcanalyzer__ memset(se->buf, 0, len * 3); #endif @@ -290,7 +288,6 @@ static void restore_env(jl_stenv_t *e, jl_savedenv_t *se, int root) JL_NOTSAFEPO v->ub = roots[i++]; v->innervars = (jl_array_t*)roots[i++]; } - v->occurs = se->buf[j++]; v->occurs_inv = se->buf[j++]; v->occurs_cov = se->buf[j++]; v->max_offset = se->buf[j++]; @@ -302,15 +299,6 @@ static void restore_env(jl_stenv_t *e, jl_savedenv_t *se, int root) JL_NOTSAFEPO memset(&e->envout[e->envidx], 0, (e->envsz - e->envidx)*sizeof(void*)); } -static void clean_occurs(jl_stenv_t *e) -{ - jl_varbinding_t *v = e->vars; - while (v) { - v->occurs = 0; - v = v->prev; - } -} - #define flip_offset(e) ((e)->Loffset *= -1) // type utilities @@ -599,6 +587,8 @@ static jl_value_t *simple_meet(jl_value_t *a, jl_value_t *b, int overesi) static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); +#define has_next_union_state(e, R) ((((R) ? &(e)->Runions : &(e)->Lunions)->more) != 0) + static int next_union_state(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT { jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; @@ -679,8 +669,6 @@ static int subtype_left_var(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int par // of determining whether the variable is concrete. static void record_var_occurrence(jl_varbinding_t *vb, jl_stenv_t *e, int param) JL_NOTSAFEPOINT { - if (vb != NULL) - vb->occurs = 1; if (vb != NULL && param) { // saturate counters at 2; we don't need values bigger than that if (param == 2 && e->invdepth > vb->depth0) { @@ -915,7 +903,7 @@ static jl_unionall_t *unalias_unionall(jl_unionall_t *u, jl_stenv_t *e) static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8_t R, int param) { u = unalias_unionall(u, e); - jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, 0, 0, 0, 0, 0, 0, 0, 0, 0, + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, 0, 0, 0, 0, 0, 0, 0, 0, e->invdepth, NULL, e->vars }; JL_GC_PUSH4(&u, &vb.lb, &vb.ub, &vb.innervars); e->vars = &vb; @@ -3312,7 +3300,7 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_ { jl_value_t *res = NULL; jl_savedenv_t se; - jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, 0, 0, 0, 0, 0, 0, 0, 0, 0, + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, 0, 0, 0, 0, 0, 0, 0, 0, e->invdepth, NULL, e->vars }; JL_GC_PUSH4(&res, &vb.lb, &vb.ub, &vb.innervars); save_env(e, &se, 1); @@ -3341,7 +3329,7 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_ vb.ub = vb.var->ub; } restore_env(e, &se, vb.constraintkind == 1 ? 1 : 0); - vb.occurs = vb.occurs_cov = vb.occurs_inv = 0; + vb.occurs_cov = vb.occurs_inv = 0; res = intersect_unionall_(t, u, e, R, param, &vb); } } @@ -4042,79 +4030,12 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa return jl_bottom_type; } -static int merge_env(jl_stenv_t *e, jl_savedenv_t *se, int count) +static int merge_env(jl_stenv_t *e, jl_savedenv_t *me, jl_savedenv_t *se, int count) { - if (count == 0) - alloc_env(e, se, 1); - jl_value_t **roots = NULL; - int nroots = 0; - if (se->gcframe.nroots == JL_GC_ENCODE_PUSHARGS(1)) { - jl_svec_t *sv = (jl_svec_t*)se->roots[0]; - assert(jl_is_svec(sv)); - roots = jl_svec_data(sv); - nroots = jl_svec_len(sv); - } - else { - roots = se->roots; - nroots = se->gcframe.nroots >> 2; - } - int m = 0, n = 0; - jl_varbinding_t *v = e->vars; - while (v != NULL) { - if (count == 0) { - // need to initialize this - se->buf[m] = 0; - se->buf[m+1] = 0; - se->buf[m+2] = 0; - se->buf[m+3] = v->max_offset; - } - jl_value_t *b1, *b2; - if (v->occurs) { - // only merge lb/ub if this var occurs. - b1 = roots[n]; - JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame - b2 = v->lb; - JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots - roots[n] = b1 ? simple_meet(b1, b2, 0) : b2; - b1 = roots[n+1]; - JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame - b2 = v->ub; - JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots - roots[n+1] = b1 ? simple_join(b1, b2) : b2; - // record the meeted vars. - se->buf[m] = 1; - } - // `innervars` might be re-sorted inside `finish_unionall`. - // We'd better always merge it. - b1 = roots[n+2]; - JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame - b2 = (jl_value_t*)v->innervars; - JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots - if (b2 && b1 != b2) { - if (b1) - jl_array_ptr_1d_append((jl_array_t*)b1, (jl_array_t*)b2); - else - roots[n+2] = b2; - } - // always merge occurs_inv/cov by max (never decrease) - if (v->occurs_inv > se->buf[m+1]) - se->buf[m+1] = v->occurs_inv; - if (v->occurs_cov > se->buf[m+2]) - se->buf[m+2] = v->occurs_cov; - // always merge max_offset by min - if (!v->intersected && v->max_offset < se->buf[m+3]) - se->buf[m+3] = v->max_offset; - m = m + 4; - n = n + 3; - v = v->prev; + if (count == 0) { + save_env(e, me, 1); + return 1; } - assert(n == nroots); (void)nroots; - return count + 1; -} - -// merge untouched vars' info. -static void final_merge_env(jl_stenv_t *e, jl_savedenv_t *me, jl_savedenv_t *se) -{ jl_value_t **merged = NULL; jl_value_t **saved = NULL; int nroots = 0; @@ -4136,47 +4057,49 @@ static void final_merge_env(jl_stenv_t *e, jl_savedenv_t *me, jl_savedenv_t *se) } assert(nroots == current_env_length(e) * 3); assert(nroots % 3 == 0); - for (int n = 0, m = 0; n < nroots; n += 3, m += 4) { - if (merged[n] == NULL) - merged[n] = saved[n]; - if (merged[n+1] == NULL) - merged[n+1] = saved[n+1]; - jl_value_t *b1, *b2; + int m = 0, n = 0; + jl_varbinding_t *v = e->vars; + while (v != NULL) { + jl_value_t *b0, *b1, *b2; + // merge `lb` + b0 = saved[n]; + b1 = merged[n]; + JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame + b2 = v->lb; + JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots + merged[n] = (b1 == b0 || b2 == b0) ? b0 : simple_meet(b1, b2, 0); + // merge `ub` + b0 = saved[n+1]; + b1 = merged[n+1]; + JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame + b2 = v->ub; + JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots + merged[n+1] = (b1 == b0 || b2 == b0) ? b0 : simple_join(b1, b2); + // merge `innervars` b1 = merged[n+2]; JL_GC_PROMISE_ROOTED(b1); // clang-sagc doesn't know this came from our GC frame - b2 = saved[n+2]; - JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know this came from our GC frame + b2 = (jl_value_t*)v->innervars; + JL_GC_PROMISE_ROOTED(b2); // clang-sagc doesn't know the fields of this are stack GC roots if (b2 && b1 != b2) { if (b1) jl_array_ptr_1d_append((jl_array_t*)b1, (jl_array_t*)b2); else merged[n+2] = b2; } - me->buf[m] |= se->buf[m]; - } -} - -static void expand_local_env(jl_stenv_t *e, jl_value_t *res) -{ - jl_varbinding_t *v = e->vars; - // Here we pull in some typevar missed in fastpath. - while (v != NULL) { - v->occurs = v->occurs || jl_has_typevar(res, v->var); - assert(v->occurs == 0 || v->occurs == 1); - v = v->prev; - } - v = e->vars; - while (v != NULL) { - if (v->occurs == 1) { - jl_varbinding_t *v2 = e->vars; - while (v2 != NULL) { - if (v2 != v && v2->occurs == 0) - v2->occurs = -(jl_has_typevar(v->lb, v2->var) || jl_has_typevar(v->ub, v2->var)); - v2 = v2->prev; - } - } + // merge occurs_inv/cov by max (never decrease) + if (v->occurs_inv > me->buf[m]) + me->buf[m] = v->occurs_inv; + if (v->occurs_cov > me->buf[m+1]) + me->buf[m+1] = v->occurs_cov; + // merge max_offset by min + if (!v->intersected && v->max_offset < me->buf[m+2]) + me->buf[m+2] = v->max_offset; + m = m + 3; + n = n + 3; v = v->prev; } + assert(n == nroots); (void)nroots; + return count + 1; } static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) @@ -4189,12 +4112,9 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) jl_savedenv_t se, me; save_env(e, &se, 1); int niter = 0, total_iter = 0; - clean_occurs(e); is[0] = intersect(x, y, e, 0); // root - if (is[0] != jl_bottom_type) { - expand_local_env(e, is[0]); - niter = merge_env(e, &me, niter); - } + if (is[0] != jl_bottom_type) + niter = merge_env(e, &me, &se, niter); restore_env(e, &se, 1); while (next_union_state(e, 1)) { if (e->emptiness_only && is[0] != jl_bottom_type) @@ -4202,12 +4122,9 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) e->Runions.depth = 0; e->Runions.more = 0; - clean_occurs(e); is[1] = intersect(x, y, e, 0); - if (is[1] != jl_bottom_type) { - expand_local_env(e, is[1]); - niter = merge_env(e, &me, niter); - } + if (is[1] != jl_bottom_type) + niter = merge_env(e, &me, &se, niter); restore_env(e, &se, 1); if (is[0] == jl_bottom_type) is[0] = is[1]; @@ -4216,13 +4133,18 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) is[0] = jl_type_union(is, 2); } total_iter++; - if (niter > 4 || total_iter > 400000) { + if (has_next_union_state(e, 1) && (niter > 4 || total_iter > 400000)) { is[0] = y; + // we give up precise intersection here, just restore the saved env + restore_env(e, &se, 1); + if (niter > 0) { + free_env(&me); + niter = 0; + } break; } } if (niter) { - final_merge_env(e, &me, &se); restore_env(e, &me, 1); free_env(&me); } @@ -4707,7 +4629,7 @@ static jl_value_t *_widen_diagonal(jl_value_t *t, jl_varbinding_t *troot) { static jl_value_t *widen_diagonal(jl_value_t *t, jl_unionall_t *u, jl_varbinding_t *troot) { - jl_varbinding_t vb = { u->var, NULL, NULL, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, troot }; + jl_varbinding_t vb = { u->var, NULL, NULL, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, troot }; jl_value_t *nt; JL_GC_PUSH2(&vb.innervars, &nt); if (jl_is_unionall(u->body)) diff --git a/test/subtype.jl b/test/subtype.jl index c26f4fc9d30e2..af023ef8ca72f 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2380,12 +2380,41 @@ let S = Tuple{T2, V2} where {T2, N2, V2<:(Array{S2, N2} where {S2 <: T2})}, @testintersect(S, T, !Union{}) end -# A simple case which has a small local union. -# make sure the env is not widened too much when we intersect(Int8, Int8). -struct T48006{A1,A2,A3} end -@testintersect(Tuple{T48006{Float64, Int, S1}, Int} where {F1<:Real, S1<:Union{Int8, Val{F1}}}, - Tuple{T48006{F2, I, S2}, I} where {F2<:Real, I<:Int, S2<:Union{Int8, Val{F2}}}, - Tuple{T48006{Float64, Int, S1}, Int} where S1<:Union{Val{Float64}, Int8}) +let S = Dict{Int, S1} where {F1, S1<:Union{Int8, Val{F1}}}, + T = Dict{F2, S2} where {F2, S2<:Union{Int8, Val{F2}}} + @test_broken typeintersect(S, T) == Dict{Int, S} where S<:Union{Val{Int}, Int8} + @test typeintersect(T, S) == Dict{Int, S} where S<:Union{Val{Int}, Int8} +end + +# Ensure inner `intersect_all` never under-esitimate. +let S = Tuple{F1, Dict{Int, S1}} where {F1, S1<:Union{Int8, Val{F1}}}, + T = Tuple{Any, Dict{F2, S2}} where {F2, S2<:Union{Int8, Val{F2}}} + @test Tuple{Nothing, Dict{Int, Int8}} <: S + @test Tuple{Nothing, Dict{Int, Int8}} <: T + @test Tuple{Nothing, Dict{Int, Int8}} <: typeintersect(S, T) + @test Tuple{Nothing, Dict{Int, Int8}} <: typeintersect(T, S) +end + +let S = Tuple{F1, Val{S1}} where {F1, S1<:Dict{F1}} + T = Tuple{Any, Val{S2}} where {F2, S2<:Union{map(T->Dict{T}, Base.BitInteger_types)...}} + ST = typeintersect(S, T) + TS = typeintersect(S, T) + for U in Base.BitInteger_types + @test Tuple{U, Val{Dict{U,Nothing}}} <: S + @test Tuple{U, Val{Dict{U,Nothing}}} <: T + @test Tuple{U, Val{Dict{U,Nothing}}} <: ST + @test Tuple{U, Val{Dict{U,Nothing}}} <: TS + end +end + +#issue 55206 +struct T55206{A,B<:Complex{A},C<:Union{Dict{Nothing},Dict{A}}} end +@testintersect(T55206, T55206{<:Any,<:Any,<:Dict{Nothing}}, T55206{A,<:Complex{A},<:Dict{Nothing}} where {A}) +@testintersect( + Tuple{Dict{Int8, Int16}, Val{S1}} where {F1, S1<:AbstractSet{F1}}, + Tuple{Dict{T1, T2}, Val{S2}} where {T1, T2, S2<:Union{Set{T1},Set{T2}}}, + Tuple{Dict{Int8, Int16}, Val{S1}} where {S1<:Union{Set{Int8},Set{Int16}}} +) f48167(::Type{Val{L2}}, ::Type{Union{Val{L1}, Set{R}}}) where {L1, R, L2<:L1} = 1 f48167(::Type{Val{L1}}, ::Type{Union{Val{L2}, Set{R}}}) where {L1, R, L2<:L1} = 2 @@ -2554,7 +2583,7 @@ end let T = Tuple{Union{Type{T}, Type{S}}, Union{Val{T}, Val{S}}, Union{Val{T}, S}} where T<:Val{A} where A where S<:Val, S = Tuple{Type{T}, T, Val{T}} where T<:(Val{S} where S<:Val) # optimal = Union{}? - @test typeintersect(T, S) == Tuple{Type{A}, Union{Val{A}, Val{S} where S<:Union{Val, A}, Val{x} where x<:Val, Val{x} where x<:Union{Val, A}}, Val{A}} where A<:(Val{S} where S<:Val) + @test typeintersect(T, S) == Tuple{Type{T}, Union{Val{T}, Val{S}}, Val{T}} where {S<:Val, T<:Val} @test typeintersect(S, T) == Tuple{Type{T}, Union{Val{T}, Val{S}}, Val{T}} where {T<:Val, S<:(Union{Val{A}, Val} where A)} end From e0f2e295091dc293561a15d302d22bf96d810018 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 29 Jul 2024 22:10:30 -0700 Subject: [PATCH 093/206] Add `lbt_forwarded_funcs()` to debug LBT forwarding issues (#55302) It can be very helpful, when struggling with LBT forwarding, to see what functions were actually forwarded to a new library. This utility function makes it easy to query which functions are forwarded to that library. --- stdlib/LinearAlgebra/src/lbt.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/stdlib/LinearAlgebra/src/lbt.jl b/stdlib/LinearAlgebra/src/lbt.jl index 02b4411566290..606ddedbe1343 100644 --- a/stdlib/LinearAlgebra/src/lbt.jl +++ b/stdlib/LinearAlgebra/src/lbt.jl @@ -284,6 +284,25 @@ function lbt_find_backing_library(symbol_name, interface::Symbol; end +""" + lbt_forwarded_funcs(config::LBTConfig, lib::LBTLibraryInfo) + +Given a backing library `lib`, return the list of all functions that are +forwarded to that library, as a vector of `String`s. +""" +function lbt_forwarded_funcs(config::LBTConfig, lib::LBTLibraryInfo) + forwarded_funcs = String[] + for (symbol_idx, symbol) in enumerate(config.exported_symbols) + forward_byte_offset = div(symbol_idx - 1, 8) + forward_byte_mask = 1 << mod(symbol_idx - 1, 8) + if lib.active_forwards[forward_byte_offset+1] & forward_byte_mask != 0x00 + push!(forwarded_funcs, symbol) + end + end + return forwarded_funcs +end + + ## NOTE: Manually setting forwards is referred to as the 'footgun API'. It allows truly ## bizarre and complex setups to be created. If you run into strange errors while using ## it, the first thing you should ask yourself is whether you've set things up properly. From 58623010fdcb71b54f15c35b370f6b0c54134220 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 30 Jul 2024 11:33:35 +0200 Subject: [PATCH 094/206] inference: Allow any non-nothing source in ci_has_source for extern owner (#55294) In updating DAECompiler to the new engine API, I was running some trouble, because the source it produces is not a `CodeInfo` or a `String` (which is fine because it has a non-nothing `owner`). Adjust the test to consider any non-nothing value in .inferred valid source (at least for non-nothing CI owners). --- base/compiler/typeinfer.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 77547a5b30877..85bdd881042dc 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -1118,7 +1118,7 @@ const SOURCE_MODE_FORCE_SOURCE = 0x2 function ci_has_source(code::CodeInstance) inf = @atomic :monotonic code.inferred - return isa(inf, CodeInfo) || isa(inf, String) + return code.owner === nothing ? (isa(inf, CodeInfo) || isa(inf, String)) : inf !== nothing end """ From 5d80593475da4afd5a08cce5d271484cfc567801 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 30 Jul 2024 11:34:18 +0200 Subject: [PATCH 095/206] inference: Switch to typename-based override for constprop heuristics (#55288) As mentioned in #55271, I'd like to get rid of `istopfunction` for various reasons. Rather than hardcoding constprop overrides based on binding name, this annotates the relevant TypeNames (like the existing `max_methods` override), removing the binding lookups from inference. --- base/Base.jl | 3 +++ base/abstractarray.jl | 4 ++++ base/boot.jl | 6 ++++++ base/compiler/abstractinterpretation.jl | 13 +++++-------- base/essentials.jl | 15 ++++++++++++++- src/datatype.c | 1 + src/jltypes.c | 10 ++++++---- src/julia.h | 1 + 8 files changed, 40 insertions(+), 13 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index a47a3a5c6459d..221ab90d8d2a9 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -53,6 +53,9 @@ function setproperty!(x, f::Symbol, v) return setfield!(x, f, val) end +typeof(function getproperty end).name.constprop_heuristic = Core.FORCE_CONST_PROP +typeof(function setproperty! end).name.constprop_heuristic = Core.FORCE_CONST_PROP + dotgetproperty(x, f) = getproperty(x, f) getproperty(x::Module, f::Symbol, order::Symbol) = (@inline; getglobal(x, f, order)) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 8d60a2443ba47..2fbae2c423196 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1264,6 +1264,10 @@ function _memory_offset(x::AbstractArray, I::Vararg{Any,N}) where {N} return sum(map((i, s, o)->s*(i-o), J, strides(x), Tuple(first(CartesianIndices(x)))))*elsize(x) end +## Special constprop heuristics for getindex/setindex +typename(typeof(function getindex end)).constprop_heuristic = Core.ARRAY_INDEX_HEURISTIC +typename(typeof(function setindex! end)).constprop_heuristic = Core.ARRAY_INDEX_HEURISTIC + ## Approach: # We only define one fallback method on getindex for all argument types. # That dispatches to an (inlined) internal _getindex function, where the goal is diff --git a/base/boot.jl b/base/boot.jl index 1481928b319b7..3afb0e563483d 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -1012,6 +1012,12 @@ const check_top_bit = check_sign_bit EnterNode(old::EnterNode, new_dest::Int) = isdefined(old, :scope) ? EnterNode(new_dest, old.scope) : EnterNode(new_dest) +# typename(_).constprop_heuristic +const FORCE_CONST_PROP = 0x1 +const ARRAY_INDEX_HEURISTIC = 0x2 +const ITERATE_HEURISTIC = 0x3 +const SAMETYPE_HEURISTIC = 0x4 + include(Core, "optimized_generics.jl") ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 3b658534b5d35..98ae3486e59ee 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1158,16 +1158,16 @@ end function force_const_prop(interp::AbstractInterpreter, @nospecialize(f), method::Method) return is_aggressive_constprop(method) || InferenceParams(interp).aggressive_constant_propagation || - istopfunction(f, :getproperty) || - istopfunction(f, :setproperty!) + typename(typeof(f)).constprop_heuristic === Core.FORCE_CONST_PROP end function const_prop_function_heuristic(interp::AbstractInterpreter, @nospecialize(f), arginfo::ArgInfo, all_overridden::Bool, sv::AbsIntState) argtypes = arginfo.argtypes + heuristic = typename(typeof(f)).constprop_heuristic if length(argtypes) > 1 𝕃ᵢ = typeinf_lattice(interp) - if istopfunction(f, :getindex) || istopfunction(f, :setindex!) + if heuristic === Core.ARRAY_INDEX_HEURISTIC arrty = argtypes[2] # don't propagate constant index into indexing of non-constant array if arrty isa Type && arrty <: AbstractArray && !issingletontype(arrty) @@ -1180,17 +1180,14 @@ function const_prop_function_heuristic(interp::AbstractInterpreter, @nospecializ elseif ⊑(𝕃ᵢ, arrty, Array) || ⊑(𝕃ᵢ, arrty, GenericMemory) return false end - elseif istopfunction(f, :iterate) + elseif heuristic === Core.ITERATE_HEURISTIC itrty = argtypes[2] if ⊑(𝕃ᵢ, itrty, Array) || ⊑(𝕃ᵢ, itrty, GenericMemory) return false end end end - if !all_overridden && (istopfunction(f, :+) || istopfunction(f, :-) || istopfunction(f, :*) || - istopfunction(f, :(==)) || istopfunction(f, :!=) || - istopfunction(f, :<=) || istopfunction(f, :>=) || istopfunction(f, :<) || istopfunction(f, :>) || - istopfunction(f, :<<) || istopfunction(f, :>>)) + if !all_overridden && heuristic === Core.SAMETYPE_HEURISTIC # it is almost useless to inline the op when all the same type, # but highly worthwhile to inline promote of a constant length(argtypes) > 2 || return false diff --git a/base/essentials.jl b/base/essentials.jl index c4ce6dfbd4e3a..238b4a393c87c 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -389,7 +389,7 @@ julia> nameof(Base.Broadcast) """ nameof(m::Module) = (@_total_meta; ccall(:jl_module_name, Ref{Symbol}, (Any,), m)) -function iterate end +typeof(function iterate end).name.constprop_heuristic = Core.ITERATE_HEURISTIC """ convert(T, x) @@ -1245,3 +1245,16 @@ that is whether it has an `iterate` method or not. function isiterable(T)::Bool return hasmethod(iterate, Tuple{T}) end + +# Special constprop heuristics for various binary opes +typename(typeof(function + end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function - end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function * end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function == end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function != end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function <= end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function >= end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function < end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function > end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function << end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC +typename(typeof(function >> end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC diff --git a/src/datatype.c b/src/datatype.c index d5ee3eb7074c3..e7ee15a63f56e 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -83,6 +83,7 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu tn->atomicfields = NULL; tn->constfields = NULL; tn->max_methods = 0; + tn->constprop_heustic = 0; return tn; } diff --git a/src/jltypes.c b/src/jltypes.c index 10b8bc937939e..fe490d2c45acb 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2895,25 +2895,26 @@ void jl_init_types(void) JL_GC_DISABLED jl_typename_type->name->mt = jl_nonfunction_mt; jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; - jl_typename_type->name->n_uninitialized = 15 - 2; - jl_typename_type->name->names = jl_perm_symsvec(15, "name", "module", + jl_typename_type->name->n_uninitialized = 16 - 2; + jl_typename_type->name->names = jl_perm_symsvec(16, "name", "module", "names", "atomicfields", "constfields", "wrapper", "Typeofwrapper", "cache", "linearcache", "mt", "partial", "hash", "n_uninitialized", "flags", // "abstract", "mutable", "mayinlinealloc", - "max_methods"); + "max_methods", "constprop_heuristic"); const static uint32_t typename_constfields[1] = { 0x00003a27 }; // (1<<0)|(1<<1)|(1<<2)|(1<<5)|(1<<9)|(1<<11)|(1<<12)|(1<<13) ; TODO: put back (1<<3)|(1<<4) in this list const static uint32_t typename_atomicfields[1] = { 0x00000180 }; // (1<<7)|(1<<8) jl_typename_type->name->constfields = typename_constfields; jl_typename_type->name->atomicfields = typename_atomicfields; jl_precompute_memoized_dt(jl_typename_type, 1); - jl_typename_type->types = jl_svec(15, jl_symbol_type, jl_any_type /*jl_module_type*/, + jl_typename_type->types = jl_svec(16, jl_symbol_type, jl_any_type /*jl_module_type*/, jl_simplevector_type, jl_any_type/*jl_voidpointer_type*/, jl_any_type/*jl_voidpointer_type*/, jl_type_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, jl_methtable_type, jl_any_type, jl_any_type /*jl_long_type*/, jl_any_type /*jl_int32_type*/, jl_any_type /*jl_uint8_type*/, + jl_any_type /*jl_uint8_type*/, jl_any_type /*jl_uint8_type*/); jl_methtable_type->name = jl_new_typename_in(jl_symbol("MethodTable"), core, 0, 1); @@ -3690,6 +3691,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_typename_type->types, 12, jl_int32_type); jl_svecset(jl_typename_type->types, 13, jl_uint8_type); jl_svecset(jl_typename_type->types, 14, jl_uint8_type); + jl_svecset(jl_typename_type->types, 15, jl_uint8_type); jl_svecset(jl_methtable_type->types, 4, jl_long_type); jl_svecset(jl_methtable_type->types, 5, jl_module_type); jl_svecset(jl_methtable_type->types, 6, jl_array_any_type); diff --git a/src/julia.h b/src/julia.h index 4574c47518d81..fe511c0ced1b0 100644 --- a/src/julia.h +++ b/src/julia.h @@ -531,6 +531,7 @@ typedef struct { uint8_t mayinlinealloc:1; uint8_t _reserved:5; uint8_t max_methods; // override for inference's max_methods setting (0 = no additional limit or relaxation) + uint8_t constprop_heustic; // override for inference's constprop heuristic } jl_typename_t; typedef struct { From 6bc2c551f825e9e98bca8db42626e8319003ecdd Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Tue, 30 Jul 2024 11:52:13 +0200 Subject: [PATCH 096/206] expand the doc string of `Union{}` (#55291) Give some characterizations/relevant terms from type theory. Clarify the, previously unexplained, usage of "bottom" in names. Cross-reference the subtyping doc string. Add an entry to the doctest, clarifying the last sentence. --- base/docs/basedocs.jl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index dd4c8d64e7d4e..2ed1bd98caa5c 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -3185,14 +3185,27 @@ Any """ Union{} -`Union{}`, the empty [`Union`](@ref) of types, is the type that has no values. That is, it has the defining -property `isa(x, Union{}) == false` for any `x`. `Base.Bottom` is defined as its alias and the type of `Union{}` -is `Core.TypeofBottom`. +`Union{}`, the empty [`Union`](@ref) of types, is the *bottom* type of the type system. That is, for each +`T::Type`, `Union{} <: T`. Also see the subtyping operator's documentation: [`<:`](@ref). + +As such, `Union{}` is also an *empty*/*uninhabited* type, meaning that it has no values. That is, for each `x`, +`isa(x, Union{}) == false`. + +`Base.Bottom` is defined as its alias and the type of `Union{}` is `Core.TypeofBottom`. # Examples ```jldoctest julia> isa(nothing, Union{}) false + +julia> Union{} <: Int +true + +julia> typeof(Union{}) === Core.TypeofBottom +true + +julia> isa(Union{}, Union) +false ``` """ kw"Union{}", Base.Bottom From 125bac4b9022ad9ff9c355e4810f94512739bac6 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 30 Jul 2024 18:58:09 +0900 Subject: [PATCH 097/206] inference: cleans up abstract interpretation code (#55308) - propagate the lattice that was not propagated - remove unused `condargs` allocation --- base/compiler/abstractinterpretation.jl | 45 ++++++++++++------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 98ae3486e59ee..22bc1cf046d98 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -17,7 +17,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), arginfo::ArgInfo, si::StmtInfo, @nospecialize(atype), sv::AbsIntState, max_methods::Int) 𝕃ₚ, 𝕃ᵢ = ipo_lattice(interp), typeinf_lattice(interp) - ⊑ₚ = ⊑(𝕃ₚ) + ⊑ₚ, ⊔ₚ, ⊔ᵢ = partialorder(𝕃ₚ), join(𝕃ₚ), join(𝕃ᵢ) if !should_infer_this_call(interp, sv) add_remark!(interp, sv, "Skipped call in throw block") # At this point we are guaranteed to end up throwing on this path, @@ -37,7 +37,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), (; valid_worlds, applicable, info) = matches update_valid_age!(sv, valid_worlds) napplicable = length(applicable) - rettype = excttype = Bottom + rettype = exctype = Bottom edges = MethodInstance[] conditionals = nothing # keeps refinement information of call argument types when the return type is boolean seen = 0 # number of signatures actually inferred @@ -96,8 +96,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), const_results[i] = const_result end edge === nothing || push!(edges, edge) - this_rt = tmerge(this_rt, rt) - this_exct = tmerge(this_exct, exct) + this_rt = this_rt ⊔ₚ rt + this_exct = this_exct ⊔ₚ exct if bail_out_call(interp, this_rt, sv) break end @@ -156,8 +156,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end @assert !(this_conditional isa Conditional || this_rt isa MustAlias) "invalid lattice element returned from inter-procedural context" seen += 1 - rettype = tmerge(𝕃ₚ, rettype, this_rt) - excttype = tmerge(𝕃ₚ, excttype, this_exct) + rettype = rettype ⊔ₚ this_rt + exctype = exctype ⊔ₚ this_exct if has_conditional(𝕃ₚ, sv) && this_conditional !== Bottom && is_lattice_bool(𝕃ₚ, rettype) && fargs !== nothing if conditionals === nothing conditionals = Any[Bottom for _ in 1:length(argtypes)], @@ -165,8 +165,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end for i = 1:length(argtypes) cnd = conditional_argtype(𝕃ᵢ, this_conditional, sig, argtypes, i) - conditionals[1][i] = tmerge(𝕃ᵢ, conditionals[1][i], cnd.thentype) - conditionals[2][i] = tmerge(𝕃ᵢ, conditionals[2][i], cnd.elsetype) + conditionals[1][i] = conditionals[1][i] ⊔ᵢ cnd.thentype + conditionals[2][i] = conditionals[2][i] ⊔ᵢ cnd.elsetype end end if bail_out_call(interp, InferenceLoopState(sig, rettype, all_effects), sv) @@ -182,14 +182,14 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), if seen ≠ napplicable # there is unanalyzed candidate, widen type and effects to the top - rettype = excttype = Any + rettype = exctype = Any all_effects = Effects() else if (matches isa MethodMatches ? (!matches.fullmatch || any_ambig(matches)) : (!all(matches.fullmatches) || any_ambig(matches))) # Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature. all_effects = Effects(all_effects; nothrow=false) - excttype = tmerge(𝕃ₚ, excttype, MethodError) + exctype = exctype ⊔ₚ MethodError end if sv isa InferenceState && fargs !== nothing slotrefinements = collect_slot_refinements(𝕃ᵢ, applicable, argtypes, fargs, sv) @@ -240,7 +240,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end end - return CallMeta(rettype, excttype, all_effects, info, slotrefinements) + return CallMeta(rettype, exctype, all_effects, info, slotrefinements) end struct FailedMethodMatch @@ -367,7 +367,7 @@ function from_interprocedural!(interp::AbstractInterpreter, @nospecialize(rt), s arginfo::ArgInfo, @nospecialize(maybecondinfo)) rt = collect_limitations!(rt, sv) if isa(rt, InterMustAlias) - rt = from_intermustalias(rt, arginfo, sv) + rt = from_intermustalias(typeinf_lattice(interp), rt, arginfo, sv) elseif is_lattice_bool(ipo_lattice(interp), rt) if maybecondinfo === nothing rt = widenconditional(rt) @@ -387,12 +387,13 @@ function collect_limitations!(@nospecialize(typ), sv::InferenceState) return typ end -function from_intermustalias(rt::InterMustAlias, arginfo::ArgInfo, sv::AbsIntState) +function from_intermustalias(𝕃ᵢ::AbstractLattice, rt::InterMustAlias, arginfo::ArgInfo, sv::AbsIntState) fargs = arginfo.fargs if fargs !== nothing && 1 ≤ rt.slot ≤ length(fargs) arg = ssa_def_slot(fargs[rt.slot], sv) if isa(arg, SlotNumber) argtyp = widenslotwrapper(arginfo.argtypes[rt.slot]) + ⊑ = partialorder(𝕃ᵢ) if rt.vartyp ⊑ argtyp return MustAlias(arg, rt.vartyp, rt.fldidx, rt.fldtyp) else @@ -412,6 +413,7 @@ function from_interconditional(𝕃ᵢ::AbstractLattice, @nospecialize(rt), sv:: alias = nothing thentype = elsetype = Any condval = maybe_extract_const_bool(rt) + ⊑, ⋤, ⊓ = partialorder(𝕃ᵢ), strictneqpartialorder(𝕃ᵢ), meet(𝕃ᵢ) for i in 1:length(fargs) # find the first argument which supports refinement, # and intersect all equivalent arguments with it @@ -447,24 +449,24 @@ function from_interconditional(𝕃ᵢ::AbstractLattice, @nospecialize(rt), sv:: end if condval === false thentype = Bottom - elseif ⊑(𝕃ᵢ, new_thentype, thentype) + elseif new_thentype ⊑ thentype thentype = new_thentype else - thentype = tmeet(𝕃ᵢ, thentype, widenconst(new_thentype)) + thentype = thentype ⊓ widenconst(new_thentype) end if condval === true elsetype = Bottom - elseif ⊑(𝕃ᵢ, new_elsetype, elsetype) + elseif new_elsetype ⊑ elsetype elsetype = new_elsetype else - elsetype = tmeet(𝕃ᵢ, elsetype, widenconst(new_elsetype)) + elsetype = elsetype ⊓ widenconst(new_elsetype) end - if (slot > 0 || condval !== false) && ⋤(𝕃ᵢ, thentype, old) + if (slot > 0 || condval !== false) && thentype ⋤ old slot = id if !(arg isa SlotNumber) && argtyp isa MustAlias alias = argtyp end - elseif (slot > 0 || condval !== true) && ⋤(𝕃ᵢ, elsetype, old) + elseif (slot > 0 || condval !== true) && elsetype ⋤ old slot = id if !(arg isa SlotNumber) && argtyp isa MustAlias alias = argtyp @@ -1368,7 +1370,6 @@ function matching_cache_argtypes(𝕃::AbstractLattice, mi::MethodInstance, given_argtypes = Vector{Any}(undef, length(argtypes)) def = mi.def::Method nargs = Int(def.nargs) - local condargs = nothing for i in 1:length(argtypes) argtype = argtypes[i] # forward `Conditional` if it conveys a constraint on any other argument @@ -1385,10 +1386,6 @@ function matching_cache_argtypes(𝕃::AbstractLattice, mi::MethodInstance, # TODO bail out here immediately rather than just propagating Bottom ? given_argtypes[i] = Bottom else - if condargs === nothing - condargs = Tuple{Int,Int}[] - end - push!(condargs, (slotid, i)) given_argtypes[i] = Conditional(slotid, thentype, elsetype) end continue From 686804d2c9f94e8b51de56320dabfaf6c630c17e Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 30 Jul 2024 13:29:24 +0000 Subject: [PATCH 098/206] LAPACK: Aggressive constprop to concretely infer syev!/syevd! (#55295) Currently, these are inferred as a 2-Tuple of possible return types depending on `jobz`, but since `jobz` is usually a constant, we may propagate it aggressively and have the return types inferred concretely. --- stdlib/LinearAlgebra/src/lapack.jl | 8 ++++---- stdlib/LinearAlgebra/test/lapack.jl | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index e9cfacfcd0cfd..6d1d871ed85fd 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -5329,7 +5329,7 @@ for (syev, syevr, syevd, sygvd, elty) in # INTEGER INFO, LDA, LWORK, N # * .. Array Arguments .. # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ) - function syev!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) + Base.@constprop :aggressive function syev!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) require_one_based_indexing(A) @chkvalidparam 1 jobz ('N', 'V') chkuplo(uplo) @@ -5429,7 +5429,7 @@ for (syev, syevr, syevd, sygvd, elty) in # * .. Array Arguments .. # INTEGER IWORK( * ) # DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ) - function syevd!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) + Base.@constprop :aggressive function syevd!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) require_one_based_indexing(A) @chkvalidparam 1 jobz ('N', 'V') chkstride1(A) @@ -5526,7 +5526,7 @@ for (syev, syevr, syevd, sygvd, elty, relty) in # * .. Array Arguments .. # DOUBLE PRECISION RWORK( * ), W( * ) # COMPLEX*16 A( LDA, * ), WORK( * ) - function syev!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) + Base.@constprop :aggressive function syev!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) require_one_based_indexing(A) @chkvalidparam 1 jobz ('N', 'V') chkstride1(A) @@ -5639,7 +5639,7 @@ for (syev, syevr, syevd, sygvd, elty, relty) in # INTEGER IWORK( * ) # DOUBLE PRECISION RWORK( * ) # COMPLEX*16 A( LDA, * ), WORK( * ) - function syevd!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) + Base.@constprop :aggressive function syevd!(jobz::AbstractChar, uplo::AbstractChar, A::AbstractMatrix{$elty}) require_one_based_indexing(A) @chkvalidparam 1 jobz ('N', 'V') chkstride1(A) diff --git a/stdlib/LinearAlgebra/test/lapack.jl b/stdlib/LinearAlgebra/test/lapack.jl index fd14dad4634a8..f05d7d99c2437 100644 --- a/stdlib/LinearAlgebra/test/lapack.jl +++ b/stdlib/LinearAlgebra/test/lapack.jl @@ -889,4 +889,14 @@ end @test UpperTriangular(A) == UpperTriangular(B) end +@testset "inference in syev!/syevd!" begin + for T in (Float32, Float64), CT in (T, Complex{T}) + A = rand(CT, 4,4) + @inferred (A -> LAPACK.syev!('N', 'U', A))(A) + @inferred (A -> LAPACK.syev!('V', 'U', A))(A) + @inferred (A -> LAPACK.syevd!('N', 'U', A))(A) + @inferred (A -> LAPACK.syevd!('V', 'U', A))(A) + end +end + end # module TestLAPACK From c66513fd639d8b73a6a3e554a57c19e4f5f038b9 Mon Sep 17 00:00:00 2001 From: Jakob Nybo Nissen Date: Tue, 30 Jul 2024 21:21:25 +0200 Subject: [PATCH 099/206] Random: Mark unexported public symbols as public (#55148) The following symbols: `seed!, default_rng, Sampler, SamplerType, SamplerTrivial, SamplerSimple` Are documented in the Julia documentation and unexported, but not marked as public. Co-authored-by: Max Horn --- stdlib/Random/src/Random.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 9ce0896d0d125..26116d3bf4c81 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -29,6 +29,8 @@ export rand!, randn!, randcycle, randcycle!, AbstractRNG, MersenneTwister, RandomDevice, TaskLocalRNG, Xoshiro +public seed!, default_rng, Sampler, SamplerType, SamplerTrivial, SamplerSimple + ## general definitions """ From f225f8428f1a0d34cf837ee40bb2380b515eabab Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Wed, 31 Jul 2024 05:06:39 -0400 Subject: [PATCH 100/206] avoid overflowing show for OffsetArrays around typemax (#55303) --- base/show.jl | 4 ++-- test/offsetarray.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/show.jl b/base/show.jl index c1ad45af5cc83..fa66a198aef4d 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1407,11 +1407,11 @@ function show_delim_array(io::IO, itr::Union{AbstractArray,SimpleVector}, op, de x = itr[i] show(recur_io, x) end - i += 1 - if i > l + if i == l delim_one && first && print(io, delim) break end + i += 1 first = false print(io, delim) print(io, ' ') diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 9d6a8b08c0b1f..c50f38c382385 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -865,6 +865,15 @@ end @test CartesianIndices(A) == CartesianIndices(B) end +@testset "overflowing show" begin + A = OffsetArray(repeat([1], 1), typemax(Int)-1) + b = IOBuffer(maxsize=10) + show(b, A) + @test String(take!(b)) == "[1]" + show(b, (A, A)) + @test String(take!(b)) == "([1], [1])" +end + @testset "indexing views (#53249)" begin v = view([1,2,3,4], :) @test v[Base.IdentityUnitRange(2:3)] == OffsetArray(2:3, 2:3) From 8d41d25e69ff7419f7b11c8d105884fa2edea925 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 31 Jul 2024 12:54:51 +0200 Subject: [PATCH 101/206] Revert changing `wrap` on `Memory` to `view` and make `wrap` non-public. (#54927) Fixes https://github.com/JuliaLang/julia/issues/54768 --- base/array.jl | 53 ++++++++++++++++++++++++++++++++++++++++++ base/genericmemory.jl | 25 -------------------- base/iobuffer.jl | 12 ++++++---- base/strings/string.jl | 5 +--- test/arrayops.jl | 53 ++++++++++++++---------------------------- test/core.jl | 3 --- 6 files changed, 79 insertions(+), 72 deletions(-) diff --git a/base/array.jl b/base/array.jl index 32c543ff12638..008a52abb952e 100644 --- a/base/array.jl +++ b/base/array.jl @@ -3064,3 +3064,56 @@ intersect(r::AbstractRange, v::AbstractVector) = intersect(v, r) _getindex(v, i) end end + +""" + wrap(Array, m::Union{Memory{T}, MemoryRef{T}}, dims) + +Create an array of size `dims` using `m` as the underlying memory. This can be thought of as a safe version +of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointers. +""" +function wrap end + +# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller +function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N} + mem = ref.mem + mem_len = length(mem) + 1 - memoryrefoffset(ref) + len = Core.checked_dims(dims...) + @boundscheck mem_len >= len || invalid_wrap_err(mem_len, dims, len) + if N != 1 && !(ref === GenericMemoryRef(mem) && len === mem_len) + mem = ccall(:jl_genericmemory_slice, Memory{T}, (Any, Ptr{Cvoid}, Int), mem, ref.ptr_or_offset, len) + ref = memoryref(mem) + end + return ref +end + +@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch(LazyString( + "Attempted to wrap a MemoryRef of length ", len, " with an Array of size dims=", dims, + " which is invalid because prod(dims) = ", proddims, " > ", len, + " so that the array would have more elements than the underlying memory can store."))) + +@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N} + dims = convert(Dims, dims) + ref = _wrap(m, dims) + $(Expr(:new, :(Array{T, N}), :ref, :dims)) +end + +@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N} + dims = convert(Dims, dims) + ref = _wrap(memoryref(m), dims) + $(Expr(:new, :(Array{T, N}), :ref, :dims)) +end +@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T} + dims = (Int(l),) + ref = _wrap(m, dims) + $(Expr(:new, :(Array{T, 1}), :ref, :dims)) +end +@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T} + dims = (Int(l),) + ref = _wrap(memoryref(m), (l,)) + $(Expr(:new, :(Array{T, 1}), :ref, :dims)) +end +@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T} + ref = memoryref(m) + dims = (length(m),) + $(Expr(:new, :(Array{T, 1}), :ref, :dims)) +end diff --git a/base/genericmemory.jl b/base/genericmemory.jl index 32c15a22e0db1..6df6c880f74a8 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -316,31 +316,6 @@ function indcopy(sz::Dims, I::GenericMemory) dst, src end -# Wrapping a memory region in an Array -@eval begin # @eval for the Array construction. Block for the docstring. - function reshape(m::GenericMemory{M, T}, dims::Vararg{Int, N}) where {M, T, N} - len = Core.checked_dims(dims...) - length(m) == len || throw(DimensionMismatch("parent has $(length(m)) elements, which is incompatible with size $(dims)")) - ref = memoryref(m) - $(Expr(:new, :(Array{T, N}), :ref, :dims)) - end - - """ - view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) - - Create a vector `v::Vector{T}` backed by the specified indices of `m`. It is only safe to - resize `v` if `m` is subseqently not used. - """ - function view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) where {M, T} - isempty(inds) && return T[] # needed to allow view(Memory{T}(undef, 0), 2:1) - @boundscheck checkbounds(m, inds) - ref = memoryref(m, first(inds)) # @inbounds would be safe here but does not help performance. - dims = (Int(length(inds)),) - $(Expr(:new, :(Array{T, 1}), :ref, :dims)) - end -end -view(m::GenericMemory, inds::Colon) = view(m, eachindex(m)) - # get, set(once), modify, swap and replace at index, atomically function getindex_atomic(mem::GenericMemory, order::Symbol, i::Int) memref = memoryref(mem, i) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 04a694a4fec15..c0c2731eec08b 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -42,7 +42,7 @@ end # allocate Vector{UInt8}s for IOBuffer storage that can efficiently become Strings StringMemory(n::Integer) = unsafe_wrap(Memory{UInt8}, _string_n(n)) -StringVector(n::Integer) = view(StringMemory(n), 1:n)::Vector{UInt8} +StringVector(n::Integer) = wrap(Array, StringMemory(n)) # IOBuffers behave like Files. They are typically readable and writable. They are seekable. (They can be appendable). @@ -466,7 +466,7 @@ function take!(io::IOBuffer) if nbytes == 0 || io.reinit data = StringVector(0) elseif io.writable - data = view(io.data, io.offset+1:nbytes+io.offset) + data = wrap(Array, memoryref(io.data, io.offset + 1), nbytes) else data = copyto!(StringVector(nbytes), 1, io.data, io.offset + 1, nbytes) end @@ -475,7 +475,7 @@ function take!(io::IOBuffer) if nbytes == 0 data = StringVector(0) elseif io.writable - data = view(io.data, io.ptr:io.ptr+nbytes-1) + data = wrap(Array, memoryref(io.data, io.ptr), nbytes) else data = read!(io, data) end @@ -501,7 +501,11 @@ state. This should only be used internally for performance-critical It might save an allocation compared to `take!` (if the compiler elides the Array allocation), as well as omits some checks. """ -_unsafe_take!(io::IOBuffer) = view(io.data, io.offset+1:io.size) +_unsafe_take!(io::IOBuffer) = + wrap(Array, io.size == io.offset ? + memoryref(Memory{UInt8}()) : + memoryref(io.data, io.offset + 1), + io.size - io.offset) function write(to::IO, from::GenericIOBuffer) written::Int = bytesavailable(from) diff --git a/base/strings/string.jl b/base/strings/string.jl index 7917f463771b2..89e2ff288c3d7 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -115,10 +115,7 @@ String(s::AbstractString) = print_to_string(s) @assume_effects :total String(s::Symbol) = unsafe_string(unsafe_convert(Ptr{UInt8}, s)) unsafe_wrap(::Type{Memory{UInt8}}, s::String) = ccall(:jl_string_to_genericmemory, Ref{Memory{UInt8}}, (Any,), s) -function unsafe_wrap(::Type{Vector{UInt8}}, s::String) - mem = unsafe_wrap(Memory{UInt8}, s) - view(mem, eachindex(mem)) -end +unsafe_wrap(::Type{Vector{UInt8}}, s::String) = wrap(Array, unsafe_wrap(Memory{UInt8}, s)) Vector{UInt8}(s::CodeUnits{UInt8,String}) = copyto!(Vector{UInt8}(undef, length(s)), s) Vector{UInt8}(s::String) = Vector{UInt8}(codeunits(s)) diff --git a/test/arrayops.jl b/test/arrayops.jl index f4bb2dc7372f8..e407ad7233bc2 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3219,42 +3219,23 @@ end end end -@testset "Wrapping Memory into Arrays with view and reshape" begin - mem::Memory{Int} = Memory{Int}(undef, 10) .= 11:20 - - @test_throws DimensionMismatch reshape(mem, 10, 10) - @test_throws DimensionMismatch reshape(mem, 5) - @test_throws BoundsError view(mem, 1:10, 1:10) - @test_throws BoundsError view(mem, 1:11) - @test_throws BoundsError view(mem, 3:11) - @test_throws BoundsError view(mem, 0:4) - - @test @inferred(view(mem, 1:5))::Vector{Int} == 11:15 - @test @inferred(view(mem, 1:2))::Vector{Int} == 11:12 - @test @inferred(view(mem, 1:10))::Vector{Int} == 11:20 - @test @inferred(view(mem, 3:8))::Vector{Int} == 13:18 - @test @inferred(view(mem, 20:19))::Vector{Int} == [] - @test @inferred(view(mem, -5:-7))::Vector{Int} == [] - @test @inferred(view(mem, :))::Vector{Int} == mem - @test @inferred(reshape(mem, 5, 2))::Matrix{Int} == reshape(11:20, 5, 2) - - # 53990 - @test @inferred(view(mem, unsigned(1):10))::Vector{Int} == 11:20 - - empty_mem = Memory{Module}(undef, 0) - @test_throws BoundsError view(empty_mem, 0:1) - @test_throws BoundsError view(empty_mem, 1:2) - @test_throws DimensionMismatch reshape(empty_mem, 1) - @test_throws DimensionMismatch reshape(empty_mem, 1, 2, 3) - @test_throws ArgumentError reshape(empty_mem, 2^16, 2^16, 2^16, 2^16) - - @test @inferred(view(empty_mem, 1:0))::Vector{Module} == [] - @test @inferred(view(empty_mem, 10:3))::Vector{Module} == [] - @test @inferred(view(empty_mem, :))::Vector{Module} == empty_mem - @test isempty(@inferred(reshape(empty_mem, 0, 7, 1))::Array{Module, 3}) - - offset_inds = OffsetArrays.IdOffsetRange(values=3:6, indices=53:56) - @test @inferred(view(collect(mem), offset_inds)) == view(mem, offset_inds) +@testset "Wrapping Memory into Arrays" begin + mem = Memory{Int}(undef, 10) .= 1 + memref = memoryref(mem) + @test_throws DimensionMismatch Base.wrap(Array, mem, (10, 10)) + @test Base.wrap(Array, mem, (5,)) == ones(Int, 5) + @test Base.wrap(Array, mem, 2) == ones(Int, 2) + @test Base.wrap(Array, memref, 10) == ones(Int, 10) + @test Base.wrap(Array, memref, (2,2,2)) == ones(Int,2,2,2) + @test Base.wrap(Array, mem, (5, 2)) == ones(Int, 5, 2) + + memref2 = memoryref(mem, 3) + @test Base.wrap(Array, memref2, (5,)) == ones(Int, 5) + @test Base.wrap(Array, memref2, 2) == ones(Int, 2) + @test Base.wrap(Array, memref2, (2,2,2)) == ones(Int,2,2,2) + @test Base.wrap(Array, memref2, (3, 2)) == ones(Int, 3, 2) + @test_throws DimensionMismatch Base.wrap(Array, memref2, 9) + @test_throws DimensionMismatch Base.wrap(Array, memref2, 10) end @testset "Memory size" begin diff --git a/test/core.jl b/test/core.jl index 3a3f6e6d1b6cd..e765d5a2ab7d7 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5532,9 +5532,6 @@ let a = Base.StringVector(2^17) @test sizeof(c) == 0 end -# issue #53990 / https://github.com/JuliaLang/julia/pull/53896#discussion_r1555087951 -@test Base.StringVector(UInt64(2)) isa Vector{UInt8} - @test_throws ArgumentError eltype(Bottom) # issue #16424, re-evaluating type definitions From d64ebd366a830e1ff85c7520145cc66b25de5f74 Mon Sep 17 00:00:00 2001 From: igrqb <100824876+igrqb@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:45:18 +1000 Subject: [PATCH 102/206] Update help info for qr.jl (#55320) 'Rather than' seems to be the correct intent of the help info. This would mean that Julia stores the result of QR in compact form instead of (=rather than) storing in dense form. 'Rather as' would mean that Julia stores Q and R in two separate dense matrices and not in compact form. --- stdlib/LinearAlgebra/src/qr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 0f81a07e12b08..9a89e58372d08 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -417,7 +417,7 @@ true `qr` returns multiple types because LAPACK uses several representations that minimize the memory storage requirements of products of Householder elementary reflectors, so that the `Q` and `R` matrices can be stored - compactly rather as two separate dense matrices. + compactly rather than two separate dense matrices. """ function qr(A::AbstractMatrix{T}, arg...; kwargs...) where T require_one_based_indexing(A) From fdecc597878ddd29c16463c621adb4b6d0a25462 Mon Sep 17 00:00:00 2001 From: jariji <96840304+jariji@users.noreply.github.com> Date: Wed, 31 Jul 2024 10:59:55 -0700 Subject: [PATCH 103/206] Restrict argument to `isleapyear(::Integer)` (#55317) In 1.10 we have ```jl julia> isleapyear(Year(1992)) false ``` which is semantically incorrect because `Year(1992)` is a duration (1992 years), not an instant. This PR restricts the currently unrestricted argument to integers. --- stdlib/Dates/src/types.jl | 2 +- stdlib/Dates/test/types.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/Dates/src/types.jl b/stdlib/Dates/src/types.jl index e1f7f900bff51..1978864b92554 100644 --- a/stdlib/Dates/src/types.jl +++ b/stdlib/Dates/src/types.jl @@ -203,7 +203,7 @@ function totaldays(y, m, d) end # If the year is divisible by 4, except for every 100 years, except for every 400 years -isleapyear(y) = (y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0)) +isleapyear(y::Integer) = (y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0)) # Number of days in month const DAYSINMONTH = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) diff --git a/stdlib/Dates/test/types.jl b/stdlib/Dates/test/types.jl index 35a793867dc5a..f5284b376ca4a 100644 --- a/stdlib/Dates/test/types.jl +++ b/stdlib/Dates/test/types.jl @@ -41,6 +41,7 @@ end @test Dates.isleapyear(-1) == false @test Dates.isleapyear(4) == true @test Dates.isleapyear(-4) == true + @test_throws MethodError Dates.isleapyear(Dates.Year(1992)) end # Create "test" check manually y = Dates.Year(1) From 5a904ac97a89506456f5e890b8dabea57bd7a0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Guedes?= Date: Wed, 31 Jul 2024 15:25:34 -0300 Subject: [PATCH 104/206] Enable per thread register state cache on libunwind (#55049) Looking into a profile recently I realized that when recording backtraces the CPU utilization is mostly dominated by lookups/updates to libunwind's register state cache (`get_rs_cache`, `put_rs_cache`): ![Screenshot from 2024-07-05 19-29-45](https://github.com/JuliaLang/julia/assets/5301739/5e65f867-6dc8-4d55-8669-aaf1f756a2ac) It is also worth noting that those functions are taking a lock and using `sigprocmask` which does not scale, so by recording backtraces in parallel we get: ![Screenshot from 2024-07-05 19-30-21](https://github.com/JuliaLang/julia/assets/5301739/ed3124dd-f340-4b52-a7f9-c0a203f935b6) And this translates to these times on a recent laptop (Linux X86_64): ``` julia> @time for i in 1:1000000 Base.backtrace() end 8.286924 seconds (32.00 M allocations: 8.389 GiB, 1.46% gc time) julia> @time Threads.@sync for i in 1:16 Threads.@spawn for j in 1:1000000 Base.backtrace() end end 20.448630 seconds (160.01 M allocations: 123.740 GiB, 8.05% gc time, 0.43% compilation time: 18% of which was recompilation) ``` Good news is that libunwind already has the solution for this in the form of the `--enable-per-thread-cache` build option which uses a thread local cache for register state instead of the default global one ([1](https://libunwind-devel.nongnu.narkive.com/V3gtFUL9/question-about-performance-of-threaded-access-in-libunwind)). But this is not without some hiccups due to how we `dlopen` libunwind so we need a small patch ([2](https://libunwind-devel.nongnu.narkive.com/QG1K3Uke/tls-model-initial-exec-attribute-prevents-dynamic-loading-of-libunwind-via-dlopen)). By applying those changes we get: ``` julia> @time for i in 1:1000000 Base.backtrace() end 2.378070 seconds (32.00 M allocations: 8.389 GiB, 4.72% gc time) julia> @time Threads.@sync for i in 1:16 Threads.@spawn for j in 1:1000000 Base.backtrace() end end 3.657772 seconds (160.01 M allocations: 123.740 GiB, 52.05% gc time, 2.33% compilation time: 19% of which was recompilation) ``` Single-Threaded: ![Screenshot from 2024-07-05 20-25-49](https://github.com/JuliaLang/julia/assets/5301739/ebc87952-e51f-488c-92f4-72aed5abb93a) Multi-Threaded: ![Screenshot from 2024-07-05 20-26-32](https://github.com/JuliaLang/julia/assets/5301739/0ea2160a-60e8-49ea-af62-7d8ffc35c963) As a companion to this PR I have created another one for applying the same change to LibUnwind_jll [on Yggdrasil](https://github.com/JuliaPackaging/Yggdrasil/pull/9030). After that lands we can bump the version here. --- deps/checksums/unwind | 48 +++++++++---------- .../libunwind-disable-initial-exec-tls.patch | 44 +++++++++++++++++ deps/unwind.mk | 8 +++- src/threading.c | 6 +++ stdlib/LibUnwind_jll/Project.toml | 2 +- 5 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 deps/patches/libunwind-disable-initial-exec-tls.patch diff --git a/deps/checksums/unwind b/deps/checksums/unwind index 7ef31e6bda06b..317809053abeb 100644 --- a/deps/checksums/unwind +++ b/deps/checksums/unwind @@ -1,26 +1,26 @@ -LibUnwind.v1.8.1+0.aarch64-linux-gnu.tar.gz/md5/e25a186941b2bedeb4a0fca60b1e5d1b -LibUnwind.v1.8.1+0.aarch64-linux-gnu.tar.gz/sha512/4b488ef13b1b09d37dd2d2f62647e6407404730beb8cab58263c2d8e9db3716bfdb8949eca8ebb126eb22a3fcd81deb7ea0774fe7527ba7374f76047fe03abd7 -LibUnwind.v1.8.1+0.aarch64-linux-musl.tar.gz/md5/75fea80870d951a5e87d37bc67e52cfb -LibUnwind.v1.8.1+0.aarch64-linux-musl.tar.gz/sha512/efb54577cddaf5e7930b15cdd98ed88e4d60ba3a1fe0097b2a64a868f92177985c71a86cfb40475976005ab55a01401960afa9c20649b1e34ea02ef262caa046 -LibUnwind.v1.8.1+0.armv6l-linux-gnueabihf.tar.gz/md5/30f3077b185f6e51b8b6ddfddcb8effb -LibUnwind.v1.8.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/524810edbcfcba4938cb63c325905569b7d232dd8b02856e5f1592d7e36620c3ee166c0c788e42a14abc281c41723f49563f59d8cf5175ae1c3605ec29a97b9f -LibUnwind.v1.8.1+0.armv6l-linux-musleabihf.tar.gz/md5/087d263a8edacec1b79d4eccef03ab53 -LibUnwind.v1.8.1+0.armv6l-linux-musleabihf.tar.gz/sha512/bad2bea6f98ed9e0ac293ab3cd7873d2c164616bd09103ad773300da1875e28ac51744809629d01b69744c610d93c90cc48ec4c81411b5d3f036db86e098adcd -LibUnwind.v1.8.1+0.armv7l-linux-gnueabihf.tar.gz/md5/218f8a37d910bcfaba1bbeb9f61593a1 -LibUnwind.v1.8.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/1912b7aa4bbcaca3facad13bf9a8a8b4bb42183b9c542c6b51f0f4a715c27b7583dcf36f49a1fac9787ba7b39728a5d1a151661a570ef637d1080c11d5426fc4 -LibUnwind.v1.8.1+0.armv7l-linux-musleabihf.tar.gz/md5/c2582785ca7dc2edbc529a93ea0f4120 -LibUnwind.v1.8.1+0.armv7l-linux-musleabihf.tar.gz/sha512/ae5414a274d973623070402806eb279dd2ab708c801fa7f24ba9b8066e7fc13ae9ebe1f331f76dd54a4eba572e87117c57d502190b63978af87d7fa35a011632 -LibUnwind.v1.8.1+0.i686-linux-gnu.tar.gz/md5/324ae0c4916a435a6746ca77a1034b58 -LibUnwind.v1.8.1+0.i686-linux-gnu.tar.gz/sha512/fe5ac30e6cdda9f99c873a7af60407c5f1ca1d17396ab46679df56093fea37289e802dd53ed083a4963f7439a1887b4d401a9ab489bdeddd2d003b761af84c1c -LibUnwind.v1.8.1+0.i686-linux-musl.tar.gz/md5/0495beea1d8e5e4572f32830125cb329 -LibUnwind.v1.8.1+0.i686-linux-musl.tar.gz/sha512/3db7f9241e11e139f02239826a65f40d77d968aa7dde574cf91759706dc9a5c97fb055b34ec011f9ac085eec121c3807e9c873773d1ab091a5a7180200ea73ec -LibUnwind.v1.8.1+0.powerpc64le-linux-gnu.tar.gz/md5/1f0feb7cced4b847295dff4c1cd0dde1 -LibUnwind.v1.8.1+0.powerpc64le-linux-gnu.tar.gz/sha512/88707b4a45e3de2901a343f20a35d2003d24db6604a5194712a3a687299b98e7507934a1bd4d7a21f84f089e0378964334c483f10311dd1bfbaa5d8b42ab9f76 -LibUnwind.v1.8.1+0.x86_64-linux-gnu.tar.gz/md5/a03c84494c04ba08fa7e314584d28945 -LibUnwind.v1.8.1+0.x86_64-linux-gnu.tar.gz/sha512/eb97ec8cf03fc5cb77a6218fcc4f1ef1266e66a774dea34e1d1fb7f89c026287bb4bd09de0b61a83b42495b8b4d5be475a61b4df68c83bfb33be2145ed659627 -LibUnwind.v1.8.1+0.x86_64-linux-musl.tar.gz/md5/194654cfd8d202599b7096783659c0ab -LibUnwind.v1.8.1+0.x86_64-linux-musl.tar.gz/sha512/f39f8d0488ec02d9693b4a17ca73ec683ea062cfc67400d02e1e38bfeb43c371068742379d5e17f8c8b4ab478de48f91284e17b0e1b94e09d1a64713276326c7 -LibUnwind.v1.8.1+0.x86_64-unknown-freebsd.tar.gz/md5/6453d66204ba5fb941046afd85345b90 -LibUnwind.v1.8.1+0.x86_64-unknown-freebsd.tar.gz/sha512/77e67c3ddda5eaee0e8b127ad8e2ad41add4410e356c4e4b9bc46eb19871b91d006a59009d9948c4cc0951c2d9e956a99c946a60ba47ceb7f827b2897d6939e5 +LibUnwind.v1.8.1+1.aarch64-linux-gnu.tar.gz/md5/0f789b9e5b2604a39cc363c4c513a808 +LibUnwind.v1.8.1+1.aarch64-linux-gnu.tar.gz/sha512/4c9c8250bfd84a96135a5e9ecdd4500214996c39852609d3a3983c2c5de44a728d9ce6b71bd649c1725e186db077f74df93a99f07452a31d344c17315eedb33d +LibUnwind.v1.8.1+1.aarch64-linux-musl.tar.gz/md5/356deb10e57d4c7e7bf7dbc728d6628d +LibUnwind.v1.8.1+1.aarch64-linux-musl.tar.gz/sha512/a998eebe7a4928bd417620bef0de9728c080f5d9714f15314ac190b333efa1bd7a21207156d56c132515bd3f7154d60204f1fac2dac5468560a7017682527c78 +LibUnwind.v1.8.1+1.armv6l-linux-gnueabihf.tar.gz/md5/b0ff12f5f0c801e5e280a142a1b7a188 +LibUnwind.v1.8.1+1.armv6l-linux-gnueabihf.tar.gz/sha512/68003f39eaf55c8742e821a228889590e8673cbafb74013a5b4f6a0c08ee372cb6b102a574e89ce9f46a38dd3d31ef75de95762f72a31a8ec9d7f495affaeb77 +LibUnwind.v1.8.1+1.armv6l-linux-musleabihf.tar.gz/md5/b04c77d707875989777ecfed66bd2dad +LibUnwind.v1.8.1+1.armv6l-linux-musleabihf.tar.gz/sha512/fb20586a0cbc998a0482d4102d8b8e5b2f802af519e25c440a64f67554468b29c6999a9ec5509ba375714beb93a4b48e8dbf71e6089c25ecd63b11eead844041 +LibUnwind.v1.8.1+1.armv7l-linux-gnueabihf.tar.gz/md5/e948016b4179d34727b456bc768cd8e1 +LibUnwind.v1.8.1+1.armv7l-linux-gnueabihf.tar.gz/sha512/6fc64e8ac7248540b95c321103d234f2c8633087f261e368251fe2cf6ea4e0654325716ac7017ae966edc4ddbb004a0f808d6e25cca766faaf505ca1f8f4aee7 +LibUnwind.v1.8.1+1.armv7l-linux-musleabihf.tar.gz/md5/660cf49c34a2ead1afbdcb44491e174a +LibUnwind.v1.8.1+1.armv7l-linux-musleabihf.tar.gz/sha512/edf337d176440c210f5860e90771758335256fe9d2f179d506656bccf92a9f9aa478d176d4b0db2213945ae847dad5bb88265110c92cfcd538d5740858b6a3f0 +LibUnwind.v1.8.1+1.i686-linux-gnu.tar.gz/md5/7032a70cfecb88cdd49cc3a4879456c6 +LibUnwind.v1.8.1+1.i686-linux-gnu.tar.gz/sha512/e34acc8f270c5156ede3ac3377d0f428c672daed869570734351c6b5a8946d65b5c0c041b713dddefedef81e55c65f5683aed0fec0d366e2d0207d8b902b0e33 +LibUnwind.v1.8.1+1.i686-linux-musl.tar.gz/md5/0541c3419020334173d299cf3482ff85 +LibUnwind.v1.8.1+1.i686-linux-musl.tar.gz/sha512/0b57745d280fb9893772936cd4872b0e04f41d86379e772b889e75baffe9324ef8dd168bb4c9761c1b8372f387ce99721dd6086b1d52b9a91215f40e8113968d +LibUnwind.v1.8.1+1.powerpc64le-linux-gnu.tar.gz/md5/fee37734fe95d1e96ebc77316df64192 +LibUnwind.v1.8.1+1.powerpc64le-linux-gnu.tar.gz/sha512/953ef70fb203db73764eeab0a37521b94e79ce70644ae16fe3157ca8d1011a0319d1928d094a3e2ed1e0489fdc0ca7dda33722095fd3aa40ed1fde150cf44c2a +LibUnwind.v1.8.1+1.x86_64-linux-gnu.tar.gz/md5/bbb201e7455fd13b805b0a96dc16183b +LibUnwind.v1.8.1+1.x86_64-linux-gnu.tar.gz/sha512/b1e21f7d772bd15bada17d287e1876ae586a97c6a8669e714347e7bf8a9b202fe53e8559cf19358f88bc458b2fe15ccbd616b64163cc715ce253f43f5133a8cd +LibUnwind.v1.8.1+1.x86_64-linux-musl.tar.gz/md5/72156f9d6da9a2742d9152822e5525f5 +LibUnwind.v1.8.1+1.x86_64-linux-musl.tar.gz/sha512/53a3f1985c5ae4816693f292604810cbe948e6332aeb227fb900ba3730f4379e863b144ae87af2c0651c2b9633b35c45c7a0a6fa34958dc9f58e0f8baa2ea701 +LibUnwind.v1.8.1+1.x86_64-unknown-freebsd.tar.gz/md5/e4346df03246d847f2867df3ab5ac624 +LibUnwind.v1.8.1+1.x86_64-unknown-freebsd.tar.gz/sha512/ee01bc12726288ae091476c1bed44de224a9ef5355687fd6fd64742da6628450434d7f33d4daf81029263aa6d23549a0aa5c5ae656599c132051255d1d742d5d libunwind-1.8.1.tar.gz/md5/10c96118ff30b88c9eeb6eac8e75599d libunwind-1.8.1.tar.gz/sha512/aba7b578c1b8cbe78f05b64e154f3530525f8a34668b2a9f1ee6acb4b22c857befe34ad4e9e8cca99dbb66689d41bc72060a8f191bd8be232725d342809431b3 diff --git a/deps/patches/libunwind-disable-initial-exec-tls.patch b/deps/patches/libunwind-disable-initial-exec-tls.patch new file mode 100644 index 0000000000000..c6718ac2db98f --- /dev/null +++ b/deps/patches/libunwind-disable-initial-exec-tls.patch @@ -0,0 +1,44 @@ +diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in +index 893fdd69..80ab9648 100644 +--- a/include/libunwind-common.h.in ++++ b/include/libunwind-common.h.in +@@ -340,5 +340,6 @@ extern int unw_get_elf_filename_by_ip (unw_addr_space_t, unw_word_t, char *, + extern const char *unw_strerror (int); + extern int unw_backtrace (void **, int); + extern int unw_backtrace2 (void **, int, unw_context_t*, int); ++extern int unw_ensure_tls (void); + + extern unw_addr_space_t unw_local_addr_space; +diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c +index 7a5d7e1f..8453ffb0 100644 +--- a/src/dwarf/Gparser.c ++++ b/src/dwarf/Gparser.c +@@ -623,7 +623,7 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) + #if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD + if (likely (caching == UNW_CACHE_PER_THREAD)) + { +- static _Thread_local struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec"))); ++ static _Thread_local struct dwarf_rs_cache tls_cache; + Debug (16, "using TLS cache\n"); + cache = &tls_cache; + } +diff --git a/src/mi/init.c b/src/mi/init.c +index e4431eeb..07cae852 100644 +--- a/src/mi/init.c ++++ b/src/mi/init.c +@@ -82,3 +82,15 @@ mi_init (void) + unw_init_page_size(); + assert(sizeof(struct cursor) <= sizeof(unw_cursor_t)); + } ++ ++int ++unw_ensure_tls (void) ++{ ++#if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD ++ static _Thread_local int alloc_trigger; ++ alloc_trigger = 1; ++ return alloc_trigger; ++#else ++ return 0; ++#endif ++} diff --git a/deps/unwind.mk b/deps/unwind.mk index 501ea6b8aedcc..079e4d69b04a3 100644 --- a/deps/unwind.mk +++ b/deps/unwind.mk @@ -38,13 +38,17 @@ $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-aarch64-inline-asm.patch-applied: cd $(SRCCACHE)/libunwind-$(UNWIND_VER) && patch -p1 -f -u -l < $(SRCDIR)/patches/libunwind-aarch64-inline-asm.patch echo 1 > $@ +$(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-disable-initial-exec-tls.patch-applied: $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-aarch64-inline-asm.patch-applied + cd $(SRCCACHE)/libunwind-$(UNWIND_VER) && patch -p1 -f -u -l < $(SRCDIR)/patches/libunwind-disable-initial-exec-tls.patch + echo 1 > $@ + # note minidebuginfo requires liblzma, which we do not have a source build for # (it will be enabled in BinaryBuilder-based downloads however) # since https://github.com/JuliaPackaging/Yggdrasil/commit/0149e021be9badcb331007c62442a4f554f3003c -$(BUILDDIR)/libunwind-$(UNWIND_VER)/build-configured: $(SRCCACHE)/libunwind-$(UNWIND_VER)/source-extracted $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-aarch64-inline-asm.patch-applied +$(BUILDDIR)/libunwind-$(UNWIND_VER)/build-configured: $(SRCCACHE)/libunwind-$(UNWIND_VER)/source-extracted $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-disable-initial-exec-tls.patch-applied mkdir -p $(dir $@) cd $(dir $@) && \ - $(dir $<)/configure $(CONFIGURE_COMMON) CPPFLAGS="$(CPPFLAGS) $(LIBUNWIND_CPPFLAGS)" CFLAGS="$(CFLAGS) $(LIBUNWIND_CFLAGS)" --enable-shared --disable-minidebuginfo --disable-tests --enable-zlibdebuginfo --disable-conservative-checks + $(dir $<)/configure $(CONFIGURE_COMMON) CPPFLAGS="$(CPPFLAGS) $(LIBUNWIND_CPPFLAGS)" CFLAGS="$(CFLAGS) $(LIBUNWIND_CFLAGS)" --enable-shared --disable-minidebuginfo --disable-tests --enable-zlibdebuginfo --disable-conservative-checks --enable-per-thread-cache echo 1 > $@ $(BUILDDIR)/libunwind-$(UNWIND_VER)/build-compiled: $(BUILDDIR)/libunwind-$(UNWIND_VER)/build-configured diff --git a/src/threading.c b/src/threading.c index 0c4e1ccf70eb0..2f658832f2220 100644 --- a/src/threading.c +++ b/src/threading.c @@ -404,6 +404,12 @@ jl_ptls_t jl_init_threadtls(int16_t tid) jl_fence(); uv_mutex_unlock(&tls_lock); +#if !defined(_OS_WINDOWS_) && !defined(JL_DISABLE_LIBUNWIND) && !defined(LLVMLIBUNWIND) + // ensures libunwind TLS space for this thread is allocated eagerly + // to make unwinding async-signal-safe even when using thread local caches. + unw_ensure_tls(); +#endif + return ptls; } diff --git a/stdlib/LibUnwind_jll/Project.toml b/stdlib/LibUnwind_jll/Project.toml index eda312ec0735e..03ccfcd1449d8 100644 --- a/stdlib/LibUnwind_jll/Project.toml +++ b/stdlib/LibUnwind_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUnwind_jll" uuid = "745a5e78-f969-53e9-954f-d19f2f74f4e3" -version = "1.8.1+0" +version = "1.8.1+1" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From dcd8cad90d7986d77f1392c773a2e01be6f1c55f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 31 Jul 2024 18:22:42 -0400 Subject: [PATCH 105/206] add `delete` for NamedTuple (#55270) from #27725 Co-authored-by: Jeffrey Sarnoff --- base/namedtuple.jl | 18 ++++++++++++++++++ test/namedtuple.jl | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 98192480db9dd..e316dbd37ccf5 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -424,6 +424,24 @@ function diff_fallback(a::NamedTuple, an::Tuple{Vararg{Symbol}}, bn::Tuple{Varar _new_NamedTuple(NamedTuple{names, types}, (A...,)) end +""" + delete(a::NamedTuple, field::Symbol) + +Construct a new named tuple from `a` by removing the named field. + +```jldoctest +julia> Base.delete((a=1, b=2, c=3), :a) +(b = 2, c = 3) + +julia> Base.delete((a=1, b=2, c=3), :b) +(a = 1, c = 3) +``` +""" +@constprop :aggressive function delete(a::NamedTuple{an}, field::Symbol) where {an} + names = diff_names(an, (field,)) + NamedTuple{names}(a) +end + """ structdiff(a::NamedTuple, b::Union{NamedTuple,Type{NamedTuple}}) diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 0487f96496309..b8dba5c06422e 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base: delete + @test_throws TypeError NamedTuple{1,Tuple{}} @test_throws TypeError NamedTuple{(),1} @test_throws TypeError NamedTuple{(:a,1),Tuple{Int}} @@ -282,6 +284,11 @@ end abstr_nt_22194_3() @test Base.return_types(abstr_nt_22194_3, ()) == Any[Any] +@test delete((a=1,), :a) == NamedTuple() +@test delete((a=1, b=2), :a) == (b=2,) +@test delete((a=1, b=2, c=3), :b) == (a=1, c=3) +@test delete((a=1, b=2, c=3), :z) == (a=1, b=2, c=3) + @test Base.structdiff((a=1, b=2), (b=3,)) == (a=1,) @test Base.structdiff((a=1, b=2, z=20), (b=3,)) == (a=1, z=20) @test Base.structdiff((a=1, b=2, z=20), (b=3, q=20, z=1)) == (a=1,) From 920c936f86ee41d3c17b403cc8d6e947c6fbc93d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 5 Jul 2024 14:01:43 -0400 Subject: [PATCH 106/206] avoid unnecessary inexact check in `write(::IO, ::String)` --- base/strings/io.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 46353ff6f7c29..aa2bc8afa170f 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -246,7 +246,7 @@ end # optimized methods to avoid iterating over chars write(io::IO, s::Union{String,SubString{String}}) = - GC.@preserve s Int(unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))))::Int + GC.@preserve s (unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))) % Int)::Int print(io::IO, s::Union{String,SubString{String}}) = (write(io, s); nothing) """ From ecf08ce3fa1d540dc774601249bf8ef52bfc6d43 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 25 Jul 2024 16:19:05 -0400 Subject: [PATCH 107/206] improve task_done_hook code for trimming --- base/task.jl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/base/task.jl b/base/task.jl index 4f7b1ea979a94..ae99a71585c85 100644 --- a/base/task.jl +++ b/base/task.jl @@ -813,6 +813,14 @@ macro sync_add(expr) end end +throwto_repl_task(@nospecialize val) = throwto(getfield(active_repl_backend, :backend_task)::Task, val) + +function is_repl_running() + return isdefined(Base, :active_repl_backend) && + (getfield(active_repl_backend, :backend_task)::Task)._state === task_state_runnable && + getfield(active_repl_backend, :in_eval) +end + # runtime system hook called when a task finishes function task_done_hook(t::Task) # `finish_task` sets `sigatomic` before entering this function @@ -834,10 +842,8 @@ function task_done_hook(t::Task) end if err && !handled && Threads.threadid() == 1 - if isa(result, InterruptException) && active_repl_backend !== nothing && - active_repl_backend.backend_task._state === task_state_runnable && isempty(Workqueue) && - active_repl_backend.in_eval - throwto(active_repl_backend.backend_task, result) # this terminates the task + if isa(result, InterruptException) && isempty(Workqueue) && is_repl_running() + throwto_repl_task(result) end end # Clear sigatomic before waiting @@ -848,11 +854,8 @@ function task_done_hook(t::Task) # If an InterruptException happens while blocked in the event loop, try handing # the exception to the REPL task since the current task is done. # issue #19467 - if Threads.threadid() == 1 && - isa(e, InterruptException) && active_repl_backend !== nothing && - active_repl_backend.backend_task._state === task_state_runnable && isempty(Workqueue) && - active_repl_backend.in_eval - throwto(active_repl_backend.backend_task, e) + if Threads.threadid() == 1 && isa(e, InterruptException) && isempty(Workqueue) && is_repl_running() + throwto_repl_task(e) else rethrow() end From b0c22817ca42f28d535e3c1c957946eb2bd207e4 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 25 Jul 2024 16:28:24 -0400 Subject: [PATCH 108/206] make `Sysinfo.__init__` easier to compile --- base/sysinfo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 3cb95396502a9..d0dcac8c6d416 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -165,7 +165,7 @@ end # without pulling in anything unnecessary like `CPU_NAME` function __init_build() global BINDIR = ccall(:jl_get_julia_bindir, Any, ())::String - vers = "v$(VERSION.major).$(VERSION.minor)" + vers = "v$(string(VERSION.major)).$(string(VERSION.minor))" global STDLIB = abspath(BINDIR, "..", "share", "julia", "stdlib", vers) nothing end From 761a8cf442e49bb76434cde15dfab7d9318e19af Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Wed, 31 Jul 2024 21:29:05 -0300 Subject: [PATCH 109/206] WIP/NFC: create GC interface for third-party GCs (#55256) Prelude to the MMTk integration. Creates an interface header specifying the functions that a third-party GC must implement to plug into Julia, and also splits the stock Julia GC implementation into a separate file `gc-stock.c`. In the future, we'll include a few pre-processor guards to ensure some of these files are not compiled if MMTk is enabled. A WIP design document describing the rationale behind the interface and the plan for MMTk integration should be in this [design document](https://docs.google.com/document/d/1v0jtSrIpdEDNOxj5S9g1jPqSpuAkNWhr_T8ToFC9RLI/edit) (feedback is welcome at this stage!). ## TODO - [x] Ensure functions in `gc-interface.h` are only declared in this header. - [x] Add allocation fast-path & codegen write-barriers into the interface. --- base/timing.jl | 4 +- doc/src/devdocs/object.md | 4 +- src/Makefile | 20 +- src/gc-alloc-profiler.cpp | 1 - src/gc-common.c | 506 ++++++++++++++++++++++++++ src/gc-common.h | 176 ++++++++++ src/gc-debug.c | 3 +- src/gc-heap-snapshot.cpp | 5 +- src/gc-heap-snapshot.h | 1 + src/gc-interface.h | 248 +++++++++++++ src/gc-page-profiler.c | 1 + src/gc-page-profiler.h | 2 +- src/gc-pages.c | 3 +- src/gc-stacks.c | 3 +- src/{gc.c => gc-stock.c} | 625 +++++---------------------------- src/{gc.h => gc-stock.h} | 72 +--- src/julia.h | 23 +- src/julia_internal.h | 29 +- src/llvm-final-gc-lowering.cpp | 62 +--- src/llvm-gc-interface-passes.h | 413 ++++++++++++++++++++++ src/llvm-late-gc-lowering.cpp | 360 +------------------ src/scheduler.c | 110 +----- src/signals-unix.c | 6 +- src/stackwalk.c | 2 +- src/threading.c | 2 - 25 files changed, 1489 insertions(+), 1192 deletions(-) create mode 100644 src/gc-common.c create mode 100644 src/gc-common.h create mode 100644 src/gc-interface.h rename src/{gc.c => gc-stock.c} (89%) rename src/{gc.h => gc-stock.h} (92%) create mode 100644 src/llvm-gc-interface-passes.h diff --git a/base/timing.jl b/base/timing.jl index 5fefd75c15852..80ebb74abee26 100644 --- a/base/timing.jl +++ b/base/timing.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -# This type must be kept in sync with the C struct in src/gc.h +# This type must be kept in sync with the C struct in src/gc-interface.h struct GC_Num allocd ::Int64 # GC internal deferred_alloc ::Int64 # GC internal @@ -47,7 +47,7 @@ gc_total_bytes(gc_num::GC_Num) = gc_num.allocd + gc_num.deferred_alloc + gc_num.total_allocd function GC_Diff(new::GC_Num, old::GC_Num) - # logic from `src/gc.c:jl_gc_total_bytes` + # logic from `jl_gc_total_bytes` old_allocd = gc_total_bytes(old) new_allocd = gc_total_bytes(new) return GC_Diff(new_allocd - old_allocd, diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index a2f72d623ab21..8134132d6ee75 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -92,7 +92,7 @@ The corresponding global `jl_datatype_t` objects are created by [`jl_init_types` The garbage collector uses several bits from the metadata portion of the `jl_typetag_t` to track each object in the system. Further details about this algorithm can be found in the comments of -the [garbage collector implementation in `gc.c`](https://github.com/JuliaLang/julia/blob/master/src/gc.c). +the [garbage collector implementation in `gc-stock.c`](https://github.com/JuliaLang/julia/blob/master/src/gc-stock.c). ## Object allocation @@ -179,7 +179,7 @@ jl_value_t *newstruct(jl_value_t *type); jl_value_t *newobj(jl_value_t *type, size_t nfields); ``` -And at the lowest level, memory is getting allocated by a call to the garbage collector (in `gc.c`), +And at the lowest level, memory is getting allocated by a call to the garbage collector (in `gc-stock.c`), then tagged with its type: ```c diff --git a/src/Makefile b/src/Makefile index 4da44a8cc8d81..6f78f4a8b6aa1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,7 +44,7 @@ SRCS := \ jltypes gf typemap smallintset ast builtins module interpreter symbol \ dlload sys init task array genericmemory staticdata toplevel jl_uv datatype \ simplevector runtime_intrinsics precompile jloptions mtarraylist \ - threading scheduler stackwalk gc gc-debug gc-pages gc-stacks gc-alloc-profiler gc-page-profiler method \ + threading scheduler stackwalk gc-common gc-stock gc-debug gc-pages gc-stacks gc-alloc-profiler gc-page-profiler method \ jlapi signal-handling safepoint timing subtype rtutils gc-heap-snapshot \ crc32c APInt-C processor ircode opaque_closure codegen-stubs coverage runtime_ccall engine @@ -103,7 +103,7 @@ ifeq ($(USE_SYSTEM_LIBUV),0) UV_HEADERS += uv.h UV_HEADERS += uv/*.h endif -PUBLIC_HEADERS := $(BUILDDIR)/julia_version.h $(wildcard $(SRCDIR)/support/*.h) $(addprefix $(SRCDIR)/,work-stealing-queue.h gc-tls.h julia.h julia_assert.h julia_threads.h julia_fasttls.h julia_locks.h julia_atomics.h jloptions.h) +PUBLIC_HEADERS := $(BUILDDIR)/julia_version.h $(wildcard $(SRCDIR)/support/*.h) $(addprefix $(SRCDIR)/,work-stealing-queue.h gc-interface.h gc-tls.h julia.h julia_assert.h julia_threads.h julia_fasttls.h julia_locks.h julia_atomics.h jloptions.h) ifeq ($(OS),WINNT) PUBLIC_HEADERS += $(addprefix $(SRCDIR)/,win32_ucontext.h) endif @@ -316,11 +316,11 @@ $(BUILDDIR)/codegen.o $(BUILDDIR)/codegen.dbg.obj: $(addprefix $(SRCDIR)/,\ $(BUILDDIR)/datatype.o $(BUILDDIR)/datatype.dbg.obj: $(SRCDIR)/support/htable.h $(SRCDIR)/support/htable.inc $(BUILDDIR)/debuginfo.o $(BUILDDIR)/debuginfo.dbg.obj: $(addprefix $(SRCDIR)/,debuginfo.h processor.h jitlayers.h debug-registry.h) $(BUILDDIR)/disasm.o $(BUILDDIR)/disasm.dbg.obj: $(SRCDIR)/debuginfo.h $(SRCDIR)/processor.h -$(BUILDDIR)/gc-debug.o $(BUILDDIR)/gc-debug.dbg.obj: $(SRCDIR)/gc.h -$(BUILDDIR)/gc-pages.o $(BUILDDIR)/gc-pages.dbg.obj: $(SRCDIR)/gc.h -$(BUILDDIR)/gc.o $(BUILDDIR)/gc.dbg.obj: $(SRCDIR)/gc.h $(SRCDIR)/gc-heap-snapshot.h $(SRCDIR)/gc-alloc-profiler.h $(SRCDIR)/gc-page-profiler.h -$(BUILDDIR)/gc-heap-snapshot.o $(BUILDDIR)/gc-heap-snapshot.dbg.obj: $(SRCDIR)/gc.h $(SRCDIR)/gc-heap-snapshot.h -$(BUILDDIR)/gc-alloc-profiler.o $(BUILDDIR)/gc-alloc-profiler.dbg.obj: $(SRCDIR)/gc.h $(SRCDIR)/gc-alloc-profiler.h +$(BUILDDIR)/gc-debug.o $(BUILDDIR)/gc-debug.dbg.obj: $(SRCDIR)/gc-common.h $(SRCDIR)/gc-stock.h +$(BUILDDIR)/gc-pages.o $(BUILDDIR)/gc-pages.dbg.obj: $(SRCDIR)/gc-common.h $(SRCDIR)/gc-stock.h +$(BUILDDIR)/gc-stock.o $(BUILDDIR)/gc.dbg.obj: $(SRCDIR)/gc-common.h $(SRCDIR)/gc-stock.h $(SRCDIR)/gc-heap-snapshot.h $(SRCDIR)/gc-alloc-profiler.h $(SRCDIR)/gc-page-profiler.h +$(BUILDDIR)/gc-heap-snapshot.o $(BUILDDIR)/gc-heap-snapshot.dbg.obj: $(SRCDIR)/gc-heap-snapshot.h +$(BUILDDIR)/gc-alloc-profiler.o $(BUILDDIR)/gc-alloc-profiler.dbg.obj: $(SRCDIR)/gc-alloc-profiler.h $(BUILDDIR)/gc-page-profiler.o $(BUILDDIR)/gc-page-profiler.dbg.obj: $(SRCDIR)/gc-page-profiler.h $(BUILDDIR)/init.o $(BUILDDIR)/init.dbg.obj: $(SRCDIR)/builtin_proto.h $(BUILDDIR)/interpreter.o $(BUILDDIR)/interpreter.dbg.obj: $(SRCDIR)/builtin_proto.h @@ -331,10 +331,10 @@ $(BUILDDIR)/llvm-alloc-helpers.o $(BUILDDIR)/llvm-alloc-helpers.dbg.obj: $(SRCDI $(BUILDDIR)/llvm-alloc-opt.o $(BUILDDIR)/llvm-alloc-opt.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-alloc-helpers.h $(BUILDDIR)/llvm-cpufeatures.o $(BUILDDIR)/llvm-cpufeatures.dbg.obj: $(SRCDIR)/jitlayers.h $(BUILDDIR)/llvm-demote-float16.o $(BUILDDIR)/llvm-demote-float16.dbg.obj: $(SRCDIR)/jitlayers.h -$(BUILDDIR)/llvm-final-gc-lowering.o $(BUILDDIR)/llvm-final-gc-lowering.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-codegen-shared.h +$(BUILDDIR)/llvm-final-gc-lowering.o $(BUILDDIR)/llvm-final-gc-lowering.dbg.obj: $(SRCDIR)/llvm-gc-interface-passes.h $(BUILDDIR)/llvm-gc-invariant-verifier.o $(BUILDDIR)/llvm-gc-invariant-verifier.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(BUILDDIR)/llvm-julia-licm.o $(BUILDDIR)/llvm-julia-licm.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/llvm-alloc-helpers.h $(SRCDIR)/llvm-pass-helpers.h -$(BUILDDIR)/llvm-late-gc-lowering.o $(BUILDDIR)/llvm-late-gc-lowering.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-codegen-shared.h +$(BUILDDIR)/llvm-late-gc-lowering.o $(BUILDDIR)/llvm-late-gc-lowering.dbg.obj: $(SRCDIR)/llvm-gc-interface-passes.h $(BUILDDIR)/llvm-lower-handlers.o $(BUILDDIR)/llvm-lower-handlers.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(BUILDDIR)/llvm-multiversioning.o $(BUILDDIR)/llvm-multiversioning.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/processor.h $(BUILDDIR)/llvm-pass-helpers.o $(BUILDDIR)/llvm-pass-helpers.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-codegen-shared.h @@ -348,7 +348,7 @@ $(BUILDDIR)/toplevel.o $(BUILDDIR)/toplevel.dbg.obj: $(SRCDIR)/builtin_proto.h $(BUILDDIR)/ircode.o $(BUILDDIR)/ircode.dbg.obj: $(SRCDIR)/serialize.h $(SRCDIR)/common_symbols1.inc $(SRCDIR)/common_symbols2.inc $(BUILDDIR)/pipeline.o $(BUILDDIR)/pipeline.dbg.obj: $(SRCDIR)/passes.h $(SRCDIR)/jitlayers.h -$(addprefix $(BUILDDIR)/,threading.o threading.dbg.obj gc.o gc.dbg.obj init.c init.dbg.obj task.o task.dbg.obj): $(addprefix $(SRCDIR)/,threading.h) +$(addprefix $(BUILDDIR)/,threading.o threading.dbg.obj gc-common.o gc-stock.o gc.dbg.obj init.c init.dbg.obj task.o task.dbg.obj): $(addprefix $(SRCDIR)/,threading.h) $(addprefix $(BUILDDIR)/,APInt-C.o APInt-C.dbg.obj runtime_intrinsics.o runtime_intrinsics.dbg.obj): $(SRCDIR)/APInt-C.h # archive library file rules diff --git a/src/gc-alloc-profiler.cpp b/src/gc-alloc-profiler.cpp index c7ee32269138a..5b462d48cd2de 100644 --- a/src/gc-alloc-profiler.cpp +++ b/src/gc-alloc-profiler.cpp @@ -3,7 +3,6 @@ #include "gc-alloc-profiler.h" #include "julia_internal.h" -#include "gc.h" #include "llvm/ADT/SmallVector.h" diff --git a/src/gc-common.c b/src/gc-common.c new file mode 100644 index 0000000000000..ee461b576ea9e --- /dev/null +++ b/src/gc-common.c @@ -0,0 +1,506 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include "gc-common.h" +#include "julia.h" +#include "julia_atomics.h" +#include "julia_gcext.h" +#include "julia_assert.h" +#include "threading.h" +#ifdef __GLIBC__ +#include // for malloc_trim +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// =========================================================================== // +// GC Metrics +// =========================================================================== // + +jl_gc_num_t gc_num = {0}; + +// =========================================================================== // +// GC Callbacks +// =========================================================================== // + +jl_gc_callback_list_t *gc_cblist_root_scanner; +jl_gc_callback_list_t *gc_cblist_task_scanner; +jl_gc_callback_list_t *gc_cblist_pre_gc; +jl_gc_callback_list_t *gc_cblist_post_gc; +jl_gc_callback_list_t *gc_cblist_notify_external_alloc; +jl_gc_callback_list_t *gc_cblist_notify_external_free; +jl_gc_callback_list_t *gc_cblist_notify_gc_pressure; + +static void jl_gc_register_callback(jl_gc_callback_list_t **list, + jl_gc_cb_func_t func) +{ + while (*list != NULL) { + if ((*list)->func == func) + return; + list = &((*list)->next); + } + *list = (jl_gc_callback_list_t *)malloc_s(sizeof(jl_gc_callback_list_t)); + (*list)->next = NULL; + (*list)->func = func; +} + +static void jl_gc_deregister_callback(jl_gc_callback_list_t **list, + jl_gc_cb_func_t func) +{ + while (*list != NULL) { + if ((*list)->func == func) { + jl_gc_callback_list_t *tmp = *list; + (*list) = (*list)->next; + free(tmp); + return; + } + list = &((*list)->next); + } +} + +JL_DLLEXPORT void jl_gc_set_cb_root_scanner(jl_gc_cb_root_scanner_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_root_scanner, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_root_scanner, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_task_scanner(jl_gc_cb_task_scanner_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_task_scanner, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_task_scanner, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_pre_gc(jl_gc_cb_pre_gc_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_pre_gc, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_pre_gc, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_post_gc(jl_gc_cb_post_gc_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_post_gc, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_post_gc, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_notify_external_alloc(jl_gc_cb_notify_external_alloc_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_notify_external_alloc, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_notify_external_alloc, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_notify_external_free(jl_gc_cb_notify_external_free_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_notify_external_free, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_notify_external_free, (jl_gc_cb_func_t)cb); +} + +JL_DLLEXPORT void jl_gc_set_cb_notify_gc_pressure(jl_gc_cb_notify_gc_pressure_t cb, int enable) +{ + if (enable) + jl_gc_register_callback(&gc_cblist_notify_gc_pressure, (jl_gc_cb_func_t)cb); + else + jl_gc_deregister_callback(&gc_cblist_notify_gc_pressure, (jl_gc_cb_func_t)cb); +} + +// =========================================================================== // +// Finalization +// =========================================================================== // + +jl_mutex_t finalizers_lock; +arraylist_t finalizer_list_marked; +arraylist_t to_finalize; +JL_DLLEXPORT _Atomic(int) jl_gc_have_pending_finalizers = 0; + +void schedule_finalization(void *o, void *f) JL_NOTSAFEPOINT +{ + arraylist_push(&to_finalize, o); + arraylist_push(&to_finalize, f); + // doesn't need release, since we'll keep checking (on the reader) until we see the work and + // release our lock, and that will have a release barrier by then + jl_atomic_store_relaxed(&jl_gc_have_pending_finalizers, 1); +} + +void run_finalizer(jl_task_t *ct, void *o, void *ff) +{ + int ptr_finalizer = gc_ptr_tag(o, 1); + o = gc_ptr_clear_tag(o, 3); + if (ptr_finalizer) { + ((void (*)(void*))ff)((void*)o); + return; + } + JL_TRY { + size_t last_age = ct->world_age; + ct->world_age = jl_atomic_load_acquire(&jl_world_counter); + jl_apply_generic((jl_value_t*)ff, (jl_value_t**)&o, 1); + ct->world_age = last_age; + } + JL_CATCH { + jl_printf((JL_STREAM*)STDERR_FILENO, "error in running finalizer: "); + jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception(ct)); + jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); + jlbacktrace(); // written to STDERR_FILENO + } +} + +// if `need_sync` is true, the `list` is the `finalizers` list of another +// thread and we need additional synchronizations +static void finalize_object(arraylist_t *list, jl_value_t *o, + arraylist_t *copied_list, int need_sync) JL_NOTSAFEPOINT +{ + // The acquire load makes sure that the first `len` objects are valid. + // If `need_sync` is true, all mutations of the content should be limited + // to the first `oldlen` elements and no mutation is allowed after the + // new length is published with the `cmpxchg` at the end of the function. + // This way, the mutation should not conflict with the owning thread, + // which only writes to locations later than `len` + // and will not resize the buffer without acquiring the lock. + size_t len = need_sync ? jl_atomic_load_acquire((_Atomic(size_t)*)&list->len) : list->len; + size_t oldlen = len; + void **items = list->items; + size_t j = 0; + for (size_t i = 0; i < len; i += 2) { + void *v = items[i]; + int move = 0; + if (o == (jl_value_t*)gc_ptr_clear_tag(v, 1)) { + void *f = items[i + 1]; + move = 1; + arraylist_push(copied_list, v); + arraylist_push(copied_list, f); + } + if (move || __unlikely(!v)) { + // remove item + } + else { + if (j < i) { + items[j] = items[i]; + items[j+1] = items[i+1]; + } + j += 2; + } + } + len = j; + if (oldlen == len) + return; + if (need_sync) { + // The memset needs to be unconditional since the thread might have + // already read the length. + // The `memset` (like any other content mutation) has to be done + // **before** the `cmpxchg` which publishes the length. + memset(&items[len], 0, (oldlen - len) * sizeof(void*)); + jl_atomic_cmpswap((_Atomic(size_t)*)&list->len, &oldlen, len); + } + else { + list->len = len; + } +} + +// The first two entries are assumed to be empty and the rest are assumed to +// be pointers to `jl_value_t` objects +static void jl_gc_push_arraylist(jl_task_t *ct, arraylist_t *list) JL_NOTSAFEPOINT +{ + void **items = list->items; + items[0] = (void*)JL_GC_ENCODE_PUSHARGS(list->len - 2); + items[1] = ct->gcstack; + ct->gcstack = (jl_gcframe_t*)items; +} + +// Same assumption as `jl_gc_push_arraylist`. Requires the finalizers lock +// to be hold for the current thread and will release the lock when the +// function returns. +static void jl_gc_run_finalizers_in_list(jl_task_t *ct, arraylist_t *list) JL_NOTSAFEPOINT_LEAVE +{ + // Avoid marking `ct` as non-migratable via an `@async` task (as noted in the docstring + // of `finalizer`) in a finalizer: + uint8_t sticky = ct->sticky; + // empty out the first two entries for the GC frame + arraylist_push(list, list->items[0]); + arraylist_push(list, list->items[1]); + jl_gc_push_arraylist(ct, list); + void **items = list->items; + size_t len = list->len; + JL_UNLOCK_NOGC(&finalizers_lock); + // run finalizers in reverse order they were added, so lower-level finalizers run last + for (size_t i = len-4; i >= 2; i -= 2) + run_finalizer(ct, items[i], items[i + 1]); + // first entries were moved last to make room for GC frame metadata + run_finalizer(ct, items[len-2], items[len-1]); + // matches the jl_gc_push_arraylist above + JL_GC_POP(); + ct->sticky = sticky; +} + +static uint64_t finalizer_rngState[JL_RNG_SIZE]; + +void jl_rng_split(uint64_t dst[JL_RNG_SIZE], uint64_t src[JL_RNG_SIZE]) JL_NOTSAFEPOINT; + +JL_DLLEXPORT void jl_gc_init_finalizer_rng_state(void) +{ + jl_rng_split(finalizer_rngState, jl_current_task->rngState); +} + +void run_finalizers(jl_task_t *ct, int finalizers_thread) +{ + // Racy fast path: + // The race here should be OK since the race can only happen if + // another thread is writing to it with the lock held. In such case, + // we don't need to run pending finalizers since the writer thread + // will flush it. + if (to_finalize.len == 0) + return; + JL_LOCK_NOGC(&finalizers_lock); + if (to_finalize.len == 0) { + JL_UNLOCK_NOGC(&finalizers_lock); + return; + } + arraylist_t copied_list; + memcpy(&copied_list, &to_finalize, sizeof(copied_list)); + if (to_finalize.items == to_finalize._space) { + copied_list.items = copied_list._space; + } + jl_atomic_store_relaxed(&jl_gc_have_pending_finalizers, 0); + arraylist_new(&to_finalize, 0); + + uint64_t save_rngState[JL_RNG_SIZE]; + memcpy(&save_rngState[0], &ct->rngState[0], sizeof(save_rngState)); + jl_rng_split(ct->rngState, finalizer_rngState); + + // This releases the finalizers lock. + int8_t was_in_finalizer = ct->ptls->in_finalizer; + ct->ptls->in_finalizer = !finalizers_thread; + jl_gc_run_finalizers_in_list(ct, &copied_list); + ct->ptls->in_finalizer = was_in_finalizer; + arraylist_free(&copied_list); + + memcpy(&ct->rngState[0], &save_rngState[0], sizeof(save_rngState)); +} + +JL_DLLEXPORT void jl_gc_run_pending_finalizers(jl_task_t *ct) +{ + if (ct == NULL) + ct = jl_current_task; + jl_ptls_t ptls = ct->ptls; + if (!ptls->in_finalizer && ptls->locks.len == 0 && ptls->finalizers_inhibited == 0 && ptls->engine_nqueued == 0) { + run_finalizers(ct, 0); + } +} + +JL_DLLEXPORT int jl_gc_get_finalizers_inhibited(jl_ptls_t ptls) +{ + if (ptls == NULL) + ptls = jl_current_task->ptls; + return ptls->finalizers_inhibited; +} + +JL_DLLEXPORT void jl_gc_disable_finalizers_internal(void) +{ + jl_ptls_t ptls = jl_current_task->ptls; + ptls->finalizers_inhibited++; +} + +JL_DLLEXPORT void jl_gc_enable_finalizers_internal(void) +{ + jl_task_t *ct = jl_current_task; +#ifdef NDEBUG + ct->ptls->finalizers_inhibited--; +#else + jl_gc_enable_finalizers(ct, 1); +#endif +} + +JL_DLLEXPORT void jl_gc_enable_finalizers(jl_task_t *ct, int on) +{ + if (ct == NULL) + ct = jl_current_task; + jl_ptls_t ptls = ct->ptls; + int old_val = ptls->finalizers_inhibited; + int new_val = old_val + (on ? -1 : 1); + if (new_val < 0) { + JL_TRY { + jl_error(""); // get a backtrace + } + JL_CATCH { + jl_printf((JL_STREAM*)STDERR_FILENO, "WARNING: GC finalizers already enabled on this thread.\n"); + // Only print the backtrace once, to avoid spamming the logs + static int backtrace_printed = 0; + if (backtrace_printed == 0) { + backtrace_printed = 1; + jlbacktrace(); // written to STDERR_FILENO + } + } + return; + } + ptls->finalizers_inhibited = new_val; + if (jl_atomic_load_relaxed(&jl_gc_have_pending_finalizers)) { + jl_gc_run_pending_finalizers(ct); + } +} + +JL_DLLEXPORT int8_t jl_gc_is_in_finalizer(void) +{ + return jl_current_task->ptls->in_finalizer; +} + +static void schedule_all_finalizers(arraylist_t *flist) JL_NOTSAFEPOINT +{ + void **items = flist->items; + size_t len = flist->len; + for(size_t i = 0; i < len; i+=2) { + void *v = items[i]; + void *f = items[i + 1]; + if (__unlikely(!v)) + continue; + schedule_finalization(v, f); + } + flist->len = 0; +} + +void jl_gc_run_all_finalizers(jl_task_t *ct) +{ + int gc_n_threads; + jl_ptls_t* gc_all_tls_states; + gc_n_threads = jl_atomic_load_acquire(&jl_n_threads); + gc_all_tls_states = jl_atomic_load_relaxed(&jl_all_tls_states); + // this is called from `jl_atexit_hook`; threads could still be running + // so we have to guard the finalizers' lists + JL_LOCK_NOGC(&finalizers_lock); + schedule_all_finalizers(&finalizer_list_marked); + for (int i = 0; i < gc_n_threads; i++) { + jl_ptls_t ptls2 = gc_all_tls_states[i]; + if (ptls2 != NULL) + schedule_all_finalizers(&ptls2->finalizers); + } + // unlock here because `run_finalizers` locks this + JL_UNLOCK_NOGC(&finalizers_lock); + run_finalizers(ct, 1); +} + +void jl_gc_add_finalizer_(jl_ptls_t ptls, void *v, void *f) JL_NOTSAFEPOINT +{ + assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_STATE_UNSAFE); + arraylist_t *a = &ptls->finalizers; + // This acquire load and the release store at the end are used to + // synchronize with `finalize_object` on another thread. Apart from the GC, + // which is blocked by entering a unsafe region, there might be only + // one other thread accessing our list in `finalize_object` + // (only one thread since it needs to acquire the finalizer lock). + // Similar to `finalize_object`, all content mutation has to be done + // between the acquire and the release of the length. + size_t oldlen = jl_atomic_load_acquire((_Atomic(size_t)*)&a->len); + if (__unlikely(oldlen + 2 > a->max)) { + JL_LOCK_NOGC(&finalizers_lock); + // `a->len` might have been modified. + // Another possibility is to always grow the array to `oldlen + 2` but + // it's simpler this way and uses slightly less memory =) + oldlen = a->len; + arraylist_grow(a, 2); + a->len = oldlen; + JL_UNLOCK_NOGC(&finalizers_lock); + } + void **items = a->items; + items[oldlen] = v; + items[oldlen + 1] = f; + jl_atomic_store_release((_Atomic(size_t)*)&a->len, oldlen + 2); +} + +JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) JL_NOTSAFEPOINT +{ + jl_gc_add_finalizer_(ptls, (void*)(((uintptr_t)v) | 1), f); +} + +// schedule f(v) to call at the next quiescent interval (aka after the next safepoint/region on all threads) +JL_DLLEXPORT void jl_gc_add_quiescent(jl_ptls_t ptls, void **v, void *f) JL_NOTSAFEPOINT +{ + assert(!gc_ptr_tag(v, 3)); + jl_gc_add_finalizer_(ptls, (void*)(((uintptr_t)v) | 3), f); +} + +JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT +{ + if (__unlikely(jl_typetagis(f, jl_voidpointer_type))) { + jl_gc_add_ptr_finalizer(ptls, v, jl_unbox_voidpointer(f)); + } + else { + jl_gc_add_finalizer_(ptls, v, f); + } +} + +JL_DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) +{ + jl_ptls_t ptls = jl_current_task->ptls; + jl_gc_add_finalizer_th(ptls, v, f); +} + +JL_DLLEXPORT void jl_finalize_th(jl_task_t *ct, jl_value_t *o) +{ + JL_LOCK_NOGC(&finalizers_lock); + // Copy the finalizers into a temporary list so that code in the finalizer + // won't change the list as we loop through them. + // This list is also used as the GC frame when we are running the finalizers + arraylist_t copied_list; + arraylist_new(&copied_list, 0); + // No need to check the to_finalize list since the user is apparently + // still holding a reference to the object + int gc_n_threads; + jl_ptls_t* gc_all_tls_states; + gc_n_threads = jl_atomic_load_acquire(&jl_n_threads); + gc_all_tls_states = jl_atomic_load_relaxed(&jl_all_tls_states); + for (int i = 0; i < gc_n_threads; i++) { + jl_ptls_t ptls2 = gc_all_tls_states[i]; + if (ptls2 != NULL) + finalize_object(&ptls2->finalizers, o, &copied_list, jl_atomic_load_relaxed(&ct->tid) != i); + } + finalize_object(&finalizer_list_marked, o, &copied_list, 0); + if (copied_list.len > 0) { + // This releases the finalizers lock. + jl_gc_run_finalizers_in_list(ct, &copied_list); + } + else { + JL_UNLOCK_NOGC(&finalizers_lock); + } + arraylist_free(&copied_list); +} + +JL_DLLEXPORT void jl_finalize(jl_value_t *o) +{ + jl_finalize_th(jl_current_task, o); +} + +// =========================================================================== // +// Threading +// =========================================================================== // + +int gc_n_threads; +jl_ptls_t* gc_all_tls_states; + +// =========================================================================== // +// MISC +// =========================================================================== // + +const uint64_t _jl_buff_tag[3] = {0x4eadc0004eadc000ull, 0x4eadc0004eadc000ull, 0x4eadc0004eadc000ull}; // aka 0xHEADER00 +JL_DLLEXPORT uintptr_t jl_get_buff_tag(void) JL_NOTSAFEPOINT +{ + return jl_buff_tag; +} + +// callback for passing OOM errors from gmp +JL_DLLEXPORT void jl_throw_out_of_memory_error(void) +{ + jl_throw(jl_memory_exception); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/gc-common.h b/src/gc-common.h new file mode 100644 index 0000000000000..4d53830442a7d --- /dev/null +++ b/src/gc-common.h @@ -0,0 +1,176 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#ifndef JL_GC_COMMON_H +#define JL_GC_COMMON_H + +#include "julia.h" +#include "julia_internal.h" +#ifndef _OS_WINDOWS_ +#include +#if defined(_OS_DARWIN_) && !defined(MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// =========================================================================== // +// GC Callbacks +// =========================================================================== // + +typedef void (*jl_gc_cb_func_t)(void); + +typedef struct _jl_gc_callback_list_t { + struct _jl_gc_callback_list_t *next; + jl_gc_cb_func_t func; +} jl_gc_callback_list_t; + +extern jl_gc_callback_list_t *gc_cblist_root_scanner; +extern jl_gc_callback_list_t *gc_cblist_task_scanner; +extern jl_gc_callback_list_t *gc_cblist_pre_gc; +extern jl_gc_callback_list_t *gc_cblist_post_gc; +extern jl_gc_callback_list_t *gc_cblist_notify_external_alloc; +extern jl_gc_callback_list_t *gc_cblist_notify_external_free; +extern jl_gc_callback_list_t *gc_cblist_notify_gc_pressure; + +#define gc_invoke_callbacks(ty, list, args) \ + do { \ + for (jl_gc_callback_list_t *cb = list; \ + cb != NULL; \ + cb = cb->next) \ + { \ + ((ty)(cb->func)) args; \ + } \ + } while (0) + +#ifdef __cplusplus +} +#endif + +// =========================================================================== // +// malloc wrappers, aligned allocation +// =========================================================================== // + +#if defined(_OS_WINDOWS_) +STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) +{ + return _aligned_malloc(sz ? sz : 1, align); +} +STATIC_INLINE void *jl_realloc_aligned(void *p, size_t sz, size_t oldsz, + size_t align) +{ + (void)oldsz; + return _aligned_realloc(p, sz ? sz : 1, align); +} +STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT +{ + _aligned_free(p); +} +#else +STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) +{ +#if defined(_P64) || defined(__APPLE__) + if (align <= 16) + return malloc(sz); +#endif + void *ptr; + if (posix_memalign(&ptr, align, sz)) + return NULL; + return ptr; +} +STATIC_INLINE void *jl_realloc_aligned(void *d, size_t sz, size_t oldsz, + size_t align) +{ +#if defined(_P64) || defined(__APPLE__) + if (align <= 16) + return realloc(d, sz); +#endif + void *b = jl_malloc_aligned(sz, align); + if (b != NULL) { + memcpy(b, d, oldsz > sz ? sz : oldsz); + free(d); + } + return b; +} +STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT +{ + free(p); +} +#endif +#define malloc_cache_align(sz) jl_malloc_aligned(sz, JL_CACHE_BYTE_ALIGNMENT) +#define realloc_cache_align(p, sz, oldsz) jl_realloc_aligned(p, sz, oldsz, JL_CACHE_BYTE_ALIGNMENT) + +// =========================================================================== // +// Pointer tagging +// =========================================================================== // + +STATIC_INLINE int gc_marked(uintptr_t bits) JL_NOTSAFEPOINT +{ + return (bits & GC_MARKED) != 0; +} + +STATIC_INLINE int gc_old(uintptr_t bits) JL_NOTSAFEPOINT +{ + return (bits & GC_OLD) != 0; +} + +STATIC_INLINE uintptr_t gc_set_bits(uintptr_t tag, int bits) JL_NOTSAFEPOINT +{ + return (tag & ~(uintptr_t)3) | bits; +} + +STATIC_INLINE uintptr_t gc_ptr_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT +{ + return ((uintptr_t)v) & mask; +} + +STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT +{ + return (void*)(((uintptr_t)v) & ~mask); +} + +// =========================================================================== // +// GC Metrics +// =========================================================================== // + +extern jl_gc_num_t gc_num; + +// =========================================================================== // +// Stop-the-world for GC +// =========================================================================== // +void jl_gc_wait_for_the_world(jl_ptls_t* gc_all_tls_states, int gc_n_threads); + +// =========================================================================== // +// Finalization +// =========================================================================== // + +// Protect all access to `finalizer_list_marked` and `to_finalize`. +// For accessing `ptls->finalizers`, the lock is needed if a thread +// is going to realloc the buffer (of its own list) or accessing the +// list of another thread +extern jl_mutex_t finalizers_lock; +// `ptls->finalizers` and `finalizer_list_marked` might have tagged pointers. +// If an object pointer has the lowest bit set, the next pointer is an unboxed c function pointer. +// If an object pointer has the second lowest bit set, the current pointer is a c object pointer. +// It must be aligned at least 4, and it finalized immediately (at "quiescence"). +// `to_finalize` should not have tagged pointers. +extern arraylist_t finalizer_list_marked; +extern arraylist_t to_finalize; + +void schedule_finalization(void *o, void *f) JL_NOTSAFEPOINT; +void run_finalizer(jl_task_t *ct, void *o, void *ff); +void run_finalizers(jl_task_t *ct, int finalizers_thread); +JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jl_finalize_th(jl_task_t *ct, jl_value_t *o); + + +// =========================================================================== // +// Threading +// =========================================================================== // + +extern int gc_n_threads; +extern jl_ptls_t* gc_all_tls_states; + +#endif // JL_GC_COMMON_H diff --git a/src/gc-debug.c b/src/gc-debug.c index a7699cc3d0168..ec3c8d731edd8 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "gc.h" +#include "gc-common.h" +#include "gc-stock.h" #include "julia.h" #include #include diff --git a/src/gc-heap-snapshot.cpp b/src/gc-heap-snapshot.cpp index 77a6e70a127e6..b84d1f96f273c 100644 --- a/src/gc-heap-snapshot.cpp +++ b/src/gc-heap-snapshot.cpp @@ -2,9 +2,9 @@ #include "gc-heap-snapshot.h" +#include "julia.h" #include "julia_internal.h" #include "julia_assert.h" -#include "gc.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -183,7 +183,8 @@ struct HeapSnapshot { // when snapshotting is on. int gc_heap_snapshot_enabled = 0; HeapSnapshot *g_snapshot = nullptr; -extern jl_mutex_t heapsnapshot_lock; +// mutex for gc-heap-snapshot. +jl_mutex_t heapsnapshot_lock; void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &snapshot, char all_one); void serialize_heap_snapshot(ios_t *stream, HeapSnapshot &snapshot, char all_one); diff --git a/src/gc-heap-snapshot.h b/src/gc-heap-snapshot.h index 70884f5f62d6a..a58f58aba5458 100644 --- a/src/gc-heap-snapshot.h +++ b/src/gc-heap-snapshot.h @@ -35,6 +35,7 @@ void _gc_heap_snapshot_record_finlist(jl_value_t *finlist, size_t index) JL_NOTS extern int gc_heap_snapshot_enabled; extern int prev_sweep_full; +extern jl_mutex_t heapsnapshot_lock; int gc_slot_to_fieldidx(void *_obj, void *slot, jl_datatype_t *vt) JL_NOTSAFEPOINT; int gc_slot_to_arrayidx(void *_obj, void *begin) JL_NOTSAFEPOINT; diff --git a/src/gc-interface.h b/src/gc-interface.h new file mode 100644 index 0000000000000..201c5f6e1741e --- /dev/null +++ b/src/gc-interface.h @@ -0,0 +1,248 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +/* + Garbage Collection interface that must be implemented by third-party GCs +*/ + +#ifndef JL_GC_INTERFACE_H +#define JL_GC_INTERFACE_H + +#include "dtypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _jl_tls_states_t; +struct _jl_value_t; +struct _jl_weakref_t; +struct _jl_datatype_t; + +// ========================================================================= // +// GC Metrics +// ========================================================================= // + +// This struct must be kept in sync with the Julia type of the same name in base/timing.jl +typedef struct { + int64_t allocd; + int64_t deferred_alloc; + int64_t freed; + uint64_t malloc; + uint64_t realloc; + uint64_t poolalloc; + uint64_t bigalloc; + uint64_t freecall; + uint64_t total_time; + uint64_t total_allocd; + size_t interval; + int pause; + int full_sweep; + uint64_t max_pause; + uint64_t max_memory; + uint64_t time_to_safepoint; + uint64_t max_time_to_safepoint; + uint64_t total_time_to_safepoint; + uint64_t sweep_time; + uint64_t mark_time; + uint64_t total_sweep_time; + uint64_t total_mark_time; + uint64_t last_full_sweep; + uint64_t last_incremental_sweep; +} jl_gc_num_t; + +// ========================================================================= // +// System-wide Initialization +// ========================================================================= // + +// System-wide initialization function. Responsible for initializing global locks as well as +// global memory parameters (e.g. target heap size) used by the collector. +void jl_gc_init(void); +// Spawns GC threads. +void jl_start_gc_threads(void); + +// ========================================================================= // +// Per-thread Initialization +// ========================================================================= // + +// Initializes thread-local data structures such as thread-local object pools, +// thread-local remembered sets and thread-local allocation counters. +// Should be called exactly once per Julia thread. +void jl_init_thread_heap(struct _jl_tls_states_t *ptls) JL_NOTSAFEPOINT; +// Deallocates any memory previously used for thread-local GC data structures. +// Mostly used to ensure that we perform this memory cleanup for foreign threads that are +// about to leave Julia. +void jl_free_thread_gc_state(struct _jl_tls_states_t *ptls); + +// ========================================================================= // +// Controls +// ========================================================================= // + +typedef enum { + JL_GC_AUTO = 0, // use heuristics to determine the collection type + JL_GC_FULL = 1, // force a full collection + JL_GC_INCREMENTAL = 2, // force an incremental collection +} jl_gc_collection_t; +// Enables or disables (depending on the value of the argument) the collector. Returns +// whether GC was previously enabled. +JL_DLLEXPORT int jl_gc_enable(int on); +// Returns whether the collector is enabled. +JL_DLLEXPORT int jl_gc_is_enabled(void); +// Sets a soft limit to Julia's heap. +JL_DLLEXPORT void jl_gc_set_max_memory(uint64_t max_mem); +// Runs a GC cycle. This function's parameter determines whether we're running an +// incremental, full, or automatic (i.e. heuristic driven) collection. Returns whether we +// should run a collection cycle again (e.g. a full mark right after a full sweep to ensure +// we do a full heap traversal). +JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t collection); + +// ========================================================================= // +// Metrics +// ========================================================================= // + +// Retrieves Julia's `GC_Num` (structure that stores GC statistics). +JL_DLLEXPORT jl_gc_num_t jl_gc_num(void); +// Returns the difference between the current value of total live bytes now +// (live bytes at the last collection plus number of bytes allocated since then), +// compared to the value at the last time this function was called. +JL_DLLEXPORT int64_t jl_gc_diff_total_bytes(void) JL_NOTSAFEPOINT; +// Returns the difference between the current value of total live bytes now +// (live bytes at the last collection plus number of bytes allocated since then) +// compared to the value at the last time this function was called. The offset parameter +// is subtracted from this value in order to obtain the return value. +JL_DLLEXPORT int64_t jl_gc_sync_total_bytes(int64_t offset) JL_NOTSAFEPOINT; +// Returns the number of pool allocated bytes. This could always return 0 for GC +// implementations that do not use pools. +JL_DLLEXPORT int64_t jl_gc_pool_live_bytes(void); +// Returns the number of live bytes at the end of the last collection cycle +// (doesn't include the number of allocated bytes since then). +JL_DLLEXPORT int64_t jl_gc_live_bytes(void); +// Stores the number of live bytes at the end of the last collection cycle plus the number +// of bytes we allocated since then into the 64-bit integer pointer passed as an argument. +JL_DLLEXPORT void jl_gc_get_total_bytes(int64_t *bytes) JL_NOTSAFEPOINT; +// Retrieves the value of Julia's soft heap limit. +JL_DLLEXPORT uint64_t jl_gc_get_max_memory(void); +// High-resolution (nano-seconds) value of total time spent in GC. +JL_DLLEXPORT uint64_t jl_gc_total_hrtime(void); + +// ========================================================================= // +// Allocation +// ========================================================================= // + +// Allocates small objects and increments Julia allocation counterst. Size of the object +// header must be included in the object size. The (possibly unused in some implementations) +// offset to the arena in which we're allocating is passed in the second parameter, and the +// object size in the third parameter. If thread-local allocators are used, then this +// function should allocate in the thread-local allocator of the thread referenced by the +// jl_ptls_t argument. An additional (last) parameter containing information about the type +// of the object being allocated may be used to record an allocation of that type in the +// allocation profiler. +JL_DLLEXPORT struct _jl_value_t *jl_gc_small_alloc(struct _jl_tls_states_t *ptls, + int offset, int osize, + struct _jl_value_t *type); +// Description: Allocates large objects and increments Julia allocation counters. Size of +// the object header must be included in the object size. If thread-local allocators are +// used, then this function should allocate in the thread-local allocator of the thread +// referenced by the jl_ptls_t argument. An additional (last) parameter containing +// information about the type of the object being allocated may be used to record an +// allocation of that type in the allocation profiler. +JL_DLLEXPORT struct _jl_value_t *jl_gc_big_alloc(struct _jl_tls_states_t *ptls, size_t sz, + struct _jl_value_t *type); +// Wrapper around Libc malloc that updates Julia allocation counters. +JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz); +// Wrapper around Libc calloc that updates Julia allocation counters. +JL_DLLEXPORT void *jl_gc_counted_calloc(size_t nm, size_t sz); +// Wrapper around Libc free that updates Julia allocation counters. +JL_DLLEXPORT void jl_gc_counted_free_with_size(void *p, size_t sz); +// Wrapper around Libc realloc that updates Julia allocation counters. +JL_DLLEXPORT void *jl_gc_counted_realloc_with_old_size(void *p, size_t old, size_t sz); +// Wrapper around Libc malloc that allocates a memory region with a few additional machine +// words before the actual payload that are used to record the size of the requested +// allocation. Also updates Julia allocation counters. The function returns a pointer to the +// payload as a result of the allocation. +JL_DLLEXPORT void *jl_malloc(size_t sz); +// Wrapper around Libc calloc that allocates a memory region with a few additional machine +// words before the actual payload that are used to record the size of the requested +// allocation. Also updates Julia allocation counters. The function returns a pointer to the +// payload as a result of the allocation. +JL_DLLEXPORT void *jl_calloc(size_t nm, size_t sz); +// Wrapper around Libc free that takes a pointer to the payload of a memory region allocated +// with jl_malloc or jl_calloc, and uses the size information stored in the first machine +// words of the memory buffer update Julia allocation counters, and then frees the +// corresponding memory buffer. +JL_DLLEXPORT void jl_free(void *p); +// Wrapper around Libc realloc that takes a memory region allocated with jl_malloc or +// jl_calloc, and uses the size information stored in the first machine words of the memory +// buffer to update Julia allocation counters, reallocating the corresponding memory buffer +// in the end. +JL_DLLEXPORT void *jl_realloc(void *p, size_t sz); +// Wrapper around Libc malloc that's used to dynamically allocate memory for Arrays and +// Strings. It increments Julia allocation counters and should check whether we're close to +// the Julia heap target, and therefore, whether we should run a collection. Note that this +// doesn't record the size of the allocation request in a side metadata (i.e. a few words in +// front of the memory payload): this function is used for Julia object allocations, and we +// assume that there is already a field in the Julia object being allocated that we may use +// to store the size of the memory buffer. +JL_DLLEXPORT void *jl_gc_managed_malloc(size_t sz); +// Allocates a new weak-reference, assigns its value and increments Julia allocation +// counters. If thread-local allocators are used, then this function should allocate in the +// thread-local allocator of the thread referenced by the first jl_ptls_t argument. +JL_DLLEXPORT struct _jl_weakref_t *jl_gc_new_weakref_th(struct _jl_tls_states_t *ptls, + struct _jl_value_t *value); +// Allocates a new weak-reference, assigns its value and increments Julia allocation +// counters. If thread-local allocators are used, then this function should allocate in the +// thread-local allocator of the current thread. +JL_DLLEXPORT struct _jl_weakref_t *jl_gc_new_weakref(struct _jl_value_t *value); +// Allocates an object whose size is specified by the function argument and increments Julia +// allocation counters. If thread-local allocators are used, then this function should +// allocate in the thread-local allocator of the current thread. +JL_DLLEXPORT struct _jl_value_t *jl_gc_allocobj(size_t sz); +// Permanently allocates a memory slot of the size specified by the first parameter. This +// block of memory is allocated in an immortal region that is never swept. The second +// parameter specifies whether the memory should be filled with zeros. The third and fourth +// parameters specify the alignment and an offset in bytes, respectively. Specifically, the +// pointer obtained by advancing the result of this function by the number of bytes +// specified in the fourth parameter will be aligned according to the value given by the +// third parameter in bytes. +JL_DLLEXPORT void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, + unsigned offset) JL_NOTSAFEPOINT; +// Permanently allocates an object of the size specified by the first parameter. Size of the +// object header must be included in the object size. This object is allocated in an +// immortal region that is never swept. The second parameter specifies the type of the +// object being allocated and will be used to set the object header. +struct _jl_value_t *jl_gc_permobj(size_t sz, void *ty) JL_NOTSAFEPOINT; + +// ========================================================================= // +// Runtime Write-Barriers +// ========================================================================= // + +// Write barrier slow-path. If a generational collector is used, +// it may enqueue an old object into the remembered set of the calling thread. +JL_DLLEXPORT void jl_gc_queue_root(const struct _jl_value_t *ptr) JL_NOTSAFEPOINT; +// In a generational collector is used, this function walks over the fields of the +// object specified by the second parameter (as defined by the data type in the third +// parameter). If a field points to a young object, the first parameter is enqueued into the +// remembered set of the calling thread. +JL_DLLEXPORT void jl_gc_queue_multiroot(const struct _jl_value_t *root, const void *stored, + struct _jl_datatype_t *dt) JL_NOTSAFEPOINT; +// If a generational collector is used, checks whether the function argument points to an +// old object, and if so, calls the write barrier slow path above. In most cases, this +// function is used when its caller has verified that there is a young reference in the +// object that's being passed as an argument to this function. +STATIC_INLINE void jl_gc_wb_back(const void *ptr) JL_NOTSAFEPOINT; +// Write barrier function that must be used after pointer writes to heap-allocated objects – +// the value of the field being written must also point to a heap-allocated object. +// If a generational collector is used, it may check whether the two function arguments are +// in different GC generations (i.e. if the first argument points to an old object and the +// second argument points to a young object), and if so, call the write barrier slow-path. +STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT; +// Write-barrier function that must be used after copying multiple fields of an object into +// another. It should be semantically equivalent to triggering multiple write barriers – one +// per field of the object being copied, but may be special-cased for performance reasons. +STATIC_INLINE void jl_gc_multi_wb(const void *parent, + const struct _jl_value_t *ptr) JL_NOTSAFEPOINT; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/gc-page-profiler.c b/src/gc-page-profiler.c index 2e876e4b7b4d6..2625fa812781a 100644 --- a/src/gc-page-profiler.c +++ b/src/gc-page-profiler.c @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license #include "gc-page-profiler.h" +#include "julia.h" #ifdef __cplusplus extern "C" { diff --git a/src/gc-page-profiler.h b/src/gc-page-profiler.h index 28989f8f8e206..0dd72ad072fa9 100644 --- a/src/gc-page-profiler.h +++ b/src/gc-page-profiler.h @@ -3,7 +3,7 @@ #ifndef GC_PAGE_PROFILER_H #define GC_PAGE_PROFILER_H -#include "gc.h" +#include "gc-stock.h" #ifdef __cplusplus extern "C" { diff --git a/src/gc-pages.c b/src/gc-pages.c index 971dbe92d7fac..71d59de29166f 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "gc.h" +#include "gc-common.h" +#include "gc-stock.h" #ifndef _OS_WINDOWS_ # include #endif diff --git a/src/gc-stacks.c b/src/gc-stacks.c index 2f6075b56b8ef..5706f4ce67c1d 100644 --- a/src/gc-stacks.c +++ b/src/gc-stacks.c @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "gc.h" +#include "gc-common.h" +#include "threading.h" #ifndef _OS_WINDOWS_ # include #endif diff --git a/src/gc.c b/src/gc-stock.c similarity index 89% rename from src/gc.c rename to src/gc-stock.c index 3ab0aa4b1bf1b..1fc2087da6503 100644 --- a/src/gc.c +++ b/src/gc-stock.c @@ -1,6 +1,9 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "gc.h" +#include "gc-common.h" +#include "gc-stock.h" +#include "gc-alloc-profiler.h" +#include "gc-heap-snapshot.h" #include "gc-page-profiler.h" #include "julia.h" #include "julia_atomics.h" @@ -38,125 +41,6 @@ uv_mutex_t gc_queue_observer_lock; // Tag for sentinel nodes in bigval list uintptr_t gc_bigval_sentinel_tag; -// Linked list of callback functions - -typedef void (*jl_gc_cb_func_t)(void); - -typedef struct jl_gc_callback_list_t { - struct jl_gc_callback_list_t *next; - jl_gc_cb_func_t func; -} jl_gc_callback_list_t; - -static jl_gc_callback_list_t *gc_cblist_root_scanner; -static jl_gc_callback_list_t *gc_cblist_task_scanner; -static jl_gc_callback_list_t *gc_cblist_pre_gc; -static jl_gc_callback_list_t *gc_cblist_post_gc; -static jl_gc_callback_list_t *gc_cblist_notify_external_alloc; -static jl_gc_callback_list_t *gc_cblist_notify_external_free; -static jl_gc_callback_list_t *gc_cblist_notify_gc_pressure; - -#define gc_invoke_callbacks(ty, list, args) \ - do { \ - for (jl_gc_callback_list_t *cb = list; \ - cb != NULL; \ - cb = cb->next) \ - { \ - ((ty)(cb->func)) args; \ - } \ - } while (0) - -static void jl_gc_register_callback(jl_gc_callback_list_t **list, - jl_gc_cb_func_t func) -{ - while (*list != NULL) { - if ((*list)->func == func) - return; - list = &((*list)->next); - } - *list = (jl_gc_callback_list_t *)malloc_s(sizeof(jl_gc_callback_list_t)); - (*list)->next = NULL; - (*list)->func = func; -} - -static void jl_gc_deregister_callback(jl_gc_callback_list_t **list, - jl_gc_cb_func_t func) -{ - while (*list != NULL) { - if ((*list)->func == func) { - jl_gc_callback_list_t *tmp = *list; - (*list) = (*list)->next; - free(tmp); - return; - } - list = &((*list)->next); - } -} - -JL_DLLEXPORT void jl_gc_set_cb_root_scanner(jl_gc_cb_root_scanner_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_root_scanner, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_root_scanner, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_task_scanner(jl_gc_cb_task_scanner_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_task_scanner, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_task_scanner, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_pre_gc(jl_gc_cb_pre_gc_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_pre_gc, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_pre_gc, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_post_gc(jl_gc_cb_post_gc_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_post_gc, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_post_gc, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_notify_external_alloc(jl_gc_cb_notify_external_alloc_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_notify_external_alloc, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_notify_external_alloc, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_notify_external_free(jl_gc_cb_notify_external_free_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_notify_external_free, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_notify_external_free, (jl_gc_cb_func_t)cb); -} - -JL_DLLEXPORT void jl_gc_set_cb_notify_gc_pressure(jl_gc_cb_notify_gc_pressure_t cb, int enable) -{ - if (enable) - jl_gc_register_callback(&gc_cblist_notify_gc_pressure, (jl_gc_cb_func_t)cb); - else - jl_gc_deregister_callback(&gc_cblist_notify_gc_pressure, (jl_gc_cb_func_t)cb); -} - -// Protect all access to `finalizer_list_marked` and `to_finalize`. -// For accessing `ptls->finalizers`, the lock is needed if a thread -// is going to realloc the buffer (of its own list) or accessing the -// list of another thread -static jl_mutex_t finalizers_lock; - -// mutex for gc-heap-snapshot. -jl_mutex_t heapsnapshot_lock; - // Flag that tells us whether we need to support conservative marking // of objects. static _Atomic(int) support_conservative_marking = 0; @@ -193,406 +77,11 @@ static _Atomic(int) support_conservative_marking = 0; * finalizers in unmanaged (GC safe) mode. */ -jl_gc_num_t gc_num = {0}; -static size_t last_long_collect_interval; -int gc_n_threads; -jl_ptls_t* gc_all_tls_states; gc_heapstatus_t gc_heap_stats = {0}; -int next_sweep_full = 0; -const uint64_t _jl_buff_tag[3] = {0x4eadc0004eadc000ull, 0x4eadc0004eadc000ull, 0x4eadc0004eadc000ull}; // aka 0xHEADER00 -JL_DLLEXPORT uintptr_t jl_get_buff_tag(void) JL_NOTSAFEPOINT -{ - return jl_buff_tag; -} // List of big objects in oldest generation (`GC_OLD_MARKED`). Not per-thread. Accessed only by master thread. bigval_t *oldest_generation_of_bigvals = NULL; -// -- Finalization -- -// `ptls->finalizers` and `finalizer_list_marked` might have tagged pointers. -// If an object pointer has the lowest bit set, the next pointer is an unboxed c function pointer. -// If an object pointer has the second lowest bit set, the current pointer is a c object pointer. -// It must be aligned at least 4, and it finalized immediately (at "quiescence"). -// `to_finalize` should not have tagged pointers. -arraylist_t finalizer_list_marked; -arraylist_t to_finalize; -JL_DLLEXPORT _Atomic(int) jl_gc_have_pending_finalizers = 0; - -void jl_gc_wait_for_the_world(jl_ptls_t* gc_all_tls_states, int gc_n_threads); - -// malloc wrappers, aligned allocation - -#if defined(_OS_WINDOWS_) -STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) -{ - return _aligned_malloc(sz ? sz : 1, align); -} -STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT -{ - _aligned_free(p); -} -#else -STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) -{ -#if defined(_P64) || defined(__APPLE__) - if (align <= 16) - return malloc(sz); -#endif - void *ptr; - if (posix_memalign(&ptr, align, sz)) - return NULL; - return ptr; -} -STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT -{ - free(p); -} -#endif -#define malloc_cache_align(sz) jl_malloc_aligned(sz, JL_CACHE_BYTE_ALIGNMENT) - -static void schedule_finalization(void *o, void *f) JL_NOTSAFEPOINT -{ - arraylist_push(&to_finalize, o); - arraylist_push(&to_finalize, f); - // doesn't need release, since we'll keep checking (on the reader) until we see the work and - // release our lock, and that will have a release barrier by then - jl_atomic_store_relaxed(&jl_gc_have_pending_finalizers, 1); -} - -static void run_finalizer(jl_task_t *ct, void *o, void *ff) -{ - int ptr_finalizer = gc_ptr_tag(o, 1); - o = gc_ptr_clear_tag(o, 3); - if (ptr_finalizer) { - ((void (*)(void*))ff)((void*)o); - return; - } - JL_TRY { - size_t last_age = ct->world_age; - ct->world_age = jl_atomic_load_acquire(&jl_world_counter); - jl_apply_generic((jl_value_t*)ff, (jl_value_t**)&o, 1); - ct->world_age = last_age; - } - JL_CATCH { - jl_printf((JL_STREAM*)STDERR_FILENO, "error in running finalizer: "); - jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception(ct)); - jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); - jlbacktrace(); // written to STDERR_FILENO - } -} - -// if `need_sync` is true, the `list` is the `finalizers` list of another -// thread and we need additional synchronizations -static void finalize_object(arraylist_t *list, jl_value_t *o, - arraylist_t *copied_list, int need_sync) JL_NOTSAFEPOINT -{ - // The acquire load makes sure that the first `len` objects are valid. - // If `need_sync` is true, all mutations of the content should be limited - // to the first `oldlen` elements and no mutation is allowed after the - // new length is published with the `cmpxchg` at the end of the function. - // This way, the mutation should not conflict with the owning thread, - // which only writes to locations later than `len` - // and will not resize the buffer without acquiring the lock. - size_t len = need_sync ? jl_atomic_load_acquire((_Atomic(size_t)*)&list->len) : list->len; - size_t oldlen = len; - void **items = list->items; - size_t j = 0; - for (size_t i = 0; i < len; i += 2) { - void *v = items[i]; - int move = 0; - if (o == (jl_value_t*)gc_ptr_clear_tag(v, 1)) { - void *f = items[i + 1]; - move = 1; - arraylist_push(copied_list, v); - arraylist_push(copied_list, f); - } - if (move || __unlikely(!v)) { - // remove item - } - else { - if (j < i) { - items[j] = items[i]; - items[j+1] = items[i+1]; - } - j += 2; - } - } - len = j; - if (oldlen == len) - return; - if (need_sync) { - // The memset needs to be unconditional since the thread might have - // already read the length. - // The `memset` (like any other content mutation) has to be done - // **before** the `cmpxchg` which publishes the length. - memset(&items[len], 0, (oldlen - len) * sizeof(void*)); - jl_atomic_cmpswap((_Atomic(size_t)*)&list->len, &oldlen, len); - } - else { - list->len = len; - } -} - -// The first two entries are assumed to be empty and the rest are assumed to -// be pointers to `jl_value_t` objects -static void jl_gc_push_arraylist(jl_task_t *ct, arraylist_t *list) JL_NOTSAFEPOINT -{ - void **items = list->items; - items[0] = (void*)JL_GC_ENCODE_PUSHARGS(list->len - 2); - items[1] = ct->gcstack; - ct->gcstack = (jl_gcframe_t*)items; -} - -// Same assumption as `jl_gc_push_arraylist`. Requires the finalizers lock -// to be hold for the current thread and will release the lock when the -// function returns. -static void jl_gc_run_finalizers_in_list(jl_task_t *ct, arraylist_t *list) JL_NOTSAFEPOINT_LEAVE -{ - // Avoid marking `ct` as non-migratable via an `@async` task (as noted in the docstring - // of `finalizer`) in a finalizer: - uint8_t sticky = ct->sticky; - // empty out the first two entries for the GC frame - arraylist_push(list, list->items[0]); - arraylist_push(list, list->items[1]); - jl_gc_push_arraylist(ct, list); - void **items = list->items; - size_t len = list->len; - JL_UNLOCK_NOGC(&finalizers_lock); - // run finalizers in reverse order they were added, so lower-level finalizers run last - for (size_t i = len-4; i >= 2; i -= 2) - run_finalizer(ct, items[i], items[i + 1]); - // first entries were moved last to make room for GC frame metadata - run_finalizer(ct, items[len-2], items[len-1]); - // matches the jl_gc_push_arraylist above - JL_GC_POP(); - ct->sticky = sticky; -} - -static uint64_t finalizer_rngState[JL_RNG_SIZE]; - -void jl_rng_split(uint64_t dst[JL_RNG_SIZE], uint64_t src[JL_RNG_SIZE]) JL_NOTSAFEPOINT; - -JL_DLLEXPORT void jl_gc_init_finalizer_rng_state(void) -{ - jl_rng_split(finalizer_rngState, jl_current_task->rngState); -} - -static void run_finalizers(jl_task_t *ct, int finalizers_thread) -{ - // Racy fast path: - // The race here should be OK since the race can only happen if - // another thread is writing to it with the lock held. In such case, - // we don't need to run pending finalizers since the writer thread - // will flush it. - if (to_finalize.len == 0) - return; - JL_LOCK_NOGC(&finalizers_lock); - if (to_finalize.len == 0) { - JL_UNLOCK_NOGC(&finalizers_lock); - return; - } - arraylist_t copied_list; - memcpy(&copied_list, &to_finalize, sizeof(copied_list)); - if (to_finalize.items == to_finalize._space) { - copied_list.items = copied_list._space; - } - jl_atomic_store_relaxed(&jl_gc_have_pending_finalizers, 0); - arraylist_new(&to_finalize, 0); - - uint64_t save_rngState[JL_RNG_SIZE]; - memcpy(&save_rngState[0], &ct->rngState[0], sizeof(save_rngState)); - jl_rng_split(ct->rngState, finalizer_rngState); - - // This releases the finalizers lock. - int8_t was_in_finalizer = ct->ptls->in_finalizer; - ct->ptls->in_finalizer = !finalizers_thread; - jl_gc_run_finalizers_in_list(ct, &copied_list); - ct->ptls->in_finalizer = was_in_finalizer; - arraylist_free(&copied_list); - - memcpy(&ct->rngState[0], &save_rngState[0], sizeof(save_rngState)); -} - -JL_DLLEXPORT void jl_gc_run_pending_finalizers(jl_task_t *ct) -{ - if (ct == NULL) - ct = jl_current_task; - jl_ptls_t ptls = ct->ptls; - if (!ptls->in_finalizer && ptls->locks.len == 0 && ptls->finalizers_inhibited == 0 && ptls->engine_nqueued == 0) { - run_finalizers(ct, 0); - } -} - -JL_DLLEXPORT int jl_gc_get_finalizers_inhibited(jl_ptls_t ptls) -{ - if (ptls == NULL) - ptls = jl_current_task->ptls; - return ptls->finalizers_inhibited; -} - -JL_DLLEXPORT void jl_gc_disable_finalizers_internal(void) -{ - jl_ptls_t ptls = jl_current_task->ptls; - ptls->finalizers_inhibited++; -} - -JL_DLLEXPORT void jl_gc_enable_finalizers_internal(void) -{ - jl_task_t *ct = jl_current_task; -#ifdef NDEBUG - ct->ptls->finalizers_inhibited--; -#else - jl_gc_enable_finalizers(ct, 1); -#endif -} - -JL_DLLEXPORT void jl_gc_enable_finalizers(jl_task_t *ct, int on) -{ - if (ct == NULL) - ct = jl_current_task; - jl_ptls_t ptls = ct->ptls; - int old_val = ptls->finalizers_inhibited; - int new_val = old_val + (on ? -1 : 1); - if (new_val < 0) { - JL_TRY { - jl_error(""); // get a backtrace - } - JL_CATCH { - jl_printf((JL_STREAM*)STDERR_FILENO, "WARNING: GC finalizers already enabled on this thread.\n"); - // Only print the backtrace once, to avoid spamming the logs - static int backtrace_printed = 0; - if (backtrace_printed == 0) { - backtrace_printed = 1; - jlbacktrace(); // written to STDERR_FILENO - } - } - return; - } - ptls->finalizers_inhibited = new_val; - if (jl_atomic_load_relaxed(&jl_gc_have_pending_finalizers)) { - jl_gc_run_pending_finalizers(ct); - } -} - -JL_DLLEXPORT int8_t jl_gc_is_in_finalizer(void) -{ - return jl_current_task->ptls->in_finalizer; -} - -static void schedule_all_finalizers(arraylist_t *flist) JL_NOTSAFEPOINT -{ - void **items = flist->items; - size_t len = flist->len; - for(size_t i = 0; i < len; i+=2) { - void *v = items[i]; - void *f = items[i + 1]; - if (__unlikely(!v)) - continue; - schedule_finalization(v, f); - } - flist->len = 0; -} - -void jl_gc_run_all_finalizers(jl_task_t *ct) -{ - int gc_n_threads; - jl_ptls_t* gc_all_tls_states; - gc_n_threads = jl_atomic_load_acquire(&jl_n_threads); - gc_all_tls_states = jl_atomic_load_relaxed(&jl_all_tls_states); - // this is called from `jl_atexit_hook`; threads could still be running - // so we have to guard the finalizers' lists - JL_LOCK_NOGC(&finalizers_lock); - schedule_all_finalizers(&finalizer_list_marked); - for (int i = 0; i < gc_n_threads; i++) { - jl_ptls_t ptls2 = gc_all_tls_states[i]; - if (ptls2 != NULL) - schedule_all_finalizers(&ptls2->finalizers); - } - // unlock here because `run_finalizers` locks this - JL_UNLOCK_NOGC(&finalizers_lock); - run_finalizers(ct, 1); -} - -void jl_gc_add_finalizer_(jl_ptls_t ptls, void *v, void *f) JL_NOTSAFEPOINT -{ - assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_STATE_UNSAFE); - arraylist_t *a = &ptls->finalizers; - // This acquire load and the release store at the end are used to - // synchronize with `finalize_object` on another thread. Apart from the GC, - // which is blocked by entering a unsafe region, there might be only - // one other thread accessing our list in `finalize_object` - // (only one thread since it needs to acquire the finalizer lock). - // Similar to `finalize_object`, all content mutation has to be done - // between the acquire and the release of the length. - size_t oldlen = jl_atomic_load_acquire((_Atomic(size_t)*)&a->len); - if (__unlikely(oldlen + 2 > a->max)) { - JL_LOCK_NOGC(&finalizers_lock); - // `a->len` might have been modified. - // Another possibility is to always grow the array to `oldlen + 2` but - // it's simpler this way and uses slightly less memory =) - oldlen = a->len; - arraylist_grow(a, 2); - a->len = oldlen; - JL_UNLOCK_NOGC(&finalizers_lock); - } - void **items = a->items; - items[oldlen] = v; - items[oldlen + 1] = f; - jl_atomic_store_release((_Atomic(size_t)*)&a->len, oldlen + 2); -} - -JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) JL_NOTSAFEPOINT -{ - jl_gc_add_finalizer_(ptls, (void*)(((uintptr_t)v) | 1), f); -} - -// schedule f(v) to call at the next quiescent interval (aka after the next safepoint/region on all threads) -JL_DLLEXPORT void jl_gc_add_quiescent(jl_ptls_t ptls, void **v, void *f) JL_NOTSAFEPOINT -{ - assert(!gc_ptr_tag(v, 3)); - jl_gc_add_finalizer_(ptls, (void*)(((uintptr_t)v) | 3), f); -} - -JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT -{ - if (__unlikely(jl_typetagis(f, jl_voidpointer_type))) { - jl_gc_add_ptr_finalizer(ptls, v, jl_unbox_voidpointer(f)); - } - else { - jl_gc_add_finalizer_(ptls, v, f); - } -} - -JL_DLLEXPORT void jl_finalize_th(jl_task_t *ct, jl_value_t *o) -{ - JL_LOCK_NOGC(&finalizers_lock); - // Copy the finalizers into a temporary list so that code in the finalizer - // won't change the list as we loop through them. - // This list is also used as the GC frame when we are running the finalizers - arraylist_t copied_list; - arraylist_new(&copied_list, 0); - // No need to check the to_finalize list since the user is apparently - // still holding a reference to the object - int gc_n_threads; - jl_ptls_t* gc_all_tls_states; - gc_n_threads = jl_atomic_load_acquire(&jl_n_threads); - gc_all_tls_states = jl_atomic_load_relaxed(&jl_all_tls_states); - for (int i = 0; i < gc_n_threads; i++) { - jl_ptls_t ptls2 = gc_all_tls_states[i]; - if (ptls2 != NULL) - finalize_object(&ptls2->finalizers, o, &copied_list, jl_atomic_load_relaxed(&ct->tid) != i); - } - finalize_object(&finalizer_list_marked, o, &copied_list, 0); - if (copied_list.len > 0) { - // This releases the finalizers lock. - jl_gc_run_finalizers_in_list(ct, &copied_list); - } - else { - JL_UNLOCK_NOGC(&finalizers_lock); - } - arraylist_free(&copied_list); -} - // explicitly scheduled objects for the sweepfunc callback static void gc_sweep_foreign_objs_in_list(arraylist_t *objs) JL_NOTSAFEPOINT { @@ -705,13 +194,13 @@ static int64_t scanned_bytes; // young bytes scanned while marking static int64_t perm_scanned_bytes; // old bytes scanned while marking int prev_sweep_full = 1; int current_sweep_full = 0; +int next_sweep_full = 0; int under_pressure = 0; // Full collection heuristics static int64_t live_bytes = 0; static int64_t promoted_bytes = 0; static int64_t last_live_bytes = 0; // live_bytes at last collection -static int64_t t_start = 0; // Time GC starts; #ifdef __GLIBC__ // maxrss at last malloc_trim static int64_t last_trim_maxrss = 0; @@ -861,8 +350,7 @@ STATIC_INLINE void maybe_collect(jl_ptls_t ptls) // weak references -JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref_th(jl_ptls_t ptls, - jl_value_t *value) +JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref_th(jl_ptls_t ptls, jl_value_t *value) { jl_weakref_t *wr = (jl_weakref_t*)jl_gc_alloc(ptls, sizeof(void*), jl_weakref_type); @@ -3751,7 +3239,7 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection) live_bytes += -gc_num.freed + gc_num.allocd; jl_timing_counter_dec(JL_TIMING_COUNTER_HeapSize, gc_num.freed); - gc_time_summary(sweep_full, t_start, gc_end_time, gc_num.freed, + gc_time_summary(sweep_full, gc_start_time, gc_end_time, gc_num.freed, live_bytes, gc_num.interval, pause, gc_num.time_to_safepoint, gc_num.mark_time, gc_num.sweep_time); @@ -3972,6 +3460,79 @@ void jl_start_gc_threads(void) } } +STATIC_INLINE int may_mark(void) JL_NOTSAFEPOINT +{ + return (jl_atomic_load(&gc_n_threads_marking) > 0); +} + +STATIC_INLINE int may_sweep(jl_ptls_t ptls) JL_NOTSAFEPOINT +{ + return (jl_atomic_load(&ptls->gc_tls.gc_sweeps_requested) > 0); +} + +// parallel gc thread function +void jl_parallel_gc_threadfun(void *arg) +{ + jl_threadarg_t *targ = (jl_threadarg_t*)arg; + + // initialize this thread (set tid and create heap) + jl_ptls_t ptls = jl_init_threadtls(targ->tid); + void *stack_lo, *stack_hi; + jl_init_stack_limits(0, &stack_lo, &stack_hi); + // warning: this changes `jl_current_task`, so be careful not to call that from this function + jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); + JL_GC_PROMISE_ROOTED(ct); + (void)jl_atomic_fetch_add_relaxed(&n_threads_running, -1); + // wait for all threads + jl_gc_state_set(ptls, JL_GC_PARALLEL_COLLECTOR_THREAD, JL_GC_STATE_UNSAFE); + uv_barrier_wait(targ->barrier); + + // free the thread argument here + free(targ); + + while (1) { + uv_mutex_lock(&gc_threads_lock); + while (!may_mark() && !may_sweep(ptls)) { + uv_cond_wait(&gc_threads_cond, &gc_threads_lock); + } + uv_mutex_unlock(&gc_threads_lock); + assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_PARALLEL_COLLECTOR_THREAD); + gc_mark_loop_parallel(ptls, 0); + if (may_sweep(ptls)) { + assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_PARALLEL_COLLECTOR_THREAD); + gc_sweep_pool_parallel(ptls); + jl_atomic_fetch_add(&ptls->gc_tls.gc_sweeps_requested, -1); + } + } +} + +// concurrent gc thread function +void jl_concurrent_gc_threadfun(void *arg) +{ + jl_threadarg_t *targ = (jl_threadarg_t*)arg; + + // initialize this thread (set tid and create heap) + jl_ptls_t ptls = jl_init_threadtls(targ->tid); + void *stack_lo, *stack_hi; + jl_init_stack_limits(0, &stack_lo, &stack_hi); + // warning: this changes `jl_current_task`, so be careful not to call that from this function + jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); + JL_GC_PROMISE_ROOTED(ct); + (void)jl_atomic_fetch_add_relaxed(&n_threads_running, -1); + // wait for all threads + jl_gc_state_set(ptls, JL_GC_CONCURRENT_COLLECTOR_THREAD, JL_GC_STATE_UNSAFE); + uv_barrier_wait(targ->barrier); + + // free the thread argument here + free(targ); + + while (1) { + assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_CONCURRENT_COLLECTOR_THREAD); + uv_sem_wait(&gc_sweep_assists_needed); + gc_free_pages(); + } +} + // System-wide initializations void jl_gc_init(void) { @@ -3997,7 +3558,6 @@ void jl_gc_init(void) arraylist_new(&to_finalize, 0); jl_atomic_store_relaxed(&gc_heap_stats.heap_target, default_collect_interval); gc_num.interval = default_collect_interval; - last_long_collect_interval = default_collect_interval; gc_num.allocd = 0; gc_num.max_pause = 0; gc_num.max_memory = 0; @@ -4018,8 +3578,6 @@ void jl_gc_init(void) hint = min_heap_size_hint; jl_gc_set_max_memory(hint - mem_reserve); } - - t_start = jl_hrtime(); } JL_DLLEXPORT void jl_gc_set_max_memory(uint64_t max_mem) @@ -4035,12 +3593,6 @@ JL_DLLEXPORT uint64_t jl_gc_get_max_memory(void) return max_total_memory; } -// callback for passing OOM errors from gmp -JL_DLLEXPORT void jl_throw_out_of_memory_error(void) -{ - jl_throw(jl_memory_exception); -} - // allocation wrappers that track allocation and let collection run JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz) @@ -4290,15 +3842,16 @@ void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, unsigned offset) return p; } -JL_DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) -{ - jl_ptls_t ptls = jl_current_task->ptls; - jl_gc_add_finalizer_th(ptls, v, f); -} - -JL_DLLEXPORT void jl_finalize(jl_value_t *o) +jl_value_t *jl_gc_permobj(size_t sz, void *ty) JL_NOTSAFEPOINT { - jl_finalize_th(jl_current_task, o); + const size_t allocsz = sz + sizeof(jl_taggedvalue_t); + unsigned align = (sz == 0 ? sizeof(void*) : (allocsz <= sizeof(void*) * 2 ? + sizeof(void*) * 2 : 16)); + jl_taggedvalue_t *o = (jl_taggedvalue_t*)jl_gc_perm_alloc(allocsz, 0, align, + sizeof(void*) % align); + uintptr_t tag = (uintptr_t)ty; + o->header = tag | GC_OLD_MARKED; + return jl_valueof(o); } JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value) diff --git a/src/gc.h b/src/gc-stock.h similarity index 92% rename from src/gc.h rename to src/gc-stock.h index 0d8421912dbc7..7176ad8b504f4 100644 --- a/src/gc.h +++ b/src/gc-stock.h @@ -18,16 +18,8 @@ #include "julia.h" #include "julia_threads.h" #include "julia_internal.h" -#include "threading.h" -#ifndef _OS_WINDOWS_ -#include -#if defined(_OS_DARWIN_) && !defined(MAP_ANONYMOUS) -#define MAP_ANONYMOUS MAP_ANON -#endif -#endif #include "julia_assert.h" -#include "gc-heap-snapshot.h" -#include "gc-alloc-profiler.h" +#include "threading.h" #ifdef __cplusplus extern "C" { @@ -41,9 +33,6 @@ extern "C" { #define GC_PAGE_SZ (1 << GC_PAGE_LG2) #define GC_PAGE_OFFSET (JL_HEAP_ALIGNMENT - (sizeof(jl_taggedvalue_t) % JL_HEAP_ALIGNMENT)) -#define jl_malloc_tag ((void*)0xdeadaa01) -#define jl_singleton_tag ((void*)0xdeadaa02) - // Used by GC_DEBUG_ENV typedef struct { uint64_t num; @@ -62,34 +51,6 @@ typedef struct { jl_alloc_num_t print; } jl_gc_debug_env_t; -// This struct must be kept in sync with the Julia type of the same name in base/timing.jl -typedef struct { - int64_t allocd; - int64_t deferred_alloc; - int64_t freed; - uint64_t malloc; - uint64_t realloc; - uint64_t poolalloc; - uint64_t bigalloc; - uint64_t freecall; - uint64_t total_time; - uint64_t total_allocd; - size_t interval; - int pause; - int full_sweep; - uint64_t max_pause; - uint64_t max_memory; - uint64_t time_to_safepoint; - uint64_t max_time_to_safepoint; - uint64_t total_time_to_safepoint; - uint64_t sweep_time; - uint64_t mark_time; - uint64_t total_sweep_time; - uint64_t total_mark_time; - uint64_t last_full_sweep; - uint64_t last_incremental_sweep; -} jl_gc_num_t; - // Array chunks (work items representing suffixes of // large arrays of pointers left to be marked) @@ -440,14 +401,9 @@ STATIC_INLINE unsigned ffs_u32(uint32_t bitvec) } #endif -extern jl_gc_num_t gc_num; extern bigval_t *oldest_generation_of_bigvals; -extern arraylist_t finalizer_list_marked; -extern arraylist_t to_finalize; extern int64_t buffered_pages; extern int gc_first_tid; -extern int gc_n_threads; -extern jl_ptls_t* gc_all_tls_states; extern gc_heapstatus_t gc_heap_stats; STATIC_INLINE int gc_first_parallel_collector_thread_id(void) JL_NOTSAFEPOINT @@ -523,31 +479,6 @@ STATIC_INLINE jl_taggedvalue_t *page_pfl_end(jl_gc_pagemeta_t *p) JL_NOTSAFEPOIN return (jl_taggedvalue_t*)(p->data + p->fl_end_offset); } -STATIC_INLINE int gc_marked(uintptr_t bits) JL_NOTSAFEPOINT -{ - return (bits & GC_MARKED) != 0; -} - -STATIC_INLINE int gc_old(uintptr_t bits) JL_NOTSAFEPOINT -{ - return (bits & GC_OLD) != 0; -} - -STATIC_INLINE uintptr_t gc_set_bits(uintptr_t tag, int bits) JL_NOTSAFEPOINT -{ - return (tag & ~(uintptr_t)3) | bits; -} - -STATIC_INLINE uintptr_t gc_ptr_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT -{ - return ((uintptr_t)v) & mask; -} - -STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT -{ - return (void*)(((uintptr_t)v) & ~mask); -} - FORCE_INLINE void gc_big_object_unlink(const bigval_t *node) JL_NOTSAFEPOINT { assert(node != oldest_generation_of_bigvals); @@ -580,6 +511,7 @@ extern uv_cond_t gc_threads_cond; extern uv_sem_t gc_sweep_assists_needed; extern _Atomic(int) gc_n_threads_marking; extern _Atomic(int) gc_n_threads_sweeping; +extern _Atomic(int) n_threads_running; extern uv_barrier_t thread_init_done; void gc_mark_queue_all_roots(jl_ptls_t ptls, jl_gc_markqueue_t *mq); void gc_mark_finlist_(jl_gc_markqueue_t *mq, jl_value_t *fl_parent, jl_value_t **fl_begin, jl_value_t **fl_end) JL_NOTSAFEPOINT; diff --git a/src/julia.h b/src/julia.h index fe511c0ced1b0..29899f2985a4f 100644 --- a/src/julia.h +++ b/src/julia.h @@ -82,6 +82,7 @@ typedef struct _jl_tls_states_t *jl_ptls_t; #ifdef JL_LIBRARY_EXPORTS #include "uv.h" #endif +#include "gc-interface.h" #include "julia_atomics.h" #include "julia_threads.h" #include "julia_assert.h" @@ -1047,35 +1048,14 @@ extern void JL_GC_POP() JL_NOTSAFEPOINT; #endif -JL_DLLEXPORT int jl_gc_enable(int on); -JL_DLLEXPORT int jl_gc_is_enabled(void); - -typedef enum { - JL_GC_AUTO = 0, // use heuristics to determine the collection type - JL_GC_FULL = 1, // force a full collection - JL_GC_INCREMENTAL = 2, // force an incremental collection -} jl_gc_collection_t; - -JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t); - JL_DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_gc_add_ptr_finalizer(jl_ptls_t ptls, jl_value_t *v, void *f) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_gc_add_quiescent(jl_ptls_t ptls, void **v, void *f) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_finalize(jl_value_t *o); -JL_DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value); -JL_DLLEXPORT jl_value_t *jl_gc_allocobj(size_t sz); JL_DLLEXPORT void *jl_malloc_stack(size_t *bufsz, struct _jl_task_t *owner) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_free_stack(void *stkbuf, size_t bufsz); -JL_DLLEXPORT void jl_gc_use(jl_value_t *a); -// Set GC memory trigger in bytes for greedy memory collecting -JL_DLLEXPORT void jl_gc_set_max_memory(uint64_t max_mem); -JL_DLLEXPORT uint64_t jl_gc_get_max_memory(void); - -JL_DLLEXPORT void jl_clear_malloc_data(void); // GC write barriers -JL_DLLEXPORT void jl_gc_queue_root(const jl_value_t *root) JL_NOTSAFEPOINT; -JL_DLLEXPORT void jl_gc_queue_multiroot(const jl_value_t *root, const void *stored, jl_datatype_t *dt) JL_NOTSAFEPOINT; STATIC_INLINE void jl_gc_wb(const void *parent, const void *ptr) JL_NOTSAFEPOINT { @@ -1107,7 +1087,6 @@ STATIC_INLINE void jl_gc_multi_wb(const void *parent, const jl_value_t *ptr) JL_ jl_gc_queue_multiroot((jl_value_t*)parent, ptr, dt); } -JL_DLLEXPORT void *jl_gc_managed_malloc(size_t sz); JL_DLLEXPORT void jl_gc_safepoint(void); JL_DLLEXPORT int jl_safepoint_suspend_thread(int tid, int waitstate); JL_DLLEXPORT void jl_safepoint_suspend_all_threads(struct _jl_task_t *ct); diff --git a/src/julia_internal.h b/src/julia_internal.h index 392fe8fd9a1fb..2ec4c9da7452b 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -311,7 +311,7 @@ static inline void memassign_safe(int hasptr, char *dst, const jl_value_t *src, memcpy(dst, jl_assume_aligned(src, sizeof(void*)), nb); } -// -- gc.c -- // +// -- GC -- // #define GC_CLEAN 0 // freshly allocated #define GC_MARKED 1 // reachable and young @@ -350,8 +350,6 @@ jl_value_t *jl_gc_small_alloc_noinline(jl_ptls_t ptls, int offset, int osize); jl_value_t *jl_gc_big_alloc_noinline(jl_ptls_t ptls, size_t allocsz); JL_DLLEXPORT int jl_gc_classify_pools(size_t sz, int *osize) JL_NOTSAFEPOINT; -JL_DLLEXPORT void *jl_gc_perm_alloc(size_t sz, int zero, - unsigned align, unsigned offset) JL_NOTSAFEPOINT; void gc_sweep_sysimg(void); @@ -544,17 +542,6 @@ STATIC_INLINE jl_gc_tracked_buffer_t *jl_gc_alloc_buf(jl_ptls_t ptls, size_t sz) return jl_gc_alloc(ptls, sz, (void*)jl_buff_tag); } -STATIC_INLINE jl_value_t *jl_gc_permobj(size_t sz, void *ty) JL_NOTSAFEPOINT -{ - const size_t allocsz = sz + sizeof(jl_taggedvalue_t); - unsigned align = (sz == 0 ? sizeof(void*) : (allocsz <= sizeof(void*) * 2 ? - sizeof(void*) * 2 : 16)); - jl_taggedvalue_t *o = (jl_taggedvalue_t*)jl_gc_perm_alloc(allocsz, 0, align, - sizeof(void*) % align); - uintptr_t tag = (uintptr_t)ty; - o->header = tag | GC_OLD_MARKED; - return jl_valueof(o); -} jl_value_t *jl_permbox8(jl_datatype_t *t, uintptr_t tag, uint8_t x); jl_value_t *jl_permbox32(jl_datatype_t *t, uintptr_t tag, uint32_t x); jl_svec_t *jl_perm_symsvec(size_t n, ...); @@ -590,14 +577,6 @@ jl_svec_t *jl_perm_symsvec(size_t n, ...); #endif #endif -JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz); - -JL_DLLEXPORT void JL_NORETURN jl_throw_out_of_memory_error(void); - - -JL_DLLEXPORT int64_t jl_gc_diff_total_bytes(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT int64_t jl_gc_sync_total_bytes(int64_t offset) JL_NOTSAFEPOINT; -void jl_gc_track_malloced_array(jl_ptls_t ptls, jl_array_t *a) JL_NOTSAFEPOINT; void jl_gc_track_malloced_genericmemory(jl_ptls_t ptls, jl_genericmemory_t *m, int isaligned) JL_NOTSAFEPOINT; size_t jl_genericmemory_nbytes(jl_genericmemory_t *a) JL_NOTSAFEPOINT; void jl_gc_count_allocd(size_t sz) JL_NOTSAFEPOINT; @@ -945,9 +924,7 @@ void jl_init_tasks(void) JL_GC_DISABLED; void jl_init_stack_limits(int ismaster, void **stack_hi, void **stack_lo) JL_NOTSAFEPOINT; jl_task_t *jl_init_root_task(jl_ptls_t ptls, void *stack_lo, void *stack_hi); void jl_init_serializer(void); -void jl_gc_init(void); void jl_init_uv(void); -void jl_init_thread_heap(jl_ptls_t ptls) JL_NOTSAFEPOINT; void jl_init_int32_int64_cache(void); JL_DLLEXPORT void jl_init_options(void); @@ -957,7 +934,6 @@ extern JL_DLLEXPORT ssize_t jl_tls_offset; extern JL_DLLEXPORT const int jl_tls_elf_support; void jl_init_threading(void); void jl_start_threads(void); -void jl_start_gc_threads(void); // Whether the GC is running extern uv_mutex_t safepoint_lock; @@ -1301,6 +1277,9 @@ void jl_push_excstack(jl_task_t *ct, jl_excstack_t **stack JL_REQUIRE_ROOTED_SLO jl_value_t *exception JL_ROOTED_ARGUMENT, jl_bt_element_t *bt_data, size_t bt_size); +// System util to get maximum RSS +JL_DLLEXPORT size_t jl_maxrss(void); + //-------------------------------------------------- // congruential random number generator // for a small amount of thread-local randomness diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp index fe32e6d09a856..0605098bec361 100644 --- a/src/llvm-final-gc-lowering.cpp +++ b/src/llvm-final-gc-lowering.cpp @@ -1,22 +1,6 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "llvm-version.h" -#include "passes.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "llvm-codegen-shared.h" -#include "julia.h" -#include "julia_internal.h" -#include "llvm-pass-helpers.h" +#include "llvm-gc-interface-passes.h" #define DEBUG_TYPE "final_gc_lowering" STATISTIC(NewGCFrameCount, "Number of lowered newGCFrameFunc intrinsics"); @@ -27,50 +11,6 @@ STATISTIC(GCAllocBytesCount, "Number of lowered GCAllocBytesFunc intrinsics"); STATISTIC(QueueGCRootCount, "Number of lowered queueGCRootFunc intrinsics"); STATISTIC(SafepointCount, "Number of lowered safepoint intrinsics"); -using namespace llvm; - -// The final GC lowering pass. This pass lowers platform-agnostic GC -// intrinsics to platform-dependent instruction sequences. The -// intrinsics it targets are those produced by the late GC frame -// lowering pass. -// -// This pass targets typical back-ends for which the standard Julia -// runtime library is available. Atypical back-ends should supply -// their own lowering pass. - -struct FinalLowerGC: private JuliaPassContext { - bool runOnFunction(Function &F); - -private: - Function *queueRootFunc; - Function *smallAllocFunc; - Function *bigAllocFunc; - Function *allocTypedFunc; - Instruction *pgcstack; - Type *T_size; - - // Lowers a `julia.new_gc_frame` intrinsic. - void lowerNewGCFrame(CallInst *target, Function &F); - - // Lowers a `julia.push_gc_frame` intrinsic. - void lowerPushGCFrame(CallInst *target, Function &F); - - // Lowers a `julia.pop_gc_frame` intrinsic. - void lowerPopGCFrame(CallInst *target, Function &F); - - // Lowers a `julia.get_gc_frame_slot` intrinsic. - void lowerGetGCFrameSlot(CallInst *target, Function &F); - - // Lowers a `julia.gc_alloc_bytes` intrinsic. - void lowerGCAllocBytes(CallInst *target, Function &F); - - // Lowers a `julia.queue_gc_root` intrinsic. - void lowerQueueGCRoot(CallInst *target, Function &F); - - // Lowers a `julia.safepoint` intrinsic. - void lowerSafepoint(CallInst *target, Function &F); -}; - void FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) { ++NewGCFrameCount; diff --git a/src/llvm-gc-interface-passes.h b/src/llvm-gc-interface-passes.h new file mode 100644 index 0000000000000..cb485751d407b --- /dev/null +++ b/src/llvm-gc-interface-passes.h @@ -0,0 +1,413 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +/* + LLVM passes that may be partially modified by a third-party GC implementation. +*/ + +#include "llvm-version.h" +#include "passes.h" + +#include "llvm/IR/DerivedTypes.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "llvm-codegen-shared.h" +#include "julia.h" +#include "julia_internal.h" +#include "julia_assert.h" +#include "llvm-pass-helpers.h" +#include +#include + +#ifndef LLVM_GC_PASSES_H +#define LLVM_GC_PASSES_H + +using namespace llvm; + +/* Julia GC Root Placement pass. For a general overview of the design of GC + root lowering, see the devdocs. This file is the actual implementation. + + The actual algorithm is fairly straightforward. First recall the goal of this + pass: + + Minimize the number of needed gc roots/stores to them subject to the constraint + that at every safepoint, any live gc-tracked pointer (i.e. for which there is + a path after this point that contains a use of this pointer) is in some gc slot. + + In particular, in order to understand this algorithm, it is important to + realize that the only places where rootedness matters is at safepoints. + + Now, the primary phases of the algorithm are: + + 1. Local Scan + + During this step, each Basic Block is inspected and analyzed for local + properties. In particular, we want to determine the ordering of any of + the following activities: + + - Any Def of a gc-tracked pointer. In general Defs are the results of + calls or loads from appropriate memory locations. Phi nodes and + selects do complicate this story slightly as described below. + - Any use of a gc-tracked or derived pointer. As described in the + devdocs, a use is in general one of + a) a load from a tracked/derived value + b) a store to a tracked/derived value + c) a store OF a tracked/derived value + d) a use of a value as a call operand (including operand bundles) + - Any safepoint + + Crucially, we also perform pointer numbering during the local scan, + assigning every Def a unique integer and caching the integer for each + derived pointer. This allows us to operate only on the set of Defs ( + represented by these integers) for the rest of the algorithm. We also + maintain some local utility information that is needed by later passes + (see the BBState struct for details). + + 2. Dataflow Computation + + This computation operates entirely over the function's control flow graph + and does not look into a basic block. The algorithm is essentially + textbook iterative data flow for liveness computation. However, the + data flow equations are slightly more complicated because we also + forward propagate rootedness information in addition to backpropagating + liveness. + + 3. Live Set Computation + + With the liveness information from the previous step, we can now compute, + for every safepoint, the set of values live at that particular safepoint. + There are three pieces of information being combined here: + i. Values that needed to be live due to local analysis (e.g. there + was a def, then a safepoint, then a use). This was computed during + local analysis. + ii. Values that are live across the basic block (i.e. they are live + at every safepoint within the basic block). This relies entirely + on the liveness information. + iii. Values that are now live-out from the basic block (i.e. they are + live at every safepoint following their def). During local + analysis, we keep, for every safepoint, those values that would + be live if they were live out. Here we can check if they are + actually live-out and make the appropriate additions to the live + set. + + Lastly, we also explicitly compute, for each value, the list of values + that are simultaneously live at some safepoint. This is known as an + "interference graph" and is the input to the next step. + + 4. GC Root coloring + + Two values which are not simultaneously live at a safepoint can share the + same slot. This is an important optimization, because otherwise long + functions would have exceptionally large GC slots, reducing performance + and bloating the size of the stack. Assigning values to these slots is + equivalent to doing graph coloring on the interference graph - the graph + where nodes are values and two values have an edge if they are + simultaneously live at a safepoint - which we computed in the previous + step. Now graph coloring in general is a hard problem. However, for SSA + form programs, (and most programs in general, by virtue of their + structure), the resulting interference graphs are chordal and can be + colored optimally in linear time by performing greedy coloring in a + perfect elimination order. Now, our interference graphs are likely not + entirely chordal due to some non-SSA corner cases. However, using the same + algorithm should still give a very good coloring while having sufficiently + low runtime. + + 5. JLCall frame optimizations + + Unlike earlier iterations of the gc root placement logic, jlcall frames + are no longer treated as a special case and need not necessarily be sunk + into the gc frame. Additionally, we now emit lifetime + intrinsics, so regular stack slot coloring will merge any jlcall frames + not sunk into the gc frame. Nevertheless performing such sinking can still + be profitable. Since all arguments to a jlcall are guaranteed to be live + at that call in some gc slot, we can attempt to rearrange the slots within + the gc-frame, or reuse slots not assigned at that particular location + for the gcframe. However, even without this optimization, stack frames + are at most two times larger than optimal (because regular stack coloring + can merge the jlcall allocas). + + N.B.: This step is not yet implemented. + + 6. Root placement + + This performs the actual insertion of the GCFrame pushes/pops, zeros out + the gc frame and creates the stores to the gc frame according to the + stack slot assignment computed in the previous step. GC frames stores + are generally sunk right before the first safe point that use them + (this is beneficial for code where the primary path does not have + safepoints, but some other path - e.g. the error path does). However, + if the first safepoint is not dominated by the definition (this can + happen due to the non-ssa corner cases), the store is inserted right after + the definition. + + 7. Cleanup + + This step performs necessary cleanup before passing the IR to codegen. In + particular, it removes any calls to julia_from_objref intrinsics and + removes the extra operand bundles from ccalls. In the future it could + also strip the addrspace information from all values as this + information is no longer needed. + + + There are a couple important special cases that deserve special attention: + + A. PHIs and Selects + + In general PHIs and selects are treated as separate defs for the purposes + of the algorithm and their operands as uses of those values. It is + important to consider however WHERE the uses of PHI's operands are + located. It is neither at the start of the basic block, because the values + do not dominate the block (so can't really consider them live-in), nor + at the end of the predecessor (because they are actually live out). + Instead it is best to think of those uses as living on the edge between + the appropriate predecessor and the block containing the PHI. + + Another concern is PHIs of derived values. Since we cannot simply root + these values by storing them to a GC slot, we need to insert a new, + artificial PHI that tracks the base pointers for the derived values. E.g. + in: + + A: + %Abase = load addrspace(10) *... + %Aderived = addrspacecast %Abase to addrspace(11) + B: + %Bbase = load addrspace(10) *... + %Bderived = addrspacecast %Bbase to addrspace(11) + C: + %phi = phi [%Aderived, %A + %Bderived, %B] + + we will insert another phi in C to track the relevant base pointers: + + %philift = phi [%Abase, %A + %Bbase, %B] + + We then pretend, for the purposes of numbering that %phi was derived from + %philift. Note that in order to be able to do this, we need to be able to + perform this lifting either during numbering or instruction scanning. + + B. Vectors of pointers/Union representations + + Since this pass runs very late in the pass pipeline, it runs after the + various vectorization passes. As a result, we have to potentially deal + with vectors of gc-tracked pointers. For the purposes of most of the + algorithm, we simply assign every element of the vector a separate number + and no changes are needed. However, those parts of the algorithm that + look at IR need to be aware of the possibility of encountering vectors of + pointers. + + Similarly, unions (e.g. in call returns) are represented as a struct of + a gc-tracked value and an argument selector. We simply assign a single + number to this struct and proceed as if it was a single pointer. However, + this again requires care at the IR level. + + C. Non mem2reg'd allocas + + Under some circumstances, allocas will still be present in the IR when + we get to this pass. We don't try very hard to handle this case, and + simply sink the alloca into the GCFrame. +*/ + +// 4096 bits == 64 words (64 bit words). Larger bit numbers are faster and doing something +// substantially smaller here doesn't actually save much memory because of malloc overhead. +// Too large is bad also though - 4096 was found to be a reasonable middle ground. +using LargeSparseBitVector = SparseBitVector<4096>; + +struct BBState { + // Uses in this BB + // These do not get updated after local analysis + LargeSparseBitVector Defs; + LargeSparseBitVector PhiOuts; + LargeSparseBitVector UpExposedUses; + // These get updated during dataflow + LargeSparseBitVector LiveIn; + LargeSparseBitVector LiveOut; + SmallVector Safepoints; + int TopmostSafepoint = -1; + bool HasSafepoint = false; + // Have we gone through this basic block in our local scan yet? + bool Done = false; +}; + +struct State { + Function *const F; + DominatorTree *DT; + + // The maximum assigned value number + int MaxPtrNumber; + // The maximum assigned safepoint number + int MaxSafepointNumber; + // Cache of numbers assigned to IR values. This includes caching of numbers + // for derived values + std::map AllPtrNumbering; + std::map> AllCompositeNumbering; + // The reverse of the previous maps + std::map ReversePtrNumbering; + // Neighbors in the coloring interference graph. I.e. for each value, the + // indices of other values that are used simultaneously at some safe point. + SmallVector Neighbors; + // The result of the local analysis + std::map BBStates; + + // Refinement map. If all of the values are rooted + // (-1 means an externally rooted value and -2 means a globally/permanently rooted value), + // the key is already rooted (but not the other way around). + // A value that can be refined to -2 never need any rooting or write barrier. + // A value that can be refined to -1 don't need local root but still need write barrier. + // At the end of `LocalScan` this map has a few properties + // 1. Values are either < 0 or dominates the key + // 2. Therefore this is a DAG + std::map> Refinements; + + // GC preserves map. All safepoints dominated by the map key, but not any + // of its uses need to preserve the values listed in the map value. + std::map> GCPreserves; + + // The assignment of numbers to safepoints. The indices in the map + // are indices into the next three maps which store safepoint properties + std::map SafepointNumbering; + + // Reverse mapping index -> safepoint + SmallVector ReverseSafepointNumbering; + + // Instructions that can return twice. For now, all values live at these + // instructions will get their own, dedicated GC frame slots, because they + // have unobservable control flow, so we can't be sure where they're + // actually live. All of these are also considered safepoints. + SmallVector ReturnsTwice; + + // The set of values live at a particular safepoint + SmallVector< LargeSparseBitVector , 0> LiveSets; + // Those values that - if live out from our parent basic block - are live + // at this safepoint. + SmallVector> LiveIfLiveOut; + // The set of values that are kept alive by the callee. + SmallVector> CalleeRoots; + // We don't bother doing liveness on Allocas that were not mem2reg'ed. + // they just get directly sunk into the root array. + SmallVector Allocas; + DenseMap ArrayAllocas; + DenseMap ShadowAllocas; + SmallVector, 0> TrackedStores; + State(Function &F) : F(&F), DT(nullptr), MaxPtrNumber(-1), MaxSafepointNumber(-1) {} +}; + + +struct LateLowerGCFrame: private JuliaPassContext { + function_ref GetDT; + LateLowerGCFrame(function_ref GetDT) : GetDT(GetDT) {} + +public: + bool runOnFunction(Function &F, bool *CFGModified = nullptr); + +private: + CallInst *pgcstack; + + void MaybeNoteDef(State &S, BBState &BBS, Value *Def, const ArrayRef &SafepointsSoFar, + SmallVector &&RefinedPtr = SmallVector()); + void NoteUse(State &S, BBState &BBS, Value *V, LargeSparseBitVector &Uses); + void NoteUse(State &S, BBState &BBS, Value *V) { + NoteUse(S, BBS, V, BBS.UpExposedUses); + } + + void LiftPhi(State &S, PHINode *Phi); + void LiftSelect(State &S, SelectInst *SI); + Value *MaybeExtractScalar(State &S, std::pair ValExpr, Instruction *InsertBefore); + SmallVector MaybeExtractVector(State &S, Value *BaseVec, Instruction *InsertBefore); + Value *GetPtrForNumber(State &S, unsigned Num, Instruction *InsertBefore); + + int Number(State &S, Value *V); + int NumberBase(State &S, Value *Base); + SmallVector NumberAll(State &S, Value *V); + SmallVector NumberAllBase(State &S, Value *Base); + + void NoteOperandUses(State &S, BBState &BBS, User &UI); + void MaybeTrackDst(State &S, MemTransferInst *MI); + void MaybeTrackStore(State &S, StoreInst *I); + State LocalScan(Function &F); + void ComputeLiveness(State &S); + void ComputeLiveSets(State &S); + SmallVector ColorRoots(const State &S); + void PlaceGCFrameStore(State &S, unsigned R, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame, Instruction *InsertBefore); + void PlaceGCFrameStores(State &S, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame); + void PlaceRootsAndUpdateCalls(SmallVectorImpl &Colors, State &S, std::map>); + void CleanupWriteBarriers(Function &F, State *S, const SmallVector &WriteBarriers, bool *CFGModified); + bool CleanupIR(Function &F, State *S, bool *CFGModified); + void NoteUseChain(State &S, BBState &BBS, User *TheUser); + SmallVector GetPHIRefinements(PHINode *phi, State &S); + void FixUpRefinements(ArrayRef PHINumbers, State &S); + void RefineLiveSet(LargeSparseBitVector &LS, State &S, ArrayRef CalleeRoots); + Value *EmitTagPtr(IRBuilder<> &builder, Type *T, Type *T_size, Value *V); + Value *EmitLoadTag(IRBuilder<> &builder, Type *T_size, Value *V); +}; + +// The final GC lowering pass. This pass lowers platform-agnostic GC +// intrinsics to platform-dependent instruction sequences. The +// intrinsics it targets are those produced by the late GC frame +// lowering pass. +// +// This pass targets typical back-ends for which the standard Julia +// runtime library is available. Atypical back-ends should supply +// their own lowering pass. + +struct FinalLowerGC: private JuliaPassContext { + bool runOnFunction(Function &F); + +private: + Function *queueRootFunc; + Function *smallAllocFunc; + Function *bigAllocFunc; + Function *allocTypedFunc; + Instruction *pgcstack; + Type *T_size; + + // Lowers a `julia.new_gc_frame` intrinsic. + void lowerNewGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.push_gc_frame` intrinsic. + void lowerPushGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.pop_gc_frame` intrinsic. + void lowerPopGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.get_gc_frame_slot` intrinsic. + void lowerGetGCFrameSlot(CallInst *target, Function &F); + + // Lowers a `julia.gc_alloc_bytes` intrinsic. + void lowerGCAllocBytes(CallInst *target, Function &F); + + // Lowers a `julia.queue_gc_root` intrinsic. + void lowerQueueGCRoot(CallInst *target, Function &F); + + // Lowers a `julia.safepoint` intrinsic. + void lowerSafepoint(CallInst *target, Function &F); +}; + +#endif // LLVM_GC_PASSES_H diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 65b8cdc5c7c05..e08f08860dfaf 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -1,367 +1,9 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -#include "llvm-version.h" -#include "passes.h" - -#include "llvm/IR/DerivedTypes.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "llvm-codegen-shared.h" -#include "julia.h" -#include "julia_internal.h" -#include "julia_assert.h" -#include "llvm-pass-helpers.h" -#include -#include +#include "llvm-gc-interface-passes.h" #define DEBUG_TYPE "late_lower_gcroot" -using namespace llvm; - -/* Julia GC Root Placement pass. For a general overview of the design of GC - root lowering, see the devdocs. This file is the actual implementation. - - The actual algorithm is fairly straightforward. First recall the goal of this - pass: - - Minimize the number of needed gc roots/stores to them subject to the constraint - that at every safepoint, any live gc-tracked pointer (i.e. for which there is - a path after this point that contains a use of this pointer) is in some gc slot. - - In particular, in order to understand this algorithm, it is important to - realize that the only places where rootedness matters is at safepoints. - - Now, the primary phases of the algorithm are: - - 1. Local Scan - - During this step, each Basic Block is inspected and analyzed for local - properties. In particular, we want to determine the ordering of any of - the following activities: - - - Any Def of a gc-tracked pointer. In general Defs are the results of - calls or loads from appropriate memory locations. Phi nodes and - selects do complicate this story slightly as described below. - - Any use of a gc-tracked or derived pointer. As described in the - devdocs, a use is in general one of - a) a load from a tracked/derived value - b) a store to a tracked/derived value - c) a store OF a tracked/derived value - d) a use of a value as a call operand (including operand bundles) - - Any safepoint - - Crucially, we also perform pointer numbering during the local scan, - assigning every Def a unique integer and caching the integer for each - derived pointer. This allows us to operate only on the set of Defs ( - represented by these integers) for the rest of the algorithm. We also - maintain some local utility information that is needed by later passes - (see the BBState struct for details). - - 2. Dataflow Computation - - This computation operates entirely over the function's control flow graph - and does not look into a basic block. The algorithm is essentially - textbook iterative data flow for liveness computation. However, the - data flow equations are slightly more complicated because we also - forward propagate rootedness information in addition to backpropagating - liveness. - - 3. Live Set Computation - - With the liveness information from the previous step, we can now compute, - for every safepoint, the set of values live at that particular safepoint. - There are three pieces of information being combined here: - i. Values that needed to be live due to local analysis (e.g. there - was a def, then a safepoint, then a use). This was computed during - local analysis. - ii. Values that are live across the basic block (i.e. they are live - at every safepoint within the basic block). This relies entirely - on the liveness information. - iii. Values that are now live-out from the basic block (i.e. they are - live at every safepoint following their def). During local - analysis, we keep, for every safepoint, those values that would - be live if they were live out. Here we can check if they are - actually live-out and make the appropriate additions to the live - set. - - Lastly, we also explicitly compute, for each value, the list of values - that are simultaneously live at some safepoint. This is known as an - "interference graph" and is the input to the next step. - - 4. GC Root coloring - - Two values which are not simultaneously live at a safepoint can share the - same slot. This is an important optimization, because otherwise long - functions would have exceptionally large GC slots, reducing performance - and bloating the size of the stack. Assigning values to these slots is - equivalent to doing graph coloring on the interference graph - the graph - where nodes are values and two values have an edge if they are - simultaneously live at a safepoint - which we computed in the previous - step. Now graph coloring in general is a hard problem. However, for SSA - form programs, (and most programs in general, by virtue of their - structure), the resulting interference graphs are chordal and can be - colored optimally in linear time by performing greedy coloring in a - perfect elimination order. Now, our interference graphs are likely not - entirely chordal due to some non-SSA corner cases. However, using the same - algorithm should still give a very good coloring while having sufficiently - low runtime. - - 5. JLCall frame optimizations - - Unlike earlier iterations of the gc root placement logic, jlcall frames - are no longer treated as a special case and need not necessarily be sunk - into the gc frame. Additionally, we now emit lifetime - intrinsics, so regular stack slot coloring will merge any jlcall frames - not sunk into the gc frame. Nevertheless performing such sinking can still - be profitable. Since all arguments to a jlcall are guaranteed to be live - at that call in some gc slot, we can attempt to rearrange the slots within - the gc-frame, or reuse slots not assigned at that particular location - for the gcframe. However, even without this optimization, stack frames - are at most two times larger than optimal (because regular stack coloring - can merge the jlcall allocas). - - N.B.: This step is not yet implemented. - - 6. Root placement - - This performs the actual insertion of the GCFrame pushes/pops, zeros out - the gc frame and creates the stores to the gc frame according to the - stack slot assignment computed in the previous step. GC frames stores - are generally sunk right before the first safe point that use them - (this is beneficial for code where the primary path does not have - safepoints, but some other path - e.g. the error path does). However, - if the first safepoint is not dominated by the definition (this can - happen due to the non-ssa corner cases), the store is inserted right after - the definition. - - 7. Cleanup - - This step performs necessary cleanup before passing the IR to codegen. In - particular, it removes any calls to julia_from_objref intrinsics and - removes the extra operand bundles from ccalls. In the future it could - also strip the addrspace information from all values as this - information is no longer needed. - - - There are a couple important special cases that deserve special attention: - - A. PHIs and Selects - - In general PHIs and selects are treated as separate defs for the purposes - of the algorithm and their operands as uses of those values. It is - important to consider however WHERE the uses of PHI's operands are - located. It is neither at the start of the basic block, because the values - do not dominate the block (so can't really consider them live-in), nor - at the end of the predecessor (because they are actually live out). - Instead it is best to think of those uses as living on the edge between - the appropriate predecessor and the block containing the PHI. - - Another concern is PHIs of derived values. Since we cannot simply root - these values by storing them to a GC slot, we need to insert a new, - artificial PHI that tracks the base pointers for the derived values. E.g. - in: - - A: - %Abase = load addrspace(10) *... - %Aderived = addrspacecast %Abase to addrspace(11) - B: - %Bbase = load addrspace(10) *... - %Bderived = addrspacecast %Bbase to addrspace(11) - C: - %phi = phi [%Aderived, %A - %Bderived, %B] - - we will insert another phi in C to track the relevant base pointers: - - %philift = phi [%Abase, %A - %Bbase, %B] - - We then pretend, for the purposes of numbering that %phi was derived from - %philift. Note that in order to be able to do this, we need to be able to - perform this lifting either during numbering or instruction scanning. - - B. Vectors of pointers/Union representations - - Since this pass runs very late in the pass pipeline, it runs after the - various vectorization passes. As a result, we have to potentially deal - with vectors of gc-tracked pointers. For the purposes of most of the - algorithm, we simply assign every element of the vector a separate number - and no changes are needed. However, those parts of the algorithm that - look at IR need to be aware of the possibility of encountering vectors of - pointers. - - Similarly, unions (e.g. in call returns) are represented as a struct of - a gc-tracked value and an argument selector. We simply assign a single - number to this struct and proceed as if it was a single pointer. However, - this again requires care at the IR level. - - C. Non mem2reg'd allocas - - Under some circumstances, allocas will still be present in the IR when - we get to this pass. We don't try very hard to handle this case, and - simply sink the alloca into the GCFrame. -*/ - -// 4096 bits == 64 words (64 bit words). Larger bit numbers are faster and doing something -// substantially smaller here doesn't actually save much memory because of malloc overhead. -// Too large is bad also though - 4096 was found to be a reasonable middle ground. -using LargeSparseBitVector = SparseBitVector<4096>; - -struct BBState { - // Uses in this BB - // These do not get updated after local analysis - LargeSparseBitVector Defs; - LargeSparseBitVector PhiOuts; - LargeSparseBitVector UpExposedUses; - // These get updated during dataflow - LargeSparseBitVector LiveIn; - LargeSparseBitVector LiveOut; - SmallVector Safepoints; - int TopmostSafepoint = -1; - bool HasSafepoint = false; - // Have we gone through this basic block in our local scan yet? - bool Done = false; -}; - -struct State { - Function *const F; - DominatorTree *DT; - - // The maximum assigned value number - int MaxPtrNumber; - // The maximum assigned safepoint number - int MaxSafepointNumber; - // Cache of numbers assigned to IR values. This includes caching of numbers - // for derived values - std::map AllPtrNumbering; - std::map> AllCompositeNumbering; - // The reverse of the previous maps - std::map ReversePtrNumbering; - // Neighbors in the coloring interference graph. I.e. for each value, the - // indices of other values that are used simultaneously at some safe point. - SmallVector Neighbors; - // The result of the local analysis - std::map BBStates; - - // Refinement map. If all of the values are rooted - // (-1 means an externally rooted value and -2 means a globally/permanently rooted value), - // the key is already rooted (but not the other way around). - // A value that can be refined to -2 never need any rooting or write barrier. - // A value that can be refined to -1 don't need local root but still need write barrier. - // At the end of `LocalScan` this map has a few properties - // 1. Values are either < 0 or dominates the key - // 2. Therefore this is a DAG - std::map> Refinements; - - // GC preserves map. All safepoints dominated by the map key, but not any - // of its uses need to preserve the values listed in the map value. - std::map> GCPreserves; - - // The assignment of numbers to safepoints. The indices in the map - // are indices into the next three maps which store safepoint properties - std::map SafepointNumbering; - - // Reverse mapping index -> safepoint - SmallVector ReverseSafepointNumbering; - - // Instructions that can return twice. For now, all values live at these - // instructions will get their own, dedicated GC frame slots, because they - // have unobservable control flow, so we can't be sure where they're - // actually live. All of these are also considered safepoints. - SmallVector ReturnsTwice; - - // The set of values live at a particular safepoint - SmallVector< LargeSparseBitVector , 0> LiveSets; - // Those values that - if live out from our parent basic block - are live - // at this safepoint. - SmallVector> LiveIfLiveOut; - // The set of values that are kept alive by the callee. - SmallVector> CalleeRoots; - // We don't bother doing liveness on Allocas that were not mem2reg'ed. - // they just get directly sunk into the root array. - SmallVector Allocas; - DenseMap ArrayAllocas; - DenseMap ShadowAllocas; - SmallVector, 0> TrackedStores; - State(Function &F) : F(&F), DT(nullptr), MaxPtrNumber(-1), MaxSafepointNumber(-1) {} -}; - - -struct LateLowerGCFrame: private JuliaPassContext { - function_ref GetDT; - LateLowerGCFrame(function_ref GetDT) : GetDT(GetDT) {} - -public: - bool runOnFunction(Function &F, bool *CFGModified = nullptr); - -private: - CallInst *pgcstack; - - void MaybeNoteDef(State &S, BBState &BBS, Value *Def, const ArrayRef &SafepointsSoFar, - SmallVector &&RefinedPtr = SmallVector()); - void NoteUse(State &S, BBState &BBS, Value *V, LargeSparseBitVector &Uses); - void NoteUse(State &S, BBState &BBS, Value *V) { - NoteUse(S, BBS, V, BBS.UpExposedUses); - } - - void LiftPhi(State &S, PHINode *Phi); - void LiftSelect(State &S, SelectInst *SI); - Value *MaybeExtractScalar(State &S, std::pair ValExpr, Instruction *InsertBefore); - SmallVector MaybeExtractVector(State &S, Value *BaseVec, Instruction *InsertBefore); - Value *GetPtrForNumber(State &S, unsigned Num, Instruction *InsertBefore); - - int Number(State &S, Value *V); - int NumberBase(State &S, Value *Base); - SmallVector NumberAll(State &S, Value *V); - SmallVector NumberAllBase(State &S, Value *Base); - - void NoteOperandUses(State &S, BBState &BBS, User &UI); - void MaybeTrackDst(State &S, MemTransferInst *MI); - void MaybeTrackStore(State &S, StoreInst *I); - State LocalScan(Function &F); - void ComputeLiveness(State &S); - void ComputeLiveSets(State &S); - SmallVector ColorRoots(const State &S); - void PlaceGCFrameStore(State &S, unsigned R, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame, Instruction *InsertBefore); - void PlaceGCFrameStores(State &S, unsigned MinColorRoot, ArrayRef Colors, Value *GCFrame); - void PlaceRootsAndUpdateCalls(SmallVectorImpl &Colors, State &S, std::map>); - void CleanupWriteBarriers(Function &F, State *S, const SmallVector &WriteBarriers, bool *CFGModified); - bool CleanupIR(Function &F, State *S, bool *CFGModified); - void NoteUseChain(State &S, BBState &BBS, User *TheUser); - SmallVector GetPHIRefinements(PHINode *phi, State &S); - void FixUpRefinements(ArrayRef PHINumbers, State &S); - void RefineLiveSet(LargeSparseBitVector &LS, State &S, ArrayRef CalleeRoots); - Value *EmitTagPtr(IRBuilder<> &builder, Type *T, Type *T_size, Value *V); - Value *EmitLoadTag(IRBuilder<> &builder, Type *T_size, Value *V); -}; - static unsigned getValueAddrSpace(Value *V) { return V->getType()->getPointerAddressSpace(); } diff --git a/src/scheduler.c b/src/scheduler.c index 2c7dbd63ef4a4..3505e935afcf6 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -7,7 +7,6 @@ #include "julia.h" #include "julia_internal.h" -#include "gc.h" #include "threading.h" #ifdef __cplusplus @@ -32,7 +31,7 @@ static const int16_t sleeping_like_the_dead JL_UNUSED = 2; // a running count of how many threads are currently not_sleeping // plus a running count of the number of in-flight wake-ups // n.b. this may temporarily exceed jl_n_threads -static _Atomic(int) nrunning = 0; +_Atomic(int) n_threads_running = 0; // invariant: No thread is ever asleep unless sleep_check_state is sleeping (or we have a wakeup signal pending). // invariant: Any particular thread is not asleep unless that thread's sleep_check_state is sleeping. @@ -112,79 +111,6 @@ void jl_init_threadinginfra(void) void JL_NORETURN jl_finish_task(jl_task_t *ct); -static inline int may_mark(void) JL_NOTSAFEPOINT -{ - return (jl_atomic_load(&gc_n_threads_marking) > 0); -} - -static inline int may_sweep(jl_ptls_t ptls) JL_NOTSAFEPOINT -{ - return (jl_atomic_load(&ptls->gc_tls.gc_sweeps_requested) > 0); -} - -// parallel gc thread function -void jl_parallel_gc_threadfun(void *arg) -{ - jl_threadarg_t *targ = (jl_threadarg_t*)arg; - - // initialize this thread (set tid and create heap) - jl_ptls_t ptls = jl_init_threadtls(targ->tid); - void *stack_lo, *stack_hi; - jl_init_stack_limits(0, &stack_lo, &stack_hi); - // warning: this changes `jl_current_task`, so be careful not to call that from this function - jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); - JL_GC_PROMISE_ROOTED(ct); - (void)jl_atomic_fetch_add_relaxed(&nrunning, -1); - // wait for all threads - jl_gc_state_set(ptls, JL_GC_PARALLEL_COLLECTOR_THREAD, JL_GC_STATE_UNSAFE); - uv_barrier_wait(targ->barrier); - - // free the thread argument here - free(targ); - - while (1) { - uv_mutex_lock(&gc_threads_lock); - while (!may_mark() && !may_sweep(ptls)) { - uv_cond_wait(&gc_threads_cond, &gc_threads_lock); - } - uv_mutex_unlock(&gc_threads_lock); - assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_PARALLEL_COLLECTOR_THREAD); - gc_mark_loop_parallel(ptls, 0); - if (may_sweep(ptls)) { - assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_PARALLEL_COLLECTOR_THREAD); - gc_sweep_pool_parallel(ptls); - jl_atomic_fetch_add(&ptls->gc_tls.gc_sweeps_requested, -1); - } - } -} - -// concurrent gc thread function -void jl_concurrent_gc_threadfun(void *arg) -{ - jl_threadarg_t *targ = (jl_threadarg_t*)arg; - - // initialize this thread (set tid and create heap) - jl_ptls_t ptls = jl_init_threadtls(targ->tid); - void *stack_lo, *stack_hi; - jl_init_stack_limits(0, &stack_lo, &stack_hi); - // warning: this changes `jl_current_task`, so be careful not to call that from this function - jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); - JL_GC_PROMISE_ROOTED(ct); - (void)jl_atomic_fetch_add_relaxed(&nrunning, -1); - // wait for all threads - jl_gc_state_set(ptls, JL_GC_CONCURRENT_COLLECTOR_THREAD, JL_GC_STATE_UNSAFE); - uv_barrier_wait(targ->barrier); - - // free the thread argument here - free(targ); - - while (1) { - assert(jl_atomic_load_relaxed(&ptls->gc_state) == JL_GC_CONCURRENT_COLLECTOR_THREAD); - uv_sem_wait(&gc_sweep_assists_needed); - gc_free_pages(); - } -} - // thread function: used by all mutator threads except the main thread void jl_threadfun(void *arg) { @@ -218,9 +144,9 @@ void jl_init_thread_scheduler(jl_ptls_t ptls) JL_NOTSAFEPOINT // record that there is now another thread that may be used to schedule work // we will decrement this again in scheduler_delete_thread, only slightly // in advance of pthread_join (which hopefully itself also had been - // adopted by now and is included in nrunning too) - (void)jl_atomic_fetch_add_relaxed(&nrunning, 1); - // n.b. this is the only point in the code where we ignore the invariants on the ordering of nrunning + // adopted by now and is included in n_threads_running too) + (void)jl_atomic_fetch_add_relaxed(&n_threads_running, 1); + // n.b. this is the only point in the code where we ignore the invariants on the ordering of n_threads_running // since we are being initialized from foreign code, we could not necessarily have expected or predicted that to happen } @@ -280,7 +206,7 @@ static int set_not_sleeping(jl_ptls_t ptls) JL_NOTSAFEPOINT return 1; } } - int wasrunning = jl_atomic_fetch_add_relaxed(&nrunning, -1); // consume in-flight wakeup + int wasrunning = jl_atomic_fetch_add_relaxed(&n_threads_running, -1); // consume in-flight wakeup assert(wasrunning > 1); (void)wasrunning; return 0; } @@ -292,7 +218,7 @@ static int wake_thread(int16_t tid) JL_NOTSAFEPOINT if (jl_atomic_load_relaxed(&ptls2->sleep_check_state) != not_sleeping) { int8_t state = sleeping; if (jl_atomic_cmpswap_relaxed(&ptls2->sleep_check_state, &state, not_sleeping)) { - int wasrunning = jl_atomic_fetch_add_relaxed(&nrunning, 1); // increment in-flight wakeup count + int wasrunning = jl_atomic_fetch_add_relaxed(&n_threads_running, 1); // increment in-flight wakeup count assert(wasrunning); (void)wasrunning; JL_PROBE_RT_SLEEP_CHECK_WAKE(ptls2, state); uv_mutex_lock(&ptls2->sleep_lock); @@ -323,11 +249,11 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) JL_NOTSAFEPOINT JULIA_DEBUG_SLEEPWAKE( wakeup_enter = cycleclock() ); if (tid == self || tid == -1) { // we're already awake, but make sure we'll exit uv_run - // and that nrunning is updated if this is now considered in-flight + // and that n_threads_running is updated if this is now considered in-flight jl_ptls_t ptls = ct->ptls; if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { if (jl_atomic_exchange_relaxed(&ptls->sleep_check_state, not_sleeping) != not_sleeping) { - int wasrunning = jl_atomic_fetch_add_relaxed(&nrunning, 1); + int wasrunning = jl_atomic_fetch_add_relaxed(&n_threads_running, 1); assert(wasrunning); (void)wasrunning; JL_PROBE_RT_SLEEP_CHECK_WAKEUP(ptls); } @@ -548,8 +474,8 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, } // any thread which wants us running again will have to observe - // sleep_check_state==sleeping and increment nrunning for us - int wasrunning = jl_atomic_fetch_add_relaxed(&nrunning, -1); + // sleep_check_state==sleeping and increment n_threads_running for us + int wasrunning = jl_atomic_fetch_add_relaxed(&n_threads_running, -1); assert(wasrunning); isrunning = 0; if (wasrunning == 1) { @@ -573,8 +499,8 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, while (may_sleep(ptls)) { if (ptls->tid == 0) { task = wait_empty; - if (task && jl_atomic_load_relaxed(&nrunning) == 0) { - wasrunning = jl_atomic_fetch_add_relaxed(&nrunning, 1); + if (task && jl_atomic_load_relaxed(&n_threads_running) == 0) { + wasrunning = jl_atomic_fetch_add_relaxed(&n_threads_running, 1); assert(!wasrunning); wasrunning = !set_not_sleeping(ptls); assert(!wasrunning); @@ -585,11 +511,11 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, } task = NULL; } - // else should we warn the user of certain deadlock here if tid == 0 && nrunning == 0? + // else should we warn the user of certain deadlock here if tid == 0 && n_threads_running == 0? uv_cond_wait(&ptls->wake_signal, &ptls->sleep_lock); } assert(jl_atomic_load_relaxed(&ptls->sleep_check_state) == not_sleeping); - assert(jl_atomic_load_relaxed(&nrunning)); + assert(jl_atomic_load_relaxed(&n_threads_running)); start_cycles = 0; uv_mutex_unlock(&ptls->sleep_lock); JULIA_DEBUG_SLEEPWAKE( ptls->sleep_leave = cycleclock() ); @@ -603,7 +529,7 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, JL_CATCH { // probably SIGINT, but possibly a user mistake in trypoptask if (!isrunning) - jl_atomic_fetch_add_relaxed(&nrunning, 1); + jl_atomic_fetch_add_relaxed(&n_threads_running, 1); set_not_sleeping(ptls); jl_rethrow(); } @@ -622,7 +548,7 @@ void scheduler_delete_thread(jl_ptls_t ptls) JL_NOTSAFEPOINT int notsleeping = jl_atomic_exchange_relaxed(&ptls->sleep_check_state, sleeping_like_the_dead) == not_sleeping; jl_fence(); if (notsleeping) { - if (jl_atomic_load_relaxed(&nrunning) == 1) { + if (jl_atomic_load_relaxed(&n_threads_running) == 1) { jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[jl_atomic_load_relaxed(&io_loop_tid)]; // This was the last running thread, and there is no thread with !may_sleep // so make sure tid 0 is notified to check wait_empty @@ -632,10 +558,10 @@ void scheduler_delete_thread(jl_ptls_t ptls) JL_NOTSAFEPOINT } } else { - jl_atomic_fetch_add_relaxed(&nrunning, 1); + jl_atomic_fetch_add_relaxed(&n_threads_running, 1); } jl_wakeup_thread(0); // force thread 0 to see that we do not have the IO lock (and am dead) - jl_atomic_fetch_add_relaxed(&nrunning, -1); + jl_atomic_fetch_add_relaxed(&n_threads_running, -1); } #ifdef __cplusplus diff --git a/src/signals-unix.c b/src/signals-unix.c index aa4d1626a4305..f01f2fcfb739a 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -1011,12 +1011,12 @@ static void *signal_listener(void *arg) else if (critical) { // critical in this case actually means SIGINFO request #ifndef SIGINFO // SIGINFO already prints something similar automatically - int nrunning = 0; + int n_threads_running = 0; for (int idx = nthreads; idx-- > 0; ) { jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[idx]; - nrunning += !jl_atomic_load_relaxed(&ptls2->sleep_check_state); + n_threads_running += !jl_atomic_load_relaxed(&ptls2->sleep_check_state); } - jl_safe_printf("\ncmd: %s %d running %d of %d\n", jl_options.julia_bin ? jl_options.julia_bin : "julia", uv_os_getpid(), nrunning, nthreads); + jl_safe_printf("\ncmd: %s %d running %d of %d\n", jl_options.julia_bin ? jl_options.julia_bin : "julia", uv_os_getpid(), n_threads_running, nthreads); #endif jl_safe_printf("\nsignal (%d): %s\n", sig, strsignal(sig)); diff --git a/src/stackwalk.c b/src/stackwalk.c index 7e4a04f6b77e4..a63694e7c3b0c 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -5,7 +5,7 @@ utilities for walking the stack and looking up information about code addresses */ #include -#include "gc.h" +#include "gc-stock.h" #include "julia.h" #include "julia_internal.h" #include "threading.h" diff --git a/src/threading.c b/src/threading.c index 2f658832f2220..8f37ee814056c 100644 --- a/src/threading.c +++ b/src/threading.c @@ -465,8 +465,6 @@ void jl_safepoint_resume_all_threads(jl_task_t *ct) void jl_task_frame_noreturn(jl_task_t *ct) JL_NOTSAFEPOINT; void scheduler_delete_thread(jl_ptls_t ptls) JL_NOTSAFEPOINT; -void jl_free_thread_gc_state(jl_ptls_t ptls); - static void jl_delete_thread(void *value) JL_NOTSAFEPOINT_ENTER { #ifndef _OS_WINDOWS_ From b759fe29a3e1f84b7cb928f1f87417d43f7fc72a Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Wed, 31 Jul 2024 20:48:42 -0400 Subject: [PATCH 110/206] Profile: Fix stdlib paths (#55327) --- src/signals-mach.c | 8 ++++---- src/signals-unix.c | 8 ++++---- src/signals-win.c | 8 ++++---- stdlib/Profile/src/Profile.jl | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/signals-mach.c b/src/signals-mach.c index 129cb8afb542f..c31b6d506b4e6 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -738,16 +738,16 @@ void *mach_profile_listener(void *arg) #endif jl_ptls_t ptls = jl_atomic_load_relaxed(&jl_all_tls_states)[i]; - // store threadid but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_THREADID store threadid but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = ptls->tid + 1; - // store task id (never null) + // META_OFFSET_TASKID store task id (never null) bt_data_prof[bt_size_cur++].jlvalue = (jl_value_t*)jl_atomic_load_relaxed(&ptls->current_task); - // store cpu cycle clock + // META_OFFSET_CPUCYCLECLOCK store cpu cycle clock bt_data_prof[bt_size_cur++].uintptr = cycleclock(); - // store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_SLEEPSTATE store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = jl_atomic_load_relaxed(&ptls->sleep_check_state) + 1; // Mark the end of this block with two 0's diff --git a/src/signals-unix.c b/src/signals-unix.c index f01f2fcfb739a..5e79fd5a2e29e 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -965,16 +965,16 @@ static void *signal_listener(void *arg) jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[i]; - // store threadid but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_THREADID store threadid but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = ptls2->tid + 1; - // store task id (never null) + // META_OFFSET_TASKID store task id (never null) bt_data_prof[bt_size_cur++].jlvalue = (jl_value_t*)jl_atomic_load_relaxed(&ptls2->current_task); - // store cpu cycle clock + // META_OFFSET_CPUCYCLECLOCK store cpu cycle clock bt_data_prof[bt_size_cur++].uintptr = cycleclock(); - // store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_SLEEPSTATE store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = jl_atomic_load_relaxed(&ptls2->sleep_check_state) + 1; // Mark the end of this block with two 0's diff --git a/src/signals-win.c b/src/signals-win.c index 4c31df766f3f1..d7288b5d365d8 100644 --- a/src/signals-win.c +++ b/src/signals-win.c @@ -421,16 +421,16 @@ static DWORD WINAPI profile_bt( LPVOID lparam ) jl_ptls_t ptls = jl_atomic_load_relaxed(&jl_all_tls_states)[0]; // given only profiling hMainThread - // store threadid but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_THREADID store threadid but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = ptls->tid + 1; - // store task id (never null) + // META_OFFSET_TASKID store task id (never null) bt_data_prof[bt_size_cur++].jlvalue = (jl_value_t*)jl_atomic_load_relaxed(&ptls->current_task); - // store cpu cycle clock + // META_OFFSET_CPUCYCLECLOCK store cpu cycle clock bt_data_prof[bt_size_cur++].uintptr = cycleclock(); - // store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block + // META_OFFSET_SLEEPSTATE store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block bt_data_prof[bt_size_cur++].uintptr = jl_atomic_load_relaxed(&ptls->sleep_check_state) + 1; // Mark the end of this block with two 0's diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 0a1f709a2ac60..55352cc4b3a9c 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -505,7 +505,7 @@ end # based on the package ecosystem function short_path(spath::Symbol, filenamecache::Dict{Symbol, String}) return get!(filenamecache, spath) do - path = string(spath) + path = Base.fixup_stdlib_path(string(spath)) if isabspath(path) if ispath(path) # try to replace the file-system prefix with a short "@Module" one, @@ -681,7 +681,7 @@ function add_fake_meta(data; threadid = 1, taskid = 0xf0f0f0f0) for i = 1:length(data) val = data[i] if iszero(val) - # (threadid, taskid, cpu_cycle_clock, thread_sleeping) + # META_OFFSET_THREADID, META_OFFSET_TASKID, META_OFFSET_CPUCYCLECLOCK, META_OFFSET_SLEEPSTATE push!(data_with_meta, threadid, taskid, cpu_clock_cycle+=1, false+1, 0, 0) else push!(data_with_meta, val) From 602b582a66ca15bbfe2328546ee04f98167e67c9 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 31 Jul 2024 20:24:02 -0700 Subject: [PATCH 111/206] [libblastrampoline] Bump to v5.11.0 (#55330) This includes support to properly forward MKL v2024's ILP64 CBLAS symbols, which fixes this [Enzyme issue](https://github.com/EnzymeAD/Enzyme.jl/issues/1683) --- deps/blastrampoline.version | 6 +- deps/checksums/blastrampoline | 68 +++++++++++------------ stdlib/libblastrampoline_jll/Project.toml | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/blastrampoline.version b/deps/blastrampoline.version index 871053db3c9f2..fd055e1ae8120 100644 --- a/deps/blastrampoline.version +++ b/deps/blastrampoline.version @@ -2,6 +2,6 @@ BLASTRAMPOLINE_JLL_NAME := libblastrampoline ## source build -BLASTRAMPOLINE_VER := 5.10.1 -BLASTRAMPOLINE_BRANCH=v5.10.1 -BLASTRAMPOLINE_SHA1=ff05ebb4e450deda0aebe8dce4d4f054e23fecfc +BLASTRAMPOLINE_VER := 5.11.0 +BLASTRAMPOLINE_BRANCH=v5.11.0 +BLASTRAMPOLINE_SHA1=05083d50611b5538df69706f0a952d8e642b0b4b diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index b8c4c68c661ba..edb8cadc74846 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,34 +1,34 @@ -blastrampoline-ff05ebb4e450deda0aebe8dce4d4f054e23fecfc.tar.gz/md5/48ec847f7a687dd36789d6365d3c5645 -blastrampoline-ff05ebb4e450deda0aebe8dce4d4f054e23fecfc.tar.gz/sha512/85f6a46e7fe5f76ff8cef5776dad73b17eb97be3b16ca1af961cf2c2cbe125c629bd808b0243b793e4235dcb545a02cc082eaf14b3a438f3e0973d46921550a3 -libblastrampoline.v5.10.1+0.aarch64-apple-darwin.tar.gz/md5/cbbb4b5a6ebee04d686f072a69e855be -libblastrampoline.v5.10.1+0.aarch64-apple-darwin.tar.gz/sha512/32eaebb0fa3c0bc85a270b5c13fecaaa86ee10b4cea04405672badbaaa5ae3f22757dc758d9d971c811dc100a8ebd72fa00391238c0227de3690341f0434842a -libblastrampoline.v5.10.1+0.aarch64-linux-gnu.tar.gz/md5/da097a9459dcb8554f3d9511ea1a1c88 -libblastrampoline.v5.10.1+0.aarch64-linux-gnu.tar.gz/sha512/0159dbd4579d2a334f4341a64841bc1cef1354fc744709055339957b299b2b36b30162c2c90367abc04a2fb2f236aaa1fe6eb290393702f6fb97eaa79e4bb028 -libblastrampoline.v5.10.1+0.aarch64-linux-musl.tar.gz/md5/f32839481836dad6a1b159d9c33db752 -libblastrampoline.v5.10.1+0.aarch64-linux-musl.tar.gz/sha512/b973e739ab4af6ba93328943b03f16f02625553efc2375909b5e5bed4446287a21f99025817ce73267cac2d0b6b65f7dc2a5bd4b4c88d263b3c923b2ec3ad5c4 -libblastrampoline.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/md5/23eb2cbc1a547f94935fa4f9ffa2285b -libblastrampoline.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/0681497bac1d8f3ff1932adbb9fdd0b710b2a28ca7f2f4bb0093ba1123b14acd8bcb062e81e538c6e51ed8449ffea582cdb5b610e97d0c76a6feb58545938a6b -libblastrampoline.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/md5/4e5168b1ada4e36861aeb3f4a6ace318 -libblastrampoline.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/sha512/4ee663d2d3665e6ea356cfac60274c5f06ab08c1ee99b345ddda6872125663acb5559f704d0a918706e6cb075fc3071aaec4bcc3b9fee5fee72696e2f1454fb3 -libblastrampoline.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/md5/a28e3820fdf1435027f69204a553b5f9 -libblastrampoline.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/48edfc069aeaead468ffb6145986b11a040286990520b191e0f9cfa99f0b9458e6b17e523c8cc81889af7c9c2adce6372c65f2205a20c8e778614eaa06d288f9 -libblastrampoline.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/md5/c5ea1756f3d58f8a74e76958f3a93658 -libblastrampoline.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/sha512/f3eb003f954ffc346ae1037325b56fb2e4db9a6f88cc878862f921df79d8e0a5c8da9d229610dcd5d21c3d7af0a61ddcc0e70e32bf45fc9ea828d9ab2d1ddda8 -libblastrampoline.v5.10.1+0.i686-linux-gnu.tar.gz/md5/8bbdd602fed40577c4c9f020a8304c57 -libblastrampoline.v5.10.1+0.i686-linux-gnu.tar.gz/sha512/67947bd68c9f1131311d5d6a0fbcc92540f2fb2e1d2d0fa46951033fd75658661ba355c415b68de5dcd1bf0c440e27e3362ece70f5fd989fade796e9e723becd -libblastrampoline.v5.10.1+0.i686-linux-musl.tar.gz/md5/455bb539e7646e060fa24fb59c82f2f0 -libblastrampoline.v5.10.1+0.i686-linux-musl.tar.gz/sha512/e392334512ebce93ea4b34265ead802c543db5678c30083fb0dce08c071dd7140a9532d3162f215815807650138ffec5ad5d6d848025ee3913dfe353308d8e57 -libblastrampoline.v5.10.1+0.i686-w64-mingw32.tar.gz/md5/9a1c6845cb2e85b3497cd01d3a89b06b -libblastrampoline.v5.10.1+0.i686-w64-mingw32.tar.gz/sha512/66a9429a70575f4fd19d1cfb263c4c7801ac4a88408f98125f6e347b0ba35d2fdc4cbb82bf7407462beab1f7a7df2184163f76d5f2330f485bc1c7e5354716aa -libblastrampoline.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/md5/b2b3eea1cfce87642a1f2afa125dcc5c -libblastrampoline.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/sha512/43d5bf6535ad8f0910a523a3940787db956a3700681cc0dc1e2a1aabdaafa669e46e42854df29c0dcff06b3ade899159cb4845a48a6e618ba52af7276151fd0e -libblastrampoline.v5.10.1+0.x86_64-apple-darwin.tar.gz/md5/497a8f88c810a12b3faf12851427c784 -libblastrampoline.v5.10.1+0.x86_64-apple-darwin.tar.gz/sha512/7e3ed2117c6248761ba5bc3fd339f12ca98050d163d5c3668a62ee90aec10858d30fe9d78cea01796c9b2231cdd4f9ad0ae886bf8e984cb24d745e9f8c0fd62b -libblastrampoline.v5.10.1+0.x86_64-linux-gnu.tar.gz/md5/355612dc7c383dd860dc03498254814b -libblastrampoline.v5.10.1+0.x86_64-linux-gnu.tar.gz/sha512/12d803c53f705dacf2bf5f3884bd9b40f89a248ebda8bce1da6bba0cfe4331222bed5124dc45ea377e7c0fcc2d0dc624cc71b0eb454319fd12e2fd4c58d265f7 -libblastrampoline.v5.10.1+0.x86_64-linux-musl.tar.gz/md5/78a09fe918b1b0b3dc72c17c2e62799b -libblastrampoline.v5.10.1+0.x86_64-linux-musl.tar.gz/sha512/1ff3d7e8d36d450f430119b30e03a64f2d78d6d13a04e4a4b97c64966e341f486080c733dbd73ee3ed7c1557ad737f37c013335578e1555d162f0591929de747 -libblastrampoline.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/md5/ad9f213bc4a7882784ad09017fc82234 -libblastrampoline.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/sha512/4de6f08a45cb3c3819f71ccd44688b847c2e9b36e0d4bce94191558fe2d775c2790f4c68eea1a366d0a869f0c986aa33626d427946403cf4e128f45b5881f70e -libblastrampoline.v5.10.1+0.x86_64-w64-mingw32.tar.gz/md5/2d0cf117d8d797e7716f8d836dfdd9f5 -libblastrampoline.v5.10.1+0.x86_64-w64-mingw32.tar.gz/sha512/d7a94f3a71400b22b6c14648455e38dff750eb88661928b66b307f721d53769dea3aec43bb86e2200145ed072475c32e1bfc38e0fc35445c4c42e5752754b0e5 +blastrampoline-05083d50611b5538df69706f0a952d8e642b0b4b.tar.gz/md5/700b22cb26291736bd1263cd2a7f2d75 +blastrampoline-05083d50611b5538df69706f0a952d8e642b0b4b.tar.gz/sha512/967c16d28834df112916c0904dd4c7231a1c5e4edf279adb26411faa17da28eee4680ce2347b3941520dccbc768944277a8f724b21976960d00f840349b90e36 +libblastrampoline.v5.11.0+0.aarch64-apple-darwin.tar.gz/md5/769458d40e004d6126cae6b34351068f +libblastrampoline.v5.11.0+0.aarch64-apple-darwin.tar.gz/sha512/75a726b9a4f41b70344ceb9e1f1a7ad370bfa84ce44c70b8a965061d777871e3bf2237ae055da7e6202ddef78932ba8baf2a01a675b1b0cec5338ef16ea2081b +libblastrampoline.v5.11.0+0.aarch64-linux-gnu.tar.gz/md5/d92cf3f3fa1e977ea3a1a74acc8442d1 +libblastrampoline.v5.11.0+0.aarch64-linux-gnu.tar.gz/sha512/3354f4eec2a410f81cc0546a04ce98ddd416d441c1701a59ec5bebea99af8823b5af10a85cb4e3377548422c6d6a0a870f2e7a05ad0cda52c6143361d59ba4fb +libblastrampoline.v5.11.0+0.aarch64-linux-musl.tar.gz/md5/41d060c03202b662e47bda5fbf7b1e84 +libblastrampoline.v5.11.0+0.aarch64-linux-musl.tar.gz/sha512/54a05516e12350441c33341fde53bc912aa52dc4b746089c2d21cb75f24f0fb140849a520327db6f52895743eab090b59fa974a2a426a49f8b4e38693340a306 +libblastrampoline.v5.11.0+0.armv6l-linux-gnueabihf.tar.gz/md5/4930dceefac63e7aa5a93e1ba0e00e59 +libblastrampoline.v5.11.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/dafce083c2b409ead61fdbdf4f46b7c93cab00c82a74a181d381c4a93f1e7af035cd6caf407b0199c1f8c2f2f68f93d67938ef092fa4a8d1133f0ea73fb51a9c +libblastrampoline.v5.11.0+0.armv6l-linux-musleabihf.tar.gz/md5/82346cc4ddeaa29ea7a081edfdfcb08b +libblastrampoline.v5.11.0+0.armv6l-linux-musleabihf.tar.gz/sha512/72e387bd661096a46077e8c15e12f8a6f18fd6aaf30af0678d00eca0d83af10758874643f5716539dd38269e831e4649d45db739aeb60996bf1b96277cea1d17 +libblastrampoline.v5.11.0+0.armv7l-linux-gnueabihf.tar.gz/md5/7e8f115268e8c62acaa2a53ecd32e2fe +libblastrampoline.v5.11.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/4210c306ff7ccb53aa6c9f45e134c63b238c563ed753f7536dfc21f6962dfea35d9de62e429e2685b70d0db780ac766b72fd5e76e2d62df74000e3e5d553c30f +libblastrampoline.v5.11.0+0.armv7l-linux-musleabihf.tar.gz/md5/7f388611c477b528a091f697b0d334d9 +libblastrampoline.v5.11.0+0.armv7l-linux-musleabihf.tar.gz/sha512/e9b017dfa8c19cb940395b253f3b28511a6619469fabff7ab1671ed0936e9e0681d1385c3d1f5d6417ccb65ffbdcf53a0c8519d4ef8e89f9500a05ca00296144 +libblastrampoline.v5.11.0+0.i686-linux-gnu.tar.gz/md5/254948ea87a435251b1e064a77b3d635 +libblastrampoline.v5.11.0+0.i686-linux-gnu.tar.gz/sha512/5a51d3c20c49c497a8f0c2d2e7b38b49ec5e367c7013a7f0efa4fc099639da20ef9c0bfdbdfbdc40b27ce61f189b18f5cf617d7a0ed4bc5300da692f7d6b77a4 +libblastrampoline.v5.11.0+0.i686-linux-musl.tar.gz/md5/a9504870af8db1e247be02c5e188f7a5 +libblastrampoline.v5.11.0+0.i686-linux-musl.tar.gz/sha512/5f0109168a16edb8ca66fcf10c2c10b57fe9c3061c0b08dac4dea936538fa5854aa1b66079f127b5d9902288b61772054013256aa307b682de38e350b1bbb367 +libblastrampoline.v5.11.0+0.i686-w64-mingw32.tar.gz/md5/815822f6bacb42c35b80bc77458c5c49 +libblastrampoline.v5.11.0+0.i686-w64-mingw32.tar.gz/sha512/c82f8c6fe0b7917860e5601c79e35d56297c53b6f7f992841d4f048e7981533e459f9db0805a16d82a9e03d452489760def0d9c57181dcfa5dc363102180eecd +libblastrampoline.v5.11.0+0.powerpc64le-linux-gnu.tar.gz/md5/ee30c9cb4c51df03026f9e471040e9cc +libblastrampoline.v5.11.0+0.powerpc64le-linux-gnu.tar.gz/sha512/5055d83a1b0625364ddd97652a4c6fa39c795078123cad33a085283889274f66c9dc053be0591c14be262dc7eef666726afa922c66ae8d05c2791c3d6bd7009e +libblastrampoline.v5.11.0+0.x86_64-apple-darwin.tar.gz/md5/210cd354c9b4a8aa2a2b55723597e58b +libblastrampoline.v5.11.0+0.x86_64-apple-darwin.tar.gz/sha512/1ee65d598f9f8a2cf7137135c8c2c431520b1cde319fc33dddfbdae9fe01d986e979a97c24cf85c090cc40064cfe47c376dfeb088ff417d17868c4df84fb2fd4 +libblastrampoline.v5.11.0+0.x86_64-linux-gnu.tar.gz/md5/e2213c42eebee6e45079ef6831077b3f +libblastrampoline.v5.11.0+0.x86_64-linux-gnu.tar.gz/sha512/ab2c3026d34962a2ca5116d71a4e8eaaca5182d53f21edd3e4be81ce26e74e427c88797308af7fbbf1b9ee615e0383acf0dae1d0eb207ebc64dddaf927f00b48 +libblastrampoline.v5.11.0+0.x86_64-linux-musl.tar.gz/md5/8cde3c618e882ea2b7c8a017a69175c7 +libblastrampoline.v5.11.0+0.x86_64-linux-musl.tar.gz/sha512/8a3aca5691c3936d114c804471b2429b9ae81308f020247765614d2f792f93a012263ce4baa31cf42f4dacc23a7161a4c7f9debfba8d9028879f1ed3fc4e2433 +libblastrampoline.v5.11.0+0.x86_64-unknown-freebsd.tar.gz/md5/b02eb694e1486ef8ffe9534ac2bd5ec6 +libblastrampoline.v5.11.0+0.x86_64-unknown-freebsd.tar.gz/sha512/989273809ae567d7e7193529740423ac1870eae3a0effeecc67f84da914d81649786f393e101f013b7232ef5fe35066d89b3cb776ad0e87394799491ef28a467 +libblastrampoline.v5.11.0+0.x86_64-w64-mingw32.tar.gz/md5/6e7f602ab0bf5a5c28bf4e959a1bbf77 +libblastrampoline.v5.11.0+0.x86_64-w64-mingw32.tar.gz/sha512/556e7ca1a2576c1d7825ac1bc2449ffe2cd40391cf316b10f60681a5c736939c97eb5221c2837640928b5544f89f44cb14ca44ccf54092376390ea1a6012c9e5 diff --git a/stdlib/libblastrampoline_jll/Project.toml b/stdlib/libblastrampoline_jll/Project.toml index 1d24d2470db2d..1dd22b7fb8d40 100644 --- a/stdlib/libblastrampoline_jll/Project.toml +++ b/stdlib/libblastrampoline_jll/Project.toml @@ -1,6 +1,6 @@ name = "libblastrampoline_jll" uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.10.1+0" +version = "5.11.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 0f51a6375f2ced11a47ea8266a2bc87f94e69a25 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 1 Aug 2024 00:13:31 -0400 Subject: [PATCH 112/206] ascii=true and fullhex=true flags for escape_string (#55099) --- NEWS.md | 3 +++ base/strings/io.jl | 30 +++++++++++++++++++++--------- test/strings/io.jl | 5 +++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index d09581e87e4b5..2eb8096bcd0d2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -92,6 +92,9 @@ New library features data-races. Or use the callback form of `open` to have all that handled automatically. * `@timed` now additionally returns the elapsed compilation and recompilation time ([#52889]) +* `escape_string` takes additional keyword arguments `ascii=true` (to escape all + non-ASCII characters) and `fullhex=true` (to require full 4/8-digit hex numbers + for u/U escapes, e.g. for C compatibility) [#55099]). * `filter` can now act on a `NamedTuple` ([#50795]). * `tempname` can now take a suffix string to allow the file name to include a suffix and include that suffix in the uniquing checking ([#53474]) diff --git a/base/strings/io.jl b/base/strings/io.jl index 46353ff6f7c29..6de72e07cd172 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -382,8 +382,8 @@ escape_nul(c::Union{Nothing, AbstractChar}) = (c !== nothing && '0' <= c <= '7') ? "\\x00" : "\\0" """ - escape_string(str::AbstractString[, esc]; keep = ())::AbstractString - escape_string(io, str::AbstractString[, esc]; keep = ())::Nothing + escape_string(str::AbstractString[, esc]; keep=(), ascii=false, fullhex=false)::AbstractString + escape_string(io, str::AbstractString[, esc]; keep=())::Nothing General escaping of traditional C and Unicode escape sequences. The first form returns the escaped string, the second prints the result to `io`. @@ -398,11 +398,23 @@ escaped by a prepending backslash (`\"` is also escaped by default in the first The argument `keep` specifies a collection of characters which are to be kept as they are. Notice that `esc` has precedence here. +The argument `ascii` can be set to `true` to escape all non-ASCII characters, +whereas the default `ascii=false` outputs printable Unicode characters as-is. +(`keep` takes precedence over `ascii`.) + +The argument `fullhex` can be set to `true` to require all `\\u` escapes to be +printed with 4 hex digits, and `\\U` escapes to be printed with 8 hex digits, +whereas by default (`fullhex=false`) they are printed with fewer digits if +possible (omitting leading zeros). + See also [`unescape_string`](@ref) for the reverse operation. !!! compat "Julia 1.7" The `keep` argument is available as of Julia 1.7. +!!! compat "Julia 1.12" + The `ascii` and `fullhex` arguments require Julia 1.12. + # Examples ```jldoctest julia> escape_string("aaa\\nbbb") @@ -421,7 +433,7 @@ julia> escape_string(string('\\u2135','\\0','0')) # \\0 would be ambiguous "ℵ\\\\x000" ``` """ -function escape_string(io::IO, s::AbstractString, esc=""; keep = ()) +function escape_string(io::IO, s::AbstractString, esc=""; keep = (), ascii::Bool=false, fullhex::Bool=false) a = Iterators.Stateful(s) for c::AbstractChar in a if c in esc @@ -436,10 +448,10 @@ function escape_string(io::IO, s::AbstractString, esc=""; keep = ()) isprint(c) ? print(io, c) : print(io, "\\x", string(UInt32(c), base = 16, pad = 2)) elseif !isoverlong(c) && !ismalformed(c) - isprint(c) ? print(io, c) : - c <= '\x7f' ? print(io, "\\x", string(UInt32(c), base = 16, pad = 2)) : - c <= '\uffff' ? print(io, "\\u", string(UInt32(c), base = 16, pad = need_full_hex(peek(a)::Union{AbstractChar,Nothing}) ? 4 : 2)) : - print(io, "\\U", string(UInt32(c), base = 16, pad = need_full_hex(peek(a)::Union{AbstractChar,Nothing}) ? 8 : 4)) + !ascii && isprint(c) ? print(io, c) : + c <= '\x7f' ? print(io, "\\x", string(UInt32(c), base = 16, pad = 2)) : + c <= '\uffff' ? print(io, "\\u", string(UInt32(c), base = 16, pad = fullhex || need_full_hex(peek(a)::Union{AbstractChar,Nothing}) ? 4 : 2)) : + print(io, "\\U", string(UInt32(c), base = 16, pad = fullhex || need_full_hex(peek(a)::Union{AbstractChar,Nothing}) ? 8 : 4)) else # malformed or overlong u = bswap(reinterpret(UInt32, c)::UInt32) while true @@ -450,8 +462,8 @@ function escape_string(io::IO, s::AbstractString, esc=""; keep = ()) end end -escape_string(s::AbstractString, esc=('\"',); keep = ()) = - sprint((io)->escape_string(io, s, esc; keep = keep), sizehint=lastindex(s)) +escape_string(s::AbstractString, esc=('\"',); keep = (), ascii::Bool=false, fullhex::Bool=false) = + sprint((io)->escape_string(io, s, esc; keep, ascii, fullhex), sizehint=lastindex(s)) function print_quoted(io, s::AbstractString) print(io, '"') diff --git a/test/strings/io.jl b/test/strings/io.jl index f1fe0c24e8aea..79e11d8cf5184 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -165,6 +165,11 @@ @test Base.escape_raw_string(raw"some\"string\\", '`') == "some\"string\\\\" @test Base.escape_raw_string(raw"some\"string") == "some\\\"string" @test Base.escape_raw_string(raw"some`string", '`') == "some\\`string" + + # ascii and fullhex flags: + @test escape_string("\u00e4\u00f6\u00fc") == "\u00e4\u00f6\u00fc" + @test escape_string("\u00e4\u00f6\u00fc", ascii=true) == "\\ue4\\uf6\\ufc" + @test escape_string("\u00e4\u00f6\u00fc", ascii=true, fullhex=true) == "\\u00e4\\u00f6\\u00fc" end @testset "join()" begin @test join([]) == join([],",") == "" From 5092379cf4b586cc15e16c14f27eebc4fb5ab11c Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Thu, 1 Aug 2024 08:46:23 +0200 Subject: [PATCH 113/206] document the return types of `fieldname` and `fieldnames` (#55259) --- base/reflection.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/base/reflection.jl b/base/reflection.jl index 7f9772e5ec976..6dfaf34bc0047 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -212,6 +212,8 @@ end Get the name of field `i` of a `DataType`. +The return type is `Symbol`, except when `x <: Tuple`, in which case the index of the field is returned, of type `Int`. + # Examples ```jldoctest julia> fieldname(Rational, 1) @@ -219,6 +221,9 @@ julia> fieldname(Rational, 1) julia> fieldname(Rational, 2) :den + +julia> fieldname(Tuple{String,Int}, 2) +2 ``` """ function fieldname(t::DataType, i::Integer) @@ -246,6 +251,9 @@ fieldname(t::Type{<:Tuple}, i::Integer) = Get a tuple with the names of the fields of a `DataType`. +Each name is a `Symbol`, except when `x <: Tuple`, in which case each name (actually the +index of the field) is an `Int`. + See also [`propertynames`](@ref), [`hasfield`](@ref). # Examples @@ -255,6 +263,9 @@ julia> fieldnames(Rational) julia> fieldnames(typeof(1+im)) (:re, :im) + +julia> fieldnames(Tuple{String,Int}) +(1, 2) ``` """ fieldnames(t::DataType) = (fieldcount(t); # error check to make sure type is specific enough From 2179f146945039dca4093ea511c8fe6ea51276c9 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Thu, 1 Aug 2024 10:16:43 +0200 Subject: [PATCH 114/206] better type inference for several functions taking `NTuple` args (#55124) Improves the abstract return type inference for these functions, for homogeneous tuple arguments: * `tail` * `front` * `reverse` * `circshift` Example: ```julia f(g, t::Type{<:Tuple}) = println(Core.Compiler.return_type(g, t)) f(Base.tail, Tuple{NTuple}) f(Base.front, Tuple{NTuple}) f(reverse, Tuple{NTuple}) f(circshift, Tuple{NTuple,Int}) ``` Results before: ```julia Tuple Tuple Tuple Tuple ``` Results after: ```julia NTuple{N, T} where {N, T} NTuple{N, T} where {N, T} NTuple{N, T} where {N, T} NTuple{N, T} where {N, T} ``` Updates #54495 --- base/essentials.jl | 8 +++++++- base/ntuple.jl | 2 +- base/tuple.jl | 16 +++++++++++++--- test/tuple.jl | 7 +++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 238b4a393c87c..c6a6d43ce17e1 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -501,7 +501,13 @@ julia> Base.tail(()) ERROR: ArgumentError: Cannot call tail on an empty tuple. ``` """ -tail(x::Tuple) = argtail(x...) +function tail(x::Tuple{Any,Vararg}) + y = argtail(x...)::Tuple + if x isa NTuple # help the type inference + y = y::NTuple + end + y +end tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple.")) function unwrap_unionall(@nospecialize(a)) diff --git a/base/ntuple.jl b/base/ntuple.jl index f81d2686b9764..4adab38a8ee82 100644 --- a/base/ntuple.jl +++ b/base/ntuple.jl @@ -95,5 +95,5 @@ end function reverse(t::NTuple{N}) where N ntuple(Val{N}()) do i t[end+1-i] - end + end::NTuple end diff --git a/base/tuple.jl b/base/tuple.jl index fc213410cfd7c..5f74d486e1e69 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -340,9 +340,15 @@ ERROR: ArgumentError: Cannot call front on an empty tuple. """ function front(t::Tuple) @inline - _front(t...) + if t === () + throw(ArgumentError("Cannot call front on an empty tuple.")) + end + r = _front(t...)::Tuple + if t isa NTuple # help the type inference + r = r::NTuple + end + r end -_front() = throw(ArgumentError("Cannot call front on an empty tuple.")) _front(v) = () function _front(v, t...) @inline @@ -699,5 +705,9 @@ function circshift(x::Tuple{Any,Any,Any,Vararg{Any,N}}, shift::Integer) where {N @inline len = N + 3 j = mod1(shift, len) - ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple + y = ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple + if x isa NTuple # help the type inference + y = y::NTuple + end + y end diff --git a/test/tuple.jl b/test/tuple.jl index b1894bd2bb6ce..59897c8adfdb2 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -845,3 +845,10 @@ end end end end + +@testset "abstract return type inference for homogeneous tuples" begin + @test NTuple == Core.Compiler.return_type(Base.tail, Tuple{NTuple}) + @test NTuple == Core.Compiler.return_type(Base.front, Tuple{NTuple}) + @test NTuple == Core.Compiler.return_type(reverse, Tuple{NTuple}) + @test NTuple == Core.Compiler.return_type(circshift, Tuple{NTuple,Int}) +end From df1976d500914bebd5651bf56c13153f49e153f9 Mon Sep 17 00:00:00 2001 From: Jakob Nybo Nissen Date: Thu, 1 Aug 2024 11:28:30 +0200 Subject: [PATCH 115/206] Define parent(::GenericMemoryRef) (#55325) It would be nice to have function to extract the `GenericMemory` underlying the `GenericMemoryRef`, without accessing its undocumented field `.mem`. I'm not sure `parent` is the right function for this, but it's the best I could think of. --- base/genericmemory.jl | 2 ++ test/arrayops.jl | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/base/genericmemory.jl b/base/genericmemory.jl index 6df6c880f74a8..6537839320206 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -71,6 +71,8 @@ size(a::GenericMemory) = (length(a),) IndexStyle(::Type{<:GenericMemory}) = IndexLinear() +parent(ref::GenericMemoryRef) = ref.mem + pointer(mem::GenericMemoryRef) = unsafe_convert(Ptr{Cvoid}, mem) # no bounds check, even for empty array _unsetindex!(A::Memory, i::Int) = (@_propagate_inbounds_meta; _unsetindex!(memoryref(A, i)); A) diff --git a/test/arrayops.jl b/test/arrayops.jl index e407ad7233bc2..c904a52e8cad9 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3246,3 +3246,9 @@ end @test size(mem, 2) == 1 @test size(mem, 0x2) == 1 end + +@testset "MemoryRef" begin + mem = Memory{Float32}(undef, 3) + ref = memoryref(mem, 2) + @test parent(ref) === mem +end From 7c6a1a217efa25f9f700b1c30301ab596f391615 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 1 Aug 2024 09:47:19 -0400 Subject: [PATCH 116/206] inference: Remove special casing for `!` (#55271) We have a handful of cases in inference where we look up functions by name (using `istopfunction`) and give them special behavior. I'd like to remove these. They're not only aesthetically ugly, but because they depend on binding lookups, rather than values, they have unclear semantics as those bindings change. They are also unsound should a user use the same name for something differnt in their own top modules (of course, it's unlikely that a user would do such a thing, but it's bad that they can't). This particular PR removes the special case for `!`, which was there to strengthen the inference result for `!` on Conditional. However, with a little bit of strengthening of the rest of the system, this can be equally well evaluated through the existing InterConditional mechanism. --- base/compiler/abstractinterpretation.jl | 46 ++++++++++++++++++++----- base/compiler/inferencestate.jl | 3 ++ base/compiler/tfuncs.jl | 11 +++++- test/compiler/inference.jl | 5 +++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 22bc1cf046d98..a7602f8cd4134 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -13,6 +13,31 @@ call_result_unused(sv::InferenceState, currpc::Int) = isexpr(sv.src.code[currpc], :call) && isempty(sv.ssavalue_uses[currpc]) call_result_unused(si::StmtInfo) = !si.used +is_const_bool_or_bottom(@nospecialize(b)) = (isa(b, Const) && isa(b.val, Bool)) || b == Bottom +function can_propagate_conditional(@nospecialize(rt), argtypes::Vector{Any}) + isa(rt, InterConditional) || return false + if rt.slot > length(argtypes) + # In the vararg tail - can't be conditional + @assert isvarargtype(argtypes[end]) + return false + end + return isa(argtypes[rt.slot], Conditional) && + is_const_bool_or_bottom(rt.thentype) && is_const_bool_or_bottom(rt.thentype) +end + +function propagate_conditional(rt::InterConditional, cond::Conditional) + new_thentype = rt.thentype === Const(false) ? cond.elsetype : cond.thentype + new_elsetype = rt.elsetype === Const(true) ? cond.thentype : cond.elsetype + if rt.thentype == Bottom + @assert rt.elsetype != Bottom + return Conditional(cond.slot, Bottom, new_elsetype) + elseif rt.elsetype == Bottom + @assert rt.thentype != Bottom + return Conditional(cond.slot, new_thentype, Bottom) + end + return Conditional(cond.slot, new_thentype, new_elsetype) +end + function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), arginfo::ArgInfo, si::StmtInfo, @nospecialize(atype), sv::AbsIntState, max_methods::Int) @@ -156,6 +181,15 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end @assert !(this_conditional isa Conditional || this_rt isa MustAlias) "invalid lattice element returned from inter-procedural context" seen += 1 + + if can_propagate_conditional(this_conditional, argtypes) + # The only case where we need to keep this in rt is where + # we can directly propagate the conditional to a slot argument + # that is not one of our arguments, otherwise we keep all the + # relevant information in `conditionals` below. + this_rt = this_conditional + end + rettype = rettype ⊔ₚ this_rt exctype = exctype ⊔ₚ this_exct if has_conditional(𝕃ₚ, sv) && this_conditional !== Bottom && is_lattice_bool(𝕃ₚ, rettype) && fargs !== nothing @@ -409,6 +443,9 @@ function from_interconditional(𝕃ᵢ::AbstractLattice, @nospecialize(rt), sv:: has_conditional(𝕃ᵢ, sv) || return widenconditional(rt) (; fargs, argtypes) = arginfo fargs === nothing && return widenconditional(rt) + if can_propagate_conditional(rt, argtypes) + return propagate_conditional(rt, argtypes[rt.slot]::Conditional) + end slot = 0 alias = nothing thentype = elsetype = Any @@ -2217,13 +2254,6 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), end elseif is_return_type(f) return return_type_tfunc(interp, argtypes, si, sv) - elseif la == 2 && istopfunction(f, :!) - # handle Conditional propagation through !Bool - aty = argtypes[2] - if isa(aty, Conditional) - call = abstract_call_gf_by_type(interp, f, ArgInfo(fargs, Any[Const(f), Bool]), si, Tuple{typeof(f), Bool}, sv, max_methods) # make sure we've inferred `!(::Bool)` - return CallMeta(Conditional(aty.slot, aty.elsetype, aty.thentype), Any, call.effects, call.info) - end elseif la == 3 && istopfunction(f, :!==) # mark !== as exactly a negated call to === call = abstract_call_gf_by_type(interp, f, ArgInfo(fargs, Any[Const(f), Any, Any]), si, Tuple{typeof(f), Any, Any}, sv, max_methods) @@ -3194,7 +3224,7 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState, # narrow representation of bestguess slightly to prepare for tmerge with rt if rt isa InterConditional && bestguess isa Const slot_id = rt.slot - old_id_type = slottypes[slot_id] + old_id_type = widenconditional(slottypes[slot_id]) if bestguess.val === true && rt.elsetype !== Bottom bestguess = InterConditional(slot_id, old_id_type, Bottom) elseif bestguess.val === false && rt.thentype !== Bottom diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index c358b1177251f..38011656e41ea 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -312,6 +312,9 @@ mutable struct InferenceState nargtypes = length(argtypes) for i = 1:nslots argtyp = (i > nargtypes) ? Bottom : argtypes[i] + if argtyp === Bool && has_conditional(typeinf_lattice(interp)) + argtyp = Conditional(i, Const(true), Const(false)) + end slottypes[i] = argtyp bb_vartable1[i] = VarState(argtyp, i > nargtypes) end diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 28e883d83312c..b40f65ab3ca1d 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -227,10 +227,19 @@ end @nospecs shift_tfunc(𝕃::AbstractLattice, x, y) = shift_tfunc(widenlattice(𝕃), x, y) @nospecs shift_tfunc(::JLTypeLattice, x, y) = widenconst(x) +function not_tfunc(𝕃::AbstractLattice, @nospecialize(b)) + if isa(b, Conditional) + return Conditional(b.slot, b.elsetype, b.thentype) + elseif isa(b, Const) + return Const(not_int(b.val)) + end + return math_tfunc(𝕃, b) +end + add_tfunc(and_int, 2, 2, and_int_tfunc, 1) add_tfunc(or_int, 2, 2, or_int_tfunc, 1) add_tfunc(xor_int, 2, 2, math_tfunc, 1) -add_tfunc(not_int, 1, 1, math_tfunc, 0) # usually used as not_int(::Bool) to negate a condition +add_tfunc(not_int, 1, 1, not_tfunc, 0) # usually used as not_int(::Bool) to negate a condition add_tfunc(shl_int, 2, 2, shift_tfunc, 1) add_tfunc(lshr_int, 2, 2, shift_tfunc, 1) add_tfunc(ashr_int, 2, 2, shift_tfunc, 1) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 8b6da828af54d..9ae98b884bef4 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5866,3 +5866,8 @@ end bar54341(args...) = foo54341(4, args...) @test Core.Compiler.return_type(bar54341, Tuple{Vararg{Int}}) === Int + +# InterConditional rt with Vararg argtypes +fcondvarargs(a, b, c, d) = isa(d, Int64) +gcondvarargs(a, x...) = return fcondvarargs(a, x...) ? isa(a, Int64) : !isa(a, Int64) +@test Core.Compiler.return_type(gcondvarargs, Tuple{Vararg{Any}}) === Bool From 0ef8a91e490dfaa90cb6e4781ca0445c7f991933 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 1 Aug 2024 14:46:19 +0000 Subject: [PATCH 117/206] Preserve structure in scaling triangular matrices by NaN (#55310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the `Matrix` cases from https://github.com/JuliaLang/julia/issues/55296. This restores the behavior to match that on v1.10, and preserves the structure of the matrix on scaling by `NaN`. This behavior is consistent with the strong-zero behavior for other structured matrix types, and the scaling may be seen to be occurring in the vector space corresponding to the filled elements. After this, ```julia julia> UpperTriangular(rand(2,2)) * NaN 2×2 UpperTriangular{Float64, Matrix{Float64}}: NaN NaN ⋅ NaN ``` cc. @mikmoore --- stdlib/LinearAlgebra/src/triangular.jl | 61 +++++++++++++++++++++++-- stdlib/LinearAlgebra/test/triangular.jl | 14 ++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index c45db3e90fab2..365ce8ee4bae2 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -702,6 +702,43 @@ function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriang return A end +function _trirdiv!(A::UpperTriangular, B::UpperOrUnitUpperTriangular, c::Number) + n = checksize1(A, B) + for j in 1:n + for i in 1:j + @inbounds A[i, j] = B[i, j] / c + end + end + return A +end +function _trirdiv!(A::LowerTriangular, B::LowerOrUnitLowerTriangular, c::Number) + n = checksize1(A, B) + for j in 1:n + for i in j:n + @inbounds A[i, j] = B[i, j] / c + end + end + return A +end +function _trildiv!(A::UpperTriangular, c::Number, B::UpperOrUnitUpperTriangular) + n = checksize1(A, B) + for j in 1:n + for i in 1:j + @inbounds A[i, j] = c \ B[i, j] + end + end + return A +end +function _trildiv!(A::LowerTriangular, c::Number, B::LowerOrUnitLowerTriangular) + n = checksize1(A, B) + for j in 1:n + for i in j:n + @inbounds A[i, j] = c \ B[i, j] + end + end + return A +end + rmul!(A::UpperOrLowerTriangular, c::Number) = @inline _triscale!(A, A, c, MulAddMul()) lmul!(c::Number, A::UpperOrLowerTriangular) = @inline _triscale!(A, c, A, MulAddMul()) @@ -1095,7 +1132,11 @@ for (t, unitt) in ((UpperTriangular, UnitUpperTriangular), tstrided = t{<:Any, <:StridedMaybeAdjOrTransMat} @eval begin (*)(A::$t, x::Number) = $t(A.data*x) - (*)(A::$tstrided, x::Number) = A .* x + function (*)(A::$tstrided, x::Number) + eltype_dest = promote_op(*, eltype(A), typeof(x)) + dest = $t(similar(parent(A), eltype_dest)) + _triscale!(dest, x, A, MulAddMul()) + end function (*)(A::$unitt, x::Number) B = $t(A.data)*x @@ -1106,7 +1147,11 @@ for (t, unitt) in ((UpperTriangular, UnitUpperTriangular), end (*)(x::Number, A::$t) = $t(x*A.data) - (*)(x::Number, A::$tstrided) = x .* A + function (*)(x::Number, A::$tstrided) + eltype_dest = promote_op(*, typeof(x), eltype(A)) + dest = $t(similar(parent(A), eltype_dest)) + _triscale!(dest, x, A, MulAddMul()) + end function (*)(x::Number, A::$unitt) B = x*$t(A.data) @@ -1117,7 +1162,11 @@ for (t, unitt) in ((UpperTriangular, UnitUpperTriangular), end (/)(A::$t, x::Number) = $t(A.data/x) - (/)(A::$tstrided, x::Number) = A ./ x + function (/)(A::$tstrided, x::Number) + eltype_dest = promote_op(/, eltype(A), typeof(x)) + dest = $t(similar(parent(A), eltype_dest)) + _trirdiv!(dest, A, x) + end function (/)(A::$unitt, x::Number) B = $t(A.data)/x @@ -1129,7 +1178,11 @@ for (t, unitt) in ((UpperTriangular, UnitUpperTriangular), end (\)(x::Number, A::$t) = $t(x\A.data) - (\)(x::Number, A::$tstrided) = x .\ A + function (\)(x::Number, A::$tstrided) + eltype_dest = promote_op(\, typeof(x), eltype(A)) + dest = $t(similar(parent(A), eltype_dest)) + _trildiv!(dest, x, A) + end function (\)(x::Number, A::$unitt) B = x\$t(A.data) diff --git a/stdlib/LinearAlgebra/test/triangular.jl b/stdlib/LinearAlgebra/test/triangular.jl index 5ee8143e3f4bb..3f7cea91ec6d4 100644 --- a/stdlib/LinearAlgebra/test/triangular.jl +++ b/stdlib/LinearAlgebra/test/triangular.jl @@ -1180,4 +1180,18 @@ end @test V == Diagonal([1, 1]) end +@testset "preserve structure in scaling by NaN" begin + M = rand(Int8,2,2) + for (Ts, TD) in (((UpperTriangular, UnitUpperTriangular), UpperTriangular), + ((LowerTriangular, UnitLowerTriangular), LowerTriangular)) + for T in Ts + U = T(M) + for V in (U * NaN, NaN * U, U / NaN, NaN \ U) + @test V isa TD{Float64, Matrix{Float64}} + @test all(isnan, diag(V)) + end + end + end +end + end # module TestTriangular From c6732a79494f604e0f320ea451856a1c10511659 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 2 Aug 2024 04:51:21 -0400 Subject: [PATCH 118/206] Avoid duplicate stat calls during startup/loading (#55331) Avoids immediately successive stat calls for the same path during startup & loading. According to MacOS Instruments this reduces `stat64` calls during `--start=no -e "using Pkg"` from 844 to 672. On MacOS I don't see a speed improvement, but on WSL2 @timholy reported the test from https://github.com/JuliaLang/julia/issues/55171 sees a modest improvement. This PR (10 iterations) ``` tim@diva:~/.julia/bin$ time for i in {1..10}; do ./cli --help &> /dev/null; done real 0m2.999s user 0m3.547s sys 0m6.552s ``` master ``` real 0m3.217s user 0m3.794s sys 0m6.700s ``` 1.11-rc2: ``` real 0m3.746s user 0m4.169s sys 0m6.755s ``` I left the `@debug`s in as they might be useful for similar investigations. --- base/client.jl | 2 ++ base/loading.jl | 12 +++++++----- base/stat.jl | 10 ++++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/base/client.jl b/base/client.jl index aa0739eaed0fe..3aebfaf6de696 100644 --- a/base/client.jl +++ b/base/client.jl @@ -339,11 +339,13 @@ function _global_julia_startup_file() # If it is not found, then continue on to the relative path based on Sys.BINDIR BINDIR = Sys.BINDIR SYSCONFDIR = Base.SYSCONFDIR + p1 = nothing if !isempty(SYSCONFDIR) p1 = abspath(BINDIR, SYSCONFDIR, "julia", "startup.jl") isfile(p1) && return p1 end p2 = abspath(BINDIR, "..", "etc", "julia", "startup.jl") + p1 == p2 && return nothing # don't check the same path twice isfile(p2) && return p2 return nothing end diff --git a/base/loading.jl b/base/loading.jl index fa46819c5731c..c273e4505701f 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -822,14 +822,15 @@ end # given a project directory (implicit env from LOAD_PATH) and a name, # find an entry point for `name`, and see if it has an associated project file function entry_point_and_project_file(dir::String, name::String)::Union{Tuple{Nothing,Nothing},Tuple{String,Nothing},Tuple{String,String}} - path = normpath(joinpath(dir, "$name.jl")) - isfile_casesensitive(path) && return path, nothing dir_name = joinpath(dir, name) path, project_file = entry_point_and_project_file_inside(dir_name, name) path === nothing || return path, project_file dir_jl = dir_name * ".jl" path, project_file = entry_point_and_project_file_inside(dir_jl, name) path === nothing || return path, project_file + # check for less likely case with a bare file and no src directory last to minimize stat calls + path = normpath(joinpath(dir, "$name.jl")) + isfile_casesensitive(path) && return path, nothing return nothing, nothing end @@ -3809,7 +3810,7 @@ end end if !ispath(f) _f = fixup_stdlib_path(f) - if isfile(_f) && startswith(_f, Sys.STDLIB) + if _f != f && isfile(_f) && startswith(_f, Sys.STDLIB) continue end @debug "Rejecting stale cache file $cachefile because file $f does not exist" @@ -3831,13 +3832,14 @@ end return true end else - fsize = filesize(f) + fstat = stat(f) + fsize = filesize(fstat) if fsize != fsize_req @debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)" record_reason(reasons, "include_dependency fsize change") return true end - hash = isdir(f) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r") + hash = isdir(fstat) ? _crc32c(join(readdir(f))) : open(_crc32c, f, "r") if hash != hash_req @debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)" record_reason(reasons, "include_dependency fhash change") diff --git a/base/stat.jl b/base/stat.jl index 29edf010b7815..3330ff0c35bc8 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -184,8 +184,14 @@ macro stat_call(sym, arg1type, arg) end stat(fd::OS_HANDLE) = @stat_call jl_fstat OS_HANDLE fd -stat(path::AbstractString) = @stat_call jl_stat Cstring path -lstat(path::AbstractString) = @stat_call jl_lstat Cstring path +function stat(path::AbstractString) + # @info "stat($(repr(path)))" exception=(ErrorException("Fake error for backtrace printing"),stacktrace()) + @stat_call jl_stat Cstring path +end +function lstat(path::AbstractString) + # @info "lstat($(repr(path)))" exception=(ErrorException("Fake error for backtrace printing"),stacktrace()) + @stat_call jl_lstat Cstring path +end if RawFD !== OS_HANDLE global stat(fd::RawFD) = stat(Libc._get_osfhandle(fd)) end From 2635dea5981e71fb672bcb72a17d9fb99195ec54 Mon Sep 17 00:00:00 2001 From: Felix Wechsler Date: Fri, 2 Aug 2024 14:35:04 +0200 Subject: [PATCH 119/206] Add insertdims method which is inverse to dropdims (#45793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example: ```julia julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> b = insertdims(a, dims=(1,4)) 1×2×2×1 Array{Int64, 4}: [:, :, 1, 1] = 1 3 [:, :, 2, 1] = 2 4 julia> b[1,1,1,1] = 5; a 2×2 Matrix{Int64}: 5 2 3 4 julia> b = insertdims(a, dims=(1,2)) 1×1×2×2 Array{Int64, 4}: [:, :, 1, 1] = 5 [:, :, 2, 1] = 3 [:, :, 1, 2] = 2 [:, :, 2, 2] = 4 julia> b = insertdims(a, dims=(1,3)) 1×2×1×2 Array{Int64, 4}: [:, :, 1, 1] = 5 3 [:, :, 1, 2] = 2 4 ``` --------- Co-authored-by: Neven Sajko Co-authored-by: Lilith Orion Hafner Co-authored-by: Mark Kittisopikul --- NEWS.md | 1 + base/abstractarraymath.jl | 64 +++++++++++++++++++++++++++++++++++++++ base/exports.jl | 1 + doc/src/base/arrays.md | 1 + test/arrayops.jl | 29 ++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2eb8096bcd0d2..6f12b8ff389cd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -72,6 +72,7 @@ New library functions * The new `isfull(c::Channel)` function can be used to check if `put!(c, some_value)` will block. ([#53159]) * `waitany(tasks; throw=false)` and `waitall(tasks; failfast=false, throw=false)` which wait multiple tasks at once ([#53341]). * `uuid7()` creates an RFC 9652 compliant UUID with version 7 ([#54834]). +* `insertdims(array; dims)` allows to insert singleton dimensions into an array which is the inverse operation to `dropdims` New library features -------------------- diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index a9efc2b87bee4..0f028a0f66729 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -93,6 +93,70 @@ function _dropdims(A::AbstractArray, dims::Dims) end _dropdims(A::AbstractArray, dim::Integer) = _dropdims(A, (Int(dim),)) + +""" + insertdims(A; dims) + +Inverse of [`dropdims`](@ref); return an array with new singleton dimensions +at every dimension in `dims`. + +Repeated dimensions are forbidden and the largest entry in `dims` must be +less than or equal than `ndims(A) + length(dims)`. + +The result shares the same underlying data as `A`, such that the +result is mutable if and only if `A` is mutable, and setting elements of one +alters the values of the other. + +See also: [`dropdims`](@ref), [`reshape`](@ref), [`vec`](@ref). +# Examples +```jldoctest +julia> x = [1 2 3; 4 5 6] +2×3 Matrix{Int64}: + 1 2 3 + 4 5 6 + +julia> insertdims(x, dims=3) +2×3×1 Array{Int64, 3}: +[:, :, 1] = + 1 2 3 + 4 5 6 + +julia> insertdims(x, dims=(1,2,5)) == reshape(x, 1, 1, 2, 3, 1) +true + +julia> dropdims(insertdims(x, dims=(1,2,5)), dims=(1,2,5)) +2×3 Matrix{Int64}: + 1 2 3 + 4 5 6 +``` + +!!! compat "Julia 1.12" + Requires Julia 1.12 or later. +""" +insertdims(A; dims) = _insertdims(A, dims) +function _insertdims(A::AbstractArray{T, N}, dims::NTuple{M, Int}) where {T, N, M} + for i in eachindex(dims) + 1 ≤ dims[i] || throw(ArgumentError("the smallest entry in dims must be ≥ 1.")) + dims[i] ≤ N+M || throw(ArgumentError("the largest entry in dims must be not larger than the dimension of the array and the length of dims added")) + for j = 1:i-1 + dims[j] == dims[i] && throw(ArgumentError("inserted dims must be unique")) + end + end + + # acc is a tuple, where the first entry is the final shape + # the second entry off acc is a counter for the axes of A + inds= Base._foldoneto((acc, i) -> + i ∈ dims + ? ((acc[1]..., Base.OneTo(1)), acc[2]) + : ((acc[1]..., axes(A, acc[2])), acc[2] + 1), + ((), 1), Val(N+M)) + new_shape = inds[1] + return reshape(A, new_shape) +end +_insertdims(A::AbstractArray, dim::Integer) = _insertdims(A, (Int(dim),)) + + + ## Unary operators ## """ diff --git a/base/exports.jl b/base/exports.jl index 1f0ccdf6b8c36..dbe12f933e597 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -407,6 +407,7 @@ export indexin, argmax, argmin, + insertdims, invperm, invpermute!, isassigned, diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index ccfb23715c476..66fe5c78f1ee6 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -138,6 +138,7 @@ Base.parentindices Base.selectdim Base.reinterpret Base.reshape +Base.insertdims Base.dropdims Base.vec Base.SubArray diff --git a/test/arrayops.jl b/test/arrayops.jl index c904a52e8cad9..f58fdb36942a2 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -308,6 +308,35 @@ end @test_throws ArgumentError dropdims(a, dims=4) @test_throws ArgumentError dropdims(a, dims=6) + + a = rand(8, 7) + @test @inferred(insertdims(a, dims=1)) == @inferred(insertdims(a, dims=(1,))) == reshape(a, (1, 8, 7)) + @test @inferred(insertdims(a, dims=3)) == @inferred(insertdims(a, dims=(3,))) == reshape(a, (8, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 3))) == reshape(a, (1, 8, 1, 7)) + @test @inferred(insertdims(a, dims=(1, 2, 3))) == reshape(a, (1, 1, 1, 8, 7)) + @test @inferred(insertdims(a, dims=(1, 4))) == reshape(a, (1, 8, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 3, 5))) == reshape(a, (1, 8, 1, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 2, 4, 6))) == reshape(a, (1, 1, 8, 1, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 3, 4, 6))) == reshape(a, (1, 8, 1, 1, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 4, 6, 3))) == reshape(a, (1, 8, 1, 1, 7, 1)) + @test @inferred(insertdims(a, dims=(1, 3, 5, 6))) == reshape(a, (1, 8, 1, 7, 1, 1)) + + @test_throws ArgumentError insertdims(a, dims=(1, 1, 2, 3)) + @test_throws ArgumentError insertdims(a, dims=(1, 2, 2, 3)) + @test_throws ArgumentError insertdims(a, dims=(1, 2, 3, 3)) + @test_throws UndefKeywordError insertdims(a) + @test_throws ArgumentError insertdims(a, dims=0) + @test_throws ArgumentError insertdims(a, dims=(1, 2, 1)) + @test_throws ArgumentError insertdims(a, dims=4) + @test_throws ArgumentError insertdims(a, dims=6) + + # insertdims and dropdims are inverses + b = rand(1,1,1,5,1,1,7) + for dims in [1, (1,), 2, (2,), 3, (3,), (1,3), (1,2,3), (1,2), (1,3,5), (1,2,5,6), (1,3,5,6), (1,3,5,6), (1,6,5,3)] + @test dropdims(insertdims(a; dims); dims) == a + @test insertdims(dropdims(b; dims); dims) == b + end + sz = (5,8,7) A = reshape(1:prod(sz),sz...) @test A[2:6] == [2:6;] From 2ec9143d2e5982bb4a6bc31367aa8fca446ec007 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 2 Aug 2024 11:25:34 -0400 Subject: [PATCH 120/206] Move `typename` and `<:` to Core and have inference check by value (#55289) As mentioned in #55271, the `istopfunction` binding-based comparisons are problematic. In #55272 and #55273, I attempted to remove the inference special cases for `>:` and `typename` (respectively) entirely, but for differing reasons (`>:` gets too many extra specializations, `typename` loses precision), those PRs are suboptimal. As discussed in #55273, this PR instead moves these functions to Core, so that both `Core.Compiler` and `Base` share the function object, allowing inference to detect them and apply the special handling by simple value-comparison. --- - closes #55273 --- base/boot.jl | 23 +++++++++++++++++++++++ base/compiler/abstractinterpretation.jl | 6 +++--- base/compiler/ssair/inlining.jl | 4 ++-- base/compiler/utilities.jl | 9 --------- base/errorshow.jl | 9 +++++++++ base/essentials.jl | 10 +--------- base/operators.jl | 8 ++++++-- test/reflection.jl | 2 +- 8 files changed, 45 insertions(+), 26 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 3afb0e563483d..f7aee9677e2f2 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -1018,6 +1018,29 @@ const ARRAY_INDEX_HEURISTIC = 0x2 const ITERATE_HEURISTIC = 0x3 const SAMETYPE_HEURISTIC = 0x4 +# `typename` has special tfunc support in inference to improve +# the result for `Type{Union{...}}`. It is defined here, so that the Compiler +# can look it up by value. +struct TypeNameError <: Exception + a + TypeNameError(@nospecialize(a)) = new(a) +end + +typename(a) = throw(TypeNameError(a)) +typename(a::DataType) = a.name +function typename(a::Union) + ta = typename(a.a) + tb = typename(a.b) + ta === tb || throw(TypeNameError(a)) + return tb +end +typename(union::UnionAll) = typename(union.body) + +# Special inference support to avoid execess specialization of these methods. +# TODO: Replace this by a generic heuristic. +(>:)(@nospecialize(a), @nospecialize(b)) = (b <: a) +(!==)(@nospecialize(a), @nospecialize(b)) = Intrinsics.not_int(a === b) + include(Core, "optimized_generics.jl") ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index a7602f8cd4134..6a7d90a7bcb21 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2254,7 +2254,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), end elseif is_return_type(f) return return_type_tfunc(interp, argtypes, si, sv) - elseif la == 3 && istopfunction(f, :!==) + elseif la == 3 && f === Core.:(!==) # mark !== as exactly a negated call to === call = abstract_call_gf_by_type(interp, f, ArgInfo(fargs, Any[Const(f), Any, Any]), si, Tuple{typeof(f), Any, Any}, sv, max_methods) rty = abstract_call_known(interp, (===), arginfo, si, sv, max_methods).rt @@ -2264,7 +2264,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), return CallMeta(Const(rty.val === false), Bottom, EFFECTS_TOTAL, MethodResultPure()) end return call - elseif la == 3 && istopfunction(f, :(>:)) + elseif la == 3 && f === Core.:(>:) # mark issupertype as a exact alias for issubtype # swap T1 and T2 arguments and call <: if fargs !== nothing && length(fargs) == 3 @@ -2274,7 +2274,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), end argtypes = Any[typeof(<:), argtypes[3], argtypes[2]] return abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods) - elseif la == 2 && istopfunction(f, :typename) + elseif la == 2 && f === Core.typename return CallMeta(typename_static(argtypes[2]), Bottom, EFFECTS_TOTAL, MethodResultPure()) elseif f === Core._hasmethod return _hasmethod_tfunc(interp, argtypes, sv) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index a77a67ab262de..70318b9e1a979 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1728,7 +1728,7 @@ function late_inline_special_case!(ir::IRCode, idx::Int, stmt::Expr, flag::UInt3 @nospecialize(type), sig::Signature, state::InliningState) OptimizationParams(state.interp).inlining || return nothing (; f, ft, argtypes) = sig - if length(argtypes) == 3 && istopfunction(f, :!==) + if length(argtypes) == 3 && f === Core.:(!==) # special-case inliner for !== that precedes _methods_by_ftype union splitting # and that works, even though inference generally avoids inferring the `!==` Method if isa(type, Const) @@ -1738,7 +1738,7 @@ function late_inline_special_case!(ir::IRCode, idx::Int, stmt::Expr, flag::UInt3 cmp_call_ssa = insert_node!(ir, idx, removable_if_unused(NewInstruction(cmp_call, Bool))) not_call = Expr(:call, GlobalRef(Core.Intrinsics, :not_int), cmp_call_ssa) return SomeCase(not_call) - elseif length(argtypes) == 3 && istopfunction(f, :(>:)) + elseif length(argtypes) == 3 && f === Core.:(>:) # special-case inliner for issupertype # that works, even though inference generally avoids inferring the `>:` Method if isa(type, Const) && has_flag(flag, IR_FLAG_NOTHROW) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 527c6ab42eb2d..b3dfd73d53452 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -48,15 +48,6 @@ anymap(f::Function, a::Array{Any,1}) = Any[ f(a[i]) for i in 1:length(a) ] _topmod(m::Module) = ccall(:jl_base_relative_to, Any, (Any,), m)::Module -function istopfunction(@nospecialize(f), name::Symbol) - tn = typeof(f).name - if tn.mt.name === name - top = _topmod(tn.module) - return isdefined(top, name) && isconst(top, name) && f === getglobal(top, name) - end - return false -end - ####### # AST # ####### diff --git a/base/errorshow.jl b/base/errorshow.jl index fc9fc5c2aac32..a3bf464439d44 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -43,6 +43,15 @@ function showerror(io::IO, ex::Meta.ParseError) end end +function showerror(io::IO, ex::Core.TypeNameError) + print(io, "TypeNameError: ") + if isa(ex.a, Union) + print(io, "typename does not apply to unions whose components have different typenames") + else + print(io, "typename does not apply to this type") + end +end + function showerror(io::IO, ex::BoundsError) print(io, "BoundsError") if isdefined(ex, :a) diff --git a/base/essentials.jl b/base/essentials.jl index c6a6d43ce17e1..2e76235cba9a6 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -581,15 +581,7 @@ function unconstrain_vararg_length(va::Core.TypeofVararg) return Vararg{unwrapva(va)} end -typename(a) = error("typename does not apply to this type") -typename(a::DataType) = a.name -function typename(a::Union) - ta = typename(a.a) - tb = typename(a.b) - ta === tb || error("typename does not apply to unions whose components have different typenames") - return tb -end -typename(union::UnionAll) = typename(union.body) +import Core: typename _tuple_error(T::Type, x) = (@noinline; throw(MethodError(convert, (T, x)))) diff --git a/base/operators.jl b/base/operators.jl index dc3c01e5645cc..b7605ba004b7a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -58,12 +58,14 @@ but which do not execute the operator or return a Bool: """ (<:) +import Core: >: + """ >:(T1, T2) Supertype operator, equivalent to `T2 <: T1`. """ -(>:)(@nospecialize(a), @nospecialize(b)) = (b <: a) +>: """ supertype(T::Union{DataType, UnionAll}) @@ -346,6 +348,7 @@ true === const ≡ = === +import Core: !== """ !==(x, y) ≢(x,y) @@ -363,7 +366,8 @@ julia> a ≢ a false ``` """ -!==(@nospecialize(x), @nospecialize(y)) = !(x === y) +!== + const ≢ = !== """ diff --git a/test/reflection.jl b/test/reflection.jl index ef940b034a2e1..634390e0680d1 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -686,7 +686,7 @@ let @test @inferred wrapperT(ReflectionExample{T, Int64} where T) == ReflectionExample @test @inferred wrapperT(ReflectionExample) == ReflectionExample @test @inferred wrapperT(Union{ReflectionExample{Union{},1},ReflectionExample{Float64,1}}) == ReflectionExample - @test_throws(ErrorException("typename does not apply to unions whose components have different typenames"), + @test_throws(Core.TypeNameError(Union{Int, Float64}), Base.typename(Union{Int, Float64})) end From b967cf0c20e09c21c5dc28eedca124d34750ea47 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 2 Aug 2024 16:09:54 +0000 Subject: [PATCH 121/206] LinearAlgebra: remove internal function _makevector (#55345) It seems a bit unnecessary to have a function to carry out a `convert`, instead of calling `convert` directly. --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 4 ---- stdlib/LinearAlgebra/src/bidiag.jl | 4 ++-- stdlib/LinearAlgebra/src/diagonal.jl | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index bad0431755e98..be59516f086ab 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -655,10 +655,6 @@ _evview(S::SymTridiagonal) = @view S.ev[begin:begin + length(S.dv) - 2] _zeros(::Type{T}, b::AbstractVector, n::Integer) where {T} = zeros(T, max(length(b), n)) _zeros(::Type{T}, B::AbstractMatrix, n::Integer) where {T} = zeros(T, max(size(B, 1), n), size(B, 2)) -# convert to Vector, if necessary -_makevector(x::Vector) = x -_makevector(x::AbstractVector) = Vector(x) - # append a zero element / drop the last element _pushzero(A) = (B = similar(A, length(A)+1); @inbounds B[begin:end-1] .= A; @inbounds B[end] = zero(eltype(B)); B) _droplast!(A) = deleteat!(A, lastindex(A)) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index ddfc6af60ef75..34ec92062ae01 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -252,8 +252,8 @@ tr(B::Bidiagonal) = sum(B.dv) function kron(A::Diagonal, B::Bidiagonal) # `_droplast!` is only guaranteed to work with `Vector` - kdv = _makevector(kron(diag(A), B.dv)) - kev = _droplast!(_makevector(kron(diag(A), _pushzero(B.ev)))) + kdv = convert(Vector, kron(diag(A), B.dv)) + kev = _droplast!(convert(Vector, kron(diag(A), _pushzero(B.ev)))) Bidiagonal(kdv, kev, B.uplo) end diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index ff8350d8ddeb1..8f643a0054719 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -684,9 +684,9 @@ function kron(A::Diagonal, B::SymTridiagonal) end function kron(A::Diagonal, B::Tridiagonal) # `_droplast!` is only guaranteed to work with `Vector` - kd = _makevector(kron(diag(A), B.d)) - kdl = _droplast!(_makevector(kron(diag(A), _pushzero(B.dl)))) - kdu = _droplast!(_makevector(kron(diag(A), _pushzero(B.du)))) + kd = convert(Vector, kron(diag(A), B.d)) + kdl = _droplast!(convert(Vector, kron(diag(A), _pushzero(B.dl)))) + kdu = _droplast!(convert(Vector, kron(diag(A), _pushzero(B.du)))) Tridiagonal(kdl, kd, kdu) end From 1dffd7752de2409b5f6c81fdcc1f33118127725e Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Fri, 2 Aug 2024 13:44:56 -0400 Subject: [PATCH 122/206] mapreduce: don't inbounds unknown functions (#55329) More finely scope the `@inbounds` annotations to ensure neither `f` nor `op` are erroneously `@inbounds`ed. --- base/reduce.jl | 10 +++++----- base/reducedim.jl | 37 +++++++++++++++++++------------------ test/reducedim.jl | 24 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index bbfd66e5686ed..0c37256b64fb5 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -638,11 +638,11 @@ function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, start = first + 1 simdstop = start + chunk_len - 4 while simdstop <= last - 3 - @inbounds for i in start:4:simdstop - v1 = _fast(op, v1, f(A[i+0])) - v2 = _fast(op, v2, f(A[i+1])) - v3 = _fast(op, v3, f(A[i+2])) - v4 = _fast(op, v4, f(A[i+3])) + for i in start:4:simdstop + v1 = _fast(op, v1, f(@inbounds(A[i+0]))) + v2 = _fast(op, v2, f(@inbounds(A[i+1]))) + v3 = _fast(op, v3, f(@inbounds(A[i+2]))) + v4 = _fast(op, v4, f(@inbounds(A[i+3]))) end checkbounds(A, simdstop+3) start += chunk_len diff --git a/base/reducedim.jl b/base/reducedim.jl index 4ab786804ff4c..e74fe2b765277 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -269,19 +269,20 @@ function _mapreducedim!(f, op, R::AbstractArray, A::AbstractArrayOrBroadcasted) if reducedim1(R, A) # keep the accumulator as a local variable when reducing along the first dimension i1 = first(axes1(R)) - @inbounds for IA in CartesianIndices(indsAt) + for IA in CartesianIndices(indsAt) IR = Broadcast.newindex(IA, keep, Idefault) - r = R[i1,IR] + @inbounds r = R[i1,IR] @simd for i in axes(A, 1) - r = op(r, f(A[i, IA])) + r = op(r, f(@inbounds(A[i, IA]))) end - R[i1,IR] = r + @inbounds R[i1,IR] = r end else - @inbounds for IA in CartesianIndices(indsAt) + for IA in CartesianIndices(indsAt) IR = Broadcast.newindex(IA, keep, Idefault) @simd for i in axes(A, 1) - R[i,IR] = op(R[i,IR], f(A[i,IA])) + v = op(@inbounds(R[i,IR]), f(@inbounds(A[i,IA]))) + @inbounds R[i,IR] = v end end end @@ -1025,33 +1026,33 @@ function findminmax!(f, op, Rval, Rind, A::AbstractArray{T,N}) where {T,N} zi = zero(eltype(ks)) if reducedim1(Rval, A) i1 = first(axes1(Rval)) - @inbounds for IA in CartesianIndices(indsAt) + for IA in CartesianIndices(indsAt) IR = Broadcast.newindex(IA, keep, Idefault) - tmpRv = Rval[i1,IR] - tmpRi = Rind[i1,IR] + @inbounds tmpRv = Rval[i1,IR] + @inbounds tmpRi = Rind[i1,IR] for i in axes(A,1) k, kss = y::Tuple - tmpAv = f(A[i,IA]) + tmpAv = f(@inbounds(A[i,IA])) if tmpRi == zi || op(tmpRv, tmpAv) tmpRv = tmpAv tmpRi = k end y = iterate(ks, kss) end - Rval[i1,IR] = tmpRv - Rind[i1,IR] = tmpRi + @inbounds Rval[i1,IR] = tmpRv + @inbounds Rind[i1,IR] = tmpRi end else - @inbounds for IA in CartesianIndices(indsAt) + for IA in CartesianIndices(indsAt) IR = Broadcast.newindex(IA, keep, Idefault) for i in axes(A, 1) k, kss = y::Tuple - tmpAv = f(A[i,IA]) - tmpRv = Rval[i,IR] - tmpRi = Rind[i,IR] + tmpAv = f(@inbounds(A[i,IA])) + @inbounds tmpRv = Rval[i,IR] + @inbounds tmpRi = Rind[i,IR] if tmpRi == zi || op(tmpRv, tmpAv) - Rval[i,IR] = tmpAv - Rind[i,IR] = k + @inbounds Rval[i,IR] = tmpAv + @inbounds Rind[i,IR] = k end y = iterate(ks, kss) end diff --git a/test/reducedim.jl b/test/reducedim.jl index 8f629fa83f28d..6a6f20214058c 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -587,6 +587,30 @@ end @test B[argmin(B, dims=[2, 3])] == @inferred(minimum(B, dims=[2, 3])) end +@testset "careful with @inbounds" begin + Base.@propagate_inbounds f(x) = x == 2 ? x[-10000] : x + Base.@propagate_inbounds op(x,y) = x[-10000] + y[-10000] + for (arr, dims) in (([1,1,2], 1), ([1 1 2], 2), ([ones(Int,256);2], 1)) + @test_throws BoundsError mapreduce(f, +, arr) + @test_throws BoundsError mapreduce(f, +, arr; dims) + @test_throws BoundsError mapreduce(f, +, arr; dims, init=0) + @test_throws BoundsError mapreduce(identity, op, arr) + try + #=@test_throws BoundsError=# mapreduce(identity, op, arr; dims) + catch ex + @test_broken ex isa BoundsError + end + @test_throws BoundsError mapreduce(identity, op, arr; dims, init=0) + + @test_throws BoundsError findmin(f, arr) + @test_throws BoundsError findmin(f, arr; dims) + + @test_throws BoundsError mapreduce(f, max, arr) + @test_throws BoundsError mapreduce(f, max, arr; dims) + @test_throws BoundsError mapreduce(f, max, arr; dims, init=0) + end +end + @testset "in-place reductions with mismatched dimensionalities" begin B = reshape(1:24, 4, 3, 2) for R in (fill(0, 4), fill(0, 4, 1), fill(0, 4, 1, 1)) From 05d0564769dfe506389ca811075b617c9df61701 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Fri, 2 Aug 2024 22:29:39 -0400 Subject: [PATCH 123/206] Profile: close files when assembling heap snapshot (#55356) --- stdlib/Profile/src/heapsnapshot_reassemble.jl | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/stdlib/Profile/src/heapsnapshot_reassemble.jl b/stdlib/Profile/src/heapsnapshot_reassemble.jl index 50da13e550d82..2413ae538b8ac 100644 --- a/stdlib/Profile/src/heapsnapshot_reassemble.jl +++ b/stdlib/Profile/src/heapsnapshot_reassemble.jl @@ -99,40 +99,42 @@ function assemble_snapshot(in_prefix, io::IO) orphans = Set{UInt}() # nodes that have no incoming edges # Parse nodes with empty edge counts that we need to fill later - nodes_file = open(string(in_prefix, ".nodes"), "r") - for i in 1:length(nodes) - node_type = read(nodes_file, Int8) - node_name_idx = read(nodes_file, UInt) - id = read(nodes_file, UInt) - self_size = read(nodes_file, Int) - @assert read(nodes_file, Int) == 0 # trace_node_id - @assert read(nodes_file, Int8) == 0 # detachedness - - nodes.type[i] = node_type - nodes.name_idx[i] = node_name_idx - nodes.id[i] = id - nodes.self_size[i] = self_size - nodes.edge_count[i] = 0 # edge_count - # populate the orphans set with node index - push!(orphans, i-1) + open(string(in_prefix, ".nodes"), "r") do nodes_file + for i in 1:length(nodes) + node_type = read(nodes_file, Int8) + node_name_idx = read(nodes_file, UInt) + id = read(nodes_file, UInt) + self_size = read(nodes_file, Int) + @assert read(nodes_file, Int) == 0 # trace_node_id + @assert read(nodes_file, Int8) == 0 # detachedness + + nodes.type[i] = node_type + nodes.name_idx[i] = node_name_idx + nodes.id[i] = id + nodes.self_size[i] = self_size + nodes.edge_count[i] = 0 # edge_count + # populate the orphans set with node index + push!(orphans, i-1) + end end # Parse the edges to fill in the edge counts for nodes and correct the to_node offsets - edges_file = open(string(in_prefix, ".edges"), "r") - for i in 1:length(nodes.edges) - edge_type = read(edges_file, Int8) - edge_name_or_index = read(edges_file, UInt) - from_node = read(edges_file, UInt) - to_node = read(edges_file, UInt) - - nodes.edges.type[i] = edge_type - nodes.edges.name_or_index[i] = edge_name_or_index - nodes.edges.to_pos[i] = to_node * k_node_number_of_fields # 7 fields per node, the streaming format doesn't multiply the offset by 7 - nodes.edge_count[from_node + 1] += UInt32(1) # C and JSON use 0-based indexing - push!(nodes.edge_idxs[from_node + 1], i) # Index into nodes.edges - # remove the node from the orphans if it has at least one incoming edge - if to_node in orphans - delete!(orphans, to_node) + open(string(in_prefix, ".edges"), "r") do edges_file + for i in 1:length(nodes.edges) + edge_type = read(edges_file, Int8) + edge_name_or_index = read(edges_file, UInt) + from_node = read(edges_file, UInt) + to_node = read(edges_file, UInt) + + nodes.edges.type[i] = edge_type + nodes.edges.name_or_index[i] = edge_name_or_index + nodes.edges.to_pos[i] = to_node * k_node_number_of_fields # 7 fields per node, the streaming format doesn't multiply the offset by 7 + nodes.edge_count[from_node + 1] += UInt32(1) # C and JSON use 0-based indexing + push!(nodes.edge_idxs[from_node + 1], i) # Index into nodes.edges + # remove the node from the orphans if it has at least one incoming edge + if to_node in orphans + delete!(orphans, to_node) + end end end From 124e0a73043aef35d073a0da83be2d5a107a12ed Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 3 Aug 2024 12:01:14 +0000 Subject: [PATCH 124/206] Condense branches in Bidiagonal indexing (#55343) --- stdlib/LinearAlgebra/src/bidiag.jl | 40 +++++++++++------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 34ec92062ae01..55d3c2d5a889a 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -130,14 +130,14 @@ function bidiagzero(A::Bidiagonal{<:AbstractMatrix}, i, j) end end +_offdiagind(uplo) = uplo == 'U' ? 1 : -1 + @inline function Base.isassigned(A::Bidiagonal, i::Int, j::Int) @boundscheck checkbounds(Bool, A, i, j) || return false if i == j return @inbounds isassigned(A.dv, i) - elseif A.uplo == 'U' && (i == j - 1) - return @inbounds isassigned(A.ev, i) - elseif A.uplo == 'L' && (i == j + 1) - return @inbounds isassigned(A.ev, j) + elseif i == j - _offdiagind(A.uplo) + return @inbounds isassigned(A.ev, A.uplo == 'U' ? i : j) else return true end @@ -147,10 +147,8 @@ end @boundscheck checkbounds(A, i, j) if i == j return @inbounds Base.isstored(A.dv, i) - elseif A.uplo == 'U' && (i == j - 1) - return @inbounds Base.isstored(A.ev, i) - elseif A.uplo == 'L' && (i == j + 1) - return @inbounds Base.isstored(A.ev, j) + elseif i == j - _offdiagind(A.uplo) + return @inbounds Base.isstored(A.ev, A.uplo == 'U' ? i : j) else return false end @@ -160,10 +158,8 @@ end @boundscheck checkbounds(A, i, j) if i == j return @inbounds A.dv[i] - elseif A.uplo == 'U' && (i == j - 1) - return @inbounds A.ev[i] - elseif A.uplo == 'L' && (i == j + 1) - return @inbounds A.ev[j] + elseif i == j - _offdiagind(A.uplo) + return @inbounds A.ev[A.uplo == 'U' ? i : j] else return bidiagzero(A, i, j) end @@ -173,9 +169,7 @@ end @boundscheck checkbounds(A, _cartinds(b)) if b.band == 0 return @inbounds A.dv[b.index] - elseif A.uplo == 'U' && b.band == 1 - return @inbounds A.ev[b.index] - elseif A.uplo == 'L' && b.band == -1 + elseif b.band == _offdiagind(A.uplo) return @inbounds A.ev[b.index] else return bidiagzero(A, Tuple(_cartinds(b))...) @@ -186,10 +180,8 @@ end @boundscheck checkbounds(A, i, j) if i == j @inbounds A.dv[i] = x - elseif A.uplo == 'U' && (i == j - 1) - @inbounds A.ev[i] = x - elseif A.uplo == 'L' && (i == j + 1) - @inbounds A.ev[j] = x + elseif i == j - _offdiagind(A.uplo) + @inbounds A.ev[A.uplo == 'U' ? i : j] = x elseif !iszero(x) throw(ArgumentError(LazyString(lazy"cannot set entry ($i, $j) off the ", istriu(A) ? "upper" : "lower", " bidiagonal band to a nonzero value ", x))) @@ -202,11 +194,7 @@ Base._reverse(A::Bidiagonal, ::Colon) = Bidiagonal(reverse(A.dv), reverse(A.ev), ## structured matrix methods ## function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::AbstractString) - if A.uplo == 'U' - i==j || i==j-1 ? s : Base.replace_with_centered_mark(s) - else - i==j || i==j+1 ? s : Base.replace_with_centered_mark(s) - end + i==j || i==j-_offdiagind(A.uplo) ? s : Base.replace_with_centered_mark(s) end #Converting from Bidiagonal to dense Matrix @@ -215,7 +203,7 @@ function Matrix{T}(A::Bidiagonal) where T if haszero(T) # optimized path for types with zero(T) defined size(B,1) > 1 && fill!(B, zero(T)) copyto!(view(B, diagind(B)), A.dv) - copyto!(view(B, diagind(B, A.uplo == 'U' ? 1 : -1)), A.ev) + copyto!(view(B, diagind(B, _offdiagind(A.uplo))), A.ev) else copyto!(B, A) end @@ -558,7 +546,7 @@ _diag(A::SymTridiagonal, k) = k == 0 ? A.dv : A.ev function _diag(A::Bidiagonal, k) if k == 0 return A.dv - elseif (A.uplo == 'L' && k == -1) || (A.uplo == 'U' && k == 1) + elseif k == _offdiagind(A.uplo) return A.ev else return diag(A, k) From a1714caa896066081de939b900e3571429d815e6 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 3 Aug 2024 12:01:29 +0000 Subject: [PATCH 125/206] Check only for Hermitian and not Symmetric in matrix exponentiation (#55349) For real matrices, a `Hermitian` eigenvalue problem would be equivalent to a `Symmetric` one, and for complex matrices, there is no special complex symmetric eigensolver (it errors at present, and complex symmetric matrices might not be diagonalizable). I think the `ishermitian` branch should suffice here. Removing the symmetric branch makes the return type simpler to infer. --- stdlib/LinearAlgebra/src/dense.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index c441e8e658ac8..94a075ffaf24d 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -565,9 +565,6 @@ function (^)(A::AbstractMatrix{T}, p::Real) where T isinteger(p) && return integerpow(A, p) # If possible, use diagonalization - if issymmetric(A) - return (Symmetric(A)^p) - end if ishermitian(A) return (Hermitian(A)^p) end From 3d99c24461d0cf9aac575bd6e6e90ddd32d8099b Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Sat, 3 Aug 2024 13:29:51 +0100 Subject: [PATCH 126/206] Create `Base.Fix` as general `Fix1`/`Fix2` for partially-applied functions (#54653) This PR generalises `Base.Fix1` and `Base.Fix2` to `Base.Fix{N}`, to allow fixing a single positional argument of a function. With this change, the implementation of these is simply ```julia const Fix1{F,T} = Fix{1,F,T} const Fix2{F,T} = Fix{2,F,T} ``` Along with the PR I also add a larger suite of unittests for all three of these functions to complement the existing tests for `Fix1`/`Fix2`. ### Context There are multiple motivations for this generalization. **By creating a more general `Fix{N}` type, there is no preferential treatment of certain types of functions:** - (i) No limitation that you can only fix positions 1-2. You can now fix any position `n`. - (ii) No asymmetry between 2-argument and n-argument functions. You can now fix an argument for functions with any number of arguments. Think of this like if `Base` only had `Vector{T}` and `Matrix{T}`, and you wished to generalise it to `Array{T,N}`. It is an analogous situation here: `Fix1` and `Fix2` are now *aliases* of `Fix{N}`. - **Convenience**: - `Base.Fix1` and `Base.Fix2` are useful shorthands for creating simple anonymous functions without compiling new functions. - They are common throughout the Julia ecosystem as a shorthand for filling arguments: - `Fix1` https://github.com/search?q=Base.Fix1+language%3Ajulia&type=code - `Fix2` https://github.com/search?q=Base.Fix2+language%3Ajulia&type=code - **Less Compilation**: - Using `Fix*` reduces the need for compilation of repeatedly-used anonymous functions (which can often trigger compilation of new functions). - **Type Stability**: - `Fix`, like `Fix1` and `Fix2`, captures variables in a struct, encouraging users to use a functional paradigm for closures, preventing any potential type instabilities from boxed variables within an anonymous function. - **Easier Functional Programming**: - Allows for a stronger functional programming paradigm by supporting partial functions with _any number of arguments_. Note that this refactors `Fix1` and `Fix2` to be equal to `Fix{1}` and `Fix{2}` respectively, rather than separate structs. This is backwards compatible. Also note that this does not constrain future generalisations of `Fix{n}` for multiple arguments. `Fix{1,F,T}` is the clear generalisation of `Fix1{F,T}`, so this isn't major new syntax choices. But in a future PR you could have, e.g., `Fix{(n1,n2)}` for multiple arguments, and it would still be backwards-compatible with this. --------- Co-authored-by: Dilum Aluthge Co-authored-by: Lilith Orion Hafner Co-authored-by: Alexander Plavin Co-authored-by: Neven Sajko --- NEWS.md | 1 + base/operators.jl | 57 +++++++++++------- base/public.jl | 1 + doc/src/base/base.md | 1 + stdlib/REPL/test/repl.jl | 4 +- test/functional.jl | 126 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 23 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6f12b8ff389cd..2e9b32befe342 100644 --- a/NEWS.md +++ b/NEWS.md @@ -73,6 +73,7 @@ New library functions * `waitany(tasks; throw=false)` and `waitall(tasks; failfast=false, throw=false)` which wait multiple tasks at once ([#53341]). * `uuid7()` creates an RFC 9652 compliant UUID with version 7 ([#54834]). * `insertdims(array; dims)` allows to insert singleton dimensions into an array which is the inverse operation to `dropdims` +* The new `Fix` type is a generalization of `Fix1/Fix2` for fixing a single argument ([#54653]). New library features -------------------- diff --git a/base/operators.jl b/base/operators.jl index b7605ba004b7a..2c8070b44d704 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1154,40 +1154,55 @@ julia> filter(!isletter, str) !(f::ComposedFunction{typeof(!)}) = f.inner #allows !!f === f """ - Fix1(f, x) + Fix{N}(f, x) -A type representing a partially-applied version of the two-argument function -`f`, with the first argument fixed to the value "x". In other words, -`Fix1(f, x)` behaves similarly to `y->f(x, y)`. +A type representing a partially-applied version of a function `f`, with the argument +`x` fixed at position `N::Int`. In other words, `Fix{3}(f, x)` behaves similarly to +`(y1, y2, y3...; kws...) -> f(y1, y2, x, y3...; kws...)`. -See also [`Fix2`](@ref Base.Fix2). +!!! compat "Julia 1.12" + This general functionality requires at least Julia 1.12, while `Fix1` and `Fix2` + are available earlier. + +!!! note + When nesting multiple `Fix`, note that the `N` in `Fix{N}` is _relative_ to the current + available arguments, rather than an absolute ordering on the target function. For example, + `Fix{1}(Fix{2}(f, 4), 4)` fixes the first and second arg, while `Fix{2}(Fix{1}(f, 4), 4)` + fixes the first and third arg. """ -struct Fix1{F,T} <: Function +struct Fix{N,F,T} <: Function f::F x::T - Fix1(f::F, x) where {F} = new{F,_stable_typeof(x)}(f, x) - Fix1(f::Type{F}, x) where {F} = new{Type{F},_stable_typeof(x)}(f, x) + function Fix{N}(f::F, x) where {N,F} + if !(N isa Int) + throw(ArgumentError(LazyString("expected type parameter in `Fix` to be `Int`, but got `", N, "::", typeof(N), "`"))) + elseif N < 1 + throw(ArgumentError(LazyString("expected `N` in `Fix{N}` to be integer greater than 0, but got ", N))) + end + new{N,_stable_typeof(f),_stable_typeof(x)}(f, x) + end end -(f::Fix1)(y) = f.f(f.x, y) +function (f::Fix{N})(args::Vararg{Any,M}; kws...) where {N,M} + M < N-1 && throw(ArgumentError(LazyString("expected at least ", N-1, " arguments to `Fix{", N, "}`, but got ", M))) + return f.f(args[begin:begin+(N-2)]..., f.x, args[begin+(N-1):end]...; kws...) +end -""" - Fix2(f, x) +# Special cases for improved constant propagation +(f::Fix{1})(arg; kws...) = f.f(f.x, arg; kws...) +(f::Fix{2})(arg; kws...) = f.f(arg, f.x; kws...) -A type representing a partially-applied version of the two-argument function -`f`, with the second argument fixed to the value "x". In other words, -`Fix2(f, x)` behaves similarly to `y->f(y, x)`. """ -struct Fix2{F,T} <: Function - f::F - x::T +Alias for `Fix{1}`. See [`Fix`](@ref Base.Fix). +""" +const Fix1{F,T} = Fix{1,F,T} - Fix2(f::F, x) where {F} = new{F,_stable_typeof(x)}(f, x) - Fix2(f::Type{F}, x) where {F} = new{Type{F},_stable_typeof(x)}(f, x) -end +""" +Alias for `Fix{2}`. See [`Fix`](@ref Base.Fix). +""" +const Fix2{F,T} = Fix{2,F,T} -(f::Fix2)(y) = f.f(y, f.x) """ isequal(x) diff --git a/base/public.jl b/base/public.jl index c11c76c13053c..862aff48da63e 100644 --- a/base/public.jl +++ b/base/public.jl @@ -14,6 +14,7 @@ public AsyncCondition, CodeUnits, Event, + Fix, Fix1, Fix2, Generator, diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 946f917682814..1a8cd29f91066 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -281,6 +281,7 @@ Base.:(|>) Base.:(∘) Base.ComposedFunction Base.splat +Base.Fix Base.Fix1 Base.Fix2 ``` diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 05db88fa0d8ac..6f0c4a5c3d6ba 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -1216,9 +1216,9 @@ global some_undef_global @test occursin("does not exist", sprint(show, help_result(".."))) # test that helpmode is sensitive to contextual module @test occursin("No documentation found", sprint(show, help_result("Fix2", Main))) -@test occursin("A type representing a partially-applied version", # exact string may change +@test occursin("Alias for `Fix{2}`. See [`Fix`](@ref Base.Fix).", # exact string may change sprint(show, help_result("Base.Fix2", Main))) -@test occursin("A type representing a partially-applied version", # exact string may change +@test occursin("Alias for `Fix{2}`. See [`Fix`](@ref Base.Fix).", # exact string may change sprint(show, help_result("Fix2", Base))) diff --git a/test/functional.jl b/test/functional.jl index 3436fb8911cc1..84c4098308ebd 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -235,3 +235,129 @@ end let (:)(a,b) = (i for i in Base.:(:)(1,10) if i%2==0) @test Int8[ i for i = 1:2 ] == [2,4,6,8,10] end + +@testset "Basic tests of Fix1, Fix2, and Fix" begin + function test_fix1(Fix1=Base.Fix1) + increment = Fix1(+, 1) + @test increment(5) == 6 + @test increment(-1) == 0 + @test increment(0) == 1 + @test map(increment, [1, 2, 3]) == [2, 3, 4] + + concat_with_hello = Fix1(*, "Hello ") + @test concat_with_hello("World!") == "Hello World!" + # Make sure inference is good: + @inferred concat_with_hello("World!") + + one_divided_by = Fix1(/, 1) + @test one_divided_by(10) == 1/10.0 + @test one_divided_by(-5) == 1/-5.0 + + return nothing + end + + function test_fix2(Fix2=Base.Fix2) + return_second = Fix2((x, y) -> y, 999) + @test return_second(10) == 999 + @inferred return_second(10) + @test return_second(-5) == 999 + + divide_by_two = Fix2(/, 2) + @test map(divide_by_two, (2, 4, 6)) == (1.0, 2.0, 3.0) + @inferred map(divide_by_two, (2, 4, 6)) + + concat_with_world = Fix2(*, " World!") + @test concat_with_world("Hello") == "Hello World!" + @inferred concat_with_world("Hello World!") + + return nothing + end + + # Test with normal Base.Fix1 and Base.Fix2 + test_fix1() + test_fix2() + + # Now, repeat the Fix1 and Fix2 tests, but + # with a Fix lambda function used in their place + test_fix1((op, arg) -> Base.Fix{1}(op, arg)) + test_fix2((op, arg) -> Base.Fix{2}(op, arg)) + + # Now, we do more complex tests of Fix: + let Fix=Base.Fix + @testset "Argument Fixation" begin + let f = (x, y, z) -> x + y * z + fixed_f1 = Fix{1}(f, 10) + @test fixed_f1(2, 3) == 10 + 2 * 3 + + fixed_f2 = Fix{2}(f, 5) + @test fixed_f2(1, 4) == 1 + 5 * 4 + + fixed_f3 = Fix{3}(f, 3) + @test fixed_f3(1, 2) == 1 + 2 * 3 + end + end + @testset "Helpful errors" begin + let g = (x, y) -> x - y + # Test minimum N + fixed_g1 = Fix{1}(g, 100) + @test fixed_g1(40) == 100 - 40 + + # Test maximum N + fixed_g2 = Fix{2}(g, 100) + @test fixed_g2(150) == 150 - 100 + + # One over + fixed_g3 = Fix{3}(g, 100) + @test_throws ArgumentError("expected at least 2 arguments to `Fix{3}`, but got 1") fixed_g3(1) + end + end + @testset "Type Stability and Inference" begin + let h = (x, y) -> x / y + fixed_h = Fix{2}(h, 2.0) + @test @inferred(fixed_h(4.0)) == 2.0 + end + end + @testset "Interaction with varargs" begin + vararg_f = (x, y, z...) -> x + 10 * y + sum(z; init=zero(x)) + fixed_vararg_f = Fix{2}(vararg_f, 6) + + # Can call with variable number of arguments: + @test fixed_vararg_f(1, 2, 3, 4) == 1 + 10 * 6 + sum((2, 3, 4)) + @inferred fixed_vararg_f(1, 2, 3, 4) + @test fixed_vararg_f(5) == 5 + 10 * 6 + @inferred fixed_vararg_f(5) + end + @testset "Errors should propagate normally" begin + error_f = (x, y) -> sin(x * y) + fixed_error_f = Fix{2}(error_f, Inf) + @test_throws DomainError fixed_error_f(10) + end + @testset "Chaining Fix together" begin + f1 = Fix{1}(*, "1") + f2 = Fix{1}(f1, "2") + f3 = Fix{1}(f2, "3") + @test f3() == "123" + + g1 = Fix{2}(*, "1") + g2 = Fix{2}(g1, "2") + g3 = Fix{2}(g2, "3") + @test g3("") == "123" + end + @testset "Zero arguments" begin + f = Fix{1}(x -> x, 'a') + @test f() == 'a' + end + @testset "Dummy-proofing" begin + @test_throws ArgumentError("expected `N` in `Fix{N}` to be integer greater than 0, but got 0") Fix{0}(>, 1) + @test_throws ArgumentError("expected type parameter in `Fix` to be `Int`, but got `0.5::Float64`") Fix{0.5}(>, 1) + @test_throws ArgumentError("expected type parameter in `Fix` to be `Int`, but got `1::UInt64`") Fix{UInt64(1)}(>, 1) + end + @testset "Specialize to structs not in `Base`" begin + struct MyStruct + x::Int + end + f = Fix{1}(MyStruct, 1) + @test f isa Fix{1,Type{MyStruct},Int} + end + end +end From f2f188d57346a0163b82740ac0a758311c41004f Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 3 Aug 2024 14:27:59 +0000 Subject: [PATCH 127/206] Ensure bidiagonal setindex! does not read indices in error message (#55342) This fixes the error message if the matrix is uninitialized. This is because a `Bidiagonal` with `uplo == 'L'` may still be `istriu` if the subdiaognal is zero. We only care about the band index in the error message, and not the values. --- stdlib/LinearAlgebra/src/bidiag.jl | 2 +- stdlib/LinearAlgebra/test/bidiag.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 55d3c2d5a889a..5f9a64904bd38 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -184,7 +184,7 @@ end @inbounds A.ev[A.uplo == 'U' ? i : j] = x elseif !iszero(x) throw(ArgumentError(LazyString(lazy"cannot set entry ($i, $j) off the ", - istriu(A) ? "upper" : "lower", " bidiagonal band to a nonzero value ", x))) + A.uplo == 'U' ? "upper" : "lower", " bidiagonal band to a nonzero value ", x))) end return x end diff --git a/stdlib/LinearAlgebra/test/bidiag.jl b/stdlib/LinearAlgebra/test/bidiag.jl index 2ff3e9b423702..37503efe42518 100644 --- a/stdlib/LinearAlgebra/test/bidiag.jl +++ b/stdlib/LinearAlgebra/test/bidiag.jl @@ -984,4 +984,9 @@ end @test Tridiagonal{Float64}(B) === Tridiagonal(evf, dvf, zf) end +@testset "off-band indexing error" begin + B = Bidiagonal(Vector{BigInt}(undef, 4), Vector{BigInt}(undef,3), :L) + @test_throws "cannot set entry" B[1,2] = 4 +end + end # module TestBidiagonal From f38015f470a5fe323cfc71f711f11677dcc80599 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 3 Aug 2024 11:39:59 -0400 Subject: [PATCH 128/206] codegen: NFC refactoring to use Align type --- src/ccall.cpp | 10 +++++----- src/cgutils.cpp | 41 ++++++++++++++++++++--------------------- src/codegen.cpp | 17 ++++++++++------- src/intrinsics.cpp | 12 ++++++------ 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 3c2857608c163..d913ed4e27e7d 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -554,8 +554,8 @@ static Value *julia_to_native( // pass the address of an alloca'd thing, not a box // since those are immutable. Value *slot = emit_static_alloca(ctx, to); - unsigned align = julia_alignment(jlto); - cast(slot)->setAlignment(Align(align)); + Align align(julia_alignment(jlto)); + cast(slot)->setAlignment(align); setName(ctx.emission_context, slot, "native_convert_buffer"); if (!jvinfo.ispointer()) { jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, jvinfo.tbaa); @@ -2230,7 +2230,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( Value *strct = emit_allocobj(ctx, (jl_datatype_t*)rt, true); setName(ctx.emission_context, strct, "ccall_ret_box"); MDNode *tbaa = jl_is_mutable(rt) ? ctx.tbaa().tbaa_mutab : ctx.tbaa().tbaa_immut; - int boxalign = julia_alignment(rt); + Align boxalign(julia_alignment(rt)); // copy the data from the return value to the new struct const DataLayout &DL = ctx.builder.GetInsertBlock()->getModule()->getDataLayout(); auto resultTy = result->getType(); @@ -2240,8 +2240,8 @@ jl_cgval_t function_sig_t::emit_a_ccall( // When this happens, cast through memory. auto slot = emit_static_alloca(ctx, resultTy); setName(ctx.emission_context, slot, "type_pun_slot"); - slot->setAlignment(Align(boxalign)); - ctx.builder.CreateAlignedStore(result, slot, Align(boxalign)); + slot->setAlignment(boxalign); + ctx.builder.CreateAlignedStore(result, slot, boxalign); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); emit_memcpy(ctx, strct, ai, slot, ai, rtsz, boxalign, boxalign); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 613d7ae719448..297fcb164b112 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -315,7 +315,7 @@ static Value *emit_pointer_from_objref(jl_codectx_t &ctx, Value *V) } static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_value_t *jt); -static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value* dest, MDNode *tbaa_dest, unsigned alignment, bool isVolatile=false); +static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value* dest, MDNode *tbaa_dest, Align alignment, bool isVolatile=false); static bool type_is_permalloc(jl_value_t *typ) { @@ -1006,11 +1006,10 @@ static Value *data_pointer(jl_codectx_t &ctx, const jl_cgval_t &x) } static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, - jl_aliasinfo_t const &src_ai, uint64_t sz, unsigned align_dst, unsigned align_src, bool is_volatile) + jl_aliasinfo_t const &src_ai, uint64_t sz, Align align_dst, Align align_src, bool is_volatile) { if (sz == 0) return; - assert(align_dst && "align must be specified"); #if JL_LLVM_VERSION < 170000 // If the types are small and simple, use load and store directly. // Going through memcpy can cause LLVM (e.g. SROA) to create bitcasts between float and int @@ -1053,7 +1052,7 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const if (isa(dst) && !dst->hasName()) setName(ctx.emission_context, dst, "memcpy_refined_dst"); auto val = src_ai.decorateInst(ctx.builder.CreateAlignedLoad(directel, src, MaybeAlign(align_src), is_volatile)); - dst_ai.decorateInst(ctx.builder.CreateAlignedStore(val, dst, Align(align_dst), is_volatile)); + dst_ai.decorateInst(ctx.builder.CreateAlignedStore(val, dst, align_dst, is_volatile)); ++SkippedMemcpys; return; } @@ -1072,12 +1071,12 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const // above problem won't be as serious. auto merged_ai = dst_ai.merge(src_ai); - ctx.builder.CreateMemCpy(dst, Align(align_dst), src, Align(align_src), sz, is_volatile, + ctx.builder.CreateMemCpy(dst, align_dst, src, align_src, sz, is_volatile, merged_ai.tbaa, merged_ai.tbaa_struct, merged_ai.scope, merged_ai.noalias); } static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, - jl_aliasinfo_t const &src_ai, Value *sz, unsigned align_dst, unsigned align_src, bool is_volatile) + jl_aliasinfo_t const &src_ai, Value *sz, Align align_dst, Align align_src, bool is_volatile) { if (auto const_sz = dyn_cast(sz)) { emit_memcpy_llvm(ctx, dst, dst_ai, src, src_ai, const_sz->getZExtValue(), align_dst, align_src, is_volatile); @@ -1086,20 +1085,20 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const ++EmittedMemcpys; auto merged_ai = dst_ai.merge(src_ai); - ctx.builder.CreateMemCpy(dst, MaybeAlign(align_dst), src, MaybeAlign(align_src), sz, is_volatile, + ctx.builder.CreateMemCpy(dst, align_dst, src, align_src, sz, is_volatile, merged_ai.tbaa, merged_ai.tbaa_struct, merged_ai.scope, merged_ai.noalias); } template static void emit_memcpy(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, - jl_aliasinfo_t const &src_ai, T1 &&sz, unsigned align_dst, unsigned align_src, bool is_volatile=false) + jl_aliasinfo_t const &src_ai, T1 &&sz, Align align_dst, Align align_src, bool is_volatile=false) { emit_memcpy_llvm(ctx, dst, dst_ai, src, src_ai, sz, align_dst, align_src, is_volatile); } template static void emit_memcpy(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, const jl_cgval_t &src, - T1 &&sz, unsigned align_dst, unsigned align_src, bool is_volatile=false) + T1 &&sz, Align align_dst, Align align_src, bool is_volatile=false) { auto src_ai = jl_aliasinfo_t::fromTBAA(ctx, src.tbaa); emit_memcpy_llvm(ctx, dst, dst_ai, data_pointer(ctx, src), src_ai, sz, align_dst, align_src, is_volatile); @@ -1999,7 +1998,7 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j else if (!alignment) alignment = julia_alignment(jltype); if (intcast && Order == AtomicOrdering::NotAtomic) { - emit_memcpy(ctx, intcast, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), data, jl_aliasinfo_t::fromTBAA(ctx, tbaa), nb, alignment, intcast->getAlign().value()); + emit_memcpy(ctx, intcast, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), data, jl_aliasinfo_t::fromTBAA(ctx, tbaa), nb, Align(alignment), intcast->getAlign()); } else { if (!isboxed && jl_is_genericmemoryref_type(jltype)) { @@ -2176,7 +2175,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, } else { assert(Order == AtomicOrdering::NotAtomic && !isboxed && rhs.typ == jltype); - emit_unbox_store(ctx, rhs, ptr, tbaa, alignment); + emit_unbox_store(ctx, rhs, ptr, tbaa, Align(alignment)); } } else if (isswapfield) { @@ -2329,7 +2328,7 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, } else { assert(!isboxed && rhs.typ == jltype); - emit_unbox_store(ctx, rhs, ptr, tbaa, alignment); + emit_unbox_store(ctx, rhs, ptr, tbaa, Align(alignment)); } ctx.builder.CreateBr(DoneBB); instr = load; @@ -2668,7 +2667,7 @@ static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex, if (al > 1) lv->setAlignment(Align(al)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); - emit_memcpy(ctx, lv, ai, addr, ai, fsz, al, al); + emit_memcpy(ctx, lv, ai, addr, ai, fsz, Align(al), Align(al)); addr = lv; } return mark_julia_slot(fsz > 0 ? addr : nullptr, jfty, tindex, tbaa); @@ -3104,11 +3103,11 @@ static Value *emit_genericmemoryowner(jl_codectx_t &ctx, Value *t) static Value *emit_allocobj(jl_codectx_t &ctx, jl_datatype_t *jt, bool fully_initialized); static void init_bits_value(jl_codectx_t &ctx, Value *newv, Value *v, MDNode *tbaa, - unsigned alignment = sizeof(void*)) // min alignment in julia's gc is pointer-aligned + Align alignment = Align(sizeof(void*))) // min alignment in julia's gc is pointer-aligned { jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); // newv should already be tagged - ai.decorateInst(ctx.builder.CreateAlignedStore(v, newv, Align(alignment))); + ai.decorateInst(ctx.builder.CreateAlignedStore(v, newv, alignment)); } static void init_bits_cgval(jl_codectx_t &ctx, Value *newv, const jl_cgval_t& v, MDNode *tbaa) @@ -3116,7 +3115,7 @@ static void init_bits_cgval(jl_codectx_t &ctx, Value *newv, const jl_cgval_t& v, // newv should already be tagged if (v.ispointer()) { unsigned align = std::max(julia_alignment(v.typ), (unsigned)sizeof(void*)); - emit_memcpy(ctx, newv, jl_aliasinfo_t::fromTBAA(ctx, tbaa), v, jl_datatype_size(v.typ), align, julia_alignment(v.typ)); + emit_memcpy(ctx, newv, jl_aliasinfo_t::fromTBAA(ctx, tbaa), v, jl_datatype_size(v.typ), Align(align), Align(julia_alignment(v.typ))); } else { init_bits_value(ctx, newv, v.V, tbaa); @@ -3582,7 +3581,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con if (jl_is_pointerfree(typ)) { unsigned alignment = julia_alignment(typ); if (!src.ispointer() || src.constant) { - emit_unbox_store(ctx, src, dest, tbaa_dst, alignment, isVolatile); + emit_unbox_store(ctx, src, dest, tbaa_dst, Align(alignment), isVolatile); } else { Value *src_ptr = data_pointer(ctx, src); @@ -3592,7 +3591,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con // if (skip) src_ptr = ctx.builder.CreateSelect(skip, dest, src_ptr); auto f = [&] { (void)emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src_ptr, - jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, alignment, alignment, isVolatile); + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, Align(alignment), Align(alignment), isVolatile); return nullptr; }; if (skip) @@ -3627,7 +3626,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con return; } else { emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src_ptr, - jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, alignment, alignment, isVolatile); + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, Align(alignment), Align(alignment), isVolatile); } } ctx.builder.CreateBr(postBB); @@ -3653,7 +3652,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con Value *datatype = emit_typeof(ctx, src, false, false); Value *copy_bytes = emit_datatype_size(ctx, datatype); (void)emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), data_pointer(ctx, src), - jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), copy_bytes, 1, 1, isVolatile); + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), copy_bytes, Align(1), Align(1), isVolatile); return nullptr; }; if (skip) @@ -4046,7 +4045,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg } else if (init_as_value) { fval = emit_unbox(ctx, fty, fval_info, jtype); } else { - emit_unbox_store(ctx, fval_info, dest, ctx.tbaa().tbaa_stack, jl_field_align(sty, i)); + emit_unbox_store(ctx, fval_info, dest, ctx.tbaa().tbaa_stack, Align(jl_field_align(sty, i))); } } if (init_as_value) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 875beb7c287dc..d8d7a1fd23814 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5652,7 +5652,7 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va else { const DataLayout &DL = jl_Module->getDataLayout(); uint64_t sz = DL.getTypeStoreSize(T); - emit_memcpy(ctx, ssaslot, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), vi.value, sz, ssaslot->getAlign().value(), varslot->getAlign().value()); + emit_memcpy(ctx, ssaslot, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), vi.value, sz, ssaslot->getAlign(), varslot->getAlign()); } Value *tindex = NULL; if (vi.pTIndex) @@ -5756,8 +5756,9 @@ static void emit_vi_assignment_unboxed(jl_codectx_t &ctx, jl_varinfo_t &vi, Valu // This check should probably mostly catch the relevant situations. if (vi.value.V != rval_info.V) { Value *copy_bytes = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_datatype_size(vi.value.typ)); + Align alignment(julia_alignment(rval_info.typ)); emit_memcpy(ctx, vi.value.V, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), rval_info, copy_bytes, - julia_alignment(rval_info.typ), julia_alignment(rval_info.typ), vi.isVolatile); + alignment, alignment, vi.isVolatile); } } else { @@ -6868,8 +6869,9 @@ static void emit_cfunc_invalidate( root1 = ctx.builder.CreateConstInBoundsGEP2_32(get_returnroots_type(ctx, return_roots), root1, 0, 0); ctx.builder.CreateStore(gf_ret, root1); } + Align alignment(julia_alignment(rettype)); emit_memcpy(ctx, &*gf_thunk->arg_begin(), jl_aliasinfo_t::fromTBAA(ctx, nullptr), gf_ret, - jl_aliasinfo_t::fromTBAA(ctx, nullptr), jl_datatype_size(rettype), julia_alignment(rettype), julia_alignment(rettype)); + jl_aliasinfo_t::fromTBAA(ctx, nullptr), jl_datatype_size(rettype), Align(alignment), Align(alignment)); ctx.builder.CreateRetVoid(); break; } @@ -8729,7 +8731,7 @@ static jl_llvm_functions_t jl_cgval_t closure_world = typed_load(ctx, worldaddr, NULL, (jl_value_t*)jl_long_type, nullptr, nullptr, false, AtomicOrdering::NotAtomic, false, ctx.types().alignof_ptr.value()); ctx.world_age_at_entry = closure_world.V; // The tls world in a OC is the world of the closure - emit_unbox_store(ctx, closure_world, world_age_field, ctx.tbaa().tbaa_gcframe, ctx.types().alignof_ptr.value()); + emit_unbox_store(ctx, closure_world, world_age_field, ctx.tbaa().tbaa_gcframe, ctx.types().alignof_ptr); // Load closure env Value *envaddr = ctx.builder.CreateInBoundsGEP( @@ -9272,8 +9274,9 @@ static jl_llvm_functions_t } if (returninfo.cc == jl_returninfo_t::SRet) { assert(jl_is_concrete_type(jlrettype)); + Align alignment(julia_alignment(jlrettype)); emit_memcpy(ctx, sret, jl_aliasinfo_t::fromTBAA(ctx, nullptr), retvalinfo, - jl_datatype_size(jlrettype), julia_alignment(jlrettype), julia_alignment(jlrettype)); + jl_datatype_size(jlrettype), alignment, alignment); } else { // must be jl_returninfo_t::Union emit_unionmove(ctx, sret, nullptr, retvalinfo, /*skip*/isboxed_union); @@ -9511,7 +9514,7 @@ static jl_llvm_functions_t // load of val) if the runtime type of val isn't phiType Value *isvalid = emit_isa_and_defined(ctx, val, phiType); emit_guarded_test(ctx, isvalid, nullptr, [&] { - emit_unbox_store(ctx, update_julia_type(ctx, val, phiType), dest, ctx.tbaa().tbaa_stack, julia_alignment(phiType)); + emit_unbox_store(ctx, update_julia_type(ctx, val, phiType), dest, ctx.tbaa().tbaa_stack, Align(julia_alignment(phiType))); return nullptr; }); } @@ -9538,7 +9541,7 @@ static jl_llvm_functions_t if (VN) V = Constant::getNullValue(ctx.types().T_prjlvalue); if (dest) - emit_unbox_store(ctx, val, dest, ctx.tbaa().tbaa_stack, julia_alignment(val.typ)); + emit_unbox_store(ctx, val, dest, ctx.tbaa().tbaa_stack, Align(julia_alignment(val.typ))); RTindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), tindex); } } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index ad89abf6ca1a2..23d272ea75e7f 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -405,7 +405,7 @@ static Value *emit_unboxed_coercion(jl_codectx_t &ctx, Type *to, Value *unboxed) } else if (!ty->isIntOrPtrTy() && !ty->isFloatingPointTy()) { assert(DL.getTypeSizeInBits(ty) == DL.getTypeSizeInBits(to)); - AllocaInst *cast = ctx.builder.CreateAlloca(ty); + AllocaInst *cast = emit_static_alloca(ctx, ty); setName(ctx.emission_context, cast, "coercion"); ctx.builder.CreateStore(unboxed, cast); unboxed = ctx.builder.CreateLoad(to, cast); @@ -498,7 +498,7 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va } // emit code to store a raw value into a destination -static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest, MDNode *tbaa_dest, unsigned alignment, bool isVolatile) +static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest, MDNode *tbaa_dest, Align alignment, bool isVolatile) { if (x.isghost) { // this can happen when a branch yielding a different type ends @@ -510,7 +510,7 @@ static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest if (!x.ispointer()) { // already unboxed, but sometimes need conversion (e.g. f32 -> i32) assert(x.V); Value *unboxed = zext_struct(ctx, x.V); - StoreInst *store = ctx.builder.CreateAlignedStore(unboxed, dest, Align(alignment)); + StoreInst *store = ctx.builder.CreateAlignedStore(unboxed, dest, alignment); store->setVolatile(isVolatile); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest); ai.decorateInst(store); @@ -518,7 +518,7 @@ static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest } Value *src = data_pointer(ctx, x); - emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest), src, jl_aliasinfo_t::fromTBAA(ctx, x.tbaa), jl_datatype_size(x.typ), alignment, julia_alignment(x.typ), isVolatile); + emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest), src, jl_aliasinfo_t::fromTBAA(ctx, x.tbaa), jl_datatype_size(x.typ), Align(alignment), Align(julia_alignment(x.typ)), isVolatile); } static jl_datatype_t *staticeval_bitstype(const jl_cgval_t &targ) @@ -770,7 +770,7 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, ArrayRef argv) thePtr = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1); setName(ctx.emission_context, thePtr, "pointerref_src"); MDNode *tbaa = best_tbaa(ctx.tbaa(), ety); - emit_memcpy(ctx, strct, jl_aliasinfo_t::fromTBAA(ctx, tbaa), thePtr, jl_aliasinfo_t::fromTBAA(ctx, nullptr), size, sizeof(jl_value_t*), align_nb); + emit_memcpy(ctx, strct, jl_aliasinfo_t::fromTBAA(ctx, tbaa), thePtr, jl_aliasinfo_t::fromTBAA(ctx, nullptr), size, Align(sizeof(jl_value_t*)), Align(align_nb)); return mark_julia_type(ctx, strct, true, ety); } else { @@ -847,7 +847,7 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, ArrayRef argv) setName(ctx.emission_context, im1, "pointerset_offset"); auto gep = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1); setName(ctx.emission_context, gep, "pointerset_ptr"); - emit_memcpy(ctx, gep, jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, align_nb, julia_alignment(ety)); + emit_memcpy(ctx, gep, jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, Align(align_nb), Align(julia_alignment(ety))); } else { bool isboxed; From e1e5a46b002a3979f6b217f1ecd7cede83bf45fd Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 3 Aug 2024 11:43:12 -0400 Subject: [PATCH 129/206] codegen: update type of x after type-assert Later code likes to see that the type is consistent with the cgval and the unbox. --- src/intrinsics.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 23d272ea75e7f..4bfe3f184d24b 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -799,7 +799,7 @@ static jl_cgval_t emit_runtime_pointerset(jl_codectx_t &ctx, ArrayRef argv) { const jl_cgval_t &e = argv[0]; - const jl_cgval_t &x = argv[1]; + jl_cgval_t x = argv[1]; const jl_cgval_t &i = argv[2]; const jl_cgval_t &align = argv[3]; @@ -822,6 +822,9 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, ArrayRef argv) return jl_cgval_t(); } emit_typecheck(ctx, x, ety, "pointerset"); + x = update_julia_type(ctx, x, ety); + if (x.typ == jl_bottom_type) + return jl_cgval_t(); Value *idx = emit_unbox(ctx, ctx.types().T_size, i, (jl_value_t*)jl_long_type); Value *im1 = ctx.builder.CreateSub(idx, ConstantInt::get(ctx.types().T_size, 1)); @@ -992,7 +995,7 @@ static jl_cgval_t emit_atomic_pointerop(jl_codectx_t &ctx, intrinsic f, ArrayRef bool ismodifyfield = f == atomic_pointermodify; const jl_cgval_t undefval; const jl_cgval_t &e = argv[0]; - const jl_cgval_t &x = isreplacefield || ismodifyfield ? argv[2] : argv[1]; + jl_cgval_t x = isreplacefield || ismodifyfield ? argv[2] : argv[1]; const jl_cgval_t &y = isreplacefield || ismodifyfield ? argv[1] : undefval; const jl_cgval_t &ord = isreplacefield || ismodifyfield ? argv[3] : argv[2]; const jl_cgval_t &failord = isreplacefield ? argv[4] : undefval; @@ -1034,8 +1037,12 @@ static jl_cgval_t emit_atomic_pointerop(jl_codectx_t &ctx, intrinsic f, ArrayRef emit_error(ctx, msg); return jl_cgval_t(); } - if (!ismodifyfield) + if (!ismodifyfield) { emit_typecheck(ctx, x, ety, std::string(jl_intrinsic_name((int)f))); + x = update_julia_type(ctx, x, ety); + if (x.typ == jl_bottom_type) + return jl_cgval_t(); + } size_t nb = jl_datatype_size(ety); if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE) { From 8bfef8f1b60155020abc9bdab8aef9788eb458ba Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Aug 2024 17:11:07 +0000 Subject: [PATCH 130/206] codegen: take gc roots (and alloca alignment) more seriously Due to limitations in the LLVM implementation, we are forced to emit fairly bad code here. But we need to make sure it is still correct with respect to GC rooting. The PR 50833c84d454ef989797e035294ba27b3cca79b7 also changed the meaning of haspadding without changing all of the existing users to use the new equivalent flag (haspadding || !isbitsegal), incurring additional breakage here as well and needing more tests for that. Fixes #54720 --- src/abi_aarch64.cpp | 8 ++-- src/abi_arm.cpp | 2 +- src/abi_ppc64le.cpp | 2 +- src/cgutils.cpp | 97 ++++++++++++++++++++++++++++----------------- src/codegen.cpp | 3 ++ src/datatype.c | 14 +++---- test/atomics.jl | 6 +++ 7 files changed, 83 insertions(+), 49 deletions(-) diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index 7c31b6606139a..0a193ee132556 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -16,7 +16,7 @@ struct ABI_AArch64Layout : AbiLayout { Type *get_llvm_vectype(jl_datatype_t *dt, LLVMContext &ctx) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields > 0` + // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->isbitsegal && dt->nfields > 0` if (dt->layout == NULL || jl_is_layout_opaque(dt->layout)) return nullptr; size_t nfields = dt->layout->nfields; @@ -62,7 +62,7 @@ Type *get_llvm_vectype(jl_datatype_t *dt, LLVMContext &ctx) const Type *get_llvm_fptype(jl_datatype_t *dt, LLVMContext &ctx) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->nfields == 0` + // `!dt->name->mutabl && dt->pointerfree && !dt->haspadding && dt->isbitsegal && dt->nfields == 0` Type *lltype; // Check size first since it's cheaper. switch (jl_datatype_size(dt)) { @@ -88,7 +88,7 @@ Type *get_llvm_fptype(jl_datatype_t *dt, LLVMContext &ctx) const Type *get_llvm_fp_or_vectype(jl_datatype_t *dt, LLVMContext &ctx) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) - if (dt->name->mutabl || dt->layout->npointers || dt->layout->flags.haspadding) + if (dt->name->mutabl || dt->layout->npointers || !dt->layout->flags.isbitsegal || dt->layout->flags.haspadding) return nullptr; return dt->layout->nfields ? get_llvm_vectype(dt, ctx) : get_llvm_fptype(dt, ctx); } @@ -184,7 +184,7 @@ Type *isHFAorHVA(jl_datatype_t *dt, size_t &nele, LLVMContext &ctx) const // uniquely addressable members. // Maximum HFA and HVA size is 64 bytes (4 x fp128 or 16bytes vector) size_t dsz = jl_datatype_size(dt); - if (dsz > 64 || !dt->layout || dt->layout->npointers || dt->layout->flags.haspadding) + if (dsz > 64 || !dt->layout || dt->layout->npointers || !dt->layout->flags.isbitsegal || dt->layout->flags.haspadding) return NULL; nele = 0; ElementType eltype; diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index 68f980d7b40da..8839a37da6e13 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -82,7 +82,7 @@ size_t isLegalHA(jl_datatype_t *dt, Type *&base, LLVMContext &ctx) const if (jl_is_structtype(dt)) { // Fast path checks before descending the type hierarchy // (4 x 128b vector == 64B max size) - if (jl_datatype_size(dt) > 64 || dt->layout->npointers || dt->layout->flags.haspadding) + if (jl_datatype_size(dt) > 64 || dt->layout->npointers || !dt->layout->flags.isbitsegal || dt->layout->flags.haspadding) return 0; base = NULL; diff --git a/src/abi_ppc64le.cpp b/src/abi_ppc64le.cpp index 1f10817cfeeee..f02e1022ddc2d 100644 --- a/src/abi_ppc64le.cpp +++ b/src/abi_ppc64le.cpp @@ -44,7 +44,7 @@ struct ABI_PPC64leLayout : AbiLayout { // count the homogeneous floating aggregate size (saturating at max count of 8) unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const { - if (jl_datatype_size(ty) > 128 || ty->layout->npointers || ty->layout->flags.haspadding) + if (jl_datatype_size(ty) > 128 || ty->layout->npointers || !ty->layout->flags.isbitsegal || ty->layout->flags.haspadding) return 9; size_t i, l = ty->layout->nfields; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 297fcb164b112..08d51f52b613b 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2119,12 +2119,15 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, FailOrder = AtomicOrdering::Monotonic; unsigned nb = isboxed ? sizeof(void*) : jl_datatype_size(jltype); AllocaInst *intcast = nullptr; + Type *intcast_eltyp = nullptr; + bool tracked_pointers = isboxed || CountTrackedPointers(elty).count > 0; if (!isboxed && Order != AtomicOrdering::NotAtomic && !elty->isIntOrPtrTy()) { + intcast_eltyp = elty; + elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb); if (!issetfield) { intcast = emit_static_alloca(ctx, elty); setName(ctx.emission_context, intcast, "atomic_store_box"); } - elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb); } Type *realelty = elty; if (Order != AtomicOrdering::NotAtomic && isa(elty)) { @@ -2133,14 +2136,20 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, elty = Type::getIntNTy(ctx.builder.getContext(), 8 * nb2); } Value *r = nullptr; - if (issetfield || isswapfield || isreplacefield || issetfieldonce) { - if (isboxed) + if (issetfield || isswapfield || isreplacefield || issetfieldonce) { // e.g. !ismodifyfield + assert(isboxed || rhs.typ == jltype); + if (isboxed) { r = boxed(ctx, rhs); - else if (aliasscope || Order != AtomicOrdering::NotAtomic || CountTrackedPointers(realelty).count) { + } + else if (intcast) { + emit_unbox_store(ctx, rhs, intcast, ctx.tbaa().tbaa_stack, intcast->getAlign()); + r = ctx.builder.CreateLoad(realelty, intcast); + } + else if (aliasscope || Order != AtomicOrdering::NotAtomic || tracked_pointers) { r = emit_unbox(ctx, realelty, rhs, jltype); - if (realelty != elty) - r = ctx.builder.CreateZExt(r, elty); } + if (realelty != elty) + r = ctx.builder.CreateZExt(r, elty); } if (isboxed) alignment = sizeof(void*); @@ -2222,7 +2231,14 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, Current->addIncoming(instr, SkipBB); ctx.builder.SetInsertPoint(BB); } - Compare = emit_unbox(ctx, realelty, cmp, jltype); + cmp = update_julia_type(ctx, cmp, jltype); + if (intcast) { + emit_unbox_store(ctx, cmp, intcast, ctx.tbaa().tbaa_stack, intcast->getAlign()); + Compare = ctx.builder.CreateLoad(realelty, intcast); + } + else { + Compare = emit_unbox(ctx, realelty, cmp, jltype); + } if (realelty != elty) Compare = ctx.builder.CreateZExt(Compare, elty); } @@ -2269,16 +2285,17 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, if (realelty != elty) realCompare = ctx.builder.CreateTrunc(realCompare, realelty); if (intcast) { + assert(!isboxed); ctx.builder.CreateStore(realCompare, intcast); - if (maybe_null_if_boxed) - realCompare = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast); + if (tracked_pointers) + realCompare = ctx.builder.CreateLoad(intcast_eltyp, intcast); } - if (maybe_null_if_boxed) { - Value *first_ptr = isboxed ? Compare : extract_first_ptr(ctx, Compare); - if (first_ptr) - null_load_check(ctx, first_ptr, mod, var); + if (maybe_null_if_boxed && tracked_pointers) { + Value *first_ptr = isboxed ? realCompare : extract_first_ptr(ctx, realCompare); + assert(first_ptr); + null_load_check(ctx, first_ptr, mod, var); } - if (intcast) + if (intcast && !tracked_pointers) oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack); else oldval = mark_julia_type(ctx, realCompare, isboxed, jltype); @@ -2286,11 +2303,18 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, if (isboxed) { r = boxed(ctx, rhs); } - else if (Order != AtomicOrdering::NotAtomic || CountTrackedPointers(realelty).count) { + else if (intcast) { + emit_unbox_store(ctx, rhs, intcast, ctx.tbaa().tbaa_stack, intcast->getAlign()); + r = ctx.builder.CreateLoad(realelty, intcast); + if (!tracked_pointers) // oldval is a slot, so put the oldval back + ctx.builder.CreateStore(realCompare, intcast); + } + else if (Order != AtomicOrdering::NotAtomic) { + assert(!tracked_pointers); r = emit_unbox(ctx, realelty, rhs, jltype); - if (realelty != elty) - r = ctx.builder.CreateZExt(r, elty); } + if (realelty != elty) + r = ctx.builder.CreateZExt(r, elty); if (needlock) emit_lockstate_value(ctx, needlock, true); cmp = oldval; @@ -2356,9 +2380,10 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, realinstr = ctx.builder.CreateTrunc(realinstr, realelty); if (intcast) { ctx.builder.CreateStore(realinstr, intcast); + // n.b. this oldval is only used for emit_f_is in this branch, so we know a priori that it does not need a gc-root oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack); if (maybe_null_if_boxed) - realinstr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast); + realinstr = ctx.builder.CreateLoad(intcast_eltyp, intcast); } else { oldval = mark_julia_type(ctx, realinstr, isboxed, jltype); @@ -2398,20 +2423,23 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, ctx.builder.SetInsertPoint(DoneBB); if (needlock) emit_lockstate_value(ctx, needlock, false); - if (parent != NULL) { + if (parent != NULL && r && tracked_pointers && (!isboxed || !type_is_permalloc(rhs.typ))) { if (isreplacefield || issetfieldonce) { - // TODO: avoid this branch if we aren't making a write barrier BasicBlock *BB = BasicBlock::Create(ctx.builder.getContext(), "xchg_wb", ctx.f); DoneBB = BasicBlock::Create(ctx.builder.getContext(), "done_xchg_wb", ctx.f); ctx.builder.CreateCondBr(Success, BB, DoneBB); ctx.builder.SetInsertPoint(BB); } - if (r) { - if (!isboxed) - emit_write_multibarrier(ctx, parent, r, rhs.typ); - else if (!type_is_permalloc(rhs.typ)) - emit_write_barrier(ctx, parent, r); + if (realelty != elty) + r = ctx.builder.Insert(CastInst::Create(Instruction::Trunc, r, realelty)); + if (intcast) { + ctx.builder.CreateStore(r, intcast); + r = ctx.builder.CreateLoad(intcast_eltyp, intcast); } + if (!isboxed) + emit_write_multibarrier(ctx, parent, r, rhs.typ); + else if (!type_is_permalloc(rhs.typ)) + emit_write_barrier(ctx, parent, r); if (isreplacefield || issetfieldonce) { ctx.builder.CreateBr(DoneBB); ctx.builder.SetInsertPoint(DoneBB); @@ -2430,21 +2458,18 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, instr = ctx.builder.Insert(CastInst::Create(Instruction::Trunc, instr, realelty)); if (intcast) { ctx.builder.CreateStore(instr, intcast); - instr = nullptr; + if (tracked_pointers) + instr = ctx.builder.CreateLoad(intcast_eltyp, intcast); } - if (maybe_null_if_boxed) { - if (intcast) - instr = ctx.builder.CreateLoad(intcast->getAllocatedType(), intcast); + if (maybe_null_if_boxed && tracked_pointers) { Value *first_ptr = isboxed ? instr : extract_first_ptr(ctx, instr); - if (first_ptr) - null_load_check(ctx, first_ptr, mod, var); - if (intcast && !first_ptr) - instr = nullptr; + assert(first_ptr); + null_load_check(ctx, first_ptr, mod, var); } - if (instr) - oldval = mark_julia_type(ctx, instr, isboxed, jltype); - else + if (intcast && !tracked_pointers) oldval = mark_julia_slot(intcast, jltype, NULL, ctx.tbaa().tbaa_stack); + else + oldval = mark_julia_type(ctx, instr, isboxed, jltype); if (isreplacefield) { Success = ctx.builder.CreateZExt(Success, getInt8Ty(ctx.builder.getContext())); const jl_cgval_t argv[2] = {oldval, mark_julia_type(ctx, Success, false, jl_bool_type)}; diff --git a/src/codegen.cpp b/src/codegen.cpp index d8d7a1fd23814..ef18d9bd1b673 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3374,11 +3374,14 @@ static size_t emit_masked_bits_compare(callback &emit_desc, jl_datatype_t *aty, size_t padding_bytes = 0; size_t nfields = jl_datatype_nfields(aty); size_t total_size = jl_datatype_size(aty); + assert(aty->layout->flags.isbitsegal); for (size_t i = 0; i < nfields; ++i) { size_t offset = jl_field_offset(aty, i); size_t fend = i == nfields - 1 ? total_size : jl_field_offset(aty, i + 1); size_t fsz = jl_field_size(aty, i); jl_datatype_t *fty = (jl_datatype_t*)jl_field_type(aty, i); + assert(jl_is_datatype(fty)); // union fields should never reach here + assert(fty->layout->flags.isbitsegal); if (jl_field_isptr(aty, i) || !fty->layout->flags.haspadding) { // The field has no internal padding data_bytes += fsz; diff --git a/src/datatype.c b/src/datatype.c index e7ee15a63f56e..e88977dd67400 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1250,7 +1250,7 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- } else if (nb == 1) { uint8_t *y8 = (uint8_t*)y; - assert(!dt->layout->flags.haspadding); + assert(dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding); if (dt == et) { *y8 = *(uint8_t*)expected; uint8_t z8 = *(uint8_t*)src; @@ -1263,7 +1263,7 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- } else if (nb == 2) { uint16_t *y16 = (uint16_t*)y; - assert(!dt->layout->flags.haspadding); + assert(dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding); if (dt == et) { *y16 = *(uint16_t*)expected; uint16_t z16 = *(uint16_t*)src; @@ -1281,7 +1281,7 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- uint32_t z32 = zext_read32(src, nb); while (1) { success = jl_atomic_cmpswap((_Atomic(uint32_t)*)dst, y32, z32); - if (success || !dt->layout->flags.haspadding || !jl_egal__bits(y, expected, dt)) + if (success || (dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding) || !jl_egal__bits(y, expected, dt)) break; } } @@ -1298,7 +1298,7 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- uint64_t z64 = zext_read64(src, nb); while (1) { success = jl_atomic_cmpswap((_Atomic(uint64_t)*)dst, y64, z64); - if (success || !dt->layout->flags.haspadding || !jl_egal__bits(y, expected, dt)) + if (success || (dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding) || !jl_egal__bits(y, expected, dt)) break; } } @@ -1316,7 +1316,7 @@ JL_DLLEXPORT int jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_value_t *y /* pre- jl_uint128_t z128 = zext_read128(src, nb); while (1) { success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, y128, z128); - if (success || !dt->layout->flags.haspadding || !jl_egal__bits(y, expected, dt)) + if (success || (dt->layout->flags.isbitsegal && !dt->layout->flags.haspadding) || !jl_egal__bits(y, expected, dt)) break; } } @@ -2010,7 +2010,7 @@ inline jl_value_t *modify_bits(jl_value_t *ty, char *p, uint8_t *psel, jl_value_ else { char *px = lock(p, parent, needlock, isatomic); int success = memcmp(px, (char*)r, fsz) == 0; - if (!success && ((jl_datatype_t*)rty)->layout->flags.haspadding) + if (!success && (!((jl_datatype_t*)rty)->layout->flags.isbitsegal || ((jl_datatype_t*)rty)->layout->flags.haspadding)) success = jl_egal__bits((jl_value_t*)px, r, (jl_datatype_t*)rty); if (success) { if (isunion) { @@ -2125,7 +2125,7 @@ inline jl_value_t *replace_bits(jl_value_t *ty, char *p, uint8_t *psel, jl_value success = (rty == jl_typeof(expected)); if (success) { success = memcmp((char*)r, (char*)expected, rsz) == 0; - if (!success && ((jl_datatype_t*)rty)->layout->flags.haspadding) + if (!success && (!((jl_datatype_t*)rty)->layout->flags.isbitsegal || ((jl_datatype_t*)rty)->layout->flags.haspadding)) success = jl_egal__bits(r, expected, (jl_datatype_t*)rty); } *((uint8_t*)r + fsz) = success ? 1 : 0; diff --git a/test/atomics.jl b/test/atomics.jl index 3df9e7d0f63c0..165c8dc4e2dfc 100644 --- a/test/atomics.jl +++ b/test/atomics.jl @@ -129,6 +129,7 @@ test_field_operators(ARefxy{Any}(123_10, 123_20)) test_field_operators(ARefxy{Union{Nothing,Int}}(123_10, nothing)) test_field_operators(ARefxy{Complex{Int32}}(123_10, 123_20)) test_field_operators(ARefxy{Complex{Int128}}(123_10, 123_20)) +test_field_operators(ARefxy{Complex{Real}}(123_10, 123_20)) test_field_operators(ARefxy{PadIntA}(123_10, 123_20)) test_field_operators(ARefxy{PadIntB}(123_10, 123_20)) #FIXME: test_field_operators(ARefxy{Int24}(123_10, 123_20)) @@ -317,6 +318,7 @@ test_field_orderings(ARefxy{Any}(true, false), true, false) test_field_orderings(ARefxy{Union{Nothing,Missing}}(nothing, missing), nothing, missing) test_field_orderings(ARefxy{Union{Nothing,Int}}(nothing, 123_1), nothing, 123_1) test_field_orderings(Complex{Int128}(10, 30), Complex{Int128}(20, 40)) +test_field_orderings(Complex{Real}(10, 30), Complex{Real}(20, 40)) test_field_orderings(10.0, 20.0) test_field_orderings(NaN, Inf) @@ -568,6 +570,7 @@ test_global_operators(Any) test_global_operators(Union{Nothing,Int}) test_global_operators(Complex{Int32}) test_global_operators(Complex{Int128}) +test_global_operators(Complex{Real}) test_global_operators(PadIntA) test_global_operators(PadIntB) #FIXME: test_global_operators(Int24) @@ -691,6 +694,7 @@ test_global_orderings(Any, true, false) test_global_orderings(Union{Nothing,Missing}, nothing, missing) test_global_orderings(Union{Nothing,Int}, nothing, 123_1) test_global_orderings(Complex{Int128}, Complex{Int128}(10, 30), Complex{Int128}(20, 40)) +test_global_orderings(Complex{Real}, Complex{Real}(10, 30), Complex{Real}(20, 40)) test_global_orderings(Float64, 10.0, 20.0) test_global_orderings(Float64, NaN, Inf) @@ -844,6 +848,7 @@ test_memory_operators(Any) test_memory_operators(Union{Nothing,Int}) test_memory_operators(Complex{Int32}) test_memory_operators(Complex{Int128}) +test_memory_operators(Complex{Real}) test_memory_operators(PadIntA) test_memory_operators(PadIntB) #FIXME: test_memory_operators(Int24) @@ -1031,6 +1036,7 @@ test_memory_orderings(Any, true, false) test_memory_orderings(Union{Nothing,Missing}, nothing, missing) test_memory_orderings(Union{Nothing,Int}, nothing, 123_1) test_memory_orderings(Complex{Int128}(10, 30), Complex{Int128}(20, 40)) +test_memory_orderings(Complex{Real}(10, 30), Complex{Real}(20, 40)) test_memory_orderings(10.0, 20.0) test_memory_orderings(NaN, Inf) From 2a56b7876be5d9364f2b187828e82f0cef0609d0 Mon Sep 17 00:00:00 2001 From: Zentrik Date: Sun, 4 Aug 2024 10:05:44 +0100 Subject: [PATCH 131/206] Bump LLVM to v18 (#54848) Co-authored-by: Gabriel Baraldi --- deps/checksums/clang | 216 +++++++------- deps/checksums/lld | 216 +++++++------- deps/checksums/llvm | 436 ++++++++++++++--------------- deps/clang.version | 2 +- deps/lld.version | 2 +- deps/llvm-tools.version | 4 +- deps/llvm.version | 12 +- src/aotcompile.cpp | 70 ++--- src/ccall.cpp | 2 +- src/clangsa/GCChecker.cpp | 12 +- src/codegen.cpp | 6 +- src/coverage.cpp | 2 +- src/datatype.c | 4 + src/disasm.cpp | 4 + src/jitlayers.cpp | 45 ++- src/jitlayers.h | 5 + src/julia.h | 18 +- src/julia_internal.h | 22 ++ src/llvm-cpufeatures.cpp | 2 +- src/llvm-multiversioning.cpp | 6 +- src/llvm-simdloop.cpp | 2 +- src/llvm_api.cpp | 12 +- src/pipeline.cpp | 15 +- src/processor_arm.cpp | 2 +- stdlib/LLD_jll/Project.toml | 4 +- stdlib/libLLVM_jll/Project.toml | 2 +- test/llvmcall.jl | 6 +- test/llvmpasses/pipeline-prints.ll | 6 +- 28 files changed, 594 insertions(+), 541 deletions(-) diff --git a/deps/checksums/clang b/deps/checksums/clang index ee3dc2125ea30..7dc297db9c05b 100644 --- a/deps/checksums/clang +++ b/deps/checksums/clang @@ -1,108 +1,108 @@ -Clang.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/5a9351db0940c66e9646e0f3d6f37e1a -Clang.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/bf344cfe91795cfc4419ea9ec50df99237b64c57e0b81655a957b15ecc5b16f0134daf189f18fe34274df8de679d407b36f82e3723e80428afb456215a5b9a20 -Clang.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/md5/6c7461a52e07a1e3ecf9911784bb26cb -Clang.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/sha512/ce63de6405cd7c34d640afb259de8056db175e55bece923ce53c39b88dccc2885de70f4c598b3282102754b0c7cf6ac602e827968b6509fd7affa20ecf07d1a5 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/5446f22e4aba17482c057ee79beb2086 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/372be10dd8752821c751e571a5a9fc4af328285dcad6f2213f6e3d54f819405c26f1a1cb1e712d4bffebe3a42ca0736903d59ba70602a8ddd96b9e6fdfb9bacf -Clang.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/ca146aa3731ef24300c8398ddfb7ffd4 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/2459729a3af81fb962c7491ff16209fe6b65f4ef2f8323857b7c548da506d227a42a9b3301b8c8465cff66bbc9acbff2ac3e86d1a8560b9cb701b133317cd730 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/68c478b00a6cb1ecf700b54c86acc584 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/669af6e27ee67ea1be7f70cc328193d6139161264e1f6ef85c31c62523997246050d8b8aa241b257a191a9566df1f3ea620641c676908b817d5dfe7519ba0c8e -Clang.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/a299ea50c4862dcd0832cc483aa9c172 -Clang.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/e42e2e09be2872d2e1c57a46099b92847873dd4ebc87801cbd5fc171bbb236ef8bb815c4fd481d4a804fd6604fcb3cee7ee6fa66e712cc7a2fc2434d0649932a -Clang.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/804ec7eeb6b2fd8fb6ad9537bebc0f3e -Clang.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/36cda1267528e54658b28d31ed4218ecb11c2a05e161faf80030a899d2cb1d1ed145bdf19f7565853277230428d521a2b33759df09e0e799226b44d477c2de46 -Clang.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/4fd80844867e14a1a245c2ed911942bc -Clang.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/acc6a4d240b54682425f40d8c5b6e3578d818b03430696c3c90cde8ad8474de5692468379cfc7f4d826bd44a6fb38cdc036df9d31833d09477fb69ae569e160c -Clang.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/1774c2ed22a44aab72d7cf58c8a85ab0 -Clang.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/686b2bd8af2f47b03b25e23ac2d2954e5b9ccdcd942fcc6ccb9b96240a1fe414ac73d88f173dfdf93f45eb609e99299041a6a976a90b7afc6e49b698b6403a94 -Clang.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/e5e0d42647b5b50102f68e76823be11f -Clang.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/72b112ab6714d67c33088c978420f996a45c6fd1900ab1725908792a5b8a0f0407ecf53817761059fa4bebd81a443680c8cd1c25633a2eb702986a23072d7b70 -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/9601966aed6cdf5af9b6da24bf088ef8 -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/c70448ed703f74c0f82c43ba35bf3a1f4f02832e42bea795b5ae0caae1e3b8aa0fdd914b3a6753a68b9f0a7d3a5156e56fad35bd6fff15bc5566f74db26ce3ca -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/3aa7b1d67c252aab4cfb85a665ecf194 -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/7575858507e07b94001200c4d4e9875a2a4c8b97074655a1c1c03edd8cd2bbe853cca3a518d36d6f3243649839aa53d4dbe2e637eaf9b93873b2dd82266d4e17 -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/7729c1ebdde07122fd0f9ae63a14c34f -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/04fe96e57a5351c3265441b73919900f1d19220747aa8ac061ef15531ee3f6bd62a70a4405c615c3b14975250b039d81fabde3b351c6e2118e684ca479eacbaa -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/37536e1d18b6b0a948b83ebcee530af0 -Clang.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/d94c3bd7afbca9dc81bb10a4d0e041165e63a2ac9dfcc1483bd55da1091c664074e9a26c9972da23adca3f711ffd22ba517546f0f0e58b717f3043973def0e97 -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/ded5fe5d4de1c3bfd0fc75494c44cb11 -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/85f6df75ed2b67fe9dcdea745ac1e659c0335c17c54b03c964d6996e926303fbf14c1c2ed6b369ffa38bde827c9894c32de82afa562673dad3268c43985dc7ce -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/e4eac3b4bfa0e3b825cd23f88738bd3a -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/c0552d1c9dbfe73b07f3ea2907d879c1142e8f6db6530297ee977c2b23858a9f55674f635a4746262e7595af2ca41a752a6abb4944e6707f4daa3a8c0715df83 -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/4b5f66f39069204ba7281740115b7ef7 -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/4c789017ec2bd98e808d198a8baefb2405222efb6e93eb5d1b8944dbd1e587afc41ebaf506b0aed5def5eb4c815ef4c822e0e0477b4aaac35fc03f9850853be3 -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/95310b525b635b8c6550226e2b9fe02b -Clang.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/faa62d41124b92d829658397eaada3ee8ce41f2e36e7f9954bd3fdd882a1232bf3431f36c9b7e65c17ae4f228da9ac37e1db0b1ae43a8540765186a230c65bab -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/5886d8e09d76ed74c2293c0af8be413f -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/ca66bb3bd39b7643cf0dcb551a6bb7a3293f4c99f8d4ae1fc16eb66a0f0da0ef10acae52169b2522dc2fdebc1f550d2d36b87bb25d9b1c9df0a8f0d5089c7642 -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/7b08c562565e408d716898bf37e44eda -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/e9051454cc15a7879d90e6b36eeaf4c956e328be7823a1fa37cb98197c0fb4dddb9aaa8cf7aedd35e0affa9e6876b79f9a1160da1ec4d26ea7c775db58293dd2 -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/dc816bd807c9d131e088c30caad9d326 -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/5700dcef831b52abf64cc9120352918c302301e19ecf6ac64aa2cfb6270f7b2c82fe3f0f1d3281539081db7d520e2301995d992b9e8234cf64d7ec88126f4bc8 -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/971caa23440c190b085300f4cd67b080 -Clang.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/5ce854fee306c14ef7964e3ab9831e816c6eefab637221b71be2187f42e7b089c1dd9e92754ab5ee3198bb3c0e84da9a2cc15c2d6afcb086f61b897cfc320ab3 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/5ad3e0a391db624713263226259b55f0 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/ed4cf7c241bbaca9f887cfb81caca687e3f30d01922e05c72b435c6333b334fa4f708193b8c85de9777f9912fcd8a55b1d7a6cd1aef00b913f0d0f1439e9ed6f -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/5d487035d147bc48655e5538f08afbdf -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/f26d96241b9b18609c1d4148e30048d73faed24fe3f623a5d2bc6aaa59a644cc97201acfbde2eed4daecc79602e6d13256e112c8b821b6d865d071db957268a2 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/fdcf70b4514c3d63498a3fa46a2525c2 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/d481c807405302eabc612075e22acc9f7d1cbdbb17de23b6a129dfba60c265eacf20cc2d48d5b4087979b1184a783bcd0bf6ed326060e5ef05119556f21a5a95 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/a8a04c92d74dcd22f980956d2b7ccb71 -Clang.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/af3ad3efc2941b98ca4ec1340e24beb1c1f1c5d2248da3000af3f2e7184df013b55127040cfd03a63acd461acdb4f1afcc6b11f1ad11502aa86f737629c185a2 -Clang.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/15d02f2f91fcdd52d641991d58b15c9b -Clang.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/e1903be2164fb3002a93829a295d2a413c14faa2a0fad2297763a6cbd63ec0bcc37689cbec4c0f0bd0f4eb4cddc716f78d57c95f7ed29145ffed3b7c50a98d04 -Clang.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/cfaab26c1c8409362a267484c2ccfbc1 -Clang.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/2f9bb137df4666f9c2947a74a4a06489d477b5093c3b0acae11d6c1213c467e258aaa360183f8b18ca28778773a5170f5dd19ea3622294f0d715a5909c6d06ed -Clang.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/6bb27685277eae5289f782657925c33a -Clang.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/35bd7b862b2a2aa372be7f0bb01aa65dc58f71d2218833ca39f832a25c3162b3282c9806f3cdc4a9a2a7bc11167a6daec30b688b979f1a38f49fa412e4628648 -Clang.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/f44f9fdebc843c5947d1777e53c4189f -Clang.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/09d1f9a29bdd04e598622cca11e0a82ef6a68f0ac9d4e6fada548482fff6219cef5714bdd3d02d1c0944de14ef14991ee0eab9b4f54c4efacae330a9e4ac47dc -Clang.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/0d7c790218fe40d1f87850197a5d08df -Clang.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/fac636c5ede5baf7d5c706f348b8992d4bf0042cb34decb83964385d9877b7555db998fc79cd7f032d80b3572275f13fbc36ccf5a76e573221266e1ee339ec76 -Clang.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/5d4f5b78645f75b93e76a75efdad721f -Clang.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/a013697f1da103a1202a1728ebfc61ec0d08e705e0caa253cd14430abfa3d47a7b43930d3d9d70d995dbb1e5f78eebd02ef8cbfd9b028b447a3b7953d437a60d -Clang.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/8d9b46562cefc0ce9b7dfd6022cb914c -Clang.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/95d8cd716bfbff69d336987a3ff0f65e28f48544679cf6bd165319cd5382f0eb9d5be119917a5b309e7544e43ac7c52f1370d159e67f18ff2eda06cf7bad31f5 -Clang.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/86bf7e43fa750d620495eb73c938273c -Clang.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/1a014fa2ec455fee7be9413fa1db901360e5728bcfffb7bb76fd3b30b00120883c91f4ebfcfe048e5f372bdcc18a2a45744ddb1e8c7e303d5952af49e386caff -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/c125dafc105894bb0bb821bb7b28ce3a -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/6da75d2fdc18ba95dd3db9181401a4ac0b7f8e465ad872f95f2e9db49701cc56da7c13f6ca69b01e15832f9bf23cd698ca5dcb28dcf775edef6bd5728ca669ca -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/4b9d2090af04573a35c0d80833f9212d -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/7e9231e286f15b4d90318a732d1fae3130a1d6714f6cf868f5d3472068b719818e4d2a63dfbb2056e1f3e7f2a25250c4de1f0629e459b36f7d8e1e42286470c0 -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/7762d01fc07748336997bee900003653 -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/c7334dfaa5317b89a58beb0b397a2784036c98fa3434f67efcbfd1ee9375a195ebfedbfcc2f7ddde00a518e2a175cd821e11b887a913499c10d60940c7cdbe43 -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/4d4388d2e621d71e390579d0684776d6 -Clang.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/b5dee74f399ed7422fc1dbb3321b8c216fe434ca57440c4ee51293b2478ef007df9f8d1031e714496014309ac8eabee4c7c884272181c0713253f43e1bcab3e6 -Clang.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/927779c5fe29a5beb2d4bf0668a0fae2 -Clang.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/3c16687184eaf180b5a6861a4b96ddf0d099769bbfb21265ed434575c537b10a30803924f05aa53ec0684cce8b8ae31f3082124130d4a4ae31b717bfc01e7442 -Clang.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/md5/5c08fb48aa15c5ee9667a3e177f19851 -Clang.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/sha512/aa773bb698145fb4040c34d787d959c0db71c90da5a5e5bf6799d287fd7925049169fa1a681742e12f81a32156b1d958c2f1d92295888cf50ccd4b84fd798625 -Clang.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/302b59a86820fa43b0f62c8788f4129f -Clang.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/543fad08f4d22a8ee5a25c29b81f8e6df729e19bd31d94cbb48d5cd9bf451fffdad692209d9a0a98583bd1cb22d3a783ecc140c10c65da58ebb1b727311aeea1 -Clang.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/5e904bd57f12999826ef39bc37382c76 -Clang.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/adb8061bc2debde834722b7965d4dc8ee5ea5a5fd5459eb84f872e13cb40a38d2e923f5dbe06cff5138e6cf065d9ce91e52ac395a586f0ac9c6f4f2fe1e4f0d1 -Clang.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/806b042515bb8294bacf37dd804dd303 -Clang.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/dabb1c73f477ca97ae2d84846ed937f084ceb9abcdd614a0fdbcab7b9d863ed8544ba25fc25f99df40254c964eb4abf89ed61bf4a61f680607e8d096f71a837f -Clang.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/1e92606453daf98bbb5879aef9a0b97f -Clang.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/f262e08e2b36dace3f7cae645709627368a221bc7d3a081e501f5a95797ef36e9c63071f17d722ee546e0993502c171049f285e22f665e3998e1a408e3adcdf0 -Clang.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/d5519cf744be4d311c5a6ce97cd26d6e -Clang.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/5ef23e8b5c0a828974dfa578eae68255e01c461f7d4bf10ec43f0bb4d2fe3b88c649dde8fe534550c602ceb835f7e736aa7d0b642c7ed21aa725c06c3bd4890f -Clang.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/22831802bfc779bac31c3b5fd5b613e5 -Clang.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/94be9e0c6c077409f8eadbdfd8ddc83901bf36f095563e630ba02a86234f30d67d4bff6df2cc33e1c52e494f231f33538ce1f8a25a2d0e187596c638121ed948 -Clang.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/71a77a339451b9d49858ecbb11119efd -Clang.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/49c3aa8c8580969750ea6d61fd69e98d1daf47b9578cf3372febd2df79542e22940a24d23ce16dee20e4bbc4becb9340f820d3d45f879fbc5209f3f9699ffe2f -Clang.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/6a6d68aaf9ba085c02ca1218cdce0246 -Clang.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/fcfbc12cb248021b4f8b9bcd7a21cf695b0bbb3983564a9602e6a23f83ef1b5d884927ae7b46ab5e3752a18d5346fc0b52a160ea18af1c9ee28870b470b4591f -Clang.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/md5/e451f3326c665c8dbdb41ffa2b6362e7 -Clang.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/sha512/d2b2f812dcd0d9d7602f37bbb629a8573be8e1d97e40efc51fe4676d6fbe69c21aa1943b6fc7172e788d3b3d2fd9d02fc3279838fad70434caf3a9e427006336 -Clang.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/md5/995abd90c834cadde6f272e097ae51e0 -Clang.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/sha512/f8f2d4ef5e2fac7d5e3b06ba76f7f54791820e15f0ab1bbd182a5e70709fc29085c73f5709cb45267671a849dd965e01683c6ced91281ef9d64f4750cf5d6151 -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/26143a5824a6564f69510f227acb6b1c -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/1ce7c9cc3c9d04934f06a32d67f5c23f68cb26b917cf81c8e9844ae20eab4709110a4142d21b62b205c714363df463e63c2563011f432e2e0206731841798ea0 -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/06dbf7651fe7d8b021fc1ab6beb125c3 -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/daddc731c54c13c0b2d665bb4360a400fec3246f6d756d5401a241cf6c9dcd2fb1df2f55c3559551ef9536d40067e9ae31753947756ef6210696b87856f831c2 -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/722fa85d203c5da1b4e28a1510bfa27a -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/cf8d09192ad248c6603de813b22bcb61e72994d0d39cfc4260d6f6e1ebe69386313f924c5e3de3021ce2041bc41d8a022623bae5c8979fcf81649c85ee25c9f1 -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/85b8d93bdc92b4014d45f5dff6ba626e -Clang.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/b1d66f9bcbaa3dc571fa8a1ca79f39f79ce4c7941bdd1a1fb7df2aae2c90960b9ffd7899237da1379e1898c18e2ffcc63eeefd20ba64550aca82167474981494 +Clang.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/ce3e582bcf2f92fdaf778339e8c51910 +Clang.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/4f977e8f0912f52b9b4054089a53a05f60bf7ae352c39b2541e68fecf3c21969d6d1b85e40d71d61040b65f7c60a2c33c8d259734bc1d2ddf77392fc425025cb +Clang.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/md5/1eda08774c2f9975de32bdce4ffc72bd +Clang.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/sha512/c76ec1de9a25f4f8bd309336830cc07e1113b941ced12cb46976b24aebd4ab3d261c943dbc9cdfb34a01f27073af6f598dded31a4e03c62f229cd2e7d5982af6 +Clang.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/2817b0eeb83eff4e1f580729e02564ab +Clang.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/88242559299836c7a7b7d3a216353fc6880a587a839793ed71d6d053318d6e2071ff218587a082f2b5dd9fb2b0952b4c60e62030d707435607303708bb1e6d81 +Clang.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/d3f92998b7cc35a507cb1071baae8b02 +Clang.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/be22296623f604927e2e815a1cc149addda6d567270a50b2cdf77fe5b09f74313210a1ca7b1b3194592da23490ba1ccfdab9f520ce7219989e646f12208e418a +Clang.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/716300acfdee4415f1afa3b5571b102b +Clang.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/b97efb3c461ea7d2736a3a8bb6b6b5c99f02df9a095f11291319c629d44f1fb934b124d38af6be3e5cc7103c6f85793d7f185c607383461de5d0c846560a1d1b +Clang.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/034f44b2fc61791234d9580402002fb2 +Clang.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/0b4ff55afcec0b1e8fbd09fab57de8b44d5ded360d3b53132c7a7df8d3a3b83a495bf6e0c706784e678c6de46be3a72e8bfe562c7f8dfad90b82880849625e35 +Clang.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/54211070d63a2afac6350d06442cb145 +Clang.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/a58f8afe9a20f202cf3956f758dc13a10be240d78877a02cd006d7e972751ed65623eef7e92a7256d9ed9157d6e277302f93b58f583d86d386ed4945f3c7d875 +Clang.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/7084567b3637fe64088fdce357a255de +Clang.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/77ae83e159a814a7117cc859a0b2aa7a5d41f983d45b7eb1ce2fd2e93f8733ee067ac8c9fad9d5af90f852b8802043ef39c29b44430b2594892e57b61ccb680b +Clang.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/9e294d16a6e1c2c76c03f32cbbbfbe23 +Clang.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/b8f83542b51f5cf953f6baed185550394744a8466307ee08525bf18a651fcecd7daafb98e75a0866b0e9a95a524e8940be7ae1878ba80d856182dcb7f7d2254e +Clang.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/70a41c2ffd55d2d87a7b8728287eb9fd +Clang.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/44bb3dea7227ee991b2666c43a88613d5b5d382eb560b5ad1f1184d38680c85a2ef961bac6ad71c2b920702c1ec6e09296198e7ff5e2929f4ba7839e55896e3f +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/95ee1406f8575898eb52e2c86ae18992 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/4da66e4d397491836b3e539258844346fe50bff41e6c0628cbb5c0eac76147bd91d1720cec1523452efdb063adf6ef8792dc278244e1f8e194ef60a180442c56 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/6c4e4e892b54ce81d73a8598728083e3 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/53d08fd8b6782867cfa6ce001b14a2fde38bc9ffc85c7e148aebf59dd9c1c535b54eaea816c39fcff42abc456c1047ed13d688917302bcc5a281abe368bd29bb +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/5acc5853111bcd529eeb06ea31b329e5 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/b1794f7cdfba838a7e43de8f66700ae44fd16d8f06300e8ab955044ae9bc96110c5ea72691841cd3787cdc93dfb91c6b257702c20390689a8d1b45a994db2fd8 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/c4de50252e557fb126360001ddae6a97 +Clang.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/9343a7272c76d5341bb49273ff8d43bed09ad99b2879ec51cfb8946174181b286af82d85e2d3a13a375c7e7859e51e4a4f06031a6a3fe7e540700cfc6a795741 +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/af301478b20e56cb7fa1160cda2573a2 +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/8822c58df101c239221fead6fb523e677da04a065b42849a2e6ffff03dfd81e07f162a9bbdd29490ad9c0e0a33d362eec46608b9e6e42dfb4889da1c22191c91 +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/901d2808599d5ac5ac7b5ca4bc39833d +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/820756cad00b1fe927801a253bd3077709c2b067ae79f9e1812f3cc9e85a0b7ac2ce1534031b7c6f7bda3364b7173c1c508e7c7d316920fb9bb901c16c1b18c7 +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/d1f368604084e907c382aaf00efe452c +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/523b25f6b79e222eb65b5f4cd8f23b0d2c8b25b29af0df88efe45546ea57c7dabd88baef454fa0b76342d8d364739107271f25d3504380fdec5c9d225fcc2521 +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/e57c116b2ad1cf32307eb4e600ac80be +Clang.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/63366b983c7aac9fe1246b25432b2200c8316f569f6930eb12de3c867f448ffccb8756d418f92eae7751d4c9ce6c42cee38237e429b81530819684fd5150c93a +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/645929ce42276db10ab79184a60cd6e3 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/65555ed26d9bd670b8363e5dad949822c2bf0e141a5418e1dc30c3f8a4733dd050620e40be2e7552c2551ecb30d4ef3e8f74cb240f1d441a9720a25f5a3bcaa7 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/8424c6c6318dfa7bebeac33917b29453 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/6cf90c253f6b22358c2389a2347af2febd010117b22de0cc91ad713b8c8224627398004567c96b673650212eb5bd40bb97b9a637d46ddfeb3c72388d83445017 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/ea8151dc1dc32befe579c7f9d7f13898 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/ed518423e9ec35afd7983471cf9ff1e971b840f637f34e0f62a1f6c7379ea59d4dafbeb9a311d39761733ecc98c0318ce3d8883298f8998e9c741441c7c9616b +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/70ed39b13bcb0435fee63bc30ae25a39 +Clang.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/b2afa383346875514c62129c2991b3604c4fd3d507ecf4fc4244dec81d08b30218f5aa03dc4977185c2c9fb2d08848ddd373e448883ab472e5221ae5bf285c99 +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/e6798835128f663f0c837aed4463e34b +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/c99856e16bd42ff967479e2c89690ea41268f1d1f868e2628482eafdfa53a0d69ed7c21ecc68ff0859eef07d9fe02f4844fad5f13df26cee6cea3a4254446096 +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/92c1bd54b0474244e35c51952966a55b +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/2d7c3b60ba8b11cf903bc5ea720193852027cbe61ea0c8d6fac70be8f97691da3d36663aac6e61b68185dd83b42d09ad61dea973d9390271210d690295e4902c +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/c495d594f8ce1f701d1bab54d0b60521 +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/0261bf45403daccf236723383341dc791e9cb3b291bde97812378d85aed785f083d5deea3bf806480a04ef1b972b00dccfd0537e43532a066c64733b817c3d77 +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/41541de24d625271bdd5fad867b8eb0c +Clang.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/595226ad7ef75ab8ae03adb456b4ee9e884e9554c720b6c4ecbc38c75d446ddba7898be94630673074f09f40c6dc3e18fea9cee5a91b8b0e4727d20a180f670c +Clang.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/8bd8ca0436611e78882939067f6277f7 +Clang.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/27c7b06e93fb0fb516b1b240e0df6c95e8bad6aea04d637ba065c6fafd087bfa94d9136afd39273c8d82d9c467395dcbd7b16f6a4b829acb0c0d4a5677676a5b +Clang.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/424bfbd7b69ddf7b1199afaacde3e028 +Clang.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/9c48d949309aef6ee39371ff39a4f12c31bf3f25ddd288b317b2a17a803db73850cba2886598a1d10c4c154d511a4b79958d1acc012e92491a63f3925c522873 +Clang.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/6b0b3e045ad64ecdc9848898f30d5f34 +Clang.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/6c0f4bdabbbc94fc9e1fedc138b0bce99d383e380ae7222fb70f5935f17701d549f6486956c8a21731061e4bf60bbc52794f6ce6858b4d2adb89bf80f88795c0 +Clang.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/3b7a461ebf957756aeb2a2455b0a298c +Clang.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/74641a3636dd58c69415b19f0cb1de444215e22cfa9f0268fd549b5c53b206811d8beecdeb9692285613468d9a0569e836d225fb8361218438346914f6282839 +Clang.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/5e7b9ad5fc3af3bfdf262687cd248dfa +Clang.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/c54835fdf8e3e442b7c774d445c2f13c5dd8b3224f4ae165e72cc893ee5453d0112a9ca6d543b17f2c02a89471e2cff7cf022dc4c8188a5df25d101dd0f954b9 +Clang.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/3204bd8074d42920a6707cc8624c0dfe +Clang.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/74b26c4556ca18645cc15647d8abdbd46fb94c75169934af885e5773a880c066b2ff221402fdb4a53417b2c97ce589783f7fae6a8d56ee89cc1f70577b02b2a1 +Clang.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/7922c04964e0c1a5b44e95480290930d +Clang.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/4f0d675c1b85dc3e5007a62a7cfea412ca432d1276a259db3ed5a1bf0f33d6c555f16010de717a62e0e065e7c1dbaa66c281815eb9629d2b6c720b152820e582 +Clang.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/e023eba0ea0a327f53013d5e4d50d0cb +Clang.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/9fbdebce9c7375a20d1cd10e39a0c26b131af686cb5771034a6afc6cab08855e0cada2add616c01394424383333950d0dde9c55a9477fa139cf0ca3fc438b229 +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/a6c7d64ede931fb19e066a1c191e2f6d +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/1a085a4ea1efb910f2b529f3c0e51be4a5e31debbefd00ceefeddc352b36bea6d0de5a06ea7d509098d16416b536ffed3da8485feefad7a2f11b1bc148a0c8c2 +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/692af94ca3e5c3d229cbb459e266aadf +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/b27f05cfb0ada89cefc5a6f6527583b6b43d03525954d5b1ad1c807712efdb8750ea558a230b587a0c0d9e77c54d9f8978cc2f3884653808c7409eab1b32a055 +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/3b59b6aa4b18b5dbbc632811f2ffa270 +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/f8c4b593f969c723ff1931c4875ed52497d83d74b94121890e10c9fcca5f6bddc5067555dee9949e61e426586ae3e568375fc44f318a07b70571ee34fdf7032c +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/bc4be32ad57b13c3dabc80684a176ba7 +Clang.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/19a8346547b6c6adc2a9156e4b913b20137593752efa3648ad532b08de67cf015bba1eb023204755f48904c3381a3665c6c54fc8233c50e887a22ceebc652303 +Clang.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/05f37d069c7d59ec245d961d0928cb37 +Clang.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/3b0956fe770fd9230319bfcaefab4922f9aee3df3e8516edf81cb7d322132ee9ab899af4464c75b1042aa99e3bcb07ede6de5646bba2a57995fc2eb32d4d0861 +Clang.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/md5/0304434211ff4101a148fcc0c96455d4 +Clang.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/sha512/a033dc589fc95e63547b7ca82964116bec33ad6e78ac131934d4bb16988756d36c24d74761ca93b0e47dada1f3d2a63071cb3721ddb9af457cbeb164fe5f0f54 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/4e5d1064d90f24d57d63f08b61baaab5 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/cbfbe8b6f2be80e59b69d25d6af901ccb4807b12180208b69afa7223dd7d5249255265bc319c9402a1b0d1f0995940e3e72d7ecf1009f60d83021f8d35626a46 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/22fead15b4c45398ca869821d04ce015 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/2ee7a7d3f293f7b63c89bbe3b541722c502a840883804ffe272848f4ac99b7a8ed350ebe92ec434dfdf03d1f4a5531c1367859f4a4603c98325abe5a0ad71177 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/46dd01b10377cc3d45c6a42cac0a07e5 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/957677ce4251938d0c5e066448762b38a21bcce5ed424072ccd58085167d61b7e45a88fe32375f6bbd43dfb579b65a9afc09a886a650fc634a8fb9c81f27c9e3 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/bd9a61ea186a39162201341f0739fe84 +Clang.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/7a06d2a9ef20e88daa00d627d482ebbb6bf7223219d8b2a24aa60ac9eda24649d206b093d5bdb88b65c1e2b0d1ba0ad7dd927697e2bbac65bc9b42f9d14ad0d9 +Clang.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/60c98c6cc7d4446fb52b7585bc8709f3 +Clang.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/4d55464b4499a45f774e1000a8b015326d114103a3d348fb263367e5506ca6659444ea6ee2767712903757e83939cd446aff6fe2351438b644f0057053422b58 +Clang.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/90a512d1881c4af1f1abfd5e90e37356 +Clang.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/62d6d855aebd49f132d6470c7b0d5a0b965c6489b025046c1ea73fc53336030d6c5b4c867523a9206821f7fcf62fdb37ef0b7ff4b5eb04d07f40b65edd2c8e0f +Clang.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/c9eb9acb605d774db9636b82bf2e5f41 +Clang.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/96e1440b3b0378edf8907d4cf779b1c53d63f6d00fa798efe1b6aaa289135aba8fd00a8d6f55d9678136e9e07d0c189293aec64f46e66788b938e1f8e1fc2199 +Clang.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/5837070450c81d44395468d8e3671dc7 +Clang.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/0e8b674c0360f9586f03c7f5d0ffd5bc73dcde1e88eddf7d6360c1461adb8efffb104d8f454116a6a6cdc909973d0876745590b21009a9de56e12ce6e1c2e8fc +Clang.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/md5/5c198d35df5cf6435f4f5ac91a78be01 +Clang.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/sha512/9ba0a532f499933320145834aec2b57a70410bf67af649ed675f00aebfd59de7c80e6f5d19e7ad57029a573090e63c5eba4b42b498a374810b48c8668b50dcaa +Clang.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/md5/8ac88c856d946e29d1121426de44e6bc +Clang.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/sha512/94af63ad3fb17d9c07f5256e2d474effc0e3d5ef66f4a9f3ffeb9bdd8f1577c35e4d0aceb8b4746ab857d8f164141790ed494b7f687e644e040d2f3820f9e1fe +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/b4be546ff44019cf46d3250dd9a4321f +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/7ce5e4d68e18021392355359f59931219eeec3be4edd01f7a18b7bee499b589414bcea73820ee38dbc3b5ab12d912a93374b4a616b10ba491f5d41b6b33f3d9e +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/4616c348320d8704215d58c7268de6d7 +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/b4c21147ed21d41321e04b092d47f99338c6ac7d50b8328ceb8ae26d6382955cbcd655dddd39f0de3d3c36a5fda7084a33272aad9f6cd9585c87fee68be73a68 +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/bf9cf2efb938b68ac7e1560c464f9051 +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/ca29438393d393912571a96ce59bdaadcacbb329342c42a0de0e8d8ab52f69d4e6966822c0743d99b1a277c8715c1f72ddd490b781b45bd691df2c137ed42a1d +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/94138893eaaa99f37354317bc13cf7e0 +Clang.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/1b03d8d4e407372875667f25f74abdaac9be0b81c6229dc1c4c1714589efde6b1f8c76302a2545b103ee4f9812fa78f9e06e5d5bb5bc3903ce579328899faa2f diff --git a/deps/checksums/lld b/deps/checksums/lld index 9238ed622c27f..cdcae063f68ff 100644 --- a/deps/checksums/lld +++ b/deps/checksums/lld @@ -1,108 +1,108 @@ -LLD.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/3144fe910aa5fa308a2a2ca86820541f -LLD.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/6b60bac8ac870c6e0f2f615ee92599c863e388bb9a654ce7dc6b037e6f7ba77b4401f88471dcdb2c8418775a833a10b010bd932a61c4264b032f5bf42642559f -LLD.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/md5/f65548e0c2c455550635d2821822e97f -LLD.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/sha512/52862c78a5bd6a33848ce33c79eabad854a5cb86487ff755160f3a7c89ceafcc24773495ced5d7d25e952b7a7147969a890de6806845996a0dcb3ecd8c1ce1cf -LLD.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/e4b46d1b3397fbc876db8f0a15745f3c -LLD.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/831ae6748e0c18e4be6a732dee56bfc3b84383e7c607828f72ba798db0bc1f61e9379edb904cfb992455ab5ecc6d4ea7dae4bd8eba481a857afe6439fdb333ac -LLD.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/16d60350522a797fac1fc3ba47609d7c -LLD.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/6d457e4de4a896bc4d8742a9c7a09c334f9f0fee1fd5e93133128889c326cb3891d7b7f774a01d1936717639bc5e84b7a3d6d39866cd6e689de78cecb5934f80 -LLD.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/f55f1eca81cc38584c94a8db9d53b53f -LLD.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/70abc3cfdf7c94ba3cbc26aaee3328e28a5e19136bd659b619a6240d64d50029f94ae36e5ca4359caf1db79e13e6283cfd7b806e96fc3245586970edaf678a0b -LLD.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/e7370d074ce08d8de4aa6a34ba7f4efb -LLD.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/5491fdf2d478abacad107a7de626d0f70388568b8f50732a91f30a93bc79a683d7acfb37a2ee9dda39f860fd9af144b322400fa0152f52041fec13a4ac01f511 -LLD.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/f75f229860bbaaf61d8ab8d89745d5b2 -LLD.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/046bd2cbf12a3d381821f87800635957bcb0bf37d55bf4a8046ca39fc652c2b98ba0f8497216f6c580b738db319932e8610c6215b020e993bffd129f730a4d9d -LLD.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/21c591ea3725c02c5cc1ba861b435966 -LLD.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/600f590486acf10dbde10dcbfa728bd53152ee7134bbb68cc15f724017f8b5e50102a286ae7a836c197c974d34078ad8e8988cf97ef032ab97d9aeab96ae9994 -LLD.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/89770e2c5fbd1f36775081f37e8374db -LLD.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/650e5fcac1f00c2ed576d9232df46325dfa2e283976ec84a7cc12c8127d532e3b4d758a736e5ca1efb5a09833f0369ab44b277469fb49d50ee14ddd9ebcf6a8d -LLD.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/4e9b983fadd5fec3a2b76698fd24bbb4 -LLD.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/058bcf4a9cee81287d1f19e9bfe5a8d16ad7955fdf175ad0f7be6fb6fcb9177674b08a8fdc98b4365324e3c754c4b957aec24daa8c135974a2f2737a6054454b -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/3cf9661e272471213ed27d70a28245d5 -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/4c2b7d02bfc73e2c36469b249bbdb9e6e695b47a464a71d5eca495fbd21fae35bbb260262771246f995ccb83ba1d89a5946d76cfb49de327f659d467ef3b2d93 -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/432800b0bd1fa328c929f24765cc32cd -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/338053e5aa25b4cffb10ab2064b5e1e75ca628cfe006933bc125421406a00a1b84386a4ad027fca75211bba9860cdcf0d1c1e992752603ada97442d97cf17f20 -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/067465123a0343a6c9d8d9cec1a6c3ee -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/895bc632e732086ac7676e9596c7a6ebc5f807fb49bd2cb542252aba76aa4faac8e7bc423681e3dd1556bac5fe5754a5e09490e2f97e40e0551263d021987290 -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/27f10a51c07df6550e9945913b8f40be -LLD.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/fc8fb0dba3aefa19098c3065cc0e83edabf9a3052691c6b3fac229c0b0bd605fa7062ad4f117220e51a6f6c15a0a6385cbdc8a2d8a0f46f96cd637fa134229de -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/5d5719e989de5cffc156955875e8ccc8 -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/71ef0800633546b4945d460f51ee9e042bfcf4d0caecbd658033199ac82bcade9efe9749998396d42345c914621f658b3d7285c849f554d369acba8c7c75ed2a -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/416ed355013ac094d39cc8bd6d573917 -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/a8d74edbf881b4f4212f22c01bc37e82dcbbe0e9399823604ed1ee78ab33a5cbac5e13933348878cd7cbac0077547af27cce80becbc5a2ebc6329306c86f45ba -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/68a609cb681b1fa2d7e8ad87ca31020e -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/6cba7cec86f914790194652fff53996458db01d26b322d2e76321273d425605d706d631141f2ae675bbc44712f3761fa2a90874de13a280fc2cdcc98eec6e0a3 -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/a3e3ae95dc0227f6a1c596b42fd5d6dd -LLD.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/e8a7e21ef3726353d15d1406cb76ce2e79de7d59244ee9c2dba6f2ca9255472dea28d9aee68d4d806f0a291b9293a3e3548f791c06b3461234efa36eac1ed356 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/1e43637c4e6ce02d7b2de3713c028067 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/820eee9280781fffe5bab8464294199389de9a6000cbdb2e3f8ae3d2c474ee176442b128436cc6edb414eda06ebbccebc4277b3d0b6b4a7a0d4d232e18593eb8 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/a61866ddb1da3130bc2c58426aee6b05 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/a193e68d3ffd1794d0107d4f003ba0ad5f5e3e72fcad1b6652c5487cbad57d9357311c8f14a8a40c2c7384042d768c86ba17f0ee5fbc3439435224273ed2cd3e -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/e72ad283df0a290f1eab61a2037031ad -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/99d04f3f27fde19d1e61821dbc3d1748e6687899e46206c99442fa9b7086f8ade1199c67f16cfc5be40bbfe37da602508441a5269ea741186a79ea1d221a58c6 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/bd08e53b82b168fbab8d97e9460ab9b0 -LLD.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/408557a99ba6c794eb8de0b0dcca04662a079f6af2e7a663075b8f18eb422006235650eadf32c3abde662f12f87019cd73c5ae759207dc11101d3f1c3b8e2d11 -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/df3bb4b61144f94e9ca0ffad461fa69f -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/e9ca992cd148026fccfe47b1e8df1bb8b60e7e44341d664a3447c06030dccf2a95ffd281b9c7346524cf87daf4e72ef7defcc1233a3b5adc228adb5b20d5d911 -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/3b6879510e198560d65d29f6cf238b5b -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/75a8e70ec5071fd41031ca96e1560f4471b6e0c45ac361d10f11e41c9e63ed41e850170f5b97cf305d0e28ac695b8a86d8d777c7a3582f6aaa7953c00a666fef -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/03eca3b921064050532b59049d2da878 -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/b7ee2af9440fdabe72005b84e05d05c28f2736135df63859f8d6ef7a10f622122d3f2d0a393ddcb39bde21ea8fbcba4a99a46b5568e42dbff2a505a5cda79e94 -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/cf9ce84e5631259776238a11c3528901 -LLD.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/b64f0b0e2b3180b569528479265f15ba2e44523dc7103af3daf82ef6b9087c2859bc378d51abf44ba10c6e10a9aac4498b43797d59ef3423de1f652beaf8b6a9 -LLD.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/a85df5a842c1ad1e9db959fe8fcc39fc -LLD.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/9f037dad3faead898854235ed48804607e19a68e4a34a28e1ea09258bda9b06c1be88de4595bb50b43234e438353db00f47dacfa0754d88e8fce01b637808f47 -LLD.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/46191b2a25020871c8c183d6f62ad477 -LLD.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/aefc623430f79050ef367edc394c72a09bfb4ec39c6ae4e31775d378d1169432695be1fef5bd93737502465363571c695f7a0a7bbcc78d78c8689a0a6b0e280a -LLD.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/5f034672f90e88a30ced0ffa0880e8af -LLD.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/fc8a6fe2f4e1a6ccca3744a4cc51be62ad2c849e9ae942e9c0452aada0303e95b376b55c951e8ffc22b65e391bbb182c977c979a8c50b50c1426cf84ca8073e4 -LLD.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/157f2faca0641168becea6b1493e4c36 -LLD.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/6981bebe07fba76f18e38f30aafcbf20325dd5a3f158ad732ce1d4f153839eb45966e707e0cdd008e8e739454f10f8dba0a372b0e67f7e753ed3e84ec47d4003 -LLD.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/de902268f693954466d62a154a2ac490 -LLD.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/57eb929a0b21d047bf2a1da287fe2038fc9cd26bab43b013ad8794abaeb387a5be0eb7d4f9ece52171609d9b74f1aa743c6cdbdbc1eb78b425e42a1ffc862133 -LLD.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/d11bbc63ca2635836f5b95283f6f93ac -LLD.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/e8b9c2383f71be7daa2afbb0a6dfd6487c832673b3272b2759e139299491374c2c3e8ff6db71c526dc0e71901fcf81fcf77db4fcb9351dc1dab0315389cb19b7 -LLD.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/8ad1aaa3ce1bd9b3aee584b6494ba6b7 -LLD.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/411d563c9856cde0834b4f035551cf1b0cb0ed853365f312889c8d85ff6e52f5470e7e9af5146061516439ad109945caf651209153db1f6671a4cb31b69abfa1 -LLD.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/aeb833592bda8c92781a9417daac1c7f -LLD.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/79134510ab99d8478b80a9a14dafaa818320b9f823c024260b6f8a82ea7ed406424f35fc9882e4590a98565098a949f8ad01fe03aea2b8146aa22827a7dd710a -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/db979fa556737823f4629c1d19d45adb -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/1790dd2098a07a31d3e3057257da0bb9d54dd71ee713569f9d15d35895feb143e22435eb1581d72922ff09ac5b733e0a3053aaeb2f31483e4441d7ee12bdffb9 -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/63811a8ee9ec2915aafbff884e8ceef5 -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/b8f6400246382ab9288bbc0b4a50cbb9264a8c0e2e3e9695580577df8460b7de015a0628ac92bc54ffa14bc7c03c86ee1e52d032d423120d4c5c731b8ff07ae8 -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/29e840a97982441b492bb6e9e30b369e -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/9a7477279f129c4c500694e78b0f587285e79adcad167da212e68c46a22c8456ef41c721d8332c7f101958cbc3ac055414fdec935e0980fe2d0d507b1bed736e -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/97bfb5e23744e57e243a9b0d3fe4252b -LLD.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/394db3828de239afa47f6896f0014900146bf8e5ecb90014601aab86fa95dba434a78a8590ebc588d3a22b93ff6481587c7c3458dda751114a7a4b41e93a9a72 -LLD.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/9dd9fdabdb07a2d25270cd936e8ceb47 -LLD.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/ffd59d483f969dee28e32166a8fe091a5ecfbb56d6c17d44c732f6f8608b14d29b4e3874d93ec2dc8563b9a4dabd61418836e6dd389aa0c38a779f527becf48a -LLD.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/md5/574c37b28031d6332075b7ce3e4b8520 -LLD.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/sha512/f09afd7098a56ef282ef364c59a2f91db51165d9ffbcbe63f70f68999c7bf67d6ee445dfde789be79c81e173db346702d983e03fe1ca51d2a2aa3cfd9b9e9e00 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/7bfb0b6c0ce4b271f3c0e7cfca20ce79 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/66daf7d38f206d428e27227bc1218bb8fe32abdc50246ba6e49ec1494c48b5217697a69e3bff51b3510a4383e2ee743a8a0ad11aedbaa895ce8a56016b5d7693 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/f2666afb8179d10cabe3bf9e739a0e2f -LLD.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/fa59a23c4b24c444173454da85e77ae4a9aa73ab91b64efe7a6aabfe21c92e4909ec61b7b848d4b0190eb5e4ebaf0d55f8fc0d92cedc6ede76add230b8e6caa2 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/292e0354262b845ab359adf298aecc6e -LLD.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/654331656feb9c4fc27a5a06c838ffaa10ee7f74ee7eb98496e9d8d0882ac2416cb8662b5ac70968d6e8277ff675200a19c56989c120caa83170707c409e0cf1 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/c0b864d0d7a830627cf0feab502eec81 -LLD.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/72404a586c46b62b0317080b925ff5fd2ea99212df50fa6631bdd2f01bf805bbc8afb2e49bde16a4b8ee7896af4d58237326cb83aa064e98509e6f4f0fff46b1 -LLD.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/942a23af6c179c2715f2bba2048fa125 -LLD.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/101a6ada3ed831dbb2f580185de732b90b81ce1b6ba544fc1ace40857fb471e61901a782f467a2077b2e34952997b8d04c841aa4e9f190e1488ce37c5f6ed32d -LLD.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/2f0aa6b5220213d549a2430a439094da -LLD.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/180f0a520fc9089ce39ae8f032d7b415442c2ce6bc9a44bc427ae98000be55d0eba6278db1e89d45e3c79c907a75264bc8185cea088d002aa9557fe1b047b42b -LLD.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/6206795db1db9f9a86346ace421fa778 -LLD.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/b86c57b2561cd8fbd4eb0158b0e3f4064cbc55936546da6dad794818eb93f51d80fac1dd094b2281ed6125416a205010e2edb801fc347db8d02d93fbc336d878 -LLD.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/e07b22829c2e8d4efdf8c41584a3cc67 -LLD.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/4695f44b9a1b21684575f58dc66644907f7fd5250db42da2cfa55d90a4d5dbafc9cf37698750f8faac45ec38dff54eb382288052b7c95e82bfc60a10136ae5d2 -LLD.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/md5/3e183403117e11f6c4b9059fb32e4acf -LLD.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/sha512/34f6fb23cc234dee826a303a8ce3bf17ddf945c2ee9a75fca4f6c625379901d5fbc4d5d9006b63d95d982de852fa1594877cdbc9451b0ca04ecac72371d1647b -LLD.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/md5/40b50d3ba65160eb842bc43241eca5e7 -LLD.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/sha512/8cb54d63bcfa0ead6b8f8583e3e30ed676df4e8042b8a40f94aa443b1de211cab71ba4ab36ae804469876511641aeb5cd29e1843adda9e09e7b7e30a936c12cf -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/d999ad0a4c62fe11037ceed768cf8cb7 -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/3c43e7eabe62f5a71d9b2411def56d5357a23ae50b639bb117eb795101f10ee896e886040db0f57c527873f07d68b49c8eb6f64a362419ba4d6ff9fbd2ecd9e3 -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/c2a7d97bc3b45591329284f55a821c26 -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/d53f16798e8d19359ee6c86e9f55135838b2db78d2e69a2b0d01c92087b9bf1195d7cdcc9e2eb5c29debe02048af6b2d7dd83c0207600143c64b5dd8be647ecb -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/0a6eb0fb8f794e4ab1ffa0ca94e69968 -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/9d1b5de37206ce411db00587a0d9dbb3d57c186ef84d2d60d20dc0c7718621bdf01dbf090ac1d2e63eec595e55fc39d9787d038766dbc0b4c49708e1b16bf09e -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/9b2f4c2988b177ac0928219406d5aa21 -LLD.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/199bac9c28bb919eb1caef1eeeb5a935183a134be3def03f401794a2241b05d62468ee9ba12836d07bbcac508304c50c4c7f34d108fcb505a69a46a0eb89c6d3 +LLD.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/64c9a9f1758b9b292e0a3ef37f16ea41 +LLD.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/cc740aaeb6ed29c56b2881e1488606338e4bd0e049ca4a5b8312b1d9129b778224570336698347e4562d632db9049e0e91ecce34ef68acb23a8bbf62455a81cc +LLD.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/md5/1a8e11dba5cb574cde42de2b9703ff79 +LLD.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/sha512/290300229576bb9155fe6bd24c0ee21beb41d0f2a46b208ab5a657b0199a7376c1f4cb07204c8ee1e6d202efe30ca040a6fff63c69b174120de3eb9866e344f4 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/cea134f347bae257cf5f55b6388cef81 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/16b59143e929791b0c3e56cfb4970d8b3c87adf6e847fa9e2aac17c4ff2aa311ba2c7511c1b0ae2f39d9aa92f87ad4d99c042fe35bec391ac865fedb72bd3b1e +LLD.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/5f903bab0e38fa608e8965acce6f020e +LLD.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/01e5f6a32958e04174c545f57c6c3b1bc88ccfd5ab18dcb9d67b92b55ebc7655a03bf963c4eaf7e5c3792d4691427a89db372e7534c6c8f965f8a715a32d9284 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/241a55374fd067f3736a2bb929e47015 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/f1fedea4e6b5f6f3bbf4d705034d6c51b06f011c2ecec1ae49c5b7bd123891eee8b991462d60be7fffd58f7c773afe910a06ec0b55b37eed9b4d09b9fdbd5068 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/ff018c7448a7589935333e46739ee2c4 +LLD.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/b646c6a945b8f42b396164a8e87fc2e54b1ad05681f438dfba83fdd3712a60167aaffcb0300bc42d904eb4bd34c002a71642b59540ca01e64d6fecc6daaacdd8 +LLD.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/e6ee9423a82322b9233cafb1c92eed2d +LLD.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/c915582a9ce2dfa8721741fb1ed19b719ba40f0092c2d29ebd68829ee558cef0b044a5e40985cff88e89129cbeed052d85fa5c6b6d87f9b3a68a6e89079ab4f3 +LLD.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/cc55112e2db358cf26d7bae3211d8e4f +LLD.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/0ecb43045419020eea911f1767dae23a6b1e81bb155ec493e911a9412e45f7ec71461aea2e6fe346e641747139cae43d9435ccecaa7fd6a234e4d69bb06606ed +LLD.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/498b2909f80b20588135466d5211bc80 +LLD.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/120fff24e85cf970670b20b5f4509475a3ae0d7621f8f67d018f3a7625548d736a3abc89f015966b1329c6b0a08a1db832e035ee3bae384e2c5864b73a856600 +LLD.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/1bcd298d5292f8e51f19b97fa4b27ab0 +LLD.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/695c42557f9ee53b2e10bbf74653fbad4d02124b962a1f50cf719d2821607dfbb9c1bf638dbbc9e0e544f3020a9ef4a82decd13f886cc41ddf47c07a5e40eaa1 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/2323ff933feaf3754b442bee48a63607 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/47b8e490b89e04fb8886dae438e3ddcd53c4e98045de2b0def3988671827528c8e9ae296411464c0f17cc64bd3956644673f47a3817237f27e1c3ed16ac8ef01 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/37cf8528666064a434296f2e0039e9c6 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/ea1504a859509f8a16030db7a65f42f0e78d67adf5946497f2178bf25456c0f2583af72c636881a4bdd1210dc0d377bdf300ef55aef5db8c56995424a1886059 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/1c341f2b161e2320d3d1a74685887f54 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/4f6fc099293deb1a2cf729ea7edd6e17fea0dc8b9fae9acfe34e00b1f5c798933df9538c805c8d28c6279eb38f9ebae2a1aeb1a2f23087352c6eeb3b27b63ddc +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/e306d59c71b0958c77108e650fac2612 +LLD.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/79fd7cec0e169a9555ec9b0acc3248991e2e37a1d5bb422808ffcfd4f47e79321560b7985c82dfe070fb0b5ded5c160d83e358399c6e7608eeb62cd4a1406f88 +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/c1d080f1aebb58778d730578fb113290 +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/1f420da1897bd0a61413321aaaf032e8ed38d59e6dfe3313ca3a6ee6582ae6c566e3761ca8fcd1f5a964337ba8a9b3e73dc55ad68aca139beeb45e43d51e862b +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/6f4e0c7d2fe9ac254650dcd2842dafa8 +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/bbc71b334250e5e6429766d88595adbb671a206630987ec2a27e05711ff0f844487dffc1c136052ec11394e9d5c51c70d1b75d5348f97d3bf7fab463291e9dc8 +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/76925b9a7bc249b2227390c479c54f8d +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/20643ecb79732e3ae9666116dbd0763c18b808afa78e6a14998aadc7265cccd6efd28670592db61d3d27b8d3023be4c5f3df41fff9e1b38d61abf76829090b4f +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/399b9aac140d9050088fdb187ed4645f +LLD.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/8bab65965670fe392e78d0b9dc78c92cdcf202898f6d5a3174eb89ca5cb95b995675c8a7d81bbc4e95e490ad1a43d9d29d7907b7006789c0143a1d8f24cccaeb +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/026a4f5ae9eb3ac05e5e8fa894d77a5b +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/4bca8bd558619260cddf4e2f4593cbb2a0691b5ccc6d1dea6dfcc5a2b5f51d7d1a76c35e481244e211e2eacf32bd628df5ad0e6c75e5185bb1d9b569f6acbfd3 +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/f898ceabcba052b7e6713a2b2c208a92 +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/92be1910f795390be5f15ba5b2c220a3209a5f7ac04fca3f5229486628bcf5d2f20cf6e4dda8b41d6beaaff42a68a9ddb95fdacc6eae33b9183b581e9a194895 +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/e366058cf69a4367945bdba9523f2a0b +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/45a786e8d0162bd5bd01c029691d2928d3744ef4a7a1efc2e39755dee2f9a9ae23ee725f0454ca601cb9c082a342209e9129df851314b5757c74767b13508fc4 +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/665a8502170729c86ea95a7ea2fcce0f +LLD.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/c1a2a85c9ce14af8c91bc9a599393c52c0b8a585057366b1ceeed34c5db44641ecd0c9b377bee80cb4951fc7102fbb4f21fd050126bfa5bb4e582ffefee17035 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/b90b2130262f63f5189cc8e4a65e4433 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/c1cbfd38c82d676c3fdbec486691334cf7bf4115d9ef2665012b71725c28545a49f34edf5689ea0352822c811c24c89cc152d1fccd1586b17ae8e6b2503641df +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/2d5360da4b2c9ffcea5d0a646a7c114b +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/73323e0937fe4423883480294c8df44744acde4f47380e35535cbe69c855c0e35e86a1eced3085ae0285f284f47af5ef237f4650bf2b6a8b9d5308efce88fa02 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/a9b9a65938a7701aaac6fa706481c867 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/fe8243aa131ad8be54f0fca5754c2e68ec39049004ec8feed499731c5228a7a46e303ba866b9f9a55e5318c73d8a46d964673e111f6c60e5ae1628c568d7d894 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/0d9592a287c9231ae2db65000be2cea2 +LLD.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/4ee192dd33f518d2735a829ac8f822b5672b39e8c2254987aea6e5f2f0056213bd85d84c4050d52ba9ac8c35762521c324fe2d6e18db0396e7142af9cb61a561 +LLD.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/d487598dec9969485dcf785fc0968bd4 +LLD.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/8d3117739919696b9b0c9ae398f1b1e9db8bd3e2e27839f62b3551c22ae2517f8abb69e57e23d125002bb466889b7352e69c1e9dfd9abf1c5433f274e928b341 +LLD.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/943434b08dffb54e8cf04ae7bee34923 +LLD.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/77b7bbc5d988cf36ecd10609e091cf24dea134cd32c7ee96dec7bfe1a4942553b6205653edc16c8454261f621966daeb267f42562172bab4cec9693ad733d867 +LLD.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/cb9e371947ad415de048636ed78ca48f +LLD.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/c00b696fa146e8c29b37f15f78ab3325db9b3f5b3514e615f145b4eb7c9c8788662cfb6255b7dead596cad8c576b378f7459c2c85d462b597ba5e21adbac0536 +LLD.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/485f061ee8425f042e4dd3042388bf8a +LLD.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/845a47a36c61b305bb70b1249f6fb7c4e8f740acff90d3e850ab2e887f7d959ae263431a02305bf7587e4194463f9932769d500a19709bc479eb6e6168325421 +LLD.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/f234526410e779188f3d22da438a4926 +LLD.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/12e2c9fc5385ff142bf82956268230fb01a6f1a1fdb3a6c1e13afd341dd2eea970b707168d5f45960dc9ebbf6d6598af0ceba371172f624ae823ea1eef4e9031 +LLD.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/e68cab4aec1abcfce12a13e3d1f67dac +LLD.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/67755b34ebe04f4d28be3be2a37df46b5e900f38dc4908875f66671fbb740cf033f2fd9af5116635f55025f330f7b1a478cd4900db9d00e4699b591a16269100 +LLD.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/4a71aef80b75b2ea1a5b7f8521afcf5f +LLD.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/9deb3e9615ae15dba8c744b22416243304d30f100c8d17538fcedbc18787147505f74ecc2f933fc54101527847503142cfe84a46a95ca3c57987996e3b8583f1 +LLD.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/9b28ee75d05cbaabff57fd45cc0d1cf7 +LLD.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/bfd3d6cfd4a5a2fbfe940f64d47a86a598360e90619f8175a2d1306f0894610f13fc44ba099ad59d2989beabf491df08a5611bcef3fd61b6391ea0230b11a432 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/7962fc6f08531f0dcfa44bd667f31582 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/2c936064685f12ed6764c187192023118e97dcbff6ca1656f0304a40772b4ecf55ee0296b3c2a00760f5bb437162e2b737635fdd59b889d35756d697fc7e6b72 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/3eb4d78af670d446f696449a5e71e3ba +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/315dc76799f3e443fdb5ebbecf96a08070f8251930a26995de892b8e67bd35bbb365f2cc5fd93bc7cbcbc9edd08280ee8d2a36b28a704866dd3fdddae4969455 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/e73cadd0354897bd5bb611cc1c027858 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/6f444a4ea22e7108ab75686ce9cd78c0db0a677e39e8434896fb1ec90b9dc013abf7de1024d329a9726dabf229a8a68c27a11f211092e676715d282efb7b8504 +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/aeb310f106f31126dbe53459e36d33bd +LLD.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/cd18c115415dd92bc7fbb5c29cacc5848b1f3851c3a526ff9c0813ad46824df0a4f13a66b1e6641ed11b44b5b937390619f01666fe6d5a047f1772f0ad03c941 +LLD.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/300dc28f7af6aaa69cec9a214a57fdb8 +LLD.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/dcb40c5934118c204968cb963a3fae91179eb1e31f5397975ca98c8a7aaecaf2a7f81847bc426fd306bb76970794502ed4f94d8f461b96ea90362130f44520e7 +LLD.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/md5/e1f23fef82fbfcbc28899677f12658b3 +LLD.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/sha512/b6b585060832d53827376ac6c00cc8bd5dfbf091c38c87020f6de42adc86dbe4fc33ec2c17f4433176c79a509681d694ed1502b179efcee2c4dd4c10a26e87a2 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/5dc96eef71dc28611bc998ef966371c6 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/781993c75bb07db96d02b5a7e779116864730a9bb941b64420a435956a7ecd501b5b2673f1854c09ece5f0c73559d5723c271d6352be57ddae6801a695629362 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/8a1fe0ccf7699ab7a7a514b620112a70 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/d002083045d3eb7c749f2e97527c1228cd317a8138ff254228e43594a6cabee47fa363785466ebc2874cc438457640ff08a836eec7334afac451506ea7bbed03 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/331be92bd3d76bb8e86991b7832ad41a +LLD.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/7b1c6df53311a17a92a41cb67ec476f947949c4ca5d15a643badaf9f01e76a186abbb6e156f95ad1605d83250df4e081164986a6b7fcb3238076b0ec5a3bb565 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/97c7f5267ad6927f699a25ce44f55a70 +LLD.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/7b847c6026fd7daeb17a4459b852562ce6664b2f406664be672bcc384dd5a79b9505561fc61dd8fb78a903a2ed4978f322cccad19f5a3966bac856e877c11ef7 +LLD.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/c86da6a396fcdddbd26cfd71c0f70458 +LLD.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/8d5b75b43167080b8ea456e516c9ace02ee6066ce715a56f0b42cb8045b965b1cf8d4ebc0786c23be4544693ff858816a6257b0638ec11e077df32ead62f7efb +LLD.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/d72e175272ed893688d18e868120c575 +LLD.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/9a46eeca8c7a8be65ed487a74227534e08a257e404814c44730f12a5bebc8cd160998cfd5ed30189aa606ddbe602e1b1788e465e4a210103c6726a7fd230abc3 +LLD.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/0206fdaa9582ae3bddaed1b6fd7a8cb5 +LLD.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/584a67f603f656ca5d27aa0ef2e425ad385612aff06cdc1d534b5944939a09246c93954fc153b8a89acff721e657a8903af9a640abc252d4e452f348781bca98 +LLD.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/0dd14af342467eac2e13cad4acbc881f +LLD.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/918f2c66898f828414009fa6ee273da5bd654e4b787ebb4d703f0be27e388b46870d68bd58c4f45638d276c61c1bfe2f3c67fbf34dfb5578158d072f82d927de +LLD.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/md5/b373e1bf2a24f34496754438e563a5e9 +LLD.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/sha512/a739f29e332be74cbcc544903d08bbcc12c3e9f5c3d02d130ef1c69426ead2c74b14f98ac79e88ba29fb2e2dc3b28b7d81c9d42f2e27e0ce9442f6a0e81bb8f0 +LLD.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/md5/1fdbf6aa0751788611054f7e98024104 +LLD.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/sha512/2015b8e84642b2434d1089908354b47b080d5683f1c7eb2c09de09abb3674e7119ce4ecfa858bf8129fd9e9075bb45f2e53a997421f2457aa9b5c4a9d7edfec8 +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/85bd5a9e312e83a09fa5b7fd6abfba76 +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/0a5cba5c65abc72361a780f64e64c463797aefe52994699d8d785437b773530e49a5fc2746e36bc5a31aabf4eb4343870aa448f8fa2b119ede3e1c4ea228cc9d +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/ab07ed76a796d86cb6ac2ae4fc563eab +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/485117c7e1daca401c1cfe77324e8f5961f6f33ed2a3c907f4c4a2bf9c45c14d929959cf8e4d9cca9ad112a3ce6a851e336cd793bd5ee284c87b9fe487700ecb +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/852449a26af61d8554fb1b4c22c4384a +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/a080d2da5ff4b832822e099f150f0c15b985d54678a9508711f7f435d6ceec68eba12b5f8c25db0b4841dc5c5edb003b74b4fef391292b9407d7bda73d35c4f5 +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/eb999bcb67f789b6443dbfe907bc61e4 +LLD.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/811f72ce250184ccdfa30aa992884f1bdd0a791fa125f089037bf1af45b844d76807c5662a904ec9312b79efc565fd0957f195a70a39248eed99ff53f3284cba diff --git a/deps/checksums/llvm b/deps/checksums/llvm index 22d86ec2e009d..122aeb9a53337 100644 --- a/deps/checksums/llvm +++ b/deps/checksums/llvm @@ -1,111 +1,111 @@ -LLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/db3b242aac30d823cd911ae3424b3d7e -LLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/5efe8bad36e748ca1883b23f5eb6da416ebea77f42232e2de9268d9aa92af868b2a20b3c9062f77e734a58ae607b4dfb134e2f8c7879652cc643802379296196 -LLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/md5/640e9260e4b4235b9497720bced5330e -LLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/sha512/b7d193821ce8de809ec4c3d035ea1cc9b889e2c22ba0d263d25b8c01474a6a353abc9c9b8bf8feef686f00cd6055f06f20cb3f5b85299cc9764fe75c7b3fb21c -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/898954f176232716590f3c885af8c824 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/8251dcc31ca7d2c827ad73668d9e422f777a219d444e9e00c0a0e16b895ffaceb266701938f630d4f354e3ded736061be69d3398f3810dc0df5b803a508bebc1 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/860b7b3b26e3fa5ff2d1c77d087cbbc0 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/4c4dcb47f952b87ea506e6c1cb07e1b978dee4aef14381e78ea389de728d49b351c401b079790a1d1f8145853840d019d02a906a39f3c1edb705c8cf663728f8 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/9cece7e656a511fc8f47fdca094a2695 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/9f918e9a4b552911b58ff43e829acc8355904fd7f050a25ba9e08437b8f7585d48bcd842c79bef756d2afe83fd0a690331b5cb51fd55a2bc4bab7e3c615987e7 -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/66fe8bb24feb2779828432e0d996381f -LLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/090adde3f779fd56815992971a532dda793d3ce4462497daff66c065822834821eb6a0b9575f94241a760cffe4cfdce8b7e8a2b1acdefcbb62fa9db55748ef71 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/b3a1eab6dff60e4c9dc770ef1d6d108f -LLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/eacc5a3fc376359e27ff795f63aaca0d1cb3c57ca0dcb27e9a43887dbcb6a2923b1e9895ef0c0fdd3545b7edb5cac8598515f464c27f5eda25dc65425f5e0c50 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/047ea0fe65332c30dda16799e7999185 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/c62949b9e4ec97f372d3d9fe7bceae923d54db5afbc0902d74b7ebac66dcc1de7d7ba12b10b5028aa1489166cf06b30fc2610ad84bee9cac95b08bc7b7af7f05 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/0fe165f62c2fee6dc0fd3167c6da9ecb -LLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/9bbdf63b00ca88afea787069da2c64ea6a9478c2f929bb540fec5d2664c19249ea63a5b69d2e703605ff5bde28a029e5bcde1470e859abdb1f0cc8da960065d3 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/0f07d3c14e1bdc435a9c69431b354c51 -LLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/f3f572dd805bfb14713a6f4ce79e91c3c9b2fd7008ce9f4ab1e2a55f0e88b192f48beb6ad3954b531261ecdcfbe8d26cbf931057e43e472ea244beae87cfbfbf -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/e7b10dd01bcf10e9c3100c4edb5b127a -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/a86a213de97ad709fa2b0afd7a2103f58c5292bd9e1f939dd79fe02574065642b67823a0b05f9cdb054c5b6546b3051873c67c93bad57c0f53b8327285ef97f7 -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/480cfee009635bfb78c164fa10745e36 -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/414af42a442224f780eb6e6455483a6a210250d28040138998ef01c57c63176aa77626ba8b9985ad9ca9a397fac5c1a8abbe0e173a585d218de8b036cec96f67 -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/1b6e3e6fcf6b20e824aea1b3b510f989 -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/7370730b97875e1f6b8b3576d68d0d4a3112ff7be66c8f04901f905938cdb495b67f4676f03c1e6f0e4f9612e2849d7a9f02a932bb66354d007c2e4cfb8fad99 -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/24bad94fd9ce261880ff589829dbeabc -LLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/cd52c2c036cdc7d986731b76324c0d241fea9d9deb3a94963b5efa01a1649042c0ec062e2cfc6c27bc747637ace09106238d07aab0df84c448755a61571e6a68 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/78273dd81559e0812eb497c91bec8279 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/1b28a9f2300d4777406d125eee8fd8217dab7ee67db38334cb0f51a749f27baa370d6229c4396f12a63dae210c0d772b83d79feeeb6dc17f19184832eb15859f -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/3a88701757a155ba35cf911b1ad6528b -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/aca7a33d28e1ddeac19d9c99fd2ab81268a23d2523df7d300c8d1999481902f7aced3e4615d40bc7257d38d10867a8440d9811db81300db1784b2515c3bc8fa5 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/3be9234f6718d0684a40fe089af08503 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/9acd3d69ea99f4e660978d830ead8253f8623d6fb66aad0c79db211f975f42b58254b7f47e284e751c94609934c6895b4a2e662fa0e8ac8835cce1b60e653ff4 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/583608958fe5159e105f349f73bf9a40 -LLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/cc574e3e9f457194b4ca01e63a6a55d46f72780833b496f570dc5b7c1d85d751f02093da95061162a8d66b0118a1cde677751b32e53261ac0272d540925fcf0e -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/3318c8aced1cd7dfae6cc5722c7ff590 -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/a202552fcd12c6379cda41a235be1eab46b7ee2c28b4cd9c9ebc581a5ad2eed3f0c54d7ed861c9045272ec04d598707877b6b831c5109b12b4d2de80ac53bd2f -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/a5718bc977c437d3268a8e4681d2adce -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/45d053db2325ff637edcebb60167e948f42b7a6e8e6dbb14b2b0785459e06667ee42c1e01b13ed9ef09b51fefb0bbdd861ad59a3320f76986fec60129f937cbe -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/53f2205312d55810fdbc1fec961d3560 -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/bb80a8003bdaef7da016138f99e8c53223642a9490c01b55ded0d02f6dd69c8460df11bfde7cbbc5ba1b3c331e2d2e6a8c6f7ca83aba20112bc0f56ee907802c -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/737492de94fb15e377789aafd66e817b -LLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/2d31da6d69deb859513ae6db6e3fc5c2bf3703648301b1c520154b6f3aa0eca12c8290026643384e40b261755d8c3061c02d685dc53f5c14104498657f52d167 -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/99a0eac6aabafb1edf3bff32c283dcbc -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/f65a01d75c3330299584f8eec1d25f54d89162e5359a7dfe0f73de76aaa371751d3e5008a0dedf5de55ac0f29613f0f2ee1d9dbb7f69871dd0e85e047b44b28e -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/b8947735e7e7f9687c9fd97c72681e9e -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/a6c699b0994a132867071f6cabffdd6bfdb51eb4fe7e5762e836d420aa7d61a5165d899037df2470e9cdb04bd64c4c153ff83c49e30f42a120fd5b5090ea4fe6 -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/fc3143ac4c492cc2041d73556a84897b -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/3e7f3281b0fee548a4135893be999456c39aaba04644f4bb55247d514257b3700d36fed376fb1ff7b3ef5546a43f791b202a2c1ddf6f924a63730c56254eeb8c -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/38f9a63bd7b6275e4cec5fb05d2ac163 -LLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/b7a131e2d1838cc3dfeca08fa8f6b329ca714e909d35bc6429952e690743a321b8f2e242f358adfe719302742015306e3cdc1ac0ce5be613a36447e53292f9d3 -LLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/ef301dbee02ae00dfb6f3cdd9e67c714 -LLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/944849a1261b3ac3a5141fad55397a0de423a73f57ec6b8d725ef09b3233fa6bd6e76be4c8c4e77c80e3b60bb3ab135d8adb30760fec1d21eb699aa1868f9a09 -LLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/1777a48a9188895ed07163df4594a688 -LLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/e5226a9b3f87c63b32e69e43f96ca07c32b34742955c5e608be7843dc1c003b75e065ed5ab29c2a4144607df23d97852382d7fe7e25f98abaca2493200ee8cdb -LLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/e8b3d76ed47923cef55a71033f78ceeb -LLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/88825e210479ba2504892af2dd01a3f0a1488f05ec5df6b352fbe0d6d8bcc691fab0e3d3b31aad2b14eef860dd8ef5bf56e83647583e7c3fde847ec7a0a651cc -LLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/ad634b98e24aa296087aaf11e6d70828 -LLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/97bb219361efc3aa847fe53fc20669821466aff399ac47bb312af7d0899bc6af0533a0e4b490d74a0fbb3f5e3d0b91af23023109fc9a0138ef56630055e5792d -LLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/cbb4bed17e57832bd99affd1a01c5e9b -LLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/948dcfcb18eb1288f4d66f9d9a7c7b234956cb8bf87d6b52b7d639dac60360e4a3b9c808a908b2d298adebaa9b6e63d8df78c57a1b0ade613fe0da0921d07807 -LLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/c800bc4f0f0ddc5d2626512a949d9b79 -LLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/4e0c9091d580d8d8bce9d5ee63beccef52dbe4428d29fe5315891ce63a0115f4226029bdd68612d813829ef49f0c6db9b5681c83cd5bc70ded55541466296cca -LLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/4439c5a18ff9c3bda01aa989b5d7a1ec -LLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/5d17b2da2d2a218ecd866d9164527bf4762090effc908fb5b93b8f4125518e2925ca65b5e96210b3e2f77750f2a3e3c2edde8ccde3ab779561191ce7eab294d4 -LLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/9544f9d46eefbf593ad8b665a1cd73c6 -LLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/8baf49c6495221ac0d0a039bf7988fd4890cb750519b0e2e4b44e8dd504c417ff9635d66d43ecef75e3d0d397b1e47aad010fb91782286b1c26f7785667d58c8 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/8f46834c72ac617d41befe0abfec29a0 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/c131d322d45a95c74ad01bd35c094b5e30a47535c6cf5cd7c2751b99f8942c1cf0c27c6039b33050a4e140ef856d79c5878a81fb98db0751d43b6e463070dcc6 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/14f97547b230bb2774bd1bcbc9e44fcc -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/ff1d8ed1a479409b3bc611cef9d6429bb7f1118972340ecf7c5b8cf6db28a6cc79778e800523c655c334496d3460a93d6c0f42a1488dea58d8c2416afd0725d2 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/6cf4a661be00b3d007c67f7af80b9cc2 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/497e853d4b06c64a61de09a1216ac612ee0ae4a3bc8f01ee9b919a82c82706bc045f0a641c5a69547b68a36597c2be8f699f711f60d5af5fbf290421a4e76816 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/4e8db53272b73e5bf7c21413cebea308 -LLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/184c1cf3e36efdd9da14f6e3decd015268f1a0a9157b9c677877f600bcb4c9d20a7f37d6fb830b22012bb7cf05d7af86ff97dce046900c1a9a90c49b0a6c3bda -LLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/c06ecd1d4ab8e4fd73c6cba18bee9750 -LLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/eee12b4e551d21ad35f780ea8f3ace4b43efede66297e6941da78ffc768fb28c31a1f7e1ec5e11495d95d456ff2a929400984282d2f2230c55ebeea8005c352c -LLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/md5/72975355fb31f13f86be0afa188dc436 -LLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/sha512/9a82c8148db2c67c50255c70fbaa3c6cb60fb6bea700357a39ff5e59dc1fb615a13c647331b494244b88001b525d4cd61035705b2ce0e6590b8894797efcfbe1 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/04820df9e180b7008598eeebe49bb981 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/ad5fd5d96f22d67e3ada73b8f0deecff2df212a8e8762d4acdede62564f379496351659232fc5450d23b4e3b8a55af95f48725841233a6a2448d18d3fdc1adfb -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/59af89fcc77a0eecd7c9e8cf812f035a -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/a5c486b44cbfb41ef0623c067e42cfbc5216cf2c09f537b8b792aba814612ded170e6a99a11bdaf9f3790d4af06f7f058b6e7a66b2f8513a8522044a83007a11 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/b404077eea756a6c5c7bca8a54898680 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/70c562d603aa974b8143fe72ce000be60fbd975cbeee4ebd0bf29bb01bae2dcb8006e3774581d1e37fe221ea0432067d06a19e5fad963977990fdb5f1c0648e2 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/1437271560c205407a4a1d72fa3d0ce5 -LLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/463b2beede8289d4b6d3a39795fcf8e2c6007b321abdd7125cd56e2f960fb2b9c3f9e27e38cc23ccfa51ab0f9f42378f64ab8d5dd28a2ba452a3111efbd46c99 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/df1353b2f06a17506ef20e0315ac8396 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/79a696d86252b23dbc439284f8a2dbab5da77af2541680c569cfa11bc2b4c9ac03218b6a307841ae92aedbcad88573e800ad5fc8bb1c55b957a837a7e53da592 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/92b15d83ee43db8522be4b4d94b8aff2 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/ace2323208f16a9c53823c0ea8ad2b910d416d834e0731485008e4607ff8ed8cf566509172f8f65a8add0e7a7dd7391704246cc024eb3d40bee73f043481decb -LLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/69c1c0f5f416d00a3237bf62e6c14075 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/733cfafec656ac3ccb51dd444f5df028062bd1b3182463402105ae78f13675dd0dcdb79e1eacb5222d0942baaa85e487fffa01018c5c19f0f971ca96315f8073 -LLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/8192a6688c46ca92ca1706fec271856d -LLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/49d602a869ba34d560966f00bf575a04516476e9c147219ef7086842326bcf88377e2c601ae22fbbe56f2a12f40d4a9611259825bfcddf05608e73b2ceb363c9 -LLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/md5/64b59e6cf3c0d8cf09ca4d376b298134 -LLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/sha512/19a1a17ad7e95ffc75cecd28be4190ed527ca5ad948995e9f3491770e010c45ec79bec52d270abeab25c96846f604b694944f2eb4dc0697f43cf4e9f86f1efb9 -LLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/md5/3221c8c4773ada18489016d3167ce509 -LLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/sha512/514a6cfbca973e95cfbbb880323056fc6b51dd373a6de26e9628801f393e42011b4c21750d0276e562ed09fcc09e9751572bb9c4f362b8972411fca3a93c8f7b -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/03744874a951f038349d0179e752ee40 -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/83f34672472ed640a9e2be7eccc71fbec4d42397174dbc5abd34ffea754681c3779c07692d9eff30db299fa0c922594727f5d316ee2542baa34d081717e89ba8 -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/649d1106a8f95de6eaa7835f4eb66fe2 -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/4955cb0e2850542a1116fcec9e04e7f9f6633a806013ec49fc9e519e2d511cccd375410225eb8630d74b65fe0f2633ae7f46b194db8e9ec78cf7a2f12f6920a1 -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/d6a1fa15be0cde66ac32692561f2249e -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/48845cee32afe6ec3338b6abac77c773980093082d9dfedc1b9f03c31a5d940125e2c01ceaaf85d3bc06bb75e5871e24a51743b91ce1b5e8ec1c7f4eab4a4c2e -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/514a676afb3bf9d5a20c52ef3f1d4bec -LLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/ee2ba45c86b8a4cb5d2214b9fbc488176e2134a9c19806c160bff7e3bc796991051e04fc5d2829b151faa3dca6738f4468405b246f94bdf27cb5366b1043021f +LLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/341e3f0b5c160100f5e12783b8f779c0 +LLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/65b2c2091db1364adba4fe1e4ec6b9d6582432a0a0751cd0a3aa1c69798633b3aa5ff09d3de4e47d552d55d5ba81bc86662f1784cff2ed58e800452488cf9d50 +LLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/md5/249910dce0a9ee089711b71626972b26 +LLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/sha512/1eba4ecfefb56a00390e5c528c467f921d64e9ca40f5fdb4d7fe0d7ee995f03d253887f7fe40ee285f03b12fa7a194543d18cade6af8a24bf47e56b06a78d901 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/7bc3125dd810bcc44ea2d454b6caa683 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/86742a4476481b14145855ead8a5acc6397782f6d3445f900ac2de0570f1fcf53563cf5e1f3cb59886282083ce63756604f1ca2434e9e427cdc1bd1f68373581 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/4eae06d9e6272aef23afc191501810fd +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/fb75927982b1428b05b765bd5ac017b2c15d89990b7e6cb582b9e1a3ec04d09801d25d5cc6c037a12c205edb7c0f7a2d33832a2d1de7920711e9720dc3ca3655 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/cd86e18a63cd6e84a1493acf0df4e267 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/1dfefc4600368467ab90ccb527a9fdb012b9b7f485d932a0db8c4b1b81985fad931b74494b76ef2162e46280447d39a055b5681b33a17c564c50094de29aeb13 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/c7cf7daa7c11827ae4f9fb2e16f3cce3 +LLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/dabe2940606a671a8e3b4f28bb9e813d000650203c382372142457020f2ccd498534903aa99320afb7ff960a62d752ee6cb724e74745bc1bad1051e12cf78ab4 +LLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/62e575b89fd92d9206abebc19b084abf +LLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/7ac029567fd68fee82b7096e2fe278ee5cd2935494433b1faace036469c54bc471d614d0bb339750429dd88f3e723165d2dacaa627f73c3647c6f3b51a4a3034 +LLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/5d39ef811bc78204ebfc7e98111469cf +LLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/10fc9a64d63351e168bc79fa63bcaa6fd49c8483e5ecc40a66216192588367e9b47ec3ea2c047e88f39ea8f1caf8052726f4bc8858223f7744606156b4133970 +LLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/f072fe487e5d1b717aec49a6244adf05 +LLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/42b03a2562728ac86e751abab2e8233d583baf006e69b107d002a9258844ad53f62e6332eab3790364940d478c7ebab6d3e0e2194220e8436f40e6b75063d1a2 +LLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/eabf0239298f13ff4893011e75828bdf +LLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/34724d9c9a550c85d406021d7265e1848b002b8f212427eebff6e8f03ec6acc336efb0c2cd9d9e1c76329e7c84a84a9d852b8de5897550d957e0e9385129033d +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/1910b5daa31db6542f0c762901ab7d43 +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/c43e8091e9946ba1d8849734a25b258df95b4759a79676565b624930d4a19805a78b66b1d193e528f95174d909d7895d4a4e49fe8ca298a24dc40d25c95900b1 +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/a5198b13dc75ad3454e05aa6cdaca48f +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/9ec8078a1a7246f1545fe074783d6b88ce9b50f62b0438ff5637f6dedf5bcac427cc252c350354b7063f79f4e31a19f699c168c15bc6547a207da497026c2827 +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/f569654ecdd8ec2a50986ccac8388c69 +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/9b50e3be1577a753f0ce42704846bd126229d8dd9f28bfcbda58c4f18e4b9ca4ec6bb9b57de61b3b9af8157a2983aeffb8af782a073e5e19a8ccc261cbea9601 +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/496de8c9e2361f44ac6933480620d07f +LLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/02a8ecfb6e81e0fe07fb0d616a84a590e23e944588c18348c32265bf6bf19196beec189a0bc40514e379e97a9c8bef83557260839800fabe9f8e39e96689713d +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/05bc7406fd0a703edbc912bb3230eb37 +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/898dd4c19dd0f22dcd1bd44264daa8dc64340c890c3368fac7451da1ac872a687d55b5eb50ae4e156c2dc4ece226ec05775daebafe9d8b53eb83b72d2986ff92 +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/d6ca30fc3a2796ebda2451f80846883d +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/d7dc96e1bbca38272b1ca78b3ff995fc30434937a58815c63d0a9b4a017964cfb269a1f3203ad8374870257152229941d420f098644375b5f4d1b88fe39e0dff +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/6eb1a197150ad6c165b82c5e0e0db102 +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/a159598c2bf351ea79d01e8a454a82bbd9823c080399520af3182e57259957ad07834b03c336e6225857da365e8ec1aa9f65b0ddd0821883ae817cb81f8e6dab +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/116d849cb2fb4b1c8c517397b2b04192 +LLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/7b2596c76d2814fc30992ba78e5c8f93519442fa76004187de9830732b80bfc6c77f5d7aca042c20d8f868cd682bb6f71e3fa32940bc8c7b401753dc4ac2f331 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/27837dc854a173bd37a20f92383f6913 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/1719205cba6de969e8724a99444bf958d5a7943ae90ee2dd11193f56ddfd4f0edf6d9af6da2e67787a64b91d994fee76bd8ffde36486c5229a980c2c4ef07e29 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/f0016c21c045e205131ea22dc711acaf +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/6d192b7e21c7ee3327d288b890f4c5dd03e5f53dcba6905a34cab96b7ad0ab6364f5271af88d95e60aab8f569a8840d17e16f27f6fcdafcaf537d5d4a651dca7 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/9a2bad4518966db29e37e7c88388e779 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/b9a10af9dcbacf1f129d4e9b4cf562a6a4687252cc8a0fcd78f52d75c0c20be0ff32e67413a7902a628b04e7fac1091d35b64b145e33814899796009b6ed2853 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/77c4e24c1e44ce14bc6476954f294a15 +LLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/d9d90a4ac788dbbc1b532623a380d4cca8813ecdf8b7b4a8cfff769499e50a1433bac618234bd0765d8a4f50aafb3fa724d16ac71baf75ae5a2b4396fa2bd017 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/b29e36dcf5a0aa05734f1d6a0afd6944 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/ab46a835f9843c5b3427101bcd0c5d2b8acf79693aa9b8d4282d499f25df4ca248a81fc94ddd96c75d69d3c6b3814b225eed81bec32fbe9199bffdd605f7fec8 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/a411269f925cc968a0438562262e6d97 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/04f275603134b0ea0f23da377e4983765885f2b1954d5c617134af9f103470a5e50dfda18bcddb836852db2382f1c134db40df00b36c8bd00e7a9e6ff1a9e684 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/841921e33407e15eeeaa76354aa2b737 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/e1fb8b75e141cc90916c5c81c31ee91336911983c525f38eab86682ba69679dfbe1f10c9b673323632fc75f38cacc2af47a3d5d5d1031ec9a2a60cebd68d501b +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/7342a1d7b1d2c0fed7f5edf1c331ffa8 +LLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/dae8ca11fa8d34f99ee19a95bcd108a65b9e6a6ddf2e5a9b126f2ba1b1cdff6b7ec21e9590d70b3785593435bb71e47703d9765811db814a90aa8a47940421ff +LLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/10aac489dfa10a77427a82958f525da2 +LLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/a87f721df4fc5f6e929a54d8e41e55fb366a051a610836923213bfa42a7f1593de880391131619653cc3571bb76a4c82e011852ee5a6005523957c9f0937e6ba +LLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/7f231fd359f9297261c22f95d8f738c8 +LLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/fdd6441011609ef341108ff2d108c6f320d415b621a69922aeacc555c3d1ae6090a0f600f24e229a609b88ba9c1868900791a6590033b7dad333ad11f8a6365b +LLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/c4523a485082044553e1a89049dc4734 +LLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/db365e63bbb5189f7f348e2fd51e627ddfebf838ca9dfc6c0f8a7bbf6b8a2a03d78ea3ccdf08b0c2674f4cf5a0979506efa643554091ba751f16051bdf42ca9f +LLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/bcd10e4f3e5a4b00d52441e0094de1c9 +LLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/b17fae89a3dfaa9428cf48c9c0866477cc75edda6aa3800702227cc9e3d6ebaacbd60cccc96acb4ccde56a2de531dea5a436bac8e6c450a4674daae23b878037 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/2be8cf274b7667adf8d967a27abdede0 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/15f58c9a00aca5bf828708089912f128adfa3b719cc2fa8b9b4cd7ff7722d02375bc9a961b02d5c6a6c9ab637b626d78876741bd824353aab944e1c3b6719837 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/0dce4be3e8cead78cd3d12ca0796d560 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/cd60b39f2ccfca8ae0a497292819e9cc1893f6c3b2162fa9bb3136187351cfb1d6e4855141f1e9252bdee7e97ad61c0560566c2e9f73fe77a26b7f4ffadfdcdd +LLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/f2548c8f4bf1edb488642245221829b2 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/1604986526156a40ea82f50ddd0465d06df9faf306835f1dbbdac7da7f97c60fe684cd6c64acd8833a9f8b1d16f80c123ceef94fc16f255f815b93f1d41251e4 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/1c268e3e93ab3a34b3c05322c2fb0dc9 +LLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/f111ca82e196ea9507bb089b9d10990de1acb1a94778c40012ba6bfc16cf362369fb1f9dcc869ce14545439df21f432589ec004816a1ba0323c5edecc2b84211 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/b39ce0b0f143c3bef4dade99251003bc +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/62148e1e0a31d6b28effda0a5016d9335005b27ffdc5be1d184efcbb13f13e29eca52eca19cc6800d1d0421c0e67a36027e05d5fdc967dae686b5bfd112fb2b6 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/9475748210eb5b1947fe3aa6673b6c29 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/54320295e59e5903db558b6be0220442dbaf7ea78e1612d54a35cbe014541b354ea708679da00851b962140b6da77301e27b656fd478666d3f0f710382c13a85 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/6a533054ccfc3d1b0920eabcfb45ee03 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/3871620aeea2ccaf6e4b17a675c5504624fc6d8ed57bf4e5b66e0372b7124e4f3d1e0f10baa1018d5a1ac5bc4bf0e9d2143e84827712fda1f512fed24829f1b9 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/3fc6d1b7d59b98823d6016f97835b7c5 +LLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/745942235e40f2ab71a5eaef2768842823620d4a4dc7454a7512fb2bd95bc8a74323eec6a4b33edf1ef935151c18a20172f60fcca2fca1ff3a37b1e019ea4640 +LLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/f069af39cbbb650e293093b5989324a8 +LLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/34685eccd8c1cf7b72a52bf353de16bd0cac13959584217ce5d0995b52f506909955a7051ff7b29ab9d9c3f603af8f7db936f11e4bde83f5acf16415de62880b +LLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/md5/819a9695c365b9365b6cdba7cf9288b2 +LLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/sha512/4280768862b19918e11b6a7ed09f150270e71cf4560b18b224b3591c460c9375777e73e41eda375271d719f23b211daf3ed51b3c87bf4ee4429344d14f1ed7a5 +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/28ae362155ce224cef605cee53e36d0b +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/d90f25e57f92a9da68245ceb15316e3868bf657d7e744f37cce5ccb4945777ec82fc5d470ba4fc104fe7aaabfff7b0dc260838a45331e4360b0fd14c59a55666 +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/d10ec63510dc1a043ee0a4e37b49eacd +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/54c393208d1f51661e631cba62a21c0685fb58827067d5ea7c42fb3d6dd8c8db99d8ee1b3c304abc25510bcb0265d86ca03e1ce19be4faa252d97cfc8a1b52cb +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/2c1e000206c9e7c6c8e7515eb8115e3e +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/12c0ead798e43448a30699b5386b3d88aac49aaef9bae283ea6d089a1c66df7293f4f220a2b5c3d96e73e556e37e745f38d81f5c68e09a86a2b19a6695eff460 +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/21d6c5d5e422412b88ffce50862efb29 +LLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/5e8e17ba79134e9752c7fbd28b62e4616574a5e1dfcb0980160a3aad28a2f6cec4e48ed1acf73ca1f94d74397f7ee3eba53cb1280699e40c451295590ede3fe3 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/293fdc43431493f915a3e0a5b3c6d587 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/27e13a4334a3bfb3c91fd06abcc4eca7a347f4bffcbce40834302d153ef29756295121b42ac433c266668af1428ffa08ed12ce75f21fef44cd7ac1d8bdfd155a +LLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/2825dac8280d0563b7f521a9eb8c0563 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/7f4549ac7b63e58d8c149f6b22bd997545713477a1df3b32adf640f3951580df1645f08756d9ba80c479160cf5759e3f9372396655a35cdca14f4be4afc4ae22 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/0c0da0eccec4a092fc0e9a915716ed6f +LLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/e538e29c4d52d9aaf151670619702541fed8231ae4c7fb9431a425d10eea95433087034a37da8fe468bd27a1c882f6f8eb9549ef71964124db10e99f4b402ba5 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/6b4fd19277c978306441da3b58ab86a1 +LLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/6216b3e1dc6aea979d8b5abc4cc0faf510e4e64441b1d18b4b36c45d65e874e9046e14eea67efb88f3219449ef048d34fcb751b15c59f8a299aa822b426d50ae +LLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/md5/b7956d25e0e5ced19df637b4fadaa532 +LLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/sha512/ad632493095a8fc3638ff48514c9902215378532c1455cb19d70da9f2ae46fdd91ad4a8b5a3151bedd38dda9f07c21f9a25d8e095ded7ba843f9bbeb005e1bd4 +LLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/md5/392f0f0f61fb672002c7473c64a63ccc +LLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/sha512/d620dcee0b20e3aa4b2fcb7ae835933b33b5e4c4b5d9102b885c70b1dcec535239eb5a3d6b56b51f7b049943a2c79950bcd4a4425610f7a1531f6c452eac03bb +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/0b41650067323bbe0c5edd5c060b517d +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/111a21a5b491a77c69ee724b37d15b0c7baea387bb6a36695a1c2dd5f6e2eedb0ed211513145d8a6ce4dd6329b2de67e9bfce1b03fbf911b906a33a39e573f9a +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/a9079da821bee8e4b5aebf47a46cd9f8 +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/7088945264d1ccead492e81636086390fad91b0e071e9f3a54ef903b619ac2a7bd38fa5e0e04ea1e299f3985e04838cd5b7a2dffd666b8e7dbbf3b419f74df88 +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/4ccb3d0eabf8253cbdc1192b04c78d4f +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/9d817068dcc2b60c77fa639aa7632cbf071746e7dba62fe524c095f86e88b9323c3ab82ed5af0dc8b1af9c3e6f0da18be53d92e7c05e2d056c84e5a4e974b6d8 +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/a88f7a9f42d2cb5567c84d7fa2a2732d +LLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/9b16cbf75e9971dd4950cd79aef85396a7d8522a572f1c8017af82725cb335674741af680e1dd10c731987a321d3afd5e3e85718d3c3fdd1c9de4803e72a66ac LLVMLibUnwind.v12.0.1+0.aarch64-apple-darwin.tar.gz/md5/b95ad4844e649bf46db43683b55b9f4f LLVMLibUnwind.v12.0.1+0.aarch64-apple-darwin.tar.gz/sha512/15e0996aebe6db91fe58121001aa7ea4b23685ead3c26b5d89afae34b535e34b4e801a971f4854d8e1a1fbc805cece06272470622eef863e225358113a127913 LLVMLibUnwind.v12.0.1+0.aarch64-linux-gnu.tar.gz/md5/6d8783dc9b86c9884e0877f0d8ac4167 @@ -138,115 +138,115 @@ LLVMLibUnwind.v12.0.1+0.x86_64-unknown-freebsd.tar.gz/md5/54ac594b4c8e7f261034a8 LLVMLibUnwind.v12.0.1+0.x86_64-unknown-freebsd.tar.gz/sha512/a43756afd92081e6dd7244d162862fc318b41ca110a5e8be6e4ee2d8fdfd8fb0f79961ae55e48913e055779791bd1c0ecd34fd59281fb66b3c4f24a1f44128f0 LLVMLibUnwind.v12.0.1+0.x86_64-w64-mingw32.tar.gz/md5/83cf8fc2a085a73b8af4245a82b7d32f LLVMLibUnwind.v12.0.1+0.x86_64-w64-mingw32.tar.gz/sha512/297a5c7b33bd3f57878871eccb3b9879ea5549639523a1b9db356b710cafb232906a74d668315340d60ba0c5087d3400f14ab92c3704e32e062e6b546abf7df6 -libLLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/1b99f43b611f8c72e187b767adf8abf6 -libLLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/e8a65c950e1d782ab6fca6da5b9ce434a66901d7c1efac0ad973cc376ea1c6d1ce7d68802d623b66d9fdd2801035383a11961cf544173a54e90b6cc4acc2ff88 -libLLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/md5/7a1171e54395fbf5742c0b3dcb1ad116 -libLLVM.v17.0.6+4.aarch64-apple-darwin-llvm_version+17.tar.gz/sha512/f173b4fd6090cfddb2fe43da5603d7eb627bd8cc1385b039a719b830fd82f230d0e1e7e9d8808c94cebb83c46145148c206e4dd43cb5cafb96d7995f116a170e -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/0564e41ee1ea590661214ed7747fba62 -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/8be4f721f5d6f264f4934423fa884e43ef6fda5f895786ecdad51bfdd3c02df575a84be87d69a367cdd4131576558096502b77063d766a3961be1f1b4ab8e205 -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/d64714dcc951dddf20423aa7831cff9b -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/41bfd5c44c27be4538a19da87bab09f35cb7212eb31205cac876c35721a15b6baba26ae52b5457f9db2e4f51e9600cf9677c68a6adb6385d1fc07fe7edec274b -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/f457fb97ed50a72dfc59a3e84177afa1 -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/a04ef467f8761843c6e621e5d996f9cbf06d11d46c6b7bf85cddd768ec7ee1a6374caf153afb8a5c017048266e6b5df6c5d90cdfd99f1ca0f2e096002e2c0d4b -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/4f6544a9c3e3e4929ccb5f53d5be47b8 -libLLVM.v17.0.6+4.aarch64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/cce7cc5eaceff2f02e67258fbade6aee130462d049d1948c37061018f9acccfb4bfbb0cf8f751da83c8f76fc504ecd4ea9afe16382e4d9f261c573a1daaef942 -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/137328448b1a47a3ef13cca0665356f7 -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/0e6ad105e6cf8ba21a7521ba213e3608679e414740cccc03fbc33385310b50637da9a8c1cb0ac3b54e0ed487e04e3e0557cdcac40d25211731645ee1c56aa238 -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/412efb53b9468fa5a64866c76a60d9ab -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/8c02a1d910aacf807f8920a930ea52ef423d70a6ddb18eaab32ec14e836e08b50d2444fde6832f5eff21bc14ca291d69a2968d6bc94e4039dc439b879378bd3f -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/56445a46ec24a4ccf796b42d83a5b43e -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/90549dfe474c8ed9b12b4589243d53508b2b682f71061d583b77a01131fd215341f8dd860609823c5a564c5dd61b317c844b9d050920e19a99daf3d024f937cc -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/48d268feb53cccc7b12700a172793525 -libLLVM.v17.0.6+4.aarch64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/a6fbfc44d5382de86548ecdf7d18a8487ad37c84efe79d67d9360872dac756e7e013972981c97758a7a9eb3857d70d79d3b8bc90aaf1638ddd8c456111507ec0 -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/17986258a97407361b4c4c3679932666 -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/71fc532446f5b20f2118a56b412690ed38c3bfc52d3e52079dd903b671bd4624e2125f377c183b86aea4ba57592ba9a1143b5a1327ce49b128bb7c81490305ab -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/dc7d7b2e6184a1ecaf433a2589b59940 -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/d14b4b583dcfd8709e17d7ac79ebb5cfb044480a85591b5e26b8fce9ecf49a13c4b562ad6e6d2081366db86e6b66caed2278ef167a97650104fb818b5b0e4776 -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/d6c4ac2506639735cd7bb4940404806a -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/2089a09a4ba75fdaf053c4a59b3a5cd333c6e043f9e5bab186d5d751aa84d616dede56799468768190b3b8120747e7e08d404b8c39e7329b3154ae134ebbcdd3 -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/20dadbec0c7ce386f718031adbc21b9a -libLLVM.v17.0.6+4.armv6l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/2a6f09158272ba3d2a332646db57a94c2b9481835a974ec87f4c9ff23b5e5dfd6030f71d98a43380fb5bde078d7fb586cd5afc75b4b4428ae80f6dd09dbd26b9 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/9508999ae1be9c15f87ac49eef8bae80 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/735e5cee32590cb1360ed760d49357b2fdc830f943e3c184ba9c213f620ee38b4b8d7dc378540fbefd0f500c61a131b36051834ce521bb6d75f0c6ba7e223606 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/0c56726d3c7b249621c7e5e71bb91660 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/843062aa01605beb40f2d5a484638fa4b896016cca242084ce74d4a5eb1c0b8fc91addd71be105a784e083b90b328d0c9fdfdfabb0d257bb91d5ada5f4f71988 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/3674c019b88c8324c78343cf45beb98d -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/043faeafccd4bfb5207078af3517832ca710add36eaebf8abde86e4801c1e964d3bad5547800ed5fc4722b90c2bdd606a11ca06ab277f1e48264a194b1cf85c1 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/bd94929dcafc7ef8d4ad1f788023afa2 -libLLVM.v17.0.6+4.armv6l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/26b40bad7ac61366e5609c6078d2ec34bc18ef89b25d0c251a6dd49e83df4a62338f49cae2729d245a1d367a9d7bde01a286eefbc71668097d83b4c98402fab6 -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/0a443c1b7289030b32e22dc137b4ff3e -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/6ad96be0acdbc90ac092130ff438a1bd0df409683df624e0fce4095bf393ca90c54c71c19b1dc1a28563a25ea06f35d7883f199533d3e52ab42bc373212aed9e -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/md5/5ada2da7581d128ec2dafed8ddd489d4 -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx03-llvm_version+17.tar.gz/sha512/6b9d41908dd882e7a874a46786f5bf67db1d63c2917a91119dddbbf01bd709ec5d2487c0f3703e669a7ef404fd1a5a7c8671e4ed2e3fd10a47e6c4f6c2b7f115 -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/86074d6b9a30cd8b6ffd8e1e1b3a6d62 -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/48c7d92a780841d333adda21984920ca66d47b54b152c4316dac05bbb6b8ea6007644cf93b4a4f8475a4cb5a228dd0d0cc17482d873c7d9c9d90213b64c3ccc8 -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/md5/df1fcdc1f7f385fe630bbc83f121943f -libLLVM.v17.0.6+4.armv7l-linux-gnueabihf-cxx11-llvm_version+17.tar.gz/sha512/8c1a8fd4665c871d50e68249453918f865429cb9d3fece6ee139f367d006d5cc21613681e84656f9cc4bc6e884b3de7c19c808fe9dc2a9c7ca8b1ea9aa594e6c -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/md5/07b634f82a8330440a2d5608cfa90c42 -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.asserts.tar.gz/sha512/51cbc0753da4612ffd8f3f50c2536e7cb26d6cc67c3b936f2f971cceb9735b9e587dcbe88dde32367c9b581fae639bbe8076b774b6135288f2b160719dd97735 -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/md5/26261c713ecceb1d7a076c784d76bc0f -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx03-llvm_version+17.tar.gz/sha512/64344d21f38858d4a10adadc169c03ff98d523937882c8244f297d5e835ec8186eb8ad20e54c4aa5bed597af35e7b25cb2499607c967bf404054084715d631f7 -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/md5/24ed4293f7fab2172ab21b96fb44817a -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.asserts.tar.gz/sha512/d3c612c24e4a3159699ba5e31d51c9068e977780f3ff2af49a1b084af707398e51756921eb0fec7103bf99e80b6beac4cff5c1bb32c72920ec0834be7929b33b -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/md5/6e53ecf916b54f97f0aa6fdabc49e9d4 -libLLVM.v17.0.6+4.armv7l-linux-musleabihf-cxx11-llvm_version+17.tar.gz/sha512/8ceff63d6ef095dc2db7d836871bb07ba8d36bd946938a21dcff9edc8531635df8af1ce0b39fee0fd644929ab14d127badc77697a559fdde2233d2a74ade6282 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/122aef0ec2c01128acd1b830faf9e279 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/b163e80b21a91b75f8c7a82a3cae705bf1dc6b9f4243ff0e5ebed535589ddea835b3071c36794ca8511b411c71b545a9c3eb75f0a530e682996922916e2bbf5e -libLLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/8410e6b787a1a39cbcdfefbc69ffc0a0 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/debda3ddf24fe3228ac3f90f809aa4c3479a4d46a61f5aafb609740d353acea80cc33086e5fc79303845a642c4171c7da79108a213728630e5045daf18e0d6e9 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/7d34ab481b9b538feb96f53c5c0d6305 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/2af919b8481c1531b9a2458dc80fddedf3bbc0eb9d70a4ba7b6b1ac5bbf1163b3c407a026fb95d5c580687ced6bfa7ab474efe91575c9d3d98e3801e1d64af99 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/26e92a8a602bad11d07e5e28dc597363 -libLLVM.v17.0.6+4.i686-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/f6ceb5ff769b7fe75e19ea10fb3ddef55517228526e6fb3d961faa8e776e7b3cf3d62536cf1f287a4d0d9054c9e7b92181b7e3dd8ecc1d0f79bdc585f2008d37 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/14025c82e278f11ce31fd115c6e8c344 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/161f80c5d1289a90cab305bc6dc6a54528e797e6a0be375afba819640507df76636885b9aa5378f2585a7441acad50566004f437ce1e872e50e8c7385fcf4621 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/47ebe4003cf9938930d992d12c52e6a5 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/0d3ca73be07d98bec4f283e84c4286249de7ee8f2b9cae7c1b0f44a96ef9d90fd16e3911c9fd49652e0fcd105cb2588d66994aa502e9b3a7cf22eed6f264c6b5 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/91d359c70756f364192ae99a3078773e -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/a2c36c4039e98b06472a4081621cca4352bf0050d915a3d28e93185f16e85fc38305079a94d13870422feb9e5c365219d9213fc64441d1f9f2dc176711447282 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/56857016759f1e7a7414d41b65756d20 -libLLVM.v17.0.6+4.i686-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/e136529b357eb9cf6659f8b0447bc63bce77e3f0b943e955c01571b69184fb0c326b08effdb9e08342556c3b8649603d94e8c9c265041482e2c103b582f102da -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/ba23feb343b22ea60d9e1ffa0d4093e8 -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/84b77313f0048e02b7e4d6185a47417e66ec6f32ba2a8e9029b688a386acd3c19c84b1bf351e2ab6ef7942101f1fd89402bd12bf4676d126cb1b283ce9272d0e -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/5bcdc7a767e191726714edc8ca6a416c -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/fee08e6b046128c83932160a376dec01666c10dcbc22584177c017ccefc7201147c74c12137213c8209db8f0ea04102628c47dbc9a51615db889afb0cd11abdc -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/526db12f2f2238cbf935f7a2bb7c2485 -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/38602341b0e5f1ab99af66cbee19c0587beeb7883c71ac9b3a7c5853a09fe1b4aef9afc6ec66fc53442e491c976f02dd5dbc739ee9974689af5f76396f2ad382 -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/6837b6aa15a9628614b046c18985dba0 -libLLVM.v17.0.6+4.powerpc64le-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/4fccea20fc1bf221b27193a85fb3b274c4479c6f9b5c8e77fd9666f053b051785e7b4bf512466a0e6df5c303316825523c634b3c81e7829824b3e6fa28b4f032 -libLLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/md5/0ba2cb738f9e3f1cbcd0774331ffb7fb -libLLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.asserts.tar.gz/sha512/5a6de296017d942e7ec108663fe238f7bcf2a0db54d9cc3c44f4b2fd2596f2d4641d5ee1ea183d0b6cfd3bf10a4d1196c21a503f89f8c1c3746023e5558c6049 -libLLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/md5/53cbd7116db0d09ef0e41802032b8d3f -libLLVM.v17.0.6+4.x86_64-apple-darwin-llvm_version+17.tar.gz/sha512/30cd95f1437fd05a73965e88d35e3c91d4281ba9a339d04a36d8450576e8f32eb1b7325b45b8c979ca63b319af582c49f867a7507248dd1f3567226c9fe29c6e -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/md5/d9d5f588ff478450645c99a6fcbc59df -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.asserts.tar.gz/sha512/b0320e945024bd3519edd48dbfac8735a6f6041c199bd78db345f27ada53bc12917184350a9448b12d4f2ebd594e0e1aacc12c7796807abfe47997f38db21c9e -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/md5/8e79c58d7ee18853107954d97d19afac -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx03-llvm_version+17.tar.gz/sha512/eafed326babfd8ab56dc75c999b7526729723d20a343c98125a532ad35bc3ef1cecacc8366679190dfb96b7be6617adba614011e87d925032c5dfe96172b9228 -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/md5/da04c26d8cfd0dc3487bdb28c5641673 -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.asserts.tar.gz/sha512/5b61115f20383e0c0c7274e24091d6e8ac29961aba5ba5a81c4f8d1226b969674d72642627125fac696b6dfbf64cbad7aab1f090bca217b8df4f50148c20442c -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/md5/0283786c2b0901e9e5893179c29c6cb3 -libLLVM.v17.0.6+4.x86_64-linux-gnu-cxx11-llvm_version+17.tar.gz/sha512/f47ebfc5acd36940ea64d5fe5d3bd69aee430c911c58b453a2355b55690b488adc032437bd10f893afce1da5f8777ca5446426dd506b8b5fc9fb6f76fbf9f6f9 -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/md5/aa8af3906a48929dfd6c04a83d909eac -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.asserts.tar.gz/sha512/ef9954203c7f3ed81e044c44ca80374485b91551267a5b74bc42c4fddf82ebdd7f4136dcd22b05d70bb66ae47d4ed49079f5e83f38f0a7b9141158d631f96c9e -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/md5/26cd3622c65ceff6a74191395bcec31b -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx03-llvm_version+17.tar.gz/sha512/033cb0f0ddc9027afb5dace0ecb39b3be9f13badda715fea1f8f04ab969f0a7b25544849abe851f4aac2576f4d99c9be8595296e8d1b7cc4accfd4cc3c882b3a -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/md5/a2fc72f59c1cdd2042b855c833e23c1b -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.asserts.tar.gz/sha512/0fc74b666b91d667fc112f38b970bca4cedc3083fa832907d9daddbf7cf99fee89ea42829eda609bd96a1bc9d80adaf32b047232a71c5957b87fef60cdd4c046 -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/md5/91d0f5839e7e744eb8048793c3236a89 -libLLVM.v17.0.6+4.x86_64-linux-musl-cxx11-llvm_version+17.tar.gz/sha512/da9ef48726b6d4e2012831bc246e3e6d2401af7ddc7636add6c96239351a36c3c5ae2fa71937b047ba0f63eb0377692ae85357c2be0a73ab6e5e710193266bed -libLLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/md5/6942c1fc5ba689e7058100a6b0fce16f -libLLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.asserts.tar.gz/sha512/8919f5b643aaa6c6c761d92b4e3d6d28165e18edd75baf2ed1dc32b27c1b2da55f71b6dd5ba7d114d021993eb4db415e8ae264ff014a12dcfad78543c510dea3 -libLLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/md5/1a91e2eb0b4d4f6d691d552e78060661 -libLLVM.v17.0.6+4.x86_64-unknown-freebsd-llvm_version+17.tar.gz/sha512/f1a1e2c1ef51bfe489660e2a1b1c997f550cddb8bf09634cbdfc6c17bb0a1d6096ad94fe92e02cc5bf61e6b4bbf4d3a91704e9c15e672f5f3ab4a9766257d395 -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/md5/c9d70905fe2dfde034855eab75d10339 -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.asserts.tar.gz/sha512/58e653a04f75078767de6d4a65086eca681f27d4c579fee518ae974d47252699bc217a150c5e688f69d7444670a3812ad0edebab2886a5c4ce501d2570e38cda -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/md5/c7342d2bc6f0004c78b8e768da06d332 -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx03-llvm_version+17.tar.gz/sha512/c1736f186925c7c21a97570b0346ca235d20651f7329ecd4142737473ce67b98a36434c02b384e3b698990238b6118f164601af5d91895bbfcab69397bc6b85f -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/md5/a90df960291596424b7291a68f632404 -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.asserts.tar.gz/sha512/ee002ab1b08078d02b5f1624ad2b6590d1937ee4c7d0c78b03b6dab8c7906d46f5373b8d5fbb76460ed8782ed85c84b12ac4b139a84bc73d2c17064930a668c6 -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/md5/e1928993bffba68c277f7bf6e1f537ad -libLLVM.v17.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+17.tar.gz/sha512/c18ee72b3187b1bb5184e5047164338d2a52eec626db44a09a77c23889db8a39e417020f3c50feea0f180aef39f2f23fff4d3324fa7030e4feef6a4033fc4c70 -llvm-julia-17.0.6-4.tar.gz/md5/3c69462bf7ba6219955dbc9e7e0c52ab -llvm-julia-17.0.6-4.tar.gz/sha512/aa96b3d01d3c2c86b79712a13f1abaee8dc95b63c8c7733588c2d5709bb72e2e835909af5a907c77b5d99d69ec69f97cf567d706d11d5f54d4c6b8536fc7762f +libLLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/2ea6046caf5a3d519ab1c3309a2eea31 +libLLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/079720b30c61ded8499eefdb314477d58bd121e9f326d98696ee39b2ed91f806d5f67e68b6fbef8613a992175fe34694e5efe83e87ef3bfbed67d6b7fc41ebf9 +libLLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/md5/62c49bc7767d1ff114dc6b6a996449ae +libLLVM.v18.1.7+2.aarch64-apple-darwin-llvm_version+18.tar.gz/sha512/c708472b325cd73b94e10003bf3267b0ecbf3627072302fb22e78336974f2c7855c8597420efc954bca30aee17cec55277aa0c95a01cfff38d5d77df50c807f7 +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/766a2de98d275877bb676ff1f23e972f +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/3b353ea038fafefc13ccb4a81c7242d569c206362605be374fb312cb495f385796d052c3a7e08c7fe6ecaa3018e2a7e3dfa43d71a8c3a94987f7dc7aa378fd22 +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/0684a6b210b799a8a0f45a286f3dfcc5 +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/4221e2d74117bd7e89aba2945030c1507e51999b236814fd23036565364c328392e87032daf1b9fe274ed89fcf9a6dcd203f0f1c8602c2a08d3fcfa189a5fefe +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/6b460256e923637e5107d67859eb60ba +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/7d3f2736afe4022842529b1355cf9914b7a1c7b1e261f814a4523ad30a0cf0189056d5117a06720bbb7a844a435bb632ddbda2daadbf7e01c0120452cd13e6a3 +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/c2b13a6a296adbb4be91dd3bb5be0877 +libLLVM.v18.1.7+2.aarch64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/9086937e718125afd535b0066ee08a3523161a94fa7ef3c9a3e86bfe760f251b6ea7b035888e61a0e7f192ed25c9bd0f4dc153df86e08569e7067a7a30ba48c5 +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/758d33fe0b2b3d0371708614365450e8 +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/79a662f72ba1b89b373d1d143ee880a12cb128211e79182e7befe8b3e50298b594de2ce489ca8bcdeadb17fceee811622f8bfcbc3e232cefdaf9927177469eec +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/2dcbb811be8985bfed3c8b37733c0d40 +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/17f6fbd96ed5029f360c101cedad127881e14b42498d66f717448d99ca1909057ae79169d934e08157edcc7467db4b3941bdda26a2e9f42645963eec51f27e29 +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/bd3b904b5f9464aaaf87c41b899c8ca5 +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/fa99e8025419a18f548f658ea589771c2803480c3cb3a25cfb75e26ed0993b7b37bba204d7cba1475319a71159813b2b58a3b3327ba24d264cf80ef24263628d +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/b4f9038d5c3c13207111ee1a9a918cba +libLLVM.v18.1.7+2.aarch64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/e8b97bee30f597cc06d31175e12f0c2035aef0054e8abdb431f31b1e9d440d561bd9bc6637a403441aa7f3e1d2a46c600734e17e3b7ed0ae899c92df91758780 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/06d8e634b4a6914efc18b7962df52021 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/cf6aeed1eaf652e5830e34dd2ba88abc33668953281146106bbfdbc92f5f225645f00ff5b4a0eb902baf904362ab4eb32192fa50ee5b2672e8b031fe2550f9a8 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/53e83804b63e6ae4d0f1c97abcbbd1c8 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/45b3ee9b105ef2ef106fa8ac7b8e902cd1d6bf3c9bfb57edeca9e14f1654714d23fb086b369a9fd3cbb828c04fee4cfe80d2b2a2bfaa852d3ac65c0d213d8c62 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/91b6cf00564053d385e30b34e5b8778e +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/9111f3f02b49bf78340c9b0c5c1325a1ca09b62c83aefece1121573dcc21dce095060351f18997971e5cfbaab346cb12c75cdc0fbe8fa92aca2e8a68b5f5f577 +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/f6c91b71dfd73c7301a4e3de48e072de +libLLVM.v18.1.7+2.armv6l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/581d7e1e4d85aeaf082fa31555074471705e391de0771bf66665807afb5192c79c481ca30e73a25f4e2d48d4d325f0198e39bcbfaed2c9bc7477ee917667f5ce +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/ce41ee46959e5e3a17b6c99293afedb7 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/73d8c5af750ea9deef822aec58d8697243ca154bc4435ac0b0ab8c90fc97750e91fa55f8de7b8283eb1ab19951cda3e3c4c60834bcf13730163e593126a8eb57 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/67ed5b654852dad400aef17fb542703f +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/07f70c57e27eea37f520f6f0a954b54d2506530d5eb5a74e5a8526ba8ef55a948073c49037544b602d03d0aa482704292eac943f0a83421386ccbfbf22ee8510 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/5b8bd88d49ce21e5b63af6f77782eed4 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/cef1c561ae388b2baa08e39dc195989cb795d8a2747f5f11e0dc9d9e107b9e99dbba465335376beff2e1b326512f6afc962775e0b246f3edcfadf509235cabd8 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/5fbf26d20b2ce3f61edc9a9ca2eb5284 +libLLVM.v18.1.7+2.armv6l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/2c564c95d648458b9a0f0c963246cf5564c625107682f680390b6db5fde0e2b15a964fd3fd23734b5b2bb135db1fc698812d61b3f275710593f4defaee4a9c23 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/c81bc29a75acf4f806f3eb13bf890604 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/c8c922a0a4fefd549f1c2ba396a3cab9cf7738aa82e7ccf7ca29c090260e2d73ec45d6f2b07173d584f6074b10fa04052114deef6ecb6f53ea87f1924074137a +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/md5/1fcb40ba1a427105b4e7d13a6c11dc78 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx03-llvm_version+18.tar.gz/sha512/392c9ee85ba7ab6697bb8979c7f443d1d25f7ac9178e96a886401cfc68d75a43ce98bf3038a7ba70a9a990f65e604d38e043472cec3badb25fbd1b38cfbb7162 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/427a19eaf69725d11bb33f48de9cb205 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/542e209b10c13d8dca867247a7414f84adb832f40051fcbdf0dcb09bc9664a77248e1b0ea1687805847dd9f5a05b86475dd76aba427c9a1bc83f8502444c60bd +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/md5/ab34bfa2950014936edd13a7b5db8170 +libLLVM.v18.1.7+2.armv7l-linux-gnueabihf-cxx11-llvm_version+18.tar.gz/sha512/6376b25d0278e5c97581480fb4d54371b09a08be88f4cc39d2c7b3875f1189cef60c1be6bea5e12b0cf306cef8b394bc7d00f8b0fd95d749bd1b4eb318af7e15 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/md5/cb6300fe87fd7cb9840f3bc44af26878 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.asserts.tar.gz/sha512/a7984cd90fef55559142fc05d91b0da1f37f77f25214e93ff7641b7c3958f08dc7c082611915dbfda4bbbaa392656ac8604d4f75369777dacfb78baee2f99b16 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/md5/b8a4e8ef43340e9cbdf5e4479c6a5a56 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx03-llvm_version+18.tar.gz/sha512/fc249f2b666c8a8129e05ea08c773cbeb7af6d37791f271461eedd99adcfc5082e8609ed096d8a46edd1e73505352712a41e0ddc247a371f78227aab01fbe0f3 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/md5/5864689df3298be4b1b4df1ae0412d3a +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.asserts.tar.gz/sha512/8f32f73e366c3a6993fa8d6b8cd1a9391611b0644cd4a77a4f7a235c037fdb75308d99b5a23ada6e4a73ed5fbd8f929a981d6bf317d79d52396220c221619303 +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/md5/6bf798476c4e94716cc47a95580104ad +libLLVM.v18.1.7+2.armv7l-linux-musleabihf-cxx11-llvm_version+18.tar.gz/sha512/9dbd27a000dd3c3dda9047d366a667c4b179cc61582525adb0f8227e8055413ce46efcbc1530305400239656e2f1016fb8833fb7f4734714078e035d388f3531 +libLLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/66e2889f86ae6bc1977419e6d9be729e +libLLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/d0cac798c4979b4d818d36596b173e523cba3f41ff7ab1e2111f6a75c3e819e563e207a547328f005c5a93c7f8f88c17bf43c1139b5c2690df4f1d719f82920a +libLLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/0534b72d6d33c8573f79dce8a2a5a6e6 +libLLVM.v18.1.7+2.i686-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/6beaf1b45eec8b46fbf92f692f53e6df40bf48e50589aeb5ef99240a5a3ec9089ffb350dda6df24530937d613bf6d2cc4da76e92921ea00def9d2d38ac5bbeba +libLLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/2cf9a1ca20472179ce4a9eb3a949457b +libLLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/cebae06ccee12a14d20d3056ce0519b1e774e3c9d9200a783262fcc40aee6d7aabfb08714bf53b88e03d8b09a96d3cda248a70c16188f8c707b291642998262a +libLLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/4712f6a46e0ff407ece958a7701511b9 +libLLVM.v18.1.7+2.i686-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/9a0a2dfa2076b93027f766277a6890cf94d67c131697f74945e92cf13ae64e84c09d3dd744498986fb22ad5e5465300aa9c8ae6632fcf919a0932515edfcc1e6 +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/b944ae477232ef10d213b4c7743280fb +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/25ff757620baaf6fbacb375b103dc0dd9af6a23c3d3bca567c182a6357a367ca125d7b6c66927d7db23816865b6ec783157352fba08532336de467be80efcb9c +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/52345a44b3ac74b3cdf93852bbc63710 +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/3e5b449b0f1bab302c45f9ee9f04d2cfbb01ce24e86096aa610fdf360ad65828f1b73734beb28b3d3c249ba8ef657d2663c5492940504f47c973038733b15248 +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/36e058b96771b4cf77e29b800227fa03 +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/98873cb2963c4469b0f69ad1d9d9e27056aabfb46a2642dfa3507b7fe2f0b0fc41c3991a2543125291783699e39fcbcac0bd6e92fa8f0df97609a85c340fd25b +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/3b3823fbafabea289a769958f633dcdb +libLLVM.v18.1.7+2.i686-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/91a9c1ad6f37cb1186ba3392935fb55d49e0f8d6afc768cf881886f9b1d8b0a2b0ecf0c81a8e32e36d32cac04c065ac852bdb95ba5ff6780c00a763583a02973 +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/bbf060d61b294b86f7e3dde381b00b8a +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/632372d41f6e400a10fae27c6cd06a5a344cfb5902cad7928cb4133f14f36f0a3373e69e73ce9baf52f518340593c3a5a16173ef59a1878e6300e9975aeaa157 +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/3d730b713e01cdb5a7a5a46028afd41b +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/052ab4fa7ac3b2c430601753ab078cdc9fd6db7f65ee0b76bb05473f4c5b99ec8919ad9d347425f1928cf619548e992c86ba97f9994218f50bca617e43d2f0d9 +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/bf9dcb92ba8c031ae62ed4434fd5447f +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/e53be14dd02a2cef8eccafb9301d29c51d652c635703529c1444947002993f6639083eb8bef13af21c9796717ce4b3129dcdcbe2751a1173d39e321db8f6e3c7 +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/b5cab0fc7c6643c6dd161f1e553ef1a0 +libLLVM.v18.1.7+2.powerpc64le-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/4032634449e2669479761c4323096b152f8df4948e3a97eea10f0b400fbf2a00d1edda59b74a714b62c4e204b113d8ecda78d828c3344ebe8bd750d14b3c4c7d +libLLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/md5/054e06d882173ede2886c510e8519c80 +libLLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.asserts.tar.gz/sha512/eb97ec25354badcac1b8a4a09fd9e04cfbb7d35493c54cff82af9ffa4c2dc5070c9232a86e900d6eb9acb03f1c572fcde8d2a865477bf6c9fbfc139763a9dd1c +libLLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/md5/f1c23200365b659f0dc07cc6d0a32c60 +libLLVM.v18.1.7+2.x86_64-apple-darwin-llvm_version+18.tar.gz/sha512/fad13fef7e7584b3f756fce9125950e788e79608cf5d0c023cb8f8a4e79001afefa8060f7866875e4861a268b3020e50305e66bf472360c1d92fce12d7a81ba9 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/md5/69564913bae176a167d24d3291ef7af7 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.asserts.tar.gz/sha512/b8eeb86b66d767218e59671bdd597623238eea72319913c2ac5e116faec3f4c13739a24f3b95338ed857ec29e714dc0308e4ddbfe359332b3c27ad5235052342 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/md5/bc9d5637fe30f21d2231a98371e798e4 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx03-llvm_version+18.tar.gz/sha512/4efbc2823322abe80d0134d35926767bd9cab717cde9308726a6a8891e5a707476138888c695ed399e3dddb57baf17abbc43a0a338cea2e5c0f472ab427c12e3 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/md5/8492ff91e6dbd1a66edd8aaf0390a582 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.asserts.tar.gz/sha512/6443bd2fa9c5beecc2b002c26595f2cf3a8e2ea5eb49aa4c00f7252a6623fe0f8c01824941ebe5475460641285c4e56a5203056c1b93a78250b7e48fb5ac9e00 +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/md5/6918c9978fd8b5887c66eee76950478d +libLLVM.v18.1.7+2.x86_64-linux-gnu-cxx11-llvm_version+18.tar.gz/sha512/d455a4f433bf3ea1b5100b9d45199bc785e4b6fbc7659bf06cbde6ada471134e7d4243d3a3a1f71d579126ef8371d70e59f174e124b3ff8d4842e9ee83e2dea4 +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/md5/075f87d106dd95c8e9c6e7e157b5e9db +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.asserts.tar.gz/sha512/8132379d8f44a21082c7a90f58a7dffb0c6ee725efd58a959d4023787411b080d72913bb1e89a35072f97aaf1ca512ab1d027b37eaed819e3c053d7a0cf64269 +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/md5/4cfc2838a77f05883f82e50b3723dcfe +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx03-llvm_version+18.tar.gz/sha512/20079c81cd6a4020b087485be1ab4928b3bd3e1a53728cc98137a35b969484278093bc75a9e51ddfd8331556577c5fb3109d74dc2eccffa93b5390e0fabff2b1 +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/md5/5b8cbf00631bd4540b7335a86302a1fe +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.asserts.tar.gz/sha512/51ba9a4b74b740905cee4baf7f4e5f3620ed81e0746f49cd352d874ebedab95277c5031123f880c9239b7dbf505b10f6531f79c8a6b0482a652b8324f4137cf5 +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/md5/11010cc2d58b1a8c6a6e7bc24df0c0db +libLLVM.v18.1.7+2.x86_64-linux-musl-cxx11-llvm_version+18.tar.gz/sha512/a6bdd9a2a2fa9a572e74ced69c3ce9d1b84cde18155ec9bc7dfbaba411ee6c43d229e6fb333eff66fb63b632b485b46b7cb1657c0c49d9d9bb849fa13f0bbc7b +libLLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/md5/8afe26d16d9fdb0fe6c0248c51b4f053 +libLLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.asserts.tar.gz/sha512/32a92685f417c1887aef3cd8a9cadccc4de3e560ba8fc42e8db721f273a3451927b24dc4a2c2e83446e32a84d47f714fc3c22ce71989f2e97c5ca23a1783b8d6 +libLLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/md5/59d8d911907127ff56f5eafcd8663300 +libLLVM.v18.1.7+2.x86_64-unknown-freebsd-llvm_version+18.tar.gz/sha512/9b0bf6f9d8d32ccbec349c249b79fd0fa3b4949c04b69c9d408f19dfa3b4f00e5cfa51b798234721f72f2793161d6af6491856e10e6a507976b0da6ed7a8065b +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/md5/b0d9a7eca92d40ecbfa47461d52659e2 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.asserts.tar.gz/sha512/dc4a91e164d88ff51b4a642b556d5767156f28d1efafa533f5d7c619e05535e2000afb2ea47469a90f5a19f970e8f0522f35d59ec250e2f9b42ce22fadb9ffd3 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/md5/92a60309ad33391415c6703edbbd5423 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx03-llvm_version+18.tar.gz/sha512/2fe90ac804d94bcf0d4058a8b8f0c274e405ffee7df0175f5e7ccd5014b29a813af48152870e1af0a79df8d3eec3118c233bc4f5b3f8439fd9792931140ee944 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/md5/0964df17cb98d2d869a33468477f9901 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.asserts.tar.gz/sha512/2c062acd62175d32dda773e9116608ced814a64ab06ea73f89958437178e2603b268638e88162fb81c22e5947cf4cc925b1af10c6f9320be22c92b279b278992 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/md5/7dfb8e61e972c66f1d754cb979bc0309 +libLLVM.v18.1.7+2.x86_64-w64-mingw32-cxx11-llvm_version+18.tar.gz/sha512/d462b6fe7aea75f6fee6c5c2f24576569b5deac8027fb88240e16c55a54d68b7dcb06b3ec4ab514616fb88549fc2f10fb1d587a641d6f29fa66273904bb9cfd8 +llvm-julia-18.1.7-2.tar.gz/md5/5c0ae4abc4ce31a86d5d6d4ecabc2683 +llvm-julia-18.1.7-2.tar.gz/sha512/b4d1dde929a8670eec1a9b25abe23fbc926a922e61b60ed99b52b440cd07cb026e7f746878292db4cd0cb422d9b87ecc4ee4b2b141f8e9411855d18da51facb9 llvmunwind-12.0.1.tar.xz/md5/4ec327cee517fdb1f6a20e83748e2c7b llvmunwind-12.0.1.tar.xz/sha512/847b6ba03010a43f4fdbfdc49bf16d18fd18474d01584712e651b11191814bf7c1cf53475021d9ee447ed78413202b4ed97973d7bdd851d3e49f8d06f55a7af4 diff --git a/deps/clang.version b/deps/clang.version index 76ddb503b3c8c..fcd55b72de5ff 100644 --- a/deps/clang.version +++ b/deps/clang.version @@ -3,4 +3,4 @@ ## jll artifact # Clang (paired with LLVM, only here as a JLL download) CLANG_JLL_NAME := Clang -CLANG_JLL_VER := 17.0.6+4 +CLANG_JLL_VER := 18.1.7+2 diff --git a/deps/lld.version b/deps/lld.version index 431c1b7a75032..3ca9960164e27 100644 --- a/deps/lld.version +++ b/deps/lld.version @@ -2,4 +2,4 @@ ## jll artifact LLD_JLL_NAME := LLD -LLD_JLL_VER := 17.0.6+4 +LLD_JLL_VER := 18.1.7+2 diff --git a/deps/llvm-tools.version b/deps/llvm-tools.version index 3609c54ddc98f..1fcc8944dc769 100644 --- a/deps/llvm-tools.version +++ b/deps/llvm-tools.version @@ -3,5 +3,5 @@ ## jll artifact # LLVM_tools (downloads LLVM_jll to get things like `lit` and `opt`) LLVM_TOOLS_JLL_NAME := LLVM -LLVM_TOOLS_JLL_VER := 17.0.6+4 -LLVM_TOOLS_ASSERT_JLL_VER := 17.0.6+4 +LLVM_TOOLS_JLL_VER := 18.1.7+2 +LLVM_TOOLS_ASSERT_JLL_VER := 18.1.7+2 diff --git a/deps/llvm.version b/deps/llvm.version index c02a52008fe25..8e4180ef5a277 100644 --- a/deps/llvm.version +++ b/deps/llvm.version @@ -2,14 +2,14 @@ ## jll artifact LLVM_JLL_NAME := libLLVM -LLVM_ASSERT_JLL_VER := 17.0.6+4 +LLVM_ASSERT_JLL_VER := 18.1.7+2 ## source build # Version number of LLVM -LLVM_VER := 17.0.6 +LLVM_VER := 18.1.7 # Git branch name in `LLVM_GIT_URL` repository -LLVM_BRANCH=julia-17.0.6-4 +LLVM_BRANCH=julia-18.1.7-2 # Git ref in `LLVM_GIT_URL` repository -LLVM_SHA1=julia-17.0.6-4 +LLVM_SHA1=julia-18.1.7-2 ## Following options are used to automatically fetch patchset from Julia's fork. This is ## useful if you want to build an external LLVM while still applying Julia's patches. @@ -18,6 +18,6 @@ LLVM_APPLY_JULIA_PATCHES := 0 # GitHub repository to use for fetching the Julia patches to apply to LLVM source code. LLVM_JULIA_DIFF_GITHUB_REPO := https://github.com/llvm/llvm-project # Base GitHub ref for generating the diff. -LLVM_BASE_REF := llvm:llvmorg-17.0.6 +LLVM_BASE_REF := llvm:llvmorg-18.1.7 # Julia fork's GitHub ref for generating the diff. -LLVM_JULIA_REF := JuliaLang:julia-17.0.6-4 +LLVM_JULIA_REF := JuliaLang:julia-18.1.7-2 diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 815e305d14376..48afa360c0037 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -19,24 +19,9 @@ // analysis passes #include -#include -#include -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -1164,7 +1149,11 @@ static AOTOutputs add_output_impl(Module &M, TargetMachine &SourceTM, ShardTimer raw_svector_ostream OS(out.obj); legacy::PassManager emitter; addTargetPasses(&emitter, TM->getTargetTriple(), TM->getTargetIRAnalysis()); +#if JL_LLVM_VERSION >= 180000 + if (TM->addPassesToEmitFile(emitter, OS, nullptr, CodeGenFileType::ObjectFile, false)) +#else if (TM->addPassesToEmitFile(emitter, OS, nullptr, CGFT_ObjectFile, false)) +#endif jl_safe_printf("ERROR: target does not support generation of object files\n"); emitter.run(M); timers.obj.stopTimer(); @@ -1175,7 +1164,11 @@ static AOTOutputs add_output_impl(Module &M, TargetMachine &SourceTM, ShardTimer raw_svector_ostream OS(out.asm_); legacy::PassManager emitter; addTargetPasses(&emitter, TM->getTargetTriple(), TM->getTargetIRAnalysis()); +#if JL_LLVM_VERSION >= 180000 + if (TM->addPassesToEmitFile(emitter, OS, nullptr, CodeGenFileType::AssemblyFile, false)) +#else if (TM->addPassesToEmitFile(emitter, OS, nullptr, CGFT_AssemblyFile, false)) +#endif jl_safe_printf("ERROR: target does not support generation of assembly files\n"); emitter.run(M); timers.asm_.stopTimer(); @@ -1632,7 +1625,11 @@ void jl_dump_native_impl(void *native_code, jl_ExecutionEngine->getTargetOptions(), RelocModel, CMModel, +#if JL_LLVM_VERSION >= 180000 + CodeGenOptLevel::Aggressive // -O3 TODO: respect command -O0 flag? +#else CodeGenOpt::Aggressive // -O3 TODO: respect command -O0 flag? +#endif )); fixupTM(*SourceTM); auto DL = jl_create_datalayout(*SourceTM); @@ -1892,26 +1889,31 @@ void jl_dump_native_impl(void *native_code, JL_TIMING(NATIVE_AOT, NATIVE_Write); object::Archive::Kind Kind = getDefaultForHost(TheTriple); +#if JL_LLVM_VERSION >= 180000 +#define WritingMode SymtabWritingMode::NormalSymtab +#else +#define WritingMode true +#endif #define WRITE_ARCHIVE(fname, field, prefix, suffix) \ - if (fname) {\ - SmallVector archive; \ - SmallVector filenames; \ - SmallVector buffers; \ - for (size_t i = 0; i < threads; i++) { \ - filenames.push_back((StringRef("text") + prefix + "#" + Twine(i) + suffix).str()); \ - buffers.push_back(StringRef(data_outputs[i].field.data(), data_outputs[i].field.size())); \ - } \ - filenames.push_back("metadata" prefix suffix); \ - buffers.push_back(StringRef(metadata_outputs[0].field.data(), metadata_outputs[0].field.size())); \ - if (z) { \ - filenames.push_back("sysimg" prefix suffix); \ - buffers.push_back(StringRef(sysimg_outputs[0].field.data(), sysimg_outputs[0].field.size())); \ - } \ - for (size_t i = 0; i < filenames.size(); i++) { \ - archive.push_back(NewArchiveMember(MemoryBufferRef(buffers[i], filenames[i]))); \ - } \ - handleAllErrors(writeArchive(fname, archive, true, Kind, true, false), reportWriterError); \ - } + if (fname) {\ + SmallVector archive; \ + SmallVector filenames; \ + SmallVector buffers; \ + for (size_t i = 0; i < threads; i++) { \ + filenames.push_back((StringRef("text") + prefix + "#" + Twine(i) + suffix).str()); \ + buffers.push_back(StringRef(data_outputs[i].field.data(), data_outputs[i].field.size())); \ + } \ + filenames.push_back("metadata" prefix suffix); \ + buffers.push_back(StringRef(metadata_outputs[0].field.data(), metadata_outputs[0].field.size())); \ + if (z) { \ + filenames.push_back("sysimg" prefix suffix); \ + buffers.push_back(StringRef(sysimg_outputs[0].field.data(), sysimg_outputs[0].field.size())); \ + } \ + for (size_t i = 0; i < filenames.size(); i++) { \ + archive.push_back(NewArchiveMember(MemoryBufferRef(buffers[i], filenames[i]))); \ + } \ + handleAllErrors(writeArchive(fname, archive, WritingMode, Kind, true, false), reportWriterError); \ + } WRITE_ARCHIVE(unopt_bc_fname, unopt, "_unopt", ".bc"); WRITE_ARCHIVE(bc_fname, opt, "_opt", ".bc"); diff --git a/src/ccall.cpp b/src/ccall.cpp index 3c2857608c163..db7bcb3a408d0 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -2108,7 +2108,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( if (!isa(llvmf) || cast(llvmf)->isIntrinsic() || cast(llvmf)->getFunctionType() != functype) llvmf = NULL; } - else if (f_name.startswith("llvm.")) { + else if (f_name.starts_with("llvm.")) { // compute and verify auto-mangling for intrinsic name auto ID = Function::lookupIntrinsicID(f_name); if (ID != Intrinsic::not_intrinsic) { diff --git a/src/clangsa/GCChecker.cpp b/src/clangsa/GCChecker.cpp index 9caff014c7703..ecaeb460ebf91 100644 --- a/src/clangsa/GCChecker.cpp +++ b/src/clangsa/GCChecker.cpp @@ -767,7 +767,7 @@ bool GCChecker::isFDAnnotatedNotSafepoint(const clang::FunctionDecl *FD, const S SourceLocation Loc = FD->getLocation(); StringRef Name = SM.getFilename(Loc); Name = llvm::sys::path::filename(Name); - if (Name.startswith("llvm-")) + if (Name.starts_with("llvm-")) return true; return false; } @@ -911,9 +911,9 @@ bool GCChecker::isSafepoint(const CallEvent &Call, CheckerContext &C) const { if (FD->getBuiltinID() != 0 || FD->isTrivial()) isCalleeSafepoint = false; else if (FD->getDeclName().isIdentifier() && - (FD->getName().startswith("uv_") || - FD->getName().startswith("unw_") || - FD->getName().startswith("_U")) && + (FD->getName().starts_with("uv_") || + FD->getName().starts_with("unw_") || + FD->getName().starts_with("_U")) && FD->getName() != "uv_run") isCalleeSafepoint = false; else @@ -1050,13 +1050,13 @@ bool GCChecker::processAllocationOfResult(const CallEvent &Call, // global roots. StringRef FDName = FD->getDeclName().isIdentifier() ? FD->getName() : ""; - if (FDName.startswith("jl_box_") || FDName.startswith("ijl_box_")) { + if (FDName.starts_with("jl_box_") || FDName.starts_with("ijl_box_")) { SVal Arg = Call.getArgSVal(0); if (auto CI = Arg.getAs()) { const llvm::APSInt &Value = CI->getValue(); bool GloballyRooted = false; const int64_t NBOX_C = 1024; - if (FDName.startswith("jl_box_u") || FDName.startswith("ijl_box_u")) { + if (FDName.starts_with("jl_box_u") || FDName.starts_with("ijl_box_u")) { if (Value < NBOX_C) { GloballyRooted = true; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 875beb7c287dc..3a363dd3fd0c1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2180,7 +2180,7 @@ static GlobalVariable *get_pointer_to_constant(jl_codegen_params_t &emission_con gv = get_gv(gvname); } } - assert(gv->getName().startswith(name.str())); + assert(gv->getName().starts_with(name.str())); assert(val == gv->getInitializer()); return gv; } @@ -8846,7 +8846,7 @@ static jl_llvm_functions_t !jl_is_submodule(mod, jl_core_module)); }; auto in_tracked_path = [] (StringRef file) { // falls within an explicitly set file or directory - return jl_options.tracked_path != NULL && file.startswith(jl_options.tracked_path); + return jl_options.tracked_path != NULL && file.starts_with(jl_options.tracked_path); }; bool mod_is_user_mod = in_user_mod(ctx.module); bool mod_is_tracked = in_tracked_path(ctx.file); @@ -9638,7 +9638,7 @@ static jl_llvm_functions_t // make sure that anything we attempt to call has some inlining info, just in case optimization messed up // (except if we know that it is an intrinsic used in our prologue, which should never have its own debug subprogram) Function *F = call->getCalledFunction(); - if (!in_prologue || !F || !(F->isIntrinsic() || F->getName().startswith("julia.") || &I == restTuple)) { + if (!in_prologue || !F || !(F->isIntrinsic() || F->getName().starts_with("julia.") || &I == restTuple)) { I.setDebugLoc(topdebugloc); } } diff --git a/src/coverage.cpp b/src/coverage.cpp index c061276e66fd9..685370198ff13 100644 --- a/src/coverage.cpp +++ b/src/coverage.cpp @@ -207,7 +207,7 @@ extern "C" JL_DLLEXPORT void jl_write_coverage_data(const char *output) { if (output) { StringRef output_pattern(output); - if (output_pattern.endswith(".info")) + if (output_pattern.ends_with(".info")) write_lcov_data(coverageData, jl_format_filename(output_pattern.str().c_str())); } else { diff --git a/src/datatype.c b/src/datatype.c index e7ee15a63f56e..8a7b256db4bef 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -936,6 +936,10 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t * jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); uint32_t nbytes = (nbits + 7) / 8; uint32_t alignm = next_power_of_two(nbytes); +# if defined(_CPU_X86_) && !defined(_OS_WINDOWS_) + if (alignm == 8) + alignm = 4; +# endif if (alignm > MAX_ALIGN) alignm = MAX_ALIGN; // memoize isprimitivetype, since it is much easier than checking diff --git a/src/disasm.cpp b/src/disasm.cpp index b24c374607113..b71503c3f7a77 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -1224,7 +1224,11 @@ jl_value_t *jl_dump_function_asm_impl(jl_llvmf_dump_t* dump, char emit_mc, const addTargetPasses(&PM, TM->getTargetTriple(), TM->getTargetIRAnalysis()); if (emit_mc) { raw_svector_ostream obj_OS(ObjBufferSV); +#if JL_LLVM_VERSION >= 180000 + if (TM->addPassesToEmitFile(PM, obj_OS, nullptr, CodeGenFileType::ObjectFile, false, nullptr)) +#else if (TM->addPassesToEmitFile(PM, obj_OS, nullptr, CGFT_ObjectFile, false, nullptr)) +#endif return jl_an_empty_string; TSM->withModuleDo([&](Module &m) { PM.run(m); }); } diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 487e6a0462500..442103c91be0f 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -3,7 +3,7 @@ #include "llvm-version.h" #include "platform.h" #include -#include +#include #include "llvm/IR/Mangler.h" #include @@ -42,7 +42,11 @@ using namespace llvm; #include "julia_assert.h" #include "processor.h" +#if JL_LLVM_VERSION >= 180000 +# include +#else # include +#endif # include # include # include @@ -564,6 +568,19 @@ jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world, return jl_an_empty_string; } +#if JL_LLVM_VERSION >= 180000 +CodeGenOptLevel CodeGenOptLevelFor(int optlevel) +{ +#ifdef DISABLE_OPT + return CodeGenOptLevel::None; +#else + return optlevel == 0 ? CodeGenOptLevel::None : + optlevel == 1 ? CodeGenOptLevel::Less : + optlevel == 2 ? CodeGenOptLevel::Default : + CodeGenOptLevel::Aggressive; +#endif +} +#else CodeGenOpt::Level CodeGenOptLevelFor(int optlevel) { #ifdef DISABLE_OPT @@ -575,6 +592,7 @@ CodeGenOpt::Level CodeGenOptLevelFor(int optlevel) CodeGenOpt::Aggressive; #endif } +#endif static auto countBasicBlocks(const Function &F) JL_NOTSAFEPOINT { @@ -589,7 +607,7 @@ static Expected validateExternRelocations(orc::ThreadSafe auto F = dyn_cast(&GO); if (!F) return false; - return F->isIntrinsic() || F->getName().startswith("julia."); + return F->isIntrinsic() || F->getName().starts_with("julia."); }; // validate the relocations for M (only for RuntimeDyld, JITLink performs its own symbol validation) auto Err = TSM.withModuleDo([isIntrinsicFunction](Module &M) JL_NOTSAFEPOINT { @@ -1157,7 +1175,7 @@ namespace { { if (*jl_ExecutionEngine->get_dump_llvm_opt_stream()) { for (auto &F : M.functions()) { - if (F.isDeclaration() || F.getName().startswith("jfptr_")) { + if (F.isDeclaration() || F.getName().starts_with("jfptr_")) { continue; } // Each function is printed as a YAML object with several attributes @@ -1210,7 +1228,7 @@ namespace { // Print LLVM function statistics _after_ optimization ios_printf(stream, " after: \n"); for (auto &F : M.functions()) { - if (F.isDeclaration() || F.getName().startswith("jfptr_")) { + if (F.isDeclaration() || F.getName().starts_with("jfptr_")) { continue; } Stat(F).dump(stream); @@ -1397,7 +1415,7 @@ struct JuliaOJIT::DLSymOptimizer { void operator()(Module &M) { for (auto &GV : M.globals()) { auto Name = GV.getName(); - if (Name.startswith("jlplt") && Name.endswith("got")) { + if (Name.starts_with("jlplt") && Name.ends_with("got")) { auto fname = GV.getAttribute("julia.fname").getValueAsString().str(); void *addr; if (GV.hasAttribute("julia.libname")) { @@ -1651,7 +1669,7 @@ JuliaOJIT::JuliaOJIT() DL.getGlobalPrefix(), [&](const orc::SymbolStringPtr &S) { const char *const atomic_prefix = "__atomic_"; - return (*S).startswith(atomic_prefix); + return (*S).starts_with(atomic_prefix); }))); } } @@ -2208,8 +2226,15 @@ static void jl_decorate_module(Module &M) { // Add special values used by debuginfo to build the UnwindData table registration for Win64 // This used to be GV, but with https://reviews.llvm.org/D100944 we no longer can emit GV into `.text` // TODO: The data is set in debuginfo.cpp but it should be okay to actually emit it here. - M.appendModuleInlineAsm("\ - .section .text \n\ + std::string inline_asm = "\ + .section "; + inline_asm += +#if JL_LLVM_VERSION >= 180000 + ".ltext,\"ax\",@progbits"; +#else + ".text"; +#endif + inline_asm += "\n\ .type __UnwindData,@object \n\ .p2align 2, 0x90 \n\ __UnwindData: \n\ @@ -2220,7 +2245,9 @@ static void jl_decorate_module(Module &M) { .p2align 2, 0x90 \n\ __catchjmp: \n\ .zero 12 \n\ - .size __catchjmp, 12"); + .size __catchjmp, 12"; + + M.appendModuleInlineAsm(inline_asm); } } diff --git a/src/jitlayers.h b/src/jitlayers.h index 101f5714abd11..107782e354d4a 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -26,6 +26,7 @@ #include "julia_internal.h" #include "platform.h" #include "llvm-codegen-shared.h" +#include "llvm-version.h" #include #include @@ -645,4 +646,8 @@ void optimizeDLSyms(Module &M); // NewPM #include "passes.h" +#if JL_LLVM_VERSION >= 180000 +CodeGenOptLevel CodeGenOptLevelFor(int optlevel) JL_NOTSAFEPOINT; +#else CodeGenOpt::Level CodeGenOptLevelFor(int optlevel) JL_NOTSAFEPOINT; +#endif diff --git a/src/julia.h b/src/julia.h index 29899f2985a4f..cbe60e78c2d24 100644 --- a/src/julia.h +++ b/src/julia.h @@ -27,22 +27,10 @@ #include #ifndef _OS_WINDOWS_ -# define jl_jmp_buf sigjmp_buf -# if defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_WASM_) -# define MAX_ALIGN 8 -# elif defined(_CPU_AARCH64_) -// int128 is 16 bytes aligned on aarch64 -# define MAX_ALIGN 16 -# elif defined(_P64) -// Generically we assume MAX_ALIGN is sizeof(void*) -# define MAX_ALIGN 8 -# else -# define MAX_ALIGN 4 -# endif + #define jl_jmp_buf sigjmp_buf #else -# include "win32_ucontext.h" -# define jl_jmp_buf jmp_buf -# define MAX_ALIGN 8 + #include "win32_ucontext.h" + #define jl_jmp_buf jmp_buf #endif // Define the largest size (bytes) of a properly aligned object that the diff --git a/src/julia_internal.h b/src/julia_internal.h index 2ec4c9da7452b..d4d1a3239785c 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -17,6 +17,8 @@ #include #include #include +#include + #if !defined(_WIN32) #include #else @@ -98,6 +100,26 @@ JL_DLLIMPORT void __tsan_destroy_fiber(void *fiber); JL_DLLIMPORT void __tsan_switch_to_fiber(void *fiber, unsigned flags); #endif +#ifndef _OS_WINDOWS_ + #if defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_WASM_) + #define MAX_ALIGN 8 + #elif defined(_CPU_AARCH64_) || (JL_LLVM_VERSION >= 180000 && (defined(_CPU_X86_64_) || defined(_CPU_X86_))) + // int128 is 16 bytes aligned on aarch64 and on x86 with LLVM >= 18 + #define MAX_ALIGN 16 + #elif defined(_P64) + // Generically we assume MAX_ALIGN is sizeof(void*) + #define MAX_ALIGN 8 + #else + #define MAX_ALIGN 4 + #endif +#else + #if JL_LLVM_VERSION >= 180000 + #define MAX_ALIGN 16 + #else + #define MAX_ALIGN 8 + #endif +#endif + #ifndef alignof # ifndef __cplusplus # ifdef __GNUC__ diff --git a/src/llvm-cpufeatures.cpp b/src/llvm-cpufeatures.cpp index 2539c5cd2e37c..05d62adc57926 100644 --- a/src/llvm-cpufeatures.cpp +++ b/src/llvm-cpufeatures.cpp @@ -94,7 +94,7 @@ bool lowerCPUFeatures(Module &M) JL_NOTSAFEPOINT for (auto &F: M.functions()) { auto FN = F.getName(); - if (FN.startswith("julia.cpu.have_fma.")) { + if (FN.starts_with("julia.cpu.have_fma.")) { for (Use &U: F.uses()) { User *RU = U.getUser(); CallInst *I = cast(RU); diff --git a/src/llvm-multiversioning.cpp b/src/llvm-multiversioning.cpp index 08600e24490b1..d544f182637b9 100644 --- a/src/llvm-multiversioning.cpp +++ b/src/llvm-multiversioning.cpp @@ -100,11 +100,11 @@ static uint32_t collect_func_info(Function &F, const Triple &TT, bool &has_vecca } if (auto callee = call->getCalledFunction()) { auto name = callee->getName(); - if (name.startswith("llvm.muladd.") || name.startswith("llvm.fma.")) { + if (name.starts_with("llvm.muladd.") || name.starts_with("llvm.fma.")) { flag |= JL_TARGET_CLONE_MATH; } - else if (name.startswith("julia.cpu.")) { - if (name.startswith("julia.cpu.have_fma.")) { + else if (name.starts_with("julia.cpu.")) { + if (name.starts_with("julia.cpu.have_fma.")) { // for some platforms we know they always do (or don't) support // FMA. in those cases we don't need to clone the function. // always_have_fma returns an optional diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index f29802b438e1e..07afa8c930deb 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -177,7 +177,7 @@ static bool processLoop(Loop &L, OptimizationRemarkEmitter &ORE, ScalarEvolution const MDString *S = dyn_cast(Op); if (S) { LLVM_DEBUG(dbgs() << "LSL: found " << S->getString() << "\n"); - if (S->getString().startswith("julia")) { + if (S->getString().starts_with("julia")) { if (S->getString().equals("julia.simdloop")) simd = true; if (S->getString().equals("julia.ivdep")) diff --git a/src/llvm_api.cpp b/src/llvm_api.cpp index d56fb3a0497fa..e98c375b711b3 100644 --- a/src/llvm_api.cpp +++ b/src/llvm_api.cpp @@ -21,6 +21,7 @@ #include #include +#if JL_LLVM_VERSION < 180000 namespace llvm { namespace orc { class OrcV2CAPIHelper { @@ -38,7 +39,7 @@ class OrcV2CAPIHelper { }; } // namespace orc } // namespace llvm - +#endif typedef struct JLOpaqueJuliaOJIT *JuliaOJITRef; typedef struct LLVMOrcOpaqueIRCompileLayer *LLVMOrcIRCompileLayerRef; @@ -46,8 +47,13 @@ typedef struct LLVMOrcOpaqueIRCompileLayer *LLVMOrcIRCompileLayerRef; DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JuliaOJIT, JuliaOJITRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::JITDylib, LLVMOrcJITDylibRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession, LLVMOrcExecutionSessionRef) +#if JL_LLVM_VERSION >= 180000 +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::SymbolStringPoolEntryUnsafe::PoolEntry, + LLVMOrcSymbolStringPoolEntryRef) +#else DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::OrcV2CAPIHelper::PoolEntry, LLVMOrcSymbolStringPoolEntryRef) +#endif DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRCompileLayer, LLVMOrcIRCompileLayerRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility, LLVMOrcMaterializationResponsibilityRef) @@ -113,7 +119,11 @@ JL_DLLEXPORT_CODEGEN LLVMOrcSymbolStringPoolEntryRef JLJITMangleAndIntern_impl(JuliaOJITRef JIT, const char *Name) { +#if JL_LLVM_VERSION >= 180000 + return wrap(orc::SymbolStringPoolEntryUnsafe::take(unwrap(JIT)->mangle(Name)).rawPtr()); +#else return wrap(orc::OrcV2CAPIHelper::moveFromSymbolStringPtr(unwrap(JIT)->mangle(Name))); +#endif } JL_DLLEXPORT_CODEGEN const char * diff --git a/src/pipeline.cpp b/src/pipeline.cpp index f0dde6aa59a40..e01645cc1f154 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -19,18 +19,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -40,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +65,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/processor_arm.cpp b/src/processor_arm.cpp index b9ad5e68111e5..d28e527ed44e8 100644 --- a/src/processor_arm.cpp +++ b/src/processor_arm.cpp @@ -839,7 +839,7 @@ template static inline bool try_read_procfs_line(llvm::StringRef line, const char *prefix, T &out, bool &flag, F &&reset) { - if (!line.startswith(prefix)) + if (!line.starts_with(prefix)) return false; if (flag) reset(); diff --git a/stdlib/LLD_jll/Project.toml b/stdlib/LLD_jll/Project.toml index 4f5e3a6659745..6a6cc72aa3c62 100644 --- a/stdlib/LLD_jll/Project.toml +++ b/stdlib/LLD_jll/Project.toml @@ -1,6 +1,6 @@ name = "LLD_jll" uuid = "d55e3150-da41-5e91-b323-ecfd1eec6109" -version = "17.0.6+4" +version = "18.1.7+2" [deps] Zlib_jll = "83775a58-1f1d-513f-b197-d71354ab007a" @@ -10,7 +10,7 @@ Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [compat] julia = "1.11" -libLLVM_jll = "17.0.6" +libLLVM_jll = "18.1.7" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/stdlib/libLLVM_jll/Project.toml b/stdlib/libLLVM_jll/Project.toml index f6d93dcb94042..a0eac13b3ab23 100644 --- a/stdlib/libLLVM_jll/Project.toml +++ b/stdlib/libLLVM_jll/Project.toml @@ -1,6 +1,6 @@ name = "libLLVM_jll" uuid = "8f36deef-c2a5-5394-99ed-8e07531fb29a" -version = "17.0.6+4" +version = "18.1.7+2" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/test/llvmcall.jl b/test/llvmcall.jl index 98968bfcdf8bc..c83ac05b1ec48 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -70,13 +70,13 @@ end ret i32 %3""", Int32, Tuple{Int32, Int32}, Int32(1), Int32(2))) # llvmcall must be compiled to be called -# Test whether declarations work properly +#Since LLVM 18, LLVM does a best effort to automatically include the intrinsics function undeclared_ceil(x::Float64) llvmcall("""%2 = call double @llvm.ceil.f64(double %0) ret double %2""", Float64, Tuple{Float64}, x) end -@test_throws ErrorException undeclared_ceil(4.2) -@test_throws ErrorException undeclared_ceil(4.2) +@test undeclared_ceil(4.2) == 5.0 +@test undeclared_ceil(4.2) == 5.0 function declared_floor(x::Float64) llvmcall( diff --git a/test/llvmpasses/pipeline-prints.ll b/test/llvmpasses/pipeline-prints.ll index babd26c797a38..ecb70953026c2 100644 --- a/test/llvmpasses/pipeline-prints.ll +++ b/test/llvmpasses/pipeline-prints.ll @@ -298,12 +298,12 @@ attributes #2 = { inaccessiblemem_or_argmemonly } ; COM: Loop simplification makes the exit condition obvious ; AFTERLOOPSIMPLIFICATION: L35.lr.ph: -; AFTERLOOPSIMPLIFICATION-NEXT: add nuw nsw +; AFTERLOOPSIMPLIFICATION: add nuw nsw ; COM: Scalar optimization removes the previous add from the preheader -; AFTERSCALAROPTIMIZATION: L35.preheader: +; AFTERSCALAROPTIMIZATION: L35.lr.ph: ; AFTERSCALAROPTIMIZATION-NOT: add nuw nsw -; AFTERSCALAROPTIMIZATION-NEXT: br label %L35 +; AFTERSCALAROPTIMIZATION: br label %L35 ; COM: Vectorization does stuff ; AFTERVECTORIZATION: vector.body From 22e53624407bc443b9cb12a2380b119e3baf54e3 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Sun, 4 Aug 2024 06:21:32 -0400 Subject: [PATCH 132/206] REPL: enable import completion when in a macro (#55366) Fixes https://github.com/JuliaLang/julia/issues/55361 I think this regressed in https://github.com/JuliaLang/julia/pull/54719 given tests didn't include leading spaces/macros --- stdlib/REPL/src/REPLCompletions.jl | 9 ++++++--- stdlib/REPL/test/replcompletions.jl | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index bc8006ec2ed5d..609a7b4d81bc0 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -900,8 +900,11 @@ const superscript_regex = Regex("^\\\\\\^[" * join(isdigit(k) || isletter(k) ? " # Aux function to detect whether we're right after a using or import keyword function get_import_mode(s::String) + # allow all of these to start with leading whitespace and macros like @eval and @eval( + # ^\s*(?:@\w+\s*(?:\(\s*)?)? + # match simple cases like `using |` and `import |` - mod_import_match_simple = match(r"^\b(using|import)\s*$", s) + mod_import_match_simple = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s*$", s) if mod_import_match_simple !== nothing if mod_import_match_simple[1] == "using" return :using_module @@ -910,7 +913,7 @@ function get_import_mode(s::String) end end # match module import statements like `using Foo|`, `import Foo, Bar|` and `using Foo.Bar, Baz, |` - mod_import_match = match(r"^\b(using|import)\s+([\w\.]+(?:\s*,\s*[\w\.]+)*),?\s*$", s) + mod_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+(?:\s*,\s*[\w\.]+)*),?\s*$", s) if mod_import_match !== nothing if mod_import_match.captures[1] == "using" return :using_module @@ -919,7 +922,7 @@ function get_import_mode(s::String) end end # now match explicit name import statements like `using Foo: |` and `import Foo: bar, baz|` - name_import_match = match(r"^\b(using|import)\s+([\w\.]+)\s*:\s*([\w@!\s,]+)$", s) + name_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+)\s*:\s*([\w@!\s,]+)$", s) if name_import_match !== nothing if name_import_match[1] == "using" return :using_name diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 15e3de2668ba1..3f8addcace73b 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -2238,6 +2238,26 @@ let s = "using .Iss" @test res @test "Issue52922" in c end +let s = " using .Iss" + c, r, res = test_complete_context(s) + @test res + @test "Issue52922" in c +end +let s = "@time using .Iss" + c, r, res = test_complete_context(s) + @test res + @test "Issue52922" in c +end +let s = " @time using .Iss" + c, r, res = test_complete_context(s) + @test res + @test "Issue52922" in c +end +let s = "@time(using .Iss" + c, r, res = test_complete_context(s) + @test res + @test "Issue52922" in c +end let s = "using .Issue52922.Inn" c, r, res = test_complete_context(s) @test res From 065d4567e771af1a642f14c482dd85b3240ec0f3 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 4 Aug 2024 12:30:41 +0000 Subject: [PATCH 133/206] Materialize complex Symmetric matrices in eigen (#55348) Currently, `eigen` for a complex Symmetric matrix fails, as there's no specialized LAPACK function to handle such matrices. We may instead materialize the matrix and use a generic solver. While a user may do it by themselves, I think returning an answer is better than throwing an error. --- stdlib/LinearAlgebra/src/bunchkaufman.jl | 15 +++++++++------ stdlib/LinearAlgebra/src/symmetriceigen.jl | 1 + stdlib/LinearAlgebra/test/hessenberg.jl | 7 +++++++ stdlib/LinearAlgebra/test/symmetriceigen.jl | 6 ++++++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index 5a73c656abe33..a44f1a1c99094 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -127,6 +127,9 @@ function bunchkaufman!(A::StridedMatrix{<:BlasFloat}, rook::Bool = false; check: end end +bkcopy_oftype(A, S) = eigencopy_oftype(A, S) +bkcopy_oftype(A::Symmetric{<:Complex}, S) = Symmetric(copytrito!(similar(parent(A), S, size(A)), A.data, A.uplo), sym_uplo(A.uplo)) + """ bunchkaufman(A, rook::Bool=false; check = true) -> S::BunchKaufman @@ -206,7 +209,7 @@ julia> S.L*S.D*S.L' - A[S.p, S.p] ``` """ bunchkaufman(A::AbstractMatrix{T}, rook::Bool=false; check::Bool = true) where {T} = - bunchkaufman!(eigencopy_oftype(A, typeof(sqrt(oneunit(T)))), rook; check = check) + bunchkaufman!(bkcopy_oftype(A, typeof(sqrt(oneunit(T)))), rook; check = check) BunchKaufman{T}(B::BunchKaufman) where {T} = BunchKaufman(convert(Matrix{T}, B.LD), B.ipiv, B.uplo, B.symmetric, B.rook, B.info) @@ -1540,7 +1543,7 @@ function bunchkaufman(A::AbstractMatrix{TS}, rook::Bool = false; check::Bool = true ) where TS <: ClosedScalar{TR} where TR <: ClosedReal - return bunchkaufman!(eigencopy_oftype(A, TS), rook; check) + return bunchkaufman!(bkcopy_oftype(A, TS), rook; check) end function bunchkaufman(A::AbstractMatrix{TS}, @@ -1562,15 +1565,15 @@ function bunchkaufman(A::AbstractMatrix{TS}, # We promote input to BigInt to avoid overflow problems if TA == Nothing if TS <: Integer - M = Rational{BigInt}.(eigencopy_oftype(A, TS)) + M = Rational{BigInt}.(bkcopy_oftype(A, TS)) else - M = Complex{Rational{BigInt}}.(eigencopy_oftype(A, TS)) + M = Complex{Rational{BigInt}}.(bkcopy_oftype(A, TS)) end else if TS <: Integer - M = TA(Rational{BigInt}.(eigencopy_oftype(A, TS)), Symbol(A.uplo)) + M = TA(Rational{BigInt}.(bkcopy_oftype(A, TS)), Symbol(A.uplo)) else - M = TA(Complex{Rational{BigInt}}.(eigencopy_oftype(A, TS)), + M = TA(Complex{Rational{BigInt}}.(bkcopy_oftype(A, TS)), Symbol(A.uplo)) end end diff --git a/stdlib/LinearAlgebra/src/symmetriceigen.jl b/stdlib/LinearAlgebra/src/symmetriceigen.jl index 666b9a9bc81df..fee524a702187 100644 --- a/stdlib/LinearAlgebra/src/symmetriceigen.jl +++ b/stdlib/LinearAlgebra/src/symmetriceigen.jl @@ -4,6 +4,7 @@ # Call `copytrito!` instead of `copy_similar` to only copy the matching triangular half eigencopy_oftype(A::Hermitian, S) = Hermitian(copytrito!(similar(parent(A), S, size(A)), A.data, A.uplo), sym_uplo(A.uplo)) eigencopy_oftype(A::Symmetric, S) = Symmetric(copytrito!(similar(parent(A), S, size(A)), A.data, A.uplo), sym_uplo(A.uplo)) +eigencopy_oftype(A::Symmetric{<:Complex}, S) = copyto!(similar(parent(A), S), A) default_eigen_alg(A) = DivideAndConquer() diff --git a/stdlib/LinearAlgebra/test/hessenberg.jl b/stdlib/LinearAlgebra/test/hessenberg.jl index 767f40aa1e53f..54dbb70aa2065 100644 --- a/stdlib/LinearAlgebra/test/hessenberg.jl +++ b/stdlib/LinearAlgebra/test/hessenberg.jl @@ -272,4 +272,11 @@ end @test S[1,2] == S[Int8(1),UInt16(2)] == S[big(1), Int16(2)] end +@testset "complex Symmetric" begin + D = diagm(0=>ComplexF64[1,2]) + S = Symmetric(D) + H = hessenberg(S) + @test H.H == D +end + end # module TestHessenberg diff --git a/stdlib/LinearAlgebra/test/symmetriceigen.jl b/stdlib/LinearAlgebra/test/symmetriceigen.jl index cacdb72c63071..d55d1deb6bf33 100644 --- a/stdlib/LinearAlgebra/test/symmetriceigen.jl +++ b/stdlib/LinearAlgebra/test/symmetriceigen.jl @@ -173,4 +173,10 @@ end @test D.vectors ≈ D32.vectors end +@testset "complex Symmetric" begin + S = Symmetric(rand(ComplexF64,2,2)) + λ, v = eigen(S) + @test S * v ≈ v * Diagonal(λ) +end + end # module TestSymmetricEigen From f4d1381b7c1242a17815bba6febeeb9a3a40c093 Mon Sep 17 00:00:00 2001 From: James Wrigley Date: Sun, 4 Aug 2024 23:14:40 +0200 Subject: [PATCH 134/206] Document `Threads.threadid(::Task)` (#55369) This is quite handy to figure out which thread a task is running on, and I couldn't find another way to do it from outside the task. --- base/threadingconstructs.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 479bcd80c586d..a21d708b4a077 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -4,10 +4,10 @@ export threadid, nthreads, @threads, @spawn, threadpool, nthreadpools """ - Threads.threadid() -> Int + Threads.threadid([t::Task]) -> Int -Get the ID number of the current thread of execution. The master thread has -ID `1`. +Get the ID number of the current thread of execution, or the thread of task +`t`. The master thread has ID `1`. # Examples ```julia-repl @@ -21,12 +21,15 @@ julia> Threads.@threads for i in 1:4 2 5 4 + +julia> Threads.threadid(Threads.@spawn "foo") +2 ``` !!! note The thread that a task runs on may change if the task yields, which is known as [`Task Migration`](@ref man-task-migration). - For this reason in most cases it is not safe to use `threadid()` to index into, say, a vector of buffer or stateful objects. - + For this reason in most cases it is not safe to use `threadid([task])` to index into, say, a vector of buffers or stateful + objects. """ threadid() = Int(ccall(:jl_threadid, Int16, ())+1) From a163483e6714631e9f6fecf141bd2dca999fbd6a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 5 Aug 2024 06:06:39 +0000 Subject: [PATCH 135/206] Fix tr for block SymTridiagonal (#55371) This ensures that `tr` for a block `SymTridiagonal` symmetrizes the diagonal elements. --- stdlib/LinearAlgebra/src/tridiag.jl | 2 +- stdlib/LinearAlgebra/test/tridiag.jl | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 3198e45ad3eb8..2ff688f4b4ed1 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -181,7 +181,7 @@ Base.copy(S::Adjoint{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(ad ishermitian(S::SymTridiagonal) = isreal(S.dv) && isreal(_evview(S)) issymmetric(S::SymTridiagonal) = true -tr(S::SymTridiagonal) = sum(S.dv) +tr(S::SymTridiagonal) = sum(symmetric, S.dv) @noinline function throw_diag_outofboundserror(n, sz) sz1, sz2 = sz diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index fae708c4c8db4..5dc1d01e850d8 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -471,7 +471,7 @@ end end @testset "SymTridiagonal/Tridiagonal block matrix" begin - M = [1 2; 2 4] + M = [1 2; 3 4] n = 5 A = SymTridiagonal(fill(M, n), fill(M, n-1)) @test @inferred A[1,1] == Symmetric(M) @@ -485,6 +485,9 @@ end @test_throws ArgumentError diag(A, n+1) @test_throws ArgumentError diag(A, -n-1) + @test tr(A) == sum(diag(A)) + @test issymmetric(tr(A)) + A = Tridiagonal(fill(M, n-1), fill(M, n), fill(M, n-1)) @test @inferred A[1,1] == M @test @inferred A[1,2] == M From 996351f5f6651d1508aef3c35c7d37eb22a0fb1e Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 5 Aug 2024 06:07:12 +0000 Subject: [PATCH 136/206] Round-trippable show for `Bidiagonal` (#55347) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes how a `Bidiagonal` is displayed using the 2-arg `show` to a form that may be parsed. After this, ```julia julia> B = Bidiagonal([1,2,3], [1,2], :U) 3×3 Bidiagonal{Int64, Vector{Int64}}: 1 1 ⋅ ⋅ 2 2 ⋅ ⋅ 3 julia> show(B) Bidiagonal([1, 2, 3], [1, 2], :U) ``` The displayed form is a valid constructor now. --- stdlib/LinearAlgebra/src/bidiag.jl | 13 +++++++------ stdlib/LinearAlgebra/test/bidiag.jl | 6 ++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 5f9a64904bd38..e2572c0f67af9 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -264,12 +264,13 @@ end #################### function show(io::IO, M::Bidiagonal) - # TODO: make this readable and one-line - summary(io, M) - print(io, ":\n diag:") - print_matrix(io, (M.dv)') - print(io, M.uplo == 'U' ? "\n super:" : "\n sub:") - print_matrix(io, (M.ev)') + print(io, "Bidiagonal(") + show(io, M.dv) + print(io, ", ") + show(io, M.ev) + print(io, ", ") + show(io, sym_uplo(M.uplo)) + print(io, ")") end size(M::Bidiagonal) = (n = length(M.dv); (n, n)) diff --git a/stdlib/LinearAlgebra/test/bidiag.jl b/stdlib/LinearAlgebra/test/bidiag.jl index 37503efe42518..3c99d0d3b6f5e 100644 --- a/stdlib/LinearAlgebra/test/bidiag.jl +++ b/stdlib/LinearAlgebra/test/bidiag.jl @@ -143,11 +143,9 @@ Random.seed!(1) @testset "show" begin BD = Bidiagonal(dv, ev, :U) - dstring = sprint(Base.print_matrix,BD.dv') - estring = sprint(Base.print_matrix,BD.ev') - @test sprint(show,BD) == "$(summary(BD)):\n diag:$dstring\n super:$estring" + @test sprint(show,BD) == "Bidiagonal($(repr(dv)), $(repr(ev)), :U)" BD = Bidiagonal(dv,ev,:L) - @test sprint(show,BD) == "$(summary(BD)):\n diag:$dstring\n sub:$estring" + @test sprint(show,BD) == "Bidiagonal($(repr(dv)), $(repr(ev)), :L)" end @testset for uplo in (:U, :L) From 40ecf690197a7a6221cfcffd9c74799258fb4495 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Mon, 5 Aug 2024 12:54:45 +0000 Subject: [PATCH 137/206] LinearAlgbera: pass sizes to muldiag_size_check (#55378) This will avoid having to specialize `_muldiag_size_check` on the matrix types, as we only need the sizes (and potentially `ndims`) for the error checks. --- stdlib/LinearAlgebra/src/bidiag.jl | 8 ++--- stdlib/LinearAlgebra/src/diagonal.jl | 53 +++++++++++++--------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index e2572c0f67af9..0caaec02b5056 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -461,7 +461,7 @@ const BiTri = Union{Bidiagonal,Tridiagonal} # B .= A * B function lmul!(A::Bidiagonal, B::AbstractVecOrMat) - _muldiag_size_check(A, B) + _muldiag_size_check(size(A), size(B)) (; dv, ev) = A if A.uplo == 'U' for k in axes(B,2) @@ -482,7 +482,7 @@ function lmul!(A::Bidiagonal, B::AbstractVecOrMat) end # B .= D * B function lmul!(D::Diagonal, B::Bidiagonal) - _muldiag_size_check(D, B) + _muldiag_size_check(size(D), size(B)) (; dv, ev) = B isL = B.uplo == 'L' dv[1] = D.diag[1] * dv[1] @@ -494,7 +494,7 @@ function lmul!(D::Diagonal, B::Bidiagonal) end # B .= B * A function rmul!(B::AbstractMatrix, A::Bidiagonal) - _muldiag_size_check(A, B) + _muldiag_size_check(size(A), size(B)) (; dv, ev) = A if A.uplo == 'U' for k in reverse(axes(dv,1)[2:end]) @@ -519,7 +519,7 @@ function rmul!(B::AbstractMatrix, A::Bidiagonal) end # B .= B * D function rmul!(B::Bidiagonal, D::Diagonal) - _muldiag_size_check(B, D) + _muldiag_size_check(size(B), size(D)) (; dv, ev) = B isU = B.uplo == 'U' dv[1] *= D.diag[1] diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 8f643a0054719..9cd13b4d26f00 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -293,42 +293,39 @@ Base.literal_pow(::typeof(^), D::Diagonal, valp::Val) = Diagonal(Base.literal_pow.(^, D.diag, valp)) # for speed Base.literal_pow(::typeof(^), D::Diagonal, ::Val{-1}) = inv(D) # for disambiguation -function _muldiag_size_check(A, B) - nA = size(A, 2) - mB = size(B, 1) - @noinline throw_dimerr(::AbstractMatrix, nA, mB) = throw(DimensionMismatch(lazy"second dimension of A, $nA, does not match first dimension of B, $mB")) - @noinline throw_dimerr(::AbstractVector, nA, mB) = throw(DimensionMismatch(lazy"second dimension of D, $nA, does not match length of V, $mB")) - nA == mB || throw_dimerr(B, nA, mB) +function _muldiag_size_check(szA::NTuple{2,Integer}, szB::Tuple{Integer,Vararg{Integer}}) + nA = szA[2] + mB = szB[1] + @noinline throw_dimerr(szB::NTuple{2}, nA, mB) = throw(DimensionMismatch(lazy"second dimension of A, $nA, does not match first dimension of B, $mB")) + @noinline throw_dimerr(szB::NTuple{1}, nA, mB) = throw(DimensionMismatch(lazy"second dimension of D, $nA, does not match length of V, $mB")) + nA == mB || throw_dimerr(szB, nA, mB) return nothing end # the output matrix should have the same size as the non-diagonal input matrix or vector @noinline throw_dimerr(szC, szA) = throw(DimensionMismatch(lazy"output matrix has size: $szC, but should have size $szA")) -_size_check_out(C, ::Diagonal, A) = _size_check_out(C, A) -_size_check_out(C, A, ::Diagonal) = _size_check_out(C, A) -_size_check_out(C, A::Diagonal, ::Diagonal) = _size_check_out(C, A) -function _size_check_out(C, A) - szA = size(A) - szC = size(C) - szA == szC || throw_dimerr(szC, szA) - return nothing +function _size_check_out(szC::NTuple{2}, szA::NTuple{2}, szB::NTuple{2}) + (szC[1] == szA[1] && szC[2] == szB[2]) || throw_dimerr(szC, (szA[1], szB[2])) +end +function _size_check_out(szC::NTuple{1}, szA::NTuple{2}, szB::NTuple{1}) + szC[1] == szA[1] || throw_dimerr(szC, (szA[1],)) end -function _muldiag_size_check(C, A, B) - _muldiag_size_check(A, B) - _size_check_out(C, A, B) +function _muldiag_size_check(szC::Tuple{Vararg{Integer}}, szA::Tuple{Vararg{Integer}}, szB::Tuple{Vararg{Integer}}) + _muldiag_size_check(szA, szB) + _size_check_out(szC, szA, szB) end function (*)(Da::Diagonal, Db::Diagonal) - _muldiag_size_check(Da, Db) + _muldiag_size_check(size(Da), size(Db)) return Diagonal(Da.diag .* Db.diag) end function (*)(D::Diagonal, V::AbstractVector) - _muldiag_size_check(D, V) + _muldiag_size_check(size(D), size(V)) return D.diag .* V end function rmul!(A::AbstractMatrix, D::Diagonal) - _muldiag_size_check(A, D) + _muldiag_size_check(size(A), size(D)) for I in CartesianIndices(A) row, col = Tuple(I) @inbounds A[row, col] *= D.diag[col] @@ -337,7 +334,7 @@ function rmul!(A::AbstractMatrix, D::Diagonal) end # T .= T * D function rmul!(T::Tridiagonal, D::Diagonal) - _muldiag_size_check(T, D) + _muldiag_size_check(size(T), size(D)) (; dl, d, du) = T d[1] *= D.diag[1] for i in axes(dl,1) @@ -349,7 +346,7 @@ function rmul!(T::Tridiagonal, D::Diagonal) end function lmul!(D::Diagonal, B::AbstractVecOrMat) - _muldiag_size_check(D, B) + _muldiag_size_check(size(D), size(B)) for I in CartesianIndices(B) row = I[1] @inbounds B[I] = D.diag[row] * B[I] @@ -360,7 +357,7 @@ end # in-place multiplication with a diagonal # T .= D * T function lmul!(D::Diagonal, T::Tridiagonal) - _muldiag_size_check(D, T) + _muldiag_size_check(size(D), size(T)) (; dl, d, du) = T d[1] = D.diag[1] * d[1] for i in axes(dl,1) @@ -452,7 +449,7 @@ function __muldiag!(out, D1::Diagonal, D2::Diagonal, _add::MulAddMul{ais1,bis0}) end function _mul_diag!(out, A, B, _add) - _muldiag_size_check(out, A, B) + _muldiag_size_check(size(out), size(A), size(B)) __muldiag!(out, A, B, _add) return out end @@ -469,14 +466,14 @@ _mul!(C::AbstractMatrix, Da::Diagonal, Db::Diagonal, _add) = _mul_diag!(C, Da, Db, _add) function (*)(Da::Diagonal, A::AbstractMatrix, Db::Diagonal) - _muldiag_size_check(Da, A) - _muldiag_size_check(A, Db) + _muldiag_size_check(size(Da), size(A)) + _muldiag_size_check(size(A), size(Db)) return broadcast(*, Da.diag, A, permutedims(Db.diag)) end function (*)(Da::Diagonal, Db::Diagonal, Dc::Diagonal) - _muldiag_size_check(Da, Db) - _muldiag_size_check(Db, Dc) + _muldiag_size_check(size(Da), size(Db)) + _muldiag_size_check(size(Db), size(Dc)) return Diagonal(Da.diag .* Db.diag .* Dc.diag) end From 4200203453c9c47c2df88f0c3b90dec46aeb2620 Mon Sep 17 00:00:00 2001 From: Satvik Date: Mon, 5 Aug 2024 12:44:48 -0700 Subject: [PATCH 138/206] Replace `@async` mentions in manual with `Threads.@spawn` (#55315) --- doc/src/base/parallel.md | 2 +- doc/src/devdocs/probes.md | 6 +++--- doc/src/manual/asynchronous-programming.md | 10 +++++----- doc/src/manual/distributed-computing.md | 8 ++++---- doc/src/manual/faq.md | 6 +++--- doc/src/manual/methods.md | 4 ++-- doc/src/manual/networking-and-streams.md | 14 +++++++------- doc/src/manual/performance-tips.md | 2 +- doc/src/manual/running-external-programs.md | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/src/base/parallel.md b/doc/src/base/parallel.md index 58ec078a8e0cf..9f24db176b538 100644 --- a/doc/src/base/parallel.md +++ b/doc/src/base/parallel.md @@ -138,7 +138,7 @@ end ev = OneWayEvent() @sync begin - @async begin + Threads.@spawn begin wait(ev) println("done") end diff --git a/doc/src/devdocs/probes.md b/doc/src/devdocs/probes.md index 5a1af0d897bc6..a0e072c0b1ae3 100644 --- a/doc/src/devdocs/probes.md +++ b/doc/src/devdocs/probes.md @@ -206,7 +206,7 @@ Now we can start `bpftrace` and have it monitor `rt__new__task` for *only* this And if we spawn a single task: -`@async 1+1` +`Threads.@spawn 1+1` we see this task being created: @@ -215,8 +215,8 @@ we see this task being created: However, if we spawn a bunch of tasks from that newly-spawned task: ```julia -@async for i in 1:10 - @async 1+1 +Threads.@spawn for i in 1:10 + Threads.@spawn 1+1 end ``` diff --git a/doc/src/manual/asynchronous-programming.md b/doc/src/manual/asynchronous-programming.md index 15db6eda5f807..d1d095c48b2ff 100644 --- a/doc/src/manual/asynchronous-programming.md +++ b/doc/src/manual/asynchronous-programming.md @@ -64,8 +64,8 @@ the next input prompt appears. That is because the REPL is waiting for `t` to finish before proceeding. It is common to want to create a task and schedule it right away, so the -macro [`@async`](@ref) is provided for that purpose --- `@async x` is -equivalent to `schedule(@task x)`. +macro [`Threads.@spawn`](@ref) is provided for that purpose --- `Threads.@spawn x` is +equivalent to `task = @task x; task.sticky = false; schedule(task)`. ## Communicating with Channels @@ -186,7 +186,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and a read end : # we can schedule `n` instances of `foo` to be active concurrently. for _ in 1:n - errormonitor(@async foo()) + errormonitor(Threads.@spawn foo()) end ``` * Channels are created via the `Channel{T}(sz)` constructor. The channel will only hold objects @@ -264,10 +264,10 @@ julia> function make_jobs(n) julia> n = 12; -julia> errormonitor(@async make_jobs(n)); # feed the jobs channel with "n" jobs +julia> errormonitor(Threads.@spawn make_jobs(n)); # feed the jobs channel with "n" jobs julia> for i in 1:4 # start 4 tasks to process requests in parallel - errormonitor(@async do_work()) + errormonitor(Threads.@spawn do_work()) end julia> @elapsed while n > 0 # print out results diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index d325239fc9e2d..f60dfb7004ada 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -123,7 +123,7 @@ An important thing to remember is that, once fetched, a [`Future`](@ref Distribu locally. Further [`fetch`](@ref) calls do not entail a network hop. Once all referencing [`Future`](@ref Distributed.Future)s have fetched, the remote stored value is deleted. -[`@async`](@ref) is similar to [`@spawnat`](@ref), but only runs tasks on the local process. We +[`Threads.@spawn`](@ref) is similar to [`@spawnat`](@ref), but only runs tasks on the local process. We use it to create a "feeder" task for each process. Each task picks the next index that needs to be computed, then waits for its process to finish, then repeats until we run out of indices. Note that the feeder tasks do not begin to execute until the main task reaches the end of the [`@sync`](@ref) @@ -657,7 +657,7 @@ julia> function make_jobs(n) julia> n = 12; -julia> errormonitor(@async make_jobs(n)); # feed the jobs channel with "n" jobs +julia> errormonitor(Threads.@spawn make_jobs(n)); # feed the jobs channel with "n" jobs julia> for p in workers() # start tasks on the workers to process requests in parallel remote_do(do_work, p, jobs, results) @@ -896,7 +896,7 @@ conflicts. For example: ```julia @sync begin for p in procs(S) - @async begin + Threads.@spawn begin remotecall_wait(fill!, p, S, p) end end @@ -978,7 +978,7 @@ and one that delegates in chunks: julia> function advection_shared!(q, u) @sync begin for p in procs(q) - @async remotecall_wait(advection_shared_chunk!, p, q, u) + Threads.@spawn remotecall_wait(advection_shared_chunk!, p, q, u) end end q diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 8984e1d15ddd3..2673ca7532acf 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -943,7 +943,7 @@ Consider the printed output from the following: ```jldoctest julia> @sync for i in 1:3 - @async write(stdout, string(i), " Foo ", " Bar ") + Threads.@spawn write(stdout, string(i), " Foo ", " Bar ") end 123 Foo Foo Foo Bar Bar Bar ``` @@ -956,7 +956,7 @@ in the above example results in: ```jldoctest julia> @sync for i in 1:3 - @async println(stdout, string(i), " Foo ", " Bar ") + Threads.@spawn println(stdout, string(i), " Foo ", " Bar ") end 1 Foo Bar 2 Foo Bar @@ -969,7 +969,7 @@ You can lock your writes with a `ReentrantLock` like this: julia> l = ReentrantLock(); julia> @sync for i in 1:3 - @async begin + Threads.@spawn begin lock(l) try write(stdout, string(i), " Foo ", " Bar ") diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index d45644bf55842..6be44dcf4fa13 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -614,7 +614,7 @@ Start some other operations that use `f(x)`: julia> g(x) = f(x) g (generic function with 1 method) -julia> t = @async f(wait()); yield(); +julia> t = Threads.@spawn f(wait()); yield(); ``` Now we add some new methods to `f(x)`: @@ -639,7 +639,7 @@ julia> g(1) julia> fetch(schedule(t, 1)) "original definition" -julia> t = @async f(wait()); yield(); +julia> t = Threads.@spawn f(wait()); yield(); julia> fetch(schedule(t, 1)) "definition for Int" diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index 45bf60a7944d2..35ba7fdf16601 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -233,7 +233,7 @@ Let's first create a simple server: ```julia-repl julia> using Sockets -julia> errormonitor(@async begin +julia> errormonitor(Threads.@spawn begin server = listen(2000) while true sock = accept(server) @@ -305,11 +305,11 @@ printed the message and waited for the next client. Reading and writing works in To see this, consider the following simple echo server: ```julia-repl -julia> errormonitor(@async begin +julia> errormonitor(Threads.@spawn begin server = listen(2001) while true sock = accept(server) - @async while isopen(sock) + Threads.@spawn while isopen(sock) write(sock, readline(sock, keep=true)) end end @@ -319,7 +319,7 @@ Task (runnable) @0x00007fd31dc12e60 julia> clientside = connect(2001) TCPSocket(RawFD(28) open, 0 bytes waiting) -julia> errormonitor(@async while isopen(clientside) +julia> errormonitor(Threads.@spawn while isopen(clientside) write(stdout, readline(clientside, keep=true)) end) Task (runnable) @0x00007fd31dc11870 @@ -357,10 +357,10 @@ ip"74.125.226.225" All I/O operations exposed by [`Base.read`](@ref) and [`Base.write`](@ref) can be performed asynchronously through the use of [coroutines](@ref man-tasks). You can create a new coroutine to -read from or write to a stream using the [`@async`](@ref) macro: +read from or write to a stream using the [`Threads.@spawn`](@ref) macro: ```julia-repl -julia> task = @async open("foo.txt", "w") do io +julia> task = Threads.@spawn open("foo.txt", "w") do io write(io, "Hello, World!") end; @@ -379,7 +379,7 @@ your program to block until all of the coroutines it wraps around have exited: julia> using Sockets julia> @sync for hostname in ("google.com", "github.com", "julialang.org") - @async begin + Threads.@spawn begin conn = connect(hostname, 80) write(conn, "GET / HTTP/1.1\r\nHost:$(hostname)\r\n\r\n") readline(conn, keep=true) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 5c10652eb99cb..38e27476f0af8 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1723,7 +1723,7 @@ using Distributed responses = Vector{Any}(undef, nworkers()) @sync begin for (idx, pid) in enumerate(workers()) - @async responses[idx] = remotecall_fetch(foo, pid, args...) + Threads.@spawn responses[idx] = remotecall_fetch(foo, pid, args...) end end ``` diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index 4a9803337990b..1f9f3129ca16b 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -332,8 +332,8 @@ will attempt to store the data in the kernel's buffers while waiting for a reade Another common solution is to separate the reader and writer of the pipeline into separate [`Task`](@ref)s: ```julia -writer = @async write(process, "data") -reader = @async do_compute(read(process, String)) +writer = Threads.@spawn write(process, "data") +reader = Threads.@spawn do_compute(read(process, String)) wait(writer) fetch(reader) ``` From e38e4db8f80f91ba0968736936ce4fcb1c835240 Mon Sep 17 00:00:00 2001 From: GHTaarn <62629455+GHTaarn@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:52:35 +0200 Subject: [PATCH 139/206] Make REPL.TerminalMenus and some if its symbols public (#55307) --- stdlib/REPL/src/REPL.jl | 2 ++ stdlib/REPL/src/TerminalMenus/TerminalMenus.jl | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 558f6ed9cab6f..67f5860082c8a 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -110,6 +110,8 @@ export LineEditREPL, StreamREPL +public TerminalMenus + import Base: AbstractDisplay, display, diff --git a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl index ffbe32575fea1..f970cd9a289c2 100644 --- a/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl +++ b/stdlib/REPL/src/TerminalMenus/TerminalMenus.jl @@ -1,5 +1,12 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + REPL.TerminalMenus + +A module that contains code for displaying text mode interactive menus. +Key exported symbols include [`REPL.TerminalMenus.RadioMenu`](@ref) and +[`REPL.TerminalMenus.MultiSelectMenu`](@ref). +""" module TerminalMenus using ..REPL: REPL @@ -23,6 +30,9 @@ export Pager, request +public Config, config, MultiSelectConfig +public pick, cancel, writeline, options, numoptions, selected, header, keypress + # TODO: remove in Julia 2.0 # While not exported, AbstractMenu documented these as an extension interface @deprecate printMenu printmenu From 6ad6a8f1e8b960d8ecb114a03e8e0eebf712abfb Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Mon, 5 Aug 2024 16:01:02 -0400 Subject: [PATCH 140/206] Delete broken and unhelpful const mutation example from docs (#55182) --- doc/src/manual/variables-and-scoping.md | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 85a83120dc517..de97ff296e37e 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -755,28 +755,7 @@ julia> const z = 100 julia> z = 100 100 ``` -The last rule applies to immutable objects even if the variable binding would change, e.g.: -```julia-repl -julia> const s1 = "1" -"1" - -julia> s2 = "1" -"1" - -julia> pointer.([s1, s2], 1) -2-element Array{Ptr{UInt8},1}: - Ptr{UInt8} @0x00000000132c9638 - Ptr{UInt8} @0x0000000013dd3d18 - -julia> s1 = s2 -"1" - -julia> pointer.([s1, s2], 1) -2-element Array{Ptr{UInt8},1}: - Ptr{UInt8} @0x0000000013dd3d18 - Ptr{UInt8} @0x0000000013dd3d18 -``` -However, for mutable objects the warning is printed as expected: +* if an assignment would change the mutable object to which the variable points (regardless of whether those two objects are deeply equal), a warning is printed: ```jldoctest julia> const a = [1] 1-element Vector{Int64}: From d1b1a5dd254e127edc994076cce61ae1cca16979 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 5 Aug 2024 16:46:54 -0400 Subject: [PATCH 141/206] inference: fix missing LimitedAccuracy markers (#55362) If the LimitedAccuracy was supposed to resolve against the top-most frame (or hypothetically a non-InferenceState frame), it would not have a parentframe, preventing it from reaching the subsequent poison_callstack line that is required for reliable inference (avoiding caching bad results). This should restore the original intent of this code (pre #48913) --- base/compiler/abstractinterpretation.jl | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 6a7d90a7bcb21..e3e3502d66173 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -698,13 +698,23 @@ function abstract_call_method(interp::AbstractInterpreter, end add_remark!(interp, sv, washardlimit ? RECURSION_MSG_HARDLIMIT : RECURSION_MSG) # TODO (#48913) implement a proper recursion handling for irinterp: - # This works just because currently the `:terminate` condition guarantees that - # irinterp doesn't fail into unresolved cycles, but it's not a good solution. + # This works just because currently the `:terminate` condition usually means this is unreachable here + # for irinterp because there are not unresolved cycles, but it's not a good solution. # We should revisit this once we have a better story for handling cycles in irinterp. - if isa(topmost, InferenceState) + if isa(sv, InferenceState) + # since the hardlimit is against the edge to the parent frame, + # we should try to poison the whole edge, not just the topmost frame parentframe = frame_parent(topmost) - if isa(sv, InferenceState) && isa(parentframe, InferenceState) - poison_callstack!(sv, parentframe === nothing ? topmost : parentframe) + while !isa(parentframe, InferenceState) + # attempt to find a parent frame that can handle this LimitedAccuracy result correctly + # so we don't try to cache this incomplete intermediate result + parentframe === nothing && break + parentframe = frame_parent(parentframe) + end + if isa(parentframe, InferenceState) + poison_callstack!(sv, parentframe) + elseif isa(topmost, InferenceState) + poison_callstack!(sv, topmost) end end # n.b. this heuristic depends on the non-local state, so we must record the limit later From 1b32fa6825739ab68542f6ea476b09931f77ec40 Mon Sep 17 00:00:00 2001 From: Michael Abbott <32575566+mcabbott@users.noreply.github.com> Date: Mon, 5 Aug 2024 22:39:30 -0400 Subject: [PATCH 142/206] Compact printing for `Adjoint` vectors, and `Diagonal` (#40722) This changes the compact printing to preserve more information -- an adjoint vector is not quite a matrix, and Diagonal wastes a lot of space: ```julia julia> (Diagonal(1:4), [5,6,7]', transpose(8:10)) # before ([1 0 0 0; 0 2 0 0; 0 0 3 0; 0 0 0 4], [5 6 7], [8 9 10]) julia> (Diagonal(1:4), [5,6,7]', transpose(8:10)) # after (Diagonal(1:4), adjoint([5, 6, 7]), transpose(8:10)) ``` Would have been better to do at the same time as 1.6's other printing changes, I guess. --------- Co-authored-by: Jishnu Bhattacharya --- base/abstractarray.jl | 2 +- stdlib/LinearAlgebra/src/adjtrans.jl | 10 ++++++++++ stdlib/LinearAlgebra/src/diagonal.jl | 5 +++++ stdlib/LinearAlgebra/test/adjtrans.jl | 5 +++++ stdlib/LinearAlgebra/test/diagonal.jl | 5 +++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2fbae2c423196..40e36ce15f6ed 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1921,7 +1921,7 @@ julia> vcat(range(1, 2, length=3)) # collects lazy ranges 2.0 julia> two = ([10, 20, 30]', Float64[4 5 6; 7 8 9]) # row vector and a matrix -([10 20 30], [4.0 5.0 6.0; 7.0 8.0 9.0]) +(adjoint([10, 20, 30]), [4.0 5.0 6.0; 7.0 8.0 9.0]) julia> vcat(two...) 3×3 Matrix{Float64}: diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index daee587b82835..b722e49bb2c3d 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -302,6 +302,16 @@ function Base.showarg(io::IO, v::Transpose, toplevel) toplevel && print(io, " with eltype ", eltype(v)) return nothing end +function Base.show(io::IO, v::Adjoint{<:Real, <:AbstractVector}) + print(io, "adjoint(") + show(io, parent(v)) + print(io, ")") +end +function Base.show(io::IO, v::Transpose{<:Number, <:AbstractVector}) + print(io, "transpose(") + show(io, parent(v)) + print(io, ")") +end # some aliases for internal convenience use const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S} diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 9cd13b4d26f00..89202e66597f8 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -213,6 +213,11 @@ end function Base.replace_in_print_matrix(A::Diagonal,i::Integer,j::Integer,s::AbstractString) i==j ? s : Base.replace_with_centered_mark(s) end +function Base.show(io::IO, A::Diagonal) + print(io, "Diagonal(") + show(io, A.diag) + print(io, ")") +end parent(D::Diagonal) = D.diag diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 1a66c7430723e..6cf2ff9ada09c 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -532,6 +532,11 @@ end @test String(take!(io)) == "transpose(::Matrix{Float64})" end +@testset "show" begin + @test repr(adjoint([1,2,3])) == "adjoint([1, 2, 3])" + @test repr(transpose([1f0,2f0])) == "transpose(Float32[1.0, 2.0])" +end + @testset "strided transposes" begin for t in (Adjoint, Transpose) @test strides(t(rand(3))) == (3, 1) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index e1fc9afa5ad2e..29f3a38473d4a 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -1231,6 +1231,11 @@ Base.size(::SMatrix1) = (1, 1) @test C isa Matrix{SMatrix1{String}} end +@testset "show" begin + @test repr(Diagonal([1,2])) == "Diagonal([1, 2])" # 2-arg show + @test contains(repr(MIME"text/plain"(), Diagonal([1,2])), "⋅ 2") # 3-arg show +end + @testset "copyto! with UniformScaling" begin @testset "Fill" begin for len in (4, InfiniteArrays.Infinity()) From b0a8024a4598f60f72a0799b3b60a29383188523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Tue, 6 Aug 2024 10:46:41 +0200 Subject: [PATCH 143/206] [build] Some improvements to the LLVM build system (#55354) ### Elaboration of the issue After #55180 we implicitly require an LLVM built with Zlib support, but compiling Julia with `make USE_BINARYBUILDER_LLVM=0` builds an LLVM without Zlib support, despite the fact we attempt to request it at https://github.com/JuliaLang/julia/blob/996351f5f6651d1508aef3c35c7d37eb22a0fb1e/deps/llvm.mk#L97 This was first identified in #55337. ### Explanation of how configuration of LLVM failed `ZLIB_LIBRARY` must be the path to the zlib library, but we currently set it to the libdir where the library is installed (introduced in #42622): https://github.com/JuliaLang/julia/blob/996351f5f6651d1508aef3c35c7d37eb22a0fb1e/deps/llvm.mk#L97 which is wrong. However, CMake is actually able to find Zlib correctly, but then the check at https://github.com/llvm/llvm-project/blob/46425b8d0fac3c529aa4a716d19abd7032e452f3/llvm/cmake/config-ix.cmake#L139-L141 uses the value of `ZLIB_LIBRARY` to list the Zlib to link for the test, but being `ZLIB_LIBRARY` a directory, CMake doesn't see any valid Zlib and thus tries to run the test without linking any Zlib, and the test silently fails (they're silent only when `LLVM_ENABLE_ZLIB=ON`), resulting in no usable Zlib available, even if found. ### Proposed solution `ZLIB_ROOT` is the only [hint recommended by the CMake module `FindZLIB`](https://cmake.org/cmake/help/latest/module/FindZLIB.html#hints). This PR replaces a broken `ZLIB_LIBRARY` with an appropriate `ZLIB_ROOT`. Also, we set `LLVM_ENABLE_ZLIB=FORCE_ON` which is the only way to make CMake fail loudly if no usable Zlib is available, and avoid going on with a non-usable build. ### Other comments I confirm this fixes #55337 for me, it should likely address https://github.com/JuliaCI/julia-buildkite/issues/373 as well. Also, options `COMPILER_RT_ENABLE_IOS`, `COMPILER_RT_ENABLE_WATCHOS`, `COMPILER_RT_ENABLE_TVOS`, and `HAVE_HISTEDIT_H` don't exist anymore, and they are removed. --- deps/BOLT.mk | 2 +- deps/llvm.mk | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/deps/BOLT.mk b/deps/BOLT.mk index 70c5d03c762ec..34391ab10f716 100644 --- a/deps/BOLT.mk +++ b/deps/BOLT.mk @@ -30,7 +30,7 @@ LLVM_LDFLAGS += $(LDFLAGS) LLVM_LDFLAGS += $(LLVM_LDFLAGS) LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING=host -DCMAKE_BUILD_TYPE=Release LLVM_CMAKE += -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_HOST_TRIPLE="$(or $(XC_HOST),$(BUILD_MACHINE))" -LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=ON -DZLIB_LIBRARY="$(build_prefix)/lib" +LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=FORCE_ON -DZLIB_ROOT="$(build_prefix)" LLVM_CMAKE += -DLLVM_BINDINGS_LIST="" -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_INCLUDE_DOCS=Off -DLLVM_ENABLE_TERMINFO=Off -DHAVE_LIBEDIT=Off diff --git a/deps/llvm.mk b/deps/llvm.mk index eddf9b60e38c7..08aff443dcff8 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -94,16 +94,15 @@ LLVM_LDFLAGS += $(BOLT_LDFLAGS) LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING="$(LLVM_TARGETS)" -DCMAKE_BUILD_TYPE="$(LLVM_CMAKE_BUILDTYPE)" LLVM_CMAKE += -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="$(LLVM_EXPERIMENTAL_TARGETS)" LLVM_CMAKE += -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_HOST_TRIPLE="$(or $(XC_HOST),$(BUILD_MACHINE))" -LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=ON -DZLIB_LIBRARY="$(build_prefix)/lib" +LLVM_CMAKE += -DLLVM_ENABLE_ZLIB=FORCE_ON -DZLIB_ROOT="$(build_prefix)" LLVM_CMAKE += -DLLVM_ENABLE_ZSTD=OFF -LLVM_CMAKE += -DCOMPILER_RT_ENABLE_IOS=OFF -DCOMPILER_RT_ENABLE_WATCHOS=OFF -DCOMPILER_RT_ENABLE_TVOS=OFF ifeq ($(USE_POLLY_ACC),1) LLVM_CMAKE += -DPOLLY_ENABLE_GPGPU_CODEGEN=ON endif LLVM_CMAKE += -DLLVM_TOOLS_INSTALL_DIR=$(call rel_path,$(build_prefix),$(build_depsbindir)) LLVM_CMAKE += -DLLVM_UTILS_INSTALL_DIR=$(call rel_path,$(build_prefix),$(build_depsbindir)) LLVM_CMAKE += -DLLVM_INCLUDE_UTILS=ON -DLLVM_INSTALL_UTILS=ON -LLVM_CMAKE += -DLLVM_BINDINGS_LIST="" -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_INCLUDE_DOCS=Off -DLLVM_ENABLE_TERMINFO=Off -DHAVE_HISTEDIT_H=Off -DHAVE_LIBEDIT=Off +LLVM_CMAKE += -DLLVM_BINDINGS_LIST="" -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_INCLUDE_DOCS=Off -DLLVM_ENABLE_TERMINFO=Off -DHAVE_LIBEDIT=Off ifeq ($(LLVM_ASSERTIONS), 1) LLVM_CMAKE += -DLLVM_ENABLE_ASSERTIONS:BOOL=ON endif # LLVM_ASSERTIONS From 1e1e710ddd7a7c0fec3c79b69024fa3b7cb2a14c Mon Sep 17 00:00:00 2001 From: William Moses Date: Tue, 6 Aug 2024 05:01:59 -0400 Subject: [PATCH 144/206] AllocOpt: Fix stack lowering where alloca continas boxed and unboxed data (#55306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Valentin Churavy Co-authored-by: Mosè Giordano Co-authored-by: Gabriel Baraldi --- src/llvm-alloc-helpers.cpp | 10 ++++++++- src/llvm-alloc-helpers.h | 7 ++++++ src/llvm-alloc-opt.cpp | 15 +++++++++++++ test/llvmpasses/alloc-opt-bits.ll | 37 +++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 test/llvmpasses/alloc-opt-bits.ll diff --git a/src/llvm-alloc-helpers.cpp b/src/llvm-alloc-helpers.cpp index 953ecc1830142..9d2fba832839c 100644 --- a/src/llvm-alloc-helpers.cpp +++ b/src/llvm-alloc-helpers.cpp @@ -88,6 +88,8 @@ bool AllocUseInfo::addMemOp(Instruction *inst, unsigned opno, uint32_t offset, memop.isaggr = isa(elty) || isa(elty) || isa(elty); memop.isobjref = hasObjref(elty); auto &field = getField(offset, size, elty); + field.second.hasunboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); + if (field.second.hasobjref != memop.isobjref) field.second.multiloc = true; // can't split this field, since it contains a mix of references and bits if (!isstore) @@ -198,6 +200,7 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r auto elty = inst->getType(); required.use_info.has_unknown_objref |= hasObjref(elty); required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } else if (!required.use_info.addMemOp(inst, 0, cur.offset, inst->getType(), @@ -289,6 +292,7 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r auto elty = storev->getType(); required.use_info.has_unknown_objref |= hasObjref(elty); required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } else if (!required.use_info.addMemOp(inst, use->getOperandNo(), cur.offset, storev->getType(), @@ -310,10 +314,14 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r } required.use_info.hasload = true; auto storev = isa(inst) ? cast(inst)->getNewValOperand() : cast(inst)->getValOperand(); + Type *elty = storev->getType(); if (cur.offset == UINT32_MAX || !required.use_info.addMemOp(inst, use->getOperandNo(), - cur.offset, storev->getType(), + cur.offset, elty, true, required.DL)) { LLVM_DEBUG(dbgs() << "Atomic inst has unknown offset\n"); + required.use_info.has_unknown_objref |= hasObjref(elty); + required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } required.use_info.refload = true; diff --git a/src/llvm-alloc-helpers.h b/src/llvm-alloc-helpers.h index 49c3b15332a56..20e9132d10b4c 100644 --- a/src/llvm-alloc-helpers.h +++ b/src/llvm-alloc-helpers.h @@ -46,6 +46,8 @@ namespace jl_alloc { bool hasaggr:1; bool multiloc:1; bool hasload:1; + // The alloc has a unboxed object at this offset. + bool hasunboxed:1; llvm::Type *elty; llvm::SmallVector accesses; Field(uint32_t size, llvm::Type *elty) @@ -54,6 +56,7 @@ namespace jl_alloc { hasaggr(false), multiloc(false), hasload(false), + hasunboxed(false), elty(elty) { } @@ -95,6 +98,9 @@ namespace jl_alloc { // The alloc has an aggregate Julia object reference not in an explicit field. bool has_unknown_objrefaggr:1; + // The alloc has an unboxed object at an unknown offset. + bool has_unknown_unboxed:1; + void reset() { escaped = false; @@ -110,6 +116,7 @@ namespace jl_alloc { allockind = llvm::AllocFnKind::Unknown; has_unknown_objref = false; has_unknown_objrefaggr = false; + has_unknown_unboxed = false; uses.clear(); preserves.clear(); memops.clear(); diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index e0cde7206b6b9..5984ad55d221c 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -252,10 +252,12 @@ void Optimizer::optimizeAll() removeAlloc(orig); continue; } + bool has_unboxed = use_info.has_unknown_unboxed; bool has_ref = use_info.has_unknown_objref; bool has_refaggr = use_info.has_unknown_objrefaggr; for (auto memop: use_info.memops) { auto &field = memop.second; + has_unboxed |= field.hasunboxed; if (field.hasobjref) { has_ref = true; // This can be relaxed a little based on hasload @@ -284,6 +286,19 @@ void Optimizer::optimizeAll() splitOnStack(orig); continue; } + // The move to stack code below, if has_ref is set, changes the allocation to an array of jlvalue_t's. This is fine + // if all objects are jlvalue_t's. However, if part of the allocation is an unboxed value (e.g. it is a { float, jlvaluet }), + // then moveToStack will create a [2 x jlvaluet] bitcast to { float, jlvaluet }. + // This later causes the GC rooting pass, to miss-characterize the float as a pointer to a GC value + if (has_unboxed && has_ref) { + REMARK([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) + << "GC allocation could not be split since it contains both boxed and unboxed values, unable to move to stack " << ore::NV("GC Allocation", orig); + }); + if (use_info.hastypeof) + optimizeTag(orig); + continue; + } REMARK([&](){ return OptimizationRemark(DEBUG_TYPE, "Stack Move Allocation", orig) << "GC allocation moved to stack " << ore::NV("GC Allocation", orig); diff --git a/test/llvmpasses/alloc-opt-bits.ll b/test/llvmpasses/alloc-opt-bits.ll new file mode 100644 index 0000000000000..e19093f46f815 --- /dev/null +++ b/test/llvmpasses/alloc-opt-bits.ll @@ -0,0 +1,37 @@ +; This file is a part of Julia. License is MIT: https://julialang.org/license + +; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes='function(AllocOpt)' -S %s | FileCheck %s + + +@tag = external addrspace(10) global {} + +@glob = external addrspace(10) global {} + +; Test that the gc_preserve intrinsics are deleted directly. + +; CHECK-LABEL: @ptr_and_bits +; CHECK-NOT: alloca +; CHECK: call noalias ptr addrspace(10) @julia.gc_alloc_obj + +define void @ptr_and_bits(ptr %fptr, i1 %b, i1 %b2, i32 %idx) { + %pgcstack = call ptr @julia.get_pgcstack() + %ptls = call ptr @julia.ptls_states() + %ptls_i8 = bitcast ptr %ptls to ptr + %v = call noalias ptr addrspace(10) @julia.gc_alloc_obj(ptr %ptls_i8, i64 16, ptr addrspace(10) @tag) + + %g0 = getelementptr { i64, ptr addrspace(10) }, ptr addrspace(10) %v, i32 %idx, i32 1 + store ptr addrspace(10) @glob, ptr addrspace(10) %g0 + + %g1 = getelementptr { i64, ptr addrspace(10) }, ptr addrspace(10) %v, i32 %idx, i32 0 + store i64 7, ptr addrspace(10) %g1 + + %res = load ptr addrspace(10), ptr addrspace(10) %g0 + %res2 = load i64, ptr addrspace(10) %g1 + ret void +} + +declare noalias ptr addrspace(10) @julia.gc_alloc_obj(ptr, i64, ptr addrspace(10)) + +declare ptr @julia.ptls_states() + +declare ptr @julia.get_pgcstack() From 0717a9454d7eb2275575d22f97962d9d9f1e95e2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 6 Aug 2024 06:53:10 -0400 Subject: [PATCH 145/206] Revert "better type inference for several functions taking `NTuple` args" (#55375) Reverts JuliaLang/julia#55124 as this turns out to hurt performance quite a bit Closes #55374 --- base/essentials.jl | 8 +------- base/ntuple.jl | 2 +- base/tuple.jl | 16 +++------------- test/tuple.jl | 7 ------- 4 files changed, 5 insertions(+), 28 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 2e76235cba9a6..50017b3d7927d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -501,13 +501,7 @@ julia> Base.tail(()) ERROR: ArgumentError: Cannot call tail on an empty tuple. ``` """ -function tail(x::Tuple{Any,Vararg}) - y = argtail(x...)::Tuple - if x isa NTuple # help the type inference - y = y::NTuple - end - y -end +tail(x::Tuple) = argtail(x...) tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple.")) function unwrap_unionall(@nospecialize(a)) diff --git a/base/ntuple.jl b/base/ntuple.jl index 4adab38a8ee82..f81d2686b9764 100644 --- a/base/ntuple.jl +++ b/base/ntuple.jl @@ -95,5 +95,5 @@ end function reverse(t::NTuple{N}) where N ntuple(Val{N}()) do i t[end+1-i] - end::NTuple + end end diff --git a/base/tuple.jl b/base/tuple.jl index 5f74d486e1e69..fc213410cfd7c 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -340,15 +340,9 @@ ERROR: ArgumentError: Cannot call front on an empty tuple. """ function front(t::Tuple) @inline - if t === () - throw(ArgumentError("Cannot call front on an empty tuple.")) - end - r = _front(t...)::Tuple - if t isa NTuple # help the type inference - r = r::NTuple - end - r + _front(t...) end +_front() = throw(ArgumentError("Cannot call front on an empty tuple.")) _front(v) = () function _front(v, t...) @inline @@ -705,9 +699,5 @@ function circshift(x::Tuple{Any,Any,Any,Vararg{Any,N}}, shift::Integer) where {N @inline len = N + 3 j = mod1(shift, len) - y = ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple - if x isa NTuple # help the type inference - y = y::NTuple - end - y + ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple end diff --git a/test/tuple.jl b/test/tuple.jl index 59897c8adfdb2..b1894bd2bb6ce 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -845,10 +845,3 @@ end end end end - -@testset "abstract return type inference for homogeneous tuples" begin - @test NTuple == Core.Compiler.return_type(Base.tail, Tuple{NTuple}) - @test NTuple == Core.Compiler.return_type(Base.front, Tuple{NTuple}) - @test NTuple == Core.Compiler.return_type(reverse, Tuple{NTuple}) - @test NTuple == Core.Compiler.return_type(circshift, Tuple{NTuple,Int}) -end From 73777606489c1bd2a2851e73f85aed6224761f9b Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 6 Aug 2024 15:14:30 +0000 Subject: [PATCH 146/206] Fuse complex conversion with function application for symmetric (#55391) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids allocating an intermediate array, which reduces allocation slightly. ```julia julia> S = Symmetric(diagm(0=>-rand(100))); julia> @btime $S^0.2; 479.196 μs (25 allocations: 560.20 KiB) # nightly v"1.12.0-DEV.994" 478.213 μs (23 allocations: 558.58 KiB) # This PR ``` --- stdlib/LinearAlgebra/src/symmetric.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index f58670e255b58..d801158232673 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -821,7 +821,7 @@ function ^(A::Symmetric{<:Real}, p::Real) if all(λ -> λ ≥ 0, F.values) return Symmetric((F.vectors * Diagonal((F.values).^p)) * F.vectors') else - return Symmetric((F.vectors * Diagonal((complex(F.values)).^p)) * F.vectors') + return Symmetric((F.vectors * Diagonal(complex.(F.values).^p)) * F.vectors') end end function ^(A::Symmetric{<:Complex}, p::Real) @@ -853,7 +853,7 @@ function ^(A::Hermitian{T}, p::Real) where T return Hermitian(retmat) end else - return (F.vectors * Diagonal((complex(F.values).^p))) * F.vectors' + return (F.vectors * Diagonal((complex.(F.values).^p))) * F.vectors' end end @@ -983,7 +983,7 @@ for func in (:log, :sqrt) end return Hermitian(retmat) else - retmat = (F.vectors * Diagonal(($func).(complex(F.values)))) * F.vectors' + retmat = (F.vectors * Diagonal(($func).(complex.(F.values)))) * F.vectors' return retmat end end From f94fe63c46d6dd860a633d429003dc5be9c472e4 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 6 Aug 2024 11:14:58 -0400 Subject: [PATCH 147/206] Disable printing of message about including GPL libs in libsuitesparse.mk (#55387) https://github.com/JuliaLang/julia/pull/54240/files#r1704655126 Co-authored-by: Viral B. Shah --- deps/libsuitesparse.mk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deps/libsuitesparse.mk b/deps/libsuitesparse.mk index d840a7b298e17..85b2c23473a18 100644 --- a/deps/libsuitesparse.mk +++ b/deps/libsuitesparse.mk @@ -113,9 +113,7 @@ uninstall-libsuitesparse: endef remove-libsuitesparse-gpl-lib: -ifeq ($(USE_GPL_LIBS),1) - @echo This build contains [GPL-2.0+] libs: libcholmod librbio libspqr libumfpack -else +ifeq ($(USE_GPL_LIBS),0) @echo Removing GPL libs... -rm -f $(build_bindir)/libcholmod* -rm -f $(build_bindir)/libklu_cholmod* From 308cd7b61267c4e4dbbd48cc979948f3675e8fc1 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 6 Aug 2024 16:42:29 +0000 Subject: [PATCH 148/206] LAPACK: return union of tuples in gees and trsen (#55353) This simplifies the return type from a `Tuple` with a `Union` field to a `Union` of `Tuple`s. --- stdlib/LinearAlgebra/src/lapack.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 6d1d871ed85fd..97dff0031329b 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -6452,7 +6452,7 @@ for (gees, gges, gges3, elty) in resize!(work, lwork) end end - A, vs, iszero(wi) ? wr : complex.(wr, wi) + iszero(wi) ? (A, vs, wr) : (A, vs, complex.(wr, wi)) end # * .. Scalar Arguments .. @@ -6833,7 +6833,7 @@ for (trexc, trsen, tgsen, elty) in resize!(iwork, liwork) end end - T, Q, iszero(wi) ? wr : complex.(wr, wi), s[], sep[] + iszero(wi) ? (T, Q, wr, s[], sep[]) : (T, Q, complex.(wr, wi), s[], sep[]) end trsen!(select::AbstractVector{BlasInt}, T::AbstractMatrix{$elty}, Q::AbstractMatrix{$elty}) = trsen!('N', 'V', select, T, Q) From 09e5c40173297365cf09a09aec876d0ba6493958 Mon Sep 17 00:00:00 2001 From: Simeon David Schaub Date: Tue, 6 Aug 2024 19:03:54 +0200 Subject: [PATCH 149/206] fix #55389: type-unstable `join` (#55395) --- base/strings/io.jl | 5 +++-- test/strings/io.jl | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index c88b7ac939c8d..acbd945c8e137 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -354,7 +354,8 @@ function join(io::IO, iterator, delim="") end function _join_preserve_annotations(iterator, args...) - if isconcretetype(eltype(iterator)) && !_isannotated(eltype(iterator)) && !any(_isannotated, args) + et = @default_eltype(iterator) + if isconcretetype(et) && !_isannotated(et) && !any(_isannotated, args) sprint(join, iterator, args...) else io = AnnotatedIOBuffer() @@ -363,7 +364,7 @@ function _join_preserve_annotations(iterator, args...) # of iterators with a non-concrete eltype), that the result is annotated # in nature, we extract an `AnnotatedString`, otherwise we just extract # a plain `String` from `io`. - if isconcretetype(eltype(iterator)) || !isempty(io.annotations) + if isconcretetype(et) || !isempty(io.annotations) read(seekstart(io), AnnotatedString{String}) else String(take!(io.io)) diff --git a/test/strings/io.jl b/test/strings/io.jl index 79e11d8cf5184..209844580b3cd 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -344,3 +344,8 @@ end @testset "`string` return types" begin @test all(T -> T <: AbstractString, Base.return_types(string)) end + +@testset "type stable `join` (#55389)" begin + itr = ("foo" for _ in 1:100) + @test Base.return_types(join, (typeof(itr),))[] == String +end From fb4e4e5bddf5896bf6c8596026ecd275e599b9af Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 6 Aug 2024 19:04:06 +0000 Subject: [PATCH 150/206] Don't read destination indices when copying structured matrices (#55322) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following regression introduced in v1.11 ```julia julia> using LinearAlgebra julia> D = Diagonal(rand(4)); julia> T = Tridiagonal(Vector{BigFloat}(undef, 3), Vector{BigFloat}(undef, 4), Vector{BigFloat}(undef, 3)) 4×4 Tridiagonal{BigFloat, Vector{BigFloat}}: #undef #undef ⋅ ⋅ #undef #undef #undef ⋅ ⋅ #undef #undef #undef ⋅ ⋅ #undef #undef julia> copyto!(T, D) ERROR: UndefRefError: access to undefined reference Stacktrace: [1] getindex @ ./essentials.jl:907 [inlined] [2] _broadcast_getindex @ ./broadcast.jl:644 [inlined] [3] _getindex @ ./broadcast.jl:675 [inlined] [4] _broadcast_getindex @ ./broadcast.jl:650 [inlined] [5] getindex @ ./broadcast.jl:610 [inlined] [6] macro expansion @ ./broadcast.jl:973 [inlined] [7] macro expansion @ ./simdloop.jl:77 [inlined] [8] copyto! @ ./broadcast.jl:972 [inlined] [9] copyto! @ ./broadcast.jl:925 [inlined] [10] materialize! @ ./broadcast.jl:883 [inlined] [11] materialize! @ ./broadcast.jl:880 [inlined] [12] _copyto_banded!(T::Tridiagonal{BigFloat, Vector{BigFloat}}, D::Diagonal{Float64, Vector{Float64}}) @ LinearAlgebra ~/.julia/juliaup/julia-nightly/share/julia/stdlib/v1.12/LinearAlgebra/src/special.jl:323 [13] copyto!(dest::Tridiagonal{BigFloat, Vector{BigFloat}}, src::Diagonal{Float64, Vector{Float64}}) @ LinearAlgebra ~/.julia/juliaup/julia-nightly/share/julia/stdlib/v1.12/LinearAlgebra/src/special.jl:315 [14] top-level scope @ REPL[4]:1 ``` After this PR ```julia julia> copyto!(T, D) 4×4 Tridiagonal{BigFloat, Vector{BigFloat}}: 0.909968 0.0 ⋅ ⋅ 0.0 0.193341 0.0 ⋅ ⋅ 0.0 0.194794 0.0 ⋅ ⋅ 0.0 0.506905 ``` The current implementation used an optimization that may not be applicable for non-isbits types, and this PR ensures that we always read from the source and write to the destination. --- stdlib/LinearAlgebra/src/bidiag.jl | 2 +- stdlib/LinearAlgebra/src/special.jl | 14 +++++++------- stdlib/LinearAlgebra/src/tridiag.jl | 2 +- stdlib/LinearAlgebra/test/special.jl | 17 +++++++++-------- stdlib/LinearAlgebra/test/tridiag.jl | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 0caaec02b5056..24958422015ab 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -305,7 +305,7 @@ function _copyto_banded!(A::Bidiagonal, B::Bidiagonal) if A.uplo == B.uplo A.ev .= B.ev elseif iszero(B.ev) # diagonal source - A.ev .= zero.(A.ev) + A.ev .= B.ev else zeroband = istriu(A) ? "lower" : "upper" uplo = A.uplo diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 9633594574055..28a1b4b1b2eab 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -320,20 +320,20 @@ function copyto!(dest::BandedMatrix, src::BandedMatrix) end function _copyto_banded!(T::Tridiagonal, D::Diagonal) T.d .= D.diag - T.dl .= zero.(T.dl) - T.du .= zero.(T.du) + T.dl .= view(D, diagind(D, -1, IndexStyle(D))) + T.du .= view(D, diagind(D, 1, IndexStyle(D))) return T end function _copyto_banded!(SymT::SymTridiagonal, D::Diagonal) issymmetric(D) || throw(ArgumentError("cannot copy a non-symmetric Diagonal matrix to a SymTridiagonal")) SymT.dv .= D.diag _ev = _evview(SymT) - _ev .= zero.(_ev) + _ev .= view(D, diagind(D, 1, IndexStyle(D))) return SymT end function _copyto_banded!(B::Bidiagonal, D::Diagonal) B.dv .= D.diag - B.ev .= zero.(B.ev) + B.ev .= view(D, diagind(D, B.uplo == 'U' ? 1 : -1, IndexStyle(D))) return B end function _copyto_banded!(D::Diagonal, B::Bidiagonal) @@ -361,10 +361,10 @@ function _copyto_banded!(T::Tridiagonal, B::Bidiagonal) T.d .= B.dv if B.uplo == 'U' T.du .= B.ev - T.dl .= zero.(T.dl) + T.dl .= view(B, diagind(B, -1, IndexStyle(B))) else T.dl .= B.ev - T.du .= zero.(T.du) + T.du .= view(B, diagind(B, 1, IndexStyle(B))) end return T end @@ -372,7 +372,7 @@ function _copyto_banded!(SymT::SymTridiagonal, B::Bidiagonal) issymmetric(B) || throw(ArgumentError("cannot copy a non-symmetric Bidiagonal matrix to a SymTridiagonal")) SymT.dv .= B.dv _ev = _evview(SymT) - _ev .= zero.(_ev) + _ev .= B.ev return SymT end function _copyto_banded!(B::Bidiagonal, T::Tridiagonal) diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 2ff688f4b4ed1..e217425402df9 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -1040,7 +1040,7 @@ function _copyto_banded!(A::Tridiagonal, B::SymTridiagonal) return A end function _copyto_banded!(A::SymTridiagonal, B::Tridiagonal) - issymmetric(B) || throw(ArgumentError("cannot copy a non-symmetric Tridiagonal matrix to a SymTridiagonal")) + issymmetric(B) || throw(ArgumentError("cannot copy an asymmetric Tridiagonal matrix to a SymTridiagonal")) A.dv .= B.d _evview(A) .= B.du return A diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 2f870373c9586..9bb84ba0e9d03 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -555,8 +555,8 @@ end @testset "from Diagonal" begin D = Diagonal(d) @testset "to Bidiagonal" begin - BU = Bidiagonal(zero(d), oneunit.(du), :U) - BL = Bidiagonal(zero(d), oneunit.(dl), :L) + BU = Bidiagonal(similar(d, BigInt), similar(du, BigInt), :U) + BL = Bidiagonal(similar(d, BigInt), similar(dl, BigInt), :L) for B in (BL, BU) copyto!(B, D) @test B == D @@ -573,7 +573,7 @@ end end end @testset "to Tridiagonal" begin - T = Tridiagonal(oneunit.(dl), zero(d), oneunit.(du)) + T = Tridiagonal(similar(dl, BigInt), similar(d, BigInt), similar(du, BigInt)) copyto!(T, D) @test T == D @@ -586,8 +586,8 @@ end end end @testset "to SymTridiagonal" begin - for du2 in (oneunit.(du), oneunit.(d)) - S = SymTridiagonal(zero(d), du2) + for du2 in (similar(du, BigInt), similar(d, BigInt)) + S = SymTridiagonal(similar(d), du2) copyto!(S, D) @test S == D end @@ -630,13 +630,14 @@ end end end @testset "to Tridiagonal" begin - T = Tridiagonal(oneunit.(dl), zero(d), oneunit.(du)) + T = Tridiagonal(similar(dl, BigInt), similar(d, BigInt), similar(du, BigInt)) for B in (BL, BU, BLones, BUones) copyto!(T, B) @test T == B end @testset "mismatched size" begin + T = Tridiagonal(oneunit.(dl), zero(d), oneunit.(du)) for uplo in (:L, :U) T .= 0 copyto!(T, Bidiagonal([1], Int[], uplo)) @@ -647,8 +648,8 @@ end end end @testset "to SymTridiagonal" begin - for du2 in (oneunit.(du), oneunit.(d)) - S = SymTridiagonal(zero(d), du2) + for du2 in (similar(du, BigInt), similar(d, BigInt)) + S = SymTridiagonal(similar(d, BigInt), du2) for B in (BL, BU) copyto!(S, B) @test S == B diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index 5dc1d01e850d8..41a28631b27a0 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -808,7 +808,7 @@ end @test copyto!(zero(S), T) == T T2 = Tridiagonal(ones(length(ev)), zero(dv), zero(ev)) - @test_throws "cannot copy a non-symmetric Tridiagonal matrix to a SymTridiagonal" copyto!(zero(S), T2) + @test_throws "cannot copy an asymmetric Tridiagonal matrix to a SymTridiagonal" copyto!(zero(S), T2) @testset "mismatched sizes" begin dv2 = [4; @view dv[2:end]] From 22f55804b9c0da372c8a5f8819732b034b442b51 Mon Sep 17 00:00:00 2001 From: Markus Hauru Date: Tue, 6 Aug 2024 22:28:51 +0100 Subject: [PATCH 151/206] Deprecate conflicting @testset arguments (#55174) Currently `@testset` allows specifying multiple descriptions and testset types, and only the last one will take effect. The others will be silently ignored. This PR starts printing deprecation warnings whenever such conflicting arguments are provided. --- stdlib/Test/src/Test.jl | 10 ++++++++++ stdlib/Test/test/runtests.jl | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 3ecf0c151164d..b4ada2ce3a9cf 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1838,9 +1838,19 @@ function parse_testset_args(args) # a standalone symbol is assumed to be the test set we should use # the same is true for a symbol that's not exported from a module if isa(arg, Symbol) || Base.isexpr(arg, :.) + if testsettype !== nothing + msg = """Multiple testset types provided to @testset. \ + This is deprecated and may error in the future.""" + Base.depwarn(msg, :testset_multiple_testset_types; force=true) + end testsettype = esc(arg) # a string is the description elseif isa(arg, AbstractString) || (isa(arg, Expr) && arg.head === :string) + if desc !== nothing + msg = """Multiple descriptions provided to @testset. \ + This is deprecated and may error in the future.""" + Base.depwarn(msg, :testset_multiple_descriptions; force=true) + end desc = esc(arg) # an assignment is an option elseif isa(arg, Expr) && arg.head === :(=) diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 31919c2881f6b..3ddcd7d5de0fd 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -1725,4 +1725,14 @@ end result = read(pipeline(ignorestatus(cmd), stderr=devnull), String) @test occursin(expected, result) end + +end + +@testset "Deprecated multiple arguments" begin + msg1 = """Multiple descriptions provided to @testset. \ + This is deprecated and may error in the future.""" + @test_deprecated msg1 @macroexpand @testset "name1" "name2" begin end + msg2 = """Multiple testset types provided to @testset. \ + This is deprecated and may error in the future.""" + @test_deprecated msg2 @macroexpand @testset DefaultTestSet DefaultTestSet begin end end From e4678ab775dadc95dd8bb050637817e449ee7300 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Tue, 6 Aug 2024 17:43:27 -0400 Subject: [PATCH 152/206] Increase default stack size limit on 64-bit systems (#55185) This increases the default stack size limit on 64-bit systems from 4 MB to 8 MB, matching glibc and typical modern Linux and macOS machines, as well as the stack size limit of the root Julia process. --- src/options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.h b/src/options.h index 5da9bf2b1a740..800be866183b0 100644 --- a/src/options.h +++ b/src/options.h @@ -110,7 +110,7 @@ #if defined(_COMPILER_ASAN_ENABLED_) || defined(_COMPILER_MSAN_ENABLED_) #define JL_STACK_SIZE (64*1024*1024) #elif defined(_P64) -#define JL_STACK_SIZE (4*1024*1024) +#define JL_STACK_SIZE (8*1024*1024) #else #define JL_STACK_SIZE (2*1024*1024) #endif From 016d035cd2678d3af90601ca2aa3aed35d50721d Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Tue, 6 Aug 2024 19:48:10 -0400 Subject: [PATCH 153/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=20e4a6723bf=20to=207aef1f044=20(#55399)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 | 1 + .../Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 | 1 + .../Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 | 1 - .../Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 create mode 100644 deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 diff --git a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 new file mode 100644 index 0000000000000..218260c77ea07 --- /dev/null +++ b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 @@ -0,0 +1 @@ +832f88c404516179ece213581cd227f8 diff --git a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 new file mode 100644 index 0000000000000..fc763c8d86f40 --- /dev/null +++ b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 @@ -0,0 +1 @@ +4355bb51a7f83bde489e587527e1e3a9c70799a5c0d27cd7f42b4227a5fbca2a1200a83db0317a75c582ee997bec72e9e8afafb059c395bd46e2aa015f481dca diff --git a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 deleted file mode 100644 index 9151d83645ac6..0000000000000 --- a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e42b7400acc62aa5987dca1be49290ae diff --git a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 b/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 deleted file mode 100644 index 5498d9f6a3069..0000000000000 --- a/deps/checksums/Pkg-e4a6723bf3074764ff9266e5e13dfea501431b33.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -71dd216051496210416db6a3489f9a934eb21ba59054fa921758e588450c6b1450f7771c8796d7b78ae3e481e0d730ad1bf48573dd2ec39975a840f9cc33114a diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 7742b41441528..964c43dfcc786 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = e4a6723bf3074764ff9266e5e13dfea501431b33 +PKG_SHA1 = 7aef1f044f3483e8b07d33fb4cfe918be554de69 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From b3a62b4c30f718e7f0f226342abb0b636b91f3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 7 Aug 2024 03:16:44 +0200 Subject: [PATCH 154/206] Restore cmdlineargs tests on non-Windows platforms (#55368) --- test/cmdlineargs.jl | 64 ++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 01a8acaeaea94..c6720e23739d8 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -339,43 +339,37 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` @test errors_not_signals(`$exename -C invalidtarget`) @test errors_not_signals(`$exename --cpu-target=invalidtarget`) - if Sys.iswindows() - # -t, --threads - code = "print(Threads.threadpoolsize())" - cpu_threads = ccall(:jl_effective_threads, Int32, ()) - @test string(cpu_threads) == - read(`$exename --threads auto -e $code`, String) == - read(`$exename --threads=auto -e $code`, String) == - read(`$exename -tauto -e $code`, String) == - read(`$exename -t auto -e $code`, String) - for nt in (nothing, "1") - withenv("JULIA_NUM_THREADS" => nt) do - @test read(`$exename --threads=2 -e $code`, String) == - read(`$exename -t 2 -e $code`, String) == "2" - end - end - # We want to test oversubscription, but on manycore machines, this can - # actually exhaust limited PID spaces - cpu_threads = max(2*cpu_threads, min(50, 10*cpu_threads)) - if Sys.WORD_SIZE == 32 - cpu_threads = min(cpu_threads, 50) - end - @test read(`$exename -t $cpu_threads -e $code`, String) == string(cpu_threads) - withenv("JULIA_NUM_THREADS" => string(cpu_threads)) do - @test read(`$exename -e $code`, String) == string(cpu_threads) + # -t, --threads + code = "print(Threads.threadpoolsize())" + cpu_threads = ccall(:jl_effective_threads, Int32, ()) + @test string(cpu_threads) == + read(`$exename --threads auto -e $code`, String) == + read(`$exename --threads=auto -e $code`, String) == + read(`$exename -tauto -e $code`, String) == + read(`$exename -t auto -e $code`, String) + for nt in (nothing, "1") + withenv("JULIA_NUM_THREADS" => nt) do + @test read(`$exename --threads=2 -e $code`, String) == + read(`$exename -t 2 -e $code`, String) == "2" end - @test errors_not_signals(`$exename -t 0`) - @test errors_not_signals(`$exename -t -1`) + end + # We want to test oversubscription, but on manycore machines, this can + # actually exhaust limited PID spaces + cpu_threads = max(2*cpu_threads, min(50, 10*cpu_threads)) + if Sys.WORD_SIZE == 32 + cpu_threads = min(cpu_threads, 50) + end + @test read(`$exename -t $cpu_threads -e $code`, String) == string(cpu_threads) + withenv("JULIA_NUM_THREADS" => string(cpu_threads)) do + @test read(`$exename -e $code`, String) == string(cpu_threads) + end + @test errors_not_signals(`$exename -t 0`) + @test errors_not_signals(`$exename -t -1`) - # Combining --threads and --procs: --threads does propagate - withenv("JULIA_NUM_THREADS" => nothing) do - code = "print(sum(remotecall_fetch(Threads.threadpoolsize, x) for x in procs()))" - @test read(`$exename -p2 -t2 -e $code`, String) == "6" - end - else - @test_skip "Command line tests with -t are flakey on non-Windows OS" - # Known issue: https://github.com/JuliaLang/julia/issues/49154 - # These tests should be fixed and reenabled on all operating systems. + # Combining --threads and --procs: --threads does propagate + withenv("JULIA_NUM_THREADS" => nothing) do + code = "print(sum(remotecall_fetch(Threads.threadpoolsize, x) for x in procs()))" + @test read(`$exename -p2 -t2 -e $code`, String) == "6" end # Combining --threads and invalid -C should yield a decent error From b43e24715869b15eb8a9f6e669a03f4722bfb32f Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 7 Aug 2024 07:48:13 -0400 Subject: [PATCH 155/206] optimized textwidth(::Char) for ASCII (#55398) --- base/strings/unicode.jl | 9 +++++++++ test/strings/util.jl | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index 42a4106d0f52f..3c6710025077c 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -256,6 +256,15 @@ julia> textwidth('⛵') ``` """ function textwidth(c::AbstractChar) + ismalformed(c) && return 1 + i = codepoint(c) + i < 0x7f && return Int(i >= 0x20) # ASCII fast path + Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), i)) +end + +function textwidth(c::Char) + b = bswap(reinterpret(UInt32, c)) # from isascii(c) + b < 0x7f && return Int(b >= 0x20) # ASCII fast path ismalformed(c) && return 1 Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), c)) end diff --git a/test/strings/util.jl b/test/strings/util.jl index 59638dc3b9ca6..e5db9bd03ae8e 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -2,6 +2,20 @@ SubStr(s) = SubString("abc$(s)de", firstindex(s) + 3, lastindex(s) + 3) +@testset "textwidth" begin + for (c, w) in [('x', 1), ('α', 1), ('🍕', 2), ('\0', 0), ('\u0302', 0), ('\xc0', 1)] + @test textwidth(c) == w + @test textwidth(c^3) == w*3 + @test w == @invoke textwidth(c::AbstractChar) + end + for i in 0x00:0x7f # test all ASCII chars (which have fast path) + w = Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), i)) + c = Char(i) + @test textwidth(c) == w + @test w == @invoke textwidth(c::AbstractChar) + end +end + @testset "padding (lpad and rpad)" begin @test lpad("foo", 2) == "foo" @test rpad("foo", 2) == "foo" From bd582f78ed3ecd3950b676e14bf0a7a64092aa3d Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Wed, 7 Aug 2024 16:42:30 +0000 Subject: [PATCH 156/206] Accept axes in Base.checkdims_perm (#55403) Since `checkdims_perm` only checks the axes of the arrays that are passed to it, this PR adds a method that accepts the axes as arguments instead of the arrays. This will avoid having to specialize on array types. An example of an improvement: On master ```julia julia> using LinearAlgebra julia> D = Diagonal(zeros(1)); julia> Dv = Diagonal(view(zeros(1),:)); julia> @time @eval permutedims(D, (2,1)); 0.016841 seconds (13.68 k allocations: 680.672 KiB, 51.37% compilation time) julia> @time @eval permutedims(Dv, (2,1)); 0.009303 seconds (11.24 k allocations: 564.203 KiB, 97.79% compilation time) ``` This PR ```julia julia> @time @eval permutedims(D, (2,1)); 0.016837 seconds (13.42 k allocations: 667.438 KiB, 51.05% compilation time) julia> @time @eval permutedims(Dv, (2,1)); 0.009076 seconds (6.59 k allocations: 321.156 KiB, 97.46% compilation time) ``` The allocations are lower in the second call. I've retained the original method as well, as some packages seem to be using it. This now forwards the axes to the new method. --- base/multidimensional.jl | 9 ++++----- base/permuteddimsarray.jl | 2 +- stdlib/LinearAlgebra/src/bidiag.jl | 2 +- stdlib/LinearAlgebra/src/diagonal.jl | 2 +- stdlib/LinearAlgebra/src/tridiag.jl | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index bd3641db4999c..5e32a19c2cafb 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1669,11 +1669,10 @@ function permutedims(B::StridedArray, perm) permutedims!(P, B, perm) end -function checkdims_perm(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, perm) where {TP,TB,N} - indsB = axes(B) - length(perm) == N || throw(ArgumentError("expected permutation of size $N, but length(perm)=$(length(perm))")) +checkdims_perm(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, perm) where {TP,TB,N} = checkdims_perm(axes(P), axes(B), perm) +function checkdims_perm(indsP::NTuple{N, AbstractUnitRange}, indsB::NTuple{N, AbstractUnitRange}, perm) where {N} + length(perm) == N || throw(ArgumentError(LazyString("expected permutation of size ", N, ", but length(perm)=", length(perm)))) isperm(perm) || throw(ArgumentError("input is not a permutation")) - indsP = axes(P) for i in eachindex(perm) indsP[i] == indsB[perm[i]] || throw(DimensionMismatch("destination tensor of incorrect size")) end @@ -1683,7 +1682,7 @@ end for (V, PT, BT) in Any[((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)] @eval @generated function permutedims!(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) where $(V...) quote - checkdims_perm(P, B, perm) + checkdims_perm(axes(P), axes(B), perm) #calculates all the strides native_strides = size_to_strides(1, size(B)...) diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 4e77d6b13ce21..cf9748168aac2 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -282,7 +282,7 @@ regions. See also [`permutedims`](@ref). """ function permutedims!(dest, src::AbstractArray, perm) - Base.checkdims_perm(dest, src, perm) + Base.checkdims_perm(axes(dest), axes(src), perm) P = PermutedDimsArray(dest, invperm(perm)) _copy!(P, src) return dest diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 24958422015ab..adb5f8c51bf47 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -287,7 +287,7 @@ adjoint(B::Bidiagonal{<:Number, <:Base.ReshapedArray{<:Number,1,<:Adjoint}}) = transpose(B::Bidiagonal{<:Number}) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? :L : :U) permutedims(B::Bidiagonal) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? 'L' : 'U') function permutedims(B::Bidiagonal, perm) - Base.checkdims_perm(B, B, perm) + Base.checkdims_perm(axes(B), axes(B), perm) NTuple{2}(perm) == (2, 1) ? permutedims(B) : B end function Base.copy(aB::Adjoint{<:Any,<:Bidiagonal}) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 89202e66597f8..77459f7cca520 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -745,7 +745,7 @@ adjoint(D::Diagonal{<:Number}) = Diagonal(vec(adjoint(D.diag))) adjoint(D::Diagonal{<:Number,<:Base.ReshapedArray{<:Number,1,<:Adjoint}}) = Diagonal(adjoint(parent(D.diag))) adjoint(D::Diagonal) = Diagonal(adjoint.(D.diag)) permutedims(D::Diagonal) = D -permutedims(D::Diagonal, perm) = (Base.checkdims_perm(D, D, perm); D) +permutedims(D::Diagonal, perm) = (Base.checkdims_perm(axes(D), axes(D), perm); D) function diag(D::Diagonal{T}, k::Integer=0) where T # every branch call similar(..., ::Int) to make sure the diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index e217425402df9..c14ed5690198c 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -173,7 +173,7 @@ adjoint(S::SymTridiagonal{<:Number, <:Base.ReshapedArray{<:Number,1,<:Adjoint}}) permutedims(S::SymTridiagonal) = S function permutedims(S::SymTridiagonal, perm) - Base.checkdims_perm(S, S, perm) + Base.checkdims_perm(axes(S), axes(S), perm) NTuple{2}(perm) == (2, 1) ? permutedims(S) : S end Base.copy(S::Adjoint{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(adjoint.(x)), (S.parent.dv, S.parent.ev))...) @@ -639,7 +639,7 @@ adjoint(S::Tridiagonal{<:Number, <:Base.ReshapedArray{<:Number,1,<:Adjoint}}) = transpose(S::Tridiagonal{<:Number}) = Tridiagonal(S.du, S.d, S.dl) permutedims(T::Tridiagonal) = Tridiagonal(T.du, T.d, T.dl) function permutedims(T::Tridiagonal, perm) - Base.checkdims_perm(T, T, perm) + Base.checkdims_perm(axes(T), axes(T), perm) NTuple{2}(perm) == (2, 1) ? permutedims(T) : T end Base.copy(aS::Adjoint{<:Any,<:Tridiagonal}) = (S = aS.parent; Tridiagonal(map(x -> copy.(adjoint.(x)), (S.du, S.d, S.dl))...)) From c767032b8ffec975cf2335105de082a6e6079c31 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 8 Aug 2024 02:12:08 +0000 Subject: [PATCH 157/206] Improve performance in `Bidiagonal` times `Diagonal` (#55175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds specialized methods to improve performance, and avoid allocations that were arising currently from the fallback tridiagonal implementations. ```julia julia> using LinearAlgebra, BenchmarkTools julia> n = 10000; B = Bidiagonal(rand(n), rand(n-1), :U); D = Diagonal(rand(size(B,1))); C = similar(B, size(B)); julia> @btime mul!($C, $B, $D); 25.552 ms (3 allocations: 78.19 KiB) # v"1.12.0-DEV.870" 25.559 ms (0 allocations: 0 bytes) # This PR julia> C = similar(B); julia> @btime mul!($C, $B, $D); 23.551 μs (3 allocations: 78.19 KiB) # v"1.12.0-DEV.870" 7.123 μs (0 allocations: 0 bytes) # This PR, specialized method ``` --- stdlib/LinearAlgebra/src/bidiag.jl | 168 +++++++++++++++++++++++++--- stdlib/LinearAlgebra/test/bidiag.jl | 39 ++++++- test/testhelpers/SizedArrays.jl | 4 + 3 files changed, 192 insertions(+), 19 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index adb5f8c51bf47..5aa4314c9ae51 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -299,6 +299,13 @@ function Base.copy(tB::Transpose{<:Any,<:Bidiagonal}) return Bidiagonal(map(x -> copy.(transpose.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U) end +@noinline function throw_zeroband_error(A) + uplo = A.uplo + zeroband = uplo == 'U' ? "lower" : "upper" + throw(ArgumentError(LazyString("cannot set the ", + zeroband, " bidiagonal band to a nonzero value for uplo=:", uplo))) +end + # copyto! for matching axes function _copyto_banded!(A::Bidiagonal, B::Bidiagonal) A.dv .= B.dv @@ -307,10 +314,7 @@ function _copyto_banded!(A::Bidiagonal, B::Bidiagonal) elseif iszero(B.ev) # diagonal source A.ev .= B.ev else - zeroband = istriu(A) ? "lower" : "upper" - uplo = A.uplo - throw(ArgumentError(LazyString("cannot set the ", - zeroband, " bidiagonal band to a nonzero value for uplo=:", uplo))) + throw_zeroband_error(A) end return A end @@ -620,7 +624,6 @@ function _mul!(C::AbstractMatrix, A::BiTriSym, B::Diagonal, _add::MulAddMul) check_A_mul_B!_sizes(size(C), size(A), size(B)) n = size(A,1) iszero(n) && return C - n <= 3 && return mul!(C, Array(A), Array(B), _add.alpha, _add.beta) _rmul_or_fill!(C, _add.beta) # see the same use above iszero(_add.alpha) && return C Al = _diag(A, -1) @@ -629,28 +632,99 @@ function _mul!(C::AbstractMatrix, A::BiTriSym, B::Diagonal, _add::MulAddMul) Bd = B.diag @inbounds begin # first row of C - C[1,1] += _add(A[1,1]*B[1,1]) - C[1,2] += _add(A[1,2]*B[2,2]) + for j in 1:min(2, n) + C[1,j] += _add(A[1,j]*B[j,j]) + end # second row of C - C[2,1] += _add(A[2,1]*B[1,1]) - C[2,2] += _add(A[2,2]*B[2,2]) - C[2,3] += _add(A[2,3]*B[3,3]) + if n > 1 + for j in 1:min(3, n) + C[2,j] += _add(A[2,j]*B[j,j]) + end + end for j in 3:n-2 C[j, j-1] += _add(Al[j-1]*Bd[j-1]) C[j, j ] += _add(Ad[j ]*Bd[j ]) C[j, j+1] += _add(Au[j ]*Bd[j+1]) end - # row before last of C - C[n-1,n-2] += _add(A[n-1,n-2]*B[n-2,n-2]) - C[n-1,n-1] += _add(A[n-1,n-1]*B[n-1,n-1]) - C[n-1,n ] += _add(A[n-1, n]*B[n ,n ]) + if n > 3 + # row before last of C + for j in n-2:n + C[n-1,j] += _add(A[n-1,j]*B[j,j]) + end + end # last row of C - C[n,n-1] += _add(A[n,n-1]*B[n-1,n-1]) - C[n,n ] += _add(A[n,n ]*B[n, n ]) + if n > 2 + for j in n-1:n + C[n,j] += _add(A[n,j]*B[j,j]) + end + end end # inbounds C end +function _mul!(C::AbstractMatrix, A::Bidiagonal, B::Diagonal, _add::MulAddMul) + require_one_based_indexing(C) + check_A_mul_B!_sizes(size(C), size(A), size(B)) + n = size(A,1) + iszero(n) && return C + _rmul_or_fill!(C, _add.beta) # see the same use above + iszero(_add.alpha) && return C + (; dv, ev) = A + Bd = B.diag + rowshift = A.uplo == 'U' ? -1 : 1 + evshift = Int(A.uplo == 'U') + @inbounds begin + # first row of C + C[1,1] += _add(dv[1]*Bd[1]) + if n > 1 + if A.uplo == 'L' + C[2,1] += _add(ev[1]*Bd[1]) + end + for col in 2:n-1 + C[col+rowshift, col] += _add(ev[col - evshift]*Bd[col]) + C[col, col] += _add(dv[col]*Bd[col]) + end + if A.uplo == 'U' + C[n-1,n] += _add(ev[n-1]*Bd[n]) + end + C[n, n] += _add(dv[n]*Bd[n]) + end + end # inbounds + C +end + +function _mul!(C::Bidiagonal, A::Bidiagonal, B::Diagonal, _add::MulAddMul) + check_A_mul_B!_sizes(size(C), size(A), size(B)) + n = size(A,1) + iszero(n) && return C + iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta) + Adv, Aev = A.dv, A.ev + Cdv, Cev = C.dv, C.ev + Bd = B.diag + shift = Int(A.uplo == 'U') + if C.uplo == A.uplo + @inbounds begin + _modify!(_add, Adv[1]*Bd[1], Cdv, 1) + for j in eachindex(IndexLinear(), Aev, Cev) + _modify!(_add, Aev[j]*Bd[j+shift], Cev, j) + _modify!(_add, Adv[j+1]*Bd[j+1], Cdv, j+1) + end + end # inbounds + else + @inbounds begin + _modify!(_add, Adv[1]*Bd[1], Cdv, 1) + for j in eachindex(IndexLinear(), Aev, Cev) + _modify!(_add, Adv[j+1]*Bd[j+1], Cdv, j+1) + # this branch will error unless the value is zero + _modify!(_add, Aev[j]*Bd[j+shift], C, (j+1-shift, j+shift)) + # zeros of the correct type + _modify!(_add, A[j+shift, j+1-shift]*Bd[j+1-shift], Cev, j) + end + end + end + C +end + function _mul!(C::AbstractVecOrMat, A::BiTriSym, B::AbstractVecOrMat, _add::MulAddMul) require_one_based_indexing(C, B) nA = size(A,1) @@ -781,6 +855,68 @@ function _dibimul!(C, A, B, _add) end # inbounds C end +function _dibimul!(C::AbstractMatrix, A::Diagonal, B::Bidiagonal, _add) + require_one_based_indexing(C) + check_A_mul_B!_sizes(size(C), size(A), size(B)) + n = size(A,1) + iszero(n) && return C + _rmul_or_fill!(C, _add.beta) # see the same use above + iszero(_add.alpha) && return C + Ad = A.diag + Bdv, Bev = B.dv, B.ev + rowshift = B.uplo == 'U' ? -1 : 1 + evshift = Int(B.uplo == 'U') + @inbounds begin + # first row of C + C[1,1] += _add(Ad[1]*Bdv[1]) + if n > 1 + if B.uplo == 'L' + C[2,1] += _add(Ad[2]*Bev[1]) + end + for col in 2:n-1 + evrow = col+rowshift + C[evrow, col] += _add(Ad[evrow]*Bev[col - evshift]) + C[col, col] += _add(Ad[col]*Bdv[col]) + end + if B.uplo == 'U' + C[n-1,n] += _add(Ad[n-1]*Bev[n-1]) + end + C[n, n] += _add(Ad[n]*Bdv[n]) + end + end # inbounds + C +end +function _dibimul!(C::Bidiagonal, A::Diagonal, B::Bidiagonal, _add) + check_A_mul_B!_sizes(size(C), size(A), size(B)) + n = size(A,1) + n == 0 && return C + iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta) + Ad = A.diag + Bdv, Bev = B.dv, B.ev + Cdv, Cev = C.dv, C.ev + shift = Int(B.uplo == 'L') + if C.uplo == B.uplo + @inbounds begin + _modify!(_add, Ad[1]*Bdv[1], Cdv, 1) + for j in eachindex(IndexLinear(), Bev, Cev) + _modify!(_add, Ad[j+shift]*Bev[j], Cev, j) + _modify!(_add, Ad[j+1]*Bdv[j+1], Cdv, j+1) + end + end # inbounds + else + @inbounds begin + _modify!(_add, Ad[1]*Bdv[1], Cdv, 1) + for j in eachindex(IndexLinear(), Bev, Cev) + _modify!(_add, Ad[j+1]*Bdv[j+1], Cdv, j+1) + # this branch will error unless the value is zero + _modify!(_add, Ad[j+shift]*Bev[j], C, (j+shift, j+1-shift)) + # zeros of the correct type + _modify!(_add, Ad[j+1-shift]*B[j+1-shift,j+shift], Cev, j) + end + end + end + C +end function *(A::UpperOrUnitUpperTriangular, B::Bidiagonal) TS = promote_op(matprod, eltype(A), eltype(B)) diff --git a/stdlib/LinearAlgebra/test/bidiag.jl b/stdlib/LinearAlgebra/test/bidiag.jl index 3c99d0d3b6f5e..e19d890237a26 100644 --- a/stdlib/LinearAlgebra/test/bidiag.jl +++ b/stdlib/LinearAlgebra/test/bidiag.jl @@ -942,9 +942,6 @@ end @test_throws ArgumentError rmul!(B, A) @test_throws ArgumentError lmul!(A, B) end - D = Diagonal(dv) - @test rmul!(copy(A), D) ≈ A * D - @test lmul!(D, copy(A)) ≈ D * A end @testset "non-commutative" begin S32 = SizedArrays.SizedArray{(3,2)}(rand(3,2)) @@ -966,6 +963,42 @@ end end end +@testset "mul with Diagonal" begin + for n in 0:4 + dv, ev = rand(n), rand(max(n-1,0)) + d = rand(n) + for uplo in (:U, :L) + A = Bidiagonal(dv, ev, uplo) + D = Diagonal(d) + M = Matrix(A) + S = similar(A, size(A)) + @test A * D ≈ mul!(S, A, D) ≈ M * D + @test D * A ≈ mul!(S, D, A) ≈ D * M + @test mul!(copy(S), D, A, 2, 2) ≈ D * M * 2 + S * 2 + @test mul!(copy(S), A, D, 2, 2) ≈ M * D * 2 + S * 2 + + A2 = Bidiagonal(dv, zero(ev), uplo) + M2 = Array(A2) + S2 = Bidiagonal(copy(dv), copy(ev), uplo == (:U) ? (:L) : (:U)) + MS2 = Array(S2) + @test mul!(copy(S2), D, A2) ≈ D * M2 + @test mul!(copy(S2), A2, D) ≈ M2 * D + @test mul!(copy(S2), A2, D, 2, 2) ≈ M2 * D * 2 + MS2 * 2 + @test mul!(copy(S2), D, A2, 2, 2) ≈ D * M2 * 2 + MS2 * 2 + end + end + + t1 = SizedArrays.SizedArray{(2,3)}([1 2 3; 3 4 5]) + t2 = SizedArrays.SizedArray{(3,2)}([1 2; 3 4; 5 6]) + dv, ev, d = fill(t1, 4), fill(2t1, 3), fill(t2, 4) + for uplo in (:U, :L) + A = Bidiagonal(dv, ev, uplo) + D = Diagonal(d) + @test A * D ≈ Array(A) * Array(D) + @test D * A ≈ Array(D) * Array(A) + end +end + @testset "conversion to Tridiagonal for immutable bands" begin n = 4 dv = FillArrays.Fill(3, n) diff --git a/test/testhelpers/SizedArrays.jl b/test/testhelpers/SizedArrays.jl index bc02fb5cbbd20..a435ca7591cac 100644 --- a/test/testhelpers/SizedArrays.jl +++ b/test/testhelpers/SizedArrays.jl @@ -64,6 +64,10 @@ function Base.similar(::Type{A}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A< R = similar(A, length.(shape)) SizedArray{length.(shape)}(R) end +function Base.similar(x::SizedArray, ::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {T} + sz = map(length, shape) + SizedArray{sz}(similar(parent(x), T, sz)) +end const SizedMatrixLike = Union{SizedMatrix, Transpose{<:Any, <:SizedMatrix}, Adjoint{<:Any, <:SizedMatrix}} From 07f563ea05cb5cce2661d1e5f8a0a6218089689f Mon Sep 17 00:00:00 2001 From: Zentrik Date: Thu, 8 Aug 2024 13:07:38 +0100 Subject: [PATCH 158/206] Fix unterminated strings in bolt makefiles (#55410) --- contrib/bolt/Makefile | 2 +- contrib/pgo-lto-bolt/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/bolt/Makefile b/contrib/bolt/Makefile index 2e911fcbcdc68..ea92ba9ff936a 100644 --- a/contrib/bolt/Makefile +++ b/contrib/bolt/Makefile @@ -52,7 +52,7 @@ FILES_TO_OPTIMIZE := $(shell for file in $(SYMLINKS_TO_OPTIMIZE); do readlink $( AFTER_INSTRUMENT_MESSAGE:='Run `make finish_stage1` to finish off the build. $\ You can now optionally collect more profiling data by running Julia with an appropriate workload, $\ if you wish, run `make clean_profiles` before doing so to remove any profiling data generated by `make finish_stage1`. $\ - You should end up with some data in $(PROFILE_DIR). Afterwards run `make merge_data && make bolt`. $\ + You should end up with some data in $(PROFILE_DIR). Afterwards run `make merge_data && make bolt`.' $(STAGE0_BUILD) $(STAGE1_BUILD): $(MAKE) -C $(JULIA_ROOT) O=$@ configure diff --git a/contrib/pgo-lto-bolt/Makefile b/contrib/pgo-lto-bolt/Makefile index 6787b3bc4e919..fa88cdcd3d6a7 100644 --- a/contrib/pgo-lto-bolt/Makefile +++ b/contrib/pgo-lto-bolt/Makefile @@ -62,7 +62,7 @@ FILES_TO_OPTIMIZE := $(shell for file in $(SYMLINKS_TO_OPTIMIZE); do readlink $( AFTER_INSTRUMENT_MESSAGE:='Run `make finish_stage2` to finish off the build. $\ You can now optionally collect more profiling data by running Julia with an appropriate workload, $\ if you wish, run `make clean_profiles` before doing so to remove any profiling data generated by `make finish_stage2`. $\ - You should end up with some data in $(BOLT_PROFILE_DIR). Afterwards run `make merge_data && make bolt`. $\ + You should end up with some data in $(BOLT_PROFILE_DIR). Afterwards run `make merge_data && make bolt`.' # When building a single libLLVM.so we need to increase -vp-counters-per-site # significantly From e4398360c33b6065e550b6b5b663543c1e497a57 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 8 Aug 2024 09:41:59 -0400 Subject: [PATCH 159/206] add `rtruncate`, `ltruncate`, `ctruncate` for truncating strings in terms of `textwidth` (#55351) Co-authored-by: Timothy Co-authored-by: Steven G. Johnson <2913679+stevengj@users.noreply.github.com> --- NEWS.md | 1 + base/exports.jl | 3 + base/strings/util.jl | 148 ++++++++++++++++++++++++++++++++++++++++ doc/src/base/strings.md | 3 + test/strings/util.jl | 46 +++++++++++++ 5 files changed, 201 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2e9b32befe342..c4e46acca164e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -102,6 +102,7 @@ New library features the uniquing checking ([#53474]) * `RegexMatch` objects can now be used to construct `NamedTuple`s and `Dict`s ([#50988]) * `Lockable` is now exported ([#54595]) +* New `ltruncate`, `rtruncate` and `ctruncate` functions for truncating strings to text width, accounting for char widths ([#55351]) Standard library changes ------------------------ diff --git a/base/exports.jl b/base/exports.jl index dbe12f933e597..daba9a010a9e6 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -596,6 +596,7 @@ export codepoint, codeunit, codeunits, + ctruncate, digits, digits!, eachsplit, @@ -620,6 +621,7 @@ export join, lpad, lstrip, + ltruncate, ncodeunits, ndigits, nextind, @@ -632,6 +634,7 @@ export rpad, rsplit, rstrip, + rtruncate, split, string, strip, diff --git a/base/strings/util.jl b/base/strings/util.jl index 4b701001a8676..0ba76e1c76fa0 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -513,6 +513,154 @@ function rpad( r == 0 ? stringfn(s, p^q) : stringfn(s, p^q, first(p, r)) end +""" + rtruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…') + +Truncate `str` to at most `maxwidth` columns (as estimated by [`textwidth`](@ref)), replacing the last characters +with `replacement` if necessary. The default replacement string is "…". + +# Examples +```jldoctest +julia> s = rtruncate("🍕🍕 I love 🍕", 10) +"🍕🍕 I lo…" + +julia> textwidth(s) +10 + +julia> rtruncate("foo", 3) +"foo" +``` + +!!! compat "Julia 1.12" + This function was added in Julia 1.12. + +See also [`ltruncate`](@ref) and [`ctruncate`](@ref). +""" +function rtruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…') + ret = string_truncate_boundaries(str, Int(maxwidth), replacement, Val(:right)) + if isnothing(ret) + return string(str) + else + left, _ = ret::Tuple{Int,Int} + @views return str[begin:left] * replacement + end +end + +""" + ltruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…') + +Truncate `str` to at most `maxwidth` columns (as estimated by [`textwidth`](@ref)), replacing the first characters +with `replacement` if necessary. The default replacement string is "…". + +# Examples +```jldoctest +julia> s = ltruncate("🍕🍕 I love 🍕", 10) +"…I love 🍕" + +julia> textwidth(s) +10 + +julia> ltruncate("foo", 3) +"foo" +``` + +!!! compat "Julia 1.12" + This function was added in Julia 1.12. + +See also [`rtruncate`](@ref) and [`ctruncate`](@ref). +""" +function ltruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…') + ret = string_truncate_boundaries(str, Int(maxwidth), replacement, Val(:left)) + if isnothing(ret) + return string(str) + else + _, right = ret::Tuple{Int,Int} + @views return replacement * str[right:end] + end +end + +""" + ctruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…'; prefer_left::Bool = true) + +Truncate `str` to at most `maxwidth` columns (as estimated by [`textwidth`](@ref)), replacing the middle characters +with `replacement` if necessary. The default replacement string is "…". By default, the truncation +prefers keeping chars on the left, but this can be changed by setting `prefer_left` to `false`. + +# Examples +```jldoctest +julia> s = ctruncate("🍕🍕 I love 🍕", 10) +"🍕🍕 …e 🍕" + +julia> textwidth(s) +10 + +julia> ctruncate("foo", 3) +"foo" +``` + +!!! compat "Julia 1.12" + This function was added in Julia 1.12. + +See also [`ltruncate`](@ref) and [`rtruncate`](@ref). +""" +function ctruncate(str::AbstractString, maxwidth::Integer, replacement::Union{AbstractString,AbstractChar} = '…'; prefer_left::Bool = true) + ret = string_truncate_boundaries(str, Int(maxwidth), replacement, Val(:center), prefer_left) + if isnothing(ret) + return string(str) + else + left, right = ret::Tuple{Int,Int} + @views return str[begin:left] * replacement * str[right:end] + end +end + +function string_truncate_boundaries( + str::AbstractString, + maxwidth::Integer, + replacement::Union{AbstractString,AbstractChar}, + ::Val{mode}, + prefer_left::Bool = true) where {mode} + + maxwidth >= 0 || throw(ArgumentError("maxwidth $maxwidth should be non-negative")) + + # check efficiently for early return if str is less wide than maxwidth + total_width = 0 + for c in str + total_width += textwidth(c) + total_width > maxwidth && break + end + total_width <= maxwidth && return nothing + + l0, _ = left, right = firstindex(str), lastindex(str) + width = textwidth(replacement) + # used to balance the truncated width on either side + rm_width_left, rm_width_right, force_other = 0, 0, false + @inbounds while true + if mode === :left || (mode === :center && (!prefer_left || left > l0)) + rm_width = textwidth(str[right]) + if mode === :left || (rm_width_right <= rm_width_left || force_other) + force_other = false + (width += rm_width) <= maxwidth || break + rm_width_right += rm_width + right = prevind(str, right) + else + force_other = true + end + end + if mode ∈ (:right, :center) + rm_width = textwidth(str[left]) + if mode === :left || (rm_width_left <= rm_width_right || force_other) + force_other = false + (width += textwidth(str[left])) <= maxwidth || break + rm_width_left += rm_width + left = nextind(str, left) + else + force_other = true + end + end + end + return prevind(str, left), nextind(str, right) +end + """ eachsplit(str::AbstractString, dlm; limit::Integer=0, keepempty::Bool=true) eachsplit(str::AbstractString; limit::Integer=0, keepempty::Bool=false) diff --git a/doc/src/base/strings.md b/doc/src/base/strings.md index ef470be6b55cc..b7d16ffc7d487 100644 --- a/doc/src/base/strings.md +++ b/doc/src/base/strings.md @@ -48,6 +48,9 @@ Base.:(==)(::AbstractString, ::AbstractString) Base.cmp(::AbstractString, ::AbstractString) Base.lpad Base.rpad +Base.ltruncate +Base.rtruncate +Base.ctruncate Base.findfirst(::AbstractString, ::AbstractString) Base.findnext(::AbstractString, ::AbstractString, ::Integer) Base.findnext(::AbstractChar, ::AbstractString, ::Integer) diff --git a/test/strings/util.jl b/test/strings/util.jl index e5db9bd03ae8e..ae16e24f4ea8b 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -67,6 +67,52 @@ end @test rpad("⟨k|H₁|k⟩", 12) |> textwidth == 12 end +@testset "string truncation (ltruncate, rtruncate, ctruncate)" begin + @test ltruncate("foo", 4) == "foo" + @test ltruncate("foo", 3) == "foo" + @test ltruncate("foo", 2) == "…o" + @test ltruncate("🍕🍕 I love 🍕", 10) == "…I love 🍕" # handle wide emojis + @test ltruncate("🍕🍕 I love 🍕", 10, "[…]") == "[…]love 🍕" + # when the replacement string is longer than the trunc + # trust that the user wants the replacement string rather than erroring + @test ltruncate("abc", 2, "xxxxxx") == "xxxxxx" + + @inferred ltruncate("xxx", 4) + @inferred ltruncate("xxx", 2) + @inferred ltruncate(@view("xxxxxxx"[1:4]), 4) + @inferred ltruncate(@view("xxxxxxx"[1:4]), 2) + + @test rtruncate("foo", 4) == "foo" + @test rtruncate("foo", 3) == "foo" + @test rtruncate("foo", 2) == "f…" + @test rtruncate("🍕🍕 I love 🍕", 10) == "🍕🍕 I lo…" + @test rtruncate("🍕🍕 I love 🍕", 10, "[…]") == "🍕🍕 I […]" + @test rtruncate("abc", 2, "xxxxxx") == "xxxxxx" + + @inferred rtruncate("xxx", 4) + @inferred rtruncate("xxx", 2) + @inferred rtruncate(@view("xxxxxxx"[1:4]), 4) + @inferred rtruncate(@view("xxxxxxx"[1:4]), 2) + + @test ctruncate("foo", 4) == "foo" + @test ctruncate("foo", 3) == "foo" + @test ctruncate("foo", 2) == "f…" + @test ctruncate("foo", 2; prefer_left=true) == "f…" + @test ctruncate("foo", 2; prefer_left=false) == "…o" + @test ctruncate("foobar", 6) == "foobar" + @test ctruncate("foobar", 5) == "fo…ar" + @test ctruncate("foobar", 4) == "fo…r" + @test ctruncate("🍕🍕 I love 🍕", 10) == "🍕🍕 …e 🍕" + @test ctruncate("🍕🍕 I love 🍕", 10, "[…]") == "🍕🍕[…] 🍕" + @test ctruncate("abc", 2, "xxxxxx") == "xxxxxx" + @test ctruncate("🍕🍕🍕🍕🍕🍕xxxxxxxxxxx", 9) == "🍕🍕…xxxx" + + @inferred ctruncate("xxxxx", 5) + @inferred ctruncate("xxxxx", 3) + @inferred ctruncate(@view("xxxxxxx"[1:5]), 5) + @inferred ctruncate(@view("xxxxxxx"[1:5]), 3) +end + # string manipulation @testset "lstrip/rstrip/strip" begin @test strip("") == "" From f0a2a7a0a9438433eb1ac824bd09627ab8fd0586 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Thu, 8 Aug 2024 10:51:48 -0400 Subject: [PATCH 160/206] re-add `unsafe_convert` for Reinterpret and Reshaped array (#55226) Fxes https://github.com/JuliaLang/julia/issues/54725 --- base/reinterpretarray.jl | 1 + base/reshapedarray.jl | 1 + test/ccall.jl | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index d74a043293a3a..d31f3ebb5dd2d 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -373,6 +373,7 @@ has_offset_axes(a::ReinterpretArray) = has_offset_axes(a.parent) elsize(::Type{<:ReinterpretArray{T}}) where {T} = sizeof(T) cconvert(::Type{Ptr{T}}, a::ReinterpretArray{T,N,S} where N) where {T,S} = cconvert(Ptr{S}, a.parent) +unsafe_convert(::Type{Ptr{T}}, a::ReinterpretArray{T,N,S} where N) where {T,S} = Ptr{T}(unsafe_convert(Ptr{S},a.parent)) @propagate_inbounds function getindex(a::NonReshapedReinterpretArray{T,0,S}) where {T,S} if isprimitivetype(T) && isprimitivetype(S) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 4173ef1d3f598..019f1d30a25c2 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -324,6 +324,7 @@ setindex!(A::ReshapedRange, val, index::ReshapedIndex) = _rs_setindex!_err() @noinline _rs_setindex!_err() = error("indexed assignment fails for a reshaped range; consider calling collect") cconvert(::Type{Ptr{T}}, a::ReshapedArray{T}) where {T} = cconvert(Ptr{T}, parent(a)) +unsafe_convert(::Type{Ptr{T}}, a::ReshapedArray{T}) where {T} = unsafe_convert(Ptr{T}, a.parent) # Add a few handy specializations to further speed up views of reshaped ranges const ReshapedUnitRange{T,N,A<:AbstractUnitRange} = ReshapedArray{T,N,A,Tuple{}} diff --git a/test/ccall.jl b/test/ccall.jl index a406af46f0c34..b10504de21abc 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1937,7 +1937,10 @@ end # issue #52025 @test Base.unsafe_convert(Ptr{Ptr{Cchar}}, Base.cconvert(Ptr{Ptr{Cchar}}, map(pointer, ["ab"]))) isa Ptr{Ptr{Cchar}} - +#issue #54725 +for A in (reinterpret(UInt, [0]), reshape([0, 0], 1, 2)) + @test pointer(A) == Base.unsafe_convert(Ptr{Cvoid}, A) == Base.unsafe_convert(Ptr{Int}, A) +end # Cglobal with non-static symbols doesn't error function cglobal_non_static1() sym = (:global_var, libccalltest) From 30d5a3400077f08a7968f7827912920796c63a7c Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:41:33 -0700 Subject: [PATCH 161/206] inference: remove `throw` block deoptimization completely (#49260) Co-authored-by: Cody Tapscott Co-authored-by: Oscar Smith --- base/compiler/abstractinterpretation.jl | 9 ------ base/compiler/compiler.jl | 3 +- base/compiler/inferencestate.jl | 25 ---------------- base/compiler/optimize.jl | 40 +++++++++++-------------- base/compiler/types.jl | 21 ------------- src/julia.h | 21 +++++++------ stdlib/REPL/src/REPLCompletions.jl | 3 +- test/compiler/AbstractInterpreter.jl | 1 - test/compiler/codegen.jl | 2 +- test/dict.jl | 4 +-- 10 files changed, 33 insertions(+), 96 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index e3e3502d66173..789b7e6f5a962 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -43,15 +43,6 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), sv::AbsIntState, max_methods::Int) 𝕃ₚ, 𝕃ᵢ = ipo_lattice(interp), typeinf_lattice(interp) ⊑ₚ, ⊔ₚ, ⊔ᵢ = partialorder(𝕃ₚ), join(𝕃ₚ), join(𝕃ᵢ) - if !should_infer_this_call(interp, sv) - add_remark!(interp, sv, "Skipped call in throw block") - # At this point we are guaranteed to end up throwing on this path, - # which is all that's required for :consistent-cy. Of course, we don't - # know anything else about this statement. - effects = Effects(; consistent=ALWAYS_TRUE) - return CallMeta(Any, Any, effects, NoCallInfo()) - end - argtypes = arginfo.argtypes matches = find_method_matches(interp, argtypes, atype; max_methods) if isa(matches, FailedMethodMatch) diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 9aecdaad51aa5..629641308a217 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -184,8 +184,7 @@ baremodule BuildSettings using Core: ARGS, include using Core.Compiler: >, getindex, length -MAX_METHODS::Int = 3 -UNOPTIMIZE_THROW_BLOCKS::Bool = true +global MAX_METHODS::Int = 3 if length(ARGS) > 2 && ARGS[2] === "--buildsettings" include(BuildSettings, ARGS[3]) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 38011656e41ea..06b038ecb6d2e 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -348,7 +348,6 @@ mutable struct InferenceState restrict_abstract_call_sites = isa(def, Module) # some more setups - InferenceParams(interp).unoptimize_throw_blocks && mark_throw_blocks!(src, handler_info) !iszero(cache_mode & CACHE_MODE_LOCAL) && push!(get_inference_cache(interp), result) this = new( @@ -1102,30 +1101,6 @@ bail_out_apply(::AbstractInterpreter, state::InferenceLoopState, ::InferenceStat bail_out_apply(::AbstractInterpreter, state::InferenceLoopState, ::IRInterpretationState) = state.rt === Any -function should_infer_this_call(interp::AbstractInterpreter, sv::InferenceState) - if InferenceParams(interp).unoptimize_throw_blocks - # Disable inference of calls in throw blocks, since we're unlikely to - # need their types. There is one exception however: If up until now, the - # function has not seen any side effects, we would like to make sure there - # aren't any in the throw block either to enable other optimizations. - if is_stmt_throw_block(get_curr_ssaflag(sv)) - should_infer_for_effects(sv) || return false - end - end - return true -end -function should_infer_for_effects(sv::InferenceState) - def = sv.linfo.def - def isa Method || return false # toplevel frame will not be [semi-]concrete-evaluated - effects = sv.ipo_effects - override = decode_effects_override(def.purity) - effects.consistent === ALWAYS_FALSE && !is_effect_overridden(override, :consistent) && return false - effects.effect_free === ALWAYS_FALSE && !is_effect_overridden(override, :effect_free) && return false - !effects.terminates && !is_effect_overridden(override, :terminates_globally) && return false - return true -end -should_infer_this_call(::AbstractInterpreter, ::IRInterpretationState) = true - add_remark!(::AbstractInterpreter, ::InferenceState, remark) = return add_remark!(::AbstractInterpreter, ::IRInterpretationState, remark) = return diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 85d4a92b3919a..9c89e8596d237 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -23,31 +23,29 @@ const IR_FLAG_INBOUNDS = one(UInt32) << 0 const IR_FLAG_INLINE = one(UInt32) << 1 # This statement is marked as @noinline by user const IR_FLAG_NOINLINE = one(UInt32) << 2 -# This statement is on a code path that eventually `throw`s. -const IR_FLAG_THROW_BLOCK = one(UInt32) << 3 # An optimization pass has updated this statement in a way that may # have exposed information that inference did not see. Re-running # inference on this statement may be profitable. -const IR_FLAG_REFINED = one(UInt32) << 4 +const IR_FLAG_REFINED = one(UInt32) << 3 # This statement is proven :consistent -const IR_FLAG_CONSISTENT = one(UInt32) << 5 +const IR_FLAG_CONSISTENT = one(UInt32) << 4 # This statement is proven :effect_free -const IR_FLAG_EFFECT_FREE = one(UInt32) << 6 +const IR_FLAG_EFFECT_FREE = one(UInt32) << 5 # This statement is proven :nothrow -const IR_FLAG_NOTHROW = one(UInt32) << 7 +const IR_FLAG_NOTHROW = one(UInt32) << 6 # This statement is proven :terminates -const IR_FLAG_TERMINATES = one(UInt32) << 8 +const IR_FLAG_TERMINATES = one(UInt32) << 7 # This statement is proven :noub -const IR_FLAG_NOUB = one(UInt32) << 9 +const IR_FLAG_NOUB = one(UInt32) << 8 # TODO: Both of these should eventually go away once # This statement is :effect_free == EFFECT_FREE_IF_INACCESSIBLEMEMONLY -const IR_FLAG_EFIIMO = one(UInt32) << 10 +const IR_FLAG_EFIIMO = one(UInt32) << 9 # This statement is :inaccessiblememonly == INACCESSIBLEMEM_OR_ARGMEMONLY -const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 11 +const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 10 # This statement has no users and may be deleted if flags get refined to IR_FLAGS_REMOVABLE -const IR_FLAG_UNUSED = one(UInt32) << 12 +const IR_FLAG_UNUSED = one(UInt32) << 11 -const NUM_IR_FLAGS = 13 # sync with julia.h +const NUM_IR_FLAGS = 12 # sync with julia.h const IR_FLAGS_EFFECTS = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_TERMINATES | IR_FLAG_NOUB @@ -249,9 +247,8 @@ end _topmod(sv::OptimizationState) = _topmod(sv.mod) -is_stmt_inline(stmt_flag::UInt32) = has_flag(stmt_flag, IR_FLAG_INLINE) -is_stmt_noinline(stmt_flag::UInt32) = has_flag(stmt_flag, IR_FLAG_NOINLINE) -is_stmt_throw_block(stmt_flag::UInt32) = has_flag(stmt_flag, IR_FLAG_THROW_BLOCK) +is_stmt_inline(stmt_flag::UInt32) = has_flag(stmt_flag, IR_FLAG_INLINE) +is_stmt_noinline(stmt_flag::UInt32) = has_flag(stmt_flag, IR_FLAG_NOINLINE) function new_expr_effect_flags(𝕃ₒ::AbstractLattice, args::Vector{Any}, src::Union{IRCode,IncrementalCompact}, pattern_match=nothing) Targ = args[1] @@ -1272,7 +1269,7 @@ plus_saturate(x::Int, y::Int) = max(x, y, x+y) isknowntype(@nospecialize T) = (T === Union{}) || isa(T, Const) || isconcretetype(widenconst(T)) function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptypes::Vector{VarState}, - params::OptimizationParams, error_path::Bool = false) + params::OptimizationParams) #=const=# UNKNOWN_CALL_COST = 20 head = ex.head if is_meta_expr_head(head) @@ -1333,10 +1330,10 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp return 0 elseif (f === Core.memoryrefget || f === Core.memoryref_isassigned) && length(ex.args) >= 3 atyp = argextype(ex.args[2], src, sptypes) - return isknowntype(atyp) ? 1 : error_path ? params.inline_error_path_cost : params.inline_nonleaf_penalty + return isknowntype(atyp) ? 1 : params.inline_nonleaf_penalty elseif f === Core.memoryrefset! && length(ex.args) >= 3 atyp = argextype(ex.args[2], src, sptypes) - return isknowntype(atyp) ? 5 : error_path ? params.inline_error_path_cost : params.inline_nonleaf_penalty + return isknowntype(atyp) ? 5 : params.inline_nonleaf_penalty elseif f === typeassert && isconstType(widenconst(argextype(ex.args[3], src, sptypes))) return 1 end @@ -1352,7 +1349,7 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp if extyp === Union{} return 0 end - return error_path ? params.inline_error_path_cost : params.inline_nonleaf_penalty + return params.inline_nonleaf_penalty elseif head === :foreigncall foreigncall = ex.args[1] if foreigncall isa QuoteNode && foreigncall.value === :jl_string_ptr @@ -1375,7 +1372,7 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp end a = ex.args[2] if a isa Expr - cost = plus_saturate(cost, statement_cost(a, -1, src, sptypes, params, error_path)) + cost = plus_saturate(cost, statement_cost(a, -1, src, sptypes, params)) end return cost elseif head === :copyast @@ -1389,8 +1386,7 @@ function statement_or_branch_cost(@nospecialize(stmt), line::Int, src::Union{Cod thiscost = 0 dst(tgt) = isa(src, IRCode) ? first(src.cfg.blocks[tgt].stmts) : tgt if stmt isa Expr - thiscost = statement_cost(stmt, line, src, sptypes, params, - is_stmt_throw_block(isa(src, IRCode) ? src.stmts.flag[line] : src.ssaflags[line]))::Int + thiscost = statement_cost(stmt, line, src, sptypes, params)::Int elseif stmt isa GotoNode # loops are generally always expensive # but assume that forward jumps are already counted for from diff --git a/base/compiler/types.jl b/base/compiler/types.jl index 7021601bf87cf..f315b7968fd9b 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -156,11 +156,6 @@ Parameters that control abstract interpretation-based type inference operation. information available. [`Base.@constprop :aggressive`](@ref Base.@constprop) can have a more fine-grained control on this configuration with per-method annotation basis. --- -- `inf_params.unoptimize_throw_blocks::Bool = true`\\ - If `true`, skips inferring calls that are in a block that is known to `throw`. - It may improve the compiler latency without sacrificing the runtime performance - in common situations. ---- - `inf_params.assume_bindings_static::Bool = false`\\ If `true`, assumes that no new bindings will be added, i.e. a non-existing binding at inference time can be assumed to always not exist at runtime (and thus e.g. any access to @@ -176,7 +171,6 @@ struct InferenceParams tuple_complexity_limit_depth::Int ipo_constant_propagation::Bool aggressive_constant_propagation::Bool - unoptimize_throw_blocks::Bool assume_bindings_static::Bool ignore_recursion_hardlimit::Bool @@ -188,7 +182,6 @@ struct InferenceParams tuple_complexity_limit_depth::Int, ipo_constant_propagation::Bool, aggressive_constant_propagation::Bool, - unoptimize_throw_blocks::Bool, assume_bindings_static::Bool, ignore_recursion_hardlimit::Bool) return new( @@ -199,7 +192,6 @@ struct InferenceParams tuple_complexity_limit_depth, ipo_constant_propagation, aggressive_constant_propagation, - unoptimize_throw_blocks, assume_bindings_static, ignore_recursion_hardlimit) end @@ -213,7 +205,6 @@ function InferenceParams( #=tuple_complexity_limit_depth::Int=# 3, #=ipo_constant_propagation::Bool=# true, #=aggressive_constant_propagation::Bool=# false, - #=unoptimize_throw_blocks::Bool=# BuildSettings.UNOPTIMIZE_THROW_BLOCKS, #=assume_bindings_static::Bool=# false, #=ignore_recursion_hardlimit::Bool=# false); max_methods::Int = params.max_methods, @@ -223,7 +214,6 @@ function InferenceParams( tuple_complexity_limit_depth::Int = params.tuple_complexity_limit_depth, ipo_constant_propagation::Bool = params.ipo_constant_propagation, aggressive_constant_propagation::Bool = params.aggressive_constant_propagation, - unoptimize_throw_blocks::Bool = params.unoptimize_throw_blocks, assume_bindings_static::Bool = params.assume_bindings_static, ignore_recursion_hardlimit::Bool = params.ignore_recursion_hardlimit) return InferenceParams( @@ -234,7 +224,6 @@ function InferenceParams( tuple_complexity_limit_depth, ipo_constant_propagation, aggressive_constant_propagation, - unoptimize_throw_blocks, assume_bindings_static, ignore_recursion_hardlimit) end @@ -259,10 +248,6 @@ Parameters that control optimizer operation. tuple return types (in hopes of splitting it up). `opt_params.inline_tupleret_bonus` will be added to `opt_params.inline_cost_threshold` when making inlining decision. --- -- `opt_params.inline_error_path_cost::Int = 20`\\ - Specifies the penalty cost for an un-optimized dynamic call in a block that is known to - `throw`. See also [`(inf_params::InferenceParams).unoptimize_throw_blocks`](@ref InferenceParams). ---- - `opt_params.max_tuple_splat::Int = 32`\\ When attempting to inline `Core._apply_iterate`, abort the optimization if the tuple contains more than this many elements. @@ -289,7 +274,6 @@ struct OptimizationParams inline_cost_threshold::Int inline_nonleaf_penalty::Int inline_tupleret_bonus::Int - inline_error_path_cost::Int max_tuple_splat::Int compilesig_invokes::Bool assume_fatal_throw::Bool @@ -300,7 +284,6 @@ struct OptimizationParams inline_cost_threshold::Int, inline_nonleaf_penalty::Int, inline_tupleret_bonus::Int, - inline_error_path_cost::Int, max_tuple_splat::Int, compilesig_invokes::Bool, assume_fatal_throw::Bool, @@ -310,7 +293,6 @@ struct OptimizationParams inline_cost_threshold, inline_nonleaf_penalty, inline_tupleret_bonus, - inline_error_path_cost, max_tuple_splat, compilesig_invokes, assume_fatal_throw, @@ -323,7 +305,6 @@ function OptimizationParams( #=inline_cost_threshold::Int=# 100, #=inline_nonleaf_penalty::Int=# 1000, #=inline_tupleret_bonus::Int=# 250, - #=inline_error_path_cost::Int=# 20, #=max_tuple_splat::Int=# 32, #=compilesig_invokes::Bool=# true, #=assume_fatal_throw::Bool=# false, @@ -332,7 +313,6 @@ function OptimizationParams( inline_cost_threshold::Int = params.inline_cost_threshold, inline_nonleaf_penalty::Int = params.inline_nonleaf_penalty, inline_tupleret_bonus::Int = params.inline_tupleret_bonus, - inline_error_path_cost::Int = params.inline_error_path_cost, max_tuple_splat::Int = params.max_tuple_splat, compilesig_invokes::Bool = params.compilesig_invokes, assume_fatal_throw::Bool = params.assume_fatal_throw, @@ -342,7 +322,6 @@ function OptimizationParams( inline_cost_threshold, inline_nonleaf_penalty, inline_tupleret_bonus, - inline_error_path_cost, max_tuple_splat, compilesig_invokes, assume_fatal_throw, diff --git a/src/julia.h b/src/julia.h index cbe60e78c2d24..2054a434577e7 100644 --- a/src/julia.h +++ b/src/julia.h @@ -276,7 +276,7 @@ typedef union __jl_purity_overrides_t { } _jl_purity_overrides_t; #define NUM_EFFECTS_OVERRIDES 10 -#define NUM_IR_FLAGS 13 +#define NUM_IR_FLAGS 12 // This type describes a single function body typedef struct _jl_code_info_t { @@ -288,16 +288,15 @@ typedef struct _jl_code_info_t { // 1 << 0 = inbounds region // 1 << 1 = callsite inline region // 1 << 2 = callsite noinline region - // 1 << 3 = throw block - // 1 << 4 = refined statement - // 1 << 5 = :consistent - // 1 << 6 = :effect_free - // 1 << 7 = :nothrow - // 1 << 8 = :terminates - // 1 << 9 = :noub - // 1 << 10 = :effect_free_if_inaccessiblememonly - // 1 << 11 = :inaccessiblemem_or_argmemonly - // 1 << 12-19 = callsite effects overrides + // 1 << 3 = refined statement + // 1 << 4 = :consistent + // 1 << 5 = :effect_free + // 1 << 6 = :nothrow + // 1 << 7 = :terminates + // 1 << 8 = :noub + // 1 << 9 = :effect_free_if_inaccessiblememonly + // 1 << 10 = :inaccessiblemem_or_argmemonly + // 1 << 11-19 = callsite effects overrides // miscellaneous data: jl_array_t *slotnames; // names of local variables jl_array_t *slotflags; // local var bit flags diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 609a7b4d81bc0..dc21cfe529e46 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -556,8 +556,7 @@ struct REPLInterpreter <: CC.AbstractInterpreter function REPLInterpreter(limit_aggressive_inference::Bool=false; world::UInt = Base.get_world_counter(), inf_params::CC.InferenceParams = CC.InferenceParams(; - aggressive_constant_propagation=true, - unoptimize_throw_blocks=false), + aggressive_constant_propagation=true), opt_params::CC.OptimizationParams = CC.OptimizationParams(), inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) return new(limit_aggressive_inference, world, inf_params, opt_params, inf_cache) diff --git a/test/compiler/AbstractInterpreter.jl b/test/compiler/AbstractInterpreter.jl index 0d475a8259000..d95354cefa80c 100644 --- a/test/compiler/AbstractInterpreter.jl +++ b/test/compiler/AbstractInterpreter.jl @@ -176,7 +176,6 @@ end == Val{6} @newinterp Issue48097Interp @MethodTable ISSUE_48097_MT CC.method_table(interp::Issue48097Interp) = CC.OverlayMethodTable(CC.get_inference_world(interp), ISSUE_48097_MT) -CC.InferenceParams(::Issue48097Interp) = CC.InferenceParams(; unoptimize_throw_blocks=false) function CC.concrete_eval_eligible(interp::Issue48097Interp, @nospecialize(f), result::CC.MethodCallResult, arginfo::CC.ArgInfo, sv::CC.AbsIntState) ret = @invoke CC.concrete_eval_eligible(interp::CC.AbstractInterpreter, diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 3d719cbc244e4..cd2702ff0e6aa 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -697,7 +697,7 @@ mktempdir() do pfx libs_deleted += 1 end @test libs_deleted > 0 - @test readchomp(`$pfx/bin/$(Base.julia_exename()) -e 'print("no codegen!\n")'`) == "no codegen!" + @test readchomp(`$pfx/bin/$(Base.julia_exename()) --startup-file=no -e 'print("no codegen!\n")'`) == "no codegen!" # PR #47343 libs_emptied = 0 diff --git a/test/dict.jl b/test/dict.jl index ca8a598de0b81..e327c86521c88 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -1510,9 +1510,9 @@ end for T in (Int, Float64, String, Symbol) @testset let T=T @test !Core.Compiler.is_consistent(Base.infer_effects(getindex, (Dict{T,Any}, T))) - @test_broken Core.Compiler.is_effect_free(Base.infer_effects(getindex, (Dict{T,Any}, T))) + @test Core.Compiler.is_effect_free(Base.infer_effects(getindex, (Dict{T,Any}, T))) @test !Core.Compiler.is_nothrow(Base.infer_effects(getindex, (Dict{T,Any}, T))) - @test_broken Core.Compiler.is_terminates(Base.infer_effects(getindex, (Dict{T,Any}, T))) + @test Core.Compiler.is_terminates(Base.infer_effects(getindex, (Dict{T,Any}, T))) end end From 1d7b036b7318215b418a369dff700ea2a406ebec Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Aug 2024 18:24:40 +0000 Subject: [PATCH 162/206] move clamp from math to intfuncs This is a more apt description, since it is not floating point related, and used earlier (such as in IOBuffer). Fixes #55279 --- base/intfuncs.jl | 99 ++++++++++++++++++++++++++++++++++++++++++++++ base/math.jl | 101 +---------------------------------------------- base/missing.jl | 1 + 3 files changed, 101 insertions(+), 100 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index c73ef68551266..f72ac6ee08d4d 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -1237,3 +1237,102 @@ function binomial(x::Number, k::Integer) # and instead divide each term by i, to avoid spurious overflow. return prod(i -> (x-(i-1))/i, OneTo(k), init=oneunit(x)/one(k)) end + +""" + clamp(x, lo, hi) + +Return `x` if `lo <= x <= hi`. If `x > hi`, return `hi`. If `x < lo`, return `lo`. Arguments +are promoted to a common type. + +See also [`clamp!`](@ref), [`min`](@ref), [`max`](@ref). + +!!! compat "Julia 1.3" + `missing` as the first argument requires at least Julia 1.3. + +# Examples +```jldoctest +julia> clamp.([pi, 1.0, big(10)], 2.0, 9.0) +3-element Vector{BigFloat}: + 3.141592653589793238462643383279502884197169399375105820974944592307816406286198 + 2.0 + 9.0 + +julia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi +3-element Vector{Int64}: + 6 + 6 + 10 +``` +""" +function clamp(x::X, lo::L, hi::H) where {X,L,H} + T = promote_type(X, L, H) + return (x > hi) ? convert(T, hi) : (x < lo) ? convert(T, lo) : convert(T, x) +end + +""" + clamp(x, T)::T + +Clamp `x` between `typemin(T)` and `typemax(T)` and convert the result to type `T`. + +See also [`trunc`](@ref). + +# Examples +```jldoctest +julia> clamp(200, Int8) +127 + +julia> clamp(-200, Int8) +-128 + +julia> trunc(Int, 4pi^2) +39 +``` +""" +function clamp(x, ::Type{T}) where {T<:Integer} + # delegating to clamp(x, typemin(T), typemax(T)) would promote types + # this way, we avoid unnecessary conversions + # think of, e.g., clamp(big(2) ^ 200, Int16) + lo = typemin(T) + hi = typemax(T) + return (x > hi) ? hi : (x < lo) ? lo : convert(T, x) +end + + +""" + clamp!(array::AbstractArray, lo, hi) + +Restrict values in `array` to the specified range, in-place. +See also [`clamp`](@ref). + +!!! compat "Julia 1.3" + `missing` entries in `array` require at least Julia 1.3. + +# Examples +```jldoctest +julia> row = collect(-4:4)'; + +julia> clamp!(row, 0, Inf) +1×9 adjoint(::Vector{Int64}) with eltype Int64: + 0 0 0 0 0 1 2 3 4 + +julia> clamp.((-4:4)', 0, Inf) +1×9 Matrix{Float64}: + 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0 +``` +""" +function clamp!(x::AbstractArray, lo, hi) + @inbounds for i in eachindex(x) + x[i] = clamp(x[i], lo, hi) + end + x +end + +""" + clamp(x::Integer, r::AbstractUnitRange) + +Clamp `x` to lie within range `r`. + +!!! compat "Julia 1.6" + This method requires at least Julia 1.6. +""" +clamp(x::Integer, r::AbstractUnitRange{<:Integer}) = clamp(x, first(r), last(r)) diff --git a/base/math.jl b/base/math.jl index de275a2afc048..da51ab3a17bd0 100644 --- a/base/math.jl +++ b/base/math.jl @@ -23,7 +23,7 @@ import .Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin, using .Base: sign_mask, exponent_mask, exponent_one, exponent_half, uinttype, significand_mask, significand_bits, exponent_bits, exponent_bias, - exponent_max, exponent_raw_max + exponent_max, exponent_raw_max, clamp, clamp! using Core.Intrinsics: sqrt_llvm @@ -69,104 +69,6 @@ end return Txy, T(xy-Txy) end -""" - clamp(x, lo, hi) - -Return `x` if `lo <= x <= hi`. If `x > hi`, return `hi`. If `x < lo`, return `lo`. Arguments -are promoted to a common type. - -See also [`clamp!`](@ref), [`min`](@ref), [`max`](@ref). - -!!! compat "Julia 1.3" - `missing` as the first argument requires at least Julia 1.3. - -# Examples -```jldoctest -julia> clamp.([pi, 1.0, big(10)], 2.0, 9.0) -3-element Vector{BigFloat}: - 3.141592653589793238462643383279502884197169399375105820974944592307816406286198 - 2.0 - 9.0 - -julia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi -3-element Vector{Int64}: - 6 - 6 - 10 -``` -""" -function clamp(x::X, lo::L, hi::H) where {X,L,H} - T = promote_type(X, L, H) - return (x > hi) ? convert(T, hi) : (x < lo) ? convert(T, lo) : convert(T, x) -end - -""" - clamp(x, T)::T - -Clamp `x` between `typemin(T)` and `typemax(T)` and convert the result to type `T`. - -See also [`trunc`](@ref). - -# Examples -```jldoctest -julia> clamp(200, Int8) -127 - -julia> clamp(-200, Int8) --128 - -julia> trunc(Int, 4pi^2) -39 -``` -""" -function clamp(x, ::Type{T}) where {T<:Integer} - # delegating to clamp(x, typemin(T), typemax(T)) would promote types - # this way, we avoid unnecessary conversions - # think of, e.g., clamp(big(2) ^ 200, Int16) - lo = typemin(T) - hi = typemax(T) - return (x > hi) ? hi : (x < lo) ? lo : convert(T, x) -end - - -""" - clamp!(array::AbstractArray, lo, hi) - -Restrict values in `array` to the specified range, in-place. -See also [`clamp`](@ref). - -!!! compat "Julia 1.3" - `missing` entries in `array` require at least Julia 1.3. - -# Examples -```jldoctest -julia> row = collect(-4:4)'; - -julia> clamp!(row, 0, Inf) -1×9 adjoint(::Vector{Int64}) with eltype Int64: - 0 0 0 0 0 1 2 3 4 - -julia> clamp.((-4:4)', 0, Inf) -1×9 Matrix{Float64}: - 0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0 -``` -""" -function clamp!(x::AbstractArray, lo, hi) - @inbounds for i in eachindex(x) - x[i] = clamp(x[i], lo, hi) - end - x -end - -""" - clamp(x::Integer, r::AbstractUnitRange) - -Clamp `x` to lie within range `r`. - -!!! compat "Julia 1.6" - This method requires at least Julia 1.6. -""" -clamp(x::Integer, r::AbstractUnitRange{<:Integer}) = clamp(x, first(r), last(r)) """ evalpoly(x, p) @@ -1690,7 +1592,6 @@ end exp2(x::AbstractFloat) = 2^x exp10(x::AbstractFloat) = 10^x -clamp(::Missing, lo, hi) = missing fourthroot(::Missing) = missing end # module diff --git a/base/missing.jl b/base/missing.jl index ce174edc297e3..1f34195efed88 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -135,6 +135,7 @@ min(::Any, ::Missing) = missing max(::Missing, ::Missing) = missing max(::Missing, ::Any) = missing max(::Any, ::Missing) = missing +clamp(::Missing, lo, hi) = missing missing_conversion_msg(@nospecialize T) = LazyString("cannot convert a missing value to type ", T, ": use Union{", T, ", Missing} instead") From fc6047bf17e0e6ef13fb487852248017d082d949 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Aug 2024 18:42:45 +0000 Subject: [PATCH 163/206] copyuntil: reduce over-allocation to start This fits into a 32-byte allocation pool, saving up to 64 bytes when repeatedly reading small chunks of data (e.g. tokenizing a CSV file). In some local `@btime` measurements, this seems to take <10% more time across a range of output lengths. --- base/io.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/io.jl b/base/io.jl index 0f1812942d23e..83a215d6359fc 100644 --- a/base/io.jl +++ b/base/io.jl @@ -543,8 +543,8 @@ julia> rm("my_file.txt") ``` """ readuntil(filename::AbstractString, delim; kw...) = open(io->readuntil(io, delim; kw...), convert(String, filename)::String) -readuntil(stream::IO, delim::UInt8; kw...) = _unsafe_take!(copyuntil(IOBuffer(sizehint=70), stream, delim; kw...)) -readuntil(stream::IO, delim::Union{AbstractChar, AbstractString}; kw...) = String(_unsafe_take!(copyuntil(IOBuffer(sizehint=70), stream, delim; kw...))) +readuntil(stream::IO, delim::UInt8; kw...) = _unsafe_take!(copyuntil(IOBuffer(sizehint=16), stream, delim; kw...)) +readuntil(stream::IO, delim::Union{AbstractChar, AbstractString}; kw...) = String(_unsafe_take!(copyuntil(IOBuffer(sizehint=16), stream, delim; kw...))) readuntil(stream::IO, delim::T; keep::Bool=false) where T = _copyuntil(Vector{T}(), stream, delim, keep) @@ -617,7 +617,7 @@ Logan readline(filename::AbstractString; keep::Bool=false) = open(io -> readline(io; keep), filename) readline(s::IO=stdin; keep::Bool=false) = - String(_unsafe_take!(copyline(IOBuffer(sizehint=70), s; keep))) + String(_unsafe_take!(copyline(IOBuffer(sizehint=16), s; keep))) """ copyline(out::IO, io::IO=stdin; keep::Bool=false) @@ -1111,7 +1111,7 @@ function copyuntil(out::IO, io::IO, target::AbstractString; keep::Bool=false) end function readuntil(io::IO, target::AbstractVector{T}; keep::Bool=false) where T - out = (T === UInt8 ? resize!(StringVector(70), 0) : Vector{T}()) + out = (T === UInt8 ? resize!(StringVector(16), 0) : Vector{T}()) readuntil_vector!(io, target, keep, out) return out end From be77f650deb8dbf6496e4bb85e19409a0459f1a5 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 8 Aug 2024 14:59:53 -0400 Subject: [PATCH 164/206] improve docs for `collect` and square brackets (#55352) fixes #55350 --------- Co-authored-by: Neven Sajko --- base/abstractarray.jl | 2 ++ base/array.jl | 20 +++++++++++++++++++- base/broadcast.jl | 1 + base/docs/basedocs.jl | 7 +++++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 40e36ce15f6ed..77aae63399ec8 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -3408,6 +3408,8 @@ mapany(f, itr) = Any[f(x) for x in itr] Transform collection `c` by applying `f` to each element. For multiple collection arguments, apply `f` elementwise, and stop when any of them is exhausted. +The element type of the result is determined in the same manner as in [`collect`](@ref). + See also [`map!`](@ref), [`foreach`](@ref), [`mapreduce`](@ref), [`mapslices`](@ref), [`zip`](@ref), [`Iterators.map`](@ref). # Examples diff --git a/base/array.jl b/base/array.jl index 008a52abb952e..648fedd5036e1 100644 --- a/base/array.jl +++ b/base/array.jl @@ -660,7 +660,7 @@ _array_for(::Type{T}, itr, isz) where {T} = _array_for(T, isz, _similar_shape(it """ - collect(collection) + collect(iterator) Return an `Array` of all items in a collection or iterator. For dictionaries, returns a `Vector` of `key=>value` [Pair](@ref Pair)s. If the argument is array-like or is an iterator @@ -671,6 +671,9 @@ Used by [comprehensions](@ref man-comprehensions) to turn a [generator expressio into an `Array`. Thus, *on generators*, the square-brackets notation may be used instead of calling `collect`, see second example. +The element type of the returned array is based on the types of the values collected. However, if the +iterator is empty then the element type of the returned (empty) array is determined by type inference. + # Examples Collect items from a `UnitRange{Int64}` collection: @@ -692,6 +695,21 @@ julia> collect(x^2 for x in 1:3) 4 9 ``` + +Collecting an empty iterator where the result type depends on type inference: + +```jldoctest +julia> [rand(Bool) ? 1 : missing for _ in []] +Union{Missing, Int64}[] +``` + +When the iterator is non-empty, the result type depends only on values: + +```julia-repl +julia> [rand(Bool) ? 1 : missing for _ in [""]] +1-element Vector{Int64}: + 1 +``` """ collect(itr) = _collect(1:1 #= Array =#, itr, IteratorEltype(itr), IteratorSize(itr)) diff --git a/base/broadcast.jl b/base/broadcast.jl index 57eac7f3a094c..927c946e53e02 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -751,6 +751,7 @@ The resulting container type is established by the following rules: - All other combinations of arguments default to returning an `Array`, but custom container types can define their own implementation and promotion-like rules to customize the result when they appear as arguments. + - The element type is determined in the same manner as in [`collect`](@ref). A special syntax exists for broadcasting: `f.(args...)` is equivalent to `broadcast(f, args...)`, and nested `f.(g.(args...))` calls are fused into a diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 2ed1bd98caa5c..e03d0db78f29f 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -663,8 +663,11 @@ kw"{", kw"{}", kw"}" """ [] -Square braces are used for [indexing](@ref man-array-indexing), [indexed assignment](@ref man-indexed-assignment), -[array literals](@ref man-array-literals), and [array comprehensions](@ref man-comprehensions). +Square brackets are used for [indexing](@ref man-array-indexing) ([`getindex`](@ref)), +[indexed assignment](@ref man-indexed-assignment) ([`setindex!`](@ref)), +[array literals](@ref man-array-literals) ([`Base.vect`](@ref)), +[array concatenation](@ref man-array-concatenation) ([`vcat`](@ref), [`hcat`](@ref), [`hvcat`](@ref), [`hvncat`](@ref)), +and [array comprehensions](@ref man-comprehensions) ([`collect`](@ref)). """ kw"[", kw"[]", kw"]" From f2767570fd5b1f3cfb3f69e8acca22cbb850a386 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 8 Aug 2024 15:17:34 -0400 Subject: [PATCH 165/206] REPL: disable flaky win32 stacktrace tests (#55408) Disables these tests on win32 that have been flaky on that platform since February at least https://github.com/JuliaLang/julia/issues/53340 --- stdlib/REPL/test/repl.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 6f0c4a5c3d6ba..f4d594b2a02e1 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -244,8 +244,9 @@ fake_repl(options = REPL.Options(confirm_exit=false,hascolor=true)) do stdin_wri @test occursin("shell> ", s) # check for the echo of the prompt @test occursin("'", s) # check for the echo of the input s = readuntil(stdout_read, "\n\n") - @test startswith(s, "\e[0mERROR: unterminated single quote\nStacktrace:\n [1] ") || - startswith(s, "\e[0m\e[1m\e[91mERROR: \e[39m\e[22m\e[91munterminated single quote\e[39m\nStacktrace:\n [1] ") + @test(startswith(s, "\e[0mERROR: unterminated single quote\nStacktrace:\n [1] ") || + startswith(s, "\e[0m\e[1m\e[91mERROR: \e[39m\e[22m\e[91munterminated single quote\e[39m\nStacktrace:\n [1] "), + skip = Sys.iswindows() && Sys.WORD_SIZE == 32) write(stdin_write, "\b") wait(t) end @@ -1650,12 +1651,12 @@ fake_repl() do stdin_write, stdout_read, repl write(stdin_write, "foobar\n") readline(stdout_read) @test readline(stdout_read) == "\e[0mERROR: UndefVarError: `foobar` not defined in `Main`" - @test readline(stdout_read) == "" + @test readline(stdout_read) == "" skip = Sys.iswindows() && Sys.WORD_SIZE == 32 readuntil(stdout_read, "julia> ", keep=true) # check that top-level error did not change `err` write(stdin_write, "err\n") readline(stdout_read) - @test readline(stdout_read) == "\e[0m" + @test readline(stdout_read) == "\e[0m" skip = Sys.iswindows() && Sys.WORD_SIZE == 32 readuntil(stdout_read, "julia> ", keep=true) # generate deeper error write(stdin_write, "foo() = foobar\n") From 32423a8039daeb57ecd7bc26db5476125c0bfb62 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Aug 2024 15:18:11 -0400 Subject: [PATCH 166/206] handle unbound vars in NTuple fields (#55405) Comparing objects by `==` will happily answer nonsense for malformed type comparisons, such as `unwrap_unionall(A) == A`. Avoid forming that query. Additionally, need to recourse through Vararg when examining type structure to make decisions. Fix #55076 Fix #55189 --- src/builtins.c | 6 ++++++ src/jltypes.c | 6 +++--- test/core.jl | 7 +++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 8cc1465592068..045a9914f5078 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2084,6 +2084,12 @@ static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layou return references_name(((jl_uniontype_t*)p)->a, name, affects_layout, freevars) || references_name(((jl_uniontype_t*)p)->b, name, affects_layout, freevars); } + if (jl_is_vararg(p)) { + jl_value_t *T = ((jl_vararg_t*)p)->T; + jl_value_t *N = ((jl_vararg_t*)p)->N; + return (T && references_name(T, name, affects_layout, freevars)) || + (N && references_name(N, name, affects_layout, freevars)); + } if (jl_is_typevar(p)) return 0; // already checked by unionall, if applicable if (jl_is_datatype(p)) { diff --git a/src/jltypes.c b/src/jltypes.c index fe490d2c45acb..5dc50ff0ca4e6 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1961,7 +1961,7 @@ static jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *t, int check, int not t = normalize_unionalls(t); p = t; jl_value_t *tw = extract_wrapper(t); - if (tw && t != tw && jl_types_equal(t, tw)) + if (tw && t != tw && !jl_has_free_typevars(t) && jl_types_equal(t, tw)) t = tw; p = t; check = 0; // remember that checks are already done now @@ -2045,7 +2045,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value // normalize types equal to wrappers (prepare for Typeofwrapper) jl_value_t *tw = extract_wrapper(pi); if (tw && tw != pi && (tn != jl_type_typename || jl_typeof(pi) == jl_typeof(tw)) && - jl_types_equal(pi, tw)) { + !jl_has_free_typevars(pi) && jl_types_equal(pi, tw)) { iparams[i] = tw; if (p) jl_gc_wb(p, tw); } @@ -2717,7 +2717,7 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n, int check, int nothrow if (valid) { t = normalize_unionalls(t); jl_value_t *tw = extract_wrapper(t); - if (tw && t != tw && jl_types_equal(t, tw)) + if (tw && t != tw && !jl_has_free_typevars(t) && jl_types_equal(t, tw)) t = tw; } } diff --git a/test/core.jl b/test/core.jl index e765d5a2ab7d7..79373722185b7 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7495,6 +7495,13 @@ struct A43411{S, T} end @test isbitstype(A43411{(:a,), Tuple{Int}}) +# issue #55189 +struct A55189{N} + children::NTuple{N,A55189{N}} +end +@test fieldtype(A55189{2}, 1) === Tuple{A55189{2}, A55189{2}} +@assert !isbitstype(A55189{2}) + # issue #44614 struct T44614_1{T} m::T From 7e1f0be207b5247a8303549f1aec2c73e79c403e Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Thu, 8 Aug 2024 16:27:33 -0300 Subject: [PATCH 167/206] codgen: make the Memory GEP an inbounds GEP (#55107) The Julia memory model is always inbounds for GEP. This makes the code in https://github.com/JuliaLang/julia/issues/55090 look almost the same as it did before the change. Locally I wasn't able to reproduce the regression, but given it's vectorized code I suspect it is backend sensitive. Fixes https://github.com/JuliaLang/julia/issues/55090 Co-authored-by: Zentrik --- src/cgutils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 08d51f52b613b..3695dc1370050 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -4286,9 +4286,8 @@ static jl_cgval_t emit_memoryref(jl_codectx_t &ctx, const jl_cgval_t &ref, jl_cg ovflw = ctx.builder.CreateICmpUGE(ctx.builder.CreateAdd(offset, mlen), ctx.builder.CreateNUWAdd(mlen, mlen)); } #endif - //Is this change fine boffset = ctx.builder.CreateMul(offset, elsz); - newdata = ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()), data, boffset); + newdata = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), data, boffset); (void)boffset; // LLVM is very bad at handling GEP with types different from the load if (bc) { BasicBlock *failBB, *endBB; From 1db5cf7bfc965d50ae96fa4b1eb34944731cca21 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Aug 2024 18:37:08 -0400 Subject: [PATCH 168/206] ml-matches: ensure all methods are included (#55365) Some methods were filtered out based simply on visit order, which was not intentional, with the lim==-1 weak-edges mode. Fix #55231 --- src/gf.c | 2 +- test/ambiguous.jl | 16 ++++++++++++++++ test/core.jl | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index 659261d434659..5ae7644c01363 100644 --- a/src/gf.c +++ b/src/gf.c @@ -3669,7 +3669,7 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array int msp2 = !msp && jl_method_morespecific(m2, m); if (!msp) { if (subt || !include_ambiguous || (lim != -1 && msp2)) { - if (subt2 || jl_subtype((jl_value_t*)ti, m2->sig)) { + if (subt2 || ((lim != -1 || (!include_ambiguous && !msp2)) && jl_subtype((jl_value_t*)ti, m2->sig))) { // this may be filtered out as fully intersected, if applicable later mayexclude = 1; } diff --git a/test/ambiguous.jl b/test/ambiguous.jl index d6f69f21bcdce..acdfdc70ba30c 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -447,4 +447,20 @@ cc46601(::Type{T}, x::Int) where {T<:AbstractString} = 7 @test length(methods(cc46601, Tuple{Type{<:Integer}, Integer})) == 2 @test length(Base.methods_including_ambiguous(cc46601, Tuple{Type{<:Integer}, Integer})) == 7 +# Issue #55231 +struct U55231{P} end +struct V55231{P} end +U55231(::V55231) = nothing +(::Type{T})(::V55231) where {T<:U55231} = nothing +@test length(methods(U55231)) == 2 +U55231(a, b) = nothing +@test length(methods(U55231)) == 3 +struct S55231{P} end +struct T55231{P} end +(::Type{T})(::T55231) where {T<:S55231} = nothing +S55231(::T55231) = nothing +@test length(methods(S55231)) == 2 +S55231(a, b) = nothing +@test length(methods(S55231)) == 3 + nothing diff --git a/test/core.jl b/test/core.jl index 79373722185b7..4cbb872ce4e50 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7572,7 +7572,7 @@ end # issue #31696 foo31696(x::Int8, y::Int8) = 1 foo31696(x::T, y::T) where {T <: Int8} = 2 -@test length(methods(foo31696)) == 1 +@test length(methods(foo31696)) == 2 let T1 = Tuple{Int8}, T2 = Tuple{T} where T<:Int8, a = T1[(1,)], b = T2[(1,)] b .= a @test b[1] == (1,) From 57aef91b4776e3bc07a813989ab56475b459ab9c Mon Sep 17 00:00:00 2001 From: Nathan Zimmerberg <39104088+nhz2@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:56:56 -0400 Subject: [PATCH 169/206] Make `mv` more atomic by trying rename before deleting `dst` (#55384) As noted in https://github.com/JuliaLang/julia/issues/41584 and https://discourse.julialang.org/t/safe-overwriting-of-files/117758/3 `mv` is usually expected to be "best effort atomic". Currently calling `mv` with `force=true` calls `checkfor_mv_cp_cptree(src, dst, "moving"; force=true)` before renaming. `checkfor_mv_cp_cptree` will delete `dst` if exists and isn't the same as `src`. If `dst` is an existing file and julia stops after deleting `dst` but before doing the rename, `dst` will be removed but will not be replaced with `src`. This PR changes `mv` with `force=true` to first try rename, and only delete `dst` if that fails. Assuming file system support and the first rename works, julia stopping will not lead to `dst` being removed without being replaced. This also replaces a stopgap solution from https://github.com/JuliaLang/julia/pull/36638#discussion_r453820564 --- base/file.jl | 77 ++++++++++++++++++++++++++++++++++++++++------ base/loading.jl | 6 ++-- test/file.jl | 2 +- test/filesystem.jl | 2 +- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/base/file.jl b/base/file.jl index e1b8e8a748fae..3987029d5f74f 100644 --- a/base/file.jl +++ b/base/file.jl @@ -440,11 +440,61 @@ julia> rm("goodbye.txt"); ``` """ function mv(src::AbstractString, dst::AbstractString; force::Bool=false) - checkfor_mv_cp_cptree(src, dst, "moving"; force=force) - rename(src, dst) + if force + _mv_replace(src, dst) + else + _mv_noreplace(src, dst) + end +end + +function _mv_replace(src::AbstractString, dst::AbstractString) + # This check is copied from checkfor_mv_cp_cptree + if ispath(dst) && Base.samefile(src, dst) + abs_src = islink(src) ? abspath(readlink(src)) : abspath(src) + abs_dst = islink(dst) ? abspath(readlink(dst)) : abspath(dst) + throw(ArgumentError(string("'src' and 'dst' refer to the same file/dir. ", + "This is not supported.\n ", + "`src` refers to: $(abs_src)\n ", + "`dst` refers to: $(abs_dst)\n"))) + end + # First try to do a regular rename, because this might avoid a situation + # where dst is deleted or truncated. + try + rename(src, dst) + catch err + err isa IOError || rethrow() + err.code==Base.UV_ENOENT && rethrow() + # on rename error try to delete dst if it exists and isn't the same as src + checkfor_mv_cp_cptree(src, dst, "moving"; force=true) + try + rename(src, dst) + catch err + err isa IOError || rethrow() + # on second error, default to force cp && rm + cp(src, dst; force=true, follow_symlinks=false) + rm(src; recursive=true) + end + end + dst +end + +function _mv_noreplace(src::AbstractString, dst::AbstractString) + # Error if dst exists. + # This check currently has TOCTTOU issues. + checkfor_mv_cp_cptree(src, dst, "moving"; force=false) + try + rename(src, dst) + catch err + err isa IOError || rethrow() + err.code==Base.UV_ENOENT && rethrow() + # on error, default to cp && rm + cp(src, dst; force=false, follow_symlinks=false) + rm(src; recursive=true) + end dst end + """ touch(path::AbstractString) touch(fd::File) @@ -1126,15 +1176,24 @@ function unlink(p::AbstractString) nothing end -# For move command -function rename(src::AbstractString, dst::AbstractString; force::Bool=false) - err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), src, dst) - # on error, default to cp && rm +""" + rename(oldpath::AbstractString, newpath::AbstractString) + +Change the name of a file from `oldpath` to `newpath`. If `newpath` is an existing file it may be replaced. +Equivalent to [rename(2)](https://man7.org/linux/man-pages/man2/rename.2.html). +Throws an `IOError` on failure. +Return `newpath`. + +OS-specific restrictions may apply when `oldpath` and `newpath` are in different directories. + +See also: [`mv`](@ref). +""" +function rename(oldpath::AbstractString, newpath::AbstractString) + err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), oldpath, newpath) if err < 0 - cp(src, dst; force=force, follow_symlinks=false) - rm(src; recursive=true) + uv_error("rename($(repr(oldpath)), $(repr(newpath)))", err) end - nothing + newpath end function sendfile(src::AbstractString, dst::AbstractString) diff --git a/base/loading.jl b/base/loading.jl index c273e4505701f..eb467d9cc0bd4 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -3047,7 +3047,9 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in end end # this is atomic according to POSIX (not Win32): - rename(tmppath, cachefile; force=true) + # but force=true means it will fall back to non atomic + # move if the initial rename fails. + mv(tmppath, cachefile; force=true) return cachefile, ocachefile end finally @@ -3066,7 +3068,7 @@ end function rename_unique_ocachefile(tmppath_so::String, ocachefile_orig::String, ocachefile::String = ocachefile_orig, num = 0) try - rename(tmppath_so, ocachefile; force=true) + mv(tmppath_so, ocachefile; force=true) catch e e isa IOError || rethrow() # If `rm` was called on a dir containing a loaded DLL, we moved it to temp for cleanup diff --git a/test/file.jl b/test/file.jl index f82b2a0fd8f39..005c765e08b90 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1031,7 +1031,7 @@ if !Sys.iswindows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER @test_throws Base._UVError("open($(repr(nonexisting_src)), $(Base.JL_O_RDONLY), 0)", Base.UV_ENOENT) cp(nonexisting_src, dst; force=true, follow_symlinks=false) @test_throws Base._UVError("open($(repr(nonexisting_src)), $(Base.JL_O_RDONLY), 0)", Base.UV_ENOENT) cp(nonexisting_src, dst; force=true, follow_symlinks=true) # mv - @test_throws Base._UVError("open($(repr(nonexisting_src)), $(Base.JL_O_RDONLY), 0)", Base.UV_ENOENT) mv(nonexisting_src, dst; force=true) + @test_throws Base._UVError("rename($(repr(nonexisting_src)), $(repr(dst)))", Base.UV_ENOENT) mv(nonexisting_src, dst; force=true) end end diff --git a/test/filesystem.jl b/test/filesystem.jl index 870350dee9f35..036a3dda30cca 100644 --- a/test/filesystem.jl +++ b/test/filesystem.jl @@ -44,7 +44,7 @@ end @testset "Base.Filesystem docstrings" begin undoc = Docs.undocumented_names(Base.Filesystem) @test_broken isempty(undoc) - @test undoc == [:File, :Filesystem, :cptree, :futime, :rename, :sendfile, :unlink] + @test undoc == [:File, :Filesystem, :cptree, :futime, :sendfile, :unlink] end @testset "write return type" begin From e7e8768a77548250d6a06a9fcd35086a0e876ddb Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 8 Aug 2024 16:44:30 -0700 Subject: [PATCH 170/206] Vendor the terminfo database for use with base/terminfo.jl (#55411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the `terminfo` database to `deps/`, providing a better user experience on systems that don't have `terminfo` on the system by default. The database is built using BinaryBuilder but is not actually platform-specific (it's built for `AnyPlatform`) and as such, this fetches the artifact directly rather than adding a new JLL to stdlib, and it requires no compilation. A build flag, `WITH_TERMINFO`, is added here and assumed true by default, allowing users to set `WITH_TERMINFO=0` in Make.user to avoid bundling `terminfo` should they want to do so. The lookup policy for `terminfo` entries is still compliant with what's described in `terminfo(5)`; the bundled directory is taken to be the first "compiled in" location, i.e. prepended to `@TERMINFO_DIRS@`. This allows any user settings that exist locally, such as custom entries or locations, to take precedence. Fixes #55274 Co-authored-by: Mosè Giordano --- Makefile | 4 +++ NEWS.md | 4 +++ base/terminfo.jl | 11 +++++++- deps/Makefile | 8 +++++- deps/checksums/terminfo | 2 ++ deps/terminfo.mk | 43 ++++++++++++++++++++++++++++++ deps/terminfo.version | 3 +++ stdlib/REPL/test/precompilation.jl | 7 +++-- 8 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 deps/checksums/terminfo create mode 100644 deps/terminfo.mk create mode 100644 deps/terminfo.version diff --git a/Makefile b/Makefile index 023c01aadaa2a..3d8bf5436b476 100644 --- a/Makefile +++ b/Makefile @@ -403,6 +403,10 @@ endif # Install appdata file mkdir -p $(DESTDIR)$(datarootdir)/metainfo/ $(INSTALL_F) $(JULIAHOME)/contrib/julia.appdata.xml $(DESTDIR)$(datarootdir)/metainfo/ + # Install terminal info database +ifneq ($(WITH_TERMINFO),0) + cp -R -L $(build_datarootdir)/terminfo $(DESTDIR)$(datarootdir) +endif # Update RPATH entries and JL_SYSTEM_IMAGE_PATH if $(private_libdir_rel) != $(build_private_libdir_rel) ifneq ($(private_libdir_rel),$(build_private_libdir_rel)) diff --git a/NEWS.md b/NEWS.md index c4e46acca164e..4bbe7645165dd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -171,6 +171,10 @@ Deprecated or removed External dependencies --------------------- +- The terminal info database, `terminfo`, is now vendored by default, providing a better + REPL user experience when `terminfo` is not available on the system. Julia can be built + without vendoring the database using the Makefile option `WITH_TERMINFO=0`. ([#55411]) + Tooling Improvements -------------------- diff --git a/base/terminfo.jl b/base/terminfo.jl index 6f1d1ca8015f0..79713f4a86aa3 100644 --- a/base/terminfo.jl +++ b/base/terminfo.jl @@ -245,7 +245,8 @@ end Locate the terminfo file for `term`, return `nothing` if none could be found. The lookup policy is described in `terminfo(5)` "Fetching Compiled -Descriptions". +Descriptions". A terminfo database is included by default with Julia and is +taken to be the first entry of `@TERMINFO_DIRS@`. """ function find_terminfo_file(term::String) isempty(term) && return @@ -261,6 +262,7 @@ function find_terminfo_file(term::String) append!(terminfo_dirs, replace(split(ENV["TERMINFO_DIRS"], ':'), "" => "/usr/share/terminfo")) + push!(terminfo_dirs, normpath(Sys.BINDIR, DATAROOTDIR, "terminfo")) Sys.isunix() && push!(terminfo_dirs, "/etc/terminfo", "/lib/terminfo", "/usr/share/terminfo") for dir in terminfo_dirs @@ -268,8 +270,15 @@ function find_terminfo_file(term::String) return joinpath(dir, chr, term) elseif isfile(joinpath(dir, chrcode, term)) return joinpath(dir, chrcode, term) + elseif isfile(joinpath(dir, lowercase(chr), lowercase(term))) + # The vendored terminfo database is fully lowercase to avoid issues on + # case-sensitive filesystems. On Unix-like systems, terminfo files with + # different cases are hard links to one another, so this is still + # correct for non-vendored terminfo, just redundant. + return joinpath(dir, lowercase(chr), lowercase(term)) end end + return nothing end """ diff --git a/deps/Makefile b/deps/Makefile index 2f9050f448d67..b87a3e1e58609 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -175,6 +175,10 @@ ifeq ($(WITH_NVTX),1) DEP_LIBS += nvtx endif +ifneq ($(WITH_TERMINFO),0) +DEP_LIBS += terminfo +endif + # Only compile standalone LAPACK if we are not using OpenBLAS. # OpenBLAS otherwise compiles LAPACK as part of its build. # This is useful where one wants to use the vendor BLAS, but @@ -197,7 +201,8 @@ DEP_LIBS_STAGED := $(DEP_LIBS) DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ - sanitizers libsuitesparse lld libtracyclient ittapi nvtx JuliaSyntax + sanitizers libsuitesparse lld libtracyclient ittapi nvtx JuliaSyntax \ + terminfo DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) @@ -259,6 +264,7 @@ include $(SRCDIR)/libgit2.mk include $(SRCDIR)/libwhich.mk include $(SRCDIR)/p7zip.mk include $(SRCDIR)/libtracyclient.mk +include $(SRCDIR)/terminfo.mk # vendored Julia libs include $(SRCDIR)/JuliaSyntax.mk diff --git a/deps/checksums/terminfo b/deps/checksums/terminfo new file mode 100644 index 0000000000000..bd971e72b1be8 --- /dev/null +++ b/deps/checksums/terminfo @@ -0,0 +1,2 @@ +TermInfoDB-v2023.12.9.any.tar.gz/md5/573d9b5adaf6af500e3dfae6e3d15ebf +TermInfoDB-v2023.12.9.any.tar.gz/sha512/e0a5bfe54346f9d5690a840628b329f6fac7375b0d29337bc70813ae3553a72bb397f8034d221c544289e40c4cfc685d5805777b7528f05bbe0123b5905c24a4 diff --git a/deps/terminfo.mk b/deps/terminfo.mk new file mode 100644 index 0000000000000..63194f786f566 --- /dev/null +++ b/deps/terminfo.mk @@ -0,0 +1,43 @@ +## TERMINFO-DB ## +include $(SRCDIR)/terminfo.version + +$(SRCCACHE)/TermInfoDB-v$(TERMINFO_VER).any.tar.gz: | $(SRCCACHE) + $(JLDOWNLOAD) $@ https://github.com/JuliaBinaryWrappers/TermInfoDB_jll.jl/releases/download/$(TERMINFO_TAG)/TermInfoDB.v$(TERMINFO_VER).any.tar.gz + touch -c $@ + +$(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/source-extracted: $(SRCCACHE)/TermInfoDB-v$(TERMINFO_VER).any.tar.gz + $(JLCHECKSUM) $< + rm -rf $(dir $@) + mkdir -p $(dir $@) + $(TAR) -C $(dir $@) --strip-components 1 -xf $< + echo 1 > $@ + +checksum-terminfo: $(SRCCACHE)/TermInfoDB-v$(TERMINFO_VER).any.tar.gz + $(JLCHECKSUM) $< + +$(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-compiled: $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/source-extracted + echo 1 > $@ + +$(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-checked: $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-compiled + echo 1 > $@ + +define TERMINFO_INSTALL + mkdir -p $2/$$(build_datarootdir) + cp -R $1/terminfo $2/$$(build_datarootdir) +endef +$(eval $(call staged-install, \ + terminfo,TermInfoDB-v$(TERMINFO_VER), \ + TERMINFO_INSTALL,,,,)) + +clean-terminfo: + -rm -f $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-compiled + +distclean-terminfo: + rm -rf $(SRCCACHE)/TermInfoDB*.tar.gz $(SRCCACHE)/TermInfoDB-v$(TERMINFO_VER) $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER) + +get-terminfo: $(SRCCACHE)/TermInfoDB-v$(TERMINFO_VER).any.tar.gz +extract-terminfo: $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/source-extracted +configure-terminfo: extract-terminfo +compile-terminfo: $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-compiled +fastcheck-terminfo: check-terminfo +check-terminfo: $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-checked diff --git a/deps/terminfo.version b/deps/terminfo.version new file mode 100644 index 0000000000000..b7c020b830517 --- /dev/null +++ b/deps/terminfo.version @@ -0,0 +1,3 @@ +# -*- makefile -*- +TERMINFO_VER := 2023.12.9 +TERMINFO_TAG := TermInfoDB-v$(TERMINFO_VER)+0 diff --git a/stdlib/REPL/test/precompilation.jl b/stdlib/REPL/test/precompilation.jl index 228cbd212a2c1..7efcf0b5e8282 100644 --- a/stdlib/REPL/test/precompilation.jl +++ b/stdlib/REPL/test/precompilation.jl @@ -15,8 +15,11 @@ if !Sys.iswindows() @testset "No interactive startup compilation" begin f, _ = mktemp() - # start an interactive session - cmd = `$(Base.julia_cmd()[1]) --trace-compile=$f -q --startup-file=no -i` + # start an interactive session, ensuring `TERM` is unset since it can trigger + # different amounts of precompilation stemming from `base/terminfo.jl` depending + # on the value, making the test here unreliable + cmd = addenv(`$(Base.julia_cmd()[1]) --trace-compile=$f -q --startup-file=no -i`, + Dict("TERM" => "")) pts, ptm = open_fake_pty() p = run(cmd, pts, pts, pts; wait=false) Base.close_stdio(pts) From ac9558c265b53cb3b3569e37be898df9d91d5ce8 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 9 Aug 2024 07:07:31 -0400 Subject: [PATCH 171/206] codegen: move undef freeze before promotion point (#55428) Fixes #55396 --- src/cgutils.cpp | 10 ++++++++-- test/compiler/codegen.jl | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 3695dc1370050..0969f78f10bb4 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -3947,8 +3947,6 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg else { strct = emit_static_alloca(ctx, lt); setName(ctx.emission_context, strct, arg_typename); - if (nargs < nf) - promotion_point = ctx.builder.CreateStore(ctx.builder.CreateFreeze(UndefValue::get(lt)), strct); if (tracked.count) undef_derived_strct(ctx, strct, sty, ctx.tbaa().tbaa_stack); } @@ -4104,6 +4102,14 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg } } } + if (promotion_point && nargs < nf) { + assert(!init_as_value); + IRBuilderBase::InsertPoint savedIP = ctx.builder.saveIP(); + ctx.builder.SetInsertPoint(promotion_point); + promotion_point = cast(ctx.builder.CreateFreeze(UndefValue::get(lt))); + ctx.builder.CreateStore(promotion_point, strct); + ctx.builder.restoreIP(savedIP); + } if (type_is_ghost(lt)) return mark_julia_const(ctx, sty->instance); else if (init_as_value) diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index cd2702ff0e6aa..c74dfbb29d3dd 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -956,3 +956,13 @@ function foonopreds() pkgid.uuid !== nothing ? pkgid.uuid : false end @test foonopreds() !== nothing + +# issue 55396 +struct Incomplete55396 + x::Tuple{Int} + y::Int + @noinline Incomplete55396(x::Int) = new((x,)) +end +let x = Incomplete55396(55396) + @test x.x === (55396,) +end From 2727e36a13431c1e7e7e464b2f0b8af0db149198 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Fri, 9 Aug 2024 10:59:51 -0300 Subject: [PATCH 172/206] Remove deprecated non string API for LLVM pass pipeline and parse all options (#55407) This technically removes the option for Oz in julia but it doesn't actually do what one wants. This removes an API currently used by Enzyme.jl and AllocCheck.jl but given that LLVM.jl doesn't support this API anymore that seems fine. @wsmoses @maleadt Do we want the replacement for this (a function that parses the PipelineConfig struct) to live in LLVM.jl or GPUCompiler.jl ? --- src/codegen-stubs.c | 2 -- src/jl_exported_funcs.inc | 1 - src/pipeline.cpp | 67 +++++--------------------------------- test/llvmpasses/parsing.ll | 3 ++ 4 files changed, 11 insertions(+), 62 deletions(-) diff --git a/src/codegen-stubs.c b/src/codegen-stubs.c index 3e97c149bffe3..41812d903816c 100644 --- a/src/codegen-stubs.c +++ b/src/codegen-stubs.c @@ -107,8 +107,6 @@ JL_DLLEXPORT uint64_t jl_getUnwindInfo_fallback(uint64_t dwAddr) return 0; } -JL_DLLEXPORT void jl_build_newpm_pipeline_fallback(void *MPM, void *PB, void *config) UNAVAILABLE - JL_DLLEXPORT void jl_register_passbuilder_callbacks_fallback(void *PB) { } #define MODULE_PASS(NAME, CLASS, CREATE_PASS) \ diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 246b666f942c1..1976dbe709733 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -542,7 +542,6 @@ YY(jl_type_to_llvm) \ YY(jl_getUnwindInfo) \ YY(jl_get_libllvm) \ - YY(jl_build_newpm_pipeline) \ YY(jl_register_passbuilder_callbacks) \ YY(LLVMExtraMPMAddCPUFeaturesPass) \ YY(LLVMExtraMPMAddRemoveNIPass) \ diff --git a/src/pipeline.cpp b/src/pipeline.cpp index e01645cc1f154..236be179e12c9 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -609,65 +609,6 @@ static void buildPipeline(ModulePassManager &MPM, PassBuilder *PB, OptimizationL MPM.addPass(AfterOptimizationMarkerPass()); } -struct PipelineConfig { - int Speedup; - int Size; - int lower_intrinsics; - int dump_native; - int external_use; - int llvm_only; - int always_inline; - int enable_early_simplifications; - int enable_early_optimizations; - int enable_scalar_optimizations; - int enable_loop_optimizations; - int enable_vector_pipeline; - int remove_ni; - int cleanup; - int warn_missed_transformations; -}; - -extern "C" JL_DLLEXPORT_CODEGEN void jl_build_newpm_pipeline_impl(void *MPM, void *PB, PipelineConfig* config) JL_NOTSAFEPOINT -{ - OptimizationLevel O; - switch (config->Size) { - case 1: - O = OptimizationLevel::Os; - break; - default: - O = OptimizationLevel::Oz; - break; - case 0: - switch (config->Speedup) { - case 0: - O = OptimizationLevel::O0; - break; - case 1: - O = OptimizationLevel::O1; - break; - case 2: - O = OptimizationLevel::O2; - break; - default: - O = OptimizationLevel::O3; - break; - } - } - buildPipeline(*reinterpret_cast(MPM), reinterpret_cast(PB), O, - OptimizationOptions{!!config->lower_intrinsics, - !!config->dump_native, - !!config->external_use, - !!config->llvm_only, - !!config->always_inline, - !!config->enable_early_simplifications, - !!config->enable_early_optimizations, - !!config->enable_scalar_optimizations, - !!config->enable_loop_optimizations, - !!config->enable_vector_pipeline, - !!config->remove_ni, - !!config->cleanup, - !!config->warn_missed_transformations}); -} #undef JULIA_PASS @@ -865,6 +806,14 @@ static Optional> parseJuliaPip OPTION(dump_native), OPTION(external_use), OPTION(llvm_only), + OPTION(always_inline), + OPTION(enable_early_simplifications), + OPTION(enable_early_optimizations), + OPTION(enable_scalar_optimizations), + OPTION(enable_loop_optimizations), + OPTION(enable_vector_pipeline), + OPTION(remove_ni), + OPTION(cleanup), OPTION(warn_missed_transformations) #undef OPTION }; diff --git a/test/llvmpasses/parsing.ll b/test/llvmpasses/parsing.ll index e75ba292f254a..e0a726176b225 100644 --- a/test/llvmpasses/parsing.ll +++ b/test/llvmpasses/parsing.ll @@ -1,6 +1,9 @@ ; COM: NewPM-only test, tests for ability to parse Julia passes ; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes='module(CPUFeatures,RemoveNI,JuliaMultiVersioning,RemoveJuliaAddrspaces,LowerPTLSPass,function(DemoteFloat16,CombineMulAdd,LateLowerGCFrame,FinalLowerGC,AllocOpt,PropagateJuliaAddrspaces,LowerExcHandlers,GCInvariantVerifier,loop(LowerSIMDLoop,JuliaLICM),GCInvariantVerifier,GCInvariantVerifier),LowerPTLSPass,LowerPTLSPass,JuliaMultiVersioning,JuliaMultiVersioning)' -S %s -o /dev/null +; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes="julia" -S %s -o /dev/null +; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes="julia" -S %s -o /dev/null +; RUN: opt --load-pass-plugin=libjulia-codegen%shlibext -passes="julia" -S %s -o /dev/null define void @test() { ret void From c3d0d67ac424c889fd7f24552a557c3a7ea8f1e6 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Sat, 10 Aug 2024 00:33:43 +0900 Subject: [PATCH 173/206] inference: follow up #49260, remove no longer necessary functions (#55430) --- base/compiler/inferencestate.jl | 66 --------------------------------- 1 file changed, 66 deletions(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 06b038ecb6d2e..87647628f772e 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -517,72 +517,6 @@ function compute_trycatch(code::Vector{Any}, bbs::Union{Vector{BasicBlock},Nothi return handler_info end -function is_throw_call(e::Expr, code::Vector{Any}) - if e.head === :call - f = e.args[1] - if isa(f, SSAValue) - f = code[f.id] - end - if isa(f, GlobalRef) - ff = abstract_eval_globalref_type(f) - if isa(ff, Const) && ff.val === Core.throw - return true - end - end - end - return false -end - -function mark_throw_blocks!(src::CodeInfo, handler_info::Union{Nothing,HandlerInfo}) - for stmt in find_throw_blocks(src.code, handler_info) - src.ssaflags[stmt] |= IR_FLAG_THROW_BLOCK - end - return nothing -end - -# this utility function is incomplete and won't catch every block that always throws, since: -# - it only recognizes direct calls to `throw` within the target code, so it can't mark -# blocks that deterministically call `throw` internally, like those containing `error`. -# - it just does a reverse linear traverse of statements, there's a chance it might miss -# blocks, particularly when there are reverse control edges. -function find_throw_blocks(code::Vector{Any}, handler_info::Union{Nothing,HandlerInfo}) - stmts = BitSet() - n = length(code) - for i in n:-1:1 - s = code[i] - if isa(s, Expr) - if s.head === :gotoifnot - if i+1 in stmts && s.args[2]::Int in stmts - push!(stmts, i) - end - elseif s.head === :return - # see `ReturnNode` handling - elseif is_throw_call(s, code) - if handler_info === nothing || handler_info.handler_at[i][1] == 0 - push!(stmts, i) - end - elseif i+1 in stmts - push!(stmts, i) - end - elseif isa(s, ReturnNode) - # NOTE: it potentially makes sense to treat unreachable nodes - # (where !isdefined(s, :val)) as `throw` points, but that can cause - # worse codegen around the call site (issue #37558) - elseif isa(s, GotoNode) - if s.label in stmts - push!(stmts, i) - end - elseif isa(s, GotoIfNot) - if i+1 in stmts && s.dest in stmts - push!(stmts, i) - end - elseif i+1 in stmts - push!(stmts, i) - end - end - return stmts -end - # check if coverage mode is enabled function should_insert_coverage(mod::Module, debuginfo::DebugInfo) coverage_enabled(mod) && return true From 18340a3eb40758f5c21428c9c03b3f2b696f475d Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 9 Aug 2024 19:47:20 +0200 Subject: [PATCH 174/206] `stale_cachefile`: handle if the expected cache file is missing (#55419) Part of fixing https://github.com/JuliaLang/Pkg.jl/issues/3984 --- base/loading.jl | 8 +++++++- test/precompile.jl | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index eb467d9cc0bd4..4dc735f0099d8 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -3666,7 +3666,13 @@ end ignore_loaded::Bool=false, requested_flags::CacheFlags=CacheFlags(), reasons::Union{Dict{String,Int},Nothing}=nothing, stalecheck::Bool=true) # n.b.: this function does nearly all of the file validation, not just those checks related to stale, so the name is potentially unclear - io = open(cachefile, "r") + io = try + open(cachefile, "r") + catch ex + ex isa IOError || ex isa SystemError || rethrow() + @debug "Rejecting cache file $cachefile for $modkey because it could not be opened" isfile(cachefile) + return true + end try checksum = isvalid_cache_header(io) if iszero(checksum) diff --git a/test/precompile.jl b/test/precompile.jl index 3241ee8b25a35..f45eb4bb1e79e 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -597,6 +597,10 @@ precompile_test_harness(false) do dir @test Base.invokelatest(Baz.baz) === 1 @test Baz === UseBaz.Baz + # should not throw if the cachefile does not exist + @test !isfile("DoesNotExist.ji") + @test Base.stale_cachefile("", "DoesNotExist.ji") === true + # Issue #12720 FooBar1_file = joinpath(dir, "FooBar1.jl") write(FooBar1_file, From 7ec39e71361c835c9ff4e659d0a23f4892f8249f Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 9 Aug 2024 19:50:58 +0200 Subject: [PATCH 175/206] fix swallowing internal errors in precompilepkgs (#55432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing: - with a package error ``` (SimpleLooper) pkg> precompile Precompiling all packages... ✗ SimpleLooper 0 dependencies successfully precompiled in 2 seconds ERROR: The following 1 direct dependency failed to precompile: SimpleLooper Failed to precompile SimpleLooper [ff33fe5b-d8e3-4cbd-8bd9-3d2408ff8cab] to "/Users/ian/.julia/compiled/v1.12/SimpleLooper/jl_PQArnH". ERROR: LoadError: Stacktrace: [1] error() @ Base ./error.jl:53 ``` - with interrupt ``` (SimpleLooper) pkg> precompile Precompiling all packages... ^C Interrupted: Exiting precompilation... ◒ SimpleLooper 1 dependency had output during precompilation: ┌ SimpleLooper │ [57879] signal 2: Interrupt: 2 │ in expression starting at /Users/ian/Documents/GitHub/SimpleLooper.jl/src/SimpleLooper.jl:2 └ ``` - an internal error simulated in the same scope that https://github.com/JuliaLang/Pkg.jl/issues/3984 was failing to throw from ``` JULIA stdlib/release.image Unhandled Task ERROR: Stacktrace: [1] error() @ Base ./error.jl:53 [2] (::Base.Precompilation.var"#27#65"{Bool, Bool, Vector{Task}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, String}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, String}, Base.Event, Base.Event, ReentrantLock, Vector{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, String}, Vector{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}}, Int64, Vector{Base.PkgId}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, Bool}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, Base.Event}, Dict{Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}, Bool}, Vector{Base.PkgId}, Dict{Base.PkgId, String}, Dict{Tuple{Base.PkgId, UInt128, String, String}, Bool}, Base.Precompilation.var"#color_string#38"{Bool}, Bool, Base.Semaphore, Bool, String, Vector{String}, Vector{Base.PkgId}, Base.PkgId, Base.CacheFlags, Cmd, Pair{Cmd, Base.CacheFlags}, Tuple{Base.PkgId, Pair{Cmd, Base.CacheFlags}}})() @ Base.Precompilation ./precompilation.jl:819 ``` --- base/precompilation.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/precompilation.jl b/base/precompilation.jl index dfaf671a63534..feee394588b19 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -897,6 +897,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; length(tasks) == 1 && notify(interrupted_or_done) end end + Base.errormonitor(task) # interrupts are handled separately so ok to watch for other errors like this push!(tasks, task) end end From 86231ce5763a41a6661d7834a28ad1c37526044a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 9 Aug 2024 19:20:42 +0000 Subject: [PATCH 176/206] LinearAlgebra: round-trippable 2-argument show for `Tridiagonal`/`SymTridiagonal` (#55415) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the displayed form of a `Tridiaognal` and a `SymTridiagonal` valid constructors. ```julia julia> T = Tridiagonal(1:3, 1:4, 1:3) 4×4 Tridiagonal{Int64, UnitRange{Int64}}: 1 1 ⋅ ⋅ 1 2 2 ⋅ ⋅ 2 3 3 ⋅ ⋅ 3 4 julia> show(T) Tridiagonal(1:3, 1:4, 1:3) julia> S = SymTridiagonal(1:4, 1:3) 4×4 SymTridiagonal{Int64, UnitRange{Int64}}: 1 1 ⋅ ⋅ 1 2 2 ⋅ ⋅ 2 3 3 ⋅ ⋅ 3 4 julia> show(S) SymTridiagonal(1:4, 1:3) ``` Displaying the bands has several advantages: firstly, it's briefer than printing the full array, and secondly, it displays the special structure in the bands, if any. E.g.: ```julia julia> T = Tridiagonal(spzeros(3), spzeros(4), spzeros(3)); julia> show(T) Tridiagonal(sparsevec(Int64[], Float64[], 3), sparsevec(Int64[], Float64[], 4), sparsevec(Int64[], Float64[], 3)) ``` It's clear from the displayed form that `T` has sparse bands. A special handling for `SymTridiagonal` matrices is necessary, as the diagonal band is symmetrized. This means: ```julia julia> using StaticArrays julia> m = SMatrix{2,2}(1:4); julia> S = SymTridiagonal(fill(m,3), fill(m,2)) 3×3 SymTridiagonal{SMatrix{2, 2, Int64, 4}, Vector{SMatrix{2, 2, Int64, 4}}}: [1 3; 3 4] [1 3; 2 4] ⋅ [1 2; 3 4] [1 3; 3 4] [1 3; 2 4] ⋅ [1 2; 3 4] [1 3; 3 4] julia> show(S) SymTridiagonal(SMatrix{2, 2, Int64, 4}[[1 3; 3 4], [1 3; 3 4], [1 3; 3 4]], SMatrix{2, 2, Int64, 4}[[1 3; 2 4], [1 3; 2 4]]) ``` The displayed values correspond to the symmetrized band, and not the actual input arguments. I think displaying the symmetrized elements makes more sense here, as this matches the form in the 3-argument `show`. --- stdlib/LinearAlgebra/src/tridiag.jl | 18 ++++++++++++++++++ stdlib/LinearAlgebra/test/tridiag.jl | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index c14ed5690198c..0ba03634d82ad 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -1045,3 +1045,21 @@ function _copyto_banded!(A::SymTridiagonal, B::Tridiagonal) _evview(A) .= B.du return A end + +# display +function show(io::IO, T::Tridiagonal) + print(io, "Tridiagonal(") + show(io, T.dl) + print(io, ", ") + show(io, T.d) + print(io, ", ") + show(io, T.du) + print(io, ")") +end +function show(io::IO, S::SymTridiagonal) + print(io, "SymTridiagonal(") + show(io, eltype(S) <: Number ? S.dv : view(S, diagind(S, IndexStyle(S)))) + print(io, ", ") + show(io, S.ev) + print(io, ")") +end diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index 41a28631b27a0..e0a8e32d77852 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -18,6 +18,9 @@ using .Main.FillArrays isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl")) using .Main.OffsetArrays +isdefined(Main, :SizedArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "SizedArrays.jl")) +using .Main.SizedArrays + include("testutils.jl") # test_approx_eq_modphase #Test equivalence of eigenvectors/singular vectors taking into account possible phase (sign) differences @@ -914,4 +917,17 @@ end end end +@testset "show" begin + T = Tridiagonal(1:3, 1:4, 1:3) + @test sprint(show, T) == "Tridiagonal(1:3, 1:4, 1:3)" + S = SymTridiagonal(1:4, 1:3) + @test sprint(show, S) == "SymTridiagonal(1:4, 1:3)" + + m = SizedArrays.SizedArray{(2,2)}(reshape([1:4;],2,2)) + T = Tridiagonal(fill(m,2), fill(m,3), fill(m,2)) + @test sprint(show, T) == "Tridiagonal($(repr(diag(T,-1))), $(repr(diag(T))), $(repr(diag(T,1))))" + S = SymTridiagonal(fill(m,3), fill(m,2)) + @test sprint(show, S) == "SymTridiagonal($(repr(diag(S))), $(repr(diag(S,1))))" +end + end # module TestTridiagonal From 7e809b0953cd80ce0fa3078dea20e848bc0d7271 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 10 Aug 2024 00:31:37 -0400 Subject: [PATCH 177/206] compiler: apply more accurate effects to return_type_tfunc (#55338) In extreme cases, the compiler could mark this function for concrete-eval, even though that is illegal unless the compiler has first deleted this instruction. Otherwise the attempt to concrete-eval will re-run the function repeatedly until it hits a StackOverflow. Workaround to fix #55147 @aviatesk You might know how to solve this even better, using post-optimization effect refinements? Since we should actually only apply the refinement of terminates=false => terminates=true (and thus allowing concrete eval) if the optimization occurs, and not just in inference thinks the optimization would be legal. --------- Co-authored-by: Shuhei Kadowaki --- base/boot.jl | 3 +- base/cmd.jl | 2 +- base/compiler/abstractinterpretation.jl | 7 ++-- base/compiler/compiler.jl | 11 +++-- base/compiler/effects.jl | 55 ++++++++++++++++++------- base/compiler/optimize.jl | 30 ++++++++++---- base/compiler/ssair/show.jl | 2 + base/compiler/tfuncs.jl | 20 +++++---- base/compiler/typeinfer.jl | 3 ++ base/essentials.jl | 33 ++++++++++----- base/expr.jl | 25 +++++++++-- src/julia.h | 5 ++- src/method.c | 2 + 13 files changed, 141 insertions(+), 57 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index f7aee9677e2f2..608e273d4b514 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -284,7 +284,8 @@ macro _foldable_meta() #=:inaccessiblememonly=#true, #=:noub=#true, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#true)) end macro inline() Expr(:meta, :inline) end diff --git a/base/cmd.jl b/base/cmd.jl index 202527abdf644..84ec52f865e98 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -482,7 +482,7 @@ function cmd_gen(parsed) end end -@assume_effects :effect_free :terminates_globally :noub function cmd_gen( +@assume_effects :foldable !:consistent function cmd_gen( parsed::Tuple{Vararg{Tuple{Vararg{Union{String, SubString{String}}}}}} ) return @invoke cmd_gen(parsed::Any) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 789b7e6f5a962..90d395600bbde 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -980,7 +980,7 @@ function concrete_eval_eligible(interp::AbstractInterpreter, end end mi = result.edge - if mi !== nothing && is_foldable(effects) + if mi !== nothing && is_foldable(effects, #=check_rtcall=#true) if f !== nothing && is_all_const_arg(arginfo, #=start=#2) if (is_nonoverlayed(interp) || is_nonoverlayed(effects) || # Even if overlay methods are involved, when `:consistent_overlay` is @@ -2910,8 +2910,9 @@ function override_effects(effects::Effects, override::EffectsOverride) notaskstate = override.notaskstate ? true : effects.notaskstate, inaccessiblememonly = override.inaccessiblememonly ? ALWAYS_TRUE : effects.inaccessiblememonly, noub = override.noub ? ALWAYS_TRUE : - (override.noub_if_noinbounds && effects.noub !== ALWAYS_TRUE) ? NOUB_IF_NOINBOUNDS : - effects.noub) + (override.noub_if_noinbounds && effects.noub !== ALWAYS_TRUE) ? NOUB_IF_NOINBOUNDS : + effects.noub, + nortcall = override.nortcall ? true : effects.nortcall) end isdefined_globalref(g::GlobalRef) = !iszero(ccall(:jl_globalref_boundp, Cint, (Any,), g)) diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 629641308a217..5cc01391267d7 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -49,10 +49,11 @@ struct EffectsOverride noub::Bool noub_if_noinbounds::Bool consistent_overlay::Bool + nortcall::Bool end function EffectsOverride( override::EffectsOverride = - EffectsOverride(false, false, false, false, false, false, false, false, false, false); + EffectsOverride(false, false, false, false, false, false, false, false, false, false, false); consistent::Bool = override.consistent, effect_free::Bool = override.effect_free, nothrow::Bool = override.nothrow, @@ -62,7 +63,8 @@ function EffectsOverride( inaccessiblememonly::Bool = override.inaccessiblememonly, noub::Bool = override.noub, noub_if_noinbounds::Bool = override.noub_if_noinbounds, - consistent_overlay::Bool = override.consistent_overlay) + consistent_overlay::Bool = override.consistent_overlay, + nortcall::Bool = override.nortcall) return EffectsOverride( consistent, effect_free, @@ -73,9 +75,10 @@ function EffectsOverride( inaccessiblememonly, noub, noub_if_noinbounds, - consistent_overlay) + consistent_overlay, + nortcall) end -const NUM_EFFECTS_OVERRIDES = 10 # sync with julia.h +const NUM_EFFECTS_OVERRIDES = 11 # sync with julia.h # essential files and libraries include("essentials.jl") diff --git a/base/compiler/effects.jl b/base/compiler/effects.jl index 0375b8dba922c..166df78f3130c 100644 --- a/base/compiler/effects.jl +++ b/base/compiler/effects.jl @@ -58,6 +58,9 @@ following meanings: methods are `:consistent` with their non-overlayed original counterparts (see [`Base.@assume_effects`](@ref) for the exact definition of `:consistenct`-cy). * `ALWAYS_FALSE`: this method may invoke overlayed methods. +- `nortcall::Bool`: this method does not call `Core.Compiler.return_type`, + and it is guaranteed that any other methods this method might call also do not call + `Core.Compiler.return_type`. Note that the representations above are just internal implementation details and thus likely to change in the future. See [`Base.@assume_effects`](@ref) for more detailed explanation @@ -103,6 +106,9 @@ The output represents the state of different effect properties in the following - `+o` (green): `ALWAYS_TRUE` - `-o` (red): `ALWAYS_FALSE` - `?o` (yellow): `CONSISTENT_OVERLAY` +9. `:nortcall` (`r`): + - `+r` (green): `true` + - `-r` (red): `false` """ struct Effects consistent::UInt8 @@ -113,6 +119,7 @@ struct Effects inaccessiblememonly::UInt8 noub::UInt8 nonoverlayed::UInt8 + nortcall::Bool function Effects( consistent::UInt8, effect_free::UInt8, @@ -121,7 +128,8 @@ struct Effects notaskstate::Bool, inaccessiblememonly::UInt8, noub::UInt8, - nonoverlayed::UInt8) + nonoverlayed::UInt8, + nortcall::Bool) return new( consistent, effect_free, @@ -130,7 +138,8 @@ struct Effects notaskstate, inaccessiblememonly, noub, - nonoverlayed) + nonoverlayed, + nortcall) end end @@ -160,10 +169,10 @@ const NOUB_IF_NOINBOUNDS = 0x01 << 1 # :nonoverlayed bits const CONSISTENT_OVERLAY = 0x01 << 1 -const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, true, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE) -const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, false, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE) -const EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_TRUE) # unknown mostly, but it's not overlayed at least (e.g. it's not a call) -const _EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_FALSE) # unknown really +const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, true, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true) +const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, false, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true) +const EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_TRUE, false) # unknown mostly, but it's not overlayed at least (e.g. it's not a call) +const _EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_FALSE, false) # unknown really function Effects(effects::Effects = _EFFECTS_UNKNOWN; consistent::UInt8 = effects.consistent, @@ -173,7 +182,8 @@ function Effects(effects::Effects = _EFFECTS_UNKNOWN; notaskstate::Bool = effects.notaskstate, inaccessiblememonly::UInt8 = effects.inaccessiblememonly, noub::UInt8 = effects.noub, - nonoverlayed::UInt8 = effects.nonoverlayed) + nonoverlayed::UInt8 = effects.nonoverlayed, + nortcall::Bool = effects.nortcall) return Effects( consistent, effect_free, @@ -182,7 +192,8 @@ function Effects(effects::Effects = _EFFECTS_UNKNOWN; notaskstate, inaccessiblememonly, noub, - nonoverlayed) + nonoverlayed, + nortcall) end function is_better_effects(new::Effects, old::Effects) @@ -247,6 +258,11 @@ function is_better_effects(new::Effects, old::Effects) elseif new.nonoverlayed != old.nonoverlayed return false end + if new.nortcall + any_improved |= !old.nortcall + elseif new.nortcall != old.nortcall + return false + end return any_improved end @@ -259,7 +275,8 @@ function merge_effects(old::Effects, new::Effects) merge_effectbits(old.notaskstate, new.notaskstate), merge_effectbits(old.inaccessiblememonly, new.inaccessiblememonly), merge_effectbits(old.noub, new.noub), - merge_effectbits(old.nonoverlayed, new.nonoverlayed)) + merge_effectbits(old.nonoverlayed, new.nonoverlayed), + merge_effectbits(old.nortcall, new.nortcall)) end function merge_effectbits(old::UInt8, new::UInt8) @@ -279,16 +296,18 @@ is_inaccessiblememonly(effects::Effects) = effects.inaccessiblememonly === ALWAY is_noub(effects::Effects) = effects.noub === ALWAYS_TRUE is_noub_if_noinbounds(effects::Effects) = effects.noub === NOUB_IF_NOINBOUNDS is_nonoverlayed(effects::Effects) = effects.nonoverlayed === ALWAYS_TRUE +is_nortcall(effects::Effects) = effects.nortcall # implies `is_notaskstate` & `is_inaccessiblememonly`, but not explicitly checked here -is_foldable(effects::Effects) = +is_foldable(effects::Effects, check_rtcall::Bool=false) = is_consistent(effects) && (is_noub(effects) || is_noub_if_noinbounds(effects)) && is_effect_free(effects) && - is_terminates(effects) + is_terminates(effects) && + (!check_rtcall || is_nortcall(effects)) -is_foldable_nothrow(effects::Effects) = - is_foldable(effects) && +is_foldable_nothrow(effects::Effects, check_rtcall::Bool=false) = + is_foldable(effects, check_rtcall) && is_nothrow(effects) # TODO add `is_noub` here? @@ -318,7 +337,8 @@ function encode_effects(e::Effects) ((e.notaskstate % UInt32) << 7) | ((e.inaccessiblememonly % UInt32) << 8) | ((e.noub % UInt32) << 10) | - ((e.nonoverlayed % UInt32) << 12) + ((e.nonoverlayed % UInt32) << 12) | + ((e.nortcall % UInt32) << 14) end function decode_effects(e::UInt32) @@ -330,7 +350,8 @@ function decode_effects(e::UInt32) _Bool((e >> 7) & 0x01), UInt8((e >> 8) & 0x03), UInt8((e >> 10) & 0x03), - UInt8((e >> 12) & 0x03)) + UInt8((e >> 12) & 0x03), + _Bool((e >> 14) & 0x01)) end function encode_effects_override(eo::EffectsOverride) @@ -345,6 +366,7 @@ function encode_effects_override(eo::EffectsOverride) eo.noub && (e |= (0x0001 << 7)) eo.noub_if_noinbounds && (e |= (0x0001 << 8)) eo.consistent_overlay && (e |= (0x0001 << 9)) + eo.nortcall && (e |= (0x0001 << 10)) return e end @@ -359,7 +381,8 @@ function decode_effects_override(e::UInt16) !iszero(e & (0x0001 << 6)), !iszero(e & (0x0001 << 7)), !iszero(e & (0x0001 << 8)), - !iszero(e & (0x0001 << 9))) + !iszero(e & (0x0001 << 9)), + !iszero(e & (0x0001 << 10))) end decode_statement_effects_override(ssaflag::UInt32) = diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 9c89e8596d237..936b604d373a0 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -42,13 +42,16 @@ const IR_FLAG_NOUB = one(UInt32) << 8 const IR_FLAG_EFIIMO = one(UInt32) << 9 # This statement is :inaccessiblememonly == INACCESSIBLEMEM_OR_ARGMEMONLY const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 10 +# This statement is :nortcall +const IR_FLAG_NORTCALL = one(UInt32) << 11 # This statement has no users and may be deleted if flags get refined to IR_FLAGS_REMOVABLE -const IR_FLAG_UNUSED = one(UInt32) << 11 +const IR_FLAG_UNUSED = one(UInt32) << 12 -const NUM_IR_FLAGS = 12 # sync with julia.h +const NUM_IR_FLAGS = 13 # sync with julia.h const IR_FLAGS_EFFECTS = - IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_TERMINATES | IR_FLAG_NOUB + IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | + IR_FLAG_TERMINATES | IR_FLAG_NOUB | IR_FLAG_NORTCALL const IR_FLAGS_REMOVABLE = IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_TERMINATES @@ -78,6 +81,9 @@ function flags_for_effects(effects::Effects) if is_noub(effects) flags |= IR_FLAG_NOUB end + if is_nortcall(effects) + flags |= IR_FLAG_NORTCALL + end return flags end @@ -583,26 +589,28 @@ mutable struct PostOptAnalysisState all_nothrow::Bool all_noub::Bool any_conditional_ub::Bool + nortcall::Bool function PostOptAnalysisState(result::InferenceResult, ir::IRCode) inconsistent = BitSetBoundedMinPrioritySet(length(ir.stmts)) tpdum = TwoPhaseDefUseMap(length(ir.stmts)) lazypostdomtree = LazyPostDomtree(ir) lazyagdomtree = LazyAugmentedDomtree(ir) return new(result, ir, inconsistent, tpdum, lazypostdomtree, lazyagdomtree, Int[], - true, true, nothing, true, true, false) + true, true, nothing, true, true, false, true) end end give_up_refinements!(sv::PostOptAnalysisState) = sv.all_retpaths_consistent = sv.all_effect_free = sv.effect_free_if_argmem_only = - sv.all_nothrow = sv.all_noub = false + sv.all_nothrow = sv.all_noub = sv.nortcall = false function any_refinable(sv::PostOptAnalysisState) effects = sv.result.ipo_effects return ((!is_consistent(effects) & sv.all_retpaths_consistent) | (!is_effect_free(effects) & sv.all_effect_free) | (!is_nothrow(effects) & sv.all_nothrow) | - (!is_noub(effects) & sv.all_noub)) + (!is_noub(effects) & sv.all_noub) | + (!is_nortcall(effects) & sv.nortcall)) end struct GetNativeEscapeCache{CodeCache} @@ -647,7 +655,8 @@ function refine_effects!(interp::AbstractInterpreter, sv::PostOptAnalysisState) effect_free = sv.all_effect_free ? ALWAYS_TRUE : sv.effect_free_if_argmem_only === true ? EFFECT_FREE_IF_INACCESSIBLEMEMONLY : effects.effect_free, nothrow = sv.all_nothrow ? true : effects.nothrow, - noub = sv.all_noub ? (sv.any_conditional_ub ? NOUB_IF_NOINBOUNDS : ALWAYS_TRUE) : effects.noub) + noub = sv.all_noub ? (sv.any_conditional_ub ? NOUB_IF_NOINBOUNDS : ALWAYS_TRUE) : effects.noub, + nortcall = sv.nortcall ? true : effects.nortcall) return true end @@ -772,6 +781,13 @@ function scan_non_dataflow_flags!(inst::Instruction, sv::PostOptAnalysisState) sv.all_noub = false end end + if !has_flag(flag, IR_FLAG_NORTCALL) + # if a function call that might invoke `Core.Compiler.return_type` has been deleted, + # there's no need to taint with `:nortcall`, allowing concrete evaluation + if isexpr(stmt, :call) || isexpr(stmt, :invoke) + sv.nortcall = false + end + end end function scan_inconsistency!(inst::Instruction, sv::PostOptAnalysisState) diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 82ca6e364f2fa..7d936a1688aba 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -1050,6 +1050,8 @@ function Base.show(io::IO, e::Effects) printstyled(io, effectbits_letter(e, :noub, 'u'); color=effectbits_color(e, :noub)) print(io, ',') printstyled(io, effectbits_letter(e, :nonoverlayed, 'o'); color=effectbits_color(e, :nonoverlayed)) + print(io, ',') + printstyled(io, effectbits_letter(e, :nortcall, 'r'); color=effectbits_color(e, :nortcall)) print(io, ')') end diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index b40f65ab3ca1d..9a4c761b4209b 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -2871,7 +2871,7 @@ end # since abstract_call_gf_by_type is a very inaccurate model of _method and of typeinf_type, # while this assumes that it is an absolutely precise and accurate and exact model of both function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, sv::AbsIntState) - UNKNOWN = CallMeta(Type, Any, EFFECTS_THROWS, NoCallInfo()) + UNKNOWN = CallMeta(Type, Any, Effects(EFFECTS_THROWS; nortcall=false), NoCallInfo()) if !(2 <= length(argtypes) <= 3) return UNKNOWN end @@ -2899,8 +2899,12 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s return UNKNOWN end + # effects are not an issue if we know this statement will get removed, but if it does not get removed, + # then this could be recursively re-entering inference (via concrete-eval), which will not terminate + RT_CALL_EFFECTS = Effects(EFFECTS_TOTAL; nortcall=false) + if contains_is(argtypes_vec, Union{}) - return CallMeta(Const(Union{}), Union{}, EFFECTS_TOTAL, NoCallInfo()) + return CallMeta(Const(Union{}), Union{}, RT_CALL_EFFECTS, NoCallInfo()) end # Run the abstract_call without restricting abstract call @@ -2918,25 +2922,25 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s rt = widenslotwrapper(call.rt) if isa(rt, Const) # output was computed to be constant - return CallMeta(Const(typeof(rt.val)), Union{}, EFFECTS_TOTAL, info) + return CallMeta(Const(typeof(rt.val)), Union{}, RT_CALL_EFFECTS, info) end rt = widenconst(rt) if rt === Bottom || (isconcretetype(rt) && !iskindtype(rt)) # output cannot be improved so it is known for certain - return CallMeta(Const(rt), Union{}, EFFECTS_TOTAL, info) + return CallMeta(Const(rt), Union{}, RT_CALL_EFFECTS, info) elseif isa(sv, InferenceState) && !isempty(sv.pclimitations) # conservatively express uncertainty of this result # in two ways: both as being a subtype of this, and # because of LimitedAccuracy causes - return CallMeta(Type{<:rt}, Union{}, EFFECTS_TOTAL, info) + return CallMeta(Type{<:rt}, Union{}, RT_CALL_EFFECTS, info) elseif isa(tt, Const) || isconstType(tt) # input arguments were known for certain # XXX: this doesn't imply we know anything about rt - return CallMeta(Const(rt), Union{}, EFFECTS_TOTAL, info) + return CallMeta(Const(rt), Union{}, RT_CALL_EFFECTS, info) elseif isType(rt) - return CallMeta(Type{rt}, Union{}, EFFECTS_TOTAL, info) + return CallMeta(Type{rt}, Union{}, RT_CALL_EFFECTS, info) else - return CallMeta(Type{<:rt}, Union{}, EFFECTS_TOTAL, info) + return CallMeta(Type{<:rt}, Union{}, RT_CALL_EFFECTS, info) end end diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 85bdd881042dc..41fb774266f25 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -449,6 +449,9 @@ function adjust_effects(ipo_effects::Effects, def::Method) if is_effect_overridden(override, :consistent_overlay) ipo_effects = Effects(ipo_effects; nonoverlayed=CONSISTENT_OVERLAY) end + if is_effect_overridden(override, :nortcall) + ipo_effects = Effects(ipo_effects; nortcall=true) + end return ipo_effects end diff --git a/base/essentials.jl b/base/essentials.jl index 50017b3d7927d..32c44a9571f23 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -202,7 +202,8 @@ macro _total_meta() #=:inaccessiblememonly=#true, #=:noub=#true, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#true)) end # can be used in place of `@assume_effects :foldable` (supposed to be used for bootstrapping) macro _foldable_meta() @@ -216,7 +217,8 @@ macro _foldable_meta() #=:inaccessiblememonly=#true, #=:noub=#true, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#true)) end # can be used in place of `@assume_effects :terminates_locally` (supposed to be used for bootstrapping) macro _terminates_locally_meta() @@ -230,7 +232,8 @@ macro _terminates_locally_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :terminates_globally` (supposed to be used for bootstrapping) macro _terminates_globally_meta() @@ -244,7 +247,8 @@ macro _terminates_globally_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :terminates_globally :notaskstate` (supposed to be used for bootstrapping) macro _terminates_globally_notaskstate_meta() @@ -258,7 +262,8 @@ macro _terminates_globally_notaskstate_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :terminates_globally :noub` (supposed to be used for bootstrapping) macro _terminates_globally_noub_meta() @@ -272,7 +277,8 @@ macro _terminates_globally_noub_meta() #=:inaccessiblememonly=#false, #=:noub=#true, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :effect_free :terminates_locally` (supposed to be used for bootstrapping) macro _effect_free_terminates_locally_meta() @@ -286,7 +292,8 @@ macro _effect_free_terminates_locally_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :nothrow :noub` (supposed to be used for bootstrapping) macro _nothrow_noub_meta() @@ -300,7 +307,8 @@ macro _nothrow_noub_meta() #=:inaccessiblememonly=#false, #=:noub=#true, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :nothrow` (supposed to be used for bootstrapping) macro _nothrow_meta() @@ -314,7 +322,8 @@ macro _nothrow_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :nothrow` (supposed to be used for bootstrapping) macro _noub_meta() @@ -342,7 +351,8 @@ macro _notaskstate_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#false, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # can be used in place of `@assume_effects :noub_if_noinbounds` (supposed to be used for bootstrapping) macro _noub_if_noinbounds_meta() @@ -356,7 +366,8 @@ macro _noub_if_noinbounds_meta() #=:inaccessiblememonly=#false, #=:noub=#false, #=:noub_if_noinbounds=#true, - #=:consistent_overlay=#false)) + #=:consistent_overlay=#false, + #=:nortcall=#false)) end # another version of inlining that propagates an inbounds context diff --git a/base/expr.jl b/base/expr.jl index 7d723c3f940d7..c4f64b89de8b6 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -505,6 +505,7 @@ The following `setting`s are supported. - `:inaccessiblememonly` - `:noub` - `:noub_if_noinbounds` +- `:nortcall` - `:foldable` - `:removable` - `:total` @@ -673,6 +674,20 @@ The `:noub` setting asserts that the method will not execute any undefined behav any other effect assertions (such as `:consistent` or `:effect_free`) as well, but we do not model this, and they assume the absence of undefined behavior. +--- +## `:nortcall` + +The `:nortcall` setting asserts that the method does not call `Core.Compiler.return_type`, +and that any other methods this method might call also do not call `Core.Compiler.return_type`. + +!!! note + To be precise, this assertion can be used when a call to `Core.Compiler.return_type` is + not made at runtime; that is, when the result of `Core.Compiler.return_type` is known + exactly at compile time and the call is eliminated by the optimizer. However, since + whether the result of `Core.Compiler.return_type` is folded at compile time depends + heavily on the compiler's implementation, it is generally risky to assert this if + the method in question uses `Core.Compiler.return_type` in any form. + --- ## `:foldable` @@ -683,6 +698,7 @@ currently equivalent to the following `setting`s: - `:effect_free` - `:terminates_globally` - `:noub` +- `:nortcall` !!! note This list in particular does not include `:nothrow`. The compiler will still @@ -716,6 +732,7 @@ the following other `setting`s: - `:notaskstate` - `:inaccessiblememonly` - `:noub` +- `:nortcall` !!! warning `:total` is a very strong assertion and will likely gain additional semantics @@ -794,17 +811,17 @@ function compute_assumed_setting(override::EffectsOverride, @nospecialize(settin elseif setting === :noub_if_noinbounds return EffectsOverride(override; noub_if_noinbounds = val) elseif setting === :foldable - consistent = effect_free = terminates_globally = noub = val - return EffectsOverride(override; consistent, effect_free, terminates_globally, noub) + consistent = effect_free = terminates_globally = noub = nortcall = val + return EffectsOverride(override; consistent, effect_free, terminates_globally, noub, nortcall) elseif setting === :removable effect_free = nothrow = terminates_globally = val return EffectsOverride(override; effect_free, nothrow, terminates_globally) elseif setting === :total consistent = effect_free = nothrow = terminates_globally = notaskstate = - inaccessiblememonly = noub = val + inaccessiblememonly = noub = nortcall = val return EffectsOverride(override; consistent, effect_free, nothrow, terminates_globally, notaskstate, - inaccessiblememonly, noub) + inaccessiblememonly, noub, nortcall) end return nothing end diff --git a/src/julia.h b/src/julia.h index 2054a434577e7..e211f31c6512c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -271,12 +271,13 @@ typedef union __jl_purity_overrides_t { uint16_t ipo_noub : 1; uint16_t ipo_noub_if_noinbounds : 1; uint16_t ipo_consistent_overlay : 1; + uint16_t ipo_nortcall : 1; } overrides; uint16_t bits; } _jl_purity_overrides_t; -#define NUM_EFFECTS_OVERRIDES 10 -#define NUM_IR_FLAGS 12 +#define NUM_EFFECTS_OVERRIDES 11 +#define NUM_IR_FLAGS 13 // This type describes a single function body typedef struct _jl_code_info_t { diff --git a/src/method.c b/src/method.c index 549575286bc7e..d890489c390f9 100644 --- a/src/method.c +++ b/src/method.c @@ -491,6 +491,8 @@ jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ir) if (noub_if_noinbounds) li->purity.overrides.ipo_noub_if_noinbounds = noub_if_noinbounds; int8_t consistent_overlay = jl_unbox_bool(jl_exprarg(ma, 9)); if (consistent_overlay) li->purity.overrides.ipo_consistent_overlay = consistent_overlay; + int8_t nortcall = jl_unbox_bool(jl_exprarg(ma, 10)); + if (nortcall) li->purity.overrides.ipo_nortcall = nortcall; } } else From 2e1235ea6523aac0ef45ac2a4e56eb73ecebd82d Mon Sep 17 00:00:00 2001 From: Haakon Ludvig Langeland Ervik <45243236+haakon-e@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:35:20 -0700 Subject: [PATCH 178/206] Update asyncmap docs to clarify order of outputs (#54974) --- base/asyncmap.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/asyncmap.jl b/base/asyncmap.jl index c81afbb7e9115..02e515d2e0c6c 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -9,6 +9,8 @@ Uses multiple concurrent tasks to map `f` over a collection (or multiple equal length collections). For multiple collection arguments, `f` is applied elementwise. +The output is guaranteed to be the same order as the elements of the collection(s) `c`. + `ntasks` specifies the number of tasks to run concurrently. Depending on the length of the collections, if `ntasks` is unspecified, up to 100 tasks will be used for concurrent mapping. From d3022722fe19ae746f45d4c891ec3996056d02e3 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Sun, 11 Aug 2024 16:13:56 +0200 Subject: [PATCH 179/206] precompilepkgs: Handle when the terminal is very short (#55445) Fixes https://github.com/JuliaLang/Pkg.jl/issues/3935 1.10 counterpart https://github.com/JuliaLang/Pkg.jl/pull/3988 --- base/precompilation.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index feee394588b19..aa70718eab9bc 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -710,7 +710,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; while !printloop_should_exit lock(print_lock) do term_size = Base.displaysize(io)::Tuple{Int,Int} - num_deps_show = term_size[1] - 3 + num_deps_show = max(term_size[1] - 3, 2) # show at least 2 deps pkg_queue_show = if !interrupted_or_done.set && length(pkg_queue) > num_deps_show last(pkg_queue, num_deps_show) else From a3859ed209006aa83c143e169e664b33bbc6414c Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Sun, 11 Aug 2024 21:11:26 -0400 Subject: [PATCH 180/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?JuliaSyntaxHighlighting=20stdlib=20from=20a463611=20to=2004b232?= =?UTF-8?q?3=20(#55464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: JuliaSyntaxHighlighting URL: https://github.com/julialang/JuliaSyntaxHighlighting.jl.git Stdlib branch: main Julia branch: master Old commit: a463611 New commit: 04b2323 Julia version: 1.12.0-DEV JuliaSyntaxHighlighting version: 1.12.0 Bump invoked by: @tecosaur Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/julialang/JuliaSyntaxHighlighting.jl/compare/a463611e715c9ec546ac8463c38b6890d892e0c8...04b2323c41f6422464c838fe9045700e9ee75e95 ``` $ git log --oneline a463611..04b2323 04b2323 Support a syntax_errors keyword argument 3fba08b Use concrete refs in paren state struct ``` Co-authored-by: Dilum Aluthge --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - stdlib/JuliaSyntaxHighlighting.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 create mode 100644 deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 diff --git a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 new file mode 100644 index 0000000000000..518e2705544ed --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 @@ -0,0 +1 @@ +956fe26df1daca727ec15bfbc175584f diff --git a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 new file mode 100644 index 0000000000000..786dd666f2927 --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 @@ -0,0 +1 @@ +20c7990134634dd252909dfa2c43f7b77d427a77f1b726eefdc47781fc3ad46152e81e612d4091541ffb32323154cb5a696157cd24d7a71087d5883720e03728 diff --git a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 deleted file mode 100644 index 47635275f0364..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -5f8e876204d20c02b8139e61c78caf44 diff --git a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 deleted file mode 100644 index d353acb42a5ce..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-a463611e715c9ec546ac8463c38b6890d892e0c8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e701477f0f7210854603e9d10758e2ecd47c1afb0f4ae6eca07cd64490cef74bbea5f3792f40b754dabbeea03bda2df07072c635b63e5f8a3f7ebb6f3f03fdf0 diff --git a/stdlib/JuliaSyntaxHighlighting.version b/stdlib/JuliaSyntaxHighlighting.version index 705f16c785a39..b076cfa26b5aa 100644 --- a/stdlib/JuliaSyntaxHighlighting.version +++ b/stdlib/JuliaSyntaxHighlighting.version @@ -1,4 +1,4 @@ JULIASYNTAXHIGHLIGHTING_BRANCH = main -JULIASYNTAXHIGHLIGHTING_SHA1 = a463611e715c9ec546ac8463c38b6890d892e0c8 +JULIASYNTAXHIGHLIGHTING_SHA1 = 04b2323c41f6422464c838fe9045700e9ee75e95 JULIASYNTAXHIGHLIGHTING_GIT_URL := https://github.com/julialang/JuliaSyntaxHighlighting.jl.git JULIASYNTAXHIGHLIGHTING_TAR_URL = https://api.github.com/repos/julialang/JuliaSyntaxHighlighting.jl/tarball/$1 From 9d222b87d77d8a76f806fb296e33916dde8c9411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 12 Aug 2024 03:13:05 +0200 Subject: [PATCH 181/206] [OpenBLAS_jll] Upgrade to v0.3.28 (#55462) Memo to self: * update version number in `stdlib/OpenBLAS_jll/Project.toml` * update version number and sha in `deps/openblas.version` * refresh checksums with `make -f contrib/refresh_checksums.mk -j openblas` See the [release notes of v0.3.28](https://github.com/OpenMathLib/OpenBLAS/releases/tag/v0.3.28). --- deps/checksums/openblas | 188 +++++++++++++++---------------- deps/openblas.version | 6 +- stdlib/OpenBLAS_jll/Project.toml | 2 +- 3 files changed, 98 insertions(+), 98 deletions(-) diff --git a/deps/checksums/openblas b/deps/checksums/openblas index ad6b38dc075fa..51317261c82a0 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,94 +1,94 @@ -OpenBLAS.v0.3.27+1.aarch64-apple-darwin-libgfortran5.tar.gz/md5/7bb5c7a169ec7660ec38fe73c74a89d7 -OpenBLAS.v0.3.27+1.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/97266fa0d786bac50f37d82e66da645dfa1b811975045d4aaad1f49361caf7945c06203cb728bf92e9071ec805dff2c75f2b45b346ae4f9cfe289d8f2215e68b -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran3.tar.gz/md5/ea42c557a49aa58172ea0e0f0f93c628 -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/baade18c9d8d91f3fb32e44609277a7a6cd827a6c9554e5b21f88d492a0c34e93d29041f691f6b0cd03ab609d5470b1a06e95121781e9622cce301812d6613de -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran4.tar.gz/md5/85a9cbbbf9fff65927a9ff96f17d0792 -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/7a0024c509a50c87c9318d209465e0d57fc2e0a8401740666f09d236678eb9d5a1b2fbbfd12c0c409006607a408f03f11c1465841417533010a7843c4af654c1 -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran5.tar.gz/md5/4e3c6a68a61b9749ebb55b20728bf0f1 -OpenBLAS.v0.3.27+1.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/dbf9fc5465f60a35849c391069c0a9d6d6fc8685b734d00088e297cf7a6c92fbed67f4264f2b2c164d3c6694d9c8f64b750faa248aa1fd44867d18a94211dc87 -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran3.tar.gz/md5/c25b607a4df84f9aeb112f24520cabb3 -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran3.tar.gz/sha512/a99fa75a3cfea19c84a4d455585e53f124e956dd5d4ee7ce0c38c0922b0bebb8b2c996079c3bc63e95444b531ddf9d1f003a22d7f6b55cf99db2334bb1c618ae -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran4.tar.gz/md5/3473d20c26f6ad50f3a0b635415858a5 -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran4.tar.gz/sha512/6e9100e0fcbe1b91c5a4461118739af9d4eca7edd7b8e6ee07a2052c0aaad0ea84c048f0e507ff88da81f47b10c102faf9fe735d13ae1cd35f44396d9a51a864 -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran5.tar.gz/md5/9ad49254a2827987e622a58a1b8c7b98 -OpenBLAS.v0.3.27+1.aarch64-linux-musl-libgfortran5.tar.gz/sha512/f8a3b9aa52920ce76f5d9550407aeefed5e2596d05b9f8f0643e1da221cf533a09de7a0454a04a2d59a3a2a2fb899a538a5e03b133746415a81415ff926826ba -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/c130634237846672f3a672f1d0e346d9 -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/c174d00870ce3944c553122606cba7b78312342a02dc4833a91ae105f05d85d06e665e86a79452bdb7d2b31c18936582d79427ec3976048cf09497011d8c77c8 -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/07c58a9399552e3b8362d9c1dd155693 -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/98570a4dae80f9b4366c08994911efc87bf6967e63e20b486240a3b2d7637fabbfcca3fe8340ae4d9bae7702be400f5976fc5aa0020f984157b097b02e08d23c -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/25a9af724bb8a5ca42be6277a726583e -OpenBLAS.v0.3.27+1.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/7afbc7453d1f22171523476e90882f67611374b03a3481bdb588722bc4816d081304b811a0dd452288ca972bea95bd2d2286644bda309dbe25fe721321298e85 -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/2f9494f7600729bfa00a0db96bd9349d -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/eae895a7ef4d9922bf9f6c454f56b2881fd5549e6c6a825e0e4d5b84defe9a97719a9f1e62f996dd545afdf372c1ab18bbee0a6cce8474d9adb2522b16678d35 -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/8f30a26bd56ced5d6edc88b1fae57beb -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/ad849216c9655dc160a0cd756904442a80d693121e60a2b33876ac347c79fe6e3e602faad0c64a45599f5a5e203c3d9e8316c6b20c41d81e666b7650dccfaa5c -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/272facb48c295ccfea2a291869e1817e -OpenBLAS.v0.3.27+1.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/7fd5c23046fa548f0bed6e7ce4f6fa809e56909b5595d2a4f348189ee99f234dc84989219ee63cdc004ce303b50fee2aa1fcb93589ff116a2191f8ef520d24be -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/c130634237846672f3a672f1d0e346d9 -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/c174d00870ce3944c553122606cba7b78312342a02dc4833a91ae105f05d85d06e665e86a79452bdb7d2b31c18936582d79427ec3976048cf09497011d8c77c8 -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/07c58a9399552e3b8362d9c1dd155693 -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/98570a4dae80f9b4366c08994911efc87bf6967e63e20b486240a3b2d7637fabbfcca3fe8340ae4d9bae7702be400f5976fc5aa0020f984157b097b02e08d23c -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/25a9af724bb8a5ca42be6277a726583e -OpenBLAS.v0.3.27+1.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/7afbc7453d1f22171523476e90882f67611374b03a3481bdb588722bc4816d081304b811a0dd452288ca972bea95bd2d2286644bda309dbe25fe721321298e85 -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/2f9494f7600729bfa00a0db96bd9349d -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/eae895a7ef4d9922bf9f6c454f56b2881fd5549e6c6a825e0e4d5b84defe9a97719a9f1e62f996dd545afdf372c1ab18bbee0a6cce8474d9adb2522b16678d35 -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/8f30a26bd56ced5d6edc88b1fae57beb -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/ad849216c9655dc160a0cd756904442a80d693121e60a2b33876ac347c79fe6e3e602faad0c64a45599f5a5e203c3d9e8316c6b20c41d81e666b7650dccfaa5c -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/272facb48c295ccfea2a291869e1817e -OpenBLAS.v0.3.27+1.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/7fd5c23046fa548f0bed6e7ce4f6fa809e56909b5595d2a4f348189ee99f234dc84989219ee63cdc004ce303b50fee2aa1fcb93589ff116a2191f8ef520d24be -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran3.tar.gz/md5/14cee2ac2cff0d9d8b614278e3f7a4ed -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran3.tar.gz/sha512/d81aa1c8ff70d8d24d2cf88adc568dbf6a77f191332aa0298fbc0faad1fda855c9a6c278d0556003cca315ef75e47cf7caa6963b4e16f4d883ba7c1b13a298bb -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran4.tar.gz/md5/559f96fb8a2a03df6689200173f2c1df -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran4.tar.gz/sha512/cc1e987b2ad7d47b474d39b0f93ee6f6e46a4e5d0760cea9e31a0d3c5336e6cfc88401122ab278c0b745c9e60b290f9c05edf39bef9e7e97c70f33dc7afac341 -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran5.tar.gz/md5/c572b06af06609e5e84dc8aee61babc1 -OpenBLAS.v0.3.27+1.i686-linux-gnu-libgfortran5.tar.gz/sha512/d799e280600970697701098f76e79d0bb72bf55cbe8d6c131bd26f6a67bdcb5ed307b26eae89bc6b7cc6b6eb25d2622f952b315f7850b7f231148f14cc09b769 -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran3.tar.gz/md5/4aa9f25b39088f79ea13aab1097c0c1f -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran3.tar.gz/sha512/126876d9de1c67302dc1b9b71a96fd2f5eb45745ebbcea6d4b7d4bdfac93088ef6b89e75a2bfcd83f1b32dc798b7ef824bb225e24e88e6443571d0576939bb05 -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran4.tar.gz/md5/4ffd9c16cd3c6535457dd654f95c62e6 -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran4.tar.gz/sha512/cc7fbe4949b5b51e5f1f5fdae537bbcc68ef4a59a02c290df2f6723bdeb52d98e699e4b23a879372d56279196295d8c938ba2221fe3a73cd1ef953059cdf694f -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran5.tar.gz/md5/7d6855b9a879259216c243dcfc75a2cc -OpenBLAS.v0.3.27+1.i686-linux-musl-libgfortran5.tar.gz/sha512/221d1ba0250802ae88daac384fd1b2c911c49f8e141efbf3c2668260f4018c5e5f1e21c459a1595652ca48ebc446fe43e54fbf732b47d68f20ecb1e280862570 -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran3.tar.gz/md5/646fdfccf16f12f23441723e13c12f58 -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran3.tar.gz/sha512/2692aae16acba199584da71275eb609071d6f7a6d644239f9b6307fe12fc875d6267b11d387b2cace1d5866bf50ab0db619510d02acd3c90696bfb0dfe958037 -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran4.tar.gz/md5/257e35006373e43fedb211c56b73315a -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran4.tar.gz/sha512/e4d8049a6e30763dbacba7646805bb72abad021f8810fb084a287d389137e30b96f12f04ad625c5ef322d127f7b603f388fee18a516e101761391d405ec58d2e -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran5.tar.gz/md5/68245d8b061c60f97f48fd4fde4492dd -OpenBLAS.v0.3.27+1.i686-w64-mingw32-libgfortran5.tar.gz/sha512/511f5fcb538067c04742ad578d2584ebb3cc54bd7c43b84b14d3597bcb84d303a729a48c79018afa119ef12e084bed5ce6fe3591774a1cd6a5b6bbe5df4a8753 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/883728fe99e27d1f066032e1465880b2 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/3363ad953d1d7b5ba233b5d6ff65411e51189adcc6e7a9b68e45388132b38701eba53745f826f896820a98bc5015a8787ab1257f1a25c0a55f0437707c451d20 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/672fb00c47939bfc1893c7bf630b6904 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/e1beb8be0b58402df60b14a81d4fefe13cb0a30450717c80f2670b3a7947a89574848e858f90e0efd5474c47cdb86ce5623645988f05f105df206abd888c2f58 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/32eeeeeb57ed38bb4123ea793faf6685 -OpenBLAS.v0.3.27+1.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/bc505de8d8378e5c0fd6b3092b7093ecae0cacd9d5f6fa94e6e01ead03ffd7abad31c8d75fa84cf6da4f4fd33dde33df968595ecdc818f5b891b82db1be2d1a1 -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran3.tar.gz/md5/e49f4562399b5d45d987e9820774f7c8 -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/0e5ade0c2112f01b3bde14ddb0fe500085d75fc86117d54bc66cc2da30f7251233387a90daca6203ebe457bc68e8bf3cff62c011b424a971ff9f7932974eaba4 -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran4.tar.gz/md5/26c9067086aa013de9c3b4001cd3f78a -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/e641bc045b96cb011183e26541730b46b8dfb401ef1223f10f19450de206d9971f3181d37c7687477d782238e580bbba4fddbcb2094a45761b55dcc93a9cacd4 -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran5.tar.gz/md5/a2cf4ac08dc296f6aaf109e8d1fff491 -OpenBLAS.v0.3.27+1.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/2210bc1dfa32b0b9b86ec84943b6673bc540a0822652274ececa0f394ed406d9f23f02909f2b8f97dd2a2bc114df2d0e9a6d868d29bc2d08a3da7176743a6d10 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran3.tar.gz/md5/1b501f18b00d1e051b4af955da81b3c9 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/1b5615dc63efd0166b206bbdc90801d0c623f93f537c320bac1af8bf41f9e3ae8ec33eb6b43a7bd9dc2d9ba526bc7bb200ff828f33ef36da920f9290fa4ff252 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran4.tar.gz/md5/079cebb72efd39454275a8199fc78c17 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/94bdd5db2546381e3cd15bb60b382c11d8ba879f8b88771a15d0d7cbf5a399f46aec60fc01e07258614ec039bf9bf73cbeffc9d2f29b03c9885e63704f0d2ab0 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran5.tar.gz/md5/cef6229311f1616c0db95cef84725cd4 -OpenBLAS.v0.3.27+1.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/297eda815134d5de59d1614b39f06a512f4ef544dc5abaffa015075a8bcba1506aa4825109213e54e94401cbf16d4292a1ec2b9b71b278cc8536379d80d96e46 -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran3.tar.gz/md5/b410edbbc651fd9f6589fda153b410da -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran3.tar.gz/sha512/718c22a940d998dcd8c754994f5a7d9bd3e3131d51beb1d8071ca0005e5c562bb2368924b0c4951839df0bc85a272962f87891b366a1bce1f735cc2b3495b834 -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran4.tar.gz/md5/af8f2dc642041d5e4eff98d6b20e7596 -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran4.tar.gz/sha512/48b88f703cc0e35d8f3b3bf7f395481a3225f5c3d1a4277a7b477815feab71df5c6b662313f4762bc8002f43c0f1bece0f383bc3920c09d383303b3927925ddf -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran5.tar.gz/md5/eba3e9322d39993d81d78486306b301f -OpenBLAS.v0.3.27+1.x86_64-linux-musl-libgfortran5.tar.gz/sha512/dc11716e4f7a53a396b8b8cd3e506bd66272e9e8c5533199dc972c91fed0cea5067ec8e14abf67da2b53af7f3189eafc5c188657d617eea3f55ed248d7ed38e4 -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/03f45c7c0276f58719235e5da3bcdc85 -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/836fbbdae1065393de8ad1410301afbecfb0bf60256322b754e17aa5b4edb20e409eeca2f66f9a2b9ffb5872479cd3cab9b721bd2fc9c3544f5e90e78c7e59c7 -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/dc6bc577a3ccd78364e9fcb98fec03dd -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/2c52880b287b0c4f48ed3539e4e0b24b6a05b46d47d7586eea7ca06ebc19c7f0d018fdd24e8da94249fa3b7dc54b85b27ebc530fc5cefb2d9b5457e00dee3529 -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/30a6a329d4d37dea7199dfcf264a2641 -OpenBLAS.v0.3.27+1.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/53be21e7a94033cd44b8e2d375b38606446800344698e4f365527d807f736b7b2b9a897138b5de5bd62ba9da104cd6f86bf59caebc18299c0abd98899c527988 -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/290a8fc0d1580aeed8cb7b793ff991bf -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/e30e4f666255982c1adbf73020bf88e2d499d2d26216a16c34b4a6b7ed0dc5b7d5374a978a7d0ef5735a82394b4ef06bd82491e2ddf7ec5775953b9183e9f601 -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/1b46471021b6914fc60401e3e1ffe78b -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/509d5138d8cd9621937f840b7f73949facec2f047676069403d3d7c482ea183766dc84536d9c2a291b18a2b89902e6f714665fa0b7a920727635530a3aa4aa17 -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/ae28948c5d496a3d0bba649c72822b2b -OpenBLAS.v0.3.27+1.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/8d66a65040e973947a8a7d4f4b1d47d63a77b75c0d5e04843de9188256aeec5a1c7e0d59bf5e1d5c262c4f1a4ff2aa36599840337e9d828fb77724c38c1fff4e -openblas-6c77e5e314474773a7749357b153caba4ec3817d.tar.gz/md5/4971eeb7adadee085d7c991db416fe7a -openblas-6c77e5e314474773a7749357b153caba4ec3817d.tar.gz/sha512/7b85c9fb7be54407ba627d77897f40de4395d6d307230aa7df83cf8e0a41f545e4af4ae0576abb40cc9e0c385e1c6a488100dff292ea307439a89587c07ba66f +OpenBLAS.v0.3.28+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/e3edc449afa805b3744eb153460b681f +OpenBLAS.v0.3.28+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/4f619ae720bc2a55c6d7d53b78bf0a15f66c5b3474c968b367f41d71c759b39028817e3e7ba3cebc4ee06f2176578a5a1bd2be7cf2f1461a396c418292fcf782 +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/e01dcbdbfd2c8f15d78efb0aa5673944 +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/33dee7c48f981b218792e150aea506989b7bbacfd540ebd1fefb150af3c33eae62cd523c329ef8f37c0b56643d480e105ed82e46ec5b3f683e006d05dda717ee +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/43662cb933b2aab820bd210edd4e994a +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/520abb2521a4b9ae71c86dafc7de4155d51df09ff119a3b1d25a9bac3fb73aceaf38b7805888d4858b96e73c0d1cf80d8953b9db954df4d0e6c164894d07d715 +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/5c693f190d26194353c1e096b40568bc +OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/3c3e11ba038e59002d23e885e22129dda13453469dad79f39f9cddceadbf1d39e61487894f5112b2fcb5265cd98075103d99eff2a83f79407aafa545b03e9f9c +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/2892710a8545b4573014024222bb8dff +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/6a628c9f7eab2a34198028846a6aec7bb13af4425e1b73ba5b58d326c1eb0741b5dc08fff3db565c92cbc0e2718b62fa6dedac5fa0bdb2f35561663f36f4dfbe +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/fbec5f47685d4bb36956cd4aee34f1e5 +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/ac69a9ed17900de79c6da0ff08a97f3397860de92ce1888f77c8c8fada08fab15fff1b19868c95865ad4a387701c2ffe74e695d6949d8ba02534f91aca2a5ca3 +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/6a0a1a1cad6452ac687e24147128f027 +OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/0ea2b7f829b4e406276911db743706b17d7902899d4492e18b9676fed9b27d976d586e38505c52932e27f194c9806d6cb53182cb128baab41898605af7c346b5 +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/677baf1c9142f1db12c89ef98a082d03 +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0a182dba6512dd50193d7625091487bb45f61ec5edbb8adffdeb68fa43744d8c9aa1233ac709249b09fed59e63b6532bf40386dfe884c26605551a6974ed0cc8 +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/d6b08be3200bef4a045be99246a3f294 +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/467d6d12cd56237e6128de4041dbffa3428f208e313f20975c0665abf42a3c39d6b527676573897d6b6801306a9a241da17f4231ce79f0081fb433733d3cb6b4 +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/8645788a731c86f26f40eaf6f65bf74c +OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/19ea4ffdef48ef1af6bdd68ce39986814b1732d65bcaee673cd3c0dcb5572faef53962c4ac18e0d1800eb9745324b3145f98c136606ff71d96778e85d4d6bf72 +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/a40dc134a8a5e31bea637bc0a6ee45b6 +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/3d4a1a67753f41bde880ae0b1d19ad7998ae7646530d3e469829e7ea859a394dde73e20239b80e8c61b58974c266d0960cbe256dea4103b04dd4ec52318f02c0 +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/0ff472d7bf455b8b3b50daa91241f288 +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/c0b306bf1ba71baebbe191d7f105287aa19fccd61ae2bc48c9b9ffd92140d4f02d3a78e0632e83924fb02c93826455493c8f5767d71b7e505a1066bd67b95dff +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/26a05928260315bc2088842d2fa75347 +OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/dd5ceb6b7fd028df3c4eac732857c537e81c6c8bb7662c6075e432acd51eb6421556b3453e37483481499b2557d34fcec22fda9192cd54b6c7c7205dd40ed387 +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/677baf1c9142f1db12c89ef98a082d03 +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0a182dba6512dd50193d7625091487bb45f61ec5edbb8adffdeb68fa43744d8c9aa1233ac709249b09fed59e63b6532bf40386dfe884c26605551a6974ed0cc8 +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/d6b08be3200bef4a045be99246a3f294 +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/467d6d12cd56237e6128de4041dbffa3428f208e313f20975c0665abf42a3c39d6b527676573897d6b6801306a9a241da17f4231ce79f0081fb433733d3cb6b4 +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/8645788a731c86f26f40eaf6f65bf74c +OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/19ea4ffdef48ef1af6bdd68ce39986814b1732d65bcaee673cd3c0dcb5572faef53962c4ac18e0d1800eb9745324b3145f98c136606ff71d96778e85d4d6bf72 +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/a40dc134a8a5e31bea637bc0a6ee45b6 +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/3d4a1a67753f41bde880ae0b1d19ad7998ae7646530d3e469829e7ea859a394dde73e20239b80e8c61b58974c266d0960cbe256dea4103b04dd4ec52318f02c0 +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/0ff472d7bf455b8b3b50daa91241f288 +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/c0b306bf1ba71baebbe191d7f105287aa19fccd61ae2bc48c9b9ffd92140d4f02d3a78e0632e83924fb02c93826455493c8f5767d71b7e505a1066bd67b95dff +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/26a05928260315bc2088842d2fa75347 +OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/dd5ceb6b7fd028df3c4eac732857c537e81c6c8bb7662c6075e432acd51eb6421556b3453e37483481499b2557d34fcec22fda9192cd54b6c7c7205dd40ed387 +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran3.tar.gz/md5/36f76f7588ad5bc48c2f68daee49da57 +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/2184cac67657fb58afc42fff46069084ffbcbc67938e7e74e9e5a926cc83733c702cacf16ca320381f5bb1f219cbea764ae8cdb9c445f7224ac0cd0beab822ff +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran4.tar.gz/md5/ef8501cc6babf8be3b8b649da2a7c692 +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/98543cfd34a185644cebc33cd82ebfb663c92f1fa8349121e6d34f86b1d10f4f37688b84b22182f9e29daa74664a469ddc67408827e8bc7fddb1a7311d918532 +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran5.tar.gz/md5/598c07efb122e75e6e99ba7fc0c4fb4b +OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/b7caa20a36d6806895f3efb02830017c3ca8037c5af3a29df00f9fe34945324c34181a945b1dbe8a8ca43c7f792667d7640c23b5c2fa4fd93564f1da78561190 +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran3.tar.gz/md5/e7667d215442ac0db83969d41a678774 +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran3.tar.gz/sha512/3b22dd658b5948d6867b3e57fe53976eef59339d2714709746098b96f13766d86e918a139929aa60672be91c50c7f739c5c0db372f07a71ae2447588db3685e4 +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran4.tar.gz/md5/91d95572ce67a21d107b9fbcd3aba11d +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran4.tar.gz/sha512/7727d24fec0a333a943de3f9d6dd5c698e4f3b9099fd838b8b5652f6216f7b9fe4a2d8f014a4f0b3b7ad7fe05b81a9079e570454d456f0462e7d04f66e264ecb +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran5.tar.gz/md5/2d56a5cfeae0a6afa2d2b8efa1ab22c5 +OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran5.tar.gz/sha512/e81207bee11f89669837db08b57b63813056730f68412345421539399c12a675ed01942558ebd42045959c29a2b774a75f28c4a6b14549b7373b54a5e93e8933 +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/5b741b5fec8b564ba8b24435b5d885ae +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/97e72a4b9b39d4889c4e36eff85186fcbabfff2930185e69b3c259b43cdbaa5fab51bf0ed4024d1ddd3c780edaf501c4f5f7534e0a2edb802d580987fbd026ab +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/d5f059fc960b7dc84ee4b92c431d87b4 +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/f1e8f31f89274ff5b466931f8941de55fb27d2ee773d87e7e0b992deeec7d921358b10520cc0f47975022536b5e9d7b1cc9acc481b95f83cc2096d7cb7494616 +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/cb99d7d4944c5283a1a0142683e1d377 +OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/b77d3225e60f49506917bfff78c187df7157dbc834eccda2fa03d03eef8214b225682888a411a8b6e4b29a8d7e2b0ca625ea8c56b84ecc39e1f4f1012523c096 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/c6e5d4867a068e08b3f56f474e498b81 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/de6249439758a501bfd27d3ef04ec04cc06edf64de73f0709a6a40a2eaf40bd3d5d77dfd54b7b19e2f6bf6c104b4416d3e225faa0cff4cb631785c08d90b8614 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/32e70466cfa3cfec65ab4cad3abc5f03 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/2642385a5e9fc8e9c3839a5a44f9753b21b5078725f7d0c3e1ebe96b76129a3b8e2627d92629dee4f6fd7e8e51e86a7fbedc80cbe4d1a6812cea363559950da0 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/e2332831bd88d57132241697952819e7 +OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/ad03edf9ac56bf6311f0ca70a1bc359242accfe82cba9e42f39f6cb1c3006226179ff9be8218847889cae10fac13bc33f60837e1e3249e309172da7fbc25400f +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/24c915a3156983745662ff99e5d1b040 +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/47fb327281c903eebb0a261458fc10f09bac317d7e135dff72a112c868a2525fa542f93f22da083c13454fc241352d39a8e8463085685aa77e055ffcadf451c8 +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/93041d21ad3f95e6d9cbac6cd6730363 +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/17cd2302860eeee884f97d87eaf0ad12cdc7361734cfaa77b543119c58103a5da107b478e7ecfcb135d2e5beffd6a3907108b2911a095a3cbc1d16f32371ac1b +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/98a8c6c8c80c11e8b6d127959c9b3414 +OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/d26a51785391d81efcaefcf647fcf0348ad68ff01845ab3547778903d2ab5c5c1cdb2a562ae5cf7f12878f3345c46321719ea82fb87ef655d303a4c0c9803377 +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/41f7fdc10d8cab0965da95e00e2269ba +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/0a47ef77f9b2b70f424e00957f676c53d19c5dffbbcd5a743ab24bbc8608c5e8ad3cb3afefd8cab60a3c51970a63dd47c97868ecc0ef3532b83278c41a8daf96 +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/8453e7a5e5285e770fde7592582bc0e2 +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/a37edfe68c85a6312d7918f1b58d6ac4bafc13081dbd327c830631913350a54bbf8bea57115b4f242d5f93c6b0a8f4995b5ef544a0de06e76c66287ff092e74c +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/6df24890be7a4899f35a2949f9f21d65 +OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/66601632f91689fe72afecd2e4d4ef3ad3b7653874228d5509c7732f2e6d63640f35d176ce2219b732632e0daeb76dc3ba11d3e776639985359b21b313056883 +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/d35df8d213c55bc1f9f765e0ba8c7b4e +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/5d5de73150a2e796dc29425dbf415ff7aa443264d767d4e688de07335961ee39835c94b7d68900d49b70bf3ac08d356f3ae00c6d651eed64e504b02c9351edcb +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/384f9173b3804e6f9c73bcde9dacb545 +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/64d3abeca401cee06575915161458408e9fb51e26f759129e1c7a9c27f68729d66e75f0654b977e842844650698c4b1627a18e495d91202a8c0483ef1b35bafc +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/0bd296248e1337fac054b9e0993fea82 +OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/fdb9ce296228f92c112bbeb346a2900a8d5a73e21a313a217cf7135fd77484cdeed53c86382ee5550f1b624eb6ed99d06b739229add7364217ca68fefedd04c4 +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/524a2481331fdd3933f06b40e63433f1 +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/06831cc855e9801dbf2248a0da123c345b6731c830f39d3166b8d8e7de8d649b6d9900e534ec6c1113a227203f6a9aa8171fcf548cfd56a4a67b6037c105ecf5 +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/82f2b8f31f7b718f6ea743c996acbe4d +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/fd1ccab964ae9410238d29b38cfe8c2ccca3fda3d78b4294bb4a54ab8abfd6bdaa80cadc0aeadf054bf99138c5dc3cac9370920b0b16cb8793630ab21d5bf667 +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/b91add21ba0e2a0f28a9e4d347111cc3 +OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/8ed1d9e327529ee067d975c5c96dac3eabab5a88ed7b1b6e1b030f96bbd2418e3173cacd70e9976d619245757f2a34cc9527aafef1626fd288f14918c9b13eaa +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/937847e2ad00539f3422d1ecb9d26d55 +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/751d889661ddd46cd5718b49e34f826a4fb34b1b992251a5a975bc0af15b74a75d8a56f403e8fae570223477b2b8927d9cb36764e4b9e466045d5f317b8e7196 +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/180c54c50362d05696589b270693ee8f +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/2e3b76be5b7c4a7dc45f07e17493abd7ef9185e92429d8fa4d38766e0da96dd0777b619a9e420d2e1142bdab2ae1f755f9bc9ad97ee9a7927741778f89b9135f +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/2f0fac7c96af66ea63fce26e409f4db6 +OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/141522971447c38b4908342f3ad09ffb18142d2e79b44f66fd80047b44c09216c9b94c39f776e3093f9ceb6bc4d6270cbbfb4209b2fc0debfe93e7145cb4dbff +openblas-5ef8b1964658f9cb6a6324a06f6a1a022609b0c5.tar.gz/md5/f7a1fe86cefbf7d4f2608843c7833ca7 +openblas-5ef8b1964658f9cb6a6324a06f6a1a022609b0c5.tar.gz/sha512/5f6020e958967a12a3c5b18bde13331f9c0602bd073563f35cd7cec848c92b45f30ca362819b12cd16989c0e4641ee3e63db8322d1092f61b31ba2e4068dd7a7 diff --git a/deps/openblas.version b/deps/openblas.version index 527764e3f8603..09dcdc45af1ef 100644 --- a/deps/openblas.version +++ b/deps/openblas.version @@ -3,9 +3,9 @@ OPENBLAS_JLL_NAME := OpenBLAS ## source build -OPENBLAS_VER := 0.3.27 -OPENBLAS_BRANCH=v0.3.27 -OPENBLAS_SHA1=6c77e5e314474773a7749357b153caba4ec3817d +OPENBLAS_VER := 0.3.28 +OPENBLAS_BRANCH=v0.3.28 +OPENBLAS_SHA1=5ef8b1964658f9cb6a6324a06f6a1a022609b0c5 # LAPACK, source-only LAPACK_VER := 3.9.0 diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index 95dc40e6a0c2b..dfca282c74704 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.27+1" +version = "0.3.28+0" [deps] # See note in `src/OpenBLAS_jll.jl` about this dependency. From c907192a4ba1ec1c4a2b00303f1b3f19188c4b5e Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 12 Aug 2024 06:51:19 -0400 Subject: [PATCH 182/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?SparseArrays=20stdlib=20from=20e61663a=20to=2055976a6=20(#55469?= =?UTF-8?q?)?= 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: main Julia branch: master Old commit: e61663a New commit: 55976a6 Julia version: 1.12.0-DEV SparseArrays version: 1.12.0 Bump invoked by: @ViralBShah Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaSparse/SparseArrays.jl/compare/e61663ad0a79a48906b0b12d53506e731a614ab8...55976a6e4f883a32e3d3658af50c49879b98fce0 ``` $ git log --oneline e61663a..55976a6 55976a6 Keep sparse solvers docs as before (#552) 95fd7ff Missing space in error message (#554) b8a13ef implement in-place `ldiv!` for Cholesky factorization (#547) 1527014 Do not use nested dissection by default. (#550) ``` Co-authored-by: Dilum Aluthge --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - stdlib/SparseArrays.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 create mode 100644 deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 delete mode 100644 deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/md5 delete mode 100644 deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 new file mode 100644 index 0000000000000..401900c9f2739 --- /dev/null +++ b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 @@ -0,0 +1 @@ +7b16893f5a49cee4a4d9219afbb57577 diff --git a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 new file mode 100644 index 0000000000000..e8f1bc3c4aaaf --- /dev/null +++ b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 @@ -0,0 +1 @@ +398028ee8f23ee0b4a5144f5dd03d756cd7575a0b806f351d76339e9521830f75c0c96806a3ee5cebe04853feab51c75c7bcdaaa623acc649bc1a24395df5581 diff --git a/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/md5 b/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/md5 deleted file mode 100644 index d35cbc567faec..0000000000000 --- a/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -19f6d3bcbeec7a123e8dde983ef66a9a diff --git a/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/sha512 b/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/sha512 deleted file mode 100644 index f2c8db80327ce..0000000000000 --- a/deps/checksums/SparseArrays-e61663ad0a79a48906b0b12d53506e731a614ab8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8cef45d83047eba97edcaed04bb49f5aabdd96ec951baaa772c7da0402259e9578cfa383ab882440f685338ed14f797afe776a14e6aeea9df2428aa1592fcabf diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 7c99b8ba52d7c..2dc7bd8f5b3b9 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = main -SPARSEARRAYS_SHA1 = e61663ad0a79a48906b0b12d53506e731a614ab8 +SPARSEARRAYS_SHA1 = 55976a6e4f883a32e3d3658af50c49879b98fce0 SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 From cf4c30accd92755bc39d52364ae6549c490a4bc8 Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Mon, 12 Aug 2024 09:10:03 -0400 Subject: [PATCH 183/206] Add push! implementation for AbstractArray depending only on resize! (#55470) Fix #55459 In Julia 1.10, `push!` and `append!` would be functional for `AbstractVector` implementations if `resize!` and `setindex!` were defined. As of #51903 by @vtjnash as in Julia 1.11.0-rc2, `append!` now depends on an implementation of `sizehint!` and `push!`. Since `push!` also depends on `append!`, a stack overflow situation can easily be created. To avoid this, this pull request defines the following * Add generic versions of `push!(a::AbstractVector, x)` which do not depend on `append!` * Add default implementation of `sizehint!` that is a no-op The implementation of `push!(a::AbstractVector, x)` is a generic version based on the implementation of `push!(a::Vector, x)` without depending on internals. # Example for SimpleArray Consider the `SimpleArray` example from test/abstractarray.jl: ```julia mutable struct SimpleArray{T} <: AbstractVector{T} els::Vector{T} end Base.size(sa::SimpleArray) = size(sa.els) Base.getindex(sa::SimpleArray, idx...) = getindex(sa.els, idx...) Base.setindex!(sa::SimpleArray, v, idx...) = setindex!(sa.els, v, idx...) Base.resize!(sa::SimpleArray, n) = resize!(sa.els, n) Base.copy(sa::SimpleArray) = SimpleArray(copy(sa.els)) ``` Note that `setindex!` and `resize!` are implemented for `SimpleArray`. ## Julia 1.10.4: push! is functional On Julia 1.10.4, `push!` has a functional implementation for `SimpleArray` ```julia-repl julia> push!(SimpleArray{Int}(zeros(Int,5)), 6) 6-element SimpleArray{Int64}: 0 0 0 0 0 6 ``` ## Julia 1.11.0-rc2 and nightly: push! requires sizehint! and is prone to stack overflow Before this pull request, on Julia 1.11.0-rc2 and nightly, `push!` fails for want of `sizehint!`. ```julia-repl julia> push!(SimpleArray{Int}(zeros(Int,5)), 6) ERROR: MethodError: no method matching sizehint!(::SimpleArray{Int64}, ::Int64) The function `sizehint!` exists, but no method is defined for this combination of argument types. ... ``` After implementing `sizehint!`, `push!` still fails with a stack overflow. ```julia-repl julia> Base.sizehint!(a::SimpleArray, x) = a julia> push!(SimpleArray{Int}(zeros(Int, 5)), 6) Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable. ERROR: StackOverflowError: Stacktrace: [1] _append! @ ./array.jl:1344 [inlined] [2] append! @ ./array.jl:1335 [inlined] [3] push!(a::SimpleArray{Int64}, iter::Int64) @ Base ./array.jl:1336 --- the above 3 lines are repeated 79982 more times --- [239950] _append! @ ./array.jl:1344 [inlined] [239951] append! @ ./array.jl:1335 [inlined] ``` This is because the new implementation of `append!` depends on `push!`. ## After this pull request, push! is functional. After this pull request, there is a functional `push!` for `SimpleArray` again as in Julia 1.10.4: ```julia-repl julia> push!(SimpleArray{Int}(zeros(Int, 5), 6) 6-element SimpleArray{Int64}: 0 0 0 0 0 6 ``` --- base/abstractarray.jl | 32 ++++++++++++++++++++++++++++++++ test/abstractarray.jl | 9 +++++++++ 2 files changed, 41 insertions(+) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 77aae63399ec8..3f8886e14940c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -3525,6 +3525,35 @@ julia> map(+, [1 2; 3 4], [1,10,100,1000], zeros(3,1)) # iterates until 3rd is """ map(f, it, iters...) = collect(Generator(f, it, iters...)) +# Generic versions of push! for AbstractVector +# These are specialized further for Vector for faster resizing and setindexing +function push!(a::AbstractVector{T}, item) where T + # convert first so we don't grow the array if the assignment won't work + itemT = item isa T ? item : convert(T, item)::T + new_length = length(a) + 1 + resize!(a, new_length) + a[new_length] = itemT + return a +end + +# specialize and optimize the single argument case +function push!(a::AbstractVector{Any}, @nospecialize x) + new_length = length(a) + 1 + resize!(a, new_length) + a[new_length] = x + return a +end +function push!(a::AbstractVector{Any}, @nospecialize x...) + @_terminates_locally_meta + na = length(a) + nx = length(x) + resize!(a, na + nx) + for i = 1:nx + a[na+i] = x[i] + end + return a +end + # multi-item push!, pushfirst! (built on top of type-specific 1-item version) # (note: must not cause a dispatch loop when 1-item case is not defined) push!(A, a, b) = push!(push!(A, a), b) @@ -3532,6 +3561,9 @@ push!(A, a, b, c...) = push!(push!(A, a, b), c...) pushfirst!(A, a, b) = pushfirst!(pushfirst!(A, b), a) pushfirst!(A, a, b, c...) = pushfirst!(pushfirst!(A, c...), a, b) +# sizehint! does not nothing by default +sizehint!(a::AbstractVector, _) = a + ## hashing AbstractArray ## const hash_abstractarray_seed = UInt === UInt64 ? 0x7e2d6fb6448beb77 : 0xd4514ce5 diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 8efe2e64b606c..8b4a1d9113940 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1436,6 +1436,15 @@ using .Main.OffsetArrays end end +@testset "Check push!($a, $args...)" for + a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1)), + args in (("eenie",), ("eenie", "minie"), ("eenie", "minie", "mo")) + orig = copy(a) + push!(a, args...) + @test length(a) == length(orig) + length(args) + @test all(a[end-length(args)+1:end] .== args) +end + @testset "splatting into hvcat" begin t = (1, 2) @test [t...; 3 4] == [1 2; 3 4] From a23aee8c66aaf2c2b35ecb63fe938ae8519f49d9 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:20:03 -0400 Subject: [PATCH 184/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?StyledStrings=20stdlib=20from=20d7496d2=20to=20f6035eb=20(#5546?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: StyledStrings URL: https://github.com/JuliaLang/StyledStrings.jl.git Stdlib branch: main Julia branch: master Old commit: d7496d2 New commit: f6035eb Julia version: 1.12.0-DEV StyledStrings version: 1.11.0(Does not match) Bump invoked by: @LilithHafner Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/StyledStrings.jl/compare/d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa...f6035eb97b516862b16e36cab2ecc6ea8adc3d7c ``` $ git log --oneline d7496d2..f6035eb f6035eb Replace accidental Int64s with Ints 4fcd8bb Use const fields in parser State instead of refs 35a3cdf Load user-customisations lazily 9802b6c Load ScopedValues symbols from their source 9b9cf71 Use branches when choosing how to merge face attrs eada2dc Avoid needlessly creating a new Face in get calls c647af9 Avoid boxing mergedface by making it toplevel a117008 Avoid creating strings for ansi_4bit_color_code 6863348 Improve type inference of face merging f588218 Quick fix for 4d04102adf0d (Optimised SimpleColor) 4d04102 Optimise creation of a SimpleColor from a UInt32 6d3f44d Actually overload Base's escape_string 58507e5 Fully qualify method overloads, avoid importing fc686f3 Explicitly test eachregion c417262 Refactor eachregion to be O(n log n) not O(n^2) f7af623 Use concrete refs in macro parser state struct 41b2446 Check for underline term capability flag 987f776 Treat printing as more than a nothing-return write 43fb018 Add types to some comprehensions d3aa7e1 Improve inference with a function over a closure 6901610 Mention the importance of semantic names in docs 0be209b Better hint at the package capabilities in readme 37b9e4b Load no faces.toml when the DEPOT_PATH is empty ``` Co-authored-by: Dilum Aluthge --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/StyledStrings.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/md5 delete mode 100644 deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/sha512 create mode 100644 deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/md5 create mode 100644 deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/sha512 diff --git a/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/md5 b/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/md5 deleted file mode 100644 index 3a5fccdec0fba..0000000000000 --- a/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -a02cd2c8bedd83b74917cf3821c89f46 diff --git a/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/sha512 b/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/sha512 deleted file mode 100644 index a042e4f306275..0000000000000 --- a/deps/checksums/StyledStrings-d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -2e86daa832533f0369e66e359d7d8f47002f93525f83233c809007a13dfd05a201bcd273b3cb4f3eba2586e98cc9afa43c242f67dc18b91fc898d98a0bd8fde9 diff --git a/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/md5 b/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/md5 new file mode 100644 index 0000000000000..0d39747d275ba --- /dev/null +++ b/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/md5 @@ -0,0 +1 @@ +bf7c157df6084942b794fbe5b768a643 diff --git a/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/sha512 b/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/sha512 new file mode 100644 index 0000000000000..d0a8d6cec08cf --- /dev/null +++ b/deps/checksums/StyledStrings-f6035eb97b516862b16e36cab2ecc6ea8adc3d7c.tar.gz/sha512 @@ -0,0 +1 @@ +ba2f6b91494662208842dec580ea9410d8d6ba4e57315c72e872227f5e2f68cc970fcf5dbd9c8a03920f93b6adabdeaab738fff04f9ca7b5da5cd6b89759e7f6 diff --git a/stdlib/StyledStrings.version b/stdlib/StyledStrings.version index 2067083aec74b..83fbece4c8bc0 100644 --- a/stdlib/StyledStrings.version +++ b/stdlib/StyledStrings.version @@ -1,4 +1,4 @@ STYLEDSTRINGS_BRANCH = main -STYLEDSTRINGS_SHA1 = d7496d24d3f05536bce6a7eb4cd8ca05a75c02aa +STYLEDSTRINGS_SHA1 = f6035eb97b516862b16e36cab2ecc6ea8adc3d7c STYLEDSTRINGS_GIT_URL := https://github.com/JuliaLang/StyledStrings.jl.git STYLEDSTRINGS_TAR_URL = https://api.github.com/repos/JuliaLang/StyledStrings.jl/tarball/$1 From ac425a597460e8188918dbe1e98a789d85e3d284 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Mon, 12 Aug 2024 15:01:03 -0400 Subject: [PATCH 185/206] Bump SparseArrays for SuiteSparse 7.8.0 (#55472) --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + deps/checksums/suitesparse | 70 +++++++++---------- deps/libsuitesparse.version | 4 +- stdlib/SparseArrays.version | 2 +- stdlib/SuiteSparse_jll/Project.toml | 4 +- 10 files changed, 43 insertions(+), 43 deletions(-) create mode 100644 deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/md5 create mode 100644 deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/sha512 delete mode 100644 deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 delete mode 100644 deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 create mode 100644 deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5 create mode 100644 deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/md5 b/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/md5 new file mode 100644 index 0000000000000..7182cc71f7b35 --- /dev/null +++ b/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/md5 @@ -0,0 +1 @@ +2db86c7030acc973d5b46a87f32f7e99 diff --git a/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/sha512 b/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/sha512 new file mode 100644 index 0000000000000..a9e18eac9bfaa --- /dev/null +++ b/deps/checksums/SparseArrays-0dd8d45d55b305458d0d3d3451057589b684f72f.tar.gz/sha512 @@ -0,0 +1 @@ +0d3f54e7e75b48966e1816608d6ddf62175b92a0c778813a562df20750c6ecef9e4ccc24f9f3fffe4051d4b6765332add8c289fcdc598c320f400cec57a223a3 diff --git a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 deleted file mode 100644 index 401900c9f2739..0000000000000 --- a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -7b16893f5a49cee4a4d9219afbb57577 diff --git a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 b/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 deleted file mode 100644 index e8f1bc3c4aaaf..0000000000000 --- a/deps/checksums/SparseArrays-55976a6e4f883a32e3d3658af50c49879b98fce0.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -398028ee8f23ee0b4a5144f5dd03d756cd7575a0b806f351d76339e9521830f75c0c96806a3ee5cebe04853feab51c75c7bcdaaa623acc649bc1a24395df5581 diff --git a/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5 b/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5 new file mode 100644 index 0000000000000..2f81a0d9191b5 --- /dev/null +++ b/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5 @@ -0,0 +1 @@ +46541001073d1c3c85e18d910f8308f3 diff --git a/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512 b/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512 new file mode 100644 index 0000000000000..e2eb44845e276 --- /dev/null +++ b/deps/checksums/SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512 @@ -0,0 +1 @@ +f7470a447b934ca9315e216a07b97e363f11bc93186f9aa057b20b2d05092c58ae4f1b733de362de4a0730861c00be4ca5588d0b3ba65f018c1798b9122b9672 diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index eec27cb539d0f..acec99b39879c 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,36 +1,34 @@ -SuiteSparse-7.7.0.tar.gz/md5/e659373ed5e9b961d2fcb6d67d250783 -SuiteSparse-7.7.0.tar.gz/sha512/aa62dae81ae423ce7162ae83b46e5cf606d95482e6c6bb7ae6d61e15987761119d9418ef3a96648e6ba2327871a2847eef8ace197aa375279d71c80329d6f451 -SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5/46541001073d1c3c85e18d910f8308f3 -SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512/f7470a447b934ca9315e216a07b97e363f11bc93186f9aa057b20b2d05092c58ae4f1b733de362de4a0730861c00be4ca5588d0b3ba65f018c1798b9122b9672 -SuiteSparse.v7.7.0+0.aarch64-apple-darwin.tar.gz/md5/276f7355e36eeab2911a141e5570dede -SuiteSparse.v7.7.0+0.aarch64-apple-darwin.tar.gz/sha512/72aa979c3a4f6d2fa65f4d16ab106a7b306f5e84da91bf04a7a11bd863f71a8386ca5248b7e3fde83347cf912fae8ec3c87617db09f6bfadf12c476061855d28 -SuiteSparse.v7.7.0+0.aarch64-linux-gnu.tar.gz/md5/4c3ab9c8c451198420516bd84fdd079f -SuiteSparse.v7.7.0+0.aarch64-linux-gnu.tar.gz/sha512/7afb088a9b117f79531d828a458419e0e8901daa635eeb1b5c753d60c26784496095f2bf70c5c3dedfc5a1c8dd04c56cd8408667fedcbd06abcec0a41a1171bb -SuiteSparse.v7.7.0+0.aarch64-linux-musl.tar.gz/md5/e12af599488fa7578fb8f2018969f4c5 -SuiteSparse.v7.7.0+0.aarch64-linux-musl.tar.gz/sha512/c9e1c2938754dc3b7704e373f36cc876b592acac06c945860958e56f26e09b7be6ce58c4a9184d3528bcc1458d1f7ab9bd605b9a11083419e849e9fa2cc93f2b -SuiteSparse.v7.7.0+0.armv6l-linux-gnueabihf.tar.gz/md5/a3912a6af26ff19d3fcd166d8426f1ff -SuiteSparse.v7.7.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/5f724f5cfb526f2db7d184976f1711f09f77d548593ef9c28ae98a15b6927303864535761929fcd729448d9ece8a7f599cf82d0a83a7668966bdd8b6b62b641f -SuiteSparse.v7.7.0+0.armv6l-linux-musleabihf.tar.gz/md5/24ab4184bf83e59e029cf950be56f1c5 -SuiteSparse.v7.7.0+0.armv6l-linux-musleabihf.tar.gz/sha512/9f1b05c48b051b3c0440e7075f84105a5c5e8e2c8685d93fac847e1cbbf5427ba623ecde16d9b2293b0c286326bfbce07f8d2906a892065fa9fe3d36a4c0386b -SuiteSparse.v7.7.0+0.armv7l-linux-gnueabihf.tar.gz/md5/8433d1206bc72053c1936a1e5f76ea30 -SuiteSparse.v7.7.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/d5f3249db8bb3a4f216d3abef0416e090c1b4d0a847d814df03f3585159602a31b8e4edffae36c3cc39b5c79691c15d51a085b746f03b86d9a0a9b18d00332d9 -SuiteSparse.v7.7.0+0.armv7l-linux-musleabihf.tar.gz/md5/8651a96c9b5617287c917b07d9f6fb16 -SuiteSparse.v7.7.0+0.armv7l-linux-musleabihf.tar.gz/sha512/3e3f21083a8cd26919d6592be41f531ce4293a9e05a84d5298a4d6c3c222892d6d364c30c75558a1461020ac5446fd51e88a333d03118d74eb28ea33a3386d3b -SuiteSparse.v7.7.0+0.i686-linux-gnu.tar.gz/md5/184c95889dfb07319b9ee51e2ff12d0e -SuiteSparse.v7.7.0+0.i686-linux-gnu.tar.gz/sha512/5424a42418e033c67e0868dd7878990158a9f099f2e3ed04aed45c6ceff0a828080df6eae004e10a3784136f66ac13da46df0b3bb3c96fc32c7bdf02830af41f -SuiteSparse.v7.7.0+0.i686-linux-musl.tar.gz/md5/0bde5fe930ec4e2e90945b6bfd78e8d2 -SuiteSparse.v7.7.0+0.i686-linux-musl.tar.gz/sha512/1ff4c8e578146cca72c1bd74cddbba5999053e5729fdb217b0e4f1c0d5cbcae5a73f466e72a52e92979e5f8cc2549b1c5222c7ca32b628db0b71e129a2d22714 -SuiteSparse.v7.7.0+0.i686-w64-mingw32.tar.gz/md5/5439e41ed1909ffe4ba28669eb45ef43 -SuiteSparse.v7.7.0+0.i686-w64-mingw32.tar.gz/sha512/380999433f0a2c1d65a1bf6ea48da60e6cead831cfc31ab3df0ba122afbc32b2e14fb3d8d578a909b9f39f2763923816a691863756996ea064a595e58a788b98 -SuiteSparse.v7.7.0+0.powerpc64le-linux-gnu.tar.gz/md5/ea08ebbd5aaae629a194450c25a77d2e -SuiteSparse.v7.7.0+0.powerpc64le-linux-gnu.tar.gz/sha512/cfe6675e6a6b7790de8a6a3de2dbf561770fa63113c66890a3f888fba71e20c77edaa89b23cdf0038f3a870be9bd5e351aa84b774e7da833c9c0c90e05c0e9fb -SuiteSparse.v7.7.0+0.x86_64-apple-darwin.tar.gz/md5/314a033b51d6d239e29a91fcca911260 -SuiteSparse.v7.7.0+0.x86_64-apple-darwin.tar.gz/sha512/77147381738484d147ce529b4e9d3dff9bccbe5ed07071b5df647a785f118e46792f739f145d597ef78c871d75759348109ad3e08125fb58dd12b8a6813a8fcc -SuiteSparse.v7.7.0+0.x86_64-linux-gnu.tar.gz/md5/f62f17fc50b15e0a4a117f77c52b35f3 -SuiteSparse.v7.7.0+0.x86_64-linux-gnu.tar.gz/sha512/0ba022a5d0039b1348a09521cc2bd366df8c6603a7d3de4bf7d1b15504add8607bf5fa2bcf7d95b2b48cb676c17cc516903323615b6a668e53310363a3f6b242 -SuiteSparse.v7.7.0+0.x86_64-linux-musl.tar.gz/md5/d9b77034590bb0511f2ea2d726303f94 -SuiteSparse.v7.7.0+0.x86_64-linux-musl.tar.gz/sha512/a1149ec6f50b978b1bad91662035d8d131d431459e1910b2cd9fe0307f50d23ca15148f1af522db04327e8cc9cc7c04f85852ddb606ac82fa346b4ab70d28752 -SuiteSparse.v7.7.0+0.x86_64-unknown-freebsd.tar.gz/md5/7b7f00672f0880e397a5182da084c334 -SuiteSparse.v7.7.0+0.x86_64-unknown-freebsd.tar.gz/sha512/06696d78cd7e385906e2fbfbd8ec804de5a4a3d8134d30bc105f713eb915742204e4226229b33a93740f30a3ff24d48dde651e64a78bc6d937e84ce484f6dd74 -SuiteSparse.v7.7.0+0.x86_64-w64-mingw32.tar.gz/md5/91b2e33ead8c2898881475ddfe202987 -SuiteSparse.v7.7.0+0.x86_64-w64-mingw32.tar.gz/sha512/cb5f2caff872ba2ab66f1285e264b4c28ec0a05a4a0fea3964c22aa167195b57a9d9de2c9b9289438459c6b1c1b9f047807414b3e1305e87642edabd22973bd6 +SuiteSparse-7.8.0.tar.gz/md5/ad42a80d28bb56a1fce15f6e7332e04e +SuiteSparse-7.8.0.tar.gz/sha512/91aff0aee26e938ba88a8f92db15b0db0ecc6ada3b60153bb299f53a45ccda131db4bc66f890c220034c900180d0bb3a5fb3e2686fec7d6174f5900a3ee64424 +SuiteSparse.v7.8.0+0.aarch64-apple-darwin.tar.gz/md5/38379e14a53663a9c23f32ed56801676 +SuiteSparse.v7.8.0+0.aarch64-apple-darwin.tar.gz/sha512/3f2a7aa7778a22d150bad9ecb8d03edfa75707a07545e65660c8ccc4b0a9fb058ccab29e21e4728741d40d390d28922d521d3841e16258cf8e26acacadfc1fbd +SuiteSparse.v7.8.0+0.aarch64-linux-gnu.tar.gz/md5/bc52c7df0a442c0fb9aafb83d60878f4 +SuiteSparse.v7.8.0+0.aarch64-linux-gnu.tar.gz/sha512/436e79ea0774d6ffb571b513e385ef48d9cc70b72010cffdc23d606ad6c8984c8b49e2422ce8881def0722f3f608e4ecb87e6752dd80cf7988addd330c5ded13 +SuiteSparse.v7.8.0+0.aarch64-linux-musl.tar.gz/md5/87e4c2588efc39723621ac5010ddf2e5 +SuiteSparse.v7.8.0+0.aarch64-linux-musl.tar.gz/sha512/17115826716bb48f16e4593941be275d47012d112e54d8826c75fde119ffc9f66accd02353b309365b59779d7af3ac220f31ab7cf7eea165b209a93ecdc4102f +SuiteSparse.v7.8.0+0.armv6l-linux-gnueabihf.tar.gz/md5/b1490603aa129942d8e4c9581853cd0a +SuiteSparse.v7.8.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/e23c3532784e295ae72b811d285c3729c3f8ac1b5ee1621e831b6b2824a5b357e4bfa49e09174de7763fc3ebcab6b84ef16536bc1cf6f4bc0543b1b229209178 +SuiteSparse.v7.8.0+0.armv6l-linux-musleabihf.tar.gz/md5/f8199358882f76dd30bcce741b837de1 +SuiteSparse.v7.8.0+0.armv6l-linux-musleabihf.tar.gz/sha512/2c8d4ec21bfe253d3d32a5f5f09601b9b2864149f63f53067b157f5f7315fb04236bf5b19a1e5b4569e2c73127dcbb1703d56c7d06fc3ab9ae155902b7a1c2a9 +SuiteSparse.v7.8.0+0.armv7l-linux-gnueabihf.tar.gz/md5/cc3aa1a013cc91e7076dddf20fba9f60 +SuiteSparse.v7.8.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/a6b8cfbc345a089f12e55d8d44061dcce30f94c2d79fc520d6c5dfe433ac2e362d049fac72278cb59d4b3760ca08d5e350b7e2658fa5e8c77ce8608f67c2c4c4 +SuiteSparse.v7.8.0+0.armv7l-linux-musleabihf.tar.gz/md5/0d7797d31c30c53bf219cdc0a48e64dc +SuiteSparse.v7.8.0+0.armv7l-linux-musleabihf.tar.gz/sha512/a7df8938ee6a04f62169bedd29c8408951cf33a43e0f529fb4d1e360bdad6462a50b2af297adb5f51fd726e1ced1fc8fcda7feeeafbeb44000bfe02a8e29c29e +SuiteSparse.v7.8.0+0.i686-linux-gnu.tar.gz/md5/e48fa3d2e00f210e964c21e4ff27efae +SuiteSparse.v7.8.0+0.i686-linux-gnu.tar.gz/sha512/3088c2af476285eb8549cf6aa56381156d49513a274348f86fbf01aa9ce0712961471f83fa50b261f3f365a302b88eb20ef0bb35b58c07a2cfb5dc337fdb72c1 +SuiteSparse.v7.8.0+0.i686-linux-musl.tar.gz/md5/e55202dbeca107a0c25a4f09d5d68915 +SuiteSparse.v7.8.0+0.i686-linux-musl.tar.gz/sha512/0f4de2e62016914b4d1bcb9b13bd8cb2bebefc5f0a532e103948b9aae79a20462ac7b74a3e968d4f99076c37dbbafb747699cd151e831ff89d297f78478fb84f +SuiteSparse.v7.8.0+0.i686-w64-mingw32.tar.gz/md5/cb971bc1042196e527f95015c8bc5ef8 +SuiteSparse.v7.8.0+0.i686-w64-mingw32.tar.gz/sha512/d445a7790e3ac5392f75c9f4ec30cd1c812354b04388b4c6c6cea2423d2f0dac7173b17a8a2b7a7f4af10321601f96819a7702f9beac0397d85916d99493bc39 +SuiteSparse.v7.8.0+0.powerpc64le-linux-gnu.tar.gz/md5/12058f122b548a37070770d1847f3ce9 +SuiteSparse.v7.8.0+0.powerpc64le-linux-gnu.tar.gz/sha512/f375feeb8448ea90ce8d9f31c7e1230f6868316f06094ba0155069dded4f8da2e1b54d462ef9cfc77abd76147740d4066236dcf1fcea91f8a7141819962ad0ae +SuiteSparse.v7.8.0+0.x86_64-apple-darwin.tar.gz/md5/1bd473f2a25f1ebcea8acc858e2594b4 +SuiteSparse.v7.8.0+0.x86_64-apple-darwin.tar.gz/sha512/034af137deee5bf0ebf3746745d09ad50ce135cd4768a2049bb9811478ff90e6ed8e2c990e277b4c3b38a3a5e9eaa856938eb86239ca445fa64b6dab6af7e996 +SuiteSparse.v7.8.0+0.x86_64-linux-gnu.tar.gz/md5/c58a86d9f25e6705941105d9e41f084c +SuiteSparse.v7.8.0+0.x86_64-linux-gnu.tar.gz/sha512/56447062802f01815ffb014624423c6fd3ab6e16b642b2fe37972a151b02865965c95ca3d1a455c6d51cd31633aea8a732b235b55d68e6779c17b293c488fa43 +SuiteSparse.v7.8.0+0.x86_64-linux-musl.tar.gz/md5/ba6e10ba61c209df94f18ab51fe2dd90 +SuiteSparse.v7.8.0+0.x86_64-linux-musl.tar.gz/sha512/3b8fc504cfb4a3b628d5b955a482bad08c85e09e529f833855a84b847721247aaa469f96adef6b218a1ba5896cde91664cc819ba33115e3cc309e72140841ca3 +SuiteSparse.v7.8.0+0.x86_64-unknown-freebsd.tar.gz/md5/a50c69142a42c14edac4ce94b86b138a +SuiteSparse.v7.8.0+0.x86_64-unknown-freebsd.tar.gz/sha512/963be0dccd1a594df08fe5135ef4ac13e1d707841c3e97d31ba5477d0d6ec26bad9be1c52d9fd78f199740a53950353adbdd767469f3bf01ea1e3ee843eb6c1a +SuiteSparse.v7.8.0+0.x86_64-w64-mingw32.tar.gz/md5/7ca11ba89bd09183cc5a9320d6e8a4a7 +SuiteSparse.v7.8.0+0.x86_64-w64-mingw32.tar.gz/sha512/e1d5def1103bbf0bb29c08cdd3bf21ba60456353694985c66f8e55a31d54a32c5b891e56e1ffe30f9e1223c49283d267e483e2f1b999f566099c239b3eed1d78 diff --git a/deps/libsuitesparse.version b/deps/libsuitesparse.version index 3131908a4a298..6f841190cebc7 100644 --- a/deps/libsuitesparse.version +++ b/deps/libsuitesparse.version @@ -4,5 +4,5 @@ LIBSUITESPARSE_JLL_NAME := SuiteSparse ## source build -LIBSUITESPARSE_VER := 7.7.0 -LIBSUITESPARSE_SHA1=13806726cbf470914d012d132a85aea1aff9ee77 +LIBSUITESPARSE_VER := 7.8.0 +LIBSUITESPARSE_SHA1=58e6558408f6a51c08e35a5557d5e68cae32147e diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 2dc7bd8f5b3b9..019306a3e9f65 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = main -SPARSEARRAYS_SHA1 = 55976a6e4f883a32e3d3658af50c49879b98fce0 +SPARSEARRAYS_SHA1 = 0dd8d45d55b305458d0d3d3451057589b684f72f SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index 314208ffc344c..39b8447138a2d 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.7.0+0" +version = "7.8.0+0" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93" @@ -8,7 +8,7 @@ Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [compat] -julia = "1.11" +julia = "1.12" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 96fd25a764c316e9e09dfd7de8e84d854a73b2cd Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 12 Aug 2024 23:07:40 -0400 Subject: [PATCH 186/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?JuliaSyntaxHighlighting=20stdlib=20from=2004b2323=20to=20b89dd9?= =?UTF-8?q?9=20(#55474)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: JuliaSyntaxHighlighting URL: https://github.com/julialang/JuliaSyntaxHighlighting.jl.git Stdlib branch: main Julia branch: master Old commit: 04b2323 New commit: b89dd99 Julia version: 1.12.0-DEV JuliaSyntaxHighlighting version: 1.12.0 Bump invoked by: @tecosaur Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/julialang/JuliaSyntaxHighlighting.jl/compare/04b2323c41f6422464c838fe9045700e9ee75e95...b89dd99db56700c47434df6106b6c6afd1c9ed01 ``` $ git log --oneline 04b2323..b89dd99 b89dd99 Actually use the syntax_errors argument fee6aa5 Use a mutable type instead of ref fields ``` Co-authored-by: Dilum Aluthge --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/JuliaSyntaxHighlighting.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 delete mode 100644 deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 create mode 100644 deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/md5 create mode 100644 deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/sha512 diff --git a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 deleted file mode 100644 index 518e2705544ed..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -956fe26df1daca727ec15bfbc175584f diff --git a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 deleted file mode 100644 index 786dd666f2927..0000000000000 --- a/deps/checksums/JuliaSyntaxHighlighting-04b2323c41f6422464c838fe9045700e9ee75e95.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -20c7990134634dd252909dfa2c43f7b77d427a77f1b726eefdc47781fc3ad46152e81e612d4091541ffb32323154cb5a696157cd24d7a71087d5883720e03728 diff --git a/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/md5 b/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/md5 new file mode 100644 index 0000000000000..cbcb8097d1673 --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/md5 @@ -0,0 +1 @@ +3dc1387ed88ba3c0df04d05a86d804d0 diff --git a/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/sha512 b/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/sha512 new file mode 100644 index 0000000000000..2e58061d16058 --- /dev/null +++ b/deps/checksums/JuliaSyntaxHighlighting-b89dd99db56700c47434df6106b6c6afd1c9ed01.tar.gz/sha512 @@ -0,0 +1 @@ +fe30ed73b257e6928097cb7baca5b82a9a60b2f9b9f219fbcf570c5ed513447f0fda2a48da06b57e381516a69278f7f8519764d00e9e4fb5683a5411e245ef45 diff --git a/stdlib/JuliaSyntaxHighlighting.version b/stdlib/JuliaSyntaxHighlighting.version index b076cfa26b5aa..280db66afe5f9 100644 --- a/stdlib/JuliaSyntaxHighlighting.version +++ b/stdlib/JuliaSyntaxHighlighting.version @@ -1,4 +1,4 @@ JULIASYNTAXHIGHLIGHTING_BRANCH = main -JULIASYNTAXHIGHLIGHTING_SHA1 = 04b2323c41f6422464c838fe9045700e9ee75e95 +JULIASYNTAXHIGHLIGHTING_SHA1 = b89dd99db56700c47434df6106b6c6afd1c9ed01 JULIASYNTAXHIGHLIGHTING_GIT_URL := https://github.com/julialang/JuliaSyntaxHighlighting.jl.git JULIASYNTAXHIGHLIGHTING_TAR_URL = https://api.github.com/repos/julialang/JuliaSyntaxHighlighting.jl/tarball/$1 From 5eda5972269558cb811ec695e399eb14579535c8 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 13 Aug 2024 16:44:41 +0200 Subject: [PATCH 187/206] make the previous active module in the REPL a non-global (#55418) The intent of the active module seems to have been for it to be REPL specific but this global kind of breaks that. Co-authored-by: KristofferC --- stdlib/REPL/src/LineEdit.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 1f6a782a23397..5af03e0df9b6d 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -66,6 +66,7 @@ show(io::IO, x::Prompt) = show(io, string("Prompt(\"", prompt_string(x.prompt), mutable struct MIState interface::ModalInterface active_module::Module + previous_active_module::Module current_mode::TextInterface aborted::Bool mode_state::IdDict{TextInterface,ModeState} @@ -78,7 +79,7 @@ mutable struct MIState async_channel::Channel{Function} end -MIState(i, mod, c, a, m) = MIState(i, mod, c, a, m, String[], 0, Char[], 0, :none, :none, Channel{Function}()) +MIState(i, mod, c, a, m) = MIState(i, mod, mod, c, a, m, String[], 0, Char[], 0, :none, :none, Channel{Function}()) const BufferLike = Union{MIState,ModeState,IOBuffer} const State = Union{MIState,ModeState} @@ -1510,13 +1511,11 @@ end current_word_with_dots(s::MIState) = current_word_with_dots(buffer(s)) -previous_active_module::Module = Main - function activate_module(s::MIState) word = current_word_with_dots(s); empty = isempty(word) mod = if empty - previous_active_module + s.previous_active_module else try Base.Core.eval(Base.active_module(), Base.Meta.parse(word)) @@ -1532,7 +1531,7 @@ function activate_module(s::MIState) if Base.active_module() == Main || mod == Main # At least one needs to be Main. Disallows toggling between two non-Main modules because it's # otherwise hard to get back to Main - global previous_active_module = Base.active_module() + s.previous_active_module = Base.active_module() end REPL.activate(mod) edit_clear(s) From 881be64de02e690f0753fb404647d216d839153d Mon Sep 17 00:00:00 2001 From: matthias314 <56549971+matthias314@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:45:19 -0400 Subject: [PATCH 188/206] fix hierarchy level of "API reference" in `Dates` documentation (#55483) Currently, "API reference" is at the same level as "Dates" although it is a subsection of it. This looks particularly weird in the PDF version of the manual: Section 67 is "Dates" and Section 68 is "API reference". Note that I didn't change the nesting level of the subsection "Constants" at the end of the file. As a result, it is now at the same level as "Dates and Time Types" and "Dates Functions". Before it was a subsection of the latter, which appears wrong to me. --- stdlib/Dates/docs/src/index.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index 545dbd90775df..38b4f7ae86d29 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -684,9 +684,9 @@ value in the days field is uncertain. See the [API reference](@ref stdlib-dates-api) for additional information on methods exported from the `Dates` module. -# [API reference](@id stdlib-dates-api) +## [API reference](@id stdlib-dates-api) -## Dates and Time Types +### Dates and Time Types ```@docs Dates.Period @@ -701,7 +701,7 @@ Dates.TimeZone Dates.UTC ``` -## Dates Functions +### Dates Functions ```@docs Dates.DateTime(::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64, ::Int64) @@ -730,7 +730,7 @@ Dates.now(::Type{Dates.UTC}) Base.eps(::Union{Type{DateTime}, Type{Date}, Type{Time}, TimeType}) ``` -### Accessor Functions +#### Accessor Functions ```@docs Dates.year @@ -758,7 +758,7 @@ Dates.monthday Dates.yearmonthday ``` -### Query Functions +#### Query Functions ```@docs Dates.dayname @@ -777,7 +777,7 @@ Dates.quarterofyear Dates.dayofquarter ``` -### Adjuster Functions +#### Adjuster Functions ```@docs Base.trunc(::Dates.TimeType, ::Type{Dates.Period}) @@ -797,7 +797,7 @@ Dates.tonext(::Function, ::Dates.TimeType) Dates.toprev(::Function, ::Dates.TimeType) ``` -### Periods +#### Periods ```@docs Dates.Period(::Any) @@ -808,7 +808,7 @@ Dates.default Dates.periods ``` -### Rounding Functions +#### Rounding Functions `Date` and `DateTime` values can be rounded to a specified resolution (e.g., 1 month or 15 minutes) with `floor`, `ceil`, or `round`. @@ -837,7 +837,7 @@ Dates.date2epochdays Dates.datetime2epochms ``` -### Conversion Functions +#### Conversion Functions ```@docs Dates.today From b7aa5e37402e2a0c81f9f2b80e89cf0f85ff6da6 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Tue, 13 Aug 2024 11:46:04 -0400 Subject: [PATCH 189/206] simplify complex atanh and remove singularity perturbation (#55268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes https://github.com/JuliaLang/julia/issues/55266, and use `inv(z)` rather than `1/z` and use `muladd` in a couple places. --------- Co-authored-by: Mosè Giordano --- base/complex.jl | 17 +++++++---------- test/complex.jl | 6 ++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 8ac126d2c6532..095c842795d38 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1037,24 +1037,22 @@ end function atanh(z::Complex{T}) where T z = float(z) Tf = float(T) - Ω = prevfloat(typemax(Tf)) - θ = sqrt(Ω)/4 - ρ = 1/θ x, y = reim(z) ax = abs(x) ay = abs(y) + θ = sqrt(floatmax(Tf))/4 if ax > θ || ay > θ #Prevent overflow if isnan(y) if isinf(x) return Complex(copysign(zero(x),x), y) else - return Complex(real(1/z), y) + return Complex(real(inv(z)), y) end end if isinf(y) return Complex(copysign(zero(x),x), copysign(oftype(y,pi)/2, y)) end - return Complex(real(1/z), copysign(oftype(y,pi)/2, y)) + return Complex(real(inv(z)), copysign(oftype(y,pi)/2, y)) end β = copysign(one(Tf), x) z *= β @@ -1064,16 +1062,15 @@ function atanh(z::Complex{T}) where T ξ = oftype(x, Inf) η = y else - ym = ay+ρ - ξ = log(sqrt(sqrt(4+y*y))/sqrt(ym)) - η = copysign(oftype(y,pi)/2 + atan(ym/2), y)/2 + ξ = log(sqrt(sqrt(muladd(y, y, 4)))/sqrt(ay)) + η = copysign(oftype(y,pi)/2 + atan(ay/2), y)/2 end else #Normal case - ysq = (ay+ρ)^2 + ysq = ay^2 if x == 0 ξ = x else - ξ = log1p(4x/((1-x)^2 + ysq))/4 + ξ = log1p(4x/(muladd(1-x, 1-x, ysq)))/4 end η = angle(Complex((1-x)*(1+x)-ysq, 2y))/2 end diff --git a/test/complex.jl b/test/complex.jl index d798cfe16489c..63304652ee7d8 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -1215,3 +1215,9 @@ end @test !iseven(7+0im) && isodd(7+0im) @test !iseven(6+1im) && !isodd(7+1im) end + +@testset "issue #55266" begin + for T in (Float16, Float32, Float64) + @test isapprox(atanh(1+im*floatmin(T)), Complex{T}(atanh(1+im*big(floatmin(T))))) + end +end From 2a4e2b1d95c15654eea7965f123f72890b84e594 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 14 Aug 2024 11:34:06 -0400 Subject: [PATCH 190/206] fix Event to use normal Condition variable (#55441) ThreadSynchronizer is only for things that are very trivial, as there are a lot of things they are forbidden from doing (such as waiting for a Task to set it). Happened to notice while reviewing https://github.com/JuliaLang/julia/pull/55439#pullrequestreview-2231026949 that this was still using the pre-v1.2 style lock, which makes this mostly useless in v1.4+ --- base/lock.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/lock.jl b/base/lock.jl index 7cbb023a78ee4..b69f3c5c03638 100644 --- a/base/lock.jl +++ b/base/lock.jl @@ -498,10 +498,10 @@ This provides an acquire & release memory ordering on notify/wait. The `autoreset` functionality and memory ordering guarantee requires at least Julia 1.8. """ mutable struct Event - const notify::ThreadSynchronizer + const notify::Threads.Condition const autoreset::Bool @atomic set::Bool - Event(autoreset::Bool=false) = new(ThreadSynchronizer(), autoreset, false) + Event(autoreset::Bool=false) = new(Threads.Condition(), autoreset, false) end function wait(e::Event) From c7309d05c16ba9a42a60eee3a03650d3d42a158b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 14 Aug 2024 17:05:05 -0400 Subject: [PATCH 191/206] subtyping: fast path for lhs union and rhs typevar (#55413) Fixes #55230 --- src/subtype.c | 16 +++++++++++- test/subtype.jl | 67 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 6f6520c5df980..4118bbeab649b 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1312,7 +1312,21 @@ static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e); static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) { if (jl_is_uniontype(x)) { - if (x == y) return 1; + if (obviously_egal(x, y)) + return 1; + if (e->Runions.depth == 0 && jl_is_typevar(y) && !jl_has_free_typevars(x) && !jl_has_free_typevars(((jl_tvar_t*)y)->ub)) { + // Similar to fast path for repeated elements: if there have been no outer + // unions on the right, and the right side is a typevar, then we can handle the + // typevar first before picking a union element, under the theory that it may + // be easy to match or reject this whole union in comparing and setting the lb + // and ub of the variable binding, without needing to examine each element. + // However, if x contains any free typevars, then each element with a free + // typevar must be handled separately from the union of all elements without + // free typevars, since the typevars presence might lead to those elements + // getting eliminated (omit_bad_union) or degenerate (Union{Ptr{T}, Ptr}) or + // combined (Union{T, S} where {T, S <: T}). + return subtype_var((jl_tvar_t*)y, x, e, 1, param); + } x = pick_union_element(x, e, 0); } if (jl_is_uniontype(y)) { diff --git a/test/subtype.jl b/test/subtype.jl index af023ef8ca72f..7be869107b432 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -707,16 +707,17 @@ macro testintersect(a, b, result) a = esc(a) b = esc(b) result = esc(result) - Base.remove_linenums!(quote + # use a manual macrocall expression since Test will examine this __source__ value + return quote # test real intersect - @test $cmp(_type_intersect($a, $b), $result) - @test $cmp(_type_intersect($b, $a), $result) + $(Expr(:macrocall, :var"@test", __source__, :($cmp(_type_intersect($a, $b), $result)))) + $(Expr(:macrocall, :var"@test", __source__, :($cmp(_type_intersect($b, $a), $result)))) # test simplified intersect if !($result === Union{}) - @test typeintersect($a, $b) != Union{} - @test typeintersect($b, $a) != Union{} + $(Expr(:macrocall, :var"@test", __source__, :(typeintersect($a, $b) != Union{}))) + $(Expr(:macrocall, :var"@test", __source__, :(typeintersect($b, $a) != Union{}))) end - end) + end end abstract type IT4805_2{N, T} end @@ -2267,31 +2268,46 @@ let S = Tuple{Integer, U} where {II<:Array, U<:Tuple{Vararg{II, 1}}} @testintersect(S, Tuple{Int, U} where {N, U<:Tuple{Any,Any,Vararg{Any,N}}}, Union{}) end +function equal_envs(env1, env2) + length(env1) == length(env2) || return false + for i = 1:length(env1) + a = env1[i] + b = env2[i] + if a isa TypeVar + if !(b isa TypeVar && a.name == b.name && a.lb == b.lb && a.ub == b.ub) + return false + end + elseif !(a == b) + return false + end + end + return true +end + # issue #43064 let - env_tuple(@nospecialize(x), @nospecialize(y)) = (intersection_env(x, y)[2]...,) - all_var(x::UnionAll) = (x.var, all_var(x.body)...) - all_var(x::DataType) = () + env_tuple(@nospecialize(x), @nospecialize(y)) = intersection_env(x, y)[2] TT0 = Tuple{Type{T},Union{Real,Missing,Nothing}} where {T} TT1 = Union{Type{Int8},Type{Int16}} @test env_tuple(Tuple{TT1,Missing}, TT0) === env_tuple(Tuple{TT1,Nothing}, TT0) === - env_tuple(Tuple{TT1,Int}, TT0) === all_var(TT0) + env_tuple(Tuple{TT1,Int}, TT0) === + Core.svec(TT0.var) TT0 = Tuple{T1,T2,Union{Real,Missing,Nothing}} where {T1,T2} TT1 = Tuple{T1,T2,Union{Real,Missing,Nothing}} where {T2,T1} TT2 = Tuple{Union{Int,Int8},Union{Int,Int8},Int} TT3 = Tuple{Int,Union{Int,Int8},Int} - @test env_tuple(TT2, TT0) === all_var(TT0) - @test env_tuple(TT2, TT1) === all_var(TT1) - @test env_tuple(TT3, TT0) === Base.setindex(all_var(TT0), Int, 1) - @test env_tuple(TT3, TT1) === Base.setindex(all_var(TT1), Int, 2) + @test equal_envs(env_tuple(TT2, TT0), Core.svec(TypeVar(:T1, Union{Int, Int8}), TypeVar(:T2, Union{Int, Int8}))) + @test equal_envs(env_tuple(TT2, TT1), Core.svec(TypeVar(:T2, Union{Int, Int8}), TypeVar(:T1, Union{Int, Int8}))) + @test equal_envs(env_tuple(TT3, TT0), Core.svec(Int, TypeVar(:T2, Union{Int, Int8}))) + @test equal_envs(env_tuple(TT3, TT1), Core.svec(TypeVar(:T2, Union{Int, Int8}), Int)) TT0 = Tuple{T1,T2,T1,Union{Real,Missing,Nothing}} where {T1,T2} TT1 = Tuple{T1,T2,T1,Union{Real,Missing,Nothing}} where {T2,T1} TT2 = Tuple{Int,Union{Int,Int8},Int,Int} - @test env_tuple(TT2, TT0) === Base.setindex(all_var(TT0), Int, 1) - @test env_tuple(TT2, TT1) === Base.setindex(all_var(TT1), Int, 2) + @test equal_envs(env_tuple(TT2, TT0), Core.svec(Int, TypeVar(:T2, Union{Int, Int8}))) + @test equal_envs(env_tuple(TT2, TT1), Core.svec(TypeVar(:T2, Union{Int, Int8}), Int)) end #issue #46735 @@ -2686,3 +2702,22 @@ let S = Tuple{Val{<:T}, Union{Int,T}} where {T}, @testintersect(S, T, !Union{}) @test !Base.has_free_typevars(typeintersect(S, T)) end + +#issue 55230 +let T1 = NTuple{12, Union{Val{1}, Val{2}, Val{3}, Val{4}, Val{5}, Val{6}}} + T2 = Tuple{<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any} + @test T1 <: T2 + T2 = Tuple{<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Val} + @test T1 <: T2 + T2 = Tuple{<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Real} + @test !(T1 <: T2) + T2 = Tuple{<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Union{Val,Real}} + @test T1 <: T2 + T2 = Tuple{<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Union{String,Real}} + @test !(T1 <: T2) + T2 = Tuple{<:Union{Val,Real},<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any} + @test T1 <: T2 + T2 = Tuple{<:Union{String,Real},<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any,<:Any} + @test !(T1 <: T2) + @test Tuple{Union{Val{1},Val{2}}} <: Tuple{S} where {T, S<:Val{T}} +end From e1aefebe1e3c62339be4b46043625170ec538137 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Wed, 14 Aug 2024 21:23:43 -0500 Subject: [PATCH 192/206] Do not load `ScopedValues` with `using` (#55452) Stop loading `ScopedValues` with `using` so folks use `ScopedValues.with` or `using ScopedValues` rather than `Base.with`. Implements https://github.com/JuliaLang/julia/pull/55095#issuecomment-2272334437 ~Have to bump the StyledStrings stdlib to include https://github.com/JuliaLang/StyledStrings.jl/pull/80~ Done --------- Co-authored-by: Dilum Aluthge --- base/Base.jl | 1 - base/logging/logging.jl | 2 +- base/mpfr.jl | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 221ab90d8d2a9..082fb55a00ef0 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -424,7 +424,6 @@ include("weakkeydict.jl") # ScopedValues include("scopedvalues.jl") -using .ScopedValues # metaprogramming include("meta.jl") diff --git a/base/logging/logging.jl b/base/logging/logging.jl index c50f581db89ba..5cf3882a300ec 100644 --- a/base/logging/logging.jl +++ b/base/logging/logging.jl @@ -3,7 +3,7 @@ module CoreLogging import Base: isless, +, -, convert, show -import Base: ScopedValue, with, @with +import Base.ScopedValues: ScopedValue, with, @with export AbstractLogger, diff --git a/base/mpfr.jl b/base/mpfr.jl index ed3ea5937ce87..d393469aa26a1 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -109,9 +109,9 @@ end tie_breaker_is_to_even(::MPFRRoundingMode) = true const ROUNDING_MODE = Ref{MPFRRoundingMode}(MPFRRoundNearest) -const CURRENT_ROUNDING_MODE = Base.ScopedValue{MPFRRoundingMode}() +const CURRENT_ROUNDING_MODE = Base.ScopedValues.ScopedValue{MPFRRoundingMode}() const DEFAULT_PRECISION = Ref{Clong}(256) -const CURRENT_PRECISION = Base.ScopedValue{Clong}() +const CURRENT_PRECISION = Base.ScopedValues.ScopedValue{Clong}() # Basic type and initialization definitions # Warning: the constants are MPFR implementation details from @@ -162,7 +162,7 @@ significand_limb_count(x::BigFloat) = div(sizeof(x._d), sizeof(Limb), RoundToZer rounding_raw(::Type{BigFloat}) = something(Base.ScopedValues.get(CURRENT_ROUNDING_MODE), ROUNDING_MODE[]) setrounding_raw(::Type{BigFloat}, r::MPFRRoundingMode) = ROUNDING_MODE[]=r function setrounding_raw(f::Function, ::Type{BigFloat}, r::MPFRRoundingMode) - Base.@with(CURRENT_ROUNDING_MODE => r, f()) + Base.ScopedValues.@with(CURRENT_ROUNDING_MODE => r, f()) end @@ -1109,7 +1109,7 @@ Note: `nextfloat()`, `prevfloat()` do not use the precision mentioned by The `base` keyword requires at least Julia 1.8. """ function setprecision(f::Function, ::Type{BigFloat}, prec::Integer; base::Integer=2) - Base.@with(CURRENT_PRECISION => _convert_precision_from_base(prec, base), f()) + Base.ScopedValues.@with(CURRENT_PRECISION => _convert_precision_from_base(prec, base), f()) end setprecision(f::Function, prec::Integer; base::Integer=2) = setprecision(f, BigFloat, prec; base) From b4ebb0018e4dcfbbb9c840fb7097e7d7a5e0ad5e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 15 Aug 2024 07:34:30 -0400 Subject: [PATCH 193/206] build: add missing dependencies for expmap (#55492) I was confused why https://github.com/JuliaLang/julia/issues/49121 was re-occuring locally, until I noticed this file was not getting rebuilt. --- cli/Makefile | 2 +- src/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/Makefile b/cli/Makefile index bbe722f6f4816..7b8d3587f5386 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -152,7 +152,7 @@ $(build_bindir)/julia$(EXE): $(EXE_OBJS) $(build_shlibdir)/libjulia.$(SHLIB_EXT) $(build_bindir)/julia-debug$(EXE): $(EXE_DOBJS) $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT) | $(build_bindir) @$(call PRINT_LINK, $(CC) $(LOADER_CFLAGS) $(DEBUGFLAGS) $(EXE_DOBJS) -o $@ $(LOADER_LDFLAGS) $(RPATH) -ljulia-debug) -$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in +$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in $(JULIAHOME)/VERSION sed <'$<' >'$@' -e 's/@JULIA_SHLIB_SYMBOL_VERSION@/JL_LIBJULIA_$(SOMAJOR)/' clean: | $(CLEAN_TARGETS) diff --git a/src/Makefile b/src/Makefile index 6f78f4a8b6aa1..52e673aa6cc1a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -385,7 +385,7 @@ $(BUILDDIR)/julia_version.h: $(JULIAHOME)/VERSION CXXLD = $(CXX) -shared -$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in +$(BUILDDIR)/julia.expmap: $(SRCDIR)/julia.expmap.in $(JULIAHOME)/VERSION $(LLVM_CONFIG_ABSOLUTE) sed <'$<' >'$@' -e "s/@JULIA_SHLIB_SYMBOL_VERSION@/JL_LIBJULIA_$(SOMAJOR)/" \ -e "s/@LLVM_SHLIB_SYMBOL_VERSION@/$(LLVM_SHLIB_SYMBOL_VERSION)/" From 67c1723ffbb1ab31d15e72a61bf8856e83079311 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 15 Aug 2024 08:57:26 -0400 Subject: [PATCH 194/206] handle async termination better (#55440) Fixes #55235 Disables the assertion failure in the scheduler, so that we are more likely to be able to report the underlying failure and run atexit handlers successfully. This should clean up some of the error messages that occur on timeout. ``` julia> sleep(5) ^\ [89829] signal 3: Quit: 3 in expression starting at REPL[1]:1 kevent at /usr/lib/system/libsystem_kernel.dylib (unknown line) unknown function (ip: 0x0) Allocations: 830502 (Pool: 830353; Big: 149); GC: 1 Quit: 3 ``` --- base/Base.jl | 2 +- base/condition.jl | 2 +- base/initdefs.jl | 5 +++++ base/stream.jl | 4 ++-- base/task.jl | 34 +++++++++++++++++++--------------- src/scheduler.c | 15 +++++++++++++++ src/signal-handling.c | 15 ++++++++++----- stdlib/Sockets/src/Sockets.jl | 2 +- stdlib/Sockets/src/addrinfo.jl | 4 ++-- 9 files changed, 56 insertions(+), 27 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 082fb55a00ef0..081426fa94d67 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -626,7 +626,7 @@ function start_profile_listener() # this will prompt any ongoing or pending event to flush also close(cond) # error-propagation is not needed, since the errormonitor will handle printing that better - _wait(t) + t === current_task() || _wait(t) end finalizer(cond) do c # if something goes south, still make sure we aren't keeping a reference in C to this diff --git a/base/condition.jl b/base/condition.jl index 52781f348eb0d..bc14b17b3ac6b 100644 --- a/base/condition.jl +++ b/base/condition.jl @@ -138,7 +138,7 @@ function wait(c::GenericCondition; first::Bool=false) try return wait() catch - ct.queue === nothing || list_deletefirst!(ct.queue::IntrusiveLinkedList{Task}, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) rethrow() finally relockall(c.lock, token) diff --git a/base/initdefs.jl b/base/initdefs.jl index aa2ea67528da9..707c96a2444d6 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -438,6 +438,11 @@ function atexit(f::Function) end function _atexit(exitcode::Cint) + # this current task shouldn't be scheduled anywhere, but if it was (because + # this exit came from a signal for example), then try to clear that state + # to minimize scheduler issues later + ct = current_task() + q = ct.queue; q === nothing || list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) # Don't hold the lock around the iteration, just in case any other thread executing in # parallel tries to register a new atexit hook while this is running. We don't want to # block that thread from proceeding, and we can allow it to register its hook which we diff --git a/base/stream.jl b/base/stream.jl index a45307b883da8..93aeead79eb9c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -462,7 +462,7 @@ function closewrite(s::LibuvStream) # try-finally unwinds the sigatomic level, so need to repeat sigatomic_end sigatomic_end() iolock_begin() - ct.queue === nothing || list_deletefirst!(ct.queue::IntrusiveLinkedList{Task}, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) if uv_req_data(req) != C_NULL # req is still alive, # so make sure we won't get spurious notifications later @@ -1076,7 +1076,7 @@ function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) # try-finally unwinds the sigatomic level, so need to repeat sigatomic_end sigatomic_end() iolock_begin() - ct.queue === nothing || list_deletefirst!(ct.queue::IntrusiveLinkedList{Task}, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) if uv_req_data(uvw) != C_NULL # uvw is still alive, # so make sure we won't get spurious notifications later diff --git a/base/task.jl b/base/task.jl index ae99a71585c85..5e4af6747f128 100644 --- a/base/task.jl +++ b/base/task.jl @@ -320,6 +320,7 @@ end # just wait for a task to be done, no error propagation function _wait(t::Task) + t === current_task() && Core.throw(ConcurrencyViolationError("deadlock detected: cannot wait on current task")) if !istaskdone(t) donenotify = t.donenotify::ThreadSynchronizer lock(donenotify) @@ -374,7 +375,6 @@ in an error, thrown as a [`TaskFailedException`](@ref) which wraps the failed ta Throws a `ConcurrencyViolationError` if `t` is the currently running task, to prevent deadlocks. """ function wait(t::Task; throw=true) - t === current_task() && Core.throw(ConcurrencyViolationError("deadlock detected: cannot wait on current task")) _wait(t) if throw && istaskfailed(t) Core.throw(TaskFailedException(t)) @@ -813,12 +813,15 @@ macro sync_add(expr) end end -throwto_repl_task(@nospecialize val) = throwto(getfield(active_repl_backend, :backend_task)::Task, val) - -function is_repl_running() - return isdefined(Base, :active_repl_backend) && - (getfield(active_repl_backend, :backend_task)::Task)._state === task_state_runnable && - getfield(active_repl_backend, :in_eval) +function repl_backend_task() + @isdefined(active_repl_backend) || return + backend = active_repl_backend + isdefined(backend, :backend_task) || return + backend_task = getfield(active_repl_backend, :backend_task)::Task + if backend_task._state === task_state_runnable && getfield(backend, :in_eval) + return backend_task + end + return end # runtime system hook called when a task finishes @@ -842,8 +845,9 @@ function task_done_hook(t::Task) end if err && !handled && Threads.threadid() == 1 - if isa(result, InterruptException) && isempty(Workqueue) && is_repl_running() - throwto_repl_task(result) + if isa(result, InterruptException) && isempty(Workqueue) + backend = repl_backend_task() + backend isa Task && throwto(backend, result) end end # Clear sigatomic before waiting @@ -854,11 +858,11 @@ function task_done_hook(t::Task) # If an InterruptException happens while blocked in the event loop, try handing # the exception to the REPL task since the current task is done. # issue #19467 - if Threads.threadid() == 1 && isa(e, InterruptException) && isempty(Workqueue) && is_repl_running() - throwto_repl_task(e) - else - rethrow() + if Threads.threadid() == 1 && isa(e, InterruptException) && isempty(Workqueue) + backend = repl_backend_task() + backend isa Task && throwto(backend, e) end + rethrow() # this will terminate the program end end @@ -1032,7 +1036,7 @@ function schedule(t::Task, @nospecialize(arg); error=false) # schedule a task to be (re)started with the given value or exception t._state === task_state_runnable || Base.error("schedule: Task not runnable") if error - t.queue === nothing || Base.list_deletefirst!(t.queue::IntrusiveLinkedList{Task}, t) + q = t.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, t) setfield!(t, :result, arg) setfield!(t, :_isexception, true) else @@ -1056,7 +1060,7 @@ function yield() try wait() catch - ct.queue === nothing || list_deletefirst!(ct.queue::IntrusiveLinkedList{Task}, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) rethrow() end end diff --git a/src/scheduler.c b/src/scheduler.c index 3505e935afcf6..3cf97ba108873 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -199,6 +199,21 @@ static int sleep_check_after_threshold(uint64_t *start_cycles) JL_NOTSAFEPOINT return 0; } +void surprise_wakeup(jl_ptls_t ptls) JL_NOTSAFEPOINT +{ + // equivalent to wake_thread, without the assert on wasrunning + int8_t state = jl_atomic_load_relaxed(&ptls->sleep_check_state); + if (state == sleeping) { + if (jl_atomic_cmpswap_relaxed(&ptls->sleep_check_state, &state, not_sleeping)) { + // this notification will never be consumed, so we may have now + // introduced some inaccuracy into the count, but that is + // unavoidable with any asynchronous interruption + jl_atomic_fetch_add_relaxed(&n_threads_running, 1); + } + } +} + + static int set_not_sleeping(jl_ptls_t ptls) JL_NOTSAFEPOINT { if (jl_atomic_load_relaxed(&ptls->sleep_check_state) != not_sleeping) { diff --git a/src/signal-handling.c b/src/signal-handling.c index febf05b653662..6835f5fa364c5 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -427,6 +427,8 @@ void jl_show_sigill(void *_ctx) #endif } +void surprise_wakeup(jl_ptls_t ptls) JL_NOTSAFEPOINT; + // make it invalid for a task to return from this point to its stack // this is generally quite an foolish operation, but does free you up to do // arbitrary things on this stack now without worrying about corrupt state that @@ -439,15 +441,17 @@ void jl_task_frame_noreturn(jl_task_t *ct) JL_NOTSAFEPOINT ct->eh = NULL; ct->world_age = 1; // Force all locks to drop. Is this a good idea? Of course not. But the alternative would probably deadlock instead of crashing. - small_arraylist_t *locks = &ct->ptls->locks; + jl_ptls_t ptls = ct->ptls; + small_arraylist_t *locks = &ptls->locks; for (size_t i = locks->len; i > 0; i--) jl_mutex_unlock_nogc((jl_mutex_t*)locks->items[i - 1]); locks->len = 0; - ct->ptls->in_pure_callback = 0; - ct->ptls->in_finalizer = 0; - ct->ptls->defer_signal = 0; + ptls->in_pure_callback = 0; + ptls->in_finalizer = 0; + ptls->defer_signal = 0; // forcibly exit GC (if we were in it) or safe into unsafe, without the mandatory safepoint - jl_atomic_store_release(&ct->ptls->gc_state, JL_GC_STATE_UNSAFE); + jl_atomic_store_release(&ptls->gc_state, JL_GC_STATE_UNSAFE); + surprise_wakeup(ptls); // allow continuing to use a Task that should have already died--unsafe necromancy! jl_atomic_store_relaxed(&ct->_state, JL_TASK_STATE_RUNNABLE); } @@ -461,6 +465,7 @@ void jl_critical_error(int sig, int si_code, bt_context_t *context, jl_task_t *c size_t i, n = ct ? *bt_size : 0; if (sig) { // kill this task, so that we cannot get back to it accidentally (via an untimely ^C or jlbacktrace in jl_exit) + // and also resets the state of ct and ptls so that some code can run on this task again jl_task_frame_noreturn(ct); #ifndef _OS_WINDOWS_ sigset_t sset; diff --git a/stdlib/Sockets/src/Sockets.jl b/stdlib/Sockets/src/Sockets.jl index 5baf8826cc883..3c30b214305fb 100644 --- a/stdlib/Sockets/src/Sockets.jl +++ b/stdlib/Sockets/src/Sockets.jl @@ -450,7 +450,7 @@ function send(sock::UDPSocket, ipaddr::IPAddr, port::Integer, msg) finally Base.sigatomic_end() iolock_begin() - ct.queue === nothing || Base.list_deletefirst!(ct.queue, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) if uv_req_data(uvw) != C_NULL # uvw is still alive, # so make sure we won't get spurious notifications later diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl index 4ee9e07a58430..866a1684c85a1 100644 --- a/stdlib/Sockets/src/addrinfo.jl +++ b/stdlib/Sockets/src/addrinfo.jl @@ -90,7 +90,7 @@ function getalladdrinfo(host::String) finally Base.sigatomic_end() iolock_begin() - ct.queue === nothing || Base.list_deletefirst!(ct.queue, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) if uv_req_data(req) != C_NULL # req is still alive, # so make sure we don't get spurious notifications later @@ -223,7 +223,7 @@ function getnameinfo(address::Union{IPv4, IPv6}) finally Base.sigatomic_end() iolock_begin() - ct.queue === nothing || Base.list_deletefirst!(ct.queue, ct) + q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct) if uv_req_data(req) != C_NULL # req is still alive, # so make sure we don't get spurious notifications later From 015c2cb60d968f8cd9474b3c3c26176a27e7e756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= <765740+giordano@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:37:48 +0200 Subject: [PATCH 195/206] [OpenBLAS_jll] Upgrade to new build to fix bug in threads buffers (#55496) --- deps/checksums/openblas | 184 +++++++++--------- deps/openblas.mk | 7 +- ...enblas-memory-buffer-multi-threading.patch | 49 +++++ stdlib/OpenBLAS_jll/Project.toml | 2 +- 4 files changed, 148 insertions(+), 94 deletions(-) create mode 100644 deps/patches/openblas-memory-buffer-multi-threading.patch diff --git a/deps/checksums/openblas b/deps/checksums/openblas index 51317261c82a0..08bd98646c24b 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,94 +1,94 @@ -OpenBLAS.v0.3.28+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/e3edc449afa805b3744eb153460b681f -OpenBLAS.v0.3.28+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/4f619ae720bc2a55c6d7d53b78bf0a15f66c5b3474c968b367f41d71c759b39028817e3e7ba3cebc4ee06f2176578a5a1bd2be7cf2f1461a396c418292fcf782 -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/e01dcbdbfd2c8f15d78efb0aa5673944 -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/33dee7c48f981b218792e150aea506989b7bbacfd540ebd1fefb150af3c33eae62cd523c329ef8f37c0b56643d480e105ed82e46ec5b3f683e006d05dda717ee -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/43662cb933b2aab820bd210edd4e994a -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/520abb2521a4b9ae71c86dafc7de4155d51df09ff119a3b1d25a9bac3fb73aceaf38b7805888d4858b96e73c0d1cf80d8953b9db954df4d0e6c164894d07d715 -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/5c693f190d26194353c1e096b40568bc -OpenBLAS.v0.3.28+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/3c3e11ba038e59002d23e885e22129dda13453469dad79f39f9cddceadbf1d39e61487894f5112b2fcb5265cd98075103d99eff2a83f79407aafa545b03e9f9c -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/2892710a8545b4573014024222bb8dff -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/6a628c9f7eab2a34198028846a6aec7bb13af4425e1b73ba5b58d326c1eb0741b5dc08fff3db565c92cbc0e2718b62fa6dedac5fa0bdb2f35561663f36f4dfbe -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/fbec5f47685d4bb36956cd4aee34f1e5 -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/ac69a9ed17900de79c6da0ff08a97f3397860de92ce1888f77c8c8fada08fab15fff1b19868c95865ad4a387701c2ffe74e695d6949d8ba02534f91aca2a5ca3 -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/6a0a1a1cad6452ac687e24147128f027 -OpenBLAS.v0.3.28+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/0ea2b7f829b4e406276911db743706b17d7902899d4492e18b9676fed9b27d976d586e38505c52932e27f194c9806d6cb53182cb128baab41898605af7c346b5 -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/677baf1c9142f1db12c89ef98a082d03 -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0a182dba6512dd50193d7625091487bb45f61ec5edbb8adffdeb68fa43744d8c9aa1233ac709249b09fed59e63b6532bf40386dfe884c26605551a6974ed0cc8 -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/d6b08be3200bef4a045be99246a3f294 -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/467d6d12cd56237e6128de4041dbffa3428f208e313f20975c0665abf42a3c39d6b527676573897d6b6801306a9a241da17f4231ce79f0081fb433733d3cb6b4 -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/8645788a731c86f26f40eaf6f65bf74c -OpenBLAS.v0.3.28+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/19ea4ffdef48ef1af6bdd68ce39986814b1732d65bcaee673cd3c0dcb5572faef53962c4ac18e0d1800eb9745324b3145f98c136606ff71d96778e85d4d6bf72 -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/a40dc134a8a5e31bea637bc0a6ee45b6 -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/3d4a1a67753f41bde880ae0b1d19ad7998ae7646530d3e469829e7ea859a394dde73e20239b80e8c61b58974c266d0960cbe256dea4103b04dd4ec52318f02c0 -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/0ff472d7bf455b8b3b50daa91241f288 -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/c0b306bf1ba71baebbe191d7f105287aa19fccd61ae2bc48c9b9ffd92140d4f02d3a78e0632e83924fb02c93826455493c8f5767d71b7e505a1066bd67b95dff -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/26a05928260315bc2088842d2fa75347 -OpenBLAS.v0.3.28+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/dd5ceb6b7fd028df3c4eac732857c537e81c6c8bb7662c6075e432acd51eb6421556b3453e37483481499b2557d34fcec22fda9192cd54b6c7c7205dd40ed387 -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/677baf1c9142f1db12c89ef98a082d03 -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0a182dba6512dd50193d7625091487bb45f61ec5edbb8adffdeb68fa43744d8c9aa1233ac709249b09fed59e63b6532bf40386dfe884c26605551a6974ed0cc8 -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/d6b08be3200bef4a045be99246a3f294 -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/467d6d12cd56237e6128de4041dbffa3428f208e313f20975c0665abf42a3c39d6b527676573897d6b6801306a9a241da17f4231ce79f0081fb433733d3cb6b4 -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/8645788a731c86f26f40eaf6f65bf74c -OpenBLAS.v0.3.28+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/19ea4ffdef48ef1af6bdd68ce39986814b1732d65bcaee673cd3c0dcb5572faef53962c4ac18e0d1800eb9745324b3145f98c136606ff71d96778e85d4d6bf72 -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/a40dc134a8a5e31bea637bc0a6ee45b6 -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/3d4a1a67753f41bde880ae0b1d19ad7998ae7646530d3e469829e7ea859a394dde73e20239b80e8c61b58974c266d0960cbe256dea4103b04dd4ec52318f02c0 -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/0ff472d7bf455b8b3b50daa91241f288 -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/c0b306bf1ba71baebbe191d7f105287aa19fccd61ae2bc48c9b9ffd92140d4f02d3a78e0632e83924fb02c93826455493c8f5767d71b7e505a1066bd67b95dff -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/26a05928260315bc2088842d2fa75347 -OpenBLAS.v0.3.28+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/dd5ceb6b7fd028df3c4eac732857c537e81c6c8bb7662c6075e432acd51eb6421556b3453e37483481499b2557d34fcec22fda9192cd54b6c7c7205dd40ed387 -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran3.tar.gz/md5/36f76f7588ad5bc48c2f68daee49da57 -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/2184cac67657fb58afc42fff46069084ffbcbc67938e7e74e9e5a926cc83733c702cacf16ca320381f5bb1f219cbea764ae8cdb9c445f7224ac0cd0beab822ff -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran4.tar.gz/md5/ef8501cc6babf8be3b8b649da2a7c692 -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/98543cfd34a185644cebc33cd82ebfb663c92f1fa8349121e6d34f86b1d10f4f37688b84b22182f9e29daa74664a469ddc67408827e8bc7fddb1a7311d918532 -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran5.tar.gz/md5/598c07efb122e75e6e99ba7fc0c4fb4b -OpenBLAS.v0.3.28+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/b7caa20a36d6806895f3efb02830017c3ca8037c5af3a29df00f9fe34945324c34181a945b1dbe8a8ca43c7f792667d7640c23b5c2fa4fd93564f1da78561190 -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran3.tar.gz/md5/e7667d215442ac0db83969d41a678774 -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran3.tar.gz/sha512/3b22dd658b5948d6867b3e57fe53976eef59339d2714709746098b96f13766d86e918a139929aa60672be91c50c7f739c5c0db372f07a71ae2447588db3685e4 -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran4.tar.gz/md5/91d95572ce67a21d107b9fbcd3aba11d -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran4.tar.gz/sha512/7727d24fec0a333a943de3f9d6dd5c698e4f3b9099fd838b8b5652f6216f7b9fe4a2d8f014a4f0b3b7ad7fe05b81a9079e570454d456f0462e7d04f66e264ecb -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran5.tar.gz/md5/2d56a5cfeae0a6afa2d2b8efa1ab22c5 -OpenBLAS.v0.3.28+0.i686-linux-musl-libgfortran5.tar.gz/sha512/e81207bee11f89669837db08b57b63813056730f68412345421539399c12a675ed01942558ebd42045959c29a2b774a75f28c4a6b14549b7373b54a5e93e8933 -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/5b741b5fec8b564ba8b24435b5d885ae -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/97e72a4b9b39d4889c4e36eff85186fcbabfff2930185e69b3c259b43cdbaa5fab51bf0ed4024d1ddd3c780edaf501c4f5f7534e0a2edb802d580987fbd026ab -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/d5f059fc960b7dc84ee4b92c431d87b4 -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/f1e8f31f89274ff5b466931f8941de55fb27d2ee773d87e7e0b992deeec7d921358b10520cc0f47975022536b5e9d7b1cc9acc481b95f83cc2096d7cb7494616 -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/cb99d7d4944c5283a1a0142683e1d377 -OpenBLAS.v0.3.28+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/b77d3225e60f49506917bfff78c187df7157dbc834eccda2fa03d03eef8214b225682888a411a8b6e4b29a8d7e2b0ca625ea8c56b84ecc39e1f4f1012523c096 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/c6e5d4867a068e08b3f56f474e498b81 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/de6249439758a501bfd27d3ef04ec04cc06edf64de73f0709a6a40a2eaf40bd3d5d77dfd54b7b19e2f6bf6c104b4416d3e225faa0cff4cb631785c08d90b8614 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/32e70466cfa3cfec65ab4cad3abc5f03 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/2642385a5e9fc8e9c3839a5a44f9753b21b5078725f7d0c3e1ebe96b76129a3b8e2627d92629dee4f6fd7e8e51e86a7fbedc80cbe4d1a6812cea363559950da0 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/e2332831bd88d57132241697952819e7 -OpenBLAS.v0.3.28+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/ad03edf9ac56bf6311f0ca70a1bc359242accfe82cba9e42f39f6cb1c3006226179ff9be8218847889cae10fac13bc33f60837e1e3249e309172da7fbc25400f -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/24c915a3156983745662ff99e5d1b040 -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/47fb327281c903eebb0a261458fc10f09bac317d7e135dff72a112c868a2525fa542f93f22da083c13454fc241352d39a8e8463085685aa77e055ffcadf451c8 -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/93041d21ad3f95e6d9cbac6cd6730363 -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/17cd2302860eeee884f97d87eaf0ad12cdc7361734cfaa77b543119c58103a5da107b478e7ecfcb135d2e5beffd6a3907108b2911a095a3cbc1d16f32371ac1b -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/98a8c6c8c80c11e8b6d127959c9b3414 -OpenBLAS.v0.3.28+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/d26a51785391d81efcaefcf647fcf0348ad68ff01845ab3547778903d2ab5c5c1cdb2a562ae5cf7f12878f3345c46321719ea82fb87ef655d303a4c0c9803377 -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/41f7fdc10d8cab0965da95e00e2269ba -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/0a47ef77f9b2b70f424e00957f676c53d19c5dffbbcd5a743ab24bbc8608c5e8ad3cb3afefd8cab60a3c51970a63dd47c97868ecc0ef3532b83278c41a8daf96 -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/8453e7a5e5285e770fde7592582bc0e2 -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/a37edfe68c85a6312d7918f1b58d6ac4bafc13081dbd327c830631913350a54bbf8bea57115b4f242d5f93c6b0a8f4995b5ef544a0de06e76c66287ff092e74c -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/6df24890be7a4899f35a2949f9f21d65 -OpenBLAS.v0.3.28+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/66601632f91689fe72afecd2e4d4ef3ad3b7653874228d5509c7732f2e6d63640f35d176ce2219b732632e0daeb76dc3ba11d3e776639985359b21b313056883 -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/d35df8d213c55bc1f9f765e0ba8c7b4e -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/5d5de73150a2e796dc29425dbf415ff7aa443264d767d4e688de07335961ee39835c94b7d68900d49b70bf3ac08d356f3ae00c6d651eed64e504b02c9351edcb -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/384f9173b3804e6f9c73bcde9dacb545 -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/64d3abeca401cee06575915161458408e9fb51e26f759129e1c7a9c27f68729d66e75f0654b977e842844650698c4b1627a18e495d91202a8c0483ef1b35bafc -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/0bd296248e1337fac054b9e0993fea82 -OpenBLAS.v0.3.28+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/fdb9ce296228f92c112bbeb346a2900a8d5a73e21a313a217cf7135fd77484cdeed53c86382ee5550f1b624eb6ed99d06b739229add7364217ca68fefedd04c4 -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/524a2481331fdd3933f06b40e63433f1 -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/06831cc855e9801dbf2248a0da123c345b6731c830f39d3166b8d8e7de8d649b6d9900e534ec6c1113a227203f6a9aa8171fcf548cfd56a4a67b6037c105ecf5 -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/82f2b8f31f7b718f6ea743c996acbe4d -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/fd1ccab964ae9410238d29b38cfe8c2ccca3fda3d78b4294bb4a54ab8abfd6bdaa80cadc0aeadf054bf99138c5dc3cac9370920b0b16cb8793630ab21d5bf667 -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/b91add21ba0e2a0f28a9e4d347111cc3 -OpenBLAS.v0.3.28+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/8ed1d9e327529ee067d975c5c96dac3eabab5a88ed7b1b6e1b030f96bbd2418e3173cacd70e9976d619245757f2a34cc9527aafef1626fd288f14918c9b13eaa -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/937847e2ad00539f3422d1ecb9d26d55 -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/751d889661ddd46cd5718b49e34f826a4fb34b1b992251a5a975bc0af15b74a75d8a56f403e8fae570223477b2b8927d9cb36764e4b9e466045d5f317b8e7196 -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/180c54c50362d05696589b270693ee8f -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/2e3b76be5b7c4a7dc45f07e17493abd7ef9185e92429d8fa4d38766e0da96dd0777b619a9e420d2e1142bdab2ae1f755f9bc9ad97ee9a7927741778f89b9135f -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/2f0fac7c96af66ea63fce26e409f4db6 -OpenBLAS.v0.3.28+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/141522971447c38b4908342f3ad09ffb18142d2e79b44f66fd80047b44c09216c9b94c39f776e3093f9ceb6bc4d6270cbbfb4209b2fc0debfe93e7145cb4dbff +OpenBLAS.v0.3.28+2.aarch64-apple-darwin-libgfortran5.tar.gz/md5/312aa603d089d680205dad7d5da58195 +OpenBLAS.v0.3.28+2.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/ffb0069561f52f8ac2f8affe937a00592e0c5d75c6d64bb0d5c93d1c925c93a46b763638031c88818b9dcef4a7b149ee3f15792a812e87f57a8ad086604164c4 +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran3.tar.gz/md5/7c43d9e9ac07820130a3d5faefdef882 +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/3ade0f098796148c37b118f9c052bad4e40431b4792f001043f040f8b1e4b7c3bae512f56ea21e6c0111246b2200e7720fe720a56a19dd11d1fba789344f29e3 +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran4.tar.gz/md5/cd2fe87dac703c8bfa25406aa732b88a +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/2aea68bd8f1db2ac920951c8d9a47ce8c071f3736ee8aad8d185a09be25234a0ffd11b9f9640015b82770ba3b3fad9aa511cc43501c1bb5a3a44f1fb7ccd5692 +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran5.tar.gz/md5/e3db2bf2f1f38aeee8530c78f3ec049a +OpenBLAS.v0.3.28+2.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/a0ccb92e818650ac3cbc292d5af1a000ee9b123953cc3eb16e2479e926af3f2be0ed9858e3c0c1075b1b9dd70ec1e51b9dce2c9d45b999d296aa050d257a3cb1 +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran3.tar.gz/md5/5bb605738930037259e773ebdb4a7041 +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran3.tar.gz/sha512/967e0f33be7b743d9617627a947a802286962a46c7c3b2418aaa1504cffc5f311b01e1702b35ded18ae3686b1914c6085213b03fa8a51e0a7ca16dc4cfee8504 +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran4.tar.gz/md5/ce175e82b9c6597c546552e79a43f934 +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran4.tar.gz/sha512/8ff5dff293d9786fc4f541b209b35afcbe325c13ddd0f9c8f9bfca8ba5c318c7890152260a5441b9e9088751ce03b1ff8f0f5d6fd4f142fae34bdb7390d1952c +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran5.tar.gz/md5/cae6aabbdccf31fb78b234785b52d48a +OpenBLAS.v0.3.28+2.aarch64-linux-musl-libgfortran5.tar.gz/sha512/ac842023e5db243fcfada22adca051bd2ffa04fca496454539931eede159e5d0490d444c338684c2d178c3367b23b8f3d76c544e30f1897bbed181f56237619f +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/5d1f45f53dd1730051095fb8e027b14f +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0b1f91e86b5078b7cd6b64bc429a0e63bb5adf28df1baa336e67819fbd2c09f59b643c39e580f63e3bbccdc631c5d5e14c7d8afa6af94250453ce5286958f90f +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/8b3e3ea928975c575798d47466aafb82 +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/ebac0f7047dd8b97d85e4251953a23824701af02754afd6808f13eb276326b30eb292c85fa717fbd2f21b929e6a9816a012b8ea378a0fa27e671f81435f5d3b9 +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/5aacfce96d5673b4d8341cb097d22c4a +OpenBLAS.v0.3.28+2.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/b84dc2b8cbe5453555182c3fcd8624d7a2b28fe3826d54fde3b77ad2c33e60309317d150f07554dd85e168b0ac1f91537a5c2c17fff9c02dd9216f01161e4965 +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/dfeac22ee204868cf254dab5ae79382b +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/710117eb7400a0aacf69d6053730eb3b3ff4767f8d38defb2aaad94aebf1646a794489e78a8f46b469901159cdca73dd2b9460fff11e95daa4a2642cab721a25 +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/13ff2a40bc55839bdef76b796db1eb76 +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/eb61fe6c0221e8f9d7a626b8d088ae1497155341dafb69835e7d53af76689ae212e1e4621e0729df5d896888c0b2d7354a24f7b57fe1d68f0b35c26bcf096699 +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/aa7349724ba1d47256705777e755289a +OpenBLAS.v0.3.28+2.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/25ab56c44b7d0d5de17344f39071e6894e878e89b5e35412a3c9fe345abd2eef76d7816cabb6407c7c521c3bf67a4741b37ad7e580962ead9275273e431f1fb3 +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/5d1f45f53dd1730051095fb8e027b14f +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/0b1f91e86b5078b7cd6b64bc429a0e63bb5adf28df1baa336e67819fbd2c09f59b643c39e580f63e3bbccdc631c5d5e14c7d8afa6af94250453ce5286958f90f +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/8b3e3ea928975c575798d47466aafb82 +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/ebac0f7047dd8b97d85e4251953a23824701af02754afd6808f13eb276326b30eb292c85fa717fbd2f21b929e6a9816a012b8ea378a0fa27e671f81435f5d3b9 +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/5aacfce96d5673b4d8341cb097d22c4a +OpenBLAS.v0.3.28+2.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/b84dc2b8cbe5453555182c3fcd8624d7a2b28fe3826d54fde3b77ad2c33e60309317d150f07554dd85e168b0ac1f91537a5c2c17fff9c02dd9216f01161e4965 +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/dfeac22ee204868cf254dab5ae79382b +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/710117eb7400a0aacf69d6053730eb3b3ff4767f8d38defb2aaad94aebf1646a794489e78a8f46b469901159cdca73dd2b9460fff11e95daa4a2642cab721a25 +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/13ff2a40bc55839bdef76b796db1eb76 +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/eb61fe6c0221e8f9d7a626b8d088ae1497155341dafb69835e7d53af76689ae212e1e4621e0729df5d896888c0b2d7354a24f7b57fe1d68f0b35c26bcf096699 +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/aa7349724ba1d47256705777e755289a +OpenBLAS.v0.3.28+2.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/25ab56c44b7d0d5de17344f39071e6894e878e89b5e35412a3c9fe345abd2eef76d7816cabb6407c7c521c3bf67a4741b37ad7e580962ead9275273e431f1fb3 +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran3.tar.gz/md5/53087cc770708c57d2654fd0095b64df +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran3.tar.gz/sha512/90961448ae40b0445bf881d0815aec54d2096ad235dc8e3db8d698a72961ef9a97e7fcd08f79c83cd1f7c5a341464f52a90351d927d5f1c3e9c8ee32b17970db +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran4.tar.gz/md5/ee910e19faa961bde11fdf90c211df9d +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran4.tar.gz/sha512/f5cfecfe965991cfd7843eff71efa71d6842058565bb63657e909b2942e58a8c7506aa66335308961e59f392da16e1177d79542ae509795566a14122f67a1782 +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran5.tar.gz/md5/fe52ba7ca8e16f37aa04b79248e0471d +OpenBLAS.v0.3.28+2.i686-linux-gnu-libgfortran5.tar.gz/sha512/79b5108886d60f12424709a841e359dc1cf23cef21bb0ee6d1a48043ac48a35dac1637e43c8ebf3f2e10dd34721993a7a12c5776f2975dd5bd7b6e29e1a9adc3 +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran3.tar.gz/md5/88d8ff421d29456f1d7670ceaf8867ca +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran3.tar.gz/sha512/91c1bd8142845d11fecba87a719315a14218e3863955ddd2ed82cecd4a2c177a48c660b6aac374ee9a11008245c0ced1bae70eaf5a1a6e3114db02e09a96396f +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran4.tar.gz/md5/3035066a53032b551e49f56b323e941d +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran4.tar.gz/sha512/f218e152a1c92bd374599814612add8010aedc78113cbe06465e8a1ee7f66892bb654cad687aa55555e74f3a65d74608692d41c9f0ce6c0bc63475ef62ab55b7 +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran5.tar.gz/md5/f7cf36ac9a0cbb535952ec73f2e6c9ea +OpenBLAS.v0.3.28+2.i686-linux-musl-libgfortran5.tar.gz/sha512/00ab052d9fa4a72a640545782019f24ed6017b36aa89c5e659ce73b1e821817f560c09f71b26c027c0a05bd13567c71a6d7f5995d1c39ab233bec56cd3a7fd9e +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran3.tar.gz/md5/b65414bb15539e5aa2f5f1c7984edb94 +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran3.tar.gz/sha512/847ada020bb92fe6ea81dfffaf855707a529c9c0f7e246e802b9521e5c7d4aa36104d04279c09a905a797184cdf05a6fabf84711b7661ecb14e9ac2fba251f61 +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran4.tar.gz/md5/0b626ebb8b3fc49b946723a9a2a21a91 +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran4.tar.gz/sha512/b5bba23878399fc1ff20abc2e2eb4acb9691ce982f290e33384732452774a0b447bd0fb01ee696d10ad8b03d99eec905662af92bd3b499d9fe6db419e05d2573 +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran5.tar.gz/md5/cb99d7d4944c5283a1a0142683e1d377 +OpenBLAS.v0.3.28+2.i686-w64-mingw32-libgfortran5.tar.gz/sha512/b77d3225e60f49506917bfff78c187df7157dbc834eccda2fa03d03eef8214b225682888a411a8b6e4b29a8d7e2b0ca625ea8c56b84ecc39e1f4f1012523c096 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/c6e5d4867a068e08b3f56f474e498b81 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/de6249439758a501bfd27d3ef04ec04cc06edf64de73f0709a6a40a2eaf40bd3d5d77dfd54b7b19e2f6bf6c104b4416d3e225faa0cff4cb631785c08d90b8614 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/32e70466cfa3cfec65ab4cad3abc5f03 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/2642385a5e9fc8e9c3839a5a44f9753b21b5078725f7d0c3e1ebe96b76129a3b8e2627d92629dee4f6fd7e8e51e86a7fbedc80cbe4d1a6812cea363559950da0 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/e2332831bd88d57132241697952819e7 +OpenBLAS.v0.3.28+2.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/ad03edf9ac56bf6311f0ca70a1bc359242accfe82cba9e42f39f6cb1c3006226179ff9be8218847889cae10fac13bc33f60837e1e3249e309172da7fbc25400f +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran3.tar.gz/md5/27c24775af446a44a72a28ffd197696d +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/2af8caa33bee88efff84653f3932b04e8fd4aabb1bf16d49fa73657b0ec13c9457fde7ab3f953fc9b01da5c2841c3c9b588e3b0f559b89df0e6268468d1f7cc8 +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran4.tar.gz/md5/414e701d918d5fba08a12de6979db4b5 +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/949886d388b80e19b944d102852f2bb58ffa03c42e624986dd9dc076797c996634d4a8fc0f04544451d6848c2079969816979e1f68a999b2747e9dd5472be7a6 +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran5.tar.gz/md5/29fcf62c0280cc10f91d22189a2e8de8 +OpenBLAS.v0.3.28+2.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/02e75d4ecf9cd922157a72c0ca2e713cf336b125df3982cd5f7cc4f2a04367ad4c2b1190ca2a0a9df8b639c7ebcfc9783066e99dd0b13acde7b02038391e8567 +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran3.tar.gz/md5/147d5e8eb2ec78fc8a31bdb091fab001 +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/2319eda568800c0b1f2d96a8a36c59b1bbd792c06de1d740aea3f1e49798242426ea8d10c100c42c3c281702e2b4f5b673b6ab5252b276d48542e875bcaa3094 +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran4.tar.gz/md5/448857d9c4b2e95afc12a14c75b24055 +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/3e7c8cd55e0b15a30992b1e0b48a6e2ae36fd9babf689fa5595c7de94aec401de1d7821d45a22bf14cd5c45c708bc8fa3511d34d732dadd4daaca3f49e200bdb +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran5.tar.gz/md5/3aaf417685b44e0e505208f7b31b981a +OpenBLAS.v0.3.28+2.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/f7b1d123e48ede93fe624a79d9535a8915bfa3441d7a6f9c6643467027414c9f2538e299858ea98bbb49d4e6d385a6a491063cb1878ac3b0b3d6a8f7ff0a48df +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran3.tar.gz/md5/5723136deaaf4b2e5960fb0774943288 +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran3.tar.gz/sha512/127ea8b2b0d8d4586a23a2b8ecbf148d512efe68626e89b0688c3c9e29ed9420b45ae86755c1467313c565f9f3835762051d7086a815b813dbe6e9eb05fb4be1 +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran4.tar.gz/md5/80b1b9cf5346916edda653174a987aa2 +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran4.tar.gz/sha512/77e1387ec969bbed4945d2a598a1cd04d258265c4b2d5c43af92118eb32e0c69e40619a20ea1835f277febcfea068b241343d44932afef832bdcfd2e9f618f0a +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran5.tar.gz/md5/44dcedf01c938d1a1c67dd3bc90ab61d +OpenBLAS.v0.3.28+2.x86_64-linux-musl-libgfortran5.tar.gz/sha512/e490d49b8d41d73ab3e71aca8c691ca58704f0fc6930cbfcc203f97b8db8d83144bad597a2c53ff0c0c4f7c40316d975a1b589a3603873d508f6beeb75970c5b +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/0e8a7e88b54cb836292c289d1c456fa9 +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/0e9b3af6839b9c41c950bb4d8b739f0243a890af7092ef9f3a00e4931f2acc3820afb78e40c7bfef716dcd3230c1d0acc7b0b37f30eb47441b476bd7540745e6 +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/5fc47ad55780c99ef9cab7ef1b26d9c0 +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/c531201e4abddd652efeb5801658f5c1e4891578f181e99d6e41fc0d3bc6347b82e5e928ff8a717ee1e75bb0a6a765260bf7c99fce44aa24c21f1c5a5e3c1e3b +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/dc127f3ab984b5d47b325d5701ab73cd +OpenBLAS.v0.3.28+2.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/50850911703320894a2e1e996c5de4613b5f9e3012f5cbf591f3677799599c45d9cc4c42cf310bdc6ba91ef550e52f6424bbbabdf47f96748d4669d94e6b46a4 +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/937847e2ad00539f3422d1ecb9d26d55 +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/751d889661ddd46cd5718b49e34f826a4fb34b1b992251a5a975bc0af15b74a75d8a56f403e8fae570223477b2b8927d9cb36764e4b9e466045d5f317b8e7196 +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/180c54c50362d05696589b270693ee8f +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/2e3b76be5b7c4a7dc45f07e17493abd7ef9185e92429d8fa4d38766e0da96dd0777b619a9e420d2e1142bdab2ae1f755f9bc9ad97ee9a7927741778f89b9135f +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/2f0fac7c96af66ea63fce26e409f4db6 +OpenBLAS.v0.3.28+2.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/141522971447c38b4908342f3ad09ffb18142d2e79b44f66fd80047b44c09216c9b94c39f776e3093f9ceb6bc4d6270cbbfb4209b2fc0debfe93e7145cb4dbff openblas-5ef8b1964658f9cb6a6324a06f6a1a022609b0c5.tar.gz/md5/f7a1fe86cefbf7d4f2608843c7833ca7 openblas-5ef8b1964658f9cb6a6324a06f6a1a022609b0c5.tar.gz/sha512/5f6020e958967a12a3c5b18bde13331f9c0602bd073563f35cd7cec848c92b45f30ca362819b12cd16989c0e4641ee3e63db8322d1092f61b31ba2e4068dd7a7 diff --git a/deps/openblas.mk b/deps/openblas.mk index 1bc068d2859d9..affd1c7a7aa55 100644 --- a/deps/openblas.mk +++ b/deps/openblas.mk @@ -90,7 +90,12 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-winexit.patch-applied: $(BUILDDIR)/$(OP patch -p1 -f < $(SRCDIR)/patches/openblas-winexit.patch echo 1 > $@ -$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-ofast-power.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-winexit.patch-applied +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-memory-buffer-multi-threading.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-winexit.patch-applied + cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && \ + patch -p1 -f < $(SRCDIR)/patches/openblas-memory-buffer-multi-threading.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-ofast-power.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-memory-buffer-multi-threading.patch-applied cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && \ patch -p1 -f < $(SRCDIR)/patches/openblas-ofast-power.patch echo 1 > $@ diff --git a/deps/patches/openblas-memory-buffer-multi-threading.patch b/deps/patches/openblas-memory-buffer-multi-threading.patch new file mode 100644 index 0000000000000..9693b5cf61597 --- /dev/null +++ b/deps/patches/openblas-memory-buffer-multi-threading.patch @@ -0,0 +1,49 @@ +From 23b5d66a86417a071bba9a96a0573192237981b6 Mon Sep 17 00:00:00 2001 +From: Martin Kroeker +Date: Wed, 14 Aug 2024 10:35:44 +0200 +Subject: [PATCH 1/2] Ensure a memory buffer has been allocated for each thread + before invoking it + +--- + driver/others/blas_server.c | 2 ++ + 1 file changed, 2 insertions(+) + +From d24b3cf39392a99e81ed47a5f093fbd074d4b39b Mon Sep 17 00:00:00 2001 +From: Martin Kroeker +Date: Thu, 15 Aug 2024 15:32:58 +0200 +Subject: [PATCH 2/2] properly fix buffer allocation and assignment + +--- + driver/others/blas_server.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) +diff --git a/driver/others/blas_server.c b/driver/others/blas_server.c +index 765511d8c7..b9a7674c17 100644 +--- a/driver/others/blas_server.c ++++ b/driver/others/blas_server.c +@@ -1076,6 +1076,8 @@ fprintf(STDERR, "Server[%2ld] Calculation started. Mode = 0x%03x M = %3ld N=%3l + main_status[cpu] = MAIN_RUNNING1; + #endif + ++if (buffer == NULL) blas_thread_buffer[cpu] = blas_memory_alloc(2); ++ + //For target LOONGSON3R5, applying an offset to the buffer is essential + //for minimizing cache conflicts and optimizing performance. + #if defined(ARCH_LOONGARCH64) && !defined(NO_AFFINITY) + +diff --git a/driver/others/blas_server.c b/driver/others/blas_server.c +index b9a7674c17..29f8a5e646 100644 +--- a/driver/others/blas_server.c ++++ b/driver/others/blas_server.c +@@ -1076,7 +1076,11 @@ fprintf(STDERR, "Server[%2ld] Calculation started. Mode = 0x%03x M = %3ld N=%3l + main_status[cpu] = MAIN_RUNNING1; + #endif + +-if (buffer == NULL) blas_thread_buffer[cpu] = blas_memory_alloc(2); ++if (buffer == NULL) { ++ blas_thread_buffer[cpu] = blas_memory_alloc(2); ++ buffer = blas_thread_buffer[cpu]; ++} ++ + + //For target LOONGSON3R5, applying an offset to the buffer is essential + //for minimizing cache conflicts and optimizing performance. diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index dfca282c74704..a9a1a04facff5 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.28+0" +version = "0.3.28+2" [deps] # See note in `src/OpenBLAS_jll.jl` about this dependency. From 6916eb742055b47a0c52de855f5d0ecd4d0769ef Mon Sep 17 00:00:00 2001 From: Zentrik Date: Fri, 16 Aug 2024 00:07:21 +0100 Subject: [PATCH 196/206] Use same toolchain throughout pgo+bolt build (#55460) Also, I added the pgo flags to the `finish_stage2` target in case they are or become useful there. --- contrib/pgo-lto-bolt/Makefile | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/contrib/pgo-lto-bolt/Makefile b/contrib/pgo-lto-bolt/Makefile index fa88cdcd3d6a7..2114b14991184 100644 --- a/contrib/pgo-lto-bolt/Makefile +++ b/contrib/pgo-lto-bolt/Makefile @@ -83,7 +83,7 @@ TOOLCHAIN_FLAGS = $\ "RANLIB=$(STAGE0_TOOLS)llvm-ranlib" $\ "CFLAGS+=$(PGO_CFLAGS)" $\ "CXXFLAGS+=$(PGO_CXXFLAGS)" $\ - "LDFLAGS+=$(PGO_LDFLAGS)" + "LDFLAGS+=-fuse-ld=lld $(PGO_LDFLAGS)" $(STAGE0_BUILD) $(STAGE1_BUILD) $(STAGE2_BUILD): $(MAKE) -C $(JULIA_ROOT) O=$@ configure @@ -99,7 +99,7 @@ stage0: | $(STAGE0_BUILD) $(STAGE1_BUILD): stage0 stage1: PGO_CFLAGS:=-fprofile-generate=$(PGO_PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) stage1: PGO_CXXFLAGS:=-fprofile-generate=$(PGO_PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) -stage1: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-generate=$(PGO_PROFILE_DIR) +stage1: PGO_LDFLAGS:=-flto=thin -fprofile-generate=$(PGO_PROFILE_DIR) stage1: export USE_BINARYBUILDER_LLVM=0 stage1: | $(STAGE1_BUILD) $(MAKE) -C $(STAGE1_BUILD) $(TOOLCHAIN_FLAGS) && touch $@ @@ -107,7 +107,7 @@ stage1: | $(STAGE1_BUILD) stage2: PGO_CFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) stage2: PGO_CXXFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) -stage2: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-use=$(PGO_PROFILE_FILE) -Wl,--icf=safe +stage2: PGO_LDFLAGS:=-flto=thin -fprofile-use=$(PGO_PROFILE_FILE) -Wl,--icf=safe stage2: export USE_BINARYBUILDER_LLVM=0 stage2: $(PGO_PROFILE_FILE) | $(STAGE2_BUILD) $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) $(BOLT_FLAGS) julia-src-release julia-symlink julia-libccalltest \ @@ -135,10 +135,13 @@ bolt_instrument: copy_originals # We don't want to rebuild julia-src as then we lose the bolt instrumentation # So we have to manually build the sysimage and package image +finish_stage2: PGO_CFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) +finish_stage2: PGO_CXXFLAGS:=-fprofile-use=$(PGO_PROFILE_FILE) +finish_stage2: PGO_LDFLAGS:=-flto=thin -fprofile-use=$(PGO_PROFILE_FILE) -Wl,--icf=safe finish_stage2: stage2 - $(MAKE) -C $(STAGE2_BUILD) julia-base-cache && \ - $(MAKE) -C $(STAGE2_BUILD) -f sysimage.mk sysimg-release && \ - $(MAKE) -C $(STAGE2_BUILD) -f pkgimage.mk release + $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) julia-base-cache && \ + $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) -f sysimage.mk sysimg-release && \ + $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) -f pkgimage.mk release merge_data: bolt_instrument for file in $(FILES_TO_OPTIMIZE); do \ From 5230d27de950165475892acfabded59713c8cd3e Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Fri, 16 Aug 2024 03:33:22 -0400 Subject: [PATCH 197/206] Fix push! for OffsetVectors, add tests for push! and append! on AbstractVector (#55480) Per https://github.com/JuliaLang/julia/pull/55470#discussion_r1714000529, the `push!(::AbstractArray, ...)` array implementation assumed one-based indexing and did not account for an `OffsetVector` scenario. Here we add tests for `push!(::AbstractArray, ...)` and `append(::AbstractArray, ...)` including using `@invoke` to test the effect on `OffsetVector`. cc: @fredrikekre --- base/abstractarray.jl | 7 ++++--- test/abstractarray.jl | 18 +++++++++++++++++- test/offsetarray.jl | 29 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 3f8886e14940c..754ab20660ab8 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -3532,7 +3532,7 @@ function push!(a::AbstractVector{T}, item) where T itemT = item isa T ? item : convert(T, item)::T new_length = length(a) + 1 resize!(a, new_length) - a[new_length] = itemT + a[end] = itemT return a end @@ -3540,7 +3540,7 @@ end function push!(a::AbstractVector{Any}, @nospecialize x) new_length = length(a) + 1 resize!(a, new_length) - a[new_length] = x + a[end] = x return a end function push!(a::AbstractVector{Any}, @nospecialize x...) @@ -3548,8 +3548,9 @@ function push!(a::AbstractVector{Any}, @nospecialize x...) na = length(a) nx = length(x) resize!(a, na + nx) + e = lastindex(a) - nx for i = 1:nx - a[na+i] = x[i] + a[e+i] = x[i] end return a end diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 8b4a1d9113940..f655d9abe423f 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1437,14 +1437,30 @@ using .Main.OffsetArrays end @testset "Check push!($a, $args...)" for - a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1)), + a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), SimpleArray{Any}(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1)), args in (("eenie",), ("eenie", "minie"), ("eenie", "minie", "mo")) orig = copy(a) push!(a, args...) @test length(a) == length(orig) + length(args) + @test a[axes(orig,1)] == orig @test all(a[end-length(args)+1:end] .== args) end +@testset "Check append!($a, $args)" for + a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), SimpleArray{Any}(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1)), + args in (("eenie",), ("eenie", "minie"), ("eenie", "minie", "mo")) + orig = copy(a) + append!(a, args) + @test length(a) == length(orig) + length(args) + @test a[axes(orig,1)] == orig + @test all(a[end-length(args)+1:end] .== args) +end + +@testset "Check sizehint!($a)" for + a in (["foo", "Bar"], SimpleArray(["foo", "Bar"]), SimpleArray{Any}(["foo", "Bar"]), OffsetVector(["foo", "Bar"], 0:1)) + @test sizehint!(a, 10) === a +end + @testset "splatting into hvcat" begin t = (1, 2) @test [t...; 3 4] == [1 2; 3 4] diff --git a/test/offsetarray.jl b/test/offsetarray.jl index c50f38c382385..5ee918e85faf7 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -383,6 +383,18 @@ v2 = copy(v) @test v2[end-1] == 2 @test v2[end] == 1 +# push!(v::AbstractVector, x...) +v2 = copy(v) +@test @invoke(push!(v2::AbstractVector, 3)) === v2 +@test v2[axes(v,1)] == v +@test v2[end] == 3 +@test v2[begin] == v[begin] == v[-2] +v2 = copy(v) +@test @invoke(push!(v2::AbstractVector, 5, 6)) == v2 +@test v2[axes(v,1)] == v +@test v2[end-1] == 5 +@test v2[end] == 6 + # append! from array v2 = copy(v) @test append!(v2, [2, 1]) === v2 @@ -399,6 +411,23 @@ v2 = copy(v) @test v2[axes(v, 1)] == v @test v2[lastindex(v)+1:end] == [2, 1] +# append!(::AbstractVector, ...) +# append! from array +v2 = copy(v) +@test @invoke(append!(v2::AbstractVector, [2, 1]::Any)) === v2 +@test v2[axes(v, 1)] == v +@test v2[lastindex(v)+1:end] == [2, 1] +# append! from HasLength iterator +v2 = copy(v) +@test @invoke(append!(v2::AbstractVector, (v for v in [2, 1])::Any)) === v2 +@test v2[axes(v, 1)] == v +@test v2[lastindex(v)+1:end] == [2, 1] +# append! from SizeUnknown iterator +v2 = copy(v) +@test @invoke(append!(v2::AbstractVector, (v for v in [2, 1] if true)::Any)) === v2 +@test v2[axes(v, 1)] == v +@test v2[lastindex(v)+1:end] == [2, 1] + # other functions v = OffsetArray(v0, (-3,)) @test lastindex(v) == 1 From ddecfe74ffdfbbdfe0c2e78cee059470982e0ab9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 16 Aug 2024 14:14:36 -0400 Subject: [PATCH 198/206] fix overlapping definitions of `Base.active_module` and `REPL.active_module` (#55316) also avoid calling `active_module` from low-level printing functions fix #54888 --- base/Enums.jl | 2 +- base/show.jl | 44 +++++++++++++++++------------------------ stdlib/REPL/src/REPL.jl | 21 ++++++++------------ 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 6e9efd8ccde38..d4094945853ec 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -44,7 +44,7 @@ Base.print(io::IO, x::Enum) = print(io, _symbol(x)) function Base.show(io::IO, x::Enum) sym = _symbol(x) if !(get(io, :compact, false)::Bool) - from = get(io, :module, Base.active_module()) + from = get(io, :module, Main) def = parentmodule(typeof(x)) if from === nothing || !Base.isvisible(sym, def, from) show(io, def) diff --git a/base/show.jl b/base/show.jl index fa66a198aef4d..0a2976e7ebe42 100644 --- a/base/show.jl +++ b/base/show.jl @@ -514,24 +514,16 @@ function _show_default(io::IO, @nospecialize(x)) end function active_module() - REPL = REPL_MODULE_REF[] - REPL === Base && return Main - return invokelatest(REPL.active_module)::Module + if ccall(:jl_is_in_pure_context, Bool, ()) + error("active_module() should not be called from a pure context") + end + if !@isdefined(active_repl) || active_repl === nothing + return Main + end + return invokelatest(active_module, active_repl)::Module end -# Check if a particular symbol is exported from a standard library module -function is_exported_from_stdlib(name::Symbol, mod::Module) - !isdefined(mod, name) && return false - orig = getfield(mod, name) - while !(mod === Base || mod === Core) - activemod = active_module() - parent = parentmodule(mod) - if mod === activemod || mod === parent || parent === activemod - return false - end - mod = parent - end - return isexported(mod, name) && isdefined(mod, name) && !isdeprecated(mod, name) && getfield(mod, name) === orig +module UsesCoreAndBaseOnly end function show_function(io::IO, f::Function, compact::Bool, fallback::Function) @@ -544,13 +536,13 @@ function show_function(io::IO, f::Function, compact::Bool, fallback::Function) print(io, mt.name) elseif isdefined(mt, :module) && isdefined(mt.module, mt.name) && getfield(mt.module, mt.name) === f - mod = active_module() - if is_exported_from_stdlib(mt.name, mt.module) || mt.module === mod - show_sym(io, mt.name) - else + # this used to call the removed internal function `is_exported_from_stdlib`, which effectively + # just checked for exports from Core and Base. + mod = get(io, :module, UsesCoreAndBaseOnly) + if !(isvisible(mt.name, mt.module, mod) || mt.module === mod) print(io, mt.module, ".") - show_sym(io, mt.name) end + show_sym(io, mt.name) else fallback(io, f) end @@ -737,9 +729,9 @@ end function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, wheres::Vector) if !(get(io, :compact, false)::Bool) # Print module prefix unless alias is visible from module passed to - # IOContext. If :module is not set, default to Main (or current active module). + # IOContext. If :module is not set, default to Main. # nothing can be used to force printing prefix. - from = get(io, :module, active_module()) + from = get(io, :module, Main) if (from === nothing || !isvisible(name.name, name.mod, from)) show(io, name.mod) print(io, ".") @@ -1053,9 +1045,9 @@ function show_type_name(io::IO, tn::Core.TypeName) quo = false if !(get(io, :compact, false)::Bool) # Print module prefix unless type is visible from module passed to - # IOContext If :module is not set, default to Main (or current active module). + # IOContext If :module is not set, default to Main. # nothing can be used to force printing prefix - from = get(io, :module, active_module()) + from = get(io, :module, Main) if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from::Module)) show(io, tn.module) print(io, ".") @@ -2535,7 +2527,7 @@ function show_signature_function(io::IO, @nospecialize(ft), demangle=false, farg uw = unwrap_unionall(ft) if ft <: Function && isa(uw, DataType) && isempty(uw.parameters) && _isself(uw) uwmod = parentmodule(uw) - if qualified && !is_exported_from_stdlib(uw.name.mt.name, uwmod) && uwmod !== Main + if qualified && !isexported(uwmod, uw.name.mt.name) && uwmod !== Main print_within_stacktrace(io, uwmod, '.', bold=true) end s = sprint(show_sym, (demangle ? demangle_function_name : identity)(uw.name.mt.name), context=io) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 67f5860082c8a..585ff1aa775b7 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -329,7 +329,7 @@ function warn_on_non_owning_accesses(current_mod, ast) end return ast end -warn_on_non_owning_accesses(ast) = warn_on_non_owning_accesses(REPL.active_module(), ast) +warn_on_non_owning_accesses(ast) = warn_on_non_owning_accesses(Base.active_module(), ast) const repl_ast_transforms = Any[softscope, warn_on_non_owning_accesses] # defaults for new REPL backends @@ -497,7 +497,7 @@ end function display(d::REPLDisplay, mime::MIME"text/plain", x) x = Ref{Any}(x) with_repl_linfo(d.repl) do io - io = IOContext(io, :limit => true, :module => active_module(d)::Module) + io = IOContext(io, :limit => true, :module => Base.active_module(d)::Module) if d.repl isa LineEditREPL mistate = d.repl.mistate mode = LineEdit.mode(mistate) @@ -527,7 +527,7 @@ show_repl(io::IO, ::MIME"text/plain", ex::Expr) = function print_response(repl::AbstractREPL, response, show_value::Bool, have_color::Bool) repl.waserror = response[2] with_repl_linfo(repl) do io - io = IOContext(io, :module => active_module(repl)::Module) + io = IOContext(io, :module => Base.active_module(repl)::Module) print_response(io, response, show_value, have_color, specialdisplay(repl)) end return nothing @@ -628,7 +628,7 @@ function run_repl(repl::AbstractREPL, @nospecialize(consumer = x -> nothing); ba Core.println(Core.stderr, e) Core.println(Core.stderr, catch_backtrace()) end - get_module = () -> active_module(repl) + get_module = () -> Base.active_module(repl) if backend_on_current_task t = @async run_frontend(repl, backend_ref) errormonitor(t) @@ -760,14 +760,9 @@ REPLCompletionProvider() = REPLCompletionProvider(LineEdit.Modifiers()) mutable struct ShellCompletionProvider <: CompletionProvider end struct LatexCompletions <: CompletionProvider end -function active_module() # this method is also called from Base - isdefined(Base, :active_repl) || return Main - Base.active_repl === nothing && return Main - return active_module(Base.active_repl::AbstractREPL) -end -active_module((; mistate)::LineEditREPL) = mistate === nothing ? Main : mistate.active_module -active_module(::AbstractREPL) = Main -active_module(d::REPLDisplay) = active_module(d.repl) +Base.active_module((; mistate)::LineEditREPL) = mistate === nothing ? Main : mistate.active_module +Base.active_module(::AbstractREPL) = Main +Base.active_module(d::REPLDisplay) = Base.active_module(d.repl) setmodifiers!(c::CompletionProvider, m::LineEdit.Modifiers) = nothing @@ -1206,7 +1201,7 @@ enable_promptpaste(v::Bool) = JL_PROMPT_PASTE[] = v function contextual_prompt(repl::LineEditREPL, prompt::Union{String,Function}) function () - mod = active_module(repl) + mod = Base.active_module(repl) prefix = mod == Main ? "" : string('(', mod, ") ") pr = prompt isa String ? prompt : prompt() prefix * pr From 5a633b7c8400cf3ae36cfebab62c5a316fc46649 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Fri, 16 Aug 2024 15:30:48 -0300 Subject: [PATCH 199/206] Fix fast getptls ccall lowering. (#55507) --- src/ccall.cpp | 3 +-- src/julia_threads.h | 3 --- test/compiler/codegen.jl | 3 +++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 97315d46b6ead..36808e13fdbf9 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1671,9 +1671,8 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) emit_gc_safepoint(ctx.builder, ctx.types().T_size, get_current_ptls(ctx), ctx.tbaa().tbaa_const); return ghostValue(ctx, jl_nothing_type); } - else if (is_libjulia_func("jl_get_ptls_states")) { + else if (is_libjulia_func(jl_get_ptls_states)) { ++CCALL_STAT(jl_get_ptls_states); - assert(lrt == ctx.types().T_size); assert(!isVa && !llvmcall && nccallargs == 0); JL_GC_POP(); return mark_or_box_ccall_result(ctx, get_current_ptls(ctx), retboxed, rt, unionall, static_rt); diff --git a/src/julia_threads.h b/src/julia_threads.h index 3486c5b969383..9a2a8cec375f5 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -206,10 +206,7 @@ typedef struct _jl_tls_states_t { #endif } jl_tls_states_t; -#ifndef JL_LIBRARY_EXPORTS -// deprecated (only for external consumers) JL_DLLEXPORT void *jl_get_ptls_states(void); -#endif // Update codegen version in `ccall.cpp` after changing either `pause` or `wake` #ifdef __MIC__ diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index c74dfbb29d3dd..cb983d7ab515e 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -966,3 +966,6 @@ end let x = Incomplete55396(55396) @test x.x === (55396,) end + +# Core.getptls() special handling +@test !occursin("call ptr @jlplt", get_llvm(Core.getptls, Tuple{})) #It should lower to a direct load of the ptls and not a ccall From f2fc2d903558fecee55d7aebf3536692ff278fed Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:58:08 -0400 Subject: [PATCH 200/206] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=207aef1f044=20to=20d1d2fc986=20(#55511)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 | 1 - .../Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 | 1 - .../Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/md5 | 1 + .../Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/md5 create mode 100644 deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/sha512 diff --git a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 deleted file mode 100644 index 218260c77ea07..0000000000000 --- a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -832f88c404516179ece213581cd227f8 diff --git a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 b/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 deleted file mode 100644 index fc763c8d86f40..0000000000000 --- a/deps/checksums/Pkg-7aef1f044f3483e8b07d33fb4cfe918be554de69.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -4355bb51a7f83bde489e587527e1e3a9c70799a5c0d27cd7f42b4227a5fbca2a1200a83db0317a75c582ee997bec72e9e8afafb059c395bd46e2aa015f481dca diff --git a/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/md5 b/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/md5 new file mode 100644 index 0000000000000..097013569ceae --- /dev/null +++ b/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/md5 @@ -0,0 +1 @@ +725181b382adb22ad4f1f5e78db526ed diff --git a/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/sha512 b/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/sha512 new file mode 100644 index 0000000000000..d6d8155431023 --- /dev/null +++ b/deps/checksums/Pkg-d1d2fc986e7249909b450979acc4d359aacfc88e.tar.gz/sha512 @@ -0,0 +1 @@ +9ab56f368d5075a6f514ab8d2169239b439610c9bc9aca67a45a8a834b4d4ae7988910de3c78a687e40623fcd8bc9ba4aeee64ae7edf2cc84f1945b7e543a559 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 964c43dfcc786..cc38c67021224 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 7aef1f044f3483e8b07d33fb4cfe918be554de69 +PKG_SHA1 = d1d2fc986e7249909b450979acc4d359aacfc88e PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From 0a26e908e77f147a5a964735ad02f74d047fe47b Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 16 Aug 2024 20:58:30 +0100 Subject: [PATCH 201/206] update precompile progress bar to match Pkg (#55512) --- base/precompilation.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index aa70718eab9bc..6997ce12c8d01 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -304,9 +304,10 @@ function show_progress(io::IO, p::MiniProgressBar; termwidth=nothing, carriagere to_print = sprint(; context=io) do io print(io, " "^p.indent) printstyled(io, p.header, color=p.color, bold=true) - print(io, " [") - print(io, "="^n_filled, ">") - print(io, " "^n_left, "] ", ) + print(io, " ") + printstyled(io, "━"^n_filled; color=p.color) + printstyled(io, perc >= 95 ? "━" : "╸"; color=p.color) + printstyled(io, "━"^n_left, " "; color=:light_black) print(io, progress_text) carriagereturn && print(io, "\r") end From 8a19b74b5f849f6832a0bfcb689f6407300e9a80 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 17 Aug 2024 19:15:58 +0530 Subject: [PATCH 202/206] Update symmetric docstring to reflect the type of uplo (#55504) This brings the docstring closer to the actual implementation. In particular, following the current docstring and defining ```julia symmetric(::MyMatrix, uplo=:U) ``` leads to a method ambiguity, as `LinearAlgebra` defines `symmetric(::AbstractMatrix, uplo::Symbol=:U)`. --- stdlib/LinearAlgebra/src/symmetric.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index d801158232673..55630595f6fb2 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -12,7 +12,7 @@ struct Symmetric{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T} end end """ - Symmetric(A, uplo=:U) + Symmetric(A::AbstractMatrix, uplo::Symbol=:U) Construct a `Symmetric` view of the upper (if `uplo = :U`) or lower (if `uplo = :L`) triangle of the matrix `A`. @@ -63,7 +63,7 @@ function Symmetric(A::AbstractMatrix, uplo::Symbol=:U) end """ - symmetric(A, uplo=:U) + symmetric(A, uplo::Symbol=:U) Construct a symmetric view of `A`. If `A` is a matrix, `uplo` controls whether the upper (if `uplo = :U`) or lower (if `uplo = :L`) triangle of `A` is used to implicitly fill the @@ -105,7 +105,7 @@ struct Hermitian{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T} end end """ - Hermitian(A, uplo=:U) + Hermitian(A::AbstractMatrix, uplo::Symbol=:U) Construct a `Hermitian` view of the upper (if `uplo = :U`) or lower (if `uplo = :L`) triangle of the matrix `A`. @@ -153,7 +153,7 @@ function Hermitian(A::AbstractMatrix, uplo::Symbol=:U) end """ - hermitian(A, uplo=:U) + hermitian(A, uplo::Symbol=:U) Construct a hermitian view of `A`. If `A` is a matrix, `uplo` controls whether the upper (if `uplo = :U`) or lower (if `uplo = :L`) triangle of `A` is used to implicitly fill the @@ -998,7 +998,7 @@ function cbrt(A::HermOrSym{<:Real}) end """ - hermitianpart(A, uplo=:U) -> Hermitian + hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) -> Hermitian Return the Hermitian part of the square matrix `A`, defined as `(A + A') / 2`, as a [`Hermitian`](@ref) matrix. For real matrices `A`, this is also known as the symmetric part @@ -1014,7 +1014,7 @@ See also [`hermitianpart!`](@ref) for the corresponding in-place operation. hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo) """ - hermitianpart!(A, uplo=:U) -> Hermitian + hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) -> Hermitian Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return [`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric From faa6095e983fed777007274f4efb9911154b1f3d Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 17 Aug 2024 17:00:26 +0200 Subject: [PATCH 203/206] Demote(B)Float16 pass: only keep enabled for PPC. (#55486) LLVM should handle this properly now for everything but PPC (where BFoat16 isn't supported anyway). --- src/llvm-demote-float16.cpp | 47 ++++++++++-------------- test/llvmpasses/fastmath.jl | 26 -------------- test/llvmpasses/float16.ll | 71 +++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 57 deletions(-) diff --git a/src/llvm-demote-float16.cpp b/src/llvm-demote-float16.cpp index 5d0d9f5d37c40..7f1b076897fc8 100644 --- a/src/llvm-demote-float16.cpp +++ b/src/llvm-demote-float16.cpp @@ -49,37 +49,28 @@ extern JuliaOJIT *jl_ExecutionEngine; namespace { -static bool have_fp16(Function &caller, const Triple &TT) { - Attribute FSAttr = caller.getFnAttribute("target-features"); - StringRef FS = ""; - if (FSAttr.isValid()) - FS = FSAttr.getValueAsString(); - else if (jl_ExecutionEngine) - FS = jl_ExecutionEngine->getTargetFeatureString(); - // else probably called from opt, just do nothing - if (TT.isAArch64()) { - if (FS.find("+fp16fml") != llvm::StringRef::npos || FS.find("+fullfp16") != llvm::StringRef::npos){ - return true; - } - } else if (TT.getArch() == Triple::x86_64) { - if (FS.find("+avx512fp16") != llvm::StringRef::npos){ - return true; - } - } - if (caller.hasFnAttribute("julia.hasfp16")) { - return true; - } - return false; +static bool have_fp16(Function &F, const Triple &TT) { + // for testing purposes + Attribute Attr = F.getFnAttribute("julia.hasfp16"); + if (Attr.isValid()) + return Attr.getValueAsBool(); + + // llvm/llvm-project#97975: on some platforms, `half` uses excessive precision + if (TT.isPPC()) + return false; + + return true; } -static bool have_bf16(Function &caller, const Triple &TT) { - if (caller.hasFnAttribute("julia.hasbf16")) { - return true; - } +static bool have_bf16(Function &F, const Triple &TT) { + // for testing purposes + Attribute Attr = F.getFnAttribute("julia.hasbf16"); + if (Attr.isValid()) + return Attr.getValueAsBool(); - // there's no targets that fully support bfloat yet;, - // AVX512BF16 only provides conversion and dot product instructions. - return false; + // https://github.com/llvm/llvm-project/issues/97975#issuecomment-2218770199: + // on current versions of LLVM, bf16 always uses TypeSoftPromoteHalf + return true; } static bool demoteFloat16(Function &F) diff --git a/test/llvmpasses/fastmath.jl b/test/llvmpasses/fastmath.jl index dd0892be56a0b..3c4c1d491ec28 100644 --- a/test/llvmpasses/fastmath.jl +++ b/test/llvmpasses/fastmath.jl @@ -16,29 +16,3 @@ import Base.FastMath # CHECK: call fast float @llvm.sqrt.f32(float %"x::Float32") emit(FastMath.sqrt_fast, Float32) - - -# Float16 operations should be performed as Float32, unless @fastmath is specified -# TODO: this is not true for platforms that natively support Float16 - -foo(x::T,y::T) where T = x-y == zero(T) -# CHECK: define {{(swiftcc )?}}i8 @julia_foo_{{[0-9]+}}({{.*}}half %[[X:"x::Float16"]], half %[[Y:"y::Float16"]]) {{.*}}{ -# CHECK-DAG: %[[XEXT:[0-9]+]] = fpext half %[[X]] to float -# CHECK-DAG: %[[YEXT:[0-9]+]] = fpext half %[[Y]] to float -# CHECK: %[[DIFF:[0-9]+]] = fsub float %[[XEXT]], %[[YEXT]] -# CHECK: %[[TRUNC:[0-9]+]] = fptrunc float %[[DIFF]] to half -# CHECK: %[[DIFFEXT:[0-9]+]] = fpext half %[[TRUNC]] to float -# CHECK: %[[CMP:[0-9]+]] = fcmp oeq float %[[DIFFEXT]], 0.000000e+00 -# CHECK: %[[ZEXT:[0-9]+]] = zext i1 %[[CMP]] to i8 -# CHECK: ret i8 %[[ZEXT]] -# CHECK: } -emit(foo, Float16, Float16) - -@fastmath foo(x::T,y::T) where T = x-y == zero(T) -# CHECK: define {{(swiftcc )?}}i8 @julia_foo_{{[0-9]+}}({{.*}}half %[[X:"x::Float16"]], half %[[Y:"y::Float16"]]) {{.*}}{ -# CHECK: %[[DIFF:[0-9]+]] = fsub fast half %[[X]], %[[Y]] -# CHECK: %[[CMP:[0-9]+]] = fcmp fast oeq half %[[DIFF]], 0xH0000 -# CHECK: %[[ZEXT:[0-9]+]] = zext i1 %[[CMP]] to i8 -# CHECK: ret i8 %[[ZEXT]] -# CHECK: } -emit(foo, Float16, Float16) diff --git a/test/llvmpasses/float16.ll b/test/llvmpasses/float16.ll index 33069c71179ed..d1dfb6aca11dd 100644 --- a/test/llvmpasses/float16.ll +++ b/test/llvmpasses/float16.ll @@ -99,7 +99,7 @@ top: ret half %13 } -define bfloat @demote_bfloat_test(bfloat %a, bfloat %b) { +define bfloat @demote_bfloat_test(bfloat %a, bfloat %b) #2 { top: ; CHECK-LABEL: @demote_bfloat_test( ; CHECK-NEXT: top: @@ -160,5 +160,70 @@ top: ret bfloat %13 } -attributes #0 = { "target-features"="-avx512fp16" } -attributes #1 = { "target-features"="+avx512fp16" } +define bfloat @native_bfloat_test(bfloat %a, bfloat %b) #3 { +top: +; CHECK-LABEL: @native_bfloat_test( +; CHECK-NEXT: top: +; CHECK-NEXT: %0 = fadd bfloat %a, %b +; CHECK-NEXT: %1 = fadd bfloat %0, %b +; CHECK-NEXT: %2 = fadd bfloat %1, %b +; CHECK-NEXT: %3 = fmul bfloat %2, %b +; CHECK-NEXT: %4 = fdiv bfloat %3, %b +; CHECK-NEXT: %5 = insertelement <2 x bfloat> undef, bfloat %a, i32 0 +; CHECK-NEXT: %6 = insertelement <2 x bfloat> %5, bfloat %b, i32 1 +; CHECK-NEXT: %7 = insertelement <2 x bfloat> undef, bfloat %b, i32 0 +; CHECK-NEXT: %8 = insertelement <2 x bfloat> %7, bfloat %b, i32 1 +; CHECK-NEXT: %9 = fadd <2 x bfloat> %6, %8 +; CHECK-NEXT: %10 = extractelement <2 x bfloat> %9, i32 0 +; CHECK-NEXT: %11 = extractelement <2 x bfloat> %9, i32 1 +; CHECK-NEXT: %12 = fadd bfloat %10, %11 +; CHECK-NEXT: %13 = fadd bfloat %12, %4 +; CHECK-NEXT: ret bfloat %13 +; + %0 = fadd bfloat %a, %b + %1 = fadd bfloat %0, %b + %2 = fadd bfloat %1, %b + %3 = fmul bfloat %2, %b + %4 = fdiv bfloat %3, %b + %5 = insertelement <2 x bfloat> undef, bfloat %a, i32 0 + %6 = insertelement <2 x bfloat> %5, bfloat %b, i32 1 + %7 = insertelement <2 x bfloat> undef, bfloat %b, i32 0 + %8 = insertelement <2 x bfloat> %7, bfloat %b, i32 1 + %9 = fadd <2 x bfloat> %6, %8 + %10 = extractelement <2 x bfloat> %9, i32 0 + %11 = extractelement <2 x bfloat> %9, i32 1 + %12 = fadd bfloat %10, %11 + %13 = fadd bfloat %12, %4 + ret bfloat %13 +} + +define i1 @fast_half_test(half %0, half %1) #0 { +top: +; CHECK-LABEL: @fast_half_test( +; CHECK-NEXT: top: +; CHECK-NEXT: %2 = fsub fast half %0, %1 +; CHECK-NEXT: %3 = fcmp fast oeq half %2, 0xH0000 +; CHECK-NEXT: ret i1 %3 +; + %2 = fsub fast half %0, %1 + %3 = fcmp fast oeq half %2, 0xH0000 + ret i1 %3 +} + +define i1 @fast_bfloat_test(bfloat %0, bfloat %1) #2 { +top: +; CHECK-LABEL: @fast_bfloat_test( +; CHECK-NEXT: top: +; CHECK-NEXT: %2 = fsub fast bfloat %0, %1 +; CHECK-NEXT: %3 = fcmp fast oeq bfloat %2, 0xR0000 +; CHECK-NEXT: ret i1 %3 +; + %2 = fsub fast bfloat %0, %1 + %3 = fcmp fast oeq bfloat %2, 0xR0000 + ret i1 %3 +} + +attributes #0 = { "julia.hasfp16"="false" } +attributes #1 = { "julia.hasfp16"="true" } +attributes #2 = { "julia.hasbf16"="false" } +attributes #3 = { "julia.hasbf16"="true" } From 4aa9dfa25bde12be7daae2680445eb477eab5da9 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 17 Aug 2024 17:25:11 -0400 Subject: [PATCH 204/206] Some small tests for transcode (#55436) This logic appears to be [uncovered](https://app.codecov.io/gh/JuliaLang/julia/blob/master/base%2Fstrings%2Fcstring.jl#L232) although it does have a doctest! Running the tests locally managed to trigger these functions. --- test/strings/basic.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 87d812c5bf201..d8ca4d204b6f4 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -1388,3 +1388,10 @@ end end end end + +@testset "transcode" begin + str = "αβγ" + @test transcode(String, transcode(UInt16, str)) == str + @test transcode(String, transcode(UInt16, transcode(UInt8, str))) == str + @test transcode(String, transcode(UInt8, transcode(UInt16, str))) == str +end From dff0f55e6154ef85c1e8e422e8553d3a3c0729be Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 18 Aug 2024 09:50:06 +0530 Subject: [PATCH 205/206] Avoid using zero for the eltype in `tr(::Matrix)` (#55519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets us compute the `tr` for `Matrix`es where the `eltype` does not have a zero, but we may sum over the diagonal. E.g. the following works after this: ```julia julia> M = fill([1 2; 3 4], 2, 2) 2×2 Matrix{Matrix{Int64}}: [1 2; 3 4] [1 2; 3 4] [1 2; 3 4] [1 2; 3 4] julia> tr(M) 2×2 Matrix{Int64}: 2 4 6 8 ``` Also, using linear indexing over Cartesian appears to provide a slight speed-up for small to mid-sized matrices: ```julia julia> A = rand(1000,1000); julia> @btime tr($A); 1.796 μs (0 allocations: 0 bytes) # nightly 1.524 μs (0 allocations: 0 bytes) # This PR ``` --- stdlib/LinearAlgebra/src/dense.jl | 9 +++------ stdlib/LinearAlgebra/test/dense.jl | 12 ++++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 94a075ffaf24d..545801b065fb5 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -371,12 +371,9 @@ diagm(v::AbstractVector) = diagm(0 => v) diagm(m::Integer, n::Integer, v::AbstractVector) = diagm(m, n, 0 => v) function tr(A::Matrix{T}) where T - n = checksquare(A) - t = zero(T) - @inbounds @simd for i in 1:n - t += A[i,i] - end - t + checksquare(A) + isempty(A) && return zero(T) + reduce(+, (A[i] for i in diagind(A))) end _kronsize(A::AbstractMatrix, B::AbstractMatrix) = map(*, size(A), size(B)) diff --git a/stdlib/LinearAlgebra/test/dense.jl b/stdlib/LinearAlgebra/test/dense.jl index afc1df817a544..b9af413ad8319 100644 --- a/stdlib/LinearAlgebra/test/dense.jl +++ b/stdlib/LinearAlgebra/test/dense.jl @@ -1285,4 +1285,16 @@ end @test eltype(A) == eltype(T) end +@testset "tr" begin + @testset "block matrices" begin + S = [1 2; 3 4] + M = fill(S, 3, 3) + @test tr(M) == 3S + end + @testset "avoid promotion" begin + A = Int8[1 3; 2 4] + @test tr(A) === Int8(5) + end +end + end # module TestDense From 306cee71560e24d26585fd1143a2aacac41b5508 Mon Sep 17 00:00:00 2001 From: matthias314 <56549971+matthias314@users.noreply.github.com> Date: Sun, 18 Aug 2024 07:32:11 -0400 Subject: [PATCH 206/206] remove redundant `print` method for `Splat` (#55494) also a related bugfix by Jameson Nash --- base/operators.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index 2c8070b44d704..d01902e302359 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1339,8 +1339,7 @@ struct Splat{F} <: Function Splat(f) = new{Core.Typeof(f)}(f) end (s::Splat)(args) = s.f(args...) -print(io::IO, s::Splat) = print(io, "splat(", s.f, ')') -show(io::IO, s::Splat) = print(io, s) +show(io::IO, s::Splat) = (print(io, "splat("); show(io, s.f); print(io, ")")) ## in and related operators