Skip to content

Commit

Permalink
Merge pull request #37210 from JuliaLang/backports-release-1.5
Browse files Browse the repository at this point in the history
Backports for 1.5.2
  • Loading branch information
KristofferC authored Sep 15, 2020
2 parents c4acbf9 + b8b7267 commit 005352a
Show file tree
Hide file tree
Showing 39 changed files with 404 additions and 74 deletions.
18 changes: 11 additions & 7 deletions base/Enums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,17 @@ function Base.show(io::IO, ::MIME"text/plain", x::Enum)
show(io, Integer(x))
end

function Base.show(io::IO, ::MIME"text/plain", t::Type{<:Enum})
print(io, "Enum ")
Base.show_datatype(io, t)
print(io, ":")
for x in instances(t)
print(io, "\n", Symbol(x), " = ")
show(io, Integer(x))
function Base.show(io::IO, m::MIME"text/plain", t::Type{<:Enum})
if isconcretetype(t)
print(io, "Enum ")
Base.show_datatype(io, t)
print(io, ":")
for x in instances(t)
print(io, "\n", Symbol(x), " = ")
show(io, Integer(x))
end
else
invoke(show, Tuple{IO, MIME"text/plain", Type}, io, m, t)
end
end

Expand Down
4 changes: 2 additions & 2 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1010,8 +1010,8 @@ function pointer(x::AbstractArray{T}, i::Integer) where T
end

