Skip to content

Commit 213feae

Browse files
authored
Backports for Julia 1.10.8 (#56653)
2 parents 4976d05 + 4d7bdbf commit 213feae

File tree

44 files changed

+365
-41
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+365
-41
lines changed

base/abstractdict.jl

+8-4
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ Return an iterator over all keys in a dictionary.
8686
When the keys are stored internally in a hash table,
8787
as is the case for `Dict`,
8888
the order in which they are returned may vary.
89-
But `keys(a)` and `values(a)` both iterate `a` and
90-
return the elements in the same order.
89+
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
90+
and return the elements in the same order.
9191
9292
# Examples
9393
```jldoctest
@@ -112,8 +112,8 @@ Return an iterator over all values in a collection.
112112
When the values are stored internally in a hash table,
113113
as is the case for `Dict`,
114114
the order in which they are returned may vary.
115-
But `keys(a)` and `values(a)` both iterate `a` and
116-
return the elements in the same order.
115+
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
116+
and return the elements in the same order.
117117
118118
# Examples
119119
```jldoctest
@@ -136,6 +136,10 @@ values(a::AbstractDict) = ValueIterator(a)
136136
Return an iterator over `key => value` pairs for any
137137
collection that maps a set of keys to a set of values.
138138
This includes arrays, where the keys are the array indices.
139+
When the entries are stored internally in a hash table,
140+
as is the case for `Dict`, the order in which they are returned may vary.
141+
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
142+
and return the elements in the same order.
139143
140144
# Examples
141145
```jldoctest

base/binaryplatforms.jl

+1
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ const arch_mapping = Dict(
593593
"armv7l" => "arm(v7l)?", # if we just see `arm-linux-gnueabihf`, we assume it's `armv7l`
594594
"armv6l" => "armv6l",
595595
"powerpc64le" => "p(ower)?pc64le",
596+
"riscv64" => "(rv64|riscv64)",
596597
)
597598
# Keep this in sync with `CPUID.ISAs_by_family`
598599
# These are the CPUID side of the microarchitectures targeted by GCC flags in BinaryBuilder.jl

base/compiler/ssair/domtree.jl

+2
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@ end
644644
Compute the nearest common (post-)dominator of `a` and `b`.
645645
"""
646646
function nearest_common_dominator(domtree::GenericDomTree, a::BBNumber, b::BBNumber)
647+
a == 0 && return a
648+
b == 0 && return b
647649
alevel = domtree.nodes[a].level
648650
blevel = domtree.nodes[b].level
649651
# W.l.g. assume blevel <= alevel

base/compiler/ssair/passes.jl

+1
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse
12941294
end
12951295
all(check_defuse, defuse.uses) || return nothing
12961296
all(check_defuse, defuse.defs) || return nothing
1297+
bb_insert_block != 0 || return nothing # verify post-dominator of all uses exists
12971298

12981299
# Check #3
12991300
dominates(domtree, finalizer_bb, bb_insert_block) || return nothing

base/docs/basedocs.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,7 @@ kw"new"
14411441
"""
14421442
where
14431443
1444-
The `where` keyword creates a type that is an iterated union of other types, over all
1444+
The `where` keyword creates a [`UnionAll`](@ref) type, which may be thought of as an iterated union of other types, over all
14451445
values of some variable. For example `Vector{T} where T<:Real` includes all [`Vector`](@ref)s
14461446
where the element type is some kind of `Real` number.
14471447
@@ -3296,6 +3296,9 @@ unused and delete the entire benchmark code).
32963296
!!! compat "Julia 1.8"
32973297
This method was added in Julia 1.8.
32983298
3299+
!!! compat "Julia 1.8"
3300+
This method was added in Julia 1.8.
3301+
32993302
# Examples
33003303
33013304
```julia

base/loading.jl

+10-2
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,12 @@ end
613613
## generic project & manifest API ##
614614

615615
const project_names = ("JuliaProject.toml", "Project.toml")
616-
const manifest_names = ("JuliaManifest.toml", "Manifest.toml")
616+
const manifest_names = (
617+
"JuliaManifest-v$(VERSION.major).$(VERSION.minor).toml",
618+
"Manifest-v$(VERSION.major).$(VERSION.minor).toml",
619+
"JuliaManifest.toml",
620+
"Manifest.toml",
621+
)
617622
const preferences_names = ("JuliaLocalPreferences.toml", "LocalPreferences.toml")
618623

619624
function locate_project_file(env::String)
@@ -1215,6 +1220,7 @@ function run_module_init(mod::Module, i::Int=1)
12151220
end
12161221

12171222
function run_package_callbacks(modkey::PkgId)
1223+
(modkey == precompilation_target) && return nothing
12181224
run_extension_callbacks(modkey)
12191225
assert_havelock(require_lock)
12201226
unlock(require_lock)
@@ -1338,7 +1344,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
13381344
# TODO: Better error message if this lookup fails?
13391345
uuid_trigger = UUID(totaldeps[trigger]::String)
13401346
trigger_id = PkgId(uuid_trigger, trigger)
1341-
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id)
1347+
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) || (trigger_id == precompilation_target)
13421348
trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
13431349
push!(trigger1, gid)
13441350
else
@@ -1350,6 +1356,7 @@ end
13501356

