Skip to content

Commit

Permalink
Merge branch 'master' into nz/fix-local-repl-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nhz2 authored Oct 23, 2024
2 parents 4a403d3 + 133051f commit 0636b9f
Show file tree
Hide file tree
Showing 107 changed files with 2,910 additions and 1,999 deletions.
8 changes: 8 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ Standard library changes
`AnnotatedString` with various faces or other attributes applied ([#49586]).

#### Package Manager
* It is now possible to specify "sources" for packages in a `[sources]` section in Project.toml.
This can be used to add non-registered normal or test dependencies.
* Pkg now obeys `[compat]` bounds for `julia` and raises an error if the version of the running Julia binary is incompatible with the bounds in `Project.toml`.
Pkg has always obeyed this compat when working with Registry packages. This change affects mostly local packages
* `pkg> add` and `Pkg.add` will now add compat entries for new direct dependencies if the active environment is a
package (has a `name` and `uuid` entry).
* Dependencies can now be directly added as weak deps or extras via the `pkg> add --weak/extra Foo` or
`Pkg.add("Foo", target=:weakdeps/:extras)` forms.

#### LinearAlgebra
* `cbrt(::AbstractMatrix{<:Real})` is now defined and returns real-valued matrix cube roots of real-valued matrices ([#50661]).
Expand Down
17 changes: 13 additions & 4 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ function include(mod::Module, path::String)
end
include(path::String) = include(Base, path)

struct IncludeInto <: Function
m::Module
end
(this::IncludeInto)(fname::AbstractString) = include(this.m, fname)

# from now on, this is now a top-module for resolving syntax
const is_primary_base_module = ccall(:jl_module_parent, Ref{Module}, (Any,), Base) === Core.Main
ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Base, is_primary_base_module)
Expand Down Expand Up @@ -533,6 +538,7 @@ include("deepcopy.jl")
include("download.jl")
include("summarysize.jl")
include("errorshow.jl")
include("util.jl")

include("initdefs.jl")
Filesystem.__postinit__()
Expand All @@ -549,7 +555,6 @@ include("loading.jl")

# misc useful functions & macros
include("timing.jl")
include("util.jl")
include("client.jl")
include("asyncmap.jl")

Expand All @@ -572,15 +577,20 @@ include("precompilation.jl")
for m in methods(include)
delete_method(m)
end
for m in methods(IncludeInto(Base))
delete_method(m)
end

# This method is here only to be overwritten during the test suite to test
# various sysimg related invalidation scenarios.
a_method_to_overwrite_in_test() = inferencebarrier(1)

# These functions are duplicated in client.jl/include(::String) for
# nicer stacktraces. Modifications here have to be backported there
include(mod::Module, _path::AbstractString) = _include(identity, mod, _path)
include(mapexpr::Function, mod::Module, _path::AbstractString) = _include(mapexpr, mod, _path)
@noinline include(mod::Module, _path::AbstractString) = _include(identity, mod, _path)
@noinline include(mapexpr::Function, mod::Module, _path::AbstractString) = _include(mapexpr, mod, _path)
(this::IncludeInto)(fname::AbstractString) = include(identity, this.m, fname)
(this::IncludeInto)(mapexpr::Function, fname::AbstractString) = include(mapexpr, this.m, fname)

# External libraries vendored into Base
Core.println("JuliaSyntax/src/JuliaSyntax.jl")
Expand Down Expand Up @@ -646,7 +656,6 @@ function __init__()
init_load_path()
init_active_project()
append!(empty!(_sysimage_modules), keys(loaded_modules))
empty!(explicit_loaded_modules)
empty!(loaded_precompiles) # If we load a packageimage when building the image this might not be empty
for (mod, key) in module_keys
push!(get!(Vector{Module}, loaded_precompiles, key), mod)
Expand Down
11 changes: 11 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,17 @@ copy
return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size)))
end