# The distance from pointer(x) to the element at x[I...] in bytes
_memory_offset(x::DenseArray, I...) = (_to_linear_index(x, I...) - first(LinearIndices(x)))*elsize(x)
function _memory_offset(x::AbstractArray, I...)
_memory_offset(x::DenseArray, I::Vararg{Any,N}) where {N} = (_to_linear_index(x, I...) - first(LinearIndices(x)))*elsize(x)
function _memory_offset(x::AbstractArray, I::Vararg{Any,N}) where {N}
J = _to_subscript_indices(x, I...)
return sum(map((i, s, o)->s*(i-o), J, strides(x), Tuple(first(CartesianIndices(x)))))*elsize(x)
end
Expand Down
5 changes: 4 additions & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,10 @@ update_valid_age!(edge::InferenceState, sv::InferenceState) = update_valid_age!(
function record_ssa_assign(ssa_id::Int, @nospecialize(new), frame::InferenceState)
old = frame.src.ssavaluetypes[ssa_id]
if old === NOT_FOUND || !(new old)
frame.src.ssavaluetypes[ssa_id] = tmerge(old, new)
# typically, we expect that old ⊑ new (that output information only
# gets less precise with worse input information), but to actually
# guarantee convergence we need to use tmerge here to ensure that is true
frame.src.ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge(old, new)
W = frame.ip
s = frame.stmt_types
for r in frame.ssavalue_uses[ssa_id]
Expand Down
6 changes: 3 additions & 3 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,9 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
end
if isa(name, Const)
nv = name.val
if !(isa(nv,Symbol) || isa(nv,Int))
return Bottom
end
if isa(sv, UnionAll)
if nv === :var || nv === 1
return Const(sv.var)
Expand All @@ -755,9 +758,6 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
if isa(sv, Module) && isa(nv, Symbol)
return abstract_eval_global(sv, nv)
end
if !(isa(nv,Symbol) || isa(nv,Int))
return Bottom
end
if (isa(sv, SimpleVector) || !ismutable(sv)) && isdefined(sv, nv)
return AbstractEvalConstant(getfield(sv, nv))
end
Expand Down
2 changes: 2 additions & 0 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ end
# but without losing too much precision in common cases
# and also trying to be mostly associative and commutative
function tmerge(@nospecialize(typea), @nospecialize(typeb))
typea === Union{} && return typeb
typeb === Union{} && return typea
suba = typea typeb
suba && issimpleenoughtype(typeb) && return typeb
subb = typeb typea
Expand Down
4 changes: 2 additions & 2 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ macro deprecate(old, new, ex=true)
end
end

function depwarn(msg, funcsym)
function depwarn(msg, funcsym; force::Bool=false)
opts = JLOptions()
if opts.depwarn == 2
throw(ErrorException(msg))
end
deplevel = opts.depwarn == 1 ? CoreLogging.Warn : CoreLogging.BelowMinLevel
deplevel = force || opts.depwarn == 1 ? CoreLogging.Warn : CoreLogging.BelowMinLevel
@logmsg(
deplevel,
msg,
Expand Down
4 changes: 2 additions & 2 deletions base/gcutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ directly to `ccall` which counts as an explicit use.)
julia> let
x = "Hello"
p = pointer(x)
GC.@preserve x @ccall strlen(p::Cstring)::Cint
Int(GC.@preserve x @ccall strlen(p::Cstring)::Csize_t)
# Preferred alternative
@ccall strlen(x::Cstring)::Cint
Int(@ccall strlen(x::Cstring)::Csize_t)
end
5
```
Expand Down
3 changes: 3 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ false
julia> ismutable([1,2])
true
```
!!! compat "Julia 1.5"
This function requires at least Julia 1.5.
"""
ismutable(@nospecialize(x)) = (@_pure_meta; typeof(x).mutable)

Expand Down
2 changes: 1 addition & 1 deletion base/secretbuffer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function SecretBuffer!(d::Vector{UInt8})
s
end

unsafe_SecretBuffer!(s::Cstring) = unsafe_SecretBuffer!(convert(Ptr{UInt8}, s), ccall(:strlen, Cint, (Cstring,), s))
unsafe_SecretBuffer!(s::Cstring) = unsafe_SecretBuffer!(convert(Ptr{UInt8}, s), Int(ccall(:strlen, Csize_t, (Cstring,), s)))
function unsafe_SecretBuffer!(p::Ptr{UInt8}, len=1)
s = SecretBuffer(sizehint=len)
for i in 1:len
Expand Down
5 changes: 4 additions & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,10 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
# scalar multiplication (i.e. "100x")
elseif (func === :* &&
length(func_args) == 2 && isa(func_args[1], Union{Int, Int64, Float32, Float64}) &&
isa(func_args[2], Symbol) && !in(string(func_args[2])[1], ('e', 'E', 'f')))
isa(func_args[2], Symbol) &&
!in(string(func_args[2]::Symbol)[1], ('e', 'E', 'f', (func_args[1] == 0 && func_args[1] isa Integer ?
# don't juxtapose 0 with b, o, x
('b', 'o', 'x') : ())...)))
if func_prec <= prec
show_enclosed_list(io, '(', func_args, "", ')', indent, func_prec, quote_level)
else
Expand Down
13 changes: 8 additions & 5 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,17 +366,20 @@ end
# The running sum is `f`; the cumulative stride product is `s`.
# If the parent is a vector, then we offset the parent's own indices with parameters of I
compute_offset1(parent::AbstractVector, stride1::Integer, I::Tuple{AbstractRange}) =
(@_inline_meta; first(I[1]) - first(axes1(I[1]))*stride1)
(@_inline_meta; first(I[1]) - stride1*first(axes1(I[1])))
# If the result is one-dimensional and it's a Colon, then linear
# indexing uses the indices along the given dimension. Otherwise
# linear indexing always starts with 1.
# indexing uses the indices along the given dimension.
# If the result is one-dimensional and it's a range, then linear
# indexing might be offset if the index itself is offset
# Otherwise linear indexing always starts with 1.
compute_offset1(parent, stride1::Integer, I::Tuple) =
(@_inline_meta; compute_offset1(parent, stride1, find_extended_dims(1, I...), find_extended_inds(I...), I))
compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Union{Slice, IdentityUnitRange}}, I::Tuple) =
compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Slice}, I::Tuple) =
(@_inline_meta; compute_linindex(parent, I) - stride1*first(axes(parent, dims[1]))) # index-preserving case
compute_offset1(parent, stride1::Integer, dims, inds::Tuple{AbstractRange}, I::Tuple) =
(@_inline_meta; compute_linindex(parent, I) - stride1*first(axes1(inds[1]))) # potentially index-offsetting case
compute_offset1(parent, stride1::Integer, dims, inds, I::Tuple) =
(@_inline_meta; compute_linindex(parent, I) - stride1) # linear indexing starts with 1

function compute_linindex(parent, I::NTuple{N,Any}) where N
@_inline_meta
IP = fill_to_length(axes(parent), OneTo(1), Val(N))
Expand Down
1 change: 1 addition & 0 deletions base/traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct Unordered <: OrderStyle end
OrderStyle(instance) = OrderStyle(typeof(instance))
OrderStyle(::Type{<:Real}) = Ordered()
OrderStyle(::Type{<:Any}) = Unordered()
OrderStyle(::Type{Union{}}) = Ordered()

# trait for objects that support arithmetic
abstract type ArithmeticStyle end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14d2db2253d6a561d7bf1cf66d0d3421
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
da49f34f57e61f86e2124440676d44678a43a98fc96970debcd9ded931be3329acbadea858cc4100204ff1ecd7027b033f759a0c2595dcad6d6f114aadb3507d

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions doc/make.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Install dependencies needed to build the documentation.
Base.HOME_PROJECT[] = nothing
empty!(LOAD_PATH)
push!(LOAD_PATH, @__DIR__, "@stdlib")
empty!(DEPOT_PATH)
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ ifneq ($(BUILD_LLVM_CLANG),1)
endif
endif

clangsa: $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT)

clang-sa-%: $(SRCDIR)/%.c $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check
@$(call PRINT_ANALYZE, $(build_depsbindir)/clang --analyze -Xanalyzer -analyzer-werror -Xanalyzer -analyzer-output=text -Xclang -load -Xclang $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) $(CLANGSA_FLAGS) $(JCPPFLAGS) $(JCFLAGS) $(DEBUGFLAGS) -Xclang -analyzer-checker=core$(COMMA)julia.GCChecker --analyzer-no-default-checks -fcolor-diagnostics -Werror -x c $<)
clang-sa-%: $(SRCDIR)/%.cpp $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) | analyzegc-deps-check
Expand Down
8 changes: 5 additions & 3 deletions src/aotcompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,11 @@ void *jl_create_native(jl_array_t *methods, const jl_cgparams_t cgparams, int _p
}
if (src == NULL || !jl_is_code_info(src)) {
src = jl_type_infer(mi, params.world, 0);
codeinst = jl_get_method_inferred(mi, src->rettype, src->min_world, src->max_world);
if (src->inferred && !codeinst->inferred)
codeinst->inferred = jl_nothing;
if (src) {
codeinst = jl_get_method_inferred(mi, src->rettype, src->min_world, src->max_world);
if (src->inferred && !codeinst->inferred)
codeinst->inferred = jl_nothing;
}
}
if (src && !emitted.count(codeinst)) {
// now add it to our compilation results
Expand Down
12 changes: 8 additions & 4 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1682,16 +1682,18 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx,
else if (is_tupletype_homogeneous(stt->types)) {
assert(nfields > 0); // nf == 0 trapped by all_pointers case
jl_value_t *jft = jl_svecref(stt->types, 0);
assert(jl_is_concrete_type(jft));
idx = idx0();
Value *ptr = maybe_decay_tracked(data_pointer(ctx, strct));
if (!stt->mutabl && !(maybe_null && jft == (jl_value_t*)jl_bool_type)) {
if (!stt->mutabl && !(maybe_null && (jft == (jl_value_t*)jl_bool_type ||
((jl_datatype_t*)jft)->layout->npointers))) {
// just compute the pointer and let user load it when necessary
Type *fty = julia_type_to_llvm(ctx, jft);
Value *addr = ctx.builder.CreateInBoundsGEP(fty, emit_bitcast(ctx, ptr, PointerType::get(fty, 0)), idx);
*ret = mark_julia_slot(addr, jft, NULL, strct.tbaa);
return true;
}
*ret = typed_load(ctx, ptr, idx, jft, strct.tbaa, nullptr, false);
*ret = typed_load(ctx, ptr, idx, jft, strct.tbaa, nullptr, maybe_null);
return true;
}
else if (strct.isboxed) {
Expand Down Expand Up @@ -1779,12 +1781,14 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
}
return mark_julia_slot(addr, jfty, tindex, strct.tbaa);
}
else if (!jt->mutabl && !(maybe_null && jfty == (jl_value_t*)jl_bool_type)) {
assert(jl_is_concrete_type(jfty));
if (!jt->mutabl && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type ||
((jl_datatype_t*)jfty)->layout->npointers))) {
// just compute the pointer and let user load it when necessary
return mark_julia_slot(addr, jfty, NULL, strct.tbaa);
}
unsigned align = jl_field_align(jt, idx);
return typed_load(ctx, addr, NULL, jfty, strct.tbaa, nullptr, true, align);
return typed_load(ctx, addr, NULL, jfty, strct.tbaa, nullptr, maybe_null, align);
}
else if (isa<UndefValue>(strct.V)) {
return jl_cgval_t();
Expand Down
85 changes: 58 additions & 27 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3355,7 +3355,7 @@ static void emit_ssaval_assign(jl_codectx_t &ctx, ssize_t idx, jl_value_t *r)

static void emit_varinfo_assign(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_cgval_t rval_info, jl_value_t *l=NULL)
{
if (!vi.used)
if (!vi.used || vi.value.typ == jl_bottom_type)
return;

// convert rval-type to lval-type
Expand Down Expand Up @@ -3441,6 +3441,49 @@ static void emit_assignment(jl_codectx_t &ctx, jl_value_t *l, jl_value_t *r, ssi
emit_varinfo_assign(ctx, vi, rval_info, l);
}

static void emit_upsilonnode(jl_codectx_t &ctx, ssize_t phic, jl_value_t *val)
{
jl_varinfo_t &vi = ctx.phic_slots[phic];
// If the val is null, we can ignore the store.
// The middle end guarantees that the value from this
// upsilon node is not dynamically observed.
if (val) {
jl_cgval_t rval_info = emit_expr(ctx, val);
if (rval_info.typ == jl_bottom_type)
// as a special case, PhiC nodes are allowed to use undefined
// values, since they are just copy operations, so we need to
// ignore the store (it will not by dynamically observed), while
// normally, for any other operation result, we'd assume this store
// was unreachable and dead
val = NULL;
else
emit_varinfo_assign(ctx, vi, rval_info);
}
if (!val) {
if (vi.boxroot) {
// memory optimization: eagerly clear this gc-root now
ctx.builder.CreateAlignedStore(ConstantPointerNull::get(cast<PointerType>(T_prjlvalue)), vi.boxroot, Align(sizeof(void*)), true);
}
if (vi.pTIndex) {
// We don't care what the contents of the variable are, but it
// does need to satisfy the union invariants (i.e. inbounds
// tindex).
ctx.builder.CreateAlignedStore(
vi.boxroot ? ConstantInt::get(T_int8, 0x80) :
ConstantInt::get(T_int8, 0x01),
vi.pTIndex, Align(1), true);
}
else if (vi.value.V && !vi.value.constant && vi.value.typ != jl_bottom_type) {
assert(vi.value.ispointer());
Type *T = cast<AllocaInst>(vi.value.V)->getAllocatedType();
if (CountTrackedPointers(T).count) {
// make sure gc pointers (including ptr_phi of union-split) are initialized to NULL
ctx.builder.CreateStore(Constant::getNullValue(T), vi.value.V, true);
}
}
}
}

// --- convert expression to code ---

static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, const jl_cgval_t &fexpr, jl_value_t *rt, jl_svec_t *argt);
Expand Down Expand Up @@ -5425,9 +5468,7 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
i == 0) { // or it is the first argument (which isn't in `argArray`)
AllocaInst *av = new AllocaInst(T_prjlvalue, 0,
jl_symbol_name(s), /*InsertBefore*/ctx.ptlsStates);
StoreInst *SI = new StoreInst(
ConstantPointerNull::get(cast<PointerType>(T_prjlvalue)), av,
false);
StoreInst *SI = new StoreInst(ConstantPointerNull::get(cast<PointerType>(T_prjlvalue)), av, false, Align(sizeof(void*)));
SI->insertAfter(ctx.ptlsStates);
varinfo.boxroot = av;
if (ctx.debug_enabled && varinfo.dinfo) {
Expand Down Expand Up @@ -6020,23 +6061,7 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
continue;
}
if (jl_is_upsilonnode(stmt)) {
jl_value_t *val = jl_fieldref_noalloc(stmt, 0);
// If the val is null, we can ignore the store.
// The middle end guarantees that the value from this
// upsilon node is not dynamically observed.
jl_varinfo_t &vi = ctx.phic_slots[upsilon_to_phic[cursor+1]];
if (val) {
jl_cgval_t rval_info = emit_expr(ctx, val);
emit_varinfo_assign(ctx, vi, rval_info);
} else if (vi.pTIndex) {
// We don't care what the contents of the variable are, but it
// does need to satisfy the union invariants (i.e. inbounds
// tindex).
ctx.builder.CreateStore(
vi.boxroot ? ConstantInt::get(T_int8, 0x80) :
ConstantInt::get(T_int8, 0x01),
vi.pTIndex, true);
}
emit_upsilonnode(ctx, upsilon_to_phic[cursor + 1], jl_fieldref_noalloc(stmt, 0));
find_next_stmt(cursor + 1);
continue;
}
Expand Down Expand Up @@ -6206,19 +6231,25 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
}
else {
Value *RTindex;
Value *V;
// The branch below is a bit too complex for GCC to realize that
// `V` is always initialized when it is used.
// Ref https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96629
Value *V = nullptr;
if (val.typ == (jl_value_t*)jl_bottom_type) {
V = undef_value_for_type(VN->getType());
if (VN)
V = undef_value_for_type(VN->getType());
RTindex = UndefValue::get(T_int8);
}
else if (jl_is_concrete_type(val.typ) || val.constant) {
size_t tindex = get_box_tindex((jl_datatype_t*)val.typ, phiType);
if (tindex == 0) {
V = boxed(ctx, val);
if (VN)
V = boxed(ctx, val);
RTindex = ConstantInt::get(T_int8, 0x80);
}
else {
V = ConstantPointerNull::get(cast<PointerType>(T_prjlvalue));
if (VN)
V = ConstantPointerNull::get(cast<PointerType>(T_prjlvalue));
Type *lty = julia_type_to_llvm(ctx, val.typ);
if (dest && !type_is_ghost(lty)) // basically, if !ghost union
emit_unbox(ctx, lty, val, val.typ, dest);
Expand All @@ -6238,7 +6269,8 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
}
new_union.TIndex = RTindex;
}
V = new_union.Vboxed ? new_union.Vboxed : ConstantPointerNull::get(cast<PointerType>(T_prjlvalue));
if (VN)
V = new_union.Vboxed ? new_union.Vboxed : ConstantPointerNull::get(cast<PointerType>(T_prjlvalue));
if (dest) { // basically, if !ghost union
Value *skip = NULL;
if (new_union.Vboxed != nullptr)
Expand Down Expand Up @@ -7230,7 +7262,6 @@ static void init_julia_llvm_env(Module *m)
jl_newbits_func = Function::Create(FunctionType::get(T_prjlvalue, newbits_args, false),
Function::ExternalLinkage,
"jl_new_bits");
add_return_attr(jl_newbits_func, Attribute::NoAlias);
add_return_attr(jl_newbits_func, Attribute::NonNull);
add_named_global(jl_newbits_func, (void*)jl_new_bits);

Expand Down
1 change: 1 addition & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
if (j != i && temp[i] && temp[j]) {
if (temp[i] == temp[j] || temp[i] == jl_bottom_type ||
temp[j] == (jl_value_t*)jl_any_type ||
jl_egal(temp[i], temp[j]) ||
(!has_free && !jl_has_free_typevars(temp[j]) &&
jl_subtype(temp[i], temp[j]))) {
temp[i] = NULL;
Expand Down
Loading

0 comments on commit 005352a

Please sign in to comment.