Skip to content

Commit 09379f1

Browse files
authored
Merge branch 'master' into strcat
2 parents 748c0e5 + 9815a8e commit 09379f1

37 files changed

+814
-446
lines changed

base/channels.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,14 +493,18 @@ function show(io::IO, ::MIME"text/plain", c::Channel)
493493
end
494494

495495
function iterate(c::Channel, state=nothing)
496-
try
497-
return (take!(c), nothing)
498-
catch e
499-
if isa(e, InvalidStateException) && e.state === :closed
500-
return nothing
501-
else
502-
rethrow()
496+
if isopen(c) || isready(c)
497+
try
498+
return (take!(c), nothing)
499+
catch e
500+
if isa(e, InvalidStateException) && e.state === :closed
501+
return nothing
502+
else
503+
rethrow()
504+
end
503505
end
506+
else
507+
return nothing
504508
end
505509
end
506510

base/compiler/abstractinterpretation.jl

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -496,13 +496,13 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp
496496
add_remark!(interp, sv, "Refusing to infer into `depwarn`")
497497
return MethodCallResult(Any, false, false, nothing, Effects())
498498
end
499-
topmost = nothing
499+
500500
# Limit argument type tuple growth of functions:
501501
# look through the parents list to see if there's a call to the same method
502502
# and from the same method.
503503
# Returns the topmost occurrence of that repeated edge.
504-
edgecycle = false
505-
edgelimited = false
504+
edgecycle = edgelimited = false
505+
topmost = nothing
506506

507507
for infstate in InfStackUnwind(sv)
508508
if method === infstate.linfo.def
@@ -617,9 +617,13 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp
617617
# this edge is known to terminate
618618
effects = Effects(effects; terminates=ALWAYS_TRUE)
619619
elseif edgecycle
620-
# Some sort of recursion was detected. Even if we did not limit types,
621-
# we cannot guarantee that the call will terminate
622-
effects = Effects(effects; terminates=ALWAYS_FALSE)
620+
# Some sort of recursion was detected.
621+
if edge !== nothing && !edgelimited && !is_edge_recursed(edge, sv)
622+
# no `MethodInstance` cycles -- don't taint :terminate
623+
else
624+
# we cannot guarantee that the call will terminate
625+
effects = Effects(effects; terminates=ALWAYS_FALSE)
626+
end
623627
end
624628

625629
return MethodCallResult(rt, edgecycle, edgelimited, edge, effects)
@@ -691,6 +695,30 @@ function matches_sv(parent::InferenceState, sv::InferenceState)
691695
return parent.linfo.def === sv.linfo.def && sv_method2 === parent_method2
692696
end
693697

