Skip to content

WIP: Backports for 1.2.1 #33073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 89 additions & 55 deletions base/abstractset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ sizehint!(s::AbstractSet, n) = nothing

copy!(dst::AbstractSet, src::AbstractSet) = union!(empty!(dst), src)

## set operations (union, intersection, symmetric difference)

"""
union(s, itrs...)
∪(s, itrs...)
Expand Down Expand Up @@ -77,11 +79,11 @@ max_values(::Type{Nothing}) = 1

function union!(s::AbstractSet{T}, itr) where T
haslength(itr) && sizehint!(s, length(s) + length(itr))
for x=itr
for x in itr
push!(s, x)
length(s) == max_values(T) && break
end
s
return s
end

"""
Expand Down Expand Up @@ -220,41 +222,16 @@ function symdiff!(s::AbstractSet, itr)
for x in itr
x in s ? delete!(s, x) : push!(s, x)
end
s
return s
end

==(l::AbstractSet, r::AbstractSet) = length(l) == length(r) && l ⊆ r
# convenience functions for AbstractSet
# (if needed, only their synonyms ⊊ and ⊆ must be specialized)
<( l::AbstractSet, r::AbstractSet) = l ⊊ r
<=(l::AbstractSet, r::AbstractSet) = l ⊆ r
## non-strict subset comparison

function issubset(l, r)
if haslength(r)
rlen = length(r)
#This threshold was empirically determined by repeatedly
#sampling using these two methods (see #26198)
lenthresh = 70

if rlen > lenthresh && !isa(r, AbstractSet)
return issubset(l, Set(r))
end
end

for elt in l
if !in(elt, r)
return false
end
end
return true
end
# use the implementation below when it becomes as efficient
# issubset(l, r) = all(_in(r), l)
const ⊆ = issubset
⊇(l, r) = r ⊆ l
function ⊇ end
"""
issubset(a, b)
⊆(a,b) -> Bool
issubset(a, b) -> Bool
⊆(a, b) -> Bool
⊇(b, a) -> Bool

Determine whether every element of `a` is also in `b`, using [`in`](@ref).
Expand All @@ -273,29 +250,35 @@ true
"""
issubset, ⊆, ⊇

"""
issetequal(a, b)

Determine whether `a` and `b` have the same elements. Equivalent
to `a ⊆ b && b ⊆ a`.
function issubset(l, r)
if haslength(r)
rlen = length(r)
if isa(l, AbstractSet)
# check l for too many unique elements
length(l) > rlen && return false
end
# if r is big enough, convert it to a Set
# threshold empirically determined by repeatedly
# sampling using these two methods (see #26198)
if rlen > 70 && !isa(r, AbstractSet)
return issubset(l, Set(r))
end
end
for elt in l
elt in r || return false
end
return true
end

# Examples
```jldoctest
julia> issetequal([1, 2], [1, 2, 3])
false
⊇(l, r) = r ⊆ l

julia> issetequal([1, 2], [2, 1])
true
```
"""
issetequal(l, r) = length(l) == length(r) && l ⊆ r
issetequal(l::AbstractSet, r::AbstractSet) = l == r
## strict subset comparison

⊊(l, r) = length(l) < length(r) && l ⊆ r
⊋(l, r) = r ⊊ l
function ⊊ end
function ⊋ end
"""
⊊(a, b)
⊋(b, a)
⊊(a, b) -> Bool
⊋(b, a) -> Bool

Determines if `a` is a subset of, but not equal to, `b`.

Expand All @@ -310,11 +293,15 @@ false
"""
⊊, ⊋

⊈(l, r) = !⊆(l, r)
⊉(l, r) = r ⊈ l
⊊(l::AbstractSet, r) = length(l) < length(r) && l ⊆ r
⊊(l, r) = Set(l) ⊊ r
⊋(l, r) = r ⊊ l

function ⊈ end
function ⊉ end
"""
⊈(a, b)
⊉(b, a)
⊈(a, b) -> Bool
⊉(b, a) -> Bool

Negation of `⊆` and `⊇`, i.e. checks that `a` is not a subset of `b`.

Expand All @@ -329,6 +316,53 @@ false
"""
⊈, ⊉

⊈(l, r) = !⊆(l, r)
⊉(l, r) = r ⊈ l

## set equality comparison

"""
issetequal(a, b) -> Bool

Determine whether `a` and `b` have the same elements. Equivalent
to `a ⊆ b && b ⊆ a` but more efficient when possible.

# Examples
```jldoctest
julia> issetequal([1, 2], [1, 2, 3])
false

julia> issetequal([1, 2], [2, 1])
true
```
"""
issetequal(l::AbstractSet, r::AbstractSet) = l == r
issetequal(l::AbstractSet, r) = issetequal(l, Set(r))

function issetequal(l, r::AbstractSet)
if haslength(l)
# check r for too many unique elements
length(l) < length(r) && return false
end
return issetequal(Set(l), r)
end

