Skip to content

Commit e1b0cce

Browse files
authored
Merge branch 'master' into jishnub/reshape_integer
2 parents b216610 + cebfd7b commit e1b0cce

File tree

126 files changed

+1904
-1145
lines changed

Some content is hidden

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

126 files changed

+1904
-1145
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,11 @@ endif
382382
cp -R -L $(JULIAHOME)/base/* $(DESTDIR)$(datarootdir)/julia/base
383383
cp -R -L $(JULIAHOME)/test/* $(DESTDIR)$(datarootdir)/julia/test
384384
cp -R -L $(build_datarootdir)/julia/* $(DESTDIR)$(datarootdir)/julia
385+
386+
# Set .jl sources as read-only to match package directories
387+
find $(DESTDIR)$(datarootdir)/julia/base -type f -name \*.jl -exec chmod 0444 '{}' \;
388+
find $(DESTDIR)$(datarootdir)/julia/test -type f -name \*.jl -exec chmod 0444 '{}' \;
389+
385390
# Copy documentation
386391
cp -R -L $(BUILDROOT)/doc/_build/html $(DESTDIR)$(docdir)/
387392
# Remove various files which should not be installed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ Standard library changes
135135

136136
#### Profile
137137

138+
* `Profile.take_heap_snapshot` takes a new keyword argument, `redact_data::Bool`,
139+
that is `true` by default. When set, the contents of Julia objects are not emitted
140+
in the heap snapshot. This currently only applies to strings. ([#55326])
141+
138142
#### Random
139143

140144
#### REPL

base/Base.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ function __init__()
647647
init_active_project()
648648
append!(empty!(_sysimage_modules), keys(loaded_modules))
649649
empty!(explicit_loaded_modules)
650-
@assert isempty(loaded_precompiles)
650+
empty!(loaded_precompiles) # If we load a packageimage when building the image this might not be empty
651651
for (mod, key) in module_keys
652652
loaded_precompiles[key => module_build_id(mod)] = mod
653653
end

base/compiler/abstractinterpretation.jl

Lines changed: 102 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -793,10 +793,10 @@ function edge_matches_sv(interp::AbstractInterpreter, frame::AbsIntState,
793793
# otherwise, we don't
794794

795795
# check in the cycle list first
796-
# all items in here are mutual parents of all others
796+
# all items in here are considered mutual parents of all others
797797
if !any(p::AbsIntState->matches_sv(p, sv), callers_in_cycle(frame))
798798
let parent = frame_parent(frame)
799-
parent !== nothing || return false
799+
parent === nothing && return false
800800
(is_cached(parent) || frame_parent(parent) !== nothing) || return false
801801
matches_sv(parent, sv) || return false
802802
end
@@ -1027,7 +1027,7 @@ collect_const_args(arginfo::ArgInfo, start::Int) = collect_const_args(arginfo.ar
10271027
function collect_const_args(argtypes::Vector{Any}, start::Int)
10281028
return Any[ let a = widenslotwrapper(argtypes[i])
10291029
isa(a, Const) ? a.val :
1030-
isconstType(a) ? (a::DataType).parameters[1] :
1030+
isconstType(a) ? a.parameters[1] :
10311031
(a::DataType).instance
10321032
end for i = start:length(argtypes) ]
10331033
end
@@ -1298,7 +1298,7 @@ function semi_concrete_eval_call(interp::AbstractInterpreter,
12981298
if code !== nothing
12991299
irsv = IRInterpretationState(interp, code, mi, arginfo.argtypes, world)
13001300
if irsv !== nothing
1301-
irsv.parent = sv
1301+
assign_parentchild!(irsv, sv)
13021302
rt, (nothrow, noub) = ir_abstract_constant_propagation(interp, irsv)
13031303
@assert !(rt isa Conditional || rt isa MustAlias) "invalid lattice element returned from irinterp"
13041304
if !(isa(rt, Type) && hasintersect(rt, Bool))
@@ -1376,11 +1376,17 @@ function const_prop_call(interp::AbstractInterpreter,
13761376
add_remark!(interp, sv, "[constprop] Could not retrieve the source")
13771377
return nothing # this is probably a bad generated function (unsound), but just ignore it
13781378
end
1379-
frame.parent = sv
1379+
assign_parentchild!(frame, sv)
13801380
if !typeinf(interp, frame)
13811381
add_remark!(interp, sv, "[constprop] Fresh constant inference hit a cycle")
1382+
@assert frame.frameid != 0 && frame.cycleid == frame.frameid
1383+
callstack = frame.callstack::Vector{AbsIntState}
1384+
@assert callstack[end] === frame && length(callstack) == frame.frameid
1385+
pop!(callstack)
13821386
return nothing
13831387
end
1388+
@assert frame.frameid != 0 && frame.cycleid == frame.frameid
1389+
@assert frame.parentid == sv.frameid
13841390
@assert inf_result.result !== nothing
13851391
# ConditionalSimpleArgtypes is allowed, because the only case in which it modifies
13861392
# the argtypes is when one of the argtypes is a `Conditional`, which case
@@ -2006,33 +2012,74 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
20062012
return Conditional(aty.slot, thentype, elsetype)
20072013
end
20082014
elseif f === isdefined
2009-
uty = argtypes[2]
20102015
a = ssa_def_slot(fargs[2], sv)
2011-
if isa(uty, Union) && isa(a, SlotNumber)
2012-
fld = argtypes[3]
2013-
thentype = Bottom
2014-
elsetype = Bottom
2015-
for ty in uniontypes(uty)
2016-
cnd = isdefined_tfunc(𝕃ᵢ, ty, fld)
2017-
if isa(cnd, Const)
2018-
if cnd.val::Bool
2019-
thentype = thentype ty
2016+
if isa(a, SlotNumber)
2017+
argtype2 = argtypes[2]
2018+
if isa(argtype2, Union)
2019+
fld = argtypes[3]
2020+
thentype = Bottom
2021+
elsetype = Bottom
2022+
for ty in uniontypes(argtype2)
2023+
cnd = isdefined_tfunc(𝕃ᵢ, ty, fld)
2024+
if isa(cnd, Const)
2025+
if cnd.val::Bool
2026+
thentype = thentype ty
2027+
else
2028+
elsetype = elsetype ty
2029+
end
20202030
else
2031+
thentype = thentype ty
20212032
elsetype = elsetype ty
20222033
end
2023-
else
2024-
thentype = thentype ty
2025-
elsetype = elsetype ty
2034+
end
2035+
return Conditional(a, thentype, elsetype)
2036+
else
2037+
thentype = form_partially_defined_struct(argtype2, argtypes[3])
2038+
if thentype !== nothing
2039+
elsetype = argtype2
2040+
if rt === Const(false)
2041+
thentype = Bottom
2042+
elseif rt === Const(true)
2043+
elsetype = Bottom
2044+
end
2045+
return Conditional(a, thentype, elsetype)
20262046
end
20272047
end
2028-
return Conditional(a, thentype, elsetype)
20292048
end
20302049
end
20312050
end
20322051
@assert !isa(rt, TypeVar) "unhandled TypeVar"
20332052
return rt
20342053
end
20352054

2055+
function form_partially_defined_struct(@nospecialize(obj), @nospecialize(name))
2056+
obj isa Const && return nothing # nothing to refine
2057+
name isa Const || return nothing
2058+
objt0 = widenconst(obj)
2059+
objt = unwrap_unionall(objt0)
2060+
objt isa DataType || return nothing
2061+
isabstracttype(objt) && return nothing
2062+
fldidx = try_compute_fieldidx(objt, name.val)
2063+
fldidx === nothing && return nothing
2064+
nminfld = datatype_min_ninitialized(objt)
2065+
if ismutabletype(objt)
2066+
# A mutable struct can have non-contiguous undefined fields, but `PartialStruct` cannot
2067+
# model such a state. So here `PartialStruct` can be used to represent only the
2068+
# objects where the field following the minimum initialized fields is also defined.
2069+
if fldidx nminfld+1
2070+
# if it is already represented as a `PartialStruct`, we can add one more
2071+
# `isdefined`-field information on top of those implied by its `fields`
2072+
if !(obj isa PartialStruct && fldidx == length(obj.fields)+1)
2073+
return nothing
2074+
end
2075+
end
2076+
else
2077+
fldidx > nminfld || return nothing
2078+
end
2079+
return PartialStruct(objt0, Any[obj isa PartialStruct && ilength(obj.fields) ?
2080+
obj.fields[i] : fieldtype(objt0,i) for i = 1:fldidx])
2081+
end
2082+
20362083
function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{Any}, call::CallMeta)
20372084
na = length(argtypes)
20382085
if isvarargtype(argtypes[end])
@@ -2573,20 +2620,18 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, vtypes::Union{V
25732620
end
25742621
ats[i] = at
25752622
end
2576-
# For now, don't allow:
2577-
# - Const/PartialStruct of mutables (but still allow PartialStruct of mutables
2578-
# with `const` fields if anything refined)
2579-
# - partially initialized Const/PartialStruct
2580-
if fcount == nargs
2581-
if consistent === ALWAYS_TRUE && allconst
2582-
argvals = Vector{Any}(undef, nargs)
2583-
for j in 1:nargs
2584-
argvals[j] = (ats[j]::Const).val
2585-
end
2586-
rt = Const(ccall(:jl_new_structv, Any, (Any, Ptr{Cvoid}, UInt32), rt, argvals, nargs))
2587-
elseif anyrefine
2588-
rt = PartialStruct(rt, ats)
2623+
if fcount == nargs && consistent === ALWAYS_TRUE && allconst
2624+
argvals = Vector{Any}(undef, nargs)
2625+
for j in 1:nargs
2626+
argvals[j] = (ats[j]::Const).val
25892627
end
2628+
rt = Const(ccall(:jl_new_structv, Any, (Any, Ptr{Cvoid}, UInt32), rt, argvals, nargs))
2629+
elseif anyrefine || nargs > datatype_min_ninitialized(rt)
2630+
# propagate partially initialized struct as `PartialStruct` when:
2631+
# - any refinement information is available (`anyrefine`), or when
2632+
# - `nargs` is greater than `n_initialized` derived from the struct type
2633+
# information alone
2634+
rt = PartialStruct(rt, ats)
25902635
end
25912636
else
25922637
rt = refine_partial_type(rt)
@@ -2688,6 +2733,8 @@ function abstract_eval_isdefined(interp::AbstractInterpreter, e::Expr, vtypes::U
26882733
rt = Const(false) # never assigned previously
26892734
elseif !vtyp.undef
26902735
rt = Const(true) # definitely assigned previously
2736+
else # form `Conditional` to refine `vtyp.undef` in the then branch
2737+
rt = Conditional(sym, vtyp.typ, vtyp.typ; isdefined=true)
26912738
end
26922739
elseif isa(sym, GlobalRef)
26932740
if InferenceParams(interp).assume_bindings_static
@@ -2794,7 +2841,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp
27942841
elseif ehead === :globaldecl
27952842
return RTEffects(Nothing, Any, EFFECTS_UNKNOWN)
27962843
elseif ehead === :thunk
2797-
return RTEffects(Any, Any, EFFECTS_UNKNOWN)
2844+
return RTEffects(Any, Any, Effects())
27982845
end
27992846
# N.B.: abstract_eval_value_expr can modify the global effects, but
28002847
# we move out any arguments with effects during SSA construction later
@@ -3094,7 +3141,8 @@ end
30943141
@nospecializeinfer function widenreturn_partials(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
30953142
if isa(rt, PartialStruct)
30963143
fields = copy(rt.fields)
3097-
local anyrefine = false
3144+
anyrefine = !isvarargtype(rt.fields[end]) &&
3145+
length(rt.fields) > datatype_min_ninitialized(unwrap_unionall(rt.typ))
30983146
𝕃 = typeinf_lattice(info.interp)
30993147
= strictpartialorder(𝕃)
31003148
for i in 1:length(fields)
@@ -3159,7 +3207,7 @@ end
31593207
@inline function abstract_eval_basic_statement(interp::AbstractInterpreter,
31603208
@nospecialize(stmt), pc_vartable::VarTable, frame::InferenceState)
31613209
if isa(stmt, NewvarNode)
3162-
changes = StateUpdate(stmt.slot, VarState(Bottom, true), false)
3210+
changes = StateUpdate(stmt.slot, VarState(Bottom, true))
31633211
return BasicStmtChange(changes, nothing, Union{})
31643212
elseif !isa(stmt, Expr)
31653213
(; rt, exct) = abstract_eval_statement(interp, stmt, pc_vartable, frame)
@@ -3174,7 +3222,7 @@ end
31743222
end
31753223
lhs = stmt.args[1]
31763224
if isa(lhs, SlotNumber)
3177-
changes = StateUpdate(lhs, VarState(rt, false), false)
3225+
changes = StateUpdate(lhs, VarState(rt, false))
31783226
elseif isa(lhs, GlobalRef)
31793227
handle_global_assignment!(interp, frame, lhs, rt)
31803228
elseif !isa(lhs, SSAValue)
@@ -3184,7 +3232,7 @@ end
31843232
elseif hd === :method
31853233
fname = stmt.args[1]
31863234
if isa(fname, SlotNumber)
3187-
changes = StateUpdate(fname, VarState(Any, false), false)
3235+
changes = StateUpdate(fname, VarState(Any, false))
31883236
end
31893237
return BasicStmtChange(changes, nothing, Union{})
31903238
elseif (hd === :code_coverage_effect || (
@@ -3298,7 +3346,6 @@ end
32983346
# make as much progress on `frame` as possible (without handling cycles)
32993347
function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
33003348
@assert !is_inferred(frame)
3301-
frame.dont_work_on_me = true # mark that this function is currently on the stack
33023349
W = frame.ip
33033350
ssavaluetypes = frame.ssavaluetypes
33043351
bbs = frame.cfg.blocks
@@ -3519,7 +3566,6 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
35193566
end
35203567
end # while currbb <= nbbs
35213568

3522-
frame.dont_work_on_me = false
35233569
nothing
35243570
end
35253571

@@ -3532,7 +3578,7 @@ function apply_refinement!(𝕃ᵢ::AbstractLattice, slot::SlotNumber, @nospecia
35323578
oldtyp = vtype.typ
35333579
= strictpartialorder(𝕃ᵢ)
35343580
if newtyp oldtyp
3535-
stmtupdate = StateUpdate(slot, VarState(newtyp, vtype.undef), false)
3581+
stmtupdate = StateUpdate(slot, VarState(newtyp, vtype.undef))
35363582
stoverwrite1!(currstate, stmtupdate)
35373583
end
35383584
end
@@ -3556,7 +3602,9 @@ function conditional_change(𝕃ᵢ::AbstractLattice, currstate::VarTable, condt
35563602
# "causes" since we ignored those in the comparison
35573603
newtyp = tmerge(𝕃ᵢ, newtyp, LimitedAccuracy(Bottom, oldtyp.causes))
35583604
end
3559-
return StateUpdate(SlotNumber(condt.slot), VarState(newtyp, vtype.undef), true)
3605+
# if this `Conditional` is from from `@isdefined condt.slot`, refine its `undef` information
3606+
newundef = condt.isdefined ? !then_or_else : vtype.undef
3607+
return StateUpdate(SlotNumber(condt.slot), VarState(newtyp, newundef), #=conditional=#true)
35603608
end
35613609

35623610
function condition_object_change(currstate::VarTable, condt::Conditional,
@@ -3565,22 +3613,29 @@ function condition_object_change(currstate::VarTable, condt::Conditional,
35653613
newcondt = Conditional(condt.slot,
35663614
then_or_else ? condt.thentype : Union{},
35673615
then_or_else ? Union{} : condt.elsetype)
3568-
return StateUpdate(condslot, VarState(newcondt, vtype.undef), false)
3616+
return StateUpdate(condslot, VarState(newcondt, vtype.undef))
35693617
end
35703618

35713619
# make as much progress on `frame` as possible (by handling cycles)
35723620
function typeinf_nocycle(interp::AbstractInterpreter, frame::InferenceState)
35733621
typeinf_local(interp, frame)
3622+
@assert isempty(frame.ip)
3623+
callstack = frame.callstack::Vector{AbsIntState}
3624+
frame.cycleid == length(callstack) && return true
35743625

3575-
# If the current frame is part of a cycle, solve the cycle before finishing
35763626
no_active_ips_in_callers = false
3577-
while !no_active_ips_in_callers
3627+
while true
3628+
# If the current frame is not the top part of a cycle, continue to the top of the cycle before resuming work
3629+
frame.cycleid == frame.frameid || return false
3630+
# If done, return and finalize this cycle
3631+
no_active_ips_in_callers && return true
3632+
# Otherwise, do at least one iteration over the entire current cycle
35783633
no_active_ips_in_callers = true
3579-
for caller in frame.callers_in_cycle
3580-
caller.dont_work_on_me && return false # cycle is above us on the stack
3634+
for i = reverse(frame.cycleid:length(callstack))
3635+
caller = callstack[i]::InferenceState
35813636
if !isempty(caller.ip)
35823637
# Note that `typeinf_local(interp, caller)` can potentially modify the other frames
3583-
# `frame.callers_in_cycle`, which is why making incremental progress requires the
3638+
# `frame.cycleid`, which is why making incremental progress requires the
35843639
# outer while loop.
35853640
typeinf_local(interp, caller)
35863641
no_active_ips_in_callers = false

base/compiler/effects.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ const NOUB_IF_NOINBOUNDS = 0x01 << 1
169169
# :nonoverlayed bits
170170
const CONSISTENT_OVERLAY = 0x01 << 1
171171

172-
const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, true, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true)
173-
const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, false, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true)
174-
const EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_TRUE, false) # unknown mostly, but it's not overlayed at least (e.g. it's not a call)
175-
const _EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_FALSE, false) # unknown really
172+
const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, true, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true)
173+
const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, false, true, true, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true)
174+
const EFFECTS_UNKNOWN = Effects(ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_TRUE, false) # unknown mostly, but it's not overlayed at least (e.g. it's not a call)
176175

177-
function Effects(effects::Effects = _EFFECTS_UNKNOWN;
176+
function Effects(effects::Effects=Effects(
177+
ALWAYS_FALSE, ALWAYS_FALSE, false, false, false, ALWAYS_FALSE, ALWAYS_FALSE, ALWAYS_FALSE, false);
178178
consistent::UInt8 = effects.consistent,
179179
effect_free::UInt8 = effects.effect_free,
180180
nothrow::Bool = effects.nothrow,

0 commit comments

Comments
 (0)