Skip to content

Commit

Permalink
Merge branch 'master' into rationalize_irrational
Browse files Browse the repository at this point in the history
  • Loading branch information
nsajko authored Jan 23, 2025
2 parents 214e24a + 88c71dd commit 3fc3cce
Show file tree
Hide file tree
Showing 97 changed files with 1,052 additions and 490 deletions.
26 changes: 19 additions & 7 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
for i in 1:length(split_argtypes)
arg_n = split_argtypes[i]::Vector{Any}
sig_n = argtypes_to_type(arg_n)
sig_n === Bottom && continue
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
mt = mt::MethodTable
Expand Down Expand Up @@ -614,7 +615,7 @@ function abstract_call_method(interp::AbstractInterpreter,
sigtuple = unwrap_unionall(sig)
sigtuple isa DataType ||
return Future(MethodCallResult(Any, Any, Effects(), nothing, false, false))
all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) ||
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) ||
return Future(MethodCallResult(Union{}, Any, EFFECTS_THROWS, nothing, false, false)) # catch bad type intersections early

if is_nospecializeinfer(method)
Expand Down Expand Up @@ -2840,6 +2841,7 @@ function abstract_call_unknown(interp::AbstractInterpreter, @nospecialize(ft),
end
# non-constant function, but the number of arguments is known and the `f` is not a builtin or intrinsic
atype = argtypes_to_type(arginfo.argtypes)
atype === Bottom && return Future(CallMeta(Union{}, Union{}, EFFECTS_THROWS, NoCallInfo())) # accidentally unreachable
return abstract_call_gf_by_type(interp, nothing, arginfo, si, atype, sv, max_methods)::Future
end

Expand Down Expand Up @@ -3454,10 +3456,10 @@ world_range(ir::IRCode) = ir.valid_worlds
world_range(ci::CodeInfo) = WorldRange(ci.min_world, ci.max_world)
world_range(compact::IncrementalCompact) = world_range(compact.ir)

function force_binding_resolution!(g::GlobalRef)
function force_binding_resolution!(g::GlobalRef, world::UInt)
# Force resolution of the binding
# TODO: This will go away once we switch over to fully partitioned semantics
ccall(:jl_globalref_boundp, Cint, (Any,), g)
ccall(:jl_force_binding_resolution, Cvoid, (Any, Csize_t), g, world)
return nothing
end

Expand All @@ -3475,7 +3477,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
# This method is surprisingly hot. For performance, don't ask the runtime to resolve
# the binding unless necessary - doing so triggers an additional lookup, which though
# not super expensive is hot enough to show up in benchmarks.
force_binding_resolution!(g)
force_binding_resolution!(g, min_world(worlds))
return abstract_eval_globalref_type(g, src, false)
end
# return Union{}
Expand All @@ -3488,7 +3490,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
end

function lookup_binding_partition!(interp::AbstractInterpreter, g::GlobalRef, sv::AbsIntState)
force_binding_resolution!(g)
force_binding_resolution!(g, get_inference_world(interp))
partition = lookup_binding_partition(get_inference_world(interp), g)
update_valid_age!(sv, WorldRange(partition.min_world, partition.max_world))
partition
Expand Down Expand Up @@ -3537,7 +3539,8 @@ function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, saw_
partition = abstract_eval_binding_partition!(interp, g, sv)
ret = abstract_eval_partition_load(interp, partition)
if ret.rt !== Union{} && ret.exct === UndefVarError && InferenceParams(interp).assume_bindings_static
if isdefined(g, :binding) && isdefined(g.binding, :value)
b = convert(Core.Binding, g)
if isdefined(b, :value)
ret = RTEffects(ret.rt, Union{}, Effects(generic_getglobal_effects, nothrow=true))
end
# We do not assume in general that assigned global bindings remain assigned.
Expand Down Expand Up @@ -3785,14 +3788,23 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
slottypes = frame.slottypes
rt = widenreturn(rt, BestguessInfo(interp, bestguess, nargs, slottypes, currstate))
# narrow representation of bestguess slightly to prepare for tmerge with rt
if rt isa InterConditional && bestguess isa Const
if rt isa InterConditional && bestguess isa Const && bestguess.val isa Bool
slot_id = rt.slot
old_id_type = widenconditional(slottypes[slot_id])
if bestguess.val === true && rt.elsetype !== Bottom
bestguess = InterConditional(slot_id, old_id_type, Bottom)
elseif bestguess.val === false && rt.thentype !== Bottom
bestguess = InterConditional(slot_id, Bottom, old_id_type)
end
# or narrow representation of rt slightly to prepare for tmerge with bestguess
elseif bestguess isa InterConditional && rt isa Const && rt.val isa Bool
slot_id = bestguess.slot
old_id_type = widenconditional(slottypes[slot_id])
if rt.val === true && bestguess.elsetype !== Bottom
rt = InterConditional(slot_id, old_id_type, Bottom)
elseif rt.val === false && bestguess.thentype !== Bottom
rt = InterConditional(slot_id, Bottom, old_id_type)
end
end
# copy limitations to return value
if !isempty(frame.pclimitations)
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
# types of call arguments only once `slot2reg` converts this `IRCode` to the SSA form
# and eliminates slots (see below)
argtypes = sv.slottypes
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, WorldRange(ci.min_world, ci.max_world))
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, world_range(ci))
end

