Skip to content

Commit

Permalink
[release-1.10] Backports for Julia 1.10.0-x (#50971)
Browse files Browse the repository at this point in the history
Backported PRs:
- [x] #48625 <!-- add replace(io, str, patterns...) -->
- [x] #48387 <!-- Improve documentation of sort-related functions -->
- [x] #48363 <!-- Revise sort.md and docstrings in sort.jl -->
- [x] #48977 <!-- Update SparseArrays.jl stdlib for SuiteSparse 7 -->
- [x] #50719 <!-- fix `CyclePadding(::DataType)` -->
- [x] #50694 <!-- inference: permit recursive type traits -->
- [x] #50860 <!-- Add `Base.get_extension` to docs/API -->
- [x] #50594 <!-- Disallow non-index Integer types in isassigned -->
- [x] #50802 <!-- Makes IntrusiveLinkedListSynchronized mutable to avoid
allocation on poptask -->
- [x] #50858 <!-- Add a `threadpool` parameter to `Channel` constructor
-->
- [x] #50874 <!-- Restrict COFF to a single thread when symbol count is
high -->
- [x] #50822 <!-- Add default method for setmodifiers! -->
- [x] #50730 <!-- Fix integer overflow in `isapprox` -->
- [x] #50850 <!-- Remove weird Rational dispatch and add pi functions to
list -->
- [x] #50809 <!-- Limit type-printing in MethodError -->
- [x] #50915 <!-- Add note the `Task` about sticky bit -->
- [x] #50929 <!-- when widening tuple types in tmerge, only widen the
complex parts -->
- [x] #50928 <!-- Bump JuliaSyntax to 0.4.6 -->
- [x] #50959 <!-- Update libssh2 patches -->
- [x] #50823 <!-- Make ranges more robust with unsigned indexes. -->
- [x] #48542 <!-- Add docs on task-specific buffering using
multithreading -->
- [x] #50912 <!-- Separate foreign threads into a :foreign threadpool
-->
- [x] #51010 <!-- Add ORIGIN to SuiteSparse rpath on Linux/FreeBSD -->
- [x] #50753 <!-- cat: remove unused promote_eltype methods that confuse
inference -->
- [x] #51027 <!-- Implement realloc accounting correctly -->
- [x] #51019 <!-- fix a case of potentially use of undefined variable
when handling error in distributed message processing -->
- [x] #51039 <!-- Revert "Optimize findall(f, ::AbstractArray{Bool})
(#42202)" -->
- [x] #51036 <!-- add missing invoke edge for nospecialize targets -->
- [x] #51042 <!-- inference: fix return_type_tfunc modeling of concrete
functions -->
- [x] #51114 <!-- Workaround upstream FreeBSD issue #272992 -->
- [x] #50892 <!-- Add `JL_DLLIMPORT` to `small_typeof` declaration -->
- [x] #51154 <!-- broadcast: use recursion rather than ntuple to map
over a tuple -->
- [x] #51153 <!-- fix debug typo in "add missing invoke edge for
nospecialize targets (#51036)" -->
- [x] #51222 <!-- Check again if the tty is open inside the IO lock -->
- [x] #51236 <!-- Add lock around uv_unref during init -->
- [x] #51243 <!-- GMP: Gracefully handle more overflows. -->
- [x] #51254 <!-- Ryu: make sure adding zeros does not overwrite
trailing dot -->
- [x] #51175 <!-- shorten stale_age for cachefile lock -->
- [x] #51300 <!-- fix method definition error for bad vararg -->
- [x] #51307 <!-- fix force-throw ctrl-C on Windows -->
- [x] #51303 <!-- ensure revising structs is safe -->
- [x] #51393 
- [x] #51403 

Need manual backport:
- [x] #51009 <!-- fix #50562, regression in `in` of tuple of Symbols -->
- [x] #51053 <!-- Bump Statistics stdlib -->
- [x] #51013 <!-- fix #50709, type bound error due to free typevar in
sparam env -->
- [x] #51305 <!-- reduce test time for rounding and floatfuncs -->

Contains multiple commits, manual intervention needed:
- [ ] #50663 <!-- Fix Expr(:loopinfo) codegen -->
- [ ] #51035 <!-- refactor GC scanning code to reflect jl_binding_t are
now first class -->
- [ ] #51092 <!-- inference: fix bad effects for recursion -->
- [x] #51247 <!-- Check if malloc has succeeded before incrementing gc
stats -->
- [x] #51294 <!-- use LibGit2_jll for LibGit2 library -->

Non-merged PRs with backport label:
- [ ] #51132 <!-- Handle `AbstractQ` in concatenation -->
- [x] #51029 <!-- testdefs: make sure that if a test set changes the
active project, they change it back when they're done -->
- [ ] #50919 <!-- Code loading: do the "skipping mtime check for stdlib"
check regardless of the value of `ispath(f)` -->
- [ ] #50824 <!-- Add some aliasing warnings to docstrings for mutating
functions -->
- [x] #50385 <!-- Precompile pidlocks: add to NEWS and docs -->
- [ ] #49805 <!-- Limit TimeType subtraction to AbstractDateTime -->
  • Loading branch information
KristofferC authored Oct 2, 2023
2 parents a468aa1 + e084a40 commit e6378ea
Show file tree
Hide file tree
Showing 132 changed files with 1,357 additions and 780 deletions.
2 changes: 1 addition & 1 deletion Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ endif

# We need python for things like BB triplet recognition. We don't really care
# about version, generally, so just find something that works:
PYTHON := "$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null || echo not found)"
PYTHON := $(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null || echo not found)
PYTHON_SYSTEM := $(shell $(PYTHON) -c 'from __future__ import print_function; import platform; print(platform.system())')

# If we're running on Cygwin, but using a native-windows Python, we need to use cygpath -w
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Compiler/Runtime improvements
* The mark phase of the garbage collector is now multi-threaded ([#48600]).
* [JITLink](https://llvm.org/docs/JITLink.html) is enabled by default on Linux aarch64 when Julia is linked to LLVM 15 or later versions ([#49745]).
This should resolve many segmentation faults previously observed on this platform.
* The precompilation process now uses pidfile locks and orchestrates multiple julia processes to only have one process
spend effort precompiling while the others wait. Previously all would do the work and race to overwrite the cache files.
([#49052])

Command-line option changes
---------------------------
Expand Down
6 changes: 4 additions & 2 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1584,10 +1584,12 @@ replace_in_print_matrix(A::AbstractVector,i::Integer,j::Integer,s::AbstractStrin
eltypeof(x) = typeof(x)
eltypeof(x::AbstractArray) = eltype(x)

promote_eltypeof() = Bottom
promote_eltypeof() = error()
promote_eltypeof(v1) = eltypeof(v1)
promote_eltypeof(v1, vs...) = promote_type(eltypeof(v1), promote_eltypeof(vs...))

promote_eltype() = Bottom
promote_eltype() = error()
promote_eltype(v1) = eltype(v1)
promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))

#TODO: ERROR CHECK
Expand Down
39 changes: 8 additions & 31 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2487,42 +2487,19 @@ function findall(A)
end

# Allocating result upfront is faster (possible only when collection can be iterated twice)
function _findall(f::Function, A::AbstractArray{Bool})
n = count(f, A)
function findall(A::AbstractArray{Bool})
n = count(A)
I = Vector{eltype(keys(A))}(undef, n)
isempty(I) && return I
_findall(f, I, A)
end

function _findall(f::Function, I::Vector, A::AbstractArray{Bool})
cnt = 1
len = length(I)
for (k, v) in pairs(A)
@inbounds I[cnt] = k
cnt += f(v)
cnt > len && return I
end
# In case of impure f, this line could potentially be hit. In that case,
# we can't assume I is the correct length.
resize!(I, cnt - 1)
end

function _findall(f::Function, I::Vector, A::AbstractVector{Bool})
i = firstindex(A)
cnt = 1
len = length(I)
while cnt len
@inbounds I[cnt] = i
cnt += f(@inbounds A[i])
i = nextind(A, i)
for (i,a) in pairs(A)
if a
I[cnt] = i
cnt += 1
end
end
cnt - 1 == len ? I : resize!(I, cnt - 1)
I
end

findall(f::Function, A::AbstractArray{Bool}) = _findall(f, A)
findall(f::Fix2{typeof(in)}, A::AbstractArray{Bool}) = _findall(f, A)
findall(A::AbstractArray{Bool}) = _findall(identity, A)

findall(x::Bool) = x ? [1] : Vector{Int}()
findall(testf::Function, x::Number) = testf(x) ? [1] : Vector{Int}()
findall(p::Fix2{typeof(in)}, x::Number) = x in p.x ? [1] : Vector{Int}()
Expand Down
4 changes: 2 additions & 2 deletions base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -750,8 +750,8 @@ _broadcast_getindex_eltype(A) = eltype(A) # Tuple, Array, etc.
eltypes(::Tuple{}) = Tuple{}
eltypes(t::Tuple{Any}) = Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]))
eltypes(t::Tuple{Any,Any}) = Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), _broadcast_getindex_eltype(t[2]))
# eltypes(t::Tuple) = (TT = eltypes(tail(t)); TT === Union{} ? Union{} : Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), TT.parameters...))
eltypes(t::Tuple) = Iterators.TupleOrBottom(ntuple(i -> _broadcast_getindex_eltype(t[i]), Val(length(t)))...)
eltypes(t::Tuple) = (TT = eltypes(tail(t)); TT === Union{} ? Union{} : Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), TT.parameters...))
# eltypes(t::Tuple) = Iterators.TupleOrBottom(ntuple(i -> _broadcast_getindex_eltype(t[i]), Val(length(t)))...)