13511357
loading_extension::Bool = false
13521358
precompiling_extension::Bool = false
1359+
precompilation_target::Union{Nothing,PkgId} = nothing
13531360
function run_extension_callbacks(extid::ExtensionId)
13541361
assert_havelock(require_lock)
13551362
succeeded = try
@@ -2342,6 +2349,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
23422349
write(io.in, """
23432350
empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated
23442351
Base.precompiling_extension = $(loading_extension)
2352+
Base.precompilation_target = $(pkg_str(pkg))
23452353
Base.include_package_for_output($(pkg_str(pkg)), $(repr(abspath(input))), $(repr(depot_path)), $(repr(dl_load_path)),
23462354
$(repr(load_path)), $deps, $(repr(source_path(nothing))))
23472355
""")

base/mathconstants.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ end
2929
Base.@assume_effects :foldable function (::Type{T})(x::_KnownIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}}
3030
Base._irrational_to_float(T, x, r)
3131
end
32-
Base.@assume_effects :foldable function rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
32+
Base.@assume_effects :foldable function Base.rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
3333
Base._rationalize_irrational(T, x, tol)
3434
end
3535
Base.@assume_effects :foldable function Base.lessrational(rx::Rational, x::_KnownIrrational)

base/meta.jl

+5
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,15 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
365365
return x
366366
end
367367
if isa(x, Core.ReturnNode)
368+
# Unreachable doesn't have val defined
369+
if !isdefined(x, :val)
370+
return x
371+
else
368372
return Core.ReturnNode(
369373
_partially_inline!(x.val, slot_replacements, type_signature, static_param_values,
370374
slot_offset, statement_offset, boundscheck),
371375
)
376+
end
372377
end
373378
if isa(x, Core.GotoIfNot)
374379
return Core.GotoIfNot(

base/special/exp.jl

+2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ end
216216
small_part = muladd(jU, expm1b_kernel(base, r), jL) + jU
217217

218218
if !(abs(x) <= SUBNORM_EXP(base, T))
219+
isnan(x) && return x
219220
x >= MAX_EXP(base, T) && return Inf
220221
x <= MIN_EXP(base, T) && return 0.0
221222
if k <= -53
@@ -243,6 +244,7 @@ end
243244
hi, lo = Base.canonicalize2(1.0, kern)
244245
small_part = fma(jU, hi, muladd(jU, (lo+xlo), very_small))
245246
if !(abs(x) <= SUBNORM_EXP(base, T))
247+
isnan(x) && return x
246248
x >= MAX_EXP(base, T) && return Inf
247249
x <= MIN_EXP(base, T) && return 0.0
248250
if k <= -53

deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/md5

-1
This file was deleted.

deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/sha512

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
220272702d818b059c86d96e5d7b6483
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
f87ae5aee2c875028cca1b6a3a2a6b494317c20b204ee25b0f62e4fa44ad7d74833e0d16ed0fe90747ed81bc1d075427f24f8820573b74335574ceaae14fda5b
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
12b074088311e98aa7b9d03da61cec9b
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
285ceafd68508831fbaa84ce9bb02da6d0cd1619303640dc46a59877214f300ff891c73a8a92a0a34d0e560f7495edfa1a7656e64afc5b908c40849a21dea60e

deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/md5

-1
This file was deleted.

deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/sha512

-1
This file was deleted.

doc/src/manual/code-loading.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Code inclusion is quite straightforward and simple: it evaluates the given sourc
1414

1515
A *package* is a source tree with a standard layout providing functionality that can be reused by other Julia projects. A package is loaded by `import X` or `using X` statements. These statements also make the module named `X`—which results from loading the package code—available within the module where the import statement occurs. The meaning of `X` in `import X` is context-dependent: which `X` package is loaded depends on what code the statement occurs in. Thus, handling of `import X` happens in two stages: first, it determines **what** package is defined to be `X` in this context; second, it determines **where** that particular `X` package is found.
1616

17-
These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`), or folders of source files.
17+
These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`, or the same names suffixed by `-v{major}.{minor}.toml` for specific versions), or folders of source files.
1818