function process_meta!(meta::Vector{Expr}, @nospecialize stmt)
Expand Down
1 change: 1 addition & 0 deletions Compiler/src/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,7 @@ function handle_call!(todo::Vector{Pair{Int,Any}},
cases === nothing && return nothing
cases, handled_all_cases, fully_covered, joint_effects = cases
atype = argtypes_to_type(sig.argtypes)
atype === Union{} && return nothing # accidentally actually unreachable
handle_cases!(todo, ir, idx, stmt, atype, cases, handled_all_cases, fully_covered, joint_effects)
end

Expand Down
4 changes: 2 additions & 2 deletions Compiler/src/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ struct IRCode
function IRCode(stmts::InstructionStream, cfg::CFG, debuginfo::DebugInfoStream,
argtypes::Vector{Any}, meta::Vector{Expr}, sptypes::Vector{VarState},
valid_worlds=WorldRange(typemin(UInt), typemax(UInt)))
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta)
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta, valid_worlds)
end
function IRCode(ir::IRCode, stmts::InstructionStream, cfg::CFG, new_nodes::NewNodeStream)
di = ir.debuginfo
Expand Down Expand Up @@ -1462,7 +1462,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
result[result_idx][:stmt] = GotoNode(label)
result_idx += 1
elseif isa(stmt, GlobalRef)
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
flag = result[result_idx][:flag]
if has_flag(flag, total_flags)
ssa_rename[idx] = stmt
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/ssair/legacy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{A
di = DebugInfoStream(nothing, ci.debuginfo, nstmts)
stmts = InstructionStream(code, ssavaluetypes, info, di.codelocs, ci.ssaflags)
meta = Expr[]
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, WorldRange(ci.min_world, ci.max_world))
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, world_range(ci))
end

