Skip to content

Commit 67ad4b6

Browse files
authored
Merge branch 'master' into jn/atomic-modify-opt
2 parents c98b43f + eff8ba4 commit 67ad4b6

File tree

131 files changed

+1635
-755
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+1635
-755
lines changed

Compiler/src/Compiler.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ using Core: ABIOverride, Builtin, CodeInstance, IntrinsicFunction, MethodInstanc
4949

5050
using Base
5151
using Base: @_foldable_meta, @_gc_preserve_begin, @_gc_preserve_end, @nospecializeinfer,
52-
BINDING_KIND_GLOBAL, BINDING_KIND_UNDEF_CONST, Base, BitVector, Bottom, Callable, DataTypeFieldDesc,
52+
BINDING_KIND_GLOBAL, BINDING_KIND_UNDEF_CONST, BINDING_KIND_BACKDATED_CONST,
53+
Base, BitVector, Bottom, Callable, DataTypeFieldDesc,
5354
EffectsOverride, Filter, Generator, IteratorSize, JLOptions, NUM_EFFECTS_OVERRIDES,
5455
OneTo, Ordering, RefValue, SizeUnknown, _NAMEDTUPLE_NAME,
5556
_array_for, _bits_findnext, _methods_by_ftype, _uniontypes, all, allocatedinline, any,

Compiler/src/abstractinterpretation.jl

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
368368
for i in 1:length(split_argtypes)
369369
arg_n = split_argtypes[i]::Vector{Any}
370370
sig_n = argtypes_to_type(arg_n)
371+
sig_n === Bottom && continue
371372
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
372373
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
373374
mt = mt::MethodTable
@@ -614,7 +615,7 @@ function abstract_call_method(interp::AbstractInterpreter,
614615
sigtuple = unwrap_unionall(sig)
615616
sigtuple isa DataType ||
616617
return Future(MethodCallResult(Any, Any, Effects(), nothing, false, false))
617-
all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) ||
618+
all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) ||
618619
return Future(MethodCallResult(Union{}, Any, EFFECTS_THROWS, nothing, false, false)) # catch bad type intersections early
619620

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

@@ -3454,10 +3456,10 @@ world_range(ir::IRCode) = ir.valid_worlds
34543456
world_range(ci::CodeInfo) = WorldRange(ci.min_world, ci.max_world)
34553457
world_range(compact::IncrementalCompact) = world_range(compact.ir)
34563458

3457-
function force_binding_resolution!(g::GlobalRef)
3459+
function force_binding_resolution!(g::GlobalRef, world::UInt)
34583460
# Force resolution of the binding
34593461
# TODO: This will go away once we switch over to fully partitioned semantics
3460-
ccall(:jl_globalref_boundp, Cint, (Any,), g)
3462+
ccall(:jl_force_binding_resolution, Cvoid, (Any, Csize_t), g, world)
34613463
return nothing
34623464
end
34633465

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