# a mutating version of copyto! that results in dst aliasing src afterwards
function _take!(dst::Array{T,N}, src::Array{T,N}) where {T,N}
if getfield(dst, :ref) !== getfield(src, :ref)
setfield!(dst, :ref, getfield(src, :ref))
end
if getfield(dst, :size) !== getfield(src, :size)
setfield!(dst, :size, getfield(src, :size))
end
return dst
end

## Constructors ##

similar(a::Array{T,1}) where {T} = Vector{T}(undef, size(a,1))
Expand Down
8 changes: 6 additions & 2 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,13 @@ Nothing() = nothing
# This should always be inlined
getptls() = ccall(:jl_get_ptls_states, Ptr{Cvoid}, ())

include(m::Module, fname::String) = ccall(:jl_load_, Any, (Any, Any), m, fname)
include(m::Module, fname::String) = (@noinline; ccall(:jl_load_, Any, (Any, Any), m, fname))
eval(m::Module, @nospecialize(e)) = (@noinline; ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e))

eval(m::Module, @nospecialize(e)) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e)
struct EvalInto <: Function
m::Module
end
(this::EvalInto)(@nospecialize(e)) = eval(this.m, e)

mutable struct Box
contents::Any
Expand Down
75 changes: 46 additions & 29 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -339,43 +339,58 @@ RPO traversal and in particular, any use of an SSA value must come after
(by linear order) its definition.
"""
function domsort_ssa!(ir::IRCode, domtree::DomTree)
# First compute the new order of basic blocks
# Mapping from new → old BB index
# An "old" index of 0 means that this was a BB inserted as part of a fixup (see below)
result_order = Int[]
stack = Int[]

# Mapping from old → new BB index
bb_rename = fill(-1, length(ir.cfg.blocks))
node = 1
ncritbreaks = 0
nnewfallthroughs = 0
while node !== -1
push!(result_order, node)
bb_rename[node] = length(result_order)
cs = domtree.nodes[node].children
terminator = ir[SSAValue(last(ir.cfg.blocks[node].stmts))][:stmt]
next_node = node + 1
node = -1

# The number of GotoNodes we need to insert to preserve control-flow after sorting
nfixupstmts = 0

# node queued up for scheduling (-1 === nothing)
node_to_schedule = 1
worklist = Int[]
while node_to_schedule !== -1
# First assign a new BB index to `node_to_schedule`
push!(result_order, node_to_schedule)
bb_rename[node_to_schedule] = length(result_order)
cs = domtree.nodes[node_to_schedule].children
terminator = ir[SSAValue(last(ir.cfg.blocks[node_to_schedule].stmts))][:stmt]
fallthrough = node_to_schedule + 1
node_to_schedule = -1

# Adding the nodes in reverse sorted order attempts to retain
# the original source order of the nodes as much as possible.
# This is not required for correctness, but is easier on the humans
for child in Iterators.Reverse(cs)
if child == next_node
for node in Iterators.Reverse(cs)
if node == fallthrough
# Schedule the fall through node first,
# so we can retain the fall through
node = next_node
node_to_schedule = node
else
push!(stack, child)
push!(worklist, node)
end
end
if node == -1 && !isempty(stack)
node = pop!(stack)
if node_to_schedule == -1 && !isempty(worklist)
node_to_schedule = pop!(worklist)
end
if node != next_node && !isa(terminator, Union{GotoNode, ReturnNode})
# If a fallthrough successor is no longer the fallthrough after sorting, we need to
# add a GotoNode (and either extend or split the basic block as necessary)
if node_to_schedule != fallthrough && !isa(terminator, Union{GotoNode, ReturnNode})
if isa(terminator, GotoIfNot)
# Need to break the critical edge
ncritbreaks += 1
push!(result_order, 0)
elseif isa(terminator, EnterNode) || isexpr(terminator, :leave)
# Cannot extend the BasicBlock with a goto, have to split it
push!(result_order, 0)
else
nnewfallthroughs += 1
# No need for a new block, just extend
@assert !isterminator(terminator)
end
# Reserve space for the fixup goto
nfixupstmts += 1
end
end
new_bbs = Vector{BasicBlock}(undef, length(result_order))
Expand All @@ -385,7 +400,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
nstmts += length(ir.cfg.blocks[i].stmts)
end
end
result = InstructionStream(nstmts + ncritbreaks + nnewfallthroughs)
result = InstructionStream(nstmts + nfixupstmts)
inst_rename = Vector{SSAValue}(undef, length(ir.stmts) + length(ir.new_nodes))
@inbounds for i = 1:length(ir.stmts)
inst_rename[i] = SSAValue(-1)
Expand All @@ -394,7 +409,6 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
inst_rename[i + length(ir.stmts)] = SSAValue(i + length(result))
end
bb_start_off = 0
crit_edge_breaks_fixup = Tuple{Int, Int}[]
for (new_bb, bb) in pairs(result_order)
if bb == 0
nidx = bb_start_off + 1
Expand Down Expand Up @@ -426,20 +440,23 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
else
result[inst_range[end]][:stmt] = GotoNode(bb_rename[terminator.label])
end
elseif isa(terminator, GotoIfNot)
# Check if we need to break the critical edge
elseif isa(terminator, GotoIfNot) || isa(terminator, EnterNode) || isexpr(terminator, :leave)
# Check if we need to break the critical edge or split the block
if bb_rename[bb + 1] != new_bb + 1
@assert result_order[new_bb + 1] == 0
# Add an explicit goto node in the next basic block (we accounted for this above)
nidx = inst_range[end] + 1
node = result[nidx]
node[:stmt], node[:type], node[:line] = GotoNode(bb_rename[bb + 1]), Any, NoLineUpdate
end
result[inst_range[end]][:stmt] = GotoIfNot(terminator.cond, bb_rename[terminator.dest])
elseif !isa(terminator, ReturnNode)
if isa(terminator, EnterNode)
if isa(terminator, GotoIfNot)
result[inst_range[end]][:stmt] = GotoIfNot(terminator.cond, bb_rename[terminator.dest])
elseif isa(terminator, EnterNode)
result[inst_range[end]][:stmt] = EnterNode(terminator, terminator.catch_dest == 0 ? 0 : bb_rename[terminator.catch_dest])
else
@assert isexpr(terminator, :leave)
end
elseif !isa(terminator, ReturnNode)
if bb_rename[bb + 1] != new_bb + 1
# Add an explicit goto node
nidx = inst_range[end] + 1
Expand All @@ -452,7 +469,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
local new_preds, new_succs
let bb = bb, bb_rename = bb_rename, result_order = result_order
new_preds = Int[bb for bb in (rename_incoming_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].preds) if bb != -1]
new_succs = Int[ rename_outgoing_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].succs]
new_succs = Int[ rename_outgoing_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].succs]
end
new_bbs[new_bb] = BasicBlock(inst_range, new_preds, new_succs)
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 @@ -601,8 +601,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 @@ -2580,7 +2580,7 @@ cases.
See also [`setproperty!`](@ref Base.setproperty!) and [`getglobal`](@ref)
# Examples
```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*"
```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*\\n.*)*"
julia> module M; global a; end;
julia> M.a # same as `getglobal(M, :a)`
Expand Down
5 changes: 4 additions & 1 deletion base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,10 @@ function _simplify_include_frames(trace)
for i in length(trace):-1:1
frame::StackFrame, _ = trace[i]
mod = parentmodule(frame)
if first_ignored === nothing
if mod === Base && frame.func === :IncludeInto ||
mod === Core && frame.func === :EvalInto
kept_frames[i] = false
elseif first_ignored === nothing
if mod === Base && frame.func === :_include
# Hide include() machinery by default
first_ignored = i
Expand Down
47 changes: 47 additions & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,53 @@ function isiterable(T)::Bool
return hasmethod(iterate, Tuple{T})
end

"""
@world(sym, world)
Resolve the binding `sym` in world `world`. See [`invoke_in_world`](@ref) for running
arbitrary code in fixed worlds. `world` may be `UnitRange`, in which case the macro
will error unless the binding is valid and has the same value across the entire world
range.
The `@world` macro is primarily used in the printing of bindings that are no longer
available in the current world.
## Example
```
julia> struct Foo; a::Int; end
Foo
julia> fold = Foo(1)
julia> Int(Base.get_world_counter())
26866
julia> struct Foo; a::Int; b::Int end
Foo
julia> fold
@world(Foo, 26866)(1)
```
!!! compat "Julia 1.12"
This functionality requires at least Julia 1.12.
"""
macro world(sym, world)
if isa(sym, Symbol)
return :($(_resolve_in_world)($(esc(world)), $(QuoteNode(GlobalRef(__module__, sym)))))
elseif isa(sym, GlobalRef)
return :($(_resolve_in_world)($(esc(world)), $(QuoteNode(sym))))
elseif isa(sym, Expr) && sym.head === :(.) &&
length(sym.args) == 2 && isa(sym.args[2], QuoteNode) && isa(sym.args[2].value, Symbol)
return :($(_resolve_in_world)($(esc(world)), $(GlobalRef)($(esc(sym.args[1])), $(sym.args[2]))))
else
error("`@world` requires a symbol or GlobalRef")
end
end

_resolve_in_world(world::Integer, gr::GlobalRef) =
invoke_in_world(UInt(world), Core.getglobal, gr.mod, gr.name)

# Special constprop heuristics for various binary opes
typename(typeof(function + end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC
typename(typeof(function - end)).constprop_heuristic = Core.SAMETYPE_HEURISTIC
Expand Down
12 changes: 11 additions & 1 deletion base/genericmemory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,17 @@ function unsafe_copyto!(dest::MemoryRef{T}, src::MemoryRef{T}, n) where {T}
@_terminates_globally_notaskstate_meta
n == 0 && return dest
@boundscheck memoryref(dest, n), memoryref(src, n)
ccall(:jl_genericmemory_copyto, Cvoid, (Any, Ptr{Cvoid}, Any, Ptr{Cvoid}, Int), dest.mem, dest.ptr_or_offset, src.mem, src.ptr_or_offset, Int(n))
if isbitstype(T)
tdest = @_gc_preserve_begin dest
tsrc = @_gc_preserve_begin src
pdest = unsafe_convert(Ptr{Cvoid}, dest)
psrc = unsafe_convert(Ptr{Cvoid}, src)
memmove(pdest, psrc, aligned_sizeof(T) * n)
@_gc_preserve_end tdest
@_gc_preserve_end tsrc
else
ccall(:jl_genericmemory_copyto, Cvoid, (Any, Ptr{Cvoid}, Any, Ptr{Cvoid}, Int), dest.mem, dest.ptr_or_offset, src.mem, src.ptr_or_offset, Int(n))
end
return dest
end

Expand Down
11 changes: 10 additions & 1 deletion base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ promote_rule(::Type{<:AbstractIrrational}, ::Type{Float16}) = Float16
promote_rule(::Type{<:AbstractIrrational}, ::Type{Float32}) = Float32
promote_rule(::Type{<:AbstractIrrational}, ::Type{<:AbstractIrrational}) = Float64
promote_rule(::Type{<:AbstractIrrational}, ::Type{T}) where {T<:Real} = promote_type(Float64, T)
promote_rule(::Type{S}, ::Type{T}) where {S<:AbstractIrrational,T<:Number} = promote_type(promote_type(S, real(T)), T)

function promote_rule(::Type{S}, ::Type{T}) where {S<:AbstractIrrational,T<:Number}
U = promote_type(S, real(T))
if S <: U
# prevent infinite recursion
promote_type(Float64, T)
else
promote_type(U, T)
end
end

AbstractFloat(x::AbstractIrrational) = Float64(x)::Float64
Float16(x::AbstractIrrational) = Float16(Float32(x)::Float32)
Expand Down
Loading

0 comments on commit 0636b9f

Please sign in to comment.