698+
function is_edge_recursed(edge::MethodInstance, sv::InferenceState)
699+
return any(InfStackUnwind(sv)) do infstate
700+
return edge === infstate.linfo
701+
end
702+
end
703+
704+
function is_method_recursed(method::Method, sv::InferenceState)
705+
return any(InfStackUnwind(sv)) do infstate
706+
return method === infstate.linfo.def
707+
end
708+
end
709+
710+
function is_constprop_edge_recursed(edge::MethodInstance, sv::InferenceState)
711+
return any(InfStackUnwind(sv)) do infstate
712+
return edge === infstate.linfo && any(infstate.result.overridden_by_const)
713+
end
714+
end
715+
716+
function is_constprop_method_recursed(method::Method, sv::InferenceState)
717+
return any(InfStackUnwind(sv)) do infstate
718+
return method === infstate.linfo.def && any(infstate.result.overridden_by_const)
719+
end
720+
end
721+
694722
# keeps result and context information of abstract_method_call, which will later be used for
695723
# backedge computation, and concrete evaluation or constant-propagation
696724
struct MethodCallResult
@@ -799,8 +827,7 @@ function const_prop_enabled(interp::AbstractInterpreter, sv::InferenceState, mat
799827
add_remark!(interp, sv, "[constprop] Disabled by parameter")
800828
return false
801829
end
802-
method = match.method
803-
if method.constprop == 0x02
830+
if is_no_constprop(match.method)
804831
add_remark!(interp, sv, "[constprop] Disabled by method parameter")
805832
return false
806833
end
@@ -836,17 +863,14 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul
836863
if inf_result === nothing
837864
# if there might be a cycle, check to make sure we don't end up
838865
# calling ourselves here.
839-
let result = result # prevent capturing
840-
if result.edgecycle && _any(InfStackUnwind(sv)) do infstate
841-
# if the type complexity limiting didn't decide to limit the call signature (`result.edgelimited = false`)
842-
# we can relax the cycle detection by comparing `MethodInstance`s and allow inference to
843-
# propagate different constant elements if the recursion is finite over the lattice
844-
return (result.edgelimited ? match.method === infstate.linfo.def : mi === infstate.linfo) &&
845-
any(infstate.result.overridden_by_const)
846-
end
847-
add_remark!(interp, sv, "[constprop] Edge cycle encountered")
848-
return nothing
849-
end
866+
if result.edgecycle && (result.edgelimited ?
867+
is_constprop_method_recursed(match.method, sv) :
868+
# if the type complexity limiting didn't decide to limit the call signature (`result.edgelimited = false`)
869+
# we can relax the cycle detection by comparing `MethodInstance`s and allow inference to
870+
# propagate different constant elements if the recursion is finite over the lattice
871+
is_constprop_edge_recursed(mi, sv))
872+
add_remark!(interp, sv, "[constprop] Edge cycle encountered")
873+
return nothing
850874
end
851875
inf_result = InferenceResult(mi, (arginfo, sv))
852876
if !any(inf_result.overridden_by_const)
@@ -963,8 +987,8 @@ function is_const_prop_profitable_arg(@nospecialize(arg))
963987
isa(arg, PartialOpaque) && return true
964988
isa(arg, Const) || return true
965989
val = arg.val
966-
# don't consider mutable values or Strings useful constants
967-
return isa(val, Symbol) || isa(val, Type) || (!isa(val, String) && !ismutable(val))
990+
# don't consider mutable values useful constants
991+
return isa(val, Symbol) || isa(val, Type) || !ismutable(val)
968992
end
969993

970994
function is_const_prop_profitable_conditional(cnd::Conditional, fargs::Vector{Any}, sv::InferenceState)
@@ -1003,7 +1027,7 @@ function is_all_overridden((; fargs, argtypes)::ArgInfo, sv::InferenceState)
10031027
end
10041028

10051029
function force_const_prop(interp::AbstractInterpreter, @nospecialize(f), method::Method)
1006-
return method.constprop == 0x01 ||
1030+
return is_aggressive_constprop(method) ||
10071031
InferenceParams(interp).aggressive_constant_propagation ||
10081032
istopfunction(f, :getproperty) ||
10091033
istopfunction(f, :setproperty!)
@@ -1345,7 +1369,7 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, sv::
13451369
end
13461370
cti = Any[Vararg{argt}]
13471371
end
1348-
if _any(t -> t === Bottom, cti)
1372+
if any(@nospecialize(t) -> t === Bottom, cti)
13491373
continue
13501374
end
13511375
for j = 1:length(ctypes)
@@ -2031,6 +2055,8 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
20312055
for i = 3:length(e.args)
20322056
if abstract_eval_value(interp, e.args[i], vtypes, sv) === Bottom
20332057
t = Bottom
2058+
tristate_merge!(sv, EFFECTS_THROWS)
2059+
@goto t_computed
20342060
end
20352061
end
20362062
cconv = e.args[5]

base/compiler/optimize.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ const IR_FLAG_EFFECT_FREE = 0x01 << 4
3030
# This statement was proven not to throw
3131
const IR_FLAG_NOTHROW = 0x01 << 5
3232

33-
3433
const TOP_TUPLE = GlobalRef(Core, :tuple)
3534

3635
#####################

0 commit comments

Comments
 (0)