# Inferred eltype of result of broadcast(f, args...)
function combine_eltypes(f, args::Tuple)
Expand Down
28 changes: 21 additions & 7 deletions base/channels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Channel(sz=0) = Channel{Any}(sz)

# special constructors
"""
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false)
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing)
Create a new task from `func`, bind it to a new channel of type
`T` and size `size`, and schedule the task, all in a single call.
Expand All @@ -70,9 +70,14 @@ The channel is automatically closed when the task terminates.
If you need a reference to the created task, pass a `Ref{Task}` object via
the keyword argument `taskref`.
If `spawn = true`, the Task created for `func` may be scheduled on another thread
If `spawn=true`, the `Task` created for `func` may be scheduled on another thread
in parallel, equivalent to creating a task via [`Threads.@spawn`](@ref).
If `spawn=true` and the `threadpool` argument is not set, it defaults to `:default`.
If the `threadpool` argument is set (to `:default` or `:interactive`), this implies
that `spawn=true` and the new Task is spawned to the specified threadpool.
Return a `Channel`.
# Examples
Expand Down Expand Up @@ -117,6 +122,9 @@ true
In earlier versions of Julia, Channel used keyword arguments to set `size` and `T`, but
those constructors are deprecated.
!!! compat "Julia 1.9"
The `threadpool=` argument was added in Julia 1.9.
```jldoctest
julia> chnl = Channel{Char}(1, spawn=true) do ch
for c in "hello world"
Expand All @@ -129,12 +137,18 @@ julia> String(collect(chnl))
"hello world"
```
"""
function Channel{T}(func::Function, size=0; taskref=nothing, spawn=false) where T
function Channel{T}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing) where T
chnl = Channel{T}(size)
task = Task(() -> func(chnl))
if threadpool === nothing
threadpool = :default
else
spawn = true
end
task.sticky = !spawn
bind(chnl, task)
if spawn
Threads._spawn_set_thrpool(task, threadpool)
schedule(task) # start it on (potentially) another thread
else
yield(task) # immediately start it, yielding the current thread
Expand All @@ -149,17 +163,17 @@ Channel(func::Function, args...; kwargs...) = Channel{Any}(func, args...; kwargs
# of course not deprecated.)
# We use `nothing` default values to check which arguments were set in order to throw the
# deprecation warning if users try to use `spawn=` with `ctype=` or `csize=`.
function Channel(func::Function; ctype=nothing, csize=nothing, taskref=nothing, spawn=nothing)
function Channel(func::Function; ctype=nothing, csize=nothing, taskref=nothing, spawn=nothing, threadpool=nothing)
# The spawn= keyword argument was added in Julia v1.3, and cannot be used with the
# deprecated keyword arguments `ctype=` or `csize=`.
if (ctype !== nothing || csize !== nothing) && spawn !== nothing
throw(ArgumentError("Cannot set `spawn=` in the deprecated constructor `Channel(f; ctype=Any, csize=0)`. Please use `Channel{T=Any}(f, size=0; taskref=nothing, spawn=false)` instead!"))
if (ctype !== nothing || csize !== nothing) && (spawn !== nothing || threadpool !== nothing)
throw(ArgumentError("Cannot set `spawn=` or `threadpool=` in the deprecated constructor `Channel(f; ctype=Any, csize=0)`. Please use `Channel{T=Any}(f, size=0; taskref=nothing, spawn=false, threadpool=nothing)` instead!"))
end
# Set the actual default values for the arguments.
ctype === nothing && (ctype = Any)
csize === nothing && (csize = 0)
spawn === nothing && (spawn = false)
return Channel{ctype}(func, csize; taskref=taskref, spawn=spawn)
return Channel{ctype}(func, csize; taskref=taskref, spawn=spawn, threadpool=threadpool)
end

closed_exception() = InvalidStateException("Channel is closed.", :closed)
Expand Down
4 changes: 2 additions & 2 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ scrub_repl_backtrace(stack::ExceptionStack) =
ExceptionStack(Any[(;x.exception, backtrace = scrub_repl_backtrace(x.backtrace)) for x in stack])

istrivialerror(stack::ExceptionStack) =
length(stack) == 1 && length(stack[1].backtrace) 1
# frame 1 = top level; assumes already went through scrub_repl_backtrace
length(stack) == 1 && length(stack[1].backtrace) 1 && !isa(stack[1].exception, MethodError)
# frame 1 = top level; assumes already went through scrub_repl_backtrace; MethodError see #50803

function display_error(io::IO, stack::ExceptionStack)
printstyled(io, "ERROR: "; bold=true, color=Base.error_color())
Expand Down
65 changes: 41 additions & 24 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1869,39 +1869,50 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
end

function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{Any})
if length(argtypes) == 3
canconst = true
na = length(argtypes)
if isvarargtype(argtypes[end])
if na 2
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
elseif na > 4
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
end
a2 = argtypes[2]
a3 = unwrapva(argtypes[3])
nothrow = false
elseif na == 3
a2 = argtypes[2]
a3 = argtypes[3]
= (typeinf_lattice(interp))
nothrow = a2 ᵢ TypeVar && (a3 ᵢ Type || a3 ᵢ TypeVar)
if isa(a3, Const)
body = a3.val
elseif isType(a3)
body = a3.parameters[1]
else
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
end
canconst = true
if isa(a3, Const)
body = a3.val
elseif isType(a3)
body = a3.parameters[1]
canconst = false
else
return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
end
if !(isa(body, Type) || isa(body, TypeVar))
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
end
if has_free_typevars(body)
if isa(a2, Const)
tv = a2.val
elseif isa(a2, PartialTypeVar)
tv = a2.tv
canconst = false
else
return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
end
if !(isa(body, Type) || isa(body, TypeVar))
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
end
if has_free_typevars(body)
if isa(a2, Const)
tv = a2.val
elseif isa(a2, PartialTypeVar)
tv = a2.tv
canconst = false
else
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
end
isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
body = UnionAll(tv, body)
end
ret = canconst ? Const(body) : Type{body}
return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
body = UnionAll(tv, body)
end
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
ret = canconst ? Const(body) : Type{body}
return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
end