"""
Expand Down
12 changes: 9 additions & 3 deletions Compiler/src/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ end

if !isdefined(@__MODULE__, Symbol("@verify_error"))
macro verify_error(arg)
arg isa String && return esc(:(print && println(stderr, $arg)))
arg isa String && return esc(:(print && println($(GlobalRef(Core, :stderr)), $arg)))
isexpr(arg, :string) || error("verify_error macro expected a string expression")
pushfirst!(arg.args, GlobalRef(Core, :stderr))
pushfirst!(arg.args, :println)
Expand Down Expand Up @@ -61,8 +61,14 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
raise_error()
end
elseif isa(op, GlobalRef)
if !isdefined(op.mod, op.name) || !isconst(op.mod, op.name)
@verify_error "Unbound GlobalRef not allowed in value position"
force_binding_resolution!(op, min_world(ir.valid_worlds))
bpart = lookup_binding_partition(min_world(ir.valid_worlds), op)
while is_some_imported(binding_kind(bpart)) && max_world(ir.valid_worlds) <= bpart.max_world
imported_binding = partition_restriction(bpart)::Core.Binding
bpart = lookup_binding_partition(min_world(ir.valid_worlds), imported_binding)
end
if !is_defined_const_binding(binding_kind(bpart)) || (bpart.max_world < max_world(ir.valid_worlds))
@verify_error "Unbound or partitioned GlobalRef not allowed in value position"
raise_error()
end
elseif isa(op, Expr)
Expand Down
38 changes: 21 additions & 17 deletions Compiler/src/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ function _getfield_tfunc_const(@nospecialize(sv), name::Const)
if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv)
return Const(getfield(sv, nv))
end
if isconst(typeof(sv), nv)
if !isa(sv, Module) && isconst(typeof(sv), nv)
if isdefined(sv, nv)
return Const(getfield(sv, nv))
end
Expand Down Expand Up @@ -3016,24 +3016,28 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any},
isvarargtype(argtypes[2]) && return Future(CallMeta(Bool, ArgumentError, EFFECTS_THROWS, NoCallInfo()))
argtypes = argtypes[2:end]
atype = argtypes_to_type(argtypes)
matches = find_method_matches(interp, argtypes, atype; max_methods)
info = NoCallInfo()
if isa(matches, FailedMethodMatch)
rt = Bool # too many matches to analyze
if atype === Union{}
rt = Union{} # accidentally unreachable code
else
(; valid_worlds, applicable) = matches
update_valid_age!(sv, valid_worlds)
napplicable = length(applicable)
if napplicable == 0
rt = Const(false) # never any matches
elseif !fully_covering(matches) || any_ambig(matches)
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
rt = Bool
matches = find_method_matches(interp, argtypes, atype; max_methods)
info = NoCallInfo()
if isa(matches, FailedMethodMatch)
rt = Bool # too many matches to analyze
else
rt = Const(true) # has applicable matches
end
if rt !== Bool
info = VirtualMethodMatchInfo(matches.info)
(; valid_worlds, applicable) = matches
update_valid_age!(sv, valid_worlds)
napplicable = length(applicable)
if napplicable == 0
rt = Const(false) # never any matches
elseif !fully_covering(matches) || any_ambig(matches)
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
rt = Bool
else
rt = Const(true) # has applicable matches
end
if rt !== Bool
info = VirtualMethodMatchInfo(matches.info)
end
end
end
return Future(CallMeta(rt, Union{}, EFFECTS_TOTAL, info))
Expand Down
7 changes: 7 additions & 0 deletions Compiler/src/typelattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ end
end
a = Bool
elseif isa(b, ConditionalT)
if isa(a, Const) && isa(a.val, Bool)
if (a.val === true && b.thentype === Any && b.elsetype === Bottom) ||
(a.val === false && b.elsetype === Any && b.thentype === Bottom)
# this Conditional contains distinctly no lattice information, and is simply an alternative representation of the Const Bool used for internal tracking purposes
return true
end
end
return false
end
return (widenlattice(lattice), a, b)
Expand Down
7 changes: 6 additions & 1 deletion Compiler/src/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ has_extended_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isTy
# certain combinations of `a` and `b` where one/both isa/are `Union`/`UnionAll` type(s)s.
isnotbrokensubtype(@nospecialize(a), @nospecialize(b)) = (!iskindtype(b) || !isType(a) || hasuniquerep(a.parameters[1]) || b <: a)

argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)...}
function argtypes_to_type(argtypes::Array{Any,1})
argtypes = anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)
filter!(@nospecialize(x) -> !isvarargtype(x) || valid_as_lattice(unwrapva(x), true), argtypes)
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), argtypes) || return Bottom
return Tuple{argtypes...}
end

function isknownlength(t::DataType)
isvatuple(t) || return true
Expand Down
2 changes: 1 addition & 1 deletion Compiler/test/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ end
# Make sure that code that has unbound sparams works
#https://github.com/JuliaLang/julia/issues/56739

f56739(a) where {T} = a
@test_warn r"declares type variable T but does not use it" @eval f56739(a) where {T} = a

@test f56739(1) == 1
g56739(x) = @noinline f56739(x)
Expand Down
26 changes: 26 additions & 0 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2734,6 +2734,26 @@ vacond(cnd, va...) = cnd ? va : 0
vacond(isa(x, Tuple{Int,Int}), x, x)
end |> only == Union{Int,Tuple{Any,Any}}

let A = Core.Const(true)
B = Core.InterConditional(2, Tuple, Union{})
C = Core.InterConditional(2, Any, Union{})
L = ipo_lattice(Compiler.NativeInterpreter())
@test !⊑(L, A, B)
@test ⊑(L, B, A)
@test tmerge(L, A, B) == C
@test ⊑(L, A, C)
end
function tail_is_ntuple((@nospecialize t::Tuple))
if unknown
t isa Tuple
else
tail_is_ntuple(t)
end
end
tail_is_ntuple_val((@nospecialize t::Tuple)) = Val(tail_is_ntuple(t))
@test Base.return_types(tail_is_ntuple, (Tuple,)) |> only === Bool
@test Base.return_types(tail_is_ntuple_val, (Tuple,)) |> only === Val{true}

# https://github.com/JuliaLang/julia/issues/47435
is_closed_ex(e::InvalidStateException) = true
is_closed_ex(e) = false
Expand Down Expand Up @@ -6162,3 +6182,9 @@ end <: Any
end
return out
end == Union{Float64,DomainError}

# issue #56628
@test Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}} ]) === Tuple{Int, UnitRange{Int}}
@test Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64 ]) === Tuple{Int, UnitRange{Int}, Float64}
@test Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64, Memory{2} ]) === Union{}
@test Base.return_types(Tuple{Tuple{Int, Vararg{Pair{Any, Union{}}}}},) do x; Returns(true)(x...); end |> only === Bool
4 changes: 2 additions & 2 deletions Compiler/test/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ end

(src, _) = only(code_typed(sum27403, Tuple{Vector{Int}}))
@test !any(src.code) do x
x isa Expr && x.head === :invoke && x.args[2] !== Core.GlobalRef(Base, :throw_boundserror)
x isa Expr && x.head === :invoke && !(x.args[2] in (Core.GlobalRef(Base, :throw_boundserror), Base.throw_boundserror))
end
end

Expand Down Expand Up @@ -313,7 +313,7 @@ end
const _a_global_array = [1]
f_inline_global_getindex() = _a_global_array[1]
let ci = code_typed(f_inline_global_getindex, Tuple{})[1].first
@test any(x->(isexpr(x, :call) && x.args[1] === GlobalRef(Base, :memoryrefget)), ci.code)
@test any(x->(isexpr(x, :call) && x.args[1] in (GlobalRef(Base, :memoryrefget), Base.memoryrefget)), ci.code)
end

# Issue #29114 & #36087 - Inlining of non-tuple splats
Expand Down
2 changes: 1 addition & 1 deletion Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1402,7 +1402,7 @@ CSL_NEXT_GLIBCXX_VERSION=GLIBCXX_3\.4\.34|GLIBCXX_3\.5\.|GLIBCXX_4\.
# Note: we explicitly _do not_ define `CSL` here, since it requires some more
# advanced techniques to decide whether it should be installed from a BB source
# or not. See `deps/csl.mk` for more detail.
BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP OPENSSL LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT BOLT
BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP OPENSSL LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD LIBTRACYCLIENT BOLT MMTK_JULIA
define SET_BB_DEFAULT
# First, check to see if BB is disabled on a global setting
ifeq ($$(USE_BINARYBUILDER),0)
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ endif
endif
endif

ifneq (${MMTK_PLAN},None)
JL_PRIVATE_LIBS-0 += libmmtk_julia
endif

# Note that we disable MSYS2's path munging here, as otherwise
# it replaces our `:`-separated list as a `;`-separated one.
define stringreplace
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ New library functions
* `uuid7()` creates an RFC 9652 compliant UUID with version 7 ([#54834]).
* `insertdims(array; dims)` allows to insert singleton dimensions into an array which is the inverse operation to `dropdims`. ([#45793])
* The new `Fix` type is a generalization of `Fix1/Fix2` for fixing a single argument ([#54653]).
* `Sys.detectwsl()` allows to testing if Julia is running inside WSL at runtime. ([#57069])

New library features
--------------------
Expand Down
1 change: 1 addition & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ end
# we know whether the .ji can just give the Base copy or not.
# TODO: We may want to do this earlier to avoid TOCTOU issues.
const _compiler_require_dependencies = Any[]
@Core.latestworld
for i = 1:length(_included_files)
isassigned(_included_files, i) || continue
(mod, file) = _included_files[i]
Expand Down
12 changes: 6 additions & 6 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ function exec_options(opts)
elseif cmd == 'm'
entrypoint = push!(split(arg, "."), "main")
Base.eval(Main, Expr(:import, Expr(:., Symbol.(entrypoint)...)))
if !should_use_main_entrypoint()
if !invokelatest(should_use_main_entrypoint)
error("`main` in `$arg` not declared as entry point (use `@main` to do so)")
end
return false
Expand Down Expand Up @@ -408,8 +408,7 @@ function load_InteractiveUtils(mod::Module=Main)
return nothing
end
end
Core.eval(mod, :(using Base.MainInclude.InteractiveUtils))
return MainInclude.InteractiveUtils
return Core.eval(mod, :(using Base.MainInclude.InteractiveUtils; Base.MainInclude.InteractiveUtils))
end

function load_REPL()
Expand Down Expand Up @@ -556,11 +555,12 @@ function _start()
local ret = 0
try
repl_was_requested = exec_options(JLOptions())
if should_use_main_entrypoint() && !is_interactive
if invokelatest(should_use_main_entrypoint) && !is_interactive
main = invokelatest(getglobal, Main, :main)
if Base.generating_output()
precompile(Main.main, (typeof(ARGS),))
precompile(main, (typeof(ARGS),))
else
ret = invokelatest(Main.main, ARGS)
ret = invokelatest(main, ARGS)
end
elseif (repl_was_requested || is_interactive)
# Run the Base `main`, which will either load the REPL stdlib
Expand Down
Loading

0 comments on commit 3fc3cce

Please sign in to comment.