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.8-rc1/beta3 #44710

Merged
merged 13 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 17 additions & 14 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,20 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
splitsigs = switchtupleunion(sig)
for sig_n in splitsigs
result = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv)
rt, edge = result.rt, result.edge
if edge !== nothing
push!(edges, edge)
end
rt = result.rt
edge = result.edge
edge !== nothing && push!(edges, edge)
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
this_arginfo = ArgInfo(fargs, this_argtypes)
const_call_result = abstract_call_method_with_const_args(interp, result,
f, this_arginfo, match, sv)
effects = result.edge_effects
const_result = nothing
if const_call_result !== nothing
if const_call_result.rt ⊑ rt
(; rt, effects, const_result) = const_call_result
const_rt = const_call_result.rt
if const_rt ⊑ rt
rt = const_rt
(; effects, const_result) = const_call_result
end
end
tristate_merge!(sv, effects)
Expand All @@ -135,6 +136,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
break
end
end
this_conditional = ignorelimited(this_rt)
this_rt = widenwrappedconditional(this_rt)
else
if infer_compilation_signature(interp)
# Also infer the compilation signature for this method, so it's available
Expand All @@ -151,10 +154,10 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
end

result = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv)
this_rt, edge = result.rt, result.edge
if edge !== nothing
push!(edges, edge)
end
this_conditional = ignorelimited(result.rt)
this_rt = widenwrappedconditional(result.rt)
edge = result.edge
edge !== nothing && push!(edges, edge)
# try constant propagation with argtypes for this match
# this is in preparation for inlining, or improving the return result
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
Expand All @@ -164,10 +167,12 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
effects = result.edge_effects
const_result = nothing
if const_call_result !== nothing
this_const_rt = const_call_result.rt
# return type of const-prop' inference can be wider than that of non const-prop' inference
this_const_conditional = ignorelimited(const_call_result.rt)
this_const_rt = widenwrappedconditional(const_call_result.rt)
# return type of const-prop' inference can be wider than that of non const-prop' inference
# e.g. in cases when there are cycles but cached result is still accurate
if this_const_rt ⊑ this_rt
this_conditional = this_const_conditional
this_rt = this_const_rt
(; effects, const_result) = const_call_result
end
Expand All @@ -178,8 +183,6 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
any_const_result = true
end
end
this_conditional = ignorelimited(this_rt)
this_rt = widenwrappedconditional(this_rt)
@assert !(this_conditional isa Conditional) "invalid lattice element returned from inter-procedural context"
seen += 1
rettype = tmerge(rettype, this_rt)
Expand Down
9 changes: 8 additions & 1 deletion base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,14 @@ function round(::Type{T}, x::BigFloat, r::Union{RoundingMode, MPFRRoundingMode})
end
return unsafe_trunc(T, res)
end
round(::Type{BigInt}, x::BigFloat, r::Union{RoundingMode, MPFRRoundingMode}) = _unchecked_cast(BigInt, x, r)

function round(::Type{BigInt}, x::BigFloat, r::Union{RoundingMode, MPFRRoundingMode})
clear_flags()
res = _unchecked_cast(BigInt, x, r)
had_range_exception() && throw(InexactError(:round, BigInt, x))
return res
end

round(::Type{T}, x::BigFloat, r::RoundingMode) where T<:Union{Signed, Unsigned} =
invoke(round, Tuple{Type{<:Union{Signed, Unsigned}}, BigFloat, Union{RoundingMode, MPFRRoundingMode}}, T, x, r)
round(::Type{BigInt}, x::BigFloat, r::RoundingMode) =
Expand Down
37 changes: 36 additions & 1 deletion base/task.jl
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ isolating the asynchronous code from changes to the variable's value in the curr
Interpolating values via `\$` is available as of Julia 1.4.
"""
macro async(expr)
do_async_macro(expr)
end

# generate the code for @async, possibly wrapping the task in something before
# pushing it to the wait queue.
function do_async_macro(expr; wrap=identity)
letargs = Base._lift_one_interp!(expr)

thunk = esc(:(()->($expr)))
Expand All @@ -479,14 +485,43 @@ macro async(expr)
let $(letargs...)
local task = Task($thunk)
if $(Expr(:islocal, var))
put!($var, task)
put!($var, $(wrap(:task)))
end
schedule(task)
task
end
end
end

# task wrapper that doesn't create exceptions wrapped in TaskFailedException
struct UnwrapTaskFailedException
task::Task
end

# common code for wait&fetch for UnwrapTaskFailedException
function unwrap_task_failed(f::Function, t::UnwrapTaskFailedException)
try
f(t.task)
catch ex
if ex isa TaskFailedException
throw(ex.task.exception)
else
rethrow()
end
end
end

# the unwrapping for above task wrapper (gets triggered in sync_end())
wait(t::UnwrapTaskFailedException) = unwrap_task_failed(wait, t)

# same for fetching the tasks, for convenience
fetch(t::UnwrapTaskFailedException) = unwrap_task_failed(fetch, t)

# macro for running async code that doesn't throw wrapped exceptions
macro async_unwrap(expr)
do_async_macro(expr, wrap=task->:(Base.UnwrapTaskFailedException($task)))
end

"""
errormonitor(t::Task)