function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, si::StmtInfo, sv::AbsIntState)
Expand Down Expand Up @@ -2182,6 +2193,12 @@ function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool)
T = UnionAll(v, T)
end
end
if has_free_typevars(T)
fv = ccall(:jl_find_free_typevars, Vector{Any}, (Any,), T)
for v in fv
T = UnionAll(v, T)
end
end
else
T = rewrap_unionall(T, spsig)
end
Expand Down
5 changes: 3 additions & 2 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -817,8 +817,8 @@ end
function compileable_specialization(mi::MethodInstance, effects::Effects,
et::InliningEdgeTracker, @nospecialize(info::CallInfo); compilesig_invokes::Bool=true)
mi_invoke = mi
method, atype, sparams = mi.def::Method, mi.specTypes, mi.sparam_vals
if compilesig_invokes
method, atype, sparams = mi.def::Method, mi.specTypes, mi.sparam_vals
new_atype = get_compileable_sig(method, atype, sparams)
new_atype === nothing && return nothing
if atype !== new_atype
Expand All @@ -836,7 +836,8 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
return nothing
end
end
add_inlining_backedge!(et, mi)
add_inlining_backedge!(et, mi) # to the dispatch lookup
push!(et.edges, method.sig, mi_invoke) # add_inlining_backedge to the invoke call
return InvokeCase(mi_invoke, effects, info)
end

Expand Down
13 changes: 7 additions & 6 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2620,13 +2620,15 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s

if length(argtypes) == 3
aft = widenslotwrapper(argtypes[2])
if !isa(aft, Const) && !(isType(aft) && !has_free_typevars(aft)) &&
!(isconcretetype(aft) && !(aft <: Builtin))
return UNKNOWN
end
argtypes_vec = Any[aft, af_argtype.parameters...]
else
argtypes_vec = Any[af_argtype.parameters...]
isempty(argtypes_vec) && push!(argtypes_vec, Union{})
aft = argtypes_vec[1]
end
if !(isa(aft, Const) || (isType(aft) && !has_free_typevars(aft)) ||
(isconcretetype(aft) && !(aft <: Builtin) && !iskindtype(aft)))
return UNKNOWN
end

if contains_is(argtypes_vec, Union{})
Expand Down Expand Up @@ -2659,8 +2661,7 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
# in two ways: both as being a subtype of this, and
# because of LimitedAccuracy causes
return CallMeta(Type{<:rt}, EFFECTS_TOTAL, info)
elseif (isa(tt, Const) || isconstType(tt)) &&
(isa(aft, Const) || isconstType(aft))
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), EFFECTS_TOTAL, info)
Expand Down
Loading

0 comments on commit e6378ea

Please sign in to comment.