Skip to content

Commit

Permalink
Merge branch 'JuliaLang:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
atomicdog authored Nov 30, 2024
2 parents c0d5f5b + c1f806d commit cfaa382
Show file tree
Hide file tree
Showing 141 changed files with 889 additions and 54,675 deletions.
57 changes: 34 additions & 23 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,7 @@ end

struct InvokeCall
types # ::Type
lookupsig # ::Type
InvokeCall(@nospecialize(types), @nospecialize(lookupsig)) = new(types, lookupsig)
InvokeCall(@nospecialize(types)) = new(types)
end

struct ConstCallResult
Expand Down Expand Up @@ -2218,34 +2217,46 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt
ft′ = argtype_by_index(argtypes, 2)
ft = widenconst(ft′)
ft === Bottom && return Future(CallMeta(Bottom, Any, EFFECTS_THROWS, NoCallInfo()))
(types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3), false)
isexact || return Future(CallMeta(Any, Any, Effects(), NoCallInfo()))
unwrapped = unwrap_unionall(types)
types === Bottom && return Future(CallMeta(Bottom, Any, EFFECTS_THROWS, NoCallInfo()))
if !(unwrapped isa DataType && unwrapped.name === Tuple.name)
return Future(CallMeta(Bottom, TypeError, EFFECTS_THROWS, NoCallInfo()))
end
argtype = argtypes_to_type(argtype_tail(argtypes, 4))
nargtype = typeintersect(types, argtype)
nargtype === Bottom && return Future(CallMeta(Bottom, TypeError, EFFECTS_THROWS, NoCallInfo()))
nargtype isa DataType || return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) # other cases are not implemented below
isdispatchelem(ft) || return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
ft = ft::DataType
lookupsig = rewrap_unionall(Tuple{ft, unwrapped.parameters...}, types)::Type
nargtype = Tuple{ft, nargtype.parameters...}
argtype = Tuple{ft, argtype.parameters...}
matched, valid_worlds = findsup(lookupsig, method_table(interp))
matched === nothing && return Future(CallMeta(Any, Any, Effects(), NoCallInfo()))
update_valid_age!(sv, valid_worlds)
method = matched.method
types = argtype_by_index(argtypes, 3)
if types isa Const && types.val isa Method
method = types.val::Method
types = method # argument value
lookupsig = method.sig # edge kind
argtype = argtypes_to_type(pushfirst!(argtype_tail(argtypes, 4), ft))
nargtype = typeintersect(lookupsig, argtype)
nargtype === Bottom && return Future(CallMeta(Bottom, TypeError, EFFECTS_THROWS, NoCallInfo()))
nargtype isa DataType || return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) # other cases are not implemented below
else
widenconst(types) >: Method && return Future(CallMeta(Any, Any, Effects(), NoCallInfo()))
(types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3), false)
isexact || return Future(CallMeta(Any, Any, Effects(), NoCallInfo()))
unwrapped = unwrap_unionall(types)
types === Bottom && return Future(CallMeta(Bottom, Any, EFFECTS_THROWS, NoCallInfo()))
if !(unwrapped isa DataType && unwrapped.name === Tuple.name)
return Future(CallMeta(Bottom, TypeError, EFFECTS_THROWS, NoCallInfo()))
end
argtype = argtypes_to_type(argtype_tail(argtypes, 4))
nargtype = typeintersect(types, argtype)
nargtype === Bottom && return Future(CallMeta(Bottom, TypeError, EFFECTS_THROWS, NoCallInfo()))
nargtype isa DataType || return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) # other cases are not implemented below
isdispatchelem(ft) || return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
ft = ft::DataType
lookupsig = rewrap_unionall(Tuple{ft, unwrapped.parameters...}, types)::Type
nargtype = Tuple{ft, nargtype.parameters...}
argtype = Tuple{ft, argtype.parameters...}
matched, valid_worlds = findsup(lookupsig, method_table(interp))
matched === nothing && return Future(CallMeta(Any, Any, Effects(), NoCallInfo()))
update_valid_age!(sv, valid_worlds)
method = matched.method
end
tienv = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector
ti = tienv[1]
env = tienv[2]::SimpleVector
mresult = abstract_call_method(interp, method, ti, env, false, si, sv)::Future
match = MethodMatch(ti, env, method, argtype <: method.sig)
ft′_box = Core.Box(ft′)
lookupsig_box = Core.Box(lookupsig)
invokecall = InvokeCall(types, lookupsig)
invokecall = InvokeCall(types)
return Future{CallMeta}(mresult, interp, sv) do result, interp, sv
(; rt, exct, effects, edge, volatile_inf_result) = result
local ft′ = ft′_box.contents
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/abstractlattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ end
if isa(t, Const)
# don't consider mutable values useful constants
val = t.val
return isa(val, Symbol) || isa(val, Type) || !ismutable(val)
return isa(val, Symbol) || isa(val, Type) || isa(val, Method) || !ismutable(val)
end
isa(t, PartialTypeVar) && return false # this isn't forwardable
return is_const_prop_profitable_arg(widenlattice(𝕃), t)
Expand Down
6 changes: 4 additions & 2 deletions Compiler/src/ssair/irinterp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,10 @@ function process_terminator!(@nospecialize(stmt), bb::Int, bb_ip::BitSetBoundedM
return backedge
elseif isa(stmt, EnterNode)
dest = stmt.catch_dest
@assert dest > bb
push!(bb_ip, dest)
if dest 0
@assert dest > bb
push!(bb_ip, dest)
end
push!(bb_ip, bb+1)
return false
else
Expand Down
6 changes: 4 additions & 2 deletions Compiler/src/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2393,8 +2393,10 @@ function cfg_simplify!(ir::IRCode)
end
elseif isa(terminator, EnterNode)
catchbb = terminator.catch_dest
if bb_rename_succ[catchbb] == 0
push!(worklist, catchbb)
if catchbb 0
if bb_rename_succ[catchbb] == 0
push!(worklist, catchbb)
end
end
elseif isa(terminator, GotoNode) || isa(terminator, ReturnNode)
# No implicit fall through. Schedule from work list.
Expand Down
4 changes: 2 additions & 2 deletions Compiler/src/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ function count_const_size(@nospecialize(x), count_self::Bool = true)
# No definite size
(isa(x, GenericMemory) || isa(x, String) || isa(x, SimpleVector)) &&
return MAX_INLINE_CONST_SIZE + 1
if isa(x, Module)
# We allow modules, because we already assume they are externally
if isa(x, Module) || isa(x, Method)
# We allow modules and methods, because we already assume they are externally
# rooted, so we count their contents as 0 size.
return sizeof(Ptr{Cvoid})
end
Expand Down
3 changes: 1 addition & 2 deletions Compiler/test/EAUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ export code_escapes, @code_escapes, __clear_cache!

include("setup_Compiler.jl")

using ..EscapeAnalysis
const EA = EscapeAnalysis
using .Compiler: EscapeAnalysis as EA

# AbstractInterpreter
# -------------------
Expand Down
29 changes: 28 additions & 1 deletion Compiler/test/irpasses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,34 @@ function f53521()
end
end
end
@test code_typed(f53521)[1][2] === Nothing
let (ir,rt) = only(Base.code_ircode(f53521, ()))
@test rt == Nothing
Compiler.verify_ir(ir)
Compiler.cfg_simplify!(ir)
Compiler.verify_ir(ir)
end

Base.@assume_effects :foldable Base.@constprop :aggressive function f53521(x::Int, ::Int)
VALUE = ScopedValue(x)
@with VALUE => 2 begin
for i = 1
@with VALUE => 3 begin
local v
try
v = sin(VALUE[])
catch
v = nothing
end
return v
end
end
end
end
let (ir,rt) = only(Base.code_ircode((Int,)) do y
f53521(1, y)
end)
@test rt == Union{Nothing,Float64}
end

# Test that adce_pass! sets Refined on PhiNode values
let code = Any[
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ New library features
* `Base.require_one_based_indexing` and `Base.has_offset_axes` are now public ([#56196])
* New `ltruncate`, `rtruncate` and `ctruncate` functions for truncating strings to text width, accounting for char widths ([#55351])
* `isless` (and thus `cmp`, sorting, etc.) is now supported for zero-dimensional `AbstractArray`s ([#55772])
* `invoke` now supports passing a Method instead of a type signature making this interface somewhat more flexible for certain uncommon use cases ([#56692]).

Standard library changes
------------------------
Expand Down
2 changes: 1 addition & 1 deletion base/cmd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ end
"""
@cmd str
Similar to `cmd`, generate a `Cmd` from the `str` string which represents the shell command(s) to be executed.
Similar to ``` `str` ```, generate a `Cmd` from the `str` string which represents the shell command(s) to be executed.
The [`Cmd`](@ref) object can be run as a process and can outlive the spawning julia process (see `Cmd` for more).
# Examples
Expand Down
15 changes: 13 additions & 2 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2030,21 +2030,32 @@ applicable

"""
invoke(f, argtypes::Type, args...; kwargs...)
invoke(f, argtypes::Method, args...; kwargs...)
Invoke a method for the given generic function `f` matching the specified types `argtypes` on the
specified arguments `args` and passing the keyword arguments `kwargs`. The arguments `args` must
conform with the specified types in `argtypes`, i.e. conversion is not automatically performed.
This method allows invoking a method other than the most specific matching method, which is useful
when the behavior of a more general definition is explicitly needed (often as part of the
implementation of a more specific method of the same function).
implementation of a more specific method of the same function). However, because this means
the runtime must do more work, `invoke` is generally also slower--sometimes significantly
so--than doing normal dispatch with a regular call.
Be careful when using `invoke` for functions that you don't write. What definition is used
Be careful when using `invoke` for functions that you don't write. What definition is used
for given `argtypes` is an implementation detail unless the function is explicitly states
that calling with certain `argtypes` is a part of public API. For example, the change
between `f1` and `f2` in the example below is usually considered compatible because the
change is invisible by the caller with a normal (non-`invoke`) call. However, the change is
visible if you use `invoke`.
# Passing a `Method` instead of a signature
The `argtypes` argument may be a `Method`, in which case the ordinary method table lookup is
bypassed entirely and the given method is invoked directly. Needing this feature is uncommon.
Note in particular that the specified `Method` may be entirely unreachable from ordinary dispatch
(or ordinary invoke), e.g. because it was replaced or fully covered by more specific methods.
If the method is part of the ordinary method table, this call behaves similar
to `invoke(f, method.sig, args...)`.
# Examples
```jldoctest
julia> f(x::Real) = x^2;
Expand Down
9 changes: 9 additions & 0 deletions base/experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,13 @@ function entrypoint(@nospecialize(argt::Type))
nothing
end

"""
Base.Experimental.disable_new_worlds()
Mark that no new worlds (methods additions, deletions, etc) are permitted to be created at
any future time, allowing for lower latencies for some operations and slightly lower memory
usage, by eliminating the tracking of those possible invalidation.
"""
disable_new_worlds() = ccall(:jl_disable_new_worlds, Cvoid, ())

end
8 changes: 4 additions & 4 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -924,8 +924,8 @@ end
"""
nextfloat(x::AbstractFloat)
Return the smallest floating point number `y` of the same type as `x` such `x < y`. If no
such `y` exists (e.g. if `x` is `Inf` or `NaN`), then return `x`.
Return the smallest floating point number `y` of the same type as `x` such that `x < y`.
If no such `y` exists (e.g. if `x` is `Inf` or `NaN`), then return `x`.
See also: [`prevfloat`](@ref), [`eps`](@ref), [`issubnormal`](@ref).
"""
Expand All @@ -942,8 +942,8 @@ prevfloat(x::AbstractFloat, d::Integer) = nextfloat(x, -d)
"""
prevfloat(x::AbstractFloat)
Return the largest floating point number `y` of the same type as `x` such `y < x`. If no
such `y` exists (e.g. if `x` is `-Inf` or `NaN`), then return `x`.
Return the largest floating point number `y` of the same type as `x` such that `y < x`.
If no such `y` exists (e.g. if `x` is `-Inf` or `NaN`), then return `x`.
"""
prevfloat(x::AbstractFloat) = nextfloat(x,-1)

Expand Down
3 changes: 2 additions & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,8 @@ julia> binomial(-5, 3)
# External links
* [Binomial coefficient](https://en.wikipedia.org/wiki/Binomial_coefficient) on Wikipedia.
"""
binomial(n::Integer, k::Integer) = binomial(promote(n, k)...)

Base.@assume_effects :terminates_locally function binomial(n::T, k::T) where T<:Integer
n0, k0 = n, k
k < 0 && return zero(T)
Expand Down Expand Up @@ -1233,7 +1235,6 @@ Base.@assume_effects :terminates_locally function binomial(n::T, k::T) where T<:
end
copysign(x, sgn)
end
binomial(n::Integer, k::Integer) = binomial(promote(n, k)...)

"""
binomial(x::Number, k::Integer)
Expand Down
14 changes: 11 additions & 3 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,7 @@ function run_module_init(mod::Module, i::Int=1)
end

function run_package_callbacks(modkey::PkgId)
@assert modkey != precompilation_target
run_extension_callbacks(modkey)
assert_havelock(require_lock)
unlock(require_lock)
Expand Down Expand Up @@ -1562,7 +1563,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
uuid_trigger = UUID(totaldeps[trigger]::String)
trigger_id = PkgId(uuid_trigger, trigger)
push!(trigger_ids, trigger_id)
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id)
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) || (trigger_id == precompilation_target)
trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
push!(trigger1, gid)
else
Expand All @@ -1575,6 +1576,7 @@ end
loading_extension::Bool = false
loadable_extensions::Union{Nothing,Vector{PkgId}} = nothing
precompiling_extension::Bool = false
precompilation_target::Union{Nothing,PkgId} = nothing
function run_extension_callbacks(extid::ExtensionId)
assert_havelock(require_lock)
succeeded = try
Expand All @@ -1585,9 +1587,14 @@ function run_extension_callbacks(extid::ExtensionId)
true
catch
# Try to continue loading if loading an extension errors
errs = current_exceptions()
@error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \
if JLOptions().incremental != 0
# during incremental precompilation, this should be fail-fast
rethrow()
else
errs = current_exceptions()
@error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \
use `Base.retry_load_extensions()` to retry." exception=errs
end
false
finally
global loading_extension = false
Expand Down Expand Up @@ -3081,6 +3088,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
Base.track_nested_precomp($(_pkg_str(vcat(Base.precompilation_stack, pkg))))
Base.loadable_extensions = $(_pkg_str(loadable_exts))
Base.precompiling_extension = $(loading_extension)
Base.precompilation_target = $(_pkg_str(pkg))
Base.include_package_for_output($(_pkg_str(pkg)), $(repr(abspath(input))), $(repr(depot_path)), $(repr(dl_load_path)),
$(repr(load_path)), $(_pkg_str(concrete_deps)), $(repr(source_path(nothing))))
""")
Expand Down
2 changes: 1 addition & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ function show_circular(io::IOContext, @nospecialize(x))
for (k, v) in io.dict
if k === :SHOWN_SET
if v === x
print(io, "#= circular reference @-$d =#")
printstyled(io, "#= circular reference @-$d =#"; color = :yellow)
return true
end
d += 1
Expand Down
Loading

0 comments on commit cfaa382

Please sign in to comment.