1919

2020
## Federation of packages
@@ -63,7 +63,7 @@ Each kind of environment defines these three maps differently, as detailed in th
6363

6464
### Project environments
6565

66-
A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred.
66+
A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred. However, from Julia v1.10.8 onwards, `(Julia)Manifest-v{major}.{minor}.toml` is recognized as a format to make a given julia version use a specific manifest file i.e. in the same folder, a `Manifest-v1.11.toml` would be used by v1.11 and `Manifest.toml` by any other julia version.
6767

6868
The roots, graph and paths maps of a project environment are defined as follows:
6969

doc/src/manual/complex-and-rational-numbers.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,30 @@ julia> float(3//4)
254254
```
255255

256256
Conversion from rational to floating-point respects the following identity for any integral values
257-
of `a` and `b`, with the exception of the two cases `b == 0` and `a == 0 && b < 0`:
257+
of `a` and `b`, except when `a==0 && b <= 0`:
258258

259259
```jldoctest
260260
julia> a = 1; b = 2;
261261
262262
julia> isequal(float(a//b), a/b)
263263
true
264+
265+
julia> a, b = 0, 0
266+
(0, 0)
267+
268+
julia> float(a//b)
269+
ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)
270+
Stacktrace:
271+
[...]
272+
273+
julia> a/b
274+
NaN
275+
276+
julia> a, b = 0, -1
277+
(0, -1)
278+
279+
julia> float(a//b), a/b
280+
(0.0, -0.0)
264281
```
265282

266283
Constructing infinite rational values is acceptable:

src/jitlayers.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,15 @@ jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES
493493
}
494494
else {
495495
// identify whether this is an invalidated method that is being recompiled
496-
is_recompile = jl_atomic_load_relaxed(&mi->cache) != NULL;
496+
// Is a recompile if there is cached code, and it was compiled (not only inferred) before
497+
jl_code_instance_t *codeinst_old = jl_atomic_load_relaxed(&mi->cache);
498+
while (codeinst_old != NULL) {
499+
if (jl_atomic_load_relaxed(&codeinst_old->invoke) != NULL) {
500+
is_recompile = 1;
501+
break;
502+
}
503+
codeinst_old = jl_atomic_load_relaxed(&codeinst_old->next);
504+
}
497505
}
498506
if (src == NULL && jl_is_method(mi->def.method) &&
499507
jl_symbol_name(mi->def.method->name)[0] != '@') {

src/staticdata.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ void *native_functions; // opaque jl_native_code_desc_t blob used for fetching
433433

434434
// table of struct field addresses to rewrite during saving
435435
static htable_t field_replace;
436+
static htable_t relocatable_ext_cis;
436437

437438
// array of definitions for the predefined function pointers
438439
// (reverse of fptr_to_id)
@@ -656,7 +657,8 @@ static int needs_uniquing(jl_value_t *v) JL_NOTSAFEPOINT
656657

657658
static void record_field_change(jl_value_t **addr, jl_value_t *newval) JL_NOTSAFEPOINT
658659
{
659-
ptrhash_put(&field_replace, (void*)addr, newval);
660+
if (*addr != newval)
661+
ptrhash_put(&field_replace, (void*)addr, newval);
660662
}
661663

662664
static jl_value_t *get_replaceable_field(jl_value_t **addr, int mutabl) JL_GC_DISABLED
@@ -797,6 +799,8 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
797799
// TODO: if (ci in ci->defs->cache)
798800
record_field_change((jl_value_t**)&ci->next, NULL);
799801
}
802+
if (jl_atomic_load_relaxed(&ci->inferred) && !is_relocatable_ci(&relocatable_ext_cis, ci))
803+
record_field_change((jl_value_t**)&ci->inferred, jl_nothing);
800804
}
801805

802806
if (immediate) // must be things that can be recursively handled, and valid as type parameters
@@ -1505,6 +1509,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
15051509
// will check on deserialize if this cache entry is still valid
15061510
}
15071511
}
1512+
newm->relocatability = 0;
15081513
}
15091514

15101515
newm->invoke = NULL;
@@ -2384,7 +2389,7 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
23842389
*edges = jl_alloc_vec_any(0);
23852390
*method_roots_list = jl_alloc_vec_any(0);
23862391
// Collect the new method roots
2387-
jl_collect_new_roots(*method_roots_list, *new_specializations, worklist_key);
2392+
jl_collect_new_roots(&relocatable_ext_cis, *method_roots_list, *new_specializations, worklist_key);
23882393
jl_collect_edges(*edges, *ext_targets, *new_specializations, world);
23892394
}
23902395
assert(edges_map == NULL); // jl_collect_edges clears this when done
@@ -2770,6 +2775,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
27702775
assert((ct->reentrant_timing & 0b1110) == 0);
27712776
ct->reentrant_timing |= 0b1000;
27722777
if (worklist) {
2778+
htable_new(&relocatable_ext_cis, 0);
27732779
jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist),
27742780
&extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges);
27752781
if (!emit_split) {
@@ -2786,6 +2792,8 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
27862792
jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges);
27872793
if (_native_data != NULL)
27882794
native_functions = NULL;
2795+
if (worklist)
2796+
htable_free(&relocatable_ext_cis);
27892797
// make sure we don't run any Julia code concurrently before this point
27902798
// Re-enable running julia code for postoutput hooks, atexit, etc.
27912799
jl_gc_enable_finalizers(ct, 1);

src/staticdata_utils.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited,
208208
return found;
209209
}
210210

211+
static int is_relocatable_ci(htable_t *relocatable_ext_cis, jl_code_instance_t *ci)
212+
{
213+
if (!ci->relocatability)
214+
return 0;
215+
jl_method_instance_t *mi = ci->def;
216+
jl_method_t *m = mi->def.method;
217+
if (!ptrhash_has(relocatable_ext_cis, ci) && jl_object_in_image((jl_value_t*)m) && (!jl_is_method(m) || jl_object_in_image((jl_value_t*)m->module)))
218+
return 0;
219+
return 1;
220+
}
221+
211222
// Given the list of CodeInstances that were inferred during the build, select
212223
// those that are (1) external, (2) still valid, (3) are inferred to be called
213224
// from the worklist or explicitly added by a `precompile` statement, and
@@ -261,7 +272,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list)
261272
}
262273

263274
// New roots for external methods
264-
static void jl_collect_new_roots(jl_array_t *roots, jl_array_t *new_specializations, uint64_t key)
275+
static void jl_collect_new_roots(htable_t *relocatable_ext_cis, jl_array_t *roots, jl_array_t *new_specializations, uint64_t key)
265276
{
266277
htable_t mset;
267278
htable_new(&mset, 0);
@@ -272,6 +283,7 @@ static void jl_collect_new_roots(jl_array_t *roots, jl_array_t *new_specializati
272283
jl_method_t *m = ci->def->def.method;
273284
assert(jl_is_method(m));
274285
ptrhash_put(&mset, (void*)m, (void*)m);
286+
ptrhash_put(relocatable_ext_cis, (void*)ci, (void*)ci);
275287
}
276288
int nwithkey;
277289
void *const *table = mset.table;

src/subtype.c

+42
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,42 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
15721572
return sub;
15731573
}
15741574

1575+
static int equal_var(jl_tvar_t *v, jl_value_t *x, jl_stenv_t *e)
1576+
{
1577+
assert(e->Loffset == 0);
1578+
// Theoretically bounds change would be merged for union inputs.
1579+
// But intersection is not happy as splitting helps to avoid circular env.
1580+
assert(!e->intersection || !jl_is_uniontype(x));
1581+
jl_varbinding_t *vb = lookup(e, v);
1582+
if (e->intersection && vb != NULL && vb->lb == vb->ub && jl_is_typevar(vb->lb))
1583+
return equal_var((jl_tvar_t *)vb->lb, x, e);
1584+
record_var_occurrence(vb, e, 2);
1585+
if (vb == NULL)
1586+
return e->ignore_free || (
1587+
local_forall_exists_subtype(x, v->lb, e, 2, !jl_has_free_typevars(x)) &&
1588+
local_forall_exists_subtype(v->ub, x, e, 0, 0));
1589+
if (!vb->right)
1590+
return local_forall_exists_subtype(x, vb->lb, e, 2, !jl_has_free_typevars(x)) &&
1591+
local_forall_exists_subtype(vb->ub, x, e, 0, 0);
1592+
if (vb->lb == x)
1593+
return var_lt(v, x, e, 0);
1594+
if (!subtype_ccheck(x, vb->ub, e))
1595+
return 0;
1596+
jl_value_t *lb = simple_join(vb->lb, x);
1597+
JL_GC_PUSH1(&lb);
1598+
if (!e->intersection || !jl_is_typevar(lb) || !reachable_var(lb, v, e))
1599+
vb->lb = lb;
1600+
JL_GC_POP();
1601+
if (vb->ub == x)
1602+
return 1;
1603+
if (!subtype_ccheck(vb->lb, x, e))
1604+
return 0;
1605+
// skip `simple_meet` here as we have proven `x <: vb->ub`
1606+
if (!e->intersection || !reachable_var(x, v, e))
1607+
vb->ub = x;
1608+
return 1;
1609+
}
1610+
15751611
static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
15761612
{
15771613
if (obviously_egal(x, y)) return 1;
@@ -1602,6 +1638,12 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
16021638
}
16031639
}
16041640

1641+
if (e->Loffset == 0 && jl_is_typevar(y) && jl_is_type(x) && (!e->intersection || !jl_is_uniontype(x))) {
1642+
// Fastpath for Type == TypeVar.
1643+
// Avoid duplicated `<:` check between adjacent `var_gt` and `var_lt`
1644+
return equal_var((jl_tvar_t *)y, x, e);
1645+
}
1646+
16051647
jl_saved_unionstate_t oldLunions; push_unionstate(&oldLunions, &e->Lunions);
16061648

16071649
int sub = local_forall_exists_subtype(x, y, e, 2, -1);

0 commit comments

Comments
 (0)