Expand Down
4 changes: 2 additions & 2 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1787,9 +1787,9 @@ JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT
return fval != NULL ? 1 : 0;
}

JL_DLLEXPORT size_t jl_get_field_offset(jl_datatype_t *ty, int field) JL_NOTSAFEPOINT
JL_DLLEXPORT size_t jl_get_field_offset(jl_datatype_t *ty, int field)
{
if (ty->layout == NULL || field > jl_datatype_nfields(ty) || field < 1)
if (!jl_struct_try_layout(ty) || field > jl_datatype_nfields(ty) || field < 1)
jl_bounds_error_int((jl_value_t*)ty, field);
return jl_field_offset(ty, field - 1);
}
Expand Down
1 change: 0 additions & 1 deletion src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@
XX(jl_get_excstack) \
XX(jl_get_fenv_consts) \
XX(jl_get_field) \
XX(jl_get_field_offset) \
XX(jl_get_global) \
XX(jl_get_image_file) \
XX(jl_get_JIT) \
Expand Down
12 changes: 10 additions & 2 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ static int layout_uses_free_typevars(jl_value_t *v, jl_typeenv_t *env)
return 0;
if (dt->name == jl_namedtuple_typename)
return layout_uses_free_typevars(jl_tparam0(dt), env) || layout_uses_free_typevars(jl_tparam1(dt), env);
if (dt->name == jl_tuple_typename)
// conservative, since we don't want to inline an abstract tuple,
// and we currently declare !has_fixed_layout for these, but that
// means we also won't be able to inline a tuple which is concrete
// except for the use of free type-vars
return 1;
jl_svec_t *types = jl_get_fieldtypes(dt);
size_t i, l = jl_svec_len(types);
for (i = 0; i < l; i++) {
Expand Down Expand Up @@ -227,8 +233,10 @@ int jl_has_fixed_layout(jl_datatype_t *dt)
return 1;
if (dt->name->abstract)
return 0;
if (jl_is_tuple_type(dt) || jl_is_namedtuple_type(dt))
return 0; // TODO: relax more?
if (dt->name == jl_namedtuple_typename)
return !layout_uses_free_typevars(jl_tparam0(dt), NULL) && !layout_uses_free_typevars(jl_tparam1(dt), NULL);
if (dt->name == jl_tuple_typename)
return 0;
jl_svec_t *types = jl_get_fieldtypes(dt);
size_t i, l = jl_svec_len(types);
for (i = 0; i < l; i++) {
Expand Down
20 changes: 12 additions & 8 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -4105,7 +4105,7 @@ f(x) = yt(x)
(cons (car e)
(map-cl-convert (cdr e) fname lam namemap defined toplevel interp opaq globals))))))))

