Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports for 1.11.3 #56741

Open
wants to merge 23 commits into
base: release-1.11
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c3449dc
subtype: fast path for Type == TypeVar (#56640)
N5N3 Nov 26, 2024
f987397
Fix test report alignment (#56789)
IanButterworth Dec 10, 2024
a788519
fix `exp(weirdNaN)` (#56784)
oscardssmith Dec 10, 2024
9a48815
Fix generate_precompile statement grouping & avoid defining new func …
IanButterworth Dec 11, 2024
3fb7f2e
Fix partially_inline for unreachable (#56787)
wsmoses Dec 12, 2024
790081c
bump Pkg to latest 1.11
Dec 16, 2024
5b83838
xref `UnionAll` in the doc string of `where` (#56411)
nsajko Dec 15, 2024
6f6bc95
docs: fix edge case in rational number conversion `float(a//b)` (#56772)
Priynsh Dec 18, 2024
aa276c3
dict docs: document that ordering of keys/values/pairs match iterate …
cossio Dec 18, 2024
06a372f
Extend `Base.rationalize` instead of defining new function (#56793)
sostock Dec 19, 2024
35ffb65
fix precompilation error printing if `CI` is set (#56905)
simeonschaub Dec 25, 2024
3dd91a1
inference: fix inference error from constructing invalid `TypeVar` (#…
aviatesk Oct 21, 2024
d031595
InteractiveUtils.jl: fixes issue where subtypes resolves bindings and…
dgleich Oct 24, 2024
0ff8f82
irinterp: set `IR_FLAG_REFINED` for narrowed `PhiNode`s (#56391)
aviatesk Nov 1, 2024
45d3238
lowering: don't reverse handler order in `(pop-handler-list ...)` (#5…
topolarity Nov 18, 2024
2adfacc
avoid memory leak in mallocarrays linked list
Jan 2, 2025
905e39a
precompileplkgs: release parallel limiter when waiting for another pr…
IanButterworth Dec 17, 2024
1b75f96
fix jl_mutex_lock deadlock under rr (#56644)
vtjnash Nov 22, 2024
bcb1f11
precompilepkgs: respect loaded dependencies when precompiling for loa…
IanButterworth Dec 30, 2024
6e28217
Don't report only-inferred methods as recompiles (#56914)
IanButterworth Jan 2, 2025
9e39755
rearrange jl_delete_thread to be thread-safe (#56097)
vtjnash Oct 11, 2024
bdf8219
precompile: don't waste memory on useless inferred code (#56749)
vtjnash Dec 9, 2024
8c63ce1
fix backport of #56097
KristofferC Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ Return an iterator over all keys in a dictionary.
When the keys are stored internally in a hash table,
as is the case for `Dict`,
the order in which they are returned may vary.
But `keys(a)` and `values(a)` both iterate `a` and
return the elements in the same order.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand All @@ -114,8 +114,8 @@ Return an iterator over all values in a collection.
When the values are stored internally in a hash table,
as is the case for `Dict`,
the order in which they are returned may vary.
But `keys(a)` and `values(a)` both iterate `a` and
return the elements in the same order.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand All @@ -138,6 +138,10 @@ values(a::AbstractDict) = ValueIterator(a)
Return an iterator over `key => value` pairs for any
collection that maps a set of keys to a set of values.
This includes arrays, where the keys are the array indices.
When the entries are stored internally in a hash table,
as is the case for `Dict`, the order in which they are returned may vary.
But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a`
and return the elements in the same order.

# Examples
```jldoctest
Expand Down
12 changes: 7 additions & 5 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2075,18 +2075,19 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
unionphi = unionphis[i]
phi = unionphi[1]
t = unionphi[2]
inst = compact.result[phi]
if t === Union{}
stmt = compact[SSAValue(phi)][:stmt]::PhiNode
stmt = inst[:stmt]::PhiNode
kill_phi!(compact, phi_uses, 1:length(stmt.values), SSAValue(phi), stmt, true)
made_changes = true
continue
elseif t === Any
continue
elseif ⊑(𝕃ₒ, compact.result[phi][:type], t)
continue
end
⊏ = strictpartialorder(𝕃ₒ)
t ⊏ inst[:type] || continue
to_drop = Int[]
stmt = compact[SSAValue(phi)][:stmt]
stmt = inst[:stmt]
stmt === nothing && continue
stmt = stmt::PhiNode
for i = 1:length(stmt.values)
Expand All @@ -2098,7 +2099,8 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
push!(to_drop, i)
end
end
compact.result[phi][:type] = t
inst[:type] = t
add_flag!(inst, IR_FLAG_REFINED) # t ⊏ inst[:type]
kill_phi!(compact, phi_uses, to_drop, SSAValue(phi), stmt, false)
made_changes = true
end
Expand Down
12 changes: 10 additions & 2 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -587,8 +587,16 @@ add_tfunc(svec, 0, INT_INF, @nospecs((𝕃::AbstractLattice, args...)->SimpleVec
return TypeVar
end
end
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
lb_valid = lb isa Type || lb isa TypeVar
ub_valid = ub isa Type || ub isa TypeVar
if lb_valid && ub_valid
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
elseif !lb_valid && lb_certain
return Union{}
elseif !ub_valid && ub_certain
return Union{}
end
end
return TypeVar
end
Expand Down
2 changes: 1 addition & 1 deletion base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,7 @@ kw"new"
"""
where

The `where` keyword creates a type that is an iterated union of other types, over all
The `where` keyword creates a [`UnionAll`](@ref) type, which may be thought of as an iterated union of other types, over all
values of some variable. For example `Vector{T} where T<:Real` includes all [`Vector`](@ref)s
where the element type is some kind of `Real` number.

Expand Down
2 changes: 1 addition & 1 deletion base/mathconstants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ end
Base.@assume_effects :foldable function (::Type{T})(x::_KnownIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}}
Base._irrational_to_float(T, x, r)
end
Base.@assume_effects :foldable function rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
Base.@assume_effects :foldable function Base.rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer}
Base._rationalize_irrational(T, x, tol)
end
Base.@assume_effects :foldable function Base.lessrational(rx::Rational, x::_KnownIrrational)
Expand Down
5 changes: 5 additions & 0 deletions base/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,15 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
return x
end
if isa(x, Core.ReturnNode)
# Unreachable doesn't have val defined
if !isdefined(x, :val)
return x
else
return Core.ReturnNode(
_partially_inline!(x.val, slot_replacements, type_signature, static_param_values,
slot_offset, statement_offset, boundscheck),
)
end
end
if isa(x, Core.GotoIfNot)
return Core.GotoIfNot(
Expand Down
30 changes: 18 additions & 12 deletions base/precompilation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ function _precompilepkgs(pkgs::Vector{String},
try
# allows processes to wait if another process is precompiling a given package to
# a functionally identical package cache (except for preferences, which may differ)
t = @elapsed ret = precompile_pkgs_maybe_cachefile_lock(io, print_lock, fancyprint, pkg_config, pkgspidlocked, hascolor) do
t = @elapsed ret = precompile_pkgs_maybe_cachefile_lock(io, print_lock, fancyprint, pkg_config, pkgspidlocked, hascolor, parallel_limiter) do
Base.with_logger(Base.NullLogger()) do
# The false here means we ignore loaded modules, so precompile for a fresh session
keep_loaded_modules = false
Expand Down Expand Up @@ -1069,7 +1069,7 @@ function _precompilepkgs(pkgs::Vector{String},
direct = strict ? "" : "direct "
err_msg = "The following $n_direct_errs $(direct)dependenc$(pluralde) failed to precompile:\n$(String(take!(err_str)))"
if internal_call # aka. auto-precompilation
if isinteractive() && !get(ENV, "CI", false)
if isinteractive()
plural1 = length(failed_deps) == 1 ? "y" : "ies"
println(io, " ", color_string("$(length(failed_deps))", Base.error_color()), " dependenc$(plural1) errored.")
println(io, " For a report of the errors see `julia> err`. To retry use `pkg> precompile`")
Expand Down Expand Up @@ -1101,7 +1101,7 @@ function _color_string(cstr::String, col::Union{Int64, Symbol}, hascolor)
end

# Can be merged with `maybe_cachefile_lock` in loading?
function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLock, fancyprint::Bool, pkg_config, pkgspidlocked, hascolor)
function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLock, fancyprint::Bool, pkg_config, pkgspidlocked, hascolor, parallel_limiter::Base.Semaphore)
pkg, config = pkg_config
flags, cacheflags = config
FileWatching = Base.loaded_modules[Base.PkgId(Base.UUID("7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"), "FileWatching")]
Expand All @@ -1122,15 +1122,21 @@ function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLo
!fancyprint && lock(print_lock) do
println(io, " ", pkg.name, _color_string(" Being precompiled by $(pkgspidlocked[pkg_config])", Base.info_color(), hascolor))
end
# wait until the lock is available
FileWatching.mkpidlock(pidfile; stale_age) do
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded=true, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
return f() # precompile
end
Base.release(parallel_limiter) # release so other work can be done while waiting
try
# wait until the lock is available
@invokelatest Base.mkpidlock_hook(() -> begin
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded=true, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
Base.acquire(f, parallel_limiter) # precompile
end
end,
pidfile; stale_age)
finally
Base.acquire(parallel_limiter) # re-acquire so the outer release is balanced
end
end
return cachefile
Expand Down
2 changes: 2 additions & 0 deletions base/special/exp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ end
small_part = muladd(jU, expm1b_kernel(base, r), jL) + jU

if !(abs(x) <= SUBNORM_EXP(base, T))
isnan(x) && return x
x >= MAX_EXP(base, T) && return Inf
x <= MIN_EXP(base, T) && return 0.0
if k <= -53
Expand Down Expand Up @@ -243,6 +244,7 @@ end
hi, lo = Base.canonicalize2(1.0, kern)
small_part = fma(jU, hi, muladd(jU, (lo+xlo), very_small))
if !(abs(x) <= SUBNORM_EXP(base, T))
isnan(x) && return x
x >= MAX_EXP(base, T) && return Inf
x <= MIN_EXP(base, T) && return 0.0
if k <= -53
Expand Down
100 changes: 48 additions & 52 deletions contrib/generate_precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,60 +131,56 @@ for match = Base._methods(+, (Int, Int), -1, Base.get_world_counter())
m = match.method
delete!(push!(Set{Method}(), m), m)
copy(Core.Compiler.retrieve_code_info(Core.Compiler.specialize_method(match), typemax(UInt)))

empty!(Set())
push!(push!(Set{Union{GlobalRef,Symbol}}(), :two), GlobalRef(Base, :two))
(setindex!(Dict{String,Base.PkgId}(), Base.PkgId(Base), "file.jl"))["file.jl"]
(setindex!(Dict{Symbol,Vector{Int}}(), [1], :two))[:two]
(setindex!(Dict{Base.PkgId,String}(), "file.jl", Base.PkgId(Base)))[Base.PkgId(Base)]
(setindex!(Dict{Union{GlobalRef,Symbol}, Vector{Int}}(), [1], :two))[:two]
(setindex!(IdDict{Type, Union{Missing, Vector{Tuple{LineNumberNode, Expr}}}}(), missing, Int))[Int]
Dict{Symbol, Union{Nothing, Bool, Symbol}}(:one => false)[:one]
Dict(Base => [:(1+1)])[Base]
Dict(:one => [1])[:one]
Dict("abc" => Set())["abc"]
pushfirst!([], sum)
get(Base.pkgorigins, Base.PkgId(Base), nothing)
sort!([1,2,3])
unique!([1,2,3])
cumsum([1,2,3])
append!(Int[], BitSet())
isempty(BitSet())
delete!(BitSet([1,2]), 3)
deleteat!(Int32[1,2,3], [1,3])
deleteat!(Any[1,2,3], [1,3])
Core.svec(1, 2) == Core.svec(3, 4)
any(t->t[1].line > 1, [(LineNumberNode(2,:none), :(1+1))])

# Code loading uses this
sortperm(mtime.(readdir(".")), rev=true)
# JLLWrappers uses these
Dict{Base.UUID,Set{String}}()[Base.UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210")] = Set{String}()
get!(Set{String}, Dict{Base.UUID,Set{String}}(), Base.UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210"))
eachindex(IndexLinear(), Expr[])
push!(Expr[], Expr(:return, false))
vcat(String[], String[])
k, v = (:hello => nothing)
Base.print_time_imports_report(Base)
Base.print_time_imports_report_init(Base)

# Preferences uses these
get(Dict{String,Any}(), "missing", nothing)
delete!(Dict{String,Any}(), "missing")
for (k, v) in Dict{String,Any}()
println(k)
end

# interactive startup uses this
write(IOBuffer(), "")

# Not critical, but helps hide unrelated compilation from @time when using --trace-compile.
f55729() = Base.Experimental.@force_compile
@time @eval f55729()
@time @eval f55729()

break # only actually need to do this once
end
empty!(Set())
push!(push!(Set{Union{GlobalRef,Symbol}}(), :two), GlobalRef(Base, :two))
(setindex!(Dict{String,Base.PkgId}(), Base.PkgId(Base), "file.jl"))["file.jl"]
(setindex!(Dict{Symbol,Vector{Int}}(), [1], :two))[:two]
(setindex!(Dict{Base.PkgId,String}(), "file.jl", Base.PkgId(Base)))[Base.PkgId(Base)]
(setindex!(Dict{Union{GlobalRef,Symbol}, Vector{Int}}(), [1], :two))[:two]
(setindex!(IdDict{Type, Union{Missing, Vector{Tuple{LineNumberNode, Expr}}}}(), missing, Int))[Int]
Dict{Symbol, Union{Nothing, Bool, Symbol}}(:one => false)[:one]
Dict(Base => [:(1+1)])[Base]
Dict(:one => [1])[:one]
Dict("abc" => Set())["abc"]
pushfirst!([], sum)
get(Base.pkgorigins, Base.PkgId(Base), nothing)
sort!([1,2,3])
unique!([1,2,3])
cumsum([1,2,3])
append!(Int[], BitSet())
isempty(BitSet())
delete!(BitSet([1,2]), 3)
deleteat!(Int32[1,2,3], [1,3])
deleteat!(Any[1,2,3], [1,3])
Core.svec(1, 2) == Core.svec(3, 4)
any(t->t[1].line > 1, [(LineNumberNode(2,:none), :(1+1))])

# Code loading uses this
sortperm(mtime.(readdir(".")), rev=true)
# JLLWrappers uses these
Dict{Base.UUID,Set{String}}()[Base.UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210")] = Set{String}()
get!(Set{String}, Dict{Base.UUID,Set{String}}(), Base.UUID("692b3bcd-3c85-4b1f-b108-f13ce0eb3210"))
eachindex(IndexLinear(), Expr[])
push!(Expr[], Expr(:return, false))
vcat(String[], String[])
k, v = (:hello => nothing)
Base.print_time_imports_report(Base)
Base.print_time_imports_report_init(Base)

# Preferences uses these
get(Dict{String,Any}(), "missing", nothing)
delete!(Dict{String,Any}(), "missing")
for (k, v) in Dict{String,Any}()
println(k)
end

# interactive startup uses this
write(IOBuffer(), "")

# precompile @time report generation and printing
@time @eval Base.Experimental.@force_compile
"""

julia_exepath() = joinpath(Sys.BINDIR, Base.julia_exename())
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
de072e265659daa77b2722bd82dfe638
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cbc18ea8aab91a4025f5d6ed085ccb5ce1f0ec4be4e8edd86ce37a900eff80ba6fa7f6e216c3af4ed0b2ffc059f9cb999fbdc90980759d3e8d044bf0791fea55
19 changes: 18 additions & 1 deletion doc/src/manual/complex-and-rational-numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,30 @@ julia> float(3//4)
```

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

```jldoctest
julia> a = 1; b = 2;

julia> isequal(float(a//b), a/b)
true

julia> a, b = 0, 0
(0, 0)

julia> float(a//b)
ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)
Stacktrace:
[...]

julia> a/b
NaN

julia> a, b = 0, -1
(0, -1)

julia> float(a//b), a/b
(0.0, -0.0)
```

Constructing infinite rational values is acceptable:
Expand Down
9 changes: 4 additions & 5 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1255,8 +1255,7 @@ static void sweep_malloced_memory(void) JL_NOTSAFEPOINT
*pma = nxt;
int isaligned = (uintptr_t)ma->a & 1;
jl_gc_free_memory(a, isaligned);
ma->next = ptls2->heap.mafreelist;
ptls2->heap.mafreelist = ma;
free(ma);
}
gc_time_count_mallocd_memory(bits);
ma = nxt;
Expand Down Expand Up @@ -3854,10 +3853,10 @@ JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t collection)
jl_atomic_store_release(&ptls->gc_state, JL_GC_STATE_WAITING);
// `jl_safepoint_start_gc()` makes sure only one thread can run the GC.
uint64_t t0 = jl_hrtime();
if (!jl_safepoint_start_gc()) {
if (!jl_safepoint_start_gc(ct)) {
// either another thread is running GC, or the GC got disabled just now.
jl_gc_state_set(ptls, old_state, JL_GC_STATE_WAITING);
jl_safepoint_wait_thread_resume(); // block in thread-suspend now if requested, after clearing the gc_state
jl_safepoint_wait_thread_resume(ct); // block in thread-suspend now if requested, after clearing the gc_state
return;
}

Expand Down Expand Up @@ -3911,7 +3910,7 @@ JL_DLLEXPORT void jl_gc_collect(jl_gc_collection_t collection)
jl_safepoint_end_gc();
jl_gc_state_set(ptls, old_state, JL_GC_STATE_WAITING);
JL_PROBE_GC_END();
jl_safepoint_wait_thread_resume(); // block in thread-suspend now if requested, after clearing the gc_state
jl_safepoint_wait_thread_resume(ct); // block in thread-suspend now if requested, after clearing the gc_state

// Only disable finalizers on current thread
// Doing this on all threads is racy (it's impossible to check
Expand Down
Loading