function issetequal(l, r)
haslength(l) && return issetequal(l, Set(r))
haslength(r) && return issetequal(r, Set(l))
return issetequal(Set(l), Set(r))
end

## partial ordering of sets by containment

==(l::AbstractSet, r::AbstractSet) = length(l) == length(r) && l ⊆ r
# convenience functions for AbstractSet
# (if needed, only their synonyms ⊊ and ⊆ must be specialized)
<( l::AbstractSet, r::AbstractSet) = l ⊊ r
<=(l::AbstractSet, r::AbstractSet) = l ⊆ r

## filtering sets

filter(pred, s::AbstractSet) = mapfilter(pred, push!, s, emptymutable(s))

# it must be safe to delete the current element while iterating over s:
Expand Down
7 changes: 4 additions & 3 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -717,9 +717,10 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
eidx = findfirst(x->x[1] == item, catch_entry_blocks)
if eidx !== nothing
for (slot, _, node) in phicnodes[catch_entry_blocks[eidx][2]]
ivalundef = incoming_vals[slot_id(slot)] === undef_token
unode = ivalundef ? UpsilonNode() : UpsilonNode(incoming_vals[slot_id(slot)])
typ = ivalundef ? MaybeUndef(Union{}) : slottypes[slot_id(slot)]
ival = incoming_vals[slot_id(slot)]
ivalundef = ival === undef_token
unode = ivalundef ? UpsilonNode() : UpsilonNode(ival)
typ = ivalundef ? MaybeUndef(Union{}) : typ_for_val(ival, ci, sptypes, -1, slottypes)
push!(node.values,
NewSSAValue(insert_node!(ir, first_insert_for_bb(code, cfg, item),
typ, unode, true).id - length(ir.stmts)))
Expand Down
21 changes: 10 additions & 11 deletions contrib/generate_precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,6 @@ function generate_precompile_statements()
push!(statements, statement)
end

if have_repl
# Seems like a reasonable number right now, adjust as needed
# comment out if debugging script
@assert length(statements) > 700
end

# Create a staging area where all the loaded packages are available
PrecompileStagingArea = Module()
for (_pkgid, _mod) in Base.loaded_modules
Expand All @@ -162,18 +156,23 @@ function generate_precompile_statements()
end

# Execute the collected precompile statements
n_succeeded = 0
include_time = @elapsed for statement in sort(collect(statements))
# println(statement)
# Work around #28808
occursin("\"YYYY-mm-dd\\THH:MM:SS\"", statement) && continue
statement == "precompile(Tuple{typeof(Base.show), Base.IOContext{Base.TTY}, Type{Vararg{Any, N} where N}})" && continue
try
Base.include_string(PrecompileStagingArea, statement)
n_succeeded += 1
catch
@error "Failed to precompile $statement"
rethrow()
# See #28808
# @error "Failed to precompile $statement"
end
end
if have_repl
# Seems like a reasonable number right now, adjust as needed
# comment out if debugging script
@assert n_succeeded > 3500
end