(define (closure-convert e) (cl-convert e #f #f #f #f #f #f #f))
(define (closure-convert e) (cl-convert e #f #f (table) (table) #f #f #f))

;; pass 5: convert to linear IR

Expand Down Expand Up @@ -4205,17 +4205,21 @@ f(x) = yt(x)
(loop (cdr s))))))
`(pop_exception ,restore-token))))
(define (emit-return x)
(define (actually-return x)
(let* ((x (if rett
(compile (convert-for-type-decl x rett) '() #t #f)
x))
(tmp (if ((if (null? catch-token-stack) valid-ir-return? simple-atom?) x)
(define (emit- x)
(let* ((tmp (if ((if (null? catch-token-stack) valid-ir-return? simple-atom?) x)
#f
(make-ssavalue))))
(if tmp (emit `(= ,tmp ,x)))
(if tmp
(begin (emit `(= ,tmp ,x)) tmp)
x)))
(define (actually-return x)
(let* ((x (if rett
(compile (convert-for-type-decl (emit- x) rett) '() #t #f)
x))
(x (emit- x)))
(let ((pexc (pop-exc-expr catch-token-stack '())))
(if pexc (emit pexc)))
(emit `(return ,(or tmp x)))))
(emit `(return ,x))))
(if x
(if (> handler-level 0)
(let ((tmp (cond ((and (simple-atom? x) (or (not (ssavalue? x)) (not finally-handler))) #f)
Expand Down
18 changes: 9 additions & 9 deletions src/processor_arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1843,20 +1843,20 @@ extern "C" int jl_test_cpu_feature(jl_cpu_feature_t feature)

#ifdef _CPU_AARCH64_
// FPCR FZ, bit [24]
static constexpr uint32_t fpcr_fz_mask = 1 << 24;
static constexpr uint64_t fpcr_fz_mask = 1 << 24;
// FPCR FZ16, bit [19]
static constexpr uint32_t fpcr_fz16_mask = 1 << 19;
static constexpr uint64_t fpcr_fz16_mask = 1 << 19;
// FPCR DN, bit [25]
static constexpr uint32_t fpcr_dn_mask = 1 << 25;
static constexpr uint64_t fpcr_dn_mask = 1 << 25;

static inline uint32_t get_fpcr_aarch64(void)
static inline uint64_t get_fpcr_aarch64(void)
{
uint32_t fpcr;
uint64_t fpcr;
asm volatile("mrs %0, fpcr" : "=r"(fpcr));
return fpcr;
}

static inline void set_fpcr_aarch64(uint32_t fpcr)
static inline void set_fpcr_aarch64(uint64_t fpcr)
{
asm volatile("msr fpcr, %0" :: "r"(fpcr));
}
Expand All @@ -1868,8 +1868,8 @@ extern "C" JL_DLLEXPORT int32_t jl_get_zero_subnormals(void)

extern "C" JL_DLLEXPORT int32_t jl_set_zero_subnormals(int8_t isZero)
{
uint32_t fpcr = get_fpcr_aarch64();
static uint32_t mask = fpcr_fz_mask | (jl_test_cpu_feature(JL_AArch64_fullfp16) ? fpcr_fz16_mask : 0);
uint64_t fpcr = get_fpcr_aarch64();
static uint64_t mask = fpcr_fz_mask | (jl_test_cpu_feature(JL_AArch64_fullfp16) ? fpcr_fz16_mask : 0);
fpcr = isZero ? (fpcr | mask) : (fpcr & ~mask);
set_fpcr_aarch64(fpcr);
return 0;
Expand All @@ -1882,7 +1882,7 @@ extern "C" JL_DLLEXPORT int32_t jl_get_default_nans(void)

extern "C" JL_DLLEXPORT int32_t jl_set_default_nans(int8_t isDefault)
{
uint32_t fpcr = get_fpcr_aarch64();
uint64_t fpcr = get_fpcr_aarch64();
fpcr = isDefault ? (fpcr | fpcr_dn_mask) : (fpcr & ~fpcr_dn_mask);
set_fpcr_aarch64(fpcr);
return 0;
Expand Down
4 changes: 2 additions & 2 deletions stdlib/Distributed/src/Distributed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Base: getindex, wait, put!, take!, fetch, isready, push!, length,
hash, ==, kill, close, isopen, showerror

# imports for use
using Base: Process, Semaphore, JLOptions, buffer_writes, @sync_add,
using Base: Process, Semaphore, JLOptions, buffer_writes, @async_unwrap,
VERSION_STRING, binding_module, atexit, julia_exename,
julia_cmd, AsyncGenerator, acquire, release, invokelatest,
shell_escape_posixly, shell_escape_csh,
Expand Down Expand Up @@ -76,7 +76,7 @@ function _require_callback(mod::Base.PkgId)
# broadcast top-level (e.g. from Main) import/using from node 1 (only)
@sync for p in procs()
p == 1 && continue
@sync_add remotecall(p) do
@async_unwrap remotecall_wait(p) do
Base.require(mod)
nothing
end
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Distributed/src/clusterserialize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ An exception is raised if a global constant is requested to be cleared.
"""
function clear!(syms, pids=workers(); mod=Main)
@sync for p in pids
@sync_add remotecall(clear_impl!, p, syms, mod)
@async_unwrap remotecall_wait(clear_impl!, p, syms, mod)
end
end
clear!(sym::Symbol, pid::Int; mod=Main) = clear!([sym], [pid]; mod=mod)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/Distributed/src/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ function remotecall_eval(m::Module, procs, ex)
if pid == myid()
run_locally += 1
else
@sync_add remotecall(Core.eval, pid, m, ex)
@async_unwrap remotecall_wait(Core.eval, pid, m, ex)
end
end
yield() # ensure that the remotecall_fetch have had a chance to start
yield() # ensure that the remotecalls have had a chance to start

# execute locally last as we do not want local execution to block serialization
# of the request to remote nodes.
Expand Down
12 changes: 5 additions & 7 deletions stdlib/LinearAlgebra/src/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,19 @@ end
function Matrix{T}(A::Bidiagonal) where T
n = size(A, 1)
B = zeros(T, n, n)
if n == 0
return B
end
for i = 1:n - 1
n == 0 && return B
@inbounds for i = 1:n - 1
B[i,i] = A.dv[i]
if A.uplo == 'U'
B[i, i + 1] = A.ev[i]
B[i,i+1] = A.ev[i]
else
B[i + 1, i] = A.ev[i]
B[i+1,i] = A.ev[i]
end
end
B[n,n] = A.dv[n]
return B
end
Matrix(A::Bidiagonal{T}) where {T} = Matrix{T}(A)
Matrix(A::Bidiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(A)
Array(A::Bidiagonal) = Matrix(A)
promote_rule(::Type{Matrix{T}}, ::Type{<:Bidiagonal{S}}) where {T,S} =
@isdefined(T) && @isdefined(S) ? Matrix{promote_type(T,S)} : Matrix
Expand Down
7 changes: 5 additions & 2 deletions stdlib/LinearAlgebra/src/blas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,9 @@ for (fname, elty) in ((:daxpy_,:Float64),
end
end
end
function axpy!(alpha::Number, x::AbstractArray{T}, y::AbstractArray{T}) where T<:BlasFloat

#TODO: replace with `x::AbstractArray{T}` once we separate `BLAS.axpy!` and `LinearAlgebra.axpy!`
function axpy!(alpha::Number, x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) where T<:BlasFloat
if length(x) != length(y)
throw(DimensionMismatch(lazy"x has length $(length(x)), but y has length $(length(y))"))
end
Expand Down Expand Up @@ -582,7 +584,8 @@ for (fname, elty) in ((:daxpby_,:Float64), (:saxpby_,:Float32),
end
end

function axpby!(alpha::Number, x::AbstractArray{T}, beta::Number, y::AbstractArray{T}) where T<:BlasFloat
#TODO: replace with `x::AbstractArray{T}` once we separate `BLAS.axpby!` and `LinearAlgebra.axpby!`
function axpby!(alpha::Number, x::Union{DenseArray{T},AbstractVector{T}}, beta::Number, y::Union{DenseArray{T},AbstractVector{T}},) where T<:BlasFloat
require_one_based_indexing(x, y)
if length(x) != length(y)
throw(DimensionMismatch(lazy"x has length $(length(x)), but y has length $(length(y))"))
Expand Down
9 changes: 9 additions & 0 deletions stdlib/LinearAlgebra/src/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ Vector `kv.second` will be placed on the `kv.first` diagonal.
By default the matrix is square and its size is inferred
from `kv`, but a non-square size `m`×`n` (padded with zeros as needed)
can be specified by passing `m,n` as the first arguments.
For repeated diagonal indices `kv.first` the values in the corresponding
vectors `kv.second` will be added.

`diagm` constructs a full matrix; if you want storage-efficient
versions with fast arithmetic, see [`Diagonal`](@ref), [`Bidiagonal`](@ref)
Expand All @@ -277,6 +279,13 @@ julia> diagm(1 => [1,2,3], -1 => [4,5])
4 0 2 0
0 5 0 3
0 0 0 0

julia> diagm(1 => [1,2,3], 1 => [1,2,3])
4×4 Matrix{Int64}:
0 2 0 0
0 0 4 0
0 0 0 6
0 0 0 0
```
"""
diagm(kv::Pair{<:Integer,<:AbstractVector}...) = _diagm(nothing, kv...)
Expand Down
Loading