Skip to content

Commit

Permalink
Merge branch 'master' into patch-3
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj authored Dec 27, 2023
2 parents ecbcd75 + 66e9410 commit 6855e6c
Show file tree
Hide file tree
Showing 99 changed files with 1,966 additions and 726 deletions.
20 changes: 17 additions & 3 deletions .github/workflows/Typos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ jobs:
OLD_FILES=$(git diff-index --name-only --diff-filter=ad FETCH_HEAD)
NEW_FILES=$(git diff-index --name-only --diff-filter=d FETCH_HEAD)
# This is necessary because the typos command interprets the
# empty string as "check all files" rather than "check no files".
if [ -z "$NEW_FILES" ]; then
echo "All edited files were deleted. Skipping typos check."
exit 0
fi
mkdir -p "${{ runner.temp }}/typos"
RELEASE_ASSET_URL="$(
gh api /repos/crate-ci/typos/releases/latest \
Expand All @@ -35,19 +42,26 @@ jobs:
echo -n $NEW_FILES | xargs "${{ runner.temp }}/typos/typos" --format json >> ${{ runner.temp }}/new_typos.jsonl || true
git checkout FETCH_HEAD -- $OLD_FILES
echo -n $OLD_FILES | xargs "${{ runner.temp }}/typos/typos" --format json >> ${{ runner.temp }}/old_typos.jsonl || true
if [ -z "$OLD_FILES" ]; then
touch "${{ runner.temp }}/old_typos.jsonl" # No old files, so no old typos.
else
echo -n $OLD_FILES | xargs "${{ runner.temp }}/typos/typos" --format json >> ${{ runner.temp }}/old_typos.jsonl || true
fi
python -c '
import sys, json
old = set()
with open(sys.argv[1]) as old_file:
for line in old_file:
old.add(json.loads(line)["typo"])
j = json.loads(line)
if j["type"] == "typo":
old.add(j["typo"])
clean = True
with open(sys.argv[2]) as new_file:
for line in new_file:
new = json.loads(line)
if new["typo"] not in old:
if new["type"] == "typo" and new["typo"] not in old:
if len(new["typo"]) > 6: # Short typos might be false positives. Long are probably real.
clean = False
print("::warning file={},line={},col={}::perhaps \"{}\" should be \"{}\".".format(
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Language changes
pkgimage caches for all other packages than the package being tested, likely meaning faster test
execution. ([#52123])

* Specifying a path in `JULIA_DEPOT_PATH` now results in the expansion of empty strings to
omit the default user depot ([#51448]).

Compiler/Runtime improvements
-----------------------------
* Updated GC heuristics to count allocated pages instead of individual objects ([#50144]).
Expand All @@ -50,6 +53,9 @@ Command-line option changes
This is intended to unify script and compilation workflows, where code loading may happen
in the compiler and execution of `Main.main` may happen in the resulting executable. For interactive use, there is no semantic
difference between defining a `main` function and executing the code directly at the end of the script ([50974]).
* The `--compiled-modules` and `--pkgimages` flags can now be set to `existing`, which will
cause Julia to consider loading existing cache files, but not to create new ones ([#50586]
and [#52573]).

Multi-threading changes
-----------------------
Expand Down Expand Up @@ -109,6 +115,7 @@ Standard library changes
* `eigvals/eigen(A, bunchkaufman(B))` and `eigvals/eigen(A, lu(B))`, which utilize the Bunchkaufman (LDL) and LU decomposition of `B`,
respectively, now efficiently compute the generalized eigenvalues (`eigen`: and eigenvectors) of `A` and `B`. Note: The second
argument is the output of `bunchkaufman` or `lu` ([#50471]).
* Structured matrices now retain either the axes of the parent (for `Symmetric`/`Hermitian`/`AbstractTriangular`/`UpperHessenberg`), or that of the principal diagonal (for banded matrices) ([#52480]).

#### Printf

Expand Down
41 changes: 17 additions & 24 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -678,15 +678,12 @@ function checkbounds(::Type{Bool}, A::AbstractArray, I...)
checkbounds_indices(Bool, axes(A), I)
end

# Linear indexing is explicitly allowed when there is only one (non-cartesian) index
# Linear indexing is explicitly allowed when there is only one (non-cartesian) index;
# indices that do not allow linear indexing (e.g., logical arrays, cartesian indices, etc)
# must add specialized methods to implement their restrictions
function checkbounds(::Type{Bool}, A::AbstractArray, i)
@inline
checkindex(Bool, eachindex(IndexLinear(), A), i)
end
# As a special extension, allow using logical arrays that match the source array exactly
function checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::AbstractArray{Bool,N}) where N
@inline
axes(A) == axes(I)
return checkindex(Bool, eachindex(IndexLinear(), A), i)
end

"""
Expand Down Expand Up @@ -720,16 +717,13 @@ of `IA`.
See also [`checkbounds`](@ref).
"""
function checkbounds_indices(::Type{Bool}, IA::Tuple, I::Tuple)
@inline
checkindex(Bool, IA[1], I[1])::Bool & checkbounds_indices(Bool, tail(IA), tail(I))
end
function checkbounds_indices(::Type{Bool}, ::Tuple{}, I::Tuple)
function checkbounds_indices(::Type{Bool}, inds::Tuple, I::Tuple{Any, Vararg})
@inline
checkindex(Bool, OneTo(1), I[1])::Bool & checkbounds_indices(Bool, (), tail(I))
return checkindex(Bool, get(inds, 1, OneTo(1)), I[1])::Bool &
checkbounds_indices(Bool, safe_tail(inds), tail(I))
end
checkbounds_indices(::Type{Bool}, IA::Tuple, ::Tuple{}) = (@inline; all(x->length(x)==1, IA))
checkbounds_indices(::Type{Bool}, ::Tuple{}, ::Tuple{}) = true

checkbounds_indices(::Type{Bool}, inds::Tuple, ::Tuple{}) = (@inline; all(x->length(x)==1, inds))

# check along a single dimension
"""
Expand All @@ -751,20 +745,19 @@ julia> checkindex(Bool, 1:20, 21)
false
```
"""
checkindex(::Type{Bool}, inds::AbstractUnitRange, i) =
throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))"))
checkindex(::Type{Bool}, inds, i) = throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))"))
checkindex(::Type{Bool}, inds::AbstractUnitRange, i::Real) = (first(inds) <= i) & (i <= last(inds))
checkindex(::Type{Bool}, inds::IdentityUnitRange, i::Real) = checkindex(Bool, inds.indices, i)
checkindex(::Type{Bool}, inds::OneTo{T}, i::T) where {T<:BitInteger} = unsigned(i - one(i)) < unsigned(last(inds))
checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Colon) = true
checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Slice) = true
function checkindex(::Type{Bool}, inds::AbstractUnitRange, r::AbstractRange)
@_propagate_inbounds_meta
isempty(r) | (checkindex(Bool, inds, first(r)) & checkindex(Bool, inds, last(r)))
end
checkindex(::Type{Bool}, indx::AbstractUnitRange, I::AbstractVector{Bool}) = indx == axes1(I)
checkindex(::Type{Bool}, indx::AbstractUnitRange, I::AbstractArray{Bool}) = false
function checkindex(::Type{Bool}, inds::AbstractUnitRange, I::AbstractArray)
checkindex(::Type{Bool}, inds::AbstractUnitRange, i::AbstractRange) =
isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i)))
# range like indices with cheap `extrema`
checkindex(::Type{Bool}, inds::AbstractUnitRange, i::LinearIndices) =
isempty(i) | (checkindex(Bool, inds, first(i)) & checkindex(Bool, inds, last(i)))

function checkindex(::Type{Bool}, inds, I::AbstractArray)
@inline
b = true
for i in I
Expand Down
2 changes: 1 addition & 1 deletion base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ julia> B[invperm(v)]
"""
function invperm(a::AbstractVector)
require_one_based_indexing(a)
b = zero(a) # similar vector of zeros
b = fill!(similar(a), zero(eltype(a))) # mutable vector of zeros
n = length(a)
@inbounds for (i, j) in enumerate(a)
((1 <= j <= n) && b[j] == 0) ||
Expand Down
14 changes: 10 additions & 4 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2088,8 +2088,13 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
rt = abstract_call_builtin(interp, f, arginfo, sv)
ft = popfirst!(argtypes)
effects = builtin_effects(𝕃ᵢ, f, argtypes, rt)
if effects.nothrow
exct = Union{}
else
exct = builtin_exct(𝕃ᵢ, f, argtypes, rt)
end
pushfirst!(argtypes, ft)
return CallMeta(rt, effects.nothrow ? Union{} : Any, effects, NoCallInfo())
return CallMeta(rt, exct, effects, NoCallInfo())
elseif isa(f, Core.OpaqueClosure)
# calling an OpaqueClosure about which we have no information returns no information
return CallMeta(typeof(f).parameters[2], Any, Effects(), NoCallInfo())
Expand Down Expand Up @@ -3099,7 +3104,8 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
end
end

function update_exc_bestguess!(@nospecialize(exct), frame::InferenceState, 𝕃ₚ::AbstractLattice)
function update_exc_bestguess!(interp::AbstractInterpreter, @nospecialize(exct), frame::InferenceState)
𝕃ₚ = ipo_lattice(interp)
cur_hand = frame.handler_at[frame.currpc][1]
if cur_hand == 0
if !(𝕃ₚ, exct, frame.exc_bestguess)
Expand Down Expand Up @@ -3200,7 +3206,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
if nothrow
add_curr_ssaflag!(frame, IR_FLAG_NOTHROW)
else
update_exc_bestguess!(TypeError, frame, ipo_lattice(interp))
update_exc_bestguess!(interp, TypeError, frame)
propagate_to_error_handler!(currstate, frame, 𝕃ᵢ)
merge_effects!(interp, frame, EFFECTS_THROWS)
end
Expand Down Expand Up @@ -3296,7 +3302,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
(; changes, rt, exct) = abstract_eval_basic_statement(interp,
stmt, currstate, frame)
if exct !== Union{}
update_exc_bestguess!(exct, frame, ipo_lattice(interp))
update_exc_bestguess!(interp, exct, frame)
end
if !has_curr_ssaflag(frame, IR_FLAG_NOTHROW)
propagate_to_error_handler!(currstate, frame, 𝕃ᵢ)
Expand Down
10 changes: 7 additions & 3 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,10 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet)
handler_id = length(handlers)
handler_at[pc + 1] = (handler_id, 0)
push!(ip, pc + 1)
handler_at[l] = (0, handler_id)
push!(ip, l)
if l != 0
handler_at[l] = (0, handler_id)
push!(ip, l)
end
end
end

Expand Down Expand Up @@ -402,7 +404,9 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet)
l = stmt.catch_dest
# We assigned a handler number above. Here we just merge that
# with out current handler information.
handler_at[l] = (cur_stacks[1], handler_at[l][2])
if l != 0
handler_at[l] = (cur_stacks[1], handler_at[l][2])
end
cur_stacks = (handler_at[pc´][1], cur_stacks[2])
elseif isa(stmt, Expr)
head = stmt.head
Expand Down
26 changes: 19 additions & 7 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ function argextype(
return Const(x.value)
elseif isa(x, GlobalRef)
return abstract_eval_globalref_type(x)
elseif isa(x, PhiNode)
elseif isa(x, PhiNode) || isa(x, PhiCNode) || isa(x, UpsilonNode)
return Any
elseif isa(x, PiNode)
return x.typ
Expand Down Expand Up @@ -978,7 +978,16 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
catchdest = expr.catch_dest
if catchdest in sv.unreachable
cfg_delete_edge!(sv.cfg, block_for_inst(sv.cfg, i), block_for_inst(sv.cfg, catchdest))
code[i] = nothing
if isdefined(expr, :scope)
# We've proven that nothing inside the enter region throws,
# but we don't yet know whether something might read the scope,
# so we need to retain this enter for the time being. However,
# we use the special marker `0` to indicate that setting up
# the try/catch frame is not required.
code[i] = EnterNode(expr, 0)
else
code[i] = nothing
end
end
end
end
Expand Down Expand Up @@ -1364,11 +1373,14 @@ function renumber_ir_elements!(body::Vector{Any}, ssachangemap::Vector{Int}, lab
end
elseif isa(el, EnterNode)
tgt = el.catch_dest
was_deleted = labelchangemap[tgt] == typemin(Int)
if was_deleted
body[i] = nothing
else
body[i] = EnterNode(el, tgt + labelchangemap[tgt])
if tgt != 0
was_deleted = labelchangemap[tgt] == typemin(Int)
if was_deleted
@assert !isdefined(el, :scope)
body[i] = nothing
else
body[i] = EnterNode(el, tgt + labelchangemap[tgt])
end
end
elseif isa(el, Expr)
if el.head === :(=) && el.args[2] isa Expr
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
elseif isa(stmt′, GotoNode)
stmt′ = GotoNode(stmt′.label + bb_offset)
elseif isa(stmt′, EnterNode)
stmt′ = EnterNode(stmt′, stmt′.catch_dest + bb_offset)
stmt′ = EnterNode(stmt′, stmt′.catch_dest == 0 ? 0 : stmt′.catch_dest + bb_offset)
elseif isa(stmt′, GotoIfNot)
stmt′ = GotoIfNot(stmt′.cond, stmt′.dest + bb_offset)
elseif isa(stmt′, PhiNode)
Expand Down Expand Up @@ -711,7 +711,7 @@ function batch_inline!(ir::IRCode, todo::Vector{Pair{Int,Any}}, propagate_inboun
elseif isa(stmt, GotoNode)
compact[idx] = GotoNode(state.bb_rename[stmt.label])
elseif isa(stmt, EnterNode)
compact[idx] = EnterNode(stmt, state.bb_rename[stmt.catch_dest])
compact[idx] = EnterNode(stmt, stmt.catch_dest == 0 ? 0 : state.bb_rename[stmt.catch_dest])
elseif isa(stmt, GotoIfNot)
compact[idx] = GotoIfNot(stmt.cond, state.bb_rename[stmt.dest])
elseif isa(stmt, PhiNode)
Expand Down
44 changes: 29 additions & 15 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Core.PhiNode() = Core.PhiNode(Int32[], Any[])

isterminator(@nospecialize(stmt)) = isa(stmt, GotoNode) || isa(stmt, GotoIfNot) || isa(stmt, ReturnNode) || isa(stmt, EnterNode)
isterminator(@nospecialize(stmt)) = isa(stmt, GotoNode) || isa(stmt, GotoIfNot) || isa(stmt, ReturnNode) || isa(stmt, EnterNode) || isexpr(stmt, :leave)

struct CFG
blocks::Vector{BasicBlock}
Expand Down Expand Up @@ -65,7 +65,9 @@ block_for_inst(cfg::CFG, inst::Int) = block_for_inst(cfg.index, inst)
push!(jump_dests, idx)
push!(jump_dests, idx+1)
# The catch block is a jump dest
push!(jump_dests, stmt.catch_dest)
if stmt.catch_dest != 0
push!(jump_dests, stmt.catch_dest)
end
elseif isa(stmt, Expr)
if stmt.head === :leave
# :leave terminates a BB
Expand Down Expand Up @@ -129,10 +131,12 @@ function compute_basic_blocks(stmts::Vector{Any})
# :enter gets a virtual edge to the exception handler and
# the exception handler gets a virtual edge from outside
# the function.
block′ = block_for_inst(basic_block_index, terminator.catch_dest)
push!(blocks[block′].preds, num)
push!(blocks[block′].preds, 0)
push!(b.succs, block′)
if terminator.catch_dest != 0
block′ = block_for_inst(basic_block_index, terminator.catch_dest)
push!(blocks[block′].preds, num)
push!(blocks[block′].preds, 0)
push!(b.succs, block′)
end
end
# statement fall-through
if num + 1 <= length(blocks)
Expand Down Expand Up @@ -949,11 +953,15 @@ function insert_node!(compact::IncrementalCompact, @nospecialize(before), newins
end
end

function maybe_reopen_bb!(compact)
function did_just_finish_bb(compact)
result_idx = compact.result_idx
result_bbs = compact.cfg_transform.result_bbs
if (compact.active_result_bb == length(result_bbs) + 1) ||
result_idx == first(result_bbs[compact.active_result_bb].stmts)
(compact.active_result_bb == length(result_bbs) + 1) ||
result_idx == first(result_bbs[compact.active_result_bb].stmts)
end

function maybe_reopen_bb!(compact)
if did_just_finish_bb(compact)
compact.active_result_bb -= 1
return true
end
Expand Down Expand Up @@ -1355,7 +1363,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
(; result, ssa_rename, late_fixup, used_ssas, new_new_used_ssas) = compact
(; cfg_transforms_enabled, fold_constant_branches, bb_rename_succ, bb_rename_pred, result_bbs) = compact.cfg_transform
mark_refined! = Refiner(result.flag, result_idx)
already_inserted = (::Int, ssa::OldSSAValue)->ssa.id <= processed_idx
already_inserted_phi_arg = already_inserted_ssa(compact, processed_idx)
if stmt === nothing
ssa_rename[idx] = stmt
elseif isa(stmt, OldSSAValue)
Expand Down Expand Up @@ -1415,10 +1423,14 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
end
elseif cfg_transforms_enabled && isa(stmt, EnterNode)
stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa, mark_refined!)::EnterNode
label = bb_rename_succ[stmt.catch_dest]
@assert label > 0
if stmt.catch_dest != 0
label = bb_rename_succ[stmt.catch_dest]
@assert label > 0
result[result_idx][:stmt] = EnterNode(stmt, label)
else
result[result_idx][:stmt] = stmt
end
ssa_rename[idx] = SSAValue(result_idx)
result[result_idx][:stmt] = EnterNode(stmt, label)
result_idx += 1
elseif isa(stmt, Expr)
stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa, mark_refined!)::Expr
Expand Down Expand Up @@ -1527,7 +1539,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
values = stmt.values
end

values = process_phinode_values(values, late_fixup, already_inserted, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!)
values = process_phinode_values(values, late_fixup, already_inserted_phi_arg, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!)
# Don't remove the phi node if it is before the definition of its value
# because doing so can create forward references. This should only
# happen with dead loops, but can cause problems when optimization
Expand Down Expand Up @@ -1566,7 +1578,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
push!(values, value)
end
end
result[result_idx][:stmt] = PhiCNode(process_phinode_values(values, late_fixup, already_inserted, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!))
result[result_idx][:stmt] = PhiCNode(process_phinode_values(values, late_fixup, already_inserted_phi_arg, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!))
result_idx += 1
else
if isa(stmt, SSAValue)
Expand Down Expand Up @@ -1875,6 +1887,8 @@ function fixup_node(compact::IncrementalCompact, @nospecialize(stmt), reify_new_
compact.used_ssas[node.id] += 1
elseif isa(node, NewSSAValue)
compact.new_new_used_ssas[-node.id] += 1
elseif isa(node, OldSSAValue)
return fixup_node(compact, node, reify_new_nodes)
end
return FixedNode(node, needs_fixup)
else
Expand Down
Loading

0 comments on commit 6855e6c

Please sign in to comment.