print(" $(length(statements)) generated in ")
tot_time = time() - start_time
Base.time_print(tot_time * 10^9)
Expand Down
15 changes: 13 additions & 2 deletions doc/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,19 @@ makedocs(
# Only deploy docs from 64bit Linux to avoid committing multiple versions of the same
# docs from different workers.
if "deploy" in ARGS && Sys.ARCH === :x86_64 && Sys.KERNEL === :Linux
# Override TRAVIS_REPO_SLUG since we deploy to a different repo
withenv("TRAVIS_REPO_SLUG" => "JuliaLang/docs.julialang.org") do

# Override a few environment variables to deploy to the appropriate repository,
# encode things like branch, whether it's built on a tag, etc....
env_mappings = [
"TRAVIS_REPO_SLUG" => "JuliaLang/docs.julialang.org",
"TRAVIS_BRANCH" => Base.GIT_VERSION_INFO.branch,
]

if Base.GIT_VERSION_INFO.tagged_commit
push!(env_mappings, "TRAVIS_TAG" => "v$(Base.VERSION)")
end

withenv(env_mappings...) do
deploydocs(
repo = "github.com/JuliaLang/docs.julialang.org.git",
target = joinpath(buildroot, "doc", "_build", "html", "en"),
Expand Down
38 changes: 32 additions & 6 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,10 @@ const char *name_from_method_instance(jl_method_instance_t *mi)
extern "C"
jl_code_instance_t *jl_compile_linfo(jl_method_instance_t *mi, jl_code_info_t *src, size_t world, const jl_cgparams_t *params)
{
// TODO: Merge with jl_dump_compiles?
static ios_t f_precompile;
static JL_STREAM* s_precompile = NULL;

// N.B.: `src` may have not been rooted by the caller.
JL_TIMING(CODEGEN);
assert(jl_is_method_instance(mi));
Expand Down Expand Up @@ -1272,12 +1276,34 @@ jl_code_instance_t *jl_compile_linfo(jl_method_instance_t *mi, jl_code_info_t *s
// ... unless mi->def isn't defined here meaning the function is a toplevel thunk and
// would have its CodeInfo printed in the stream, which might contain double-quotes that
// would not be properly escaped given the double-quotes added to the stream below.
if (dump_compiles_stream != NULL && jl_is_method(mi->def.method)) {
uint64_t this_time = jl_hrtime();
jl_printf(dump_compiles_stream, "%" PRIu64 "\t\"", this_time - last_time);
jl_static_show(dump_compiles_stream, mi->specTypes);
jl_printf(dump_compiles_stream, "\"\n");
last_time = this_time;
if (jl_is_method(mi->def.method)) {
if (jl_options.trace_compile != NULL) {
if (s_precompile == NULL) {
const char* t = jl_options.trace_compile;
if (!strncmp(t, "stderr", 6))
s_precompile = JL_STDERR;
else {
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
s_precompile = (JL_STREAM*) &f_precompile;
}
}
if (!jl_has_free_typevars(mi->specTypes)) {
jl_printf(s_precompile, "precompile(");
jl_static_show(s_precompile, mi->specTypes);
jl_printf(s_precompile, ")\n");

if (s_precompile != JL_STDERR)
ios_flush(&f_precompile);
}
}
if (dump_compiles_stream != NULL) {
uint64_t this_time = jl_hrtime();
jl_printf(dump_compiles_stream, "%" PRIu64 "\t\"", this_time - last_time);
jl_static_show(dump_compiles_stream, mi->specTypes);
jl_printf(dump_compiles_stream, "\"\n");
last_time = this_time;
}
}
JL_GC_POP();
return codeinst;
Expand Down
24 changes: 0 additions & 24 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,10 +995,6 @@ static jl_method_instance_t *cache_method(

static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int mt_cache, size_t world)
{
// TODO: Merge with jl_dump_compiles?
static ios_t f_precompile;
static JL_STREAM* s_precompile = NULL;

// caller must hold the mt->writelock
jl_typemap_entry_t *entry = NULL;
entry = jl_typemap_assoc_by_type(mt->cache, (jl_value_t*)tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
Expand All @@ -1014,26 +1010,6 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype
if (entry != NULL) {
jl_method_t *m = entry->func.method;
if (!jl_has_call_ambiguities((jl_value_t*)tt, m)) {
if (jl_options.trace_compile != NULL) {
if (s_precompile == NULL) {
const char* t = jl_options.trace_compile;
if (!strncmp(t, "stderr", 6))
s_precompile = JL_STDERR;
else {
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
s_precompile = (JL_STREAM*) &f_precompile;
}
}
if (!jl_has_free_typevars((jl_value_t*)tt)) {
jl_printf(s_precompile, "precompile(");
jl_static_show(s_precompile, (jl_value_t*)tt);
jl_printf(s_precompile, ")\n");

if (s_precompile != JL_STDERR)
ios_flush(&f_precompile);
}
}
if (!mt_cache) {
intptr_t nspec = (mt == jl_type_type_mt ? m->nargs + 1 : mt->max_args + 2);
jl_compilation_sig(tt, env, m, nspec, &newparams);
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/src/qr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ AbstractMatrix{T}(Q::QRPackedQ) where {T} = QRPackedQ{T}(Q)
QRCompactWYQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T))
AbstractMatrix{S}(Q::QRCompactWYQ{S}) where {S} = Q
AbstractMatrix{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ{S}(Q)
Matrix{T}(Q::AbstractQ) where {T} = lmul!(Q, Matrix{T}(I, size(Q, 1), min(size(Q.factors)...)))
Matrix{T}(Q::AbstractQ{S}) where {T,S} = Matrix{T}(lmul!(Q, Matrix{S}(I, size(Q, 1), min(size(Q.factors)...))))
Matrix(Q::AbstractQ{T}) where {T} = Matrix{T}(Q)
Array{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
Array(Q::AbstractQ) = Matrix(Q)
Expand Down
10 changes: 8 additions & 2 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -764,15 +764,21 @@ setup_interface(
repl::LineEditREPL;
# those keyword arguments may be deprecated eventually in favor of the Options mechanism
hascolor::Bool = repl.options.hascolor,
extra_repl_keymap::Union{Dict,Vector{<:Dict}} = repl.options.extra_keymap
extra_repl_keymap::Any = repl.options.extra_keymap
) = setup_interface(repl, hascolor, extra_repl_keymap)

# This non keyword method can be precompiled which is important
function setup_interface(
repl::LineEditREPL,
hascolor::Bool,
extra_repl_keymap::Union{Dict,Vector{<:Dict}},
extra_repl_keymap::Any, # Union{Dict,Vector{<:Dict}},
)
# The precompile statement emitter has problem outputting valid syntax for the
# type of `Union{Dict,Vector{<:Dict}}` (see #28808).
# This function is however important to precompile for REPL startup time, therefore,
# make the type Any and just assert that we have the correct type below.
@assert extra_repl_keymap isa Union{Dict,Vector{<:Dict}}

###
#
# This function returns the main interface that describes the REPL
Expand Down
Loading