34903492
function lookup_binding_partition!(interp::AbstractInterpreter, g::GlobalRef, sv::AbsIntState)
3491-
force_binding_resolution!(g)
3493+
force_binding_resolution!(g, get_inference_world(interp))
34923494
partition = lookup_binding_partition(get_inference_world(interp), g)
34933495
update_valid_age!(sv, WorldRange(partition.min_world, partition.max_world))
34943496
partition
@@ -3522,6 +3524,11 @@ function abstract_eval_partition_load(interp::AbstractInterpreter, partition::Co
35223524
end
35233525

35243526
if is_defined_const_binding(kind)
3527+
if kind == BINDING_KIND_BACKDATED_CONST
3528+
# Infer this as guard. We do not want a later const definition to retroactively improve
3529+
# inference results in an earlier world.
3530+
return RTEffects(Any, UndefVarError, generic_getglobal_effects)
3531+
end
35253532
rt = Const(partition_restriction(partition))
35263533
return RTEffects(rt, Union{}, Effects(EFFECTS_TOTAL, inaccessiblememonly=is_mutation_free_argtype(rt) ? ALWAYS_TRUE : ALWAYS_FALSE))
35273534
end
@@ -3537,7 +3544,8 @@ function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, saw_
35373544
partition = abstract_eval_binding_partition!(interp, g, sv)
35383545
ret = abstract_eval_partition_load(interp, partition)
35393546
if ret.rt !== Union{} && ret.exct === UndefVarError && InferenceParams(interp).assume_bindings_static
3540-
if isdefined(g, :binding) && isdefined(g.binding, :value)
3547+
b = convert(Core.Binding, g)
3548+
if isdefined(b, :value)
35413549
ret = RTEffects(ret.rt, Union{}, Effects(generic_getglobal_effects, nothrow=true))
35423550
end
35433551
# We do not assume in general that assigned global bindings remain assigned.
@@ -3785,14 +3793,23 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
37853793
slottypes = frame.slottypes
37863794
rt = widenreturn(rt, BestguessInfo(interp, bestguess, nargs, slottypes, currstate))
37873795
# narrow representation of bestguess slightly to prepare for tmerge with rt
3788-
if rt isa InterConditional && bestguess isa Const
3796+
if rt isa InterConditional && bestguess isa Const && bestguess.val isa Bool
37893797
slot_id = rt.slot
37903798
old_id_type = widenconditional(slottypes[slot_id])
37913799
if bestguess.val === true && rt.elsetype !== Bottom
37923800
bestguess = InterConditional(slot_id, old_id_type, Bottom)
37933801
elseif bestguess.val === false && rt.thentype !== Bottom
37943802
bestguess = InterConditional(slot_id, Bottom, old_id_type)
37953803
end
3804+
# or narrow representation of rt slightly to prepare for tmerge with bestguess
3805+
elseif bestguess isa InterConditional && rt isa Const && rt.val isa Bool
3806+
slot_id = bestguess.slot
3807+
old_id_type = widenconditional(slottypes[slot_id])
3808+
if rt.val === true && bestguess.elsetype !== Bottom
3809+
rt = InterConditional(slot_id, old_id_type, Bottom)
3810+
elseif rt.val === false && bestguess.thentype !== Bottom
3811+
rt = InterConditional(slot_id, Bottom, old_id_type)
3812+
end
37963813
end
37973814
# copy limitations to return value
37983815
if !isempty(frame.pclimitations)

Compiler/src/optimize.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
12861286
# types of call arguments only once `slot2reg` converts this `IRCode` to the SSA form
12871287
# and eliminates slots (see below)
12881288
argtypes = sv.slottypes
1289-
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, WorldRange(ci.min_world, ci.max_world))
1289+
return IRCode(stmts, sv.cfg, di, argtypes, meta, sv.sptypes, world_range(ci))
12901290
end
12911291

12921292
function process_meta!(meta::Vector{Expr}, @nospecialize stmt)

Compiler/src/ssair/inlining.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ function handle_call!(todo::Vector{Pair{Int,Any}},
13991399
cases === nothing && return nothing
14001400
cases, handled_all_cases, fully_covered, joint_effects = cases
14011401
atype = argtypes_to_type(sig.argtypes)
1402+
atype === Union{} && return nothing # accidentally actually unreachable
14021403
handle_cases!(todo, ir, idx, stmt, atype, cases, handled_all_cases, fully_covered, joint_effects)
14031404
end
14041405

Compiler/src/ssair/ir.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ struct IRCode
434434
function IRCode(stmts::InstructionStream, cfg::CFG, debuginfo::DebugInfoStream,
435435
argtypes::Vector{Any}, meta::Vector{Expr}, sptypes::Vector{VarState},
436436
valid_worlds=WorldRange(typemin(UInt), typemax(UInt)))
437-
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta)
437+
return new(stmts, argtypes, sptypes, debuginfo, cfg, NewNodeStream(), meta, valid_worlds)
438438
end
439439
function IRCode(ir::IRCode, stmts::InstructionStream, cfg::CFG, new_nodes::NewNodeStream)
440440
di = ir.debuginfo
@@ -1462,7 +1462,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
14621462
result[result_idx][:stmt] = GotoNode(label)
14631463
result_idx += 1
14641464
elseif isa(stmt, GlobalRef)
1465-
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE
1465+
total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
14661466
flag = result[result_idx][:flag]
14671467
if has_flag(flag, total_flags)
14681468
ssa_rename[idx] = stmt

Compiler/src/ssair/legacy.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{A
4444
di = DebugInfoStream(nothing, ci.debuginfo, nstmts)
4545
stmts = InstructionStream(code, ssavaluetypes, info, di.codelocs, ci.ssaflags)
4646
meta = Expr[]
47-
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, WorldRange(ci.min_world, ci.max_world))
47+
return IRCode(stmts, cfg, di, argtypes, meta, sptypes, world_range(ci))
4848
end
4949

5050
"""

Compiler/src/ssair/slot2ssa.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
137137
return nothing
138138
end
139139
op[] = x
140-
elseif isa(val, GlobalRef) && !(isdefined(val.mod, val.name) && isconst(val.mod, val.name))
141-
typ = typ_for_val(val, ci, ir, idx, Any[])
142-
new_inst = NewInstruction(val, typ)
143-
op[] = NewSSAValue(insert_node!(ir, idx, new_inst).id - length(ir.stmts))
144140
elseif isexpr(val, :static_parameter)
145141
ty = typ_for_val(val, ci, ir, idx, Any[])
146142
if isa(ty, Const)

Compiler/src/ssair/verify.jl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ end
1212

1313
if !isdefined(@__MODULE__, Symbol("@verify_error"))
1414
macro verify_error(arg)
15-
arg isa String && return esc(:(print && println(stderr, $arg)))
15+
arg isa String && return esc(:(print && println($(GlobalRef(Core, :stderr)), $arg)))
1616
isexpr(arg, :string) || error("verify_error macro expected a string expression")
1717
pushfirst!(arg.args, GlobalRef(Core, :stderr))
1818
pushfirst!(arg.args, :println)
@@ -61,8 +61,14 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
6161
raise_error()
6262
end
6363
elseif isa(op, GlobalRef)
64-
if !isdefined(op.mod, op.name) || !isconst(op.mod, op.name)
65-
@verify_error "Unbound GlobalRef not allowed in value position"
64+
force_binding_resolution!(op, min_world(ir.valid_worlds))
65+
bpart = lookup_binding_partition(min_world(ir.valid_worlds), op)
66+
while is_some_imported(binding_kind(bpart)) && max_world(ir.valid_worlds) <= bpart.max_world
67+
imported_binding = partition_restriction(bpart)::Core.Binding
68+
bpart = lookup_binding_partition(min_world(ir.valid_worlds), imported_binding)
69+
end
70+
if !is_defined_const_binding(binding_kind(bpart)) || (bpart.max_world < max_world(ir.valid_worlds))
71+
@verify_error "Unbound or partitioned GlobalRef not allowed in value position"
6672
raise_error()
6773
end
6874
elseif isa(op, Expr)
@@ -115,7 +121,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
115121
if mi !== nothing
116122
push!(error_args, "\n", " Method instance: ", mi)
117123
end
118-
error(error_args...)
124+
invokelatest(error, error_args...)
119125
end
120126
# Verify CFG graph. Must be well formed to construct domtree
121127
if !(length(ir.cfg.blocks) - 1 <= length(ir.cfg.index) <= length(ir.cfg.blocks))
@@ -374,6 +380,15 @@ function verify_ir(ir::IRCode, print::Bool=true,
374380
# undefined GlobalRef is OK in isdefined
375381
continue
376382
end
383+
elseif stmt.head === :throw_undef_if_not
384+
if length(stmt.args) > 3
385+
@verify_error "malformed throw_undef_if_not"
386+
raise_error()
387+
end
388+
if stmt.args[1] isa GlobalRef
389+
# undefined GlobalRef is OK in throw_undef_if_not
390+
continue
391+
end
377392
elseif stmt.head === :gc_preserve_end
378393
# We allow gc_preserve_end tokens to span across try/catch
379394
# blocks, which isn't allowed for regular SSA values, so

Compiler/src/tfuncs.jl

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ function _getfield_tfunc_const(@nospecialize(sv), name::Const)
11091109
if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv)
11101110
return Const(getfield(sv, nv))
11111111
end
1112-
if isconst(typeof(sv), nv)
1112+
if !isa(sv, Module) && isconst(typeof(sv), nv)
11131113
if isdefined(sv, nv)
11141114
return Const(getfield(sv, nv))
11151115
end
@@ -3016,24 +3016,28 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any},
30163016
isvarargtype(argtypes[2]) && return Future(CallMeta(Bool, ArgumentError, EFFECTS_THROWS, NoCallInfo()))
30173017
argtypes = argtypes[2:end]
30183018
atype = argtypes_to_type(argtypes)
3019-
matches = find_method_matches(interp, argtypes, atype; max_methods)
3020-
info = NoCallInfo()
3021-
if isa(matches, FailedMethodMatch)
3022-
rt = Bool # too many matches to analyze
3019+
if atype === Union{}
3020+
rt = Union{} # accidentally unreachable code
30233021
else
3024-
(; valid_worlds, applicable) = matches
3025-
update_valid_age!(sv, valid_worlds)
3026-
napplicable = length(applicable)
3027-
if napplicable == 0
3028-
rt = Const(false) # never any matches
3029-
elseif !fully_covering(matches) || any_ambig(matches)
3030-
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
3031-
rt = Bool
3022+
matches = find_method_matches(interp, argtypes, atype; max_methods)
3023+
info = NoCallInfo()
3024+
if isa(matches, FailedMethodMatch)
3025+
rt = Bool # too many matches to analyze
30323026
else
3033-
rt = Const(true) # has applicable matches
3034-
end
3035-
if rt !== Bool
3036-
info = VirtualMethodMatchInfo(matches.info)
3027+
(; valid_worlds, applicable) = matches
3028+
update_valid_age!(sv, valid_worlds)
3029+
napplicable = length(applicable)
3030+
if napplicable == 0
3031+
rt = Const(false) # never any matches
3032+
elseif !fully_covering(matches) || any_ambig(matches)
3033+
# Account for the fact that we may encounter a MethodError with a non-covered or ambiguous signature.
3034+
rt = Bool
3035+
else
3036+
rt = Const(true) # has applicable matches
3037+
end
3038+
if rt !== Bool
3039+
info = VirtualMethodMatchInfo(matches.info)
3040+
end
30373041
end
30383042
end
30393043
return Future(CallMeta(rt, Union{}, EFFECTS_TOTAL, info))

Compiler/src/typeinfer.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,8 +1280,20 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim::
12801280
ci isa CodeInstance && !use_const_api(ci) && push!(tocompile, ci)
12811281
end
12821282
elseif item isa SimpleVector
1283-
push!(codeinfos, item[1]::Type)
1284-
push!(codeinfos, item[2]::Type)
1283+
(rt::Type, sig::Type) = item
1284+
# make a best-effort attempt to enqueue the relevant code for the ccallable
1285+
ptr = ccall(:jl_get_specialization1,
1286+
#= MethodInstance =# Ptr{Cvoid}, (Any, Csize_t, Cint),
1287+
sig, this_world, #= mt_cache =# 0)
1288+
if ptr !== C_NULL
1289+
mi = unsafe_pointer_to_objref(ptr)
1290+
ci = typeinf_ext(interp, mi, SOURCE_MODE_NOT_REQUIRED)
1291+
ci isa CodeInstance && !use_const_api(ci) && push!(tocompile, ci)
1292+
end
1293+
# additionally enqueue the ccallable entrypoint / adapter, which implicitly
1294+
# invokes the above ci
1295+
push!(codeinfos, rt)
1296+
push!(codeinfos, sig)
12851297
end
12861298
end
12871299
while !isempty(tocompile)

0 commit comments

Comments
 (0)