Skip to content

Backports for 1.9.0 #49302

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

Merged
merged 31 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4e7a55e
Offset to indices in (unsafe_)copyto docstring (#49147)
jishnub Mar 25, 2023
8219ad5
allow more statements in generate_precompile.jl (#49200)
JeffBezanson Mar 31, 2023
c9596ef
Make :open ccall use variadic cconv (#49212)
vchuravy Apr 1, 2023
f8a4a37
(re-)allow include_dependency(directory) (#49244)
benlorenz Apr 4, 2023
ab206cb
Fix LazyString building with non-ASCII preceding $ (#49248)
Liozou Apr 5, 2023
8c1fe98
make default worker pool an AbstractWorkerPool (#49101)
tanmaykm Apr 6, 2023
03ec03d
more robust validation of allocation type (#49269)
vtjnash Apr 7, 2023
ba9c797
Revert "delay loading of extensions as much as possible (#48674)"
Apr 5, 2023
b82c5db
add a test that extension is available during precompilation
KristofferC Apr 9, 2023
0d28812
fix new scope assignment warning in Distributed (#49303)
tanmaykm Apr 9, 2023
4498251
Bump to LBT v5.7.0 (#49281)
staticfloat Apr 10, 2023
a05bb0f
Resolve artifact ambiguities using shortest match
staticfloat Feb 21, 2023
be1c71d
make thread 1 interactive when there is an interactive pool, so it ca…
JeffBezanson Apr 13, 2023
eb764cc
Merge pull request #48534 from N5N3/Test2
N5N3 Feb 8, 2023
9aa7669
Merge pull request #48809 from ven-k/vkb/imageing-default
staticfloat Apr 12, 2023
f7d8e20
bump SparseArrays to latest v1.9
KristofferC Apr 13, 2023
6d03913
Subtype: fix union estimation on non-type parameters. (#49345)
N5N3 Apr 13, 2023
3ece193
Rename `ipython_mode` to `numbered_prompt` (#49314)
hyrodium Apr 14, 2023
304037b
InteractiveUtils: use quoted `typesof` in macroexpansion (#47626)
aviatesk Nov 19, 2022
b05b958
Bump the Pkg stdlib from 1b73599d2 to 3ca88658d (#49347)
DilumAluthgeBot Apr 17, 2023
0033465
Bump LLVM to 14.0.6-3
vchuravy Apr 17, 2023
faeb43b
Subtype: Improve `simple_meet` resolution for `Union` inputs (#49376)
N5N3 Apr 22, 2023
f89f5d9
Enable the AVR backend of LLVM (#49006)
Seelengrab Mar 15, 2023
cbc4f49
prevent `display` in REPL from erroring on non standard prompts (#49383)
KristofferC Apr 20, 2023
f6561ce
Add missing entry to invalidation log (#49449)
timholy Apr 21, 2023
7c6dd4c
make extension not load twice on workers (#49441)
KristofferC Apr 22, 2023
29889c7
Extract specializations, 1.9-style (#49467)
timholy Apr 23, 2023
a666aab
Subtype: minor optimization for `simple_intersect`
N5N3 Apr 23, 2023
3f42af0
Avoid usage of `jl_error()` in `check_cmdline()`
staticfloat Apr 24, 2023
0a374d5
Merge pull request #49486 from JuliaLang/sf/backport_win_hang_fix
staticfloat Apr 24, 2023
ad9b54f
rename `jl_tls_offset` in sysimage to avoid naming clash with `libjul…
KristofferC Apr 24, 2023
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
4 changes: 2 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ Standard library changes
* The contextual module which is active in the REPL can be changed (it is `Main` by default),
via the `REPL.activate(::Module)` function or via typing the module in the REPL and pressing
the keybinding Alt-m ([#33872]).
* An "IPython mode" which mimics the behaviour of the prompts and storing the evaluated result in `Out` can be
activated with `REPL.ipython_mode!()`. See the manual for how to enable this at startup ([#46474]).
* A "numbered prompt" mode which prints numbers for each input and output and stores evaluated results in `Out` can be
activated with `REPL.numbered_prompt!()`. See the manual for how to enable this at startup ([#46474]).
* Tab completion displays available keyword arguments ([#43536]).

#### SuiteSparse
Expand Down
6 changes: 3 additions & 3 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ end
"""
unsafe_copyto!(dest::Array, do, src::Array, so, N)

Copy `N` elements from a source array to a destination, starting at offset `so` in the
Copy `N` elements from a source array to a destination, starting at the linear index `so` in the
source and `do` in the destination (1-indexed).

The `unsafe` prefix on this function indicates that no validation is performed to ensure
Expand Down Expand Up @@ -307,8 +307,8 @@ unsafe_copyto!(dest::Array, doffs, src::Array, soffs, n) =
"""
copyto!(dest, do, src, so, N)

Copy `N` elements from collection `src` starting at offset `so`, to array `dest` starting at
offset `do`. Return `dest`.
Copy `N` elements from collection `src` starting at the linear index `so`, to array `dest` starting at
the index `do`. Return `dest`.
"""
function copyto!(dest::Array, doffs::Integer, src::Array, soffs::Integer, n::Integer)
return _copyto_impl!(dest, doffs, src, soffs, n)
Expand Down
20 changes: 14 additions & 6 deletions base/binaryplatforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1066,12 +1066,20 @@ function select_platform(download_info::Dict, platform::AbstractPlatform = HostP
return nothing
end

# At this point, we may have multiple possibilities. E.g. if, in the future,
# Julia can be built without a direct dependency on libgfortran, we may match
# multiple tarballs that vary only within their libgfortran ABI. To narrow it
# down, we just sort by triplet, then pick the last one. This has the effect
# of generally choosing the latest release (e.g. a `libgfortran5` tarball
# rather than a `libgfortran3` tarball)
# At this point, we may have multiple possibilities. We now engage a multi-
# stage selection algorithm, where we first choose simpler matches over more
# complex matches. We define a simpler match as one that has fewer tags
# overall. As these candidate matches have already been filtered to match
# the given platform, the only other tags that exist are ones that are in
# addition to the tags declared by the platform. Hence, selecting the
# minimum in number of tags is equivalent to selecting the closest match.
min_tag_count = minimum(length(tags(p)) for p in ps)
filter!(p -> length(tags(p)) == min_tag_count, ps)

# Now we _still_ may continue to have multiple matches, so we now simply sort
# the candidate matches by their triplets and take the last one, so as to
# generally choose the latest release (e.g. a `libgfortran5` tarball over a
# `libgfortran3` tarball).
p = last(sort(ps, by = p -> triplet(p)))
return download_info[p]
end
Expand Down
2 changes: 1 addition & 1 deletion base/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ if Sys.iswindows()
end
else
function cd(f::Function, dir::AbstractString)
fd = ccall(:open, Int32, (Cstring, Int32), :., 0)
fd = ccall(:open, Int32, (Cstring, Int32, UInt32...), :., 0)
systemerror(:open, fd == -1)
try
cd(dir)
Expand Down
102 changes: 50 additions & 52 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
end

function run_package_callbacks(modkey::PkgId)
run_extension_callbacks(modkey)
assert_havelock(require_lock)
unlock(require_lock)
try
Expand Down Expand Up @@ -1188,9 +1189,12 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, <:An
end
end

loading_extension::Bool = false
function run_extension_callbacks(extid::ExtensionId)
assert_havelock(require_lock)
succeeded = try
# Used by Distributed to now load extensions in the package callback
global loading_extension = true
_require_prelocked(extid.id)
@debug "Extension $(extid.id.name) of $(extid.parentid.name) loaded"
true
Expand All @@ -1200,59 +1204,57 @@ function run_extension_callbacks(extid::ExtensionId)
@error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \
use `Base.retry_load_extensions()` to retry." exception=errs
false
finally
global loading_extension = false
end
return succeeded
end

function run_extension_callbacks()
function run_extension_callbacks(pkgid::PkgId)
assert_havelock(require_lock)
loaded_triggers = collect(intersect(keys(Base.loaded_modules), keys(Base.EXT_DORMITORY)))
sort!(loaded_triggers; by=x->x.uuid)
for pkgid in loaded_triggers
# take ownership of extids that depend on this pkgid
extids = pop!(EXT_DORMITORY, pkgid, nothing)
extids === nothing && continue
for extid in extids
if extid.ntriggers > 0
# It is possible that pkgid was loaded in an environment
# below the one of the parent. This will cause a load failure when the
# pkg ext tries to load the triggers. Therefore, check this first
# before loading the pkg ext.
pkgenv = Base.identify_package_env(extid.id, pkgid.name)
ext_not_allowed_load = false
if pkgenv === nothing
# take ownership of extids that depend on this pkgid
extids = pop!(EXT_DORMITORY, pkgid, nothing)
extids === nothing && return
for extid in extids
if extid.ntriggers > 0
# It is possible that pkgid was loaded in an environment
# below the one of the parent. This will cause a load failure when the
# pkg ext tries to load the triggers. Therefore, check this first
# before loading the pkg ext.
pkgenv = identify_package_env(extid.id, pkgid.name)
ext_not_allowed_load = false
if pkgenv === nothing
ext_not_allowed_load = true
else
pkg, env = pkgenv
path = locate_package(pkg, env)
if path === nothing
ext_not_allowed_load = true
else
pkg, env = pkgenv
path = Base.locate_package(pkg, env)
if path === nothing
ext_not_allowed_load = true
end
end
if ext_not_allowed_load
@debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \
since $(pkgid.name) loaded in environment lower in load path"
# indicate extid is expected to fail
extid.ntriggers *= -1
else
# indicate pkgid is loaded
extid.ntriggers -= 1
end
end
if extid.ntriggers < 0
# indicate pkgid is loaded
extid.ntriggers += 1
succeeded = false
if ext_not_allowed_load
@debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \
since $(pkgid.name) loaded in environment lower in load path"
# indicate extid is expected to fail
extid.ntriggers *= -1
else
succeeded = true
end
if extid.ntriggers == 0
# actually load extid, now that all dependencies are met,
# and record the result
succeeded = succeeded && run_extension_callbacks(extid)
succeeded || push!(EXT_DORMITORY_FAILED, extid)
# indicate pkgid is loaded
extid.ntriggers -= 1
end
end
if extid.ntriggers < 0
# indicate pkgid is loaded
extid.ntriggers += 1
succeeded = false
else
succeeded = true
end
if extid.ntriggers == 0
# actually load extid, now that all dependencies are met,
# and record the result
succeeded = succeeded && run_extension_callbacks(extid)
succeeded || push!(EXT_DORMITORY_FAILED, extid)
end
end
return
end
Expand All @@ -1276,7 +1278,7 @@ function retry_load_extensions()
end
prepend!(EXT_DORMITORY_FAILED, failed)
end
nothing
return
end

"""
Expand Down Expand Up @@ -1510,11 +1512,11 @@ end
"""
include_dependency(path::AbstractString)

In a module, declare that the file specified by `path` (relative or absolute) is a
dependency for precompilation; that is, the module will need to be recompiled if this file
changes.
In a module, declare that the file, directory, or symbolic link specified by `path`
(relative or absolute) is a dependency for precompilation; that is, the module will need
to be recompiled if the modification time of `path` changes.

This is only needed if your module depends on a file that is not used via [`include`](@ref). It has
This is only needed if your module depends on a path that is not used via [`include`](@ref). It has
no effect outside of compilation.
"""
function include_dependency(path::AbstractString)
Expand Down Expand Up @@ -1631,10 +1633,6 @@ function _require_prelocked(uuidkey::PkgId, env=nothing)
else
newm = root_module(uuidkey)
end
# Load extensions when not precompiling and not in a nested package load
if JLOptions().incremental == 0 && isempty(package_locks)
run_extension_callbacks()
end
return newm
end

Expand Down Expand Up @@ -2790,7 +2788,7 @@ end
end
for chi in includes
f, ftime_req = chi.filename, chi.mtime
if !isfile(f)
if !ispath(f)
_f = fixup_stdlib_path(f)
if isfile(_f) && startswith(_f, Sys.STDLIB)
# mtime is changed by extraction
Expand Down
2 changes: 1 addition & 1 deletion base/strings/lazy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ macro lazy_str(text)
parts = Any[]
lastidx = idx = 1
while (idx = findnext('$', text, idx)) !== nothing
lastidx < idx && push!(parts, text[lastidx:idx-1])
lastidx < idx && push!(parts, text[lastidx:prevind(text, idx)])
idx += 1
expr, idx = Meta.parseatom(text, idx; filename=string(__source__.file))
push!(parts, esc(expr))
Expand Down
4 changes: 2 additions & 2 deletions base/task.jl
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ istaskfailed(t::Task) = (load_state_acquire(t) === task_state_failed)
Threads.threadid(t::Task) = Int(ccall(:jl_get_task_tid, Int16, (Any,), t)+1)
function Threads.threadpool(t::Task)
tpid = ccall(:jl_get_task_threadpoolid, Int8, (Any,), t)
return tpid == 0 ? :default : :interactive
return Threads._tpid_to_sym(tpid)
end

task_result(t::Task) = t.result
Expand Down Expand Up @@ -786,7 +786,7 @@ function enq_work(t::Task)
if Threads.threadpoolsize(tp) == 1
# There's only one thread in the task's assigned thread pool;
# use its work queue.
tid = (tp === :default) ? 1 : Threads.threadpoolsize(:default)+1
tid = (tp === :interactive) ? 1 : Threads.threadpoolsize(:interactive)+1
ccall(:jl_set_task_tid, Cint, (Any, Cint), t, tid-1)
push!(workqueue_for(tid), t)
else
Expand Down
58 changes: 43 additions & 15 deletions base/threadingconstructs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,22 @@ function _nthreads_in_pool(tpid::Int8)
return Int(unsafe_load(p, tpid + 1))
end

function _tpid_to_sym(tpid::Int8)
return tpid == 0 ? :interactive : :default
end

function _sym_to_tpid(tp::Symbol)
return tp === :interactive ? Int8(0) : Int8(1)
end

"""
Threads.threadpool(tid = threadid()) -> Symbol

Returns the specified thread's threadpool; either `:default` or `:interactive`.
"""
function threadpool(tid = threadid())
tpid = ccall(:jl_threadpoolid, Int8, (Int16,), tid-1)
return tpid == 0 ? :default : :interactive
return _tpid_to_sym(tpid)
end

"""
Expand All @@ -67,24 +75,39 @@ See also: `BLAS.get_num_threads` and `BLAS.set_num_threads` in the
[`Distributed`](@ref man-distributed) standard library.
"""
function threadpoolsize(pool::Symbol = :default)
if pool === :default
tpid = Int8(0)
elseif pool === :interactive
tpid = Int8(1)
if pool === :default || pool === :interactive
tpid = _sym_to_tpid(pool)
else
error("invalid threadpool specified")
end
return _nthreads_in_pool(tpid)
end

"""
threadpooltids(pool::Symbol)

Returns a vector of IDs of threads in the given pool.
"""
function threadpooltids(pool::Symbol)
ni = _nthreads_in_pool(Int8(0))
if pool === :interactive
return collect(1:ni)
elseif pool === :default
return collect(ni+1:ni+_nthreads_in_pool(Int8(1)))
else
error("invalid threadpool specified")
end
end

function threading_run(fun, static)
ccall(:jl_enter_threaded_region, Cvoid, ())
n = threadpoolsize()
tid_offset = threadpoolsize(:interactive)
tasks = Vector{Task}(undef, n)
for i = 1:n
t = Task(() -> fun(i)) # pass in tid
t.sticky = static
static && ccall(:jl_set_task_tid, Cint, (Any, Cint), t, i-1)
static && ccall(:jl_set_task_tid, Cint, (Any, Cint), t, tid_offset + i-1)
tasks[i] = t
schedule(t)
end
Expand Down Expand Up @@ -287,6 +310,15 @@ macro threads(args...)
return _threadsfor(ex.args[1], ex.args[2], sched)
end

function _spawn_set_thrpool(t::Task, tp::Symbol)
tpid = _sym_to_tpid(tp)
if _nthreads_in_pool(tpid) == 0
tpid = _sym_to_tpid(:default)
end
ccall(:jl_set_task_threadpoolid, Cint, (Any, Int8), t, tpid)
nothing
end

"""
Threads.@spawn [:default|:interactive] expr

Expand Down Expand Up @@ -315,7 +347,7 @@ the variable's value in the current task.
A threadpool may be specified as of Julia 1.9.
"""
macro spawn(args...)
tpid = Int8(0)
tp = :default
na = length(args)
if na == 2
ttype, ex = args
Expand All @@ -325,9 +357,9 @@ macro spawn(args...)
# TODO: allow unquoted symbols
ttype = nothing
end
if ttype === :interactive
tpid = Int8(1)
elseif ttype !== :default
if ttype === :interactive || ttype === :default
tp = ttype
else
throw(ArgumentError("unsupported threadpool in @spawn: $ttype"))
end
elseif na == 1
Expand All @@ -344,11 +376,7 @@ macro spawn(args...)
let $(letargs...)
local task = Task($thunk)
task.sticky = false
local tpid_actual = $tpid
if _nthreads_in_pool(tpid_actual) == 0
tpid_actual = Int8(0)
end
ccall(:jl_set_task_threadpoolid, Cint, (Any, Int8), task, tpid_actual)
_spawn_set_thrpool(task, $(QuoteNode(tp)))
if $(Expr(:islocal, var))
put!($var, task)
end
Expand Down
Loading