diff --git a/Make.inc b/Make.inc index a6de773b88dcd..5d58454c80333 100644 --- a/Make.inc +++ b/Make.inc @@ -759,6 +759,12 @@ JCXXFLAGS += -DGC_VERIFY JCFLAGS += -DGC_VERIFY endif +ifneq ($(JL_STACK_SIZE),) +JCXXFLAGS += -DJL_STACK_SIZE=$(JL_STACK_SIZE) +JCFLAGS += -DJL_STACK_SIZE=$(JL_STACK_SIZE) +endif + + ifeq ($(WITH_GC_DEBUG_ENV), 1) JCXXFLAGS += -DGC_DEBUG_ENV JCFLAGS += -DGC_DEBUG_ENV @@ -1386,7 +1392,7 @@ endif ifeq ($(OS), WINNT) HAVE_SSP := 1 OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ - $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -luserenv -lsecur32 -latomic + $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -luserenv -lsecur32 -latomic -lole32 JLDFLAGS += -Wl,--stack,8388608 ifeq ($(ARCH),i686) JLDFLAGS += -Wl,--large-address-aware diff --git a/NEWS.md b/NEWS.md index 6db22fa1f8be7..2da8a7bad8b23 100644 --- a/NEWS.md +++ b/NEWS.md @@ -54,6 +54,7 @@ Compiler/Runtime improvements * A new `LazyLibrary` type is exported from `Libdl` for use in building chained lazy library loads, primarily to be used within JLLs ([#50074]). * Added support for annotating `Base.@assume_effects` on code blocks ([#52400]). +* The libuv library has been updated from a base of v1.44.2 to v1.48.0 ([#49937]). Command-line option changes --------------------------- @@ -86,6 +87,7 @@ New library functions * `Sys.username()` can be used to return the current user's username ([#51897]). * `wrap(Array, m::Union{MemoryRef{T}, Memory{T}}, dims)` is the safe counterpart to `unsafe_wrap` ([#52049]). * `GC.logging_enabled()` can be used to test whether GC logging has been enabled via `GC.enable_logging` ([#51647]). +* `IdSet` is now exported from Base and considered public ([#53262]). New library features -------------------- @@ -139,6 +141,7 @@ Standard library changes * Structured matrices now retain either the axes of the parent (for `Symmetric`/`Hermitian`/`AbstractTriangular`/`UpperHessenberg`), or that of the principal diagonal (for banded matrices) ([#52480]). * `bunchkaufman` and `bunchkaufman!` now work for any `AbstractFloat`, `Rational` and their complex variants. `bunchkaufman` now supports `Integer` types, by making an internal conversion to `Rational{BigInt}`. Added new function `inertia` that computes the inertia of the diagonal factor given by the `BunchKaufman` factorization object of a real symmetric or Hermitian matrix. For complex symmetric matrices, `inertia` only computes the number of zero eigenvalues of the diagonal factor ([#51487]). * Packages that specialize matrix-matrix `mul!` with a method signature of the form `mul!(::AbstractMatrix, ::MyMatrix, ::AbstractMatrix, ::Number, ::Number)` no longer encounter method ambiguities when interacting with `LinearAlgebra`. Previously, ambiguities used to arise when multiplying a `MyMatrix` with a structured matrix type provided by LinearAlgebra, such as `AbstractTriangular`, which used to necessitate additional methods to resolve such ambiguities. Similar sources of ambiguities have also been removed for matrix-vector `mul!` operations ([#52837]). +* `lu` and `issuccess(::LU)` now accept an `allowsingular` keyword argument. When set to `true`, a valid factorization with rank-deficient U factor will be treated as success instead of throwing an error. Such factorizations are now shown by printing the factors together with a "rank-deficient" note rather than printing a "Failed Factorization" message ([#52957]). #### Logging * New `@create_log_macro` macro for creating new log macros like `@info`, `@warn` etc. For instance diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 5ca485610f053..62a5b3ee9e1b0 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -416,7 +416,7 @@ end Update `d`, removing elements for which `f` is `false`. The function `f` is passed `key=>value` pairs. -# Example +# Examples ```jldoctest julia> d = Dict(1=>"a", 2=>"b", 3=>"c") Dict{Int64, String} with 3 entries: @@ -579,6 +579,55 @@ _tablesz(x::T) where T <: Integer = x < 16 ? T(16) : one(T)<<(top_set_bit(x-one( TP{K,V} = Union{Type{Tuple{K,V}},Type{Pair{K,V}}} +# This error is thrown if `grow_to!` cannot validate the contents of the iterator argument to it, which it does by testing the iteration protocol (isiterable) on it each time it is about to start iteration on it +_throw_dict_kv_error() = throw(ArgumentError("AbstractDict(kv): kv needs to be an iterator of 2-tuples or pairs")) + +function grow_to!(dest::AbstractDict, itr) + applicable(iterate, itr) || _throw_dict_kv_error() + y = iterate(itr) + y === nothing && return dest + kv, st = y + applicable(iterate, kv) || _throw_dict_kv_error() + k = iterate(kv) + k === nothing && _throw_dict_kv_error() + k, kvst = k + v = iterate(kv, kvst) + v === nothing && _throw_dict_kv_error() + v, kvst = v + iterate(kv, kvst) === nothing || _throw_dict_kv_error() + if !(dest isa AbstractDict{typeof(k), typeof(v)}) + dest = empty(dest, typeof(k), typeof(v)) + end + dest[k] = v + return grow_to!(dest, itr, st) +end + +function grow_to!(dest::AbstractDict{K,V}, itr, st) where {K, V} + y = iterate(itr, st) + while y !== nothing + kv, st = y + applicable(iterate, kv) || _throw_dict_kv_error() + kst = iterate(kv) + kst === nothing && _throw_dict_kv_error() + k, kvst = kst + vst = iterate(kv, kvst) + vst === nothing && _throw_dict_kv_error() + v, kvst = vst + iterate(kv, kvst) === nothing || _throw_dict_kv_error() + if isa(k, K) && isa(v, V) + dest[k] = v + else + new = empty(dest, promote_typejoin(K, typeof(k)), promote_typejoin(V, typeof(v))) + merge!(new, dest) + new[k] = v + return grow_to!(new, itr, st) + end + y = iterate(itr, st) + end + return dest +end + + dict_with_eltype(DT_apply, kv, ::TP{K,V}) where {K,V} = DT_apply(K, V)(kv) dict_with_eltype(DT_apply, kv::Generator, ::TP{K,V}) where {K,V} = DT_apply(K, V)(kv) dict_with_eltype(DT_apply, ::Type{Pair{K,V}}) where {K,V} = DT_apply(K, V)() diff --git a/base/boot.jl b/base/boot.jl index ed26536b961ff..8ca6d392ead67 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -483,13 +483,13 @@ eval(Core, quote end) function CodeInstance( - mi::MethodInstance, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const), + mi::MethodInstance, owner, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const), @nospecialize(inferred), const_flags::Int32, min_world::UInt, max_world::UInt, ipo_effects::UInt32, effects::UInt32, @nospecialize(analysis_results), relocatability::UInt8) return ccall(:jl_new_codeinst, Ref{CodeInstance}, - (Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, UInt32, Any, UInt8), - mi, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world, + (Any, Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, UInt32, Any, UInt8), + mi, owner, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world, ipo_effects, effects, analysis_results, relocatability) end diff --git a/base/cartesian.jl b/base/cartesian.jl index decc01cbc3e5f..ca0fc0aac0cfc 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -115,7 +115,7 @@ Generate a function call expression with keyword arguments `kw...`. As in the case of [`@ncall`](@ref), `sym` represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded into `N` arguments. -# Example +# Examples ```jldoctest julia> using Base.Cartesian diff --git a/base/cmd.jl b/base/cmd.jl index da29c732c7f26..202527abdf644 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -3,9 +3,10 @@ abstract type AbstractCmd end # libuv process option flags -const UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = UInt8(1 << 2) -const UV_PROCESS_DETACHED = UInt8(1 << 3) -const UV_PROCESS_WINDOWS_HIDE = UInt8(1 << 4) +const UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = UInt32(1 << 2) +const UV_PROCESS_DETACHED = UInt32(1 << 3) +const UV_PROCESS_WINDOWS_HIDE = UInt32(1 << 4) +const UV_PROCESS_WINDOWS_DISABLE_EXACT_NAME = UInt32(1 << 7) struct Cmd <: AbstractCmd exec::Vector{String} @@ -14,7 +15,7 @@ struct Cmd <: AbstractCmd env::Union{Vector{String},Nothing} dir::String cpus::Union{Nothing,Vector{UInt16}} - Cmd(exec::Vector{String}) = + Cmd(exec::Vector{<:AbstractString}) = new(exec, false, 0x00, nothing, "", nothing) Cmd(cmd::Cmd, ignorestatus, flags, env, dir, cpus = nothing) = new(cmd.exec, ignorestatus, flags, env, diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 2b736dbeff9d8..9244ee5f3f8ec 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -3304,6 +3304,10 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) end if rt === Bottom ssavaluetypes[currpc] = Bottom + # Special case: Bottom-typed PhiNodes do not error (but must also be unused) + if isa(stmt, PhiNode) + continue + end @goto find_next_bb end if changes !== nothing diff --git a/base/compiler/cicache.jl b/base/compiler/cicache.jl index 8332777e6d5bc..a6ed18fe5105f 100644 --- a/base/compiler/cicache.jl +++ b/base/compiler/cicache.jl @@ -7,15 +7,16 @@ Internally, each `MethodInstance` keep a unique global cache of code instances that have been created for the given method instance, stratified by world age ranges. This struct abstracts over access to this cache. """ -struct InternalCodeCache end +struct InternalCodeCache + owner::Any # `jl_egal` is used for comparison +end function setindex!(cache::InternalCodeCache, ci::CodeInstance, mi::MethodInstance) + @assert ci.owner === cache.owner ccall(:jl_mi_cache_insert, Cvoid, (Any, Any), mi, ci) return cache end -const GLOBAL_CI_CACHE = InternalCodeCache() - struct WorldRange min_world::UInt max_world::UInt @@ -49,11 +50,11 @@ WorldView(wvc::WorldView, wr::WorldRange) = WorldView(wvc.cache, wr) WorldView(wvc::WorldView, args...) = WorldView(wvc.cache, args...) function haskey(wvc::WorldView{InternalCodeCache}, mi::MethodInstance) - return ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds)) !== nothing + return ccall(:jl_rettype_inferred, Any, (Any, Any, UInt, UInt), wvc.cache.owner, mi, first(wvc.worlds), last(wvc.worlds)) !== nothing end function get(wvc::WorldView{InternalCodeCache}, mi::MethodInstance, default) - r = ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds)) + r = ccall(:jl_rettype_inferred, Any, (Any, Any, UInt, UInt), wvc.cache.owner, mi, first(wvc.worlds), last(wvc.worlds)) if r === nothing return default end @@ -70,3 +71,9 @@ function setindex!(wvc::WorldView{InternalCodeCache}, ci::CodeInstance, mi::Meth setindex!(wvc.cache, ci, mi) return wvc end + +function code_cache(interp::AbstractInterpreter) + cache = InternalCodeCache(cache_owner(interp)) + worlds = WorldRange(get_inference_world(interp)) + return WorldView(cache, worlds) +end diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index f634fc0bcb7e4..cbe80a65fc607 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -1086,7 +1086,7 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState) idx += 1 prevloc = codeloc end - if ssavaluetypes[idx] === Union{} && !(oldidx in sv.unreachable) + if ssavaluetypes[idx] === Union{} && !(oldidx in sv.unreachable) && !isa(code[idx], PhiNode) # We should have converted any must-throw terminators to an equivalent w/o control-flow edges @assert !isterminator(code[idx]) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index e9edd04e59d40..e30c6e5f96fcb 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -326,7 +326,7 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult, end end # relocatability = isa(inferred_result, String) ? inferred_result[end] : UInt8(0) - return CodeInstance(result.linfo, + return CodeInstance(result.linfo, cache_owner(interp), widenconst(result_type), widenconst(result.exc_result), rettype_const, inferred_result, const_flags, first(valid_worlds), last(valid_worlds), # TODO: Actually do something with non-IPO effects diff --git a/base/compiler/types.jl b/base/compiler/types.jl index cdf90a3a6e78c..642a7ac551662 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -14,7 +14,7 @@ the following methods to satisfy the `AbstractInterpreter` API requirement: - `OptimizationParams(interp::NewInterpreter)` - return an `OptimizationParams` instance - `get_inference_world(interp::NewInterpreter)` - return the world age for this interpreter - `get_inference_cache(interp::NewInterpreter)` - return the local inference cache -- `code_cache(interp::NewInterpreter)` - return the global inference cache +- `cache_owner(interp::NewInterpreter)` - return the owner of any new cache entries """ :(AbstractInterpreter) @@ -404,7 +404,7 @@ InferenceParams(interp::NativeInterpreter) = interp.inf_params OptimizationParams(interp::NativeInterpreter) = interp.opt_params get_inference_world(interp::NativeInterpreter) = interp.world get_inference_cache(interp::NativeInterpreter) = interp.inf_cache -code_cache(interp::NativeInterpreter) = WorldView(GLOBAL_CI_CACHE, get_inference_world(interp)) +cache_owner(interp::NativeInterpreter) = nothing """ already_inferred_quick_test(::AbstractInterpreter, ::MethodInstance) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 368395e714054..7d554e46a1744 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -321,25 +321,6 @@ function iterate(iter::BackedgeIterator, i::Int=1) return BackedgePair(item, backedges[i+1]::MethodInstance), i+2 # `invoke` calls end -""" - add_invalidation_callback!(callback, mi::MethodInstance) - -Register `callback` to be triggered upon the invalidation of `mi`. -`callback` should a function taking two arguments, `callback(replaced::MethodInstance, max_world::UInt32)`, -and it will be recursively invoked on `MethodInstance`s within the invalidation graph. -""" -function add_invalidation_callback!(@nospecialize(callback), mi::MethodInstance) - if !isdefined(mi, :callbacks) - callbacks = mi.callbacks = Any[callback] - else - callbacks = mi.callbacks::Vector{Any} - if !any(@nospecialize(cb)->cb===callback, callbacks) - push!(callbacks, callback) - end - end - return callbacks -end - ######### # types # ######### @@ -415,15 +396,15 @@ function find_ssavalue_uses(body::Vector{Any}, nvals::Int) if isa(e, SSAValue) push!(uses[e.id], line) elseif isa(e, Expr) - find_ssavalue_uses(e, uses, line) + find_ssavalue_uses!(uses, e, line) elseif isa(e, PhiNode) - find_ssavalue_uses(e, uses, line) + find_ssavalue_uses!(uses, e, line) end end return uses end -function find_ssavalue_uses(e::Expr, uses::Vector{BitSet}, line::Int) +function find_ssavalue_uses!(uses::Vector{BitSet}, e::Expr, line::Int) head = e.head is_meta_expr_head(head) && return skiparg = (head === :(=)) @@ -433,13 +414,16 @@ function find_ssavalue_uses(e::Expr, uses::Vector{BitSet}, line::Int) elseif isa(a, SSAValue) push!(uses[a.id], line) elseif isa(a, Expr) - find_ssavalue_uses(a, uses, line) + find_ssavalue_uses!(uses, a, line) end end end -function find_ssavalue_uses(e::PhiNode, uses::Vector{BitSet}, line::Int) - for val in e.values +function find_ssavalue_uses!(uses::Vector{BitSet}, e::PhiNode, line::Int) + values = e.values + for i = 1:length(values) + isassigned(values, i) || continue + val = values[i] if isa(val, SSAValue) push!(uses[val.id], line) end diff --git a/base/complex.jl b/base/complex.jl index f14b7f2f5336f..8ac126d2c6532 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1097,7 +1097,7 @@ second is used for rounding the imaginary components. which rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. -# Example +# Examples ```jldoctest julia> round(3.14 + 4.5im) 3.0 + 4.0im diff --git a/base/dict.jl b/base/dict.jl index 2b6fd41d8d075..c924e10ab4d6e 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -114,45 +114,7 @@ const AnyDict = Dict{Any,Any} Dict(ps::Pair{K,V}...) where {K,V} = Dict{K,V}(ps) Dict(ps::Pair...) = Dict(ps) -function Dict(kv) - try - dict_with_eltype((K, V) -> Dict{K, V}, kv, eltype(kv)) - catch - if !isiterable(typeof(kv)) || !all(x->isa(x,Union{Tuple,Pair}),kv) - throw(ArgumentError("Dict(kv): kv needs to be an iterator of tuples or pairs")) - else - rethrow() - end - end -end - -function grow_to!(dest::AbstractDict{K, V}, itr) where V where K - y = iterate(itr) - y === nothing && return dest - ((k,v), st) = y - dest2 = empty(dest, typeof(k), typeof(v)) - dest2[k] = v - grow_to!(dest2, itr, st) -end - -# this is a special case due to (1) allowing both Pairs and Tuples as elements, -# and (2) Pair being invariant. a bit annoying. -function grow_to!(dest::AbstractDict{K,V}, itr, st) where V where K - y = iterate(itr, st) - while y !== nothing - (k,v), st = y - if isa(k,K) && isa(v,V) - dest[k] = v - else - new = empty(dest, promote_typejoin(K,typeof(k)), promote_typejoin(V,typeof(v))) - merge!(new, dest) - new[k] = v - return grow_to!(new, itr, st) - end - y = iterate(itr, st) - end - return dest -end +Dict(kv) = dict_with_eltype((K, V) -> Dict{K, V}, kv, eltype(kv)) empty(a::AbstractDict, ::Type{K}, ::Type{V}) where {K, V} = Dict{K, V}() diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 7ddb556d40871..637a8e1a50bd9 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -60,7 +60,7 @@ function. include("bindings.jl") -import .Base.Meta: quot, isexpr +import .Base.Meta: quot, isexpr, unblock, unescape, uncurly import .Base: Callable, with_output_color using .Base: RefValue, mapany import ..CoreDocs: lazy_iterpolate @@ -285,29 +285,6 @@ catdoc(xs...) = vcat(xs...) const keywords = Dict{Symbol, DocStr}() -function unblock(@nospecialize ex) - while isexpr(ex, :var"hygienic-scope") - isexpr(ex.args[1], :escape) || break - ex = ex.args[1].args[1] - end - isexpr(ex, :block) || return ex - exs = filter(ex -> !(isa(ex, LineNumberNode) || isexpr(ex, :line)), ex.args) - length(exs) == 1 || return ex - return unblock(exs[1]) -end - -# peek through ex to figure out what kind of expression it may eventually act like -# but ignoring scopes and line numbers -function unescape(@nospecialize ex) - ex = unblock(ex) - while isexpr(ex, :escape) || isexpr(ex, :var"hygienic-scope") - ex = unblock(ex.args[1]) - end - return ex -end - -uncurly(@nospecialize ex) = isexpr(ex, :curly) ? ex.args[1] : ex - namify(@nospecialize x) = astname(x, isexpr(x, :macro))::Union{Symbol,Expr,GlobalRef} function astname(x::Expr, ismacro::Bool) diff --git a/base/errorshow.jl b/base/errorshow.jl index a6ed409f61069..0705c142157d2 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -450,7 +450,8 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs=[]) # functions methods and counting the number of matching arguments. f = ex.f ft = typeof(f) - lines = [] + lines = String[] + line_score = Int[] # These functions are special cased to only show if first argument is matched. special = f === convert || f === getindex || f === setindex! funcs = Tuple{Any,Vector{Any}}[(f, arg_types_param)] @@ -541,85 +542,82 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs=[]) end end - if right_matches > 0 || length(arg_types_param) < 2 - if length(t_i) < length(sig) - # If the methods args is longer than input then the method - # arguments is printed as not a match - for (k, sigtype) in enumerate(sig[length(t_i)+1:end]) - sigtype = isvarargtype(sigtype) ? unwrap_unionall(sigtype) : sigtype - if Base.isvarargtype(sigtype) - sigstr = (unwrapva(sigtype::Core.TypeofVararg), "...") - else - sigstr = (sigtype,) - end - if !((min(length(t_i), length(sig)) == 0) && k==1) - print(iob, ", ") - end - if k == 1 && Base.isvarargtype(sigtype) - # There wasn't actually a mismatch - the method match failed for - # some other reason, e.g. world age. Just print the sigstr. - print(iob, sigstr...) - elseif get(io, :color, false)::Bool - let sigstr=sigstr - Base.with_output_color(Base.error_color(), iob) do iob - print(iob, "::", sigstr...) - end - end - else - print(iob, "!Matched::", sigstr...) - end + if length(t_i) < length(sig) + # If the methods args is longer than input then the method + # arguments is printed as not a match + for (k, sigtype) in enumerate(sig[length(t_i)+1:end]) + sigtype = isvarargtype(sigtype) ? unwrap_unionall(sigtype) : sigtype + if Base.isvarargtype(sigtype) + sigstr = (unwrapva(sigtype::Core.TypeofVararg), "...") + else + sigstr = (sigtype,) end - end - kwords = kwarg_decl(method) - if !isempty(kwords) - print(iob, "; ") - join(iob, kwords, ", ") - end - print(iob, ")") - show_method_params(iob0, tv) - file, line = updated_methodloc(method) - if file === nothing - file = string(method.file) - end - stacktrace_contract_userdir() && (file = contractuser(file)) - - if !isempty(kwargs)::Bool - unexpected = Symbol[] - if isempty(kwords) || !(any(endswith(string(kword), "...") for kword in kwords)) - for (k, v) in kwargs - if !(k::Symbol in kwords) - push!(unexpected, k::Symbol) + if !((min(length(t_i), length(sig)) == 0) && k==1) + print(iob, ", ") + end + if k == 1 && Base.isvarargtype(sigtype) + # There wasn't actually a mismatch - the method match failed for + # some other reason, e.g. world age. Just print the sigstr. + print(iob, sigstr...) + elseif get(io, :color, false)::Bool + let sigstr=sigstr + Base.with_output_color(Base.error_color(), iob) do iob + print(iob, "::", sigstr...) end end + else + print(iob, "!Matched::", sigstr...) end - if !isempty(unexpected) - Base.with_output_color(Base.error_color(), iob) do iob - plur = length(unexpected) > 1 ? "s" : "" - print(iob, " got unsupported keyword argument$plur \"", join(unexpected, "\", \""), "\"") + end + end + kwords = kwarg_decl(method) + if !isempty(kwords) + print(iob, "; ") + join(iob, kwords, ", ") + end + print(iob, ")") + show_method_params(iob0, tv) + file, line = updated_methodloc(method) + if file === nothing + file = string(method.file) + end + stacktrace_contract_userdir() && (file = contractuser(file)) + + if !isempty(kwargs)::Bool + unexpected = Symbol[] + if isempty(kwords) || !(any(endswith(string(kword), "...") for kword in kwords)) + for (k, v) in kwargs + if !(k::Symbol in kwords) + push!(unexpected, k::Symbol) end end end - if ex.world < reinterpret(UInt, method.primary_world) - print(iob, " (method too new to be called from this world context.)") - elseif ex.world > reinterpret(UInt, method.deleted_world) - print(iob, " (method deleted before this world age.)") + if !isempty(unexpected) + Base.with_output_color(Base.error_color(), iob) do iob + plur = length(unexpected) > 1 ? "s" : "" + print(iob, " got unsupported keyword argument$plur \"", join(unexpected, "\", \""), "\"") + end end - println(iob) - - m = parentmodule_before_main(method) - modulecolor = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m) - print_module_path_file(iob, m, string(file), line; modulecolor, digit_align_width = 3) - - # TODO: indicate if it's in the wrong world - push!(lines, (buf, right_matches)) end + if ex.world < reinterpret(UInt, method.primary_world) + print(iob, " (method too new to be called from this world context.)") + elseif ex.world > reinterpret(UInt, method.deleted_world) + print(iob, " (method deleted before this world age.)") + end + println(iob) + + m = parentmodule_before_main(method) + modulecolor = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m) + print_module_path_file(iob, m, string(file), line; modulecolor, digit_align_width = 3) + push!(lines, String(take!(buf))) + push!(line_score, -(right_matches * 2 + (length(arg_types_param) < 2 ? 1 : 0))) end end if !isempty(lines) # Display up to three closest candidates Base.with_output_color(:normal, io) do io print(io, "\n\nClosest candidates are:") - sort!(lines, by = x -> -x[2]) + permute!(lines, sortperm(line_score)) i = 0 for line in lines println(io) @@ -628,7 +626,7 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs=[]) break end i += 1 - print(io, String(take!(line[1]))) + print(io, line) end println(io) # extra newline for spacing to stacktrace end diff --git a/base/essentials.jl b/base/essentials.jl index 8e329c4f7c4d9..9c156fb1b8f6d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -90,7 +90,7 @@ f(y) = [x for x in y] standard ones) on type-inference. Use [`Base.@nospecializeinfer`](@ref) together with `@nospecialize` to additionally suppress inference. -# Example +# Examples ```julia julia> f(A::AbstractArray) = g(A) diff --git a/base/experimental.jl b/base/experimental.jl index c599d973b0a76..8dbdcacd65376 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -254,7 +254,7 @@ When issuing a hint, the output should typically start with `\\n`. If you define custom exception types, your `showerror` method can support hints by calling [`Experimental.show_error_hints`](@ref). -# Example +# Examples ``` julia> module Hinter diff --git a/base/exports.jl b/base/exports.jl index b1b84539c07a3..fbb5b449719d6 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -65,6 +65,7 @@ export Missing, NTuple, IdDict, + IdSet, OrdinalRange, Pair, PartialQuickSort, diff --git a/base/expr.jl b/base/expr.jl index 39da1408a77b3..b90f75e75a76f 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -831,7 +831,7 @@ end Tells the compiler to infer `f` using the declared types of `@nospecialize`d arguments. This can be used to limit the number of compiler-generated specializations during inference. -# Example +# Examples ```julia julia> f(A::AbstractArray) = g(A) diff --git a/base/filesystem.jl b/base/filesystem.jl index d9760ec08a8a9..ee6fde982caab 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -4,6 +4,45 @@ module Filesystem +""" + JL_O_APPEND + JL_O_ASYNC + JL_O_CLOEXEC + JL_O_CREAT + JL_O_DIRECT + JL_O_DIRECTORY + JL_O_DSYNC + JL_O_EXCL + JL_O_FSYNC + JL_O_LARGEFILE + JL_O_NDELAY + JL_O_NOATIME + JL_O_NOCTTY + JL_O_NOFOLLOW + JL_O_NONBLOCK + JL_O_PATH + JL_O_RANDOM + JL_O_RDONLY + JL_O_RDWR + JL_O_RSYNC + JL_O_SEQUENTIAL + JL_O_SHORT_LIVED + JL_O_SYNC + JL_O_TEMPORARY + JL_O_TMPFILE + JL_O_TRUNC + JL_O_WRONLY + +Enum constant for the `open` syscall, where `JL_O_*` corresponds to the `O_*` constant. +See [the libuv docs](https://docs.libuv.org/en/v1.x/fs.html#file-open-constants) for more details. +""" +(:JL_O_APPEND, :JL_O_ASYNC, :JL_O_CLOEXEC, :JL_O_CREAT, :JL_O_DIRECT, + :JL_O_DIRECTORY, :JL_O_DSYNC, :JL_O_EXCL, :JL_O_FSYNC, :JL_O_LARGEFILE, + :JL_O_NOATIME, :JL_O_NOCTTY, :JL_O_NDELAY, :JL_O_NOFOLLOW, :JL_O_NONBLOCK, + :JL_O_PATH, :JL_O_RANDOM, :JL_O_RDONLY, :JL_O_RDWR, :JL_O_RSYNC, + :JL_O_SEQUENTIAL, :JL_O_SHORT_LIVED, :JL_O_SYNC, :JL_O_TEMPORARY, + :JL_O_TMPFILE, :JL_O_TRUNC, :JL_O_WRONLY) + const S_IFDIR = 0o040000 # directory const S_IFCHR = 0o020000 # character device const S_IFBLK = 0o060000 # block device @@ -31,6 +70,36 @@ const S_IWOTH = 0o0002 # write by other const S_IXOTH = 0o0001 # execute by other const S_IRWXO = 0o0007 # mask for other permissions +""" + S_IRUSR + S_IWUSR + S_IXUSR + S_IRGRP + S_IWGRP + S_IXGRP + S_IROTH + S_IWOTH + S_IXOTH + +Constants for file access permission bits. +The general structure is `S_I[permission][class]` +where `permission` is `R` for read, `W` for write, and `X` for execute, +and `class` is `USR` for user/owner, `GRP` for group, and `OTH` for other. +""" +(:S_IRUSR, :S_IWUSR, :S_IXUSR, :S_IRGRP, :S_IWGRP, :S_IXGRP, :S_IROTH, :S_IWOTH, :S_IXOTH) + +""" + S_IRWXU + S_IRWXG + S_IRWXO + +Constants for file access permission masks, i.e. the combination of read, write, +and execute permissions for a class. +The general structure is `S_IRWX[class]` +where `class` is `U` for user/owner, `G` for group, and `O` for other. +""" +(:S_IRWXU, :S_IRWXG, :S_IRWXO) + export File, StatStruct, # open, @@ -48,7 +117,6 @@ export File, JL_O_SEQUENTIAL, JL_O_RANDOM, JL_O_NOCTTY, - JL_O_NOCTTY, JL_O_NONBLOCK, JL_O_NDELAY, JL_O_SYNC, @@ -195,9 +263,13 @@ end function read(f::File, ::Type{UInt8}) check_open(f) - ret = ccall(:jl_fs_read_byte, Int32, (OS_HANDLE,), f.handle) + p = Ref{UInt8}() + ret = ccall(:jl_fs_read, Int32, (OS_HANDLE, Ptr{Cvoid}, Csize_t), + f.handle, p, 1) uv_error("read", ret) - return ret % UInt8 + @assert ret <= sizeof(p) == 1 + ret < 1 && throw(EOFError()) + return p[] % UInt8 end function read(f::File, ::Type{Char}) diff --git a/base/float.jl b/base/float.jl index 5e40652490835..64dcb8b807550 100644 --- a/base/float.jl +++ b/base/float.jl @@ -14,6 +14,8 @@ const Inf16 = bitcast(Float16, 0x7c00) NaN16 A not-a-number value of type [`Float16`](@ref). + +See also: [`NaN`](@ref). """ const NaN16 = bitcast(Float16, 0x7e00) """ @@ -26,6 +28,8 @@ const Inf32 = bitcast(Float32, 0x7f800000) NaN32 A not-a-number value of type [`Float32`](@ref). + +See also: [`NaN`](@ref). """ const NaN32 = bitcast(Float32, 0x7fc00000) const Inf64 = bitcast(Float64, 0x7ff0000000000000) @@ -69,9 +73,23 @@ NaN julia> Inf - Inf NaN -julia> NaN == NaN, isequal(NaN, NaN), NaN === NaN +julia> NaN == NaN, isequal(NaN, NaN), isnan(NaN) (false, true, true) ``` + +!!! note + Always use [`isnan`](@ref) or [`isequal`](@ref) for checking for `NaN`. + Using `x === NaN` may give unexpected results: + ```julia-repl + julia> reinterpret(UInt32, NaN32) + 0x7fc00000 + + julia> NaN32p1 = reinterpret(Float32, 0x7fc00001) + NaN32 + + julia> NaN32p1 === NaN32, isequal(NaN32p1, NaN32), isnan(NaN32p1) + (false, true, true) + ``` """ NaN, NaN64 diff --git a/base/gcutils.jl b/base/gcutils.jl index 25f098e407223..3b8c4cf4ede10 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -70,7 +70,6 @@ end A finalizer may be registered at object construction. In the following example note that we implicitly rely on the finalizer returning the newly created mutable struct `x`. -# Example ```julia mutable struct MyMutableStruct bar diff --git a/base/iddict.jl b/base/iddict.jl index 73f532af9bba6..9c133d5ba23c6 100644 --- a/base/iddict.jl +++ b/base/iddict.jl @@ -4,11 +4,12 @@ IdDict([itr]) `IdDict{K,V}()` constructs a hash table using [`objectid`](@ref) as hash and -`===` as equality with keys of type `K` and values of type `V`. +`===` as equality with keys of type `K` and values of type `V`. See [`Dict`](@ref) +for further help and [`IdSet`](@ref) for the set version of this. -See [`Dict`](@ref) for further help. In the example below, The `Dict` -keys are all `isequal` and therefore get hashed the same, so they get overwritten. -The `IdDict` hashes by object-id, and thus preserves the 3 different keys. +In the example below, the `Dict` keys are all `isequal` and therefore get hashed +the same, so they get overwritten. The `IdDict` hashes by object-id, and thus +preserves the 3 different keys. # Examples ```julia-repl @@ -53,18 +54,7 @@ IdDict(ps::Pair{K}...) where {K} = IdDict{K,Any}(ps) IdDict(ps::(Pair{K,V} where K)...) where {V} = IdDict{Any,V}(ps) IdDict(ps::Pair...) = IdDict{Any,Any}(ps) -function IdDict(kv) - try - dict_with_eltype((K, V) -> IdDict{K, V}, kv, eltype(kv)) - catch - if !applicable(iterate, kv) || !all(x->isa(x,Union{Tuple,Pair}),kv) - throw(ArgumentError( - "IdDict(kv): kv needs to be an iterator of tuples or pairs")) - else - rethrow() - end - end -end +IdDict(kv) = dict_with_eltype((K, V) -> IdDict{K, V}, kv, eltype(kv)) empty(d::IdDict, ::Type{K}, ::Type{V}) where {K, V} = IdDict{K,V}() diff --git a/base/idset.jl b/base/idset.jl index 6e0b7a85a5b23..23f9ca009af0c 100644 --- a/base/idset.jl +++ b/base/idset.jl @@ -1,5 +1,28 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + IdSet{T}([itr]) + IdSet() + +IdSet{T}() constructs a set (see [`Set`](@ref)) using +`===` as equality with values of type `V`. + +In the example below, the values are all `isequal` so they get overwritten. +The `IdSet` compares by `===` so preserves the 3 different keys. + +Examples +≡≡≡≡≡≡≡≡ + +julia> Set(Any[true, 1, 1.0]) +Set{Any} with 1 element: + 1.0 + +julia> IdSet{Any}(Any[true, 1, 1.0]) +IdSet{Any} with 3 elements: + 1.0 + 1 + true +""" mutable struct IdSet{K} <: AbstractSet{K} list::Memory{Any} idxs::Union{Memory{UInt8}, Memory{UInt16}, Memory{UInt32}} diff --git a/base/indices.jl b/base/indices.jl index 9f2115e692564..0bd46f9787dab 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -464,7 +464,7 @@ julia> extrema(b) Return a `LinearIndices` array with the specified shape or [`axes`](@ref). -# Example +# Examples The main purpose of this constructor is intuitive conversion from cartesian to linear indexing: diff --git a/base/libdl.jl b/base/libdl.jl index bd909bb7b90eb..199d847572ca4 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -130,7 +130,7 @@ end Wrapper for usage with `do` blocks to automatically close the dynamic library once control flow leaves the `do` block scope. -# Example +# Examples ```julia vendor = dlopen("libblas") do lib if Libdl.dlsym(lib, :openblas_set_num_threads; throw_error=false) !== nothing @@ -234,7 +234,7 @@ end Get the full path of the library `libname`. -# Example +# Examples ```julia-repl julia> dlpath("libjulia") ``` diff --git a/base/loading.jl b/base/loading.jl index 34d1e848ecb98..5f0ea1859bc0f 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2121,6 +2121,10 @@ function _require(pkg::PkgId, env=nothing) end end + if JLOptions().use_compiled_modules == 3 + error("Precompiled image $pkg not available with flags $(CacheFlags())") + end + # if the module being required was supposed to have a particular version # but it was not handled by the precompile loader, complain for (concrete_pkg, concrete_build_id) in _concrete_dependencies @@ -2331,7 +2335,7 @@ and return the value of the last expression. The optional `args` argument can be used to set the input arguments of the script (i.e. the global `ARGS` variable). Note that definitions (e.g. methods, globals) are evaluated in the anonymous module and do not affect the current module. -# Example +# Examples ```jldoctest julia> write("testfile.jl", \"\"\" @@ -2508,6 +2512,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o:: # write data over stdin to avoid the (unlikely) case of exceeding max command line size write(io.in, """ empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated + Base.track_nested_precomp($(vcat(Base.precompilation_stack, pkg))) Base.precompiling_extension = $(loading_extension) Base.include_package_for_output($(pkg_str(pkg)), $(repr(abspath(input))), $(repr(depot_path)), $(repr(dl_load_path)), $(repr(load_path)), $deps, $(repr(source_path(nothing)))) @@ -2516,6 +2521,18 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o:: return io end +const precompilation_stack = Vector{PkgId}() +# Helpful for debugging when precompilation is unexpectedly nested. +# Enable with `JULIA_DEBUG=nested_precomp`. Note that it expected to be nested in classical code-load precompilation +# TODO: Add detection if extension precompilation is nested and error / return early? +function track_nested_precomp(pkgs::Vector{PkgId}) + append!(precompilation_stack, pkgs) + if length(precompilation_stack) > 1 + list() = join(map(p->p.name, precompilation_stack), " > ") + @debug "Nested precompilation: $(list())" _group=:nested_precomp + end +end + function compilecache_dir(pkg::PkgId) entrypath, entryfile = cache_file_entry(pkg) return joinpath(DEPOT_PATH[1], entrypath) @@ -3541,7 +3558,7 @@ Macro to obtain the absolute path of the current directory as a string. If in a script, returns the directory of the script containing the `@__DIR__` macrocall. If run from a REPL or if evaluated by `julia -e `, returns the current working directory. -# Example +# Examples The example illustrates the difference in the behaviors of `@__DIR__` and `pwd()`, by creating a simple script in a different directory than the current working one and executing both commands: diff --git a/base/logging.jl b/base/logging.jl index 1853caa16148c..436d00335acf3 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -608,7 +608,7 @@ end Execute `function`, directing all log messages to `logger`. -# Example +# Examples ```julia function test(x) diff --git a/base/math.jl b/base/math.jl index b0870c60016f7..0071d427fbbac 100644 --- a/base/math.jl +++ b/base/math.jl @@ -177,7 +177,7 @@ a Goertzel-like [^DK62] algorithm if `x` is complex. !!! compat "Julia 1.4" This function requires Julia 1.4 or later. -# Example +# Examples ```jldoctest julia> evalpoly(2, (1, 2, 3)) 17 diff --git a/base/meta.jl b/base/meta.jl index 545b1dbf5243b..bc07a7efa6c74 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -461,4 +461,45 @@ end _instantiate_type_in_env(x, spsig, spvals) = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), x, spsig, spvals) +""" + Meta.unblock(expr) + +Peel away redundant block expressions. + +Specifically, the following expressions are stripped by this function: +- `:block` expressions with a single non-line-number argument. +- Pairs of `:var"hygienic-scope"` / `:escape` expressions. +""" +function unblock(@nospecialize ex) + while isexpr(ex, :var"hygienic-scope") + isexpr(ex.args[1], :escape) || break + ex = ex.args[1].args[1] + end + isexpr(ex, :block) || return ex + exs = filter(ex -> !(isa(ex, LineNumberNode) || isexpr(ex, :line)), ex.args) + length(exs) == 1 || return ex + return unblock(exs[1]) +end + +""" + Meta.unescape(expr) + +Peel away `:escape` expressions and redundant block expressions (see +[`unblock`](@ref)). +""" +function unescape(@nospecialize ex) + ex = unblock(ex) + while isexpr(ex, :escape) || isexpr(ex, :var"hygienic-scope") + ex = unblock(ex.args[1]) + end + return ex +end + +""" + Meta.uncurly(expr) + +Turn `T{P...}` into just `T`. +""" +uncurly(@nospecialize ex) = isexpr(ex, :curly) ? ex.args[1] : ex + end # module diff --git a/base/namedtuple.jl b/base/namedtuple.jl index cc82edf3d3e3a..cbcade94f1c0d 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -182,6 +182,7 @@ nextind(@nospecialize(t::NamedTuple), i::Integer) = Int(i)+1 convert(::Type{NT}, nt::NT) where {names, NT<:NamedTuple{names}} = nt convert(::Type{NT}, nt::NT) where {names, T<:Tuple, NT<:NamedTuple{names,T}} = nt +convert(::Type{NT}, t::Tuple) where {NT<:NamedTuple} = NT(t) function convert(::Type{NamedTuple{names,T}}, nt::NamedTuple{names}) where {names,T<:Tuple} NamedTuple{names,T}(T(nt))::NamedTuple{names,T} diff --git a/base/operators.jl b/base/operators.jl index 2138888c82d9f..3d5ad705ed99a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1242,7 +1242,7 @@ it into the original function. This is useful as an adaptor to pass a multi-argument function in a context that expects a single argument, but passes a tuple as that single argument. -# Example usage: +# Examples ```jldoctest julia> map(splat(+), zip(1:3,4:6)) 3-element Vector{Int64}: diff --git a/base/path.jl b/base/path.jl index 80886f7ba09e6..211526b67d32c 100644 --- a/base/path.jl +++ b/base/path.jl @@ -435,11 +435,11 @@ normpath(a::AbstractString, b::AbstractString...) = normpath(joinpath(a,b...)) Convert a path to an absolute path by adding the current directory if necessary. Also normalizes the path as in [`normpath`](@ref). -# Example +# Examples If you are in a directory called `JuliaExample` and the data you are using is two levels up relative to the `JuliaExample` directory, you could write: -abspath("../../data") + abspath("../../data") Which gives a path like `"/home/JuliaUser/data/"`. diff --git a/base/process.jl b/base/process.jl index 24e676138bfae..fbc4acfd83e80 100644 --- a/base/process.jl +++ b/base/process.jl @@ -114,6 +114,7 @@ end handle = Libc.malloc(_sizeof_uv_process) disassociate_julia_struct(handle) (; exec, flags, env, dir) = cmd + flags ⊻= UV_PROCESS_WINDOWS_DISABLE_EXACT_NAME # libuv inverts the default for this, so flip this bit now iolock_begin() err = ccall(:jl_spawn, Int32, (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, diff --git a/base/range.jl b/base/range.jl index e7d57fa3c7e85..9480b46d8fcf1 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1393,8 +1393,8 @@ sort!(r::AbstractUnitRange) = r sort(r::AbstractRange) = issorted(r) ? r : reverse(r) -sortperm(r::AbstractUnitRange) = 1:length(r) -sortperm(r::AbstractRange) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1) +sortperm(r::AbstractUnitRange) = eachindex(r) +sortperm(r::AbstractRange) = issorted(r) ? (firstindex(r):1:lastindex(r)) : (lastindex(r):-1:firstindex(r)) function sum(r::AbstractRange{<:Real}) l = length(r) diff --git a/base/reflection.jl b/base/reflection.jl index 8c3ec226d6e22..65a46242c389d 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -89,7 +89,7 @@ since it is not idiomatic to explicitly mark names from `Main` as public. `names` will return symbols marked with `public` or `export`, even if they are not defined in the module. -See also: [`isexported`](@ref), [`ispublic`](@ref), [`@locals`](@ref Base.@locals), [`@__MODULE__`](@ref). +See also: [`Base.isexported`](@ref), [`Base.ispublic`](@ref), [`Base.@locals`](@ref), [`@__MODULE__`](@ref). """ names(m::Module; all::Bool = false, imported::Bool = false) = sort!(unsorted_names(m; all, imported)) @@ -880,6 +880,9 @@ issingletontype(@nospecialize(t)) = (@_total_meta; isa(t, DataType) && isdefined Compute a type that contains the intersection of `T` and `S`. Usually this will be the smallest such type or one close to it. + +A special case where exact behavior is guaranteed: when `T <: S`, +`typeintersect(S, T) == T == typeintersect(T, S)`. """ typeintersect(@nospecialize(a), @nospecialize(b)) = (@_total_meta; ccall(:jl_type_intersection, Any, (Any, Any), a::Type, b::Type)) @@ -1061,7 +1064,7 @@ fieldtypes(T::Type) = (@_foldable_meta; ntupleany(i -> fieldtype(T, i), fieldcou Return a collection of all instances of the given type, if applicable. Mostly used for enumerated types (see `@enum`). -# Example +# Examples ```jldoctest julia> @enum Color red blue green @@ -1332,6 +1335,15 @@ function method_instances(@nospecialize(f), @nospecialize(t), world::UInt) return results end +function method_instance(@nospecialize(f), @nospecialize(t); + world=Base.get_world_counter(), method_table=nothing) + tt = signature_type(f, t) + mi = ccall(:jl_method_lookup_by_tt, Any, + (Any, Csize_t, Any), + tt, world, method_table) + return mi::Union{Nothing, MethodInstance} +end + default_debug_info_kind() = unsafe_load(cglobal(:jl_default_debug_info_kind, Cint)) # this type mirrors jl_cgparams_t (documented in julia.h) @@ -1546,7 +1558,7 @@ internals. - `interp::Core.Compiler.AbstractInterpreter = Core.Compiler.NativeInterpreter(world)`: optional, controls the abstract interpreter to use, use the native interpreter if not specified. -# Example +# Examples One can put the argument types in a tuple to get the corresponding `code_typed`. @@ -1654,7 +1666,7 @@ internals. If it is an integer, it specifies the number of passes to run. If it is `nothing` (default), all passes are run. -# Example +# Examples One can put the argument types in a tuple to get the corresponding `code_ircode`. @@ -1752,7 +1764,7 @@ candidates for `f` and `types` (see also [`methods(f, types)`](@ref methods). methods matching with the given `f` and `types`. The list's order matches the order returned by `methods(f, types)`. -# Example +# Examples ```julia julia> Base.return_types(sum, Tuple{Vector{Int}}) @@ -1821,7 +1833,7 @@ Returns an inferred return type of the function call specified by `f` and `types It returns a single return type, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> checksym(::Symbol) = :symbol; @@ -1892,7 +1904,7 @@ It works like [`Base.return_types`](@ref), but it infers the exception types ins methods matching with the given `f` and `types`. The list's order matches the order returned by `methods(f, types)`. -# Example +# Examples ```julia julia> throw_if_number(::Number) = error("number is given"); @@ -1975,7 +1987,7 @@ Returns the type of exception potentially thrown by the function call specified It returns a single exception type, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> f1(x) = x * 2; @@ -2059,7 +2071,7 @@ Returns the possible computation effects of the function call specified by `f` a It returns a single effect, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> f1(x) = x * 2; diff --git a/base/secretbuffer.jl b/base/secretbuffer.jl index 61eeffdb4f18d..bf37c3caa6c23 100644 --- a/base/secretbuffer.jl +++ b/base/secretbuffer.jl @@ -200,7 +200,7 @@ resetting its pointer and size. This function is used to securely erase the sensitive data held in the buffer, reducing the potential for information leaks. -# Example +# Examples ```julia s = SecretBuffer() write(s, 's', 'e', 'c', 'r', 'e', 't') diff --git a/base/set.jl b/base/set.jl index 76502ee9d22ef..6b0c933f79faa 100644 --- a/base/set.jl +++ b/base/set.jl @@ -201,7 +201,7 @@ end unique(itr) Return an array containing only the unique elements of collection `itr`, -as determined by [`isequal`](@ref), in the order that the first of each +as determined by [`isequal`](@ref) and [`hash`](@ref), in the order that the first of each set of equivalent elements originally appears. The element type of the input is preserved. @@ -436,7 +436,7 @@ end """ unique!(A::AbstractVector) -Remove duplicate items as determined by [`isequal`](@ref), then return the modified `A`. +Remove duplicate items as determined by [`isequal`](@ref) and [`hash`](@ref), then return the modified `A`. `unique!` will return the elements of `A` in the order that they occur. If you do not care about the order of the returned data, then calling `(sort!(A); unique!(A))` will be much more efficient as long as the elements of `A` can be sorted. diff --git a/base/shell.jl b/base/shell.jl index dd4533c182534..9f15550a1aa59 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -416,7 +416,7 @@ rather than returned as a string. See also [`escape_microsoft_c_args`](@ref), [`shell_escape_posixly`](@ref). -# Example +# Examples ```jldoctest julia> Base.shell_escape_wincmd("a^\\"^o\\"^u\\"") "a^^\\"^o\\"^^u^\\"" diff --git a/base/show.jl b/base/show.jl index 8c59bb3bd9f6d..a5bf5f73ba0ed 100644 --- a/base/show.jl +++ b/base/show.jl @@ -3174,7 +3174,7 @@ representing argument `x` in terms of its type. (The double-colon is omitted if `toplevel=true`.) However, you can specialize this function for specific types to customize printing. -# Example +# Examples A SubArray created as `view(a, :, 3, 2:5)`, where `a` is a 3-dimensional Float64 array, has type diff --git a/base/slicearray.jl b/base/slicearray.jl index de4272550bdb0..215cf13f9651e 100644 --- a/base/slicearray.jl +++ b/base/slicearray.jl @@ -96,7 +96,7 @@ See also [`eachrow`](@ref), [`eachcol`](@ref), [`mapslices`](@ref) and [`selectd !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator, and only a single dimension `dims` was supported. -# Example +# Examples ```jldoctest julia> m = [1 2 3; 4 5 6; 7 8 9] @@ -144,7 +144,7 @@ See also [`eachcol`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref). !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator. -# Example +# Examples ```jldoctest julia> a = [1 2; 3 4] @@ -182,7 +182,7 @@ See also [`eachrow`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref). !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator. -# Example +# Examples ```jldoctest julia> a = [1 2; 3 4] diff --git a/base/strings/annotated.jl b/base/strings/annotated.jl index f84a85eaf62ab..d67ac70d8c684 100644 --- a/base/strings/annotated.jl +++ b/base/strings/annotated.jl @@ -45,7 +45,7 @@ AnnotatedString(s::S<:AbstractString, annotations::Vector{Tuple{UnitRange{Int}, A AnnotatedString can also be created with [`annotatedstring`](@ref), which acts much like [`string`](@ref) but preserves any annotations present in the arguments. -# Example +# Examples ```julia-repl julia> AnnotatedString("this is an example annotated string", diff --git a/base/strings/util.jl b/base/strings/util.jl index b5eb9185c3766..219b329d7924d 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -1,13 +1,23 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -const Chars = Union{AbstractChar,Tuple{Vararg{AbstractChar}},AbstractVector{<:AbstractChar},Set{<:AbstractChar}} +""" + Base.Chars = Union{AbstractChar,Tuple{Vararg{AbstractChar}},AbstractVector{<:AbstractChar},AbstractSet{<:AbstractChar}} + +An alias type for a either single character or a tuple/vector/set of characters, used to describe arguments +of several string-matching functions such as [`startswith`](@ref) and [`strip`](@ref). + +!!! compat "Julia 1.11" + Julia versions prior to 1.11 only included `Set`, not `AbstractSet`, in `Base.Chars` types. +""" +const Chars = Union{AbstractChar,Tuple{Vararg{AbstractChar}},AbstractVector{<:AbstractChar},AbstractSet{<:AbstractChar}} # starts with and ends with predicates """ - startswith(s::AbstractString, prefix::AbstractString) + startswith(s::AbstractString, prefix::Union{AbstractString,Base.Chars}) -Return `true` if `s` starts with `prefix`. If `prefix` is a vector or set +Return `true` if `s` starts with `prefix`, which can be a string, a character, +or a tuple/vector/set of characters. If `prefix` is a tuple/vector/set of characters, test whether the first character of `s` belongs to that set. See also [`endswith`](@ref), [`contains`](@ref). @@ -30,10 +40,11 @@ end startswith(str::AbstractString, chars::Chars) = !isempty(str) && first(str)::AbstractChar in chars """ - endswith(s::AbstractString, suffix::AbstractString) + endswith(s::AbstractString, suffix::Union{AbstractString,Base.Chars}) -Return `true` if `s` ends with `suffix`. If `suffix` is a vector or set of -characters, test whether the last character of `s` belongs to that set. +Return `true` if `s` ends with `suffix`, which can be a string, a character, +or a tuple/vector/set of characters. If `suffix` is a tuple/vector/set +of characters, test whether the last character of `s` belongs to that set. See also [`startswith`](@ref), [`contains`](@ref). @@ -70,7 +81,8 @@ end """ startswith(io::IO, prefix::Union{AbstractString,Base.Chars}) -Check if an `IO` object starts with a prefix. See also [`peek`](@ref). +Check if an `IO` object starts with a prefix, which can be either a string, a +character, or a tuple/vector/set of characters. See also [`peek`](@ref). """ function Base.startswith(io::IO, prefix::Base.Chars) mark(io) diff --git a/base/terminfo.jl b/base/terminfo.jl index b8cfef85df193..3792e35e0fd8d 100644 --- a/base/terminfo.jl +++ b/base/terminfo.jl @@ -303,19 +303,50 @@ end Return a boolean signifying whether the current terminal supports 24-bit colors. -This uses the `COLORTERM` environment variable if possible, returning true if it -is set to either `"truecolor"` or `"24bit"`. - -As a fallback, first on unix systems the `colors` terminal capability is checked -— should more than 256 colors be reported, this is taken to signify 24-bit -support. +Multiple conditions are taken as signifying truecolor support, specifically any of the following: +- The `COLORTERM` environment variable is set to `"truecolor"` or `"24bit"` +- The current terminfo sets the [`RGB`[^1] + capability](https://invisible-island.net/ncurses/man/user_caps.5.html#h3-Recognized-Capabilities) + (or the legacy `Tc` capability[^2]) flag +- The current terminfo provides `setrgbf` and `setrgbb` strings[^3] +- The current terminfo has a `colors` number greater that `256`, on a unix system +- The VTE version is at least 3600 (detected via the `VTE_VERSION` environment variable) +- The current terminal has the `XTERM_VERSION` environment variable set +- The current terminal appears to be iTerm according to the `TERMINAL_PROGRAM` environment variable +- The `TERM` environment variable corresponds to: linuxvt, rxvt, or st + +[^1]: Added to Ncurses 6.1, and used in `TERM=*-direct` terminfos. +[^2]: Convention [added to tmux in 2016](https://github.com/tmux/tmux/commit/427b8204268af5548d09b830e101c59daa095df9), + superseded by `RGB`. +[^3]: Proposed by [Rüdiger Sonderfeld in 2013](https://lists.gnu.org/archive/html/bug-ncurses/2013-10/msg00007.html), + adopted by a few terminal emulators. + +!!! note + The set of conditions is messy, because the situation is a mess, and there's + no resolution in sight. `COLORTERM` is widely accepted, but an imperfect + solution because only `TERM` is passed across `ssh` sessions. Terminfo is + the obvious place for a terminal to declare capabilities, but it's taken + enough years for ncurses/terminfo to declare a standard capability (`RGB`) + that a number of other approaches have taken root. Furthermore, the official + `RGB` capability is *incompatible* with 256-color operation, and so is + unable to resolve the fragmentation in the terminal ecosystem. """ function ttyhastruecolor() + # Lasciate ogne speranza, voi ch'intrate get(ENV, "COLORTERM", "") ∈ ("truecolor", "24bit") || - @static if Sys.isunix() - get(current_terminfo, :colors, 0) > 256 - else - false + get(current_terminfo, :RGB, false) || get(current_terminfo, :Tc, false) || + (haskey(current_terminfo, :setrgbf) && haskey(current_terminfo, :setrgbb)) || + @static if Sys.isunix() get(current_terminfo, :colors, 0) > 256 else false end || + (Sys.iswindows() && Sys.windows_version() ≥ v"10.0.14931") || # See + something(tryparse(Int, get(ENV, "VTE_VERSION", "")), 0) >= 3600 || # Per GNOME bug #685759 + haskey(ENV, "XTERM_VERSION") || + get(ENV, "TERMINAL_PROGRAM", "") == "iTerm.app" || # Why does Apple need to be special? + haskey(ENV, "KONSOLE_PROFILE_NAME") || # Per commentary in VT102Emulation.cpp + haskey(ENV, "KONSOLE_DBUS_SESSION") || + let term = get(ENV, "TERM", "") + startswith(term, "linux") || # Linux 4.8+ supports true-colour SGR. + startswith(term, "rxvt") || # See + startswith(term, "st") # From experimentation end end diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index eef75916880da..56d596958bc7e 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -345,7 +345,7 @@ thread other than 1. In newly written library functions, `:static` scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads. -## Example +## Examples To illustrate of the different scheduling strategies, consider the following function `busywait` containing a non-yielding timed loop that runs for a given number of seconds. diff --git a/base/util.jl b/base/util.jl index 38e27520a39cc..a26a874c7a461 100644 --- a/base/util.jl +++ b/base/util.jl @@ -207,6 +207,7 @@ function julia_cmd(julia=joinpath(Sys.BINDIR, julia_exename()); cpu_target::Unio opts.can_inline == 0 && push!(addflags, "--inline=no") opts.use_compiled_modules == 0 && push!(addflags, "--compiled-modules=no") opts.use_compiled_modules == 2 && push!(addflags, "--compiled-modules=existing") + opts.use_compiled_modules == 3 && push!(addflags, "--compiled-modules=strict") opts.use_pkgimages == 0 && push!(addflags, "--pkgimages=no") opts.use_pkgimages == 2 && push!(addflags, "--pkgimages=existing") opts.opt_level == 2 || push!(addflags, "-O$(opts.opt_level)") @@ -374,7 +375,7 @@ then the user can enter just a newline character to select the `default`. See also `Base.winprompt` (for Windows) and `Base.getpass` for secure entry of passwords. -# Example +# Examples ```julia-repl julia> your_name = Base.prompt("Enter your name"); @@ -563,24 +564,31 @@ Stacktrace: macro kwdef(expr) expr = macroexpand(__module__, expr) # to expand @static isexpr(expr, :struct) || error("Invalid usage of @kwdef") - T = expr.args[2] + _, T, fieldsblock = expr.args if T isa Expr && T.head === :<: T = T.args[1] end - params_ex = Expr(:parameters) - call_args = Any[] + fieldnames = Any[] + defvals = Any[] + extract_names_and_defvals_from_kwdef_fieldblock!(fieldsblock, fieldnames, defvals) + parameters = map(fieldnames, defvals) do fieldname, defval + if isnothing(defval) + return fieldname + else + return Expr(:kw, fieldname, esc(defval)) + end + end - _kwdef!(expr.args[3], params_ex.args, call_args) # Only define a constructor if the type has fields, otherwise we'll get a stack # overflow on construction - if !isempty(params_ex.args) - if T isa Symbol - sig = :(($(esc(T)))($params_ex)) - call = :(($(esc(T)))($(call_args...))) - body = Expr(:block, __source__, call) + if !isempty(parameters) + T_no_esc = Meta.unescape(T) + if T_no_esc isa Symbol + sig = Expr(:call, esc(T), Expr(:parameters, parameters...)) + body = Expr(:block, __source__, Expr(:call, esc(T), fieldnames...)) kwdefs = Expr(:function, sig, body) - elseif isexpr(T, :curly) + elseif isexpr(T_no_esc, :curly) # if T == S{A<:AA,B<:BB}, define two methods # S(...) = ... # S{A,B}(...) where {A<:AA,B<:BB} = ... @@ -588,11 +596,11 @@ macro kwdef(expr) P = T.args[2:end] Q = Any[isexpr(U, :<:) ? U.args[1] : U for U in P] SQ = :($S{$(Q...)}) - body1 = Expr(:block, __source__, :(($(esc(S)))($(call_args...)))) - sig1 = :(($(esc(S)))($params_ex)) + body1 = Expr(:block, __source__, Expr(:call, esc(S), fieldnames...)) + sig1 = Expr(:call, esc(S), Expr(:parameters, parameters...)) def1 = Expr(:function, sig1, body1) - body2 = Expr(:block, __source__, :(($(esc(SQ)))($(call_args...)))) - sig2 = :(($(esc(SQ)))($params_ex) where {$(esc.(P)...)}) + body2 = Expr(:block, __source__, Expr(:call, esc(SQ), fieldnames...)) + sig2 = :($(Expr(:call, esc(SQ), Expr(:parameters, parameters...))) where {$(esc.(P)...)}) def2 = Expr(:function, sig2, body2) kwdefs = Expr(:block, def1, def2) else @@ -609,54 +617,44 @@ end # @kwdef helper function # mutates arguments inplace -function _kwdef!(blk, params_args, call_args) - for i in eachindex(blk.args) - ei = blk.args[i] - if ei isa Symbol - # var - push!(params_args, ei) - push!(call_args, ei) - elseif ei isa Expr - is_atomic = ei.head === :atomic - ei = is_atomic ? first(ei.args) : ei # strip "@atomic" and add it back later - is_const = ei.head === :const - ei = is_const ? first(ei.args) : ei # strip "const" and add it back later - # Note: `@atomic const ..` isn't valid, but reconstruct it anyway to serve a nice error - if ei isa Symbol - # const var - push!(params_args, ei) - push!(call_args, ei) - elseif ei.head === :(=) - lhs = ei.args[1] - if lhs isa Symbol - # var = defexpr - var = lhs - elseif lhs isa Expr && lhs.head === :(::) && lhs.args[1] isa Symbol - # var::T = defexpr - var = lhs.args[1] - else - # something else, e.g. inline inner constructor - # F(...) = ... - continue +function extract_names_and_defvals_from_kwdef_fieldblock!(block, names, defvals) + for (i, item) in pairs(block.args) + if isexpr(item, :block) + extract_names_and_defvals_from_kwdef_fieldblock!(item, names, defvals) + elseif item isa Expr && item.head in (:escape, :var"hygienic-scope") + n = length(names) + extract_names_and_defvals_from_kwdef_fieldblock!(item, names, defvals) + for j in n+1:length(defvals) + if !isnothing(defvals[j]) + defvals[j] = Expr(item.head, defvals[j]) end - defexpr = ei.args[2] # defexpr - push!(params_args, Expr(:kw, var, esc(defexpr))) - push!(call_args, var) - lhs = is_const ? Expr(:const, lhs) : lhs - lhs = is_atomic ? Expr(:atomic, lhs) : lhs - blk.args[i] = lhs # overrides arg - elseif ei.head === :(::) && ei.args[1] isa Symbol - # var::Typ - var = ei.args[1] - push!(params_args, var) - push!(call_args, var) - elseif ei.head === :block - # can arise with use of @static inside type decl - _kwdef!(ei, params_args, call_args) end + else + def, name, defval = @something(def_name_defval_from_kwdef_fielddef(item), continue) + block.args[i] = def + push!(names, name) + push!(defvals, defval) end end - blk +end + +function def_name_defval_from_kwdef_fielddef(kwdef) + if kwdef isa Symbol + return kwdef, kwdef, nothing + elseif isexpr(kwdef, :(::)) + name, _ = kwdef.args + return kwdef, Meta.unescape(name), nothing + elseif isexpr(kwdef, :(=)) + lhs, rhs = kwdef.args + def, name, _ = @something(def_name_defval_from_kwdef_fielddef(lhs), return nothing) + return def, name, rhs + elseif kwdef isa Expr && kwdef.head in (:const, :atomic) + def, name, defval = @something(def_name_defval_from_kwdef_fielddef(kwdef.args[1]), return nothing) + return Expr(kwdef.head, def), name, defval + elseif kwdef isa Expr && kwdef.head in (:escape, :var"hygienic-scope") + def, name, defval = @something(def_name_defval_from_kwdef_fielddef(kwdef.args[1]), return nothing) + return Expr(kwdef.head, def), name, isnothing(defval) ? defval : Expr(kwdef.head, defval) + end end # testing diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index b827f0d1495da..1a98bf1ee4333 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -54,17 +54,7 @@ WeakKeyDict(ps::Pair{K}...) where {K} = WeakKeyDict{K,Any}(ps) WeakKeyDict(ps::(Pair{K,V} where K)...) where {V} = WeakKeyDict{Any,V}(ps) WeakKeyDict(ps::Pair...) = WeakKeyDict{Any,Any}(ps) -function WeakKeyDict(kv) - try - Base.dict_with_eltype((K, V) -> WeakKeyDict{K, V}, kv, eltype(kv)) - catch - if !isiterable(typeof(kv)) || !all(x->isa(x,Union{Tuple,Pair}),kv) - throw(ArgumentError("WeakKeyDict(kv): kv needs to be an iterator of tuples or pairs")) - else - rethrow() - end - end -end +WeakKeyDict(kv) = Base.dict_with_eltype((K, V) -> WeakKeyDict{K, V}, kv, eltype(kv)) function _cleanup_locked(h::WeakKeyDict) if h.dirty diff --git a/contrib/pgo-lto/.gitignore b/contrib/pgo-lto/.gitignore new file mode 100644 index 0000000000000..978d8f2ca86dd --- /dev/null +++ b/contrib/pgo-lto/.gitignore @@ -0,0 +1,4 @@ +profiles +stage0* +stage1* +stage2* diff --git a/contrib/pgo-lto/Makefile b/contrib/pgo-lto/Makefile new file mode 100644 index 0000000000000..a73825e182561 --- /dev/null +++ b/contrib/pgo-lto/Makefile @@ -0,0 +1,80 @@ +.PHONY: top clean clean-profiles + +STAGE0_BUILD:=$(CURDIR)/stage0.build +STAGE1_BUILD:=$(CURDIR)/stage1.build +STAGE2_BUILD:=$(CURDIR)/stage2.build + +STAGE0_TOOLS:=$(STAGE0_BUILD)/usr/tools/ + +PROFILE_DIR:=$(CURDIR)/profiles +PROFILE_FILE:=$(PROFILE_DIR)/merged.prof +PROFRAW_FILES:=$(wildcard $(PROFILE_DIR)/*.profraw) +JULIA_ROOT:=$(CURDIR)/../.. + +LLVM_CXXFILT:=$(STAGE0_TOOLS)llvm-cxxfilt +LLVM_PROFDATA:=$(STAGE0_TOOLS)llvm-profdata +LLVM_OBJCOPY:=$(STAGE0_TOOLS)llvm-objcopy + +# When building a single libLLVM.so we need to increase -vp-counters-per-site +# significantly +COUNTERS_PER_SITE:=6 + +AFTER_STAGE1_MESSAGE:='Run `make clean-profiles` to start with a clean slate. $\ + Then run Julia to collect realistic profile data, for example: `$(STAGE1_BUILD)/julia -O3 -e $\ + '\''using Pkg; Pkg.add("LoopVectorization"); Pkg.test("LoopVectorization")'\''`. This $\ + should produce about 15MB of data in $(PROFILE_DIR). Note that running extensive $\ + scripts may result in counter overflows, which can be detected by running $\ + `make top`. Afterwards run `make stage2`.' + +TOOLCHAIN_FLAGS = $\ + "CC=$(STAGE0_TOOLS)clang" $\ + "CXX=$(STAGE0_TOOLS)clang++" $\ + "LD=$(STAGE0_TOOLS)ld.lld" $\ + "AR=$(STAGE0_TOOLS)llvm-ar" $\ + "RANLIB=$(STAGE0_TOOLS)llvm-ranlib" $\ + "CFLAGS+=$(PGO_CFLAGS)" $\ + "CXXFLAGS+=$(PGO_CXXFLAGS)" $\ + "LDFLAGS+=$(PGO_LDFLAGS)" + +$(STAGE0_BUILD) $(STAGE1_BUILD) $(STAGE2_BUILD): + $(MAKE) -C $(JULIA_ROOT) O=$@ configure + +stage0: export USE_BINARYBUILDER_LLVM=1 +stage0: | $(STAGE0_BUILD) + # Turn [cd]tors into init/fini_array sections in libclang_rt, since lld + # doesn't do that, and otherwise the profile constructor is not executed + $(MAKE) -C $(STAGE0_BUILD)/deps install-clang install-llvm install-lld install-llvm-tools && \ + find $< -name 'libclang_rt.profile-*.a' -exec $(LLVM_OBJCOPY) --rename-section .ctors=.init_array --rename-section .dtors=.fini_array {} + && \ + touch $@ + +$(STAGE1_BUILD): stage0 +stage1: PGO_CFLAGS:=-fprofile-generate=$(PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) +stage1: PGO_CXXFLAGS:=-fprofile-generate=$(PROFILE_DIR) -Xclang -mllvm -Xclang -vp-counters-per-site=$(COUNTERS_PER_SITE) +stage1: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-generate=$(PROFILE_DIR) +stage1: export USE_BINARYBUILDER_LLVM=0 +stage1: | $(STAGE1_BUILD) + $(MAKE) -C $(STAGE1_BUILD) $(TOOLCHAIN_FLAGS) && touch $@ + @echo $(AFTER_STAGE1_MESSAGE) + +stage2: PGO_CFLAGS:=-fprofile-use=$(PROFILE_FILE) +stage2: PGO_CXXFLAGS:=-fprofile-use=$(PROFILE_FILE) +stage2: PGO_LDFLAGS:=-fuse-ld=lld -flto=thin -fprofile-use=$(PROFILE_FILE) -Wl,--icf=safe +stage2: export USE_BINARYBUILDER_LLVM=0 +stage2: $(PROFILE_FILE) | $(STAGE2_BUILD) + $(MAKE) -C $(STAGE2_BUILD) $(TOOLCHAIN_FLAGS) && touch $@ + +install: stage2 + $(MAKE) -C $(STAGE2_BUILD) USE_BINARYBUILDER_LLVM=0 install + +$(PROFILE_FILE): stage1 $(PROFRAW_FILES) + $(LLVM_PROFDATA) merge -output=$@ $(PROFRAW_FILES) + +# show top 50 functions +top: $(PROFILE_FILE) + $(LLVM_PROFDATA) show --topn=50 $< | $(LLVM_CXXFILT) + +clean-profiles: + rm -rf $(PROFILE_DIR) + +clean: + rm -f stage0 stage1 stage2 $(PROFILE_FILE) diff --git a/deps/checksums/gmp b/deps/checksums/gmp index c9f6deac6e19b..0c7dd415e6f16 100644 --- a/deps/checksums/gmp +++ b/deps/checksums/gmp @@ -1,60 +1,60 @@ -GMP.v6.2.1+6.aarch64-apple-darwin.tar.gz/md5/8123f7925ae9aa60b6998313b21a9db9 -GMP.v6.2.1+6.aarch64-apple-darwin.tar.gz/sha512/5c7927ecfd47409dd4116cd4209768294ba229b51472ed220da498823dc1e7f9100292ec4b3a990491acd27f16ce3a3dce7a7c6e20dcd515982a9c8e364d91bc -GMP.v6.2.1+6.aarch64-linux-gnu-cxx03.tar.gz/md5/0d0d2ee67cff251941e3474341280b34 -GMP.v6.2.1+6.aarch64-linux-gnu-cxx03.tar.gz/sha512/69fb2f1476e0bb73f89ad2f73b58ec4da1b99e099124666e6da93b7705fde23913daa59f2ad479f99fcb4f0df152603bb0ba4875420b583f01fded0fec280a15 -GMP.v6.2.1+6.aarch64-linux-gnu-cxx11.tar.gz/md5/86ba1313c8ab4ca1ae8313cbf96e1e7d -GMP.v6.2.1+6.aarch64-linux-gnu-cxx11.tar.gz/sha512/05c306c01d1b0e9e4dc7ce937075eeaede4e5e0791826a8892fae2eb73cdb7f22c4873cf31cea3cfe3db996ac77387346f4f8a851ce52c29883146678f3851fd -GMP.v6.2.1+6.aarch64-linux-musl-cxx03.tar.gz/md5/2fbbb9adee7db794f5888442b7b7688c -GMP.v6.2.1+6.aarch64-linux-musl-cxx03.tar.gz/sha512/d8a1719e529374d00ba6372013d0c7ddc9f44f9f6ee0f966b4ed16d731ce74c26b6e6a807403b3396bed67dd3e775e18c1e70c247a371d622a6e7013eb6b8905 -GMP.v6.2.1+6.aarch64-linux-musl-cxx11.tar.gz/md5/b6a8c494d4c90decb6eacbca3ce3f22a -GMP.v6.2.1+6.aarch64-linux-musl-cxx11.tar.gz/sha512/6798406e20cc4d58647c266a2b1b8d0670e62f19bf4bff991c39eef13cf92c043f00717e7289bcc00007d7e248e943b37ba2eef89c9e68c42e30f0e2be9dd589 -GMP.v6.2.1+6.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/a6866ee9784e9359e32dc18f417b2be7 -GMP.v6.2.1+6.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/548953ccc8444886316d4dfd7081783e397ec180e88a1d17a464e4b1d0a27f51ee7f6a1936ddab499db192d3cdfdc87d572731c5ab2f87d528609dabfccad2d3 -GMP.v6.2.1+6.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/6b78c826a4aedc8107c1bbfccbe5c097 -GMP.v6.2.1+6.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/e8c075c29e4d8a916f087faeb2db50168e1a5546fcb02fc841477cf82a39188c3b9e7703b5354d4842880b5ac7215a32d022abe08aacc5e23238b63c6b994af4 -GMP.v6.2.1+6.armv6l-linux-musleabihf-cxx03.tar.gz/md5/57e1a6c71b3c5b4047bf08bfc4d4f22d -GMP.v6.2.1+6.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/0f72c675ab3005ea183393bc4e5b4a157c13042367fd1bb3b03b3f7742e09604bddffb89f1478dc0dab4d992939519578549d05f9885b89319b0b51678b8a619 -GMP.v6.2.1+6.armv6l-linux-musleabihf-cxx11.tar.gz/md5/65a13f49cbdaa9d3a8e20d0b84bbc701 -GMP.v6.2.1+6.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/0487b18d1c9c59d990e6c4ec435b8dff91ae02d5d56c665b12aaaea105f7d2ab5beae9dfcbb133c990f70774b0d32e55df7f2e91e2d0a85c391a4090dcadf080 -GMP.v6.2.1+6.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/30e20c183153f8ce60e564b35e4b54bd -GMP.v6.2.1+6.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/41bdabc2610b46b215043e98eaddb2e2ad0695ae15f3088c9beef24a97864dce4088ae68993de928d952baaf123f279d74705664fffbf96be9b7436f1ba7692b -GMP.v6.2.1+6.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/5f2cba31677e6681666c0b6ebd33c3ad -GMP.v6.2.1+6.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/a89399bf84bebf4b8432e48aae6dce5547bb6f1c048364697c577541c4f1a555b976370634624e9cf039fcbcb70e449a2f55563f0a4f48e60ee4653a185cf7dd -GMP.v6.2.1+6.armv7l-linux-musleabihf-cxx03.tar.gz/md5/4a682d832109d7ab5743832f73ca33d2 -GMP.v6.2.1+6.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/d5062bd8eee926eb1177e70e5d9e8d6ed7a00a17c25d2b165b974c01aa79d45ca97e219b26ded752b5f323546192d595b838b474c61bdd87e641549db9e9ef5d -GMP.v6.2.1+6.armv7l-linux-musleabihf-cxx11.tar.gz/md5/caa51529cb1b6dc8db765e202e1b7737 -GMP.v6.2.1+6.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/d11ae870e68ca8d28bbcdf799a04769c3df2fbd169f6f2b16d88a556c40866b39636820ac3497e869086e638ba31dc1c87ec780add2d1aafe5e4ca178641678e -GMP.v6.2.1+6.i686-linux-gnu-cxx03.tar.gz/md5/dfcb024b9cfba37f80da5b7cc0c5b1ad -GMP.v6.2.1+6.i686-linux-gnu-cxx03.tar.gz/sha512/10eb086228b4250ecce11ad5bbec15e2bfff2429530cfd700602ead7f108163bc48fc83d9714443cbf5a93e7dd5f9046bdc15ef324486475f6b4be1cf34bad4b -GMP.v6.2.1+6.i686-linux-gnu-cxx11.tar.gz/md5/e889c1d65c9ca710c859129ae99ef322 -GMP.v6.2.1+6.i686-linux-gnu-cxx11.tar.gz/sha512/4d97ebdd6a12d39907ccc9bad00266e286c949b3f99a306c1c4a4380a292694d944f275c351d9ddf465d020c8197b3b19dfccb5080249c75e3f5ffb9aa77a1c4 -GMP.v6.2.1+6.i686-linux-musl-cxx03.tar.gz/md5/d57b3948e7a120bafeae67c28fe40869 -GMP.v6.2.1+6.i686-linux-musl-cxx03.tar.gz/sha512/88165c809a73007d2b5e750d23c619fbb088f6de200aae1dee34b5e3783949150d91b94774cd1881d2a621d092c0e7e7332707ed4737ff8426686dfce7e0313a -GMP.v6.2.1+6.i686-linux-musl-cxx11.tar.gz/md5/e3c53fc468a9f48f9d06fdf51eafae62 -GMP.v6.2.1+6.i686-linux-musl-cxx11.tar.gz/sha512/3c6a99acd84c226d7a48177c8e18624a677ea2a3df15fb2d54002eb5a6d55144b6f51f82ff491373366f32e92252fd14747503166621c2d2359029bdb1b20741 -GMP.v6.2.1+6.i686-w64-mingw32-cxx03.tar.gz/md5/64b9bed188f9a300200659efdb9facef -GMP.v6.2.1+6.i686-w64-mingw32-cxx03.tar.gz/sha512/f7ed47cc29be31f99e612abd1db0d806ece84c117677cd639e04e2f6b08bbbfa4056ed9504bb073ec5f722de6955db668934f3d3ca05ddde0f22b096afcea2e3 -GMP.v6.2.1+6.i686-w64-mingw32-cxx11.tar.gz/md5/a8f38cefb46dc9c3faddfd597d0e1a4c -GMP.v6.2.1+6.i686-w64-mingw32-cxx11.tar.gz/sha512/f02c3458c05869fab493d9be5ea98390baf6eed136fe2916cd6214c4f24a6f22d0716d59f352454fd4c799df71a8fd90e3a169644e1c6ffe89f3620f2a52f158 -GMP.v6.2.1+6.powerpc64le-linux-gnu-cxx03.tar.gz/md5/7f8da2b7e16ef4cb593fea4bdb2e43eb -GMP.v6.2.1+6.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/d0105fe7dfcc1daf7024d2f58b53240bab473c3ae44a904833d009beeb8e41f5487430f68e79bd79fc5c74b55f1111eb7479fedc84bcb45fe4dff3d8c3ac3e4f -GMP.v6.2.1+6.powerpc64le-linux-gnu-cxx11.tar.gz/md5/31fb7b6e37c650f0b8c3a2d475cb2b5b -GMP.v6.2.1+6.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/d03f3f1303996008ff267682de5b9d6e3be78ca1b0d6aa7cadbf4a612b331fe70460b689125f4ededa1c6078092ad3dafaad32c68a98d31713764a7a7461cf98 -GMP.v6.2.1+6.x86_64-apple-darwin.tar.gz/md5/9276d90b4f850f167f673f731c7d3781 -GMP.v6.2.1+6.x86_64-apple-darwin.tar.gz/sha512/f914452a49988b0694915483547c2f878c0ba71be2079fd1228b3e583cb08e92d8c958a052f29025054ded74cacb699893a5a6ef27749c851e83607ad3f1fe8f -GMP.v6.2.1+6.x86_64-linux-gnu-cxx03.tar.gz/md5/cded149fcef93ab1ba89c51d7cc58b73 -GMP.v6.2.1+6.x86_64-linux-gnu-cxx03.tar.gz/sha512/8f97582d6323df6f86e3079b9a2534425bd4e64bb4cec337c21059605d50c1220fd006e55bdb34e8aa7195cd79ef518f1541c1b1a92187ed928f7939b3128dd6 -GMP.v6.2.1+6.x86_64-linux-gnu-cxx11.tar.gz/md5/0529bb60dcf584222cd91e9e11510f24 -GMP.v6.2.1+6.x86_64-linux-gnu-cxx11.tar.gz/sha512/0532821e81a4e51363570f87ec59c37dea24cab59a94e43127837ce4b388d1951853d50e52d4c9f30b4a21cfe222e368207239ce8ac0f1ee1e9375f51fb10127 -GMP.v6.2.1+6.x86_64-linux-musl-cxx03.tar.gz/md5/2d332d096da5515581ee92128aff88ab -GMP.v6.2.1+6.x86_64-linux-musl-cxx03.tar.gz/sha512/b17f7b762bd4d61fa4c4be8124275c2b337383da167bdeaca34e44d71f20716b182b46bc5a6714a798a0951d73b335ab9c87f451cf4c5456edbe76cf3ad36ba4 -GMP.v6.2.1+6.x86_64-linux-musl-cxx11.tar.gz/md5/a9dae953f9d59589162a3ea149c46d1e -GMP.v6.2.1+6.x86_64-linux-musl-cxx11.tar.gz/sha512/31e568aba38a29ec6713dda9eb1c7d7b50c2a736e8883ae8ff2eaf16840b15c93e6dc53025e7750d3ac3e4ffc7d2c91787bda5b799ecfdeea3d928657176b1b3 -GMP.v6.2.1+6.x86_64-unknown-freebsd.tar.gz/md5/6f42d7486fa85ce1bf0cac409d1dd5ae -GMP.v6.2.1+6.x86_64-unknown-freebsd.tar.gz/sha512/5111751619388e51d1b3c0e32548a6de0aa02b7967994a4b4b78cdc9e0e852dae9d78bf48a503a6fb67e3b08343ddcf5a9f0b7a64a803c4d5067d69e4cb2edee -GMP.v6.2.1+6.x86_64-w64-mingw32-cxx03.tar.gz/md5/39cca70db2d23bc73a47870a0ee5156c -GMP.v6.2.1+6.x86_64-w64-mingw32-cxx03.tar.gz/sha512/a2877a6641e4cccd39e7ef093dd9ba7501c6e312f160b2924880d129195aadb74badfbf198fd6ee11035a6a7c99d64c0965c44526104a43569ca0d97fa565b5a -GMP.v6.2.1+6.x86_64-w64-mingw32-cxx11.tar.gz/md5/e2e03ed150558405ca1993ca14488662 -GMP.v6.2.1+6.x86_64-w64-mingw32-cxx11.tar.gz/sha512/50995f6382ed2a4c425097e7abf762b847872734c104847f6a042090be132c68e864d34bb24baf64832d3636810cb631464767949eb2df2fedaa7ccd9824f78b -gmp-6.2.1.tar.bz2/md5/28971fc21cf028042d4897f02fd355ea -gmp-6.2.1.tar.bz2/sha512/8904334a3bcc5c896ececabc75cda9dec642e401fb5397c4992c4fabea5e962c9ce8bd44e8e4233c34e55c8010cc28db0545f5f750cbdbb5f00af538dc763be9 +GMP.v6.3.0+0.aarch64-apple-darwin.tar.gz/md5/70a730ecf64eefb5a13f4524e29a6388 +GMP.v6.3.0+0.aarch64-apple-darwin.tar.gz/sha512/51791b4ae0ede1db4c6e7759072d125ca56f6a3a3e43fd5970981a3b2d651f28fe0abefce4b3ad0589d3a46c143054d20fee801bbd423bd2a4c12ba97314c39c +GMP.v6.3.0+0.aarch64-linux-gnu-cxx03.tar.gz/md5/e2b0bf1317259972cdc4f0e6fc3c2bc8 +GMP.v6.3.0+0.aarch64-linux-gnu-cxx03.tar.gz/sha512/8de1dd5d6971c76693c67222725c9eb0a1d276a55a28cd49d94115123100bfe45144652421d4cde468dce67a5630736f4174c9491c8a6e2543aadcb44f1f2d12 +GMP.v6.3.0+0.aarch64-linux-gnu-cxx11.tar.gz/md5/2017b6215ed99c3aed8b04abe75cb3e9 +GMP.v6.3.0+0.aarch64-linux-gnu-cxx11.tar.gz/sha512/78b22106f96348f0d9222279fdf8d1e3f5bd400f771fb0c54dd4045985ee05b896e3097f788739eefab9a9ab09a885aad65c4adb31ae5ba59b7ab22ca10bb574 +GMP.v6.3.0+0.aarch64-linux-musl-cxx03.tar.gz/md5/6477f35f92203db871f56f047b99a1fe +GMP.v6.3.0+0.aarch64-linux-musl-cxx03.tar.gz/sha512/66a6d18979c1ee9a5d06323a717d0a5dd73efc196087349408e739d7aa0444e8ee1af4bd634f85dfd4cfa4c97c24dda4ba472b490f50409581aff967c81b0750 +GMP.v6.3.0+0.aarch64-linux-musl-cxx11.tar.gz/md5/4648558f1e42b8e679f5be494a910402 +GMP.v6.3.0+0.aarch64-linux-musl-cxx11.tar.gz/sha512/9b7ff68a412bccd423b3cffefbc6350db6db8f3f7657713767187c2c2ea3b09d835e1c80d34ab4407f79fccbec82594e024787def27b9ad2ee7ea01ef1607b53 +GMP.v6.3.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/md5/6cabb238d148b3e2e76e8527e65893cd +GMP.v6.3.0+0.armv6l-linux-gnueabihf-cxx03.tar.gz/sha512/07b5673b4680781b7d42399213ecd491ede8883bbf1825689ad6678986a76581f6c4e53f17353f63bec8db8df5ed3fbddc228694eecc54ae7fc949f106bb8f14 +GMP.v6.3.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/md5/0257216ad4e96b404d456f07fcc30b09 +GMP.v6.3.0+0.armv6l-linux-gnueabihf-cxx11.tar.gz/sha512/ae8bbbbe3992f78186fe7535e450330e94e6630540eefbdfb51bb5014afd90feac0b1583e3fd2bbf226e61523647b3ec6324188bd6267c353a2a98594566c02b +GMP.v6.3.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/md5/48b949c062ea27dc0dbcc07ea5387821 +GMP.v6.3.0+0.armv6l-linux-musleabihf-cxx03.tar.gz/sha512/03699c20b5c50dbd44f45a0f5f115c6b10b4e8de68d747bceba605c3090469c819b82ad7e57fe7702c1700c25aae6ab9394a22ded319bc58c80e9d20692b610e +GMP.v6.3.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/md5/847ba3116072a523e1ff4ce83e5a18a8 +GMP.v6.3.0+0.armv6l-linux-musleabihf-cxx11.tar.gz/sha512/402548acd57f4112bf2435803f35ea93fd8d07f3df0e2f053b0bec6b08aa3dff4052990a724e2547ce35a29ee376b17d34b7e7e2ab45ecb4981ffc99c56f1a9f +GMP.v6.3.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/md5/5cc75b66059c3b8b5fbf9b8fcb781b10 +GMP.v6.3.0+0.armv7l-linux-gnueabihf-cxx03.tar.gz/sha512/1ef583d014c825e1d4e6d5f7e2d84c3ba183ba9490410f5d424760e275b7032e98f8377d87ed349d4969c6ef8f9b961a1e8df6f40efb406d41983446a9510303 +GMP.v6.3.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/md5/c0295c143bcb6b53d6184e2852ce35c5 +GMP.v6.3.0+0.armv7l-linux-gnueabihf-cxx11.tar.gz/sha512/3c74edb123a6f4147b416e5f7f25903bc859ac5f58f141bd463d3dff8cc2928fedf176f20869a1018a2731c1d7170444b3b3405c8f89c3fc22dc2edf9c036c24 +GMP.v6.3.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/md5/a67696b02a7f67405dd84252c908e071 +GMP.v6.3.0+0.armv7l-linux-musleabihf-cxx03.tar.gz/sha512/73ba1809cfc68199401974f73e7a37b1fe00d4c0cf3e58ed85d161a8fbac4390aeb28591c3108fc503ef8fb5b131d027cb76dcf5d7731698997c2f377d929dce +GMP.v6.3.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/md5/484f00cd5b0beec20f63cd6734d02611 +GMP.v6.3.0+0.armv7l-linux-musleabihf-cxx11.tar.gz/sha512/46fc56f945647f5c8577ad45f540a034f747604e5a89230d9d419b10d5f0571c7580e18e1138ea920efc08b25798c0c7110e15359de17dce3b6db7f07b8ceb3a +GMP.v6.3.0+0.i686-linux-gnu-cxx03.tar.gz/md5/d36d84638e2e5f927d15f07c55919f5f +GMP.v6.3.0+0.i686-linux-gnu-cxx03.tar.gz/sha512/61c62084ab90d25f7168281c7fb672f5bcafdf909afbf66847cfaa1077dd5474b2c27464eb76cac45f5e319aca0c4f7367fc238b83d2dde46ba90a7c1f396dfb +GMP.v6.3.0+0.i686-linux-gnu-cxx11.tar.gz/md5/d87627470bdcac981f7b004c27ac9a89 +GMP.v6.3.0+0.i686-linux-gnu-cxx11.tar.gz/sha512/2a34028687f75422b43f5365b0a8c9530b29473d41bfec4fb9822f074f813b8c6c1fc9efbfbb17a7e4d3d66f2549b5589b3fdbd08711a365330deb72be4958d0 +GMP.v6.3.0+0.i686-linux-musl-cxx03.tar.gz/md5/a2f2fc663bcacfc3e7d6aff29a52de23 +GMP.v6.3.0+0.i686-linux-musl-cxx03.tar.gz/sha512/a30a5d0ee78e747f074b3a5f0a26b9ba99b7553b3c83411a3cb9298814e605509194e9f0d8934caaa1cb7b78eef521805bbc86a297aebd06473ba80a20ffc443 +GMP.v6.3.0+0.i686-linux-musl-cxx11.tar.gz/md5/246b24935442815ff75a13b3dcf24756 +GMP.v6.3.0+0.i686-linux-musl-cxx11.tar.gz/sha512/ca351c4b93adf3f3e40f93c7b0cd61b33ec10049d39e8d33975f46d509efcded67600e6b19d8018a29ee893027d7a28edef0b19c1d70451d072a7a0989e9317d +GMP.v6.3.0+0.i686-w64-mingw32-cxx03.tar.gz/md5/c3b321ae48db0cb8dac4e09e2722e56c +GMP.v6.3.0+0.i686-w64-mingw32-cxx03.tar.gz/sha512/6a6feeb8baf6d499409a9010295b474a8c6de461fa0e34562d53e58190b66c50e278fae7560495cd85ea6f5b41f9e8c6e950ff4f451d26d0757e1d1696e8bca5 +GMP.v6.3.0+0.i686-w64-mingw32-cxx11.tar.gz/md5/3f633b0ff74c2a44350855fc6ce310b8 +GMP.v6.3.0+0.i686-w64-mingw32-cxx11.tar.gz/sha512/eecb17dec70fe84d90f47e1958672d273c865da9607ba3056c9c923a6ff9a3cab5b30414389d8f0c7f5ae5d87c05999964ed0900c80ae5afb525eaec00f401e2 +GMP.v6.3.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/md5/8b5f113ad7fd4a312229cfe8c2d1abca +GMP.v6.3.0+0.powerpc64le-linux-gnu-cxx03.tar.gz/sha512/36525ffc0ac5c363810c47945c34c81daabf88cf1f9c60d236447249d06332d3f5a130b431ab2d1c0148eb5413a4fa66bdd50671f2e7fcb77858d9fcdf83a94c +GMP.v6.3.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/md5/7f1237e9668136b00dd719a5cad3b6aa +GMP.v6.3.0+0.powerpc64le-linux-gnu-cxx11.tar.gz/sha512/46a6efe23173a12299da371121847d16d7950ffe5c87d1221b54c5e95dafbf723c4a327b1c2e832d4742a91254aa40fd5d8152d6d0801769b2efd4f83a042afd +GMP.v6.3.0+0.x86_64-apple-darwin.tar.gz/md5/cd2d1b309aea2c781a9c28470fd2f0eb +GMP.v6.3.0+0.x86_64-apple-darwin.tar.gz/sha512/d7f94d80f1ba170c9553601d1af323bef7bbb98575b80b58b3d7b37d69d81cdee0e132fb4fa20393a0e8719984c785d0c7e5c8ae2c29c62ffbd82b00375993d4 +GMP.v6.3.0+0.x86_64-linux-gnu-cxx03.tar.gz/md5/5be8efef65dafe52e5726ef24238ae36 +GMP.v6.3.0+0.x86_64-linux-gnu-cxx03.tar.gz/sha512/f4c303fe915c89fecdb5a333a30412e0cfb04e07b4f1bc2f726179243dbc61d60ae5b0773a6bd5da8a10cb8764e448bc88035a639ea88d2e06f04e55074d8551 +GMP.v6.3.0+0.x86_64-linux-gnu-cxx11.tar.gz/md5/66f9a3858d07591227f2bc057c3c988b +GMP.v6.3.0+0.x86_64-linux-gnu-cxx11.tar.gz/sha512/5611b9bfd24efac0a189bbd85533e1cd2bee7f833f5ae0a06343f2c1d92925e0d0f0758b99c43520293348ad61f98e1b470829514c35d208697988d8b469fc41 +GMP.v6.3.0+0.x86_64-linux-musl-cxx03.tar.gz/md5/edaa83f6432ff7e75e106d8bfd03d509 +GMP.v6.3.0+0.x86_64-linux-musl-cxx03.tar.gz/sha512/1587e7b91e387da9c23559826c161fa4d447250bd7b6565f0b9fedc36e7502dc2b59caa8157abcb7e7862d24d696470289bd650511b07e8711ecf5a462330b6d +GMP.v6.3.0+0.x86_64-linux-musl-cxx11.tar.gz/md5/e668c4f0c1246aa1510c36f246b1b483 +GMP.v6.3.0+0.x86_64-linux-musl-cxx11.tar.gz/sha512/cf4bd47a5ddb067a57e852855fbd637a93f3652c3327af256f74e9e265c9e0de7c5be78b3e7bcbf08a03916876ecdc05cc294149e2c3d472a30fedc2e6dded47 +GMP.v6.3.0+0.x86_64-unknown-freebsd.tar.gz/md5/4cbf56d2884aa357291321b182d07cb8 +GMP.v6.3.0+0.x86_64-unknown-freebsd.tar.gz/sha512/0c723b8e0f5fabf9e43945d3fb355c3d7b036662a8d6542629aaff27164f12d13b2a19f5c4964f165466705b231884b7f7193d7a01a0e9d3644da1d79af79631 +GMP.v6.3.0+0.x86_64-w64-mingw32-cxx03.tar.gz/md5/02e8f5d66c15731117cf805e0a4c4976 +GMP.v6.3.0+0.x86_64-w64-mingw32-cxx03.tar.gz/sha512/1f94805fe9f34f4e77c54e92625615d91ade617468483409037d0693c3bf106187916d9d21e92681673faae158b376133c0ede643f31bfc9f73ac29c9fd13bcc +GMP.v6.3.0+0.x86_64-w64-mingw32-cxx11.tar.gz/md5/10752137fccc73175872db07749d6f49 +GMP.v6.3.0+0.x86_64-w64-mingw32-cxx11.tar.gz/sha512/3a5d7e8125f3b538a2e59e9c6919db36c974575e6b1950451cb60307da68dc092c4ce21b8f49c40871aadf3bd07681b43eea9c7bf37ba383da9a0e80c30b176e +gmp-6.3.0.tar.bz2/md5/c1cd6ef33085e9cb818b9b08371f9000 +gmp-6.3.0.tar.bz2/sha512/3b684c9bcb9ede2b7e54d0ba4c9764bfa17c20d4f3000017c553b6f1e135b536949580ff37341680c25dc236cfe0ba1db8cfdfe619ce013656189ef0871b89f8 diff --git a/deps/checksums/libuv b/deps/checksums/libuv index 6ad61210bc0cc..7ac93952b8b34 100644 --- a/deps/checksums/libuv +++ b/deps/checksums/libuv @@ -1,34 +1,34 @@ -LibUV.v2.0.1+14.aarch64-apple-darwin.tar.gz/md5/1a58ce9dc88984c3b5f7df97af6cbf83 -LibUV.v2.0.1+14.aarch64-apple-darwin.tar.gz/sha512/2bfd482ac759ac88d885371854affa8e358a10fea6c7756e0d1b366bc82ecbea56bdf24ca634525fb2a6fc2b3a5c77b07a4c6dec2923d8bffe2bc962bd3e7f84 -LibUV.v2.0.1+14.aarch64-linux-gnu.tar.gz/md5/7f270dd1e3046c8db432e350dd5cf114 -LibUV.v2.0.1+14.aarch64-linux-gnu.tar.gz/sha512/c0debcf17b54ba9f1588d4b267d610751f739d8ff96936c9d5fb6d8742039f8736c63fa70037322705569e221d73fb83c03b6ba9fb4454442fffd3a9f1a1a2da -LibUV.v2.0.1+14.aarch64-linux-musl.tar.gz/md5/07f56c32d5a2c12e6c351cf9f705631c -LibUV.v2.0.1+14.aarch64-linux-musl.tar.gz/sha512/8037d7aa0cb06850f055fd19cebdcfcf3146dde0d12768a9669bf05dcab91fdf3708798203258cb3f452158bdec7faae41e6afbb0e60b21403e683db3e23a1c9 -LibUV.v2.0.1+14.armv6l-linux-gnueabihf.tar.gz/md5/5558a7f68c7c375f40bc64da59fef0ad -LibUV.v2.0.1+14.armv6l-linux-gnueabihf.tar.gz/sha512/92ed6601cb5aa9a3ea2478a1485849543c9e847c8e85542e72f372a2d37c4c8b90f5ecb1bee1e462db31e1e8dba460f584b3cca9c833989c2b9ee404e355654e -LibUV.v2.0.1+14.armv6l-linux-musleabihf.tar.gz/md5/de6bfb7f0c0468b79e8895f166fb6340 -LibUV.v2.0.1+14.armv6l-linux-musleabihf.tar.gz/sha512/7948d007171bf57b827b489f3627ac74df447f4d696e8226e54e95ef0c8eed5a5ddbf758fbad841bc367f78cd61e6a5899eb478003dca3a79cb494b38cab830b -LibUV.v2.0.1+14.armv7l-linux-gnueabihf.tar.gz/md5/5be35de1d881f80981647c369b9b4ec8 -LibUV.v2.0.1+14.armv7l-linux-gnueabihf.tar.gz/sha512/458e5058ea4e794e0dc790da4c98569676056bac336df69762e8ccfec8f2955dcc55e8d090daa1b191c0ffa41392a04530c9bc28aa27cf411c1df2f1ba14bb97 -LibUV.v2.0.1+14.armv7l-linux-musleabihf.tar.gz/md5/8d034490da1ec2ef3dd3c69336177654 -LibUV.v2.0.1+14.armv7l-linux-musleabihf.tar.gz/sha512/7f595a8ab8b664d229cf6144e9ed1b5936ba8aaa70b92611ddb85bbe9046bb1b94d8417355a5abf058fb00023d4d56be0b2ddfd5dba896cd7b64e84e32dbfc5a -LibUV.v2.0.1+14.i686-linux-gnu.tar.gz/md5/ccb9aba78456c99b8473e8ddd328f90e -LibUV.v2.0.1+14.i686-linux-gnu.tar.gz/sha512/d382d90137db308933257a75e51d90988d6d07663b3b2915478547127d32f73ae6cdb4575d5ee20758f8850c7e85908fe4710c053cb361826621f22bc5b6502d -LibUV.v2.0.1+14.i686-linux-musl.tar.gz/md5/5ade48f16aa26bb68dc046d285c73043 -LibUV.v2.0.1+14.i686-linux-musl.tar.gz/sha512/f5728a5dc567268e59aa2697deb793ae427e11dcb6796c577e3da3ac24225ece5d4a6c4f903d4a7b184d3c3a3c8c1586c34b97e4a75de0a4e23ace720020fa8c -LibUV.v2.0.1+14.i686-w64-mingw32.tar.gz/md5/541210fef837c2ef7cffa508d282f9bb -LibUV.v2.0.1+14.i686-w64-mingw32.tar.gz/sha512/4541a02c59b66f97099b5264dce0cad90fcdf9a4d7ccd8e950cc1f3a530616a0fb2aa43db21b5b1f52819efef22cd0b68595d419e2e5b05924e344b0333f8bf8 -LibUV.v2.0.1+14.powerpc64le-linux-gnu.tar.gz/md5/26656d4eaae8739099c55054bad54f57 -LibUV.v2.0.1+14.powerpc64le-linux-gnu.tar.gz/sha512/f85f8cfd91e7b1b02b073931ef9a3bb05620641d18ada039744a92b8c40e5a3de8d7c5efa7189b88baf1eb11fbcf9e6d16031b86e40f99f1b7cfebb0f5c5adf1 -LibUV.v2.0.1+14.x86_64-apple-darwin.tar.gz/md5/c7da6b91394a20c43acdf6f680cb62e2 -LibUV.v2.0.1+14.x86_64-apple-darwin.tar.gz/sha512/238d22bd299ae3b0dfd24a5b38d6d0d07b751fb301487a2d1d2f5313ae3596f33492388ea9fbff549293787505fc527e174ebcd4068f1bda43b40bc19e016d89 -LibUV.v2.0.1+14.x86_64-linux-gnu.tar.gz/md5/8c8913068263257cce5042b725918e0e -LibUV.v2.0.1+14.x86_64-linux-gnu.tar.gz/sha512/a848381012d5a20a0c881f5835e479cfff811928ce508cc57041d69668782f2135c14c7e5388e7dbf693ae57aa1825d911f6f450b9e909cce45487b03a581a23 -LibUV.v2.0.1+14.x86_64-linux-musl.tar.gz/md5/16747c066b6d7fe56850c77f66ea7478 -LibUV.v2.0.1+14.x86_64-linux-musl.tar.gz/sha512/833a02f9191edf3b56f1e02f5671f22de6cb27ec3c9f770530ec95d8da7ba0b9c05bcdf6b094224ea8e43ba70918e1599f3237bd98900763daef80c327d3d2de -LibUV.v2.0.1+14.x86_64-unknown-freebsd.tar.gz/md5/e828eb79728e75766a72d7b304c9f989 -LibUV.v2.0.1+14.x86_64-unknown-freebsd.tar.gz/sha512/37df5b966f70b3d1e0eae603d4a6b00c84dffdfc3632ca581669a99a0cd894a81aff4361de3beed53ec032273f62cf397cf52085c6c387d0bbb2c57b59ae84fe -LibUV.v2.0.1+14.x86_64-w64-mingw32.tar.gz/md5/bded9d94435a70fd0dfff3f0fc605736 -LibUV.v2.0.1+14.x86_64-w64-mingw32.tar.gz/sha512/48793a386f6231d12f01b4718d87aaab409f0b807b03a3577e2401f7493caef36a5072fdc33f3cd3ce9733ba50ab344cb2e2fa6a21ba5adb56d6cca642afad0c -libuv-2723e256e952be0b015b3c0086f717c3d365d97e.tar.gz/md5/d2284d7f6fa75d6a35673d22e1be058b -libuv-2723e256e952be0b015b3c0086f717c3d365d97e.tar.gz/sha512/68d6ab740945b9ce3475118ce3d186fb67d7e8125784cc0c827df23d63f50c40c0261ef37365d8c11ab9462a8dd4e2e6b19e91e3c84b64d8fb84fd3894afc4ac +LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/md5/f12ee08b8d5721bd88b651ac573c59ed +LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/sha512/b3c53e04624d9c60e664db2eaaf3add696f95c52e55db0c577547f7bf7e045ce30cffa0e38c3451f483dcdb7ddcac1b7f43b694dfadb37282773ce416af1030a +LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/md5/8cb9f4d6c6a4013fa9ed9ae120058275 +LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/sha512/d4213ee47ebdcab4cc4719478608ffa461a5543a16656c2881587364c8ed1b39a2f418d5c3c6a04d7e6dd3df349f0afa72cd1df0e06db6146512356b37637024 +LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/md5/e23a0d7162fc3f09f0ea92d24cba3f4d +LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/sha512/f4a13eee72575092ab673777a53d43ce999a7a8bf847daa0a86b39bbfd3f6c1575f105a0bb629766268921ff94f10d354a0e53d32623f6ad35fca44e7bac25f8 +LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/md5/70ed0616cd3737a357b7571ab648d239 +LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/sha512/25a4b8a90b7bb62e31c1c2bb1d7e137050de26f311daa9f77be932ab3d9a2b92c82ce82ed37cc74a2b1cd5a60bd0dc412e92d31013d36ad35af2d4f376fbc0b0 +LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/md5/e4320c51c8904a59c105f7b63d086c79 +LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/sha512/bbc39d800277a66298c56849c1131a6f1958a2c8b2465b59527965a1bd3f36a4c87c1d7ad4be59ec0f4ca8f94ec1804a619eb963d956b77e645e0e00effc6613 +LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/md5/d5436552dc177fc3fd0cf4f575cc03b4 +LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/sha512/8d3722290151ecf65f4e3fe3440828492a7b115810b87c8711c5592f4dea69727e516228a5a1bdac430c74b288f12de390daf0a9408274aa27cdd69efc81cfee +LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/md5/67e1ba03ddf2d2bdd79fef25a5976350 +LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/sha512/535565657b5714da0db5c622b65b261a77f21f407b1166eee99f35ba3bb9c6fab4c7d1f3db70528767cef7c66c856c5101b01423be05efb9219ec4c76df0be6a +LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/md5/ba1432ecd75e6a43ff197d51ba76446c +LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/sha512/dc8940284d4ba05098037fcf4b3bada199878794ef34ad09d8992ef58e4c829b00a3fcca29c4f65b49edcab4274092232ff5d7619b3535333125043f89503cfc +LibUV.v2.0.1+15.i686-linux-musl.tar.gz/md5/237080cf5d1286a3d2f35d134a285d28 +LibUV.v2.0.1+15.i686-linux-musl.tar.gz/sha512/834f16a16cf6b765dfd094037c8a45ccdedc2eb9e45f527c6721eb0f60f4e56dc4f9b90a2a35e3ed10da4a937d8555e97034e0a29d733cac5352061ebe286799 +LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/md5/8a5261a6ce4200d272b5eda4fe9ecb31 +LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/sha512/b372b9368a9ac92775a8d6ee39b492905dc5f58f16d7edf792e0c2ffbd4507ede79139a24fe852dfa26068d0f076a4abf3c3b868a8a057b23fdbad80999d315f +LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/md5/53db7b763af204477ce8f0bfae0ce15c +LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/sha512/bbfe2518d4dc84fe73b7d3f3bcaf5aeef0db0d284c0e205e3e3670b8ce6f3ea593a0e52d125fd9a79cd098dba0d35f151cb46469fa25dfeef62ebcc966f94d4f +LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/md5/b4699192c098564edc5589e90c47324e +LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/sha512/2505e4060712143d3213747d4276c0b99dec78579d2ab0b71c5d7edf15ae80e0178138a11470c976d97de14e44b153dcb00c08c864523d7ee0ead8e48cf15d14 +LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/md5/f5515c50106a0748b9a1986c912a00f3 +LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/sha512/5822396039e14a5d919f2612559a8d62a925c4319e66eb05ed20faed754318762f5653851684701cd4ddb1edf10bfe25d252c3d9cd84228e498e825ba61146b1 +LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/md5/1962e6f21080e874d2ca0275c5b569b2 +LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/sha512/4702e13633d77a6c0aeb1e7cd252471a779177e20c68485130f420cc4878c8f7de7f0f51730008ba9dc0f275875a5947629d39aff200691e26f31d42e388d53d +LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/md5/928a789c3cd3b4cefcc1cf13f5f179ac +LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/sha512/ee58667b19fdf7ec0218b4645b3f5bed2e9fc01cc29eab8473ee02aaa044f94a48eb220c6427200aaf56eacf52d0f72156712d17017cfecbc25d3c1b71a4bd2f +LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/md5/d3b84729ee9d5a6e6a1e29357e25cced +LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/sha512/43ca5999d8e8ff820722b1a548bd4e277e95c739c3363ed6159d080dd06842316f5370e8e4f4a886bf76010f4aed2bbf01f6091845b0e84b75f709277c561649 +libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/md5/3863ccd5a51f85cf76679070c99be6cd +libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/sha512/bf4c705e05e730139b62de799331653eea2767898d654b8890ca2623db3adb9a1efcfcfab38af22e8ac44c67a9c5c018f1f7847a3703bee5f05657169a67d817 diff --git a/deps/gmp.mk b/deps/gmp.mk index 491d649e9202f..23075c861cd35 100644 --- a/deps/gmp.mk +++ b/deps/gmp.mk @@ -35,34 +35,17 @@ $(SRCCACHE)/gmp-$(GMP_VER)/source-extracted: $(SRCCACHE)/gmp-$(GMP_VER).tar.bz2 checksum-gmp: $(SRCCACHE)/gmp-$(GMP_VER).tar.bz2 $(JLCHECKSUM) $< -# Apply fix to avoid using Apple ARM reserved register X18 -# Necessary for version 6.2.1, remove after next gmp release -$(SRCCACHE)/gmp-$(GMP_VER)/gmp-HG-changeset.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/source-extracted - cd $(dir $@) && \ - patch -p1 -f < $(SRCDIR)/patches/gmp-HG-changeset.patch - echo 1 > $@ - -$(SRCCACHE)/gmp-$(GMP_VER)/gmp-exception.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-HG-changeset.patch-applied +$(SRCCACHE)/gmp-$(GMP_VER)/gmp-exception.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/source-extracted cd $(dir $@) && \ patch -p1 -f < $(SRCDIR)/patches/gmp-exception.patch echo 1 > $@ -$(SRCCACHE)/gmp-$(GMP_VER)/gmp_alloc_overflow_func.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-exception.patch-applied - cd $(dir $@) && \ - patch -p1 -f < $(SRCDIR)/patches/gmp_alloc_overflow_func.patch - echo 1 > $@ - -$(SRCCACHE)/gmp-$(GMP_VER)/gmp-CVE-2021-43618.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/gmp_alloc_overflow_func.patch-applied - cd $(dir $@) && \ - patch -p1 -f < $(SRCDIR)/patches/gmp-CVE-2021-43618.patch - echo 1 > $@ - -$(SRCCACHE)/gmp-$(GMP_VER)/gmp-more_alloc_overflow.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-CVE-2021-43618.patch-applied +$(SRCCACHE)/gmp-$(GMP_VER)/gmp-alloc_overflow.patch-applied: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-exception.patch-applied cd $(dir $@) && \ - patch -p1 -f < $(SRCDIR)/patches/gmp-more_alloc_overflow.patch + patch -p1 -f < $(SRCDIR)/patches/gmp-alloc_overflow.patch echo 1 > $@ -$(SRCCACHE)/gmp-$(GMP_VER)/source-patched: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-more_alloc_overflow.patch-applied +$(SRCCACHE)/gmp-$(GMP_VER)/source-patched: $(SRCCACHE)/gmp-$(GMP_VER)/gmp-alloc_overflow.patch-applied echo 1 > $@ $(BUILDDIR)/gmp-$(GMP_VER)/build-configured: $(SRCCACHE)/gmp-$(GMP_VER)/source-patched diff --git a/deps/gmp.version b/deps/gmp.version index f77cac5906cea..3b6659faea7b7 100644 --- a/deps/gmp.version +++ b/deps/gmp.version @@ -1,5 +1,6 @@ +# -*- makefile -*- ## jll artifact GMP_JLL_NAME := GMP ## source build -GMP_VER := 6.2.1 +GMP_VER := 6.3.0 diff --git a/deps/libuv.version b/deps/libuv.version index 01bf4fecc6dc6..9ae54aa7be91a 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -3,5 +3,5 @@ LIBUV_JLL_NAME := LibUV ## source build LIBUV_VER := 2 -LIBUV_BRANCH=julia-uv2-1.44.2 -LIBUV_SHA1=2723e256e952be0b015b3c0086f717c3d365d97e +LIBUV_BRANCH=julia-uv2-1.48.0 +LIBUV_SHA1=afa1c67fa496eb49ade1e520f76fd018a1409eaa diff --git a/deps/patches/gmp-CVE-2021-43618.patch b/deps/patches/gmp-CVE-2021-43618.patch deleted file mode 100644 index a4e420e9219da..0000000000000 --- a/deps/patches/gmp-CVE-2021-43618.patch +++ /dev/null @@ -1,24 +0,0 @@ -# Origin: https://gmplib.org/repo/gmp-6.2/rev/561a9c25298e -# HG changeset patch -# User Marco Bodrato -# Date 1634836009 -7200 -# Node ID 561a9c25298e17bb01896801ff353546c6923dbd -# Parent e1fd9db13b475209a864577237ea4b9105b3e96e -mpz/inp_raw.c: Avoid bit size overflows - -diff -r e1fd9db13b47 -r 561a9c25298e mpz/inp_raw.c ---- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100 -+++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200 -@@ -88,8 +88,11 @@ - - abs_csize = ABS (csize); - -+ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8)) -+ return 0; /* Bit size overflows */ -+ - /* round up to a multiple of limbs */ -- abs_xsize = BITS_TO_LIMBS (abs_csize*8); -+ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8); - - if (abs_xsize != 0) - { diff --git a/deps/patches/gmp-HG-changeset.patch b/deps/patches/gmp-HG-changeset.patch deleted file mode 100644 index 7437fb6f2f748..0000000000000 --- a/deps/patches/gmp-HG-changeset.patch +++ /dev/null @@ -1,520 +0,0 @@ - -# HG changeset patch -# User Torbjorn Granlund -# Date 1606685500 -3600 -# Node ID 5f32dbc41afc1f8cd77af1614f0caeb24deb7d7b -# Parent 94c84d919f83ba963ed1809f8e80c7bef32db55c -Avoid the x18 register since it is reserved on Darwin. - -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/aors_n.asm ---- a/mpn/arm64/aors_n.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/aors_n.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -68,7 +68,7 @@ - EPILOGUE() - PROLOGUE(func_n) - CLRCY --L(ent): lsr x18, n, #2 -+L(ent): lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x7, [up] -@@ -77,7 +77,7 @@ - str x13, [rp],#8 - tbnz n, #1, L(b11) - --L(b01): cbz x18, L(ret) -+L(b01): cbz x17, L(ret) - ldp x4, x5, [up,#8] - ldp x8, x9, [vp,#8] - sub up, up, #8 -@@ -88,7 +88,7 @@ - ldp x10, x11, [vp,#8] - add up, up, #8 - add vp, vp, #8 -- cbz x18, L(end) -+ cbz x17, L(end) - b L(top) - - L(bx0): tbnz n, #1, L(b10) -@@ -101,7 +101,7 @@ - - L(b10): ldp x6, x7, [up] - ldp x10, x11, [vp] -- cbz x18, L(end) -+ cbz x17, L(end) - - ALIGN(16) - L(top): ldp x4, x5, [up,#16] -@@ -114,8 +114,8 @@ - ADDSUBC x12, x4, x8 - ADDSUBC x13, x5, x9 - stp x12, x13, [rp],#16 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x17, x17, #1 -+ cbnz x17, L(top) - - L(end): ADDSUBC x12, x6, x10 - ADDSUBC x13, x7, x11 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/aorsmul_1.asm ---- a/mpn/arm64/aorsmul_1.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/aorsmul_1.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -32,10 +32,15 @@ - - include(`../config.m4') - --C cycles/limb --C Cortex-A53 9.3-9.8 --C Cortex-A57 7.0 --C X-Gene 5.0 -+C addmul_1 submul_1 -+C cycles/limb cycles/limb -+C Cortex-A53 9.3-9.8 9.3-9.8 -+C Cortex-A55 9.0-9.5 9.3-9.8 -+C Cortex-A57 7 7 -+C Cortex-A72 -+C Cortex-A73 6 6 -+C X-Gene 5 5 -+C Apple M1 1.75 1.75 - - C NOTES - C * It is possible to keep the carry chain alive between the addition blocks -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/aorsorrlshC_n.asm ---- a/mpn/arm64/aorsorrlshC_n.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/aorsorrlshC_n.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -65,14 +65,14 @@ - - ASM_START() - PROLOGUE(func_n) -- lsr x18, n, #2 -+ lsr x6, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x5, [up] - tbnz n, #1, L(b11) - - L(b01): ldr x11, [vp] -- cbz x18, L(1) -+ cbz x6, L(1) - ldp x8, x9, [vp,#8] - lsl x13, x11, #LSH - ADDSUB( x15, x13, x5) -@@ -94,7 +94,7 @@ - ADDSUB( x17, x13, x5) - str x17, [rp],#8 - sub up, up, #8 -- cbz x18, L(end) -+ cbz x6, L(end) - b L(top) - - L(bx0): tbnz n, #1, L(b10) -@@ -107,7 +107,7 @@ - L(b10): CLRRCY( x9) - ldp x10, x11, [vp] - sub up, up, #16 -- cbz x18, L(end) -+ cbz x6, L(end) - - ALIGN(16) - L(top): ldp x4, x5, [up,#16] -@@ -124,8 +124,8 @@ - ADDSUBC(x16, x12, x4) - ADDSUBC(x17, x13, x5) - stp x16, x17, [rp],#16 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x6, x6, #1 -+ cbnz x6, L(top) - - L(end): ldp x4, x5, [up,#16] - extr x12, x10, x9, #RSH -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/cnd_aors_n.asm ---- a/mpn/arm64/cnd_aors_n.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/cnd_aors_n.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -65,7 +65,7 @@ - - CLRCY - -- lsr x18, n, #2 -+ lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x13, [vp] -@@ -75,7 +75,7 @@ - str x9, [rp] - tbnz n, #1, L(b11) - --L(b01): cbz x18, L(rt) -+L(b01): cbz x17, L(rt) - ldp x12, x13, [vp,#8] - ldp x10, x11, [up,#8] - sub up, up, #8 -@@ -86,7 +86,7 @@ - L(b11): ldp x12, x13, [vp,#8]! - ldp x10, x11, [up,#8]! - sub rp, rp, #8 -- cbz x18, L(end) -+ cbz x17, L(end) - b L(top) - - L(bx0): ldp x12, x13, [vp] -@@ -99,7 +99,7 @@ - b L(mid) - - L(b10): sub rp, rp, #16 -- cbz x18, L(end) -+ cbz x17, L(end) - - ALIGN(16) - L(top): bic x6, x12, cnd -@@ -116,8 +116,8 @@ - ADDSUBC x9, x11, x7 - ldp x10, x11, [up,#32]! - stp x8, x9, [rp,#32]! -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x17, x17, #1 -+ cbnz x17, L(top) - - L(end): bic x6, x12, cnd - bic x7, x13, cnd -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/logops_n.asm ---- a/mpn/arm64/logops_n.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/logops_n.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -78,7 +78,7 @@ - - ASM_START() - PROLOGUE(func) -- lsr x18, n, #2 -+ lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x7, [up] -@@ -88,7 +88,7 @@ - str x15, [rp],#8 - tbnz n, #1, L(b11) - --L(b01): cbz x18, L(ret) -+L(b01): cbz x17, L(ret) - ldp x4, x5, [up,#8] - ldp x8, x9, [vp,#8] - sub up, up, #8 -@@ -99,7 +99,7 @@ - ldp x10, x11, [vp,#8] - add up, up, #8 - add vp, vp, #8 -- cbz x18, L(end) -+ cbz x17, L(end) - b L(top) - - L(bx0): tbnz n, #1, L(b10) -@@ -110,7 +110,7 @@ - - L(b10): ldp x6, x7, [up] - ldp x10, x11, [vp] -- cbz x18, L(end) -+ cbz x17, L(end) - - ALIGN(16) - L(top): ldp x4, x5, [up,#16] -@@ -127,8 +127,8 @@ - POSTOP( x12) - POSTOP( x13) - stp x12, x13, [rp],#16 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x17, x17, #1 -+ cbnz x17, L(top) - - L(end): LOGOP( x12, x6, x10) - LOGOP( x13, x7, x11) -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/lshift.asm ---- a/mpn/arm64/lshift.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/lshift.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -61,7 +61,7 @@ - add rp, rp_arg, n, lsl #3 - add up, up, n, lsl #3 - sub tnc, xzr, cnt -- lsr x18, n, #2 -+ lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x4, [up,#-8] -@@ -69,7 +69,7 @@ - - L(b01): NSHIFT x0, x4, tnc - PSHIFT x2, x4, cnt -- cbnz x18, L(gt1) -+ cbnz x17, L(gt1) - str x2, [rp,#-8] - ret - L(gt1): ldp x4, x5, [up,#-24] -@@ -89,7 +89,7 @@ - PSHIFT x13, x5, cnt - NSHIFT x10, x4, tnc - PSHIFT x2, x4, cnt -- cbnz x18, L(gt2) -+ cbnz x17, L(gt2) - orr x10, x10, x13 - stp x2, x10, [rp,#-16] - ret -@@ -123,11 +123,11 @@ - orr x11, x12, x2 - stp x10, x11, [rp,#-32]! - PSHIFT x2, x4, cnt --L(lo0): sub x18, x18, #1 -+L(lo0): sub x17, x17, #1 - L(lo3): NSHIFT x10, x6, tnc - PSHIFT x13, x7, cnt - NSHIFT x12, x7, tnc -- cbnz x18, L(top) -+ cbnz x17, L(top) - - L(end): orr x10, x10, x13 - orr x11, x12, x2 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/lshiftc.asm ---- a/mpn/arm64/lshiftc.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/lshiftc.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -61,7 +61,7 @@ - add rp, rp_arg, n, lsl #3 - add up, up, n, lsl #3 - sub tnc, xzr, cnt -- lsr x18, n, #2 -+ lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x4, [up,#-8] -@@ -69,7 +69,7 @@ - - L(b01): NSHIFT x0, x4, tnc - PSHIFT x2, x4, cnt -- cbnz x18, L(gt1) -+ cbnz x17, L(gt1) - mvn x2, x2 - str x2, [rp,#-8] - ret -@@ -90,7 +90,7 @@ - PSHIFT x13, x5, cnt - NSHIFT x10, x4, tnc - PSHIFT x2, x4, cnt -- cbnz x18, L(gt2) -+ cbnz x17, L(gt2) - eon x10, x10, x13 - mvn x2, x2 - stp x2, x10, [rp,#-16] -@@ -125,11 +125,11 @@ - eon x11, x12, x2 - stp x10, x11, [rp,#-32]! - PSHIFT x2, x4, cnt --L(lo0): sub x18, x18, #1 -+L(lo0): sub x17, x17, #1 - L(lo3): NSHIFT x10, x6, tnc - PSHIFT x13, x7, cnt - NSHIFT x12, x7, tnc -- cbnz x18, L(top) -+ cbnz x17, L(top) - - L(end): eon x10, x10, x13 - eon x11, x12, x2 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/mul_1.asm ---- a/mpn/arm64/mul_1.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/mul_1.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -56,7 +56,7 @@ - - PROLOGUE(mpn_mul_1) - adds x4, xzr, xzr C clear register and cy flag --L(com): lsr x18, n, #2 -+L(com): lsr x17, n, #2 - tbnz n, #0, L(bx1) - - L(bx0): mov x11, x4 -@@ -65,7 +65,7 @@ - L(b10): ldp x4, x5, [up] - mul x8, x4, v0 - umulh x10, x4, v0 -- cbz x18, L(2) -+ cbz x17, L(2) - ldp x6, x7, [up,#16]! - mul x9, x5, v0 - b L(mid)-8 -@@ -80,7 +80,7 @@ - str x9, [rp],#8 - tbnz n, #1, L(b10) - --L(b01): cbz x18, L(1) -+L(b01): cbz x17, L(1) - - L(b00): ldp x6, x7, [up] - mul x8, x6, v0 -@@ -90,8 +90,8 @@ - adcs x12, x8, x11 - umulh x11, x7, v0 - add rp, rp, #16 -- sub x18, x18, #1 -- cbz x18, L(end) -+ sub x17, x17, #1 -+ cbz x17, L(end) - - ALIGN(16) - L(top): mul x8, x4, v0 -@@ -110,8 +110,8 @@ - stp x12, x13, [rp],#32 - adcs x12, x8, x11 - umulh x11, x7, v0 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x17, x17, #1 -+ cbnz x17, L(top) - - L(end): mul x8, x4, v0 - adcs x13, x9, x10 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/rsh1aors_n.asm ---- a/mpn/arm64/rsh1aors_n.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/rsh1aors_n.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -59,7 +59,7 @@ - - ASM_START() - PROLOGUE(func_n) -- lsr x18, n, #2 -+ lsr x6, n, #2 - - tbz n, #0, L(bx0) - -@@ -69,7 +69,7 @@ - - L(b01): ADDSUB x13, x5, x9 - and x10, x13, #1 -- cbz x18, L(1) -+ cbz x6, L(1) - ldp x4, x5, [up],#48 - ldp x8, x9, [vp],#48 - ADDSUBC x14, x4, x8 -@@ -80,8 +80,8 @@ - ADDSUBC x12, x4, x8 - ADDSUBC x13, x5, x9 - str x17, [rp], #24 -- sub x18, x18, #1 -- cbz x18, L(end) -+ sub x6, x6, #1 -+ cbz x6, L(end) - b L(top) - - L(1): cset x14, COND -@@ -97,7 +97,7 @@ - ldp x8, x9, [vp],#32 - ADDSUBC x12, x4, x8 - ADDSUBC x13, x5, x9 -- cbz x18, L(3) -+ cbz x6, L(3) - ldp x4, x5, [up,#-16] - ldp x8, x9, [vp,#-16] - extr x17, x12, x15, #1 -@@ -117,7 +117,7 @@ - ADDSUB x12, x4, x8 - ADDSUBC x13, x5, x9 - and x10, x12, #1 -- cbz x18, L(2) -+ cbz x6, L(2) - ldp x4, x5, [up,#-16] - ldp x8, x9, [vp,#-16] - ADDSUBC x14, x4, x8 -@@ -134,8 +134,8 @@ - ADDSUBC x12, x4, x8 - ADDSUBC x13, x5, x9 - add rp, rp, #16 -- sub x18, x18, #1 -- cbz x18, L(end) -+ sub x6, x6, #1 -+ cbz x6, L(end) - - ALIGN(16) - L(top): ldp x4, x5, [up,#-16] -@@ -152,8 +152,8 @@ - ADDSUBC x12, x4, x8 - ADDSUBC x13, x5, x9 - stp x16, x17, [rp],#32 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x6, x6, #1 -+ cbnz x6, L(top) - - L(end): extr x16, x15, x14, #1 - extr x17, x12, x15, #1 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/rshift.asm ---- a/mpn/arm64/rshift.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/rshift.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -60,7 +60,7 @@ - PROLOGUE(mpn_rshift) - mov rp, rp_arg - sub tnc, xzr, cnt -- lsr x18, n, #2 -+ lsr x17, n, #2 - tbz n, #0, L(bx0) - - L(bx1): ldr x5, [up] -@@ -68,7 +68,7 @@ - - L(b01): NSHIFT x0, x5, tnc - PSHIFT x2, x5, cnt -- cbnz x18, L(gt1) -+ cbnz x17, L(gt1) - str x2, [rp] - ret - L(gt1): ldp x4, x5, [up,#8] -@@ -89,7 +89,7 @@ - PSHIFT x13, x4, cnt - NSHIFT x10, x5, tnc - PSHIFT x2, x5, cnt -- cbnz x18, L(gt2) -+ cbnz x17, L(gt2) - orr x10, x10, x13 - stp x10, x2, [rp] - ret -@@ -121,11 +121,11 @@ - orr x11, x12, x2 - stp x11, x10, [rp,#32]! - PSHIFT x2, x5, cnt --L(lo0): sub x18, x18, #1 -+L(lo0): sub x17, x17, #1 - L(lo3): NSHIFT x10, x7, tnc - NSHIFT x12, x6, tnc - PSHIFT x13, x6, cnt -- cbnz x18, L(top) -+ cbnz x17, L(top) - - L(end): orr x10, x10, x13 - orr x11, x12, x2 -diff -r 94c84d919f83 -r 5f32dbc41afc mpn/arm64/sqr_diag_addlsh1.asm ---- a/mpn/arm64/sqr_diag_addlsh1.asm Sat Nov 28 23:38:32 2020 +0100 -+++ b/mpn/arm64/sqr_diag_addlsh1.asm Sun Nov 29 22:31:40 2020 +0100 -@@ -47,7 +47,7 @@ - ASM_START() - PROLOGUE(mpn_sqr_diag_addlsh1) - ldr x15, [up],#8 -- lsr x18, n, #1 -+ lsr x14, n, #1 - tbz n, #0, L(bx0) - - L(bx1): adds x7, xzr, xzr -@@ -62,8 +62,8 @@ - ldr x17, [up],#16 - ldp x6, x7, [tp],#32 - umulh x11, x15, x15 -- sub x18, x18, #1 -- cbz x18, L(end) -+ sub x14, x14, #1 -+ cbz x14, L(end) - - ALIGN(16) - L(top): extr x9, x6, x5, #63 -@@ -84,8 +84,8 @@ - extr x8, x5, x4, #63 - stp x12, x13, [rp],#16 - adcs x12, x8, x10 -- sub x18, x18, #1 -- cbnz x18, L(top) -+ sub x14, x14, #1 -+ cbnz x14, L(top) - - L(end): extr x9, x6, x5, #63 - mul x10, x17, x17 diff --git a/deps/patches/gmp_alloc_overflow_func.patch b/deps/patches/gmp-alloc_overflow.patch similarity index 54% rename from deps/patches/gmp_alloc_overflow_func.patch rename to deps/patches/gmp-alloc_overflow.patch index 51506d70d46fb..6a0f02c66e3f4 100644 --- a/deps/patches/gmp_alloc_overflow_func.patch +++ b/deps/patches/gmp-alloc_overflow.patch @@ -1,7 +1,7 @@ -diff --git a/gmp-h.in b/gmp-h.in ---- a/gmp-h.in -+++ b/gmp-h.in -@@ -479,6 +479,13 @@ using std::FILE; +diff -ru gmp-6.3.0/gmp-h.in gmp-6.3.0.new/gmp-h.in +--- gmp-6.3.0/gmp-h.in 2023-07-29 09:42:16 ++++ gmp-6.3.0.new/gmp-h.in 2023-12-29 15:33:34 +@@ -487,6 +487,12 @@ void *(**) (void *, size_t, size_t), void (**) (void *, size_t)) __GMP_NOTHROW; @@ -10,15 +10,23 @@ diff --git a/gmp-h.in b/gmp-h.in + +#define mp_get_alloc_overflow_function __gmp_get_alloc_overflow_function +__GMP_DECLSPEC void mp_get_alloc_overflow_function (void (**) (void)) __GMP_NOTHROW; -+ + #define mp_bits_per_limb __gmp_bits_per_limb __GMP_DECLSPEC extern const int mp_bits_per_limb; -diff --git a/gmp-impl.h b/gmp-impl.h ---- a/gmp-impl.h -+++ b/gmp-impl.h -@@ -696,10 +696,12 @@ struct tmp_debug_entry_t { +diff -ru gmp-6.3.0/gmp-impl.h gmp-6.3.0.new/gmp-impl.h +--- gmp-6.3.0/gmp-impl.h 2023-07-29 09:42:16 ++++ gmp-6.3.0.new/gmp-impl.h 2023-12-30 16:02:36 +@@ -58,6 +58,8 @@ + short can be 24, 32, 46 or 64 bits, and different for ushort. */ + + #include ++#include ++#include + + /* For fat.h and other fat binary stuff. + No need for __GMP_ATTRIBUTE_PURE or __GMP_NOTHROW, since functions +@@ -699,14 +701,22 @@ __GMP_DECLSPEC extern void * (*__gmp_allocate_func) (size_t); __GMP_DECLSPEC extern void * (*__gmp_reallocate_func) (void *, size_t, size_t); __GMP_DECLSPEC extern void (*__gmp_free_func) (void *, size_t); @@ -31,10 +39,7 @@ diff --git a/gmp-impl.h b/gmp-impl.h #define __GMP_ALLOCATE_FUNC_TYPE(n,type) \ ((type *) (*__gmp_allocate_func) ((n) * sizeof (type))) -@@ -727,6 +729,12 @@ struct tmp_debug_entry_t { - (ptr, (oldsize) * sizeof (type), (newsize) * sizeof (type)); \ - } while (0) - + #define __GMP_ALLOCATE_FUNC_LIMBS(n) __GMP_ALLOCATE_FUNC_TYPE (n, mp_limb_t) +#define __GMP_ALLOC_OVERFLOW_FUNC() \ + do { \ + (*__gmp_alloc_overflow_func) (); \ @@ -42,12 +47,12 @@ diff --git a/gmp-impl.h b/gmp-impl.h + abort (); \ + } while (0) - /* Dummy for non-gcc, code involving it will go dead. */ - #if ! defined (__GNUC__) || __GNUC__ < 2 -diff --git a/memory.c b/memory.c ---- a/memory.c -+++ b/memory.c -@@ -38,6 +38,7 @@ see https://www.gnu.org/licenses/. */ + #define __GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \ + ((type *) (*__gmp_reallocate_func) \ +diff -ru gmp-6.3.0/memory.c gmp-6.3.0.new/memory.c +--- gmp-6.3.0/memory.c 2023-07-29 09:42:16 ++++ gmp-6.3.0.new/memory.c 2023-12-29 15:43:27 +@@ -37,6 +37,7 @@ void * (*__gmp_allocate_func) (size_t) = __gmp_default_allocate; void * (*__gmp_reallocate_func) (void *, size_t, size_t) = __gmp_default_reallocate; void (*__gmp_free_func) (void *, size_t) = __gmp_default_free; @@ -55,21 +60,22 @@ diff --git a/memory.c b/memory.c /* Default allocation functions. In case of failure to allocate/reallocate -@@ -144,3 +145,10 @@ void +@@ -142,4 +143,11 @@ + } #endif free (blk_ptr); - } ++} + +void +__gmp_default_alloc_overflow(void) +{ + fprintf (stderr, "gmp: overflow in mpz type\n"); + abort(); -+} -diff --git a/mp_get_fns.c b/mp_get_fns.c ---- a/mp_get_fns.c -+++ b/mp_get_fns.c -@@ -46,3 +46,11 @@ mp_get_memory_functions (void *(**alloc_ + } +diff -ru gmp-6.3.0/mp_get_fns.c gmp-6.3.0.new/mp_get_fns.c +--- gmp-6.3.0/mp_get_fns.c 2023-07-29 09:42:16 ++++ gmp-6.3.0.new/mp_get_fns.c 2023-12-29 15:43:27 +@@ -45,3 +45,11 @@ if (free_func != NULL) *free_func = __gmp_free_func; } @@ -81,10 +87,10 @@ diff --git a/mp_get_fns.c b/mp_get_fns.c + if (alloc_overflow_func != NULL) + *alloc_overflow_func = __gmp_alloc_overflow_func; +} -diff --git a/mp_set_fns.c b/mp_set_fns.c ---- a/mp_set_fns.c -+++ b/mp_set_fns.c -@@ -48,3 +48,12 @@ mp_set_memory_functions (void *(*alloc_f +diff -ru gmp-6.3.0/mp_set_fns.c gmp-6.3.0.new/mp_set_fns.c +--- gmp-6.3.0/mp_set_fns.c 2023-07-29 09:42:16 ++++ gmp-6.3.0.new/mp_set_fns.c 2023-12-29 15:43:27 +@@ -47,3 +47,12 @@ __gmp_reallocate_func = realloc_func; __gmp_free_func = free_func; } @@ -97,58 +103,66 @@ diff --git a/mp_set_fns.c b/mp_set_fns.c + alloc_overflow_func = __gmp_default_alloc_overflow; + __gmp_alloc_overflow_func = alloc_overflow_func; +} -diff --git a/mpz/init2.c b/mpz/init2.c ---- a/mpz/init2.c -+++ b/mpz/init2.c -@@ -45,8 +45,7 @@ mpz_init2 (mpz_ptr x, mp_bitcnt_t bits) +diff -ru gmp-6.3.0/mpz/init2.c gmp-6.3.0.new/mpz/init2.c +--- gmp-6.3.0/mpz/init2.c 2023-07-29 09:42:17 ++++ gmp-6.3.0.new/mpz/init2.c 2023-12-30 12:22:34 +@@ -41,7 +41,7 @@ + if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */ { if (UNLIKELY (new_alloc > INT_MAX)) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } +- MPZ_OVERFLOW; ++ __GMP_ALLOC_OVERFLOW_FUNC (); } -diff --git a/mpz/realloc.c b/mpz/realloc.c ---- a/mpz/realloc.c -+++ b/mpz/realloc.c -@@ -45,16 +45,14 @@ void * + PTR(x) = __GMP_ALLOCATE_FUNC_LIMBS (new_alloc); +diff -ru gmp-6.3.0/mpz/realloc.c gmp-6.3.0.new/mpz/realloc.c +--- gmp-6.3.0/mpz/realloc.c 2023-07-29 09:42:17 ++++ gmp-6.3.0.new/mpz/realloc.c 2023-12-30 12:22:47 +@@ -42,12 +42,12 @@ + if (sizeof (mp_size_t) == sizeof (int)) { if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS)) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } +- MPZ_OVERFLOW; ++ __GMP_ALLOC_OVERFLOW_FUNC (); } else { if (UNLIKELY (new_alloc > INT_MAX)) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } +- MPZ_OVERFLOW; ++ __GMP_ALLOC_OVERFLOW_FUNC (); } -diff --git a/mpz/realloc2.c b/mpz/realloc2.c ---- a/mpz/realloc2.c -+++ b/mpz/realloc2.c -@@ -45,8 +45,7 @@ mpz_realloc2 (mpz_ptr m, mp_bitcnt_t bit + if (ALLOC (m) == 0) +diff -ru gmp-6.3.0/mpz/realloc2.c gmp-6.3.0.new/mpz/realloc2.c +--- gmp-6.3.0/mpz/realloc2.c 2023-07-29 09:42:17 ++++ gmp-6.3.0.new/mpz/realloc2.c 2023-12-30 12:22:59 +@@ -42,7 +42,7 @@ + if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */ { if (UNLIKELY (new_alloc > INT_MAX)) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } +- MPZ_OVERFLOW; ++ __GMP_ALLOC_OVERFLOW_FUNC (); } -diff --git a/tests/mpz/t-pow.c b/tests/mpz/t-pow.c ---- a/tests/mpz/t-pow.c -+++ b/tests/mpz/t-pow.c -@@ -195,6 +195,34 @@ check_random (int reps) + if (ALLOC (m) == 0) +diff -ru gmp-6.3.0/tal-reent.c gmp-6.3.0.new/tal-reent.c +--- gmp-6.3.0/tal-reent.c 2023-07-29 09:42:17 ++++ gmp-6.3.0.new/tal-reent.c 2023-12-30 12:19:40 +@@ -61,6 +61,10 @@ + + total_size = size + HSIZ; + p = __GMP_ALLOCATE_FUNC_TYPE (total_size, char); ++ if (!p) ++ { ++ __GMP_ALLOC_OVERFLOW_FUNC (); ++ } + P->size = total_size; + P->next = *markp; + *markp = P; +diff -ru gmp-6.3.0/tests/mpz/t-pow.c gmp-6.3.0.new/tests/mpz/t-pow.c +--- gmp-6.3.0/tests/mpz/t-pow.c 2023-07-29 09:42:17 ++++ gmp-6.3.0.new/tests/mpz/t-pow.c 2023-12-30 15:57:58 +@@ -194,6 +194,33 @@ mpz_clear (want); } @@ -178,12 +192,11 @@ diff --git a/tests/mpz/t-pow.c b/tests/mpz/t-pow.c + } + mpz_clear (x); +} -+ + int main (int argc, char **argv) { -@@ -212,6 +240,7 @@ main (int argc, char **argv) +@@ -211,6 +238,7 @@ check_various (); check_random (reps); diff --git a/deps/patches/gmp-more_alloc_overflow.patch b/deps/patches/gmp-more_alloc_overflow.patch deleted file mode 100644 index 597f0d52d73e7..0000000000000 --- a/deps/patches/gmp-more_alloc_overflow.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -ur a/mpz/n_pow_ui.c b/mpz/n_pow_ui.c ---- a/mpz/n_pow_ui.c -+++ b/mpz/n_pow_ui.c -@@ -220,8 +220,7 @@ - umul_ppmm (ovfl, rtwos_bits, e, btwos); - if (ovfl) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } - - rtwos_limbs += rtwos_bits / GMP_NUMB_BITS; -@@ -382,8 +381,7 @@ - umul_ppmm (ovfl, ralloc, (bsize*GMP_NUMB_BITS - cnt + GMP_NAIL_BITS), e); - if (ovfl) - { -- fprintf (stderr, "gmp: overflow in mpz type\n"); -- abort (); -+ __GMP_ALLOC_OVERFLOW_FUNC (); - } - ralloc = ralloc / GMP_NUMB_BITS + 5; - -diff -ur a/tal-reent.c b/tal-reent.c ---- a/tal-reent.c -+++ b/tal-reent.c -@@ -61,6 +61,10 @@ - - total_size = size + HSIZ; - p = __GMP_ALLOCATE_FUNC_TYPE (total_size, char); -+ if (!p) -+ { -+ __GMP_ALLOC_OVERFLOW_FUNC (); -+ } - P->size = total_size; - P->next = *markp; - *markp = P; diff --git a/doc/Manifest.toml b/doc/Manifest.toml index f3e4b08306bd2..b34942bbddd3a 100644 --- a/doc/Manifest.toml +++ b/doc/Manifest.toml @@ -134,6 +134,7 @@ uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" version = "1.17.0+0" [[deps.Logging]] +deps = ["StyledStrings"] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" version = "1.11.0" diff --git a/doc/man/julia.1 b/doc/man/julia.1 index ee0f973c259fd..a060c6dffb6b8 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -93,8 +93,10 @@ Enable or disable Julia's default signal handlers Use native code from system image if available .TP ---compiled-modules={yes*|no|existing} +--compiled-modules={yes*|no|existing|strict} Enable or disable incremental precompilation of modules. +The "existing" option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files. +The "strict" option is similar, but will error if no precompile file is found. .TP --pkgimages={yes*|no|existing} diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 909f968b30baf..9d68d55be3459 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -225,14 +225,15 @@ Base.valtype Fully implemented by: - * [`IdDict`](@ref) * [`Dict`](@ref) + * [`IdDict`](@ref) * [`WeakKeyDict`](@ref) Partially implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) * [`EnvDict`](@ref Base.EnvDict) * [`Array`](@ref) * [`BitArray`](@ref) @@ -246,6 +247,7 @@ Partially implemented by: Base.AbstractSet Base.Set Base.BitSet +Base.IdSet Base.union Base.union! Base.intersect @@ -264,8 +266,10 @@ Base.isdisjoint Fully implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) + Partially implemented by: diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index f829b27663e62..c2cd0e92d58d2 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -627,6 +627,10 @@ for important details on how to modify these fields safely. The `MethodInstance` that this cache entry is derived from. + * `owner` + + A token that represents the owner of this `CodeInstance`. Will use `jl_egal` to match. + * `rettype`/`rettype_const` diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index f79f4f2b1e3e3..50cdd738e3b34 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -155,6 +155,7 @@ MethodInstance/CodeInstance updates : Method->writelock, codegen lock > * specTypes > * sparam_vals > * def +> * owner > * These are set by `jl_type_infer` (while holding codegen lock): > * cache diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 13b289becf6e0..6aa3a7a724e0e 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -889,7 +889,7 @@ in their implementations, other arrays — like [`Diagonal`](@ref) — need the full set of cartesian indices to do their lookup (see [`IndexStyle`](@ref) to introspect which is which). -!!! warnings +!!! warning When iterating over all the indices for an array, it is better to iterate over [`eachindex(A)`](@ref) instead of `1:length(A)`. diff --git a/doc/src/manual/command-line-interface.md b/doc/src/manual/command-line-interface.md index b27c6bee1be38..d56b27622532c 100644 --- a/doc/src/manual/command-line-interface.md +++ b/doc/src/manual/command-line-interface.md @@ -172,7 +172,7 @@ The following is a complete list of command-line switches available when launchi |`--startup-file={yes*\|no}` |Load `JULIA_DEPOT_PATH/config/startup.jl`; if [`JULIA_DEPOT_PATH`](@ref JULIA_DEPOT_PATH) environment variable is unset, load `~/.julia/config/startup.jl`| |`--handle-signals={yes*\|no}` |Enable or disable Julia's default signal handlers| |`--sysimage-native-code={yes*\|no}` |Use native code from system image if available| -|`--compiled-modules={yes*\|no\|existing}` |Enable or disable incremental precompilation of modules. The `existing` option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files.| +|`--compiled-modules={yes*\|no\|existing|strict}` |Enable or disable incremental precompilation of modules. The `existing` option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files. The `strict` option is similar, but will error if no precompile file is found. | |`--pkgimages={yes*\|no}` |Enable or disable usage of native code caching in the form of pkgimages| |`-e`, `--eval ` |Evaluate ``| |`-E`, `--print ` |Evaluate `` and display the result| diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 2cfa6e25503d2..f8b9dd9673082 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -379,6 +379,8 @@ The type `Point` exists, but no method is defined for this combination of argume Closest candidates are: Point(::T, !Matched::T) where T<:Real @ Main none:1 + Point(!Matched::Int64, !Matched::Float64) + @ Main none:1 Stacktrace: [...] diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index dd372ccbc53d4..020181dd0a08c 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -270,10 +270,11 @@ julia> addprocs(2) Module [`Distributed`](@ref man-distributed) must be explicitly loaded on the master process before invoking [`addprocs`](@ref). It is automatically made available on the worker processes. -Note that workers do not run a `~/.julia/config/startup.jl` startup script, nor do they synchronize -their global state (such as global variables, new method definitions, and loaded modules) with any -of the other running processes. You may use `addprocs(exeflags="--project")` to initialize a worker with -a particular environment, and then `@everywhere using ` or `@everywhere include("file.jl")`. +!!! note + Note that workers do not run a `~/.julia/config/startup.jl` startup script, nor do they synchronize + their global state (such as command-line switches, global variables, new method definitions, and loaded modules) with any + of the other running processes. You may use `addprocs(exeflags="--project")` to initialize a worker with + a particular environment, and then `@everywhere using ` or `@everywhere include("file.jl")`. Other types of clusters can be supported by writing your own custom `ClusterManager`, as described below in the [ClusterManagers](@ref) section. @@ -813,16 +814,18 @@ will always operate on copies of arguments. ## [Shared Arrays](@id man-shared-arrays) -Shared Arrays use system shared memory to map the same array across many processes. While there -are some similarities to a [`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl), the -behavior of a [`SharedArray`](@ref) is quite different. In a [`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl), -each process has local access to just a chunk of the data, and no two processes share the same -chunk; in contrast, in a [`SharedArray`](@ref) each "participating" process has access to the -entire array. A [`SharedArray`](@ref) is a good choice when you want to have a large amount of -data jointly accessible to two or more processes on the same machine. +Shared Arrays use system shared memory to map the same array across many processes. A +[`SharedArray`](@ref) is a good choice when you want to have a large amount of data jointly +accessible to two or more processes on the same machine. Shared Array support is available via the +module `SharedArrays`, which must be explicitly loaded on all participating workers. -Shared Array support is available via module `SharedArrays` which must be explicitly loaded on -all participating workers. +A complementary data structure is provided by the external package +[`DistributedArrays.jl`](https://github.com/JuliaParallel/DistributedArrays.jl) in the form of a +`DArray`. While there are some similarities to a [`SharedArray`](@ref), the behavior of a +[`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl) is quite different. In a +[`SharedArray`](@ref), each "participating" process has access to the entire array; in contrast, in +a [`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl), each process has local access +to just a chunk of the data, and no two processes share the same chunk. [`SharedArray`](@ref) indexing (assignment and accessing values) works just as with regular arrays, and is efficient because the underlying memory is available to the local process. Therefore, @@ -1326,8 +1329,11 @@ in future releases. ## Noteworthy external packages Outside of Julia parallelism there are plenty of external packages that should be mentioned. -For example [MPI.jl](https://github.com/JuliaParallel/MPI.jl) is a Julia wrapper for the `MPI` protocol, [Dagger.jl](https://github.com/JuliaParallel/Dagger.jl) provides functionality similar to Python's [Dask](https://dask.org/), and -[DistributedArrays.jl](https://github.com/JuliaParallel/Distributedarrays.jl) provides array operations distributed across workers, as presented in [Shared Arrays](@ref). +For example, [`MPI.jl`](https://github.com/JuliaParallel/MPI.jl) is a Julia wrapper for the `MPI` +protocol, [`Dagger.jl`](https://github.com/JuliaParallel/Dagger.jl) provides functionality similar to +Python's [Dask](https://dask.org/), and +[`DistributedArrays.jl`](https://github.com/JuliaParallel/Distributedarrays.jl) provides array +operations distributed across workers, as [outlined above](@ref man-shared-arrays). A mention must be made of Julia's GPU programming ecosystem, which includes: diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 41eb4e4d6dde5..47b8b84dda1b6 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -434,10 +434,13 @@ Adds docstring `"..."` to the `@m(::Any)` macro definition. ```julia "..." -:(@m) +:(@m1) + +"..." +macro m2 end ``` -Adds docstring `"..."` to the macro named `@m`. +Adds docstring `"..."` to the macros named `@m1` and `@m2`. ### Types @@ -458,6 +461,20 @@ end Adds the docstring `"..."` to types `T1`, `T2`, and `T3`. +``` +"..." +T1 + +"..." +T2 + +"..." +T3 +``` + +Adds the docstring `"..."` to types `T1`, `T2`, and `T3`. +The previous version is the preferred syntax, however both are equivalent. + ```julia "..." struct T diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index f59dee225e1a7..9df9a6c198003 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -247,7 +247,7 @@ Its second argument `args` is an array of `jl_value_t*` arguments and `nargs` is arguments. There is also an alternative, possibly simpler, way of calling Julia functions and that is via [`@cfunction`](@ref). -Using `@cfunction` allows you to do the type conversions on the Julia side which typically is easier than doing it on +Using `@cfunction` allows you to do the type conversions on the Julia side, which is typically easier than doing it on the C side. The `sqrt` example above would with `@cfunction` be written as: ```c @@ -255,7 +255,10 @@ double (*sqrt_jl)(double) = jl_unbox_voidpointer(jl_eval_string("@cfunction(sqrt double ret = sqrt_jl(2.0); ``` -where we first define a C callable function in Julia, extract the function pointer from it and finally call it. +where we first define a C callable function in Julia, extract the function pointer from it, and finally call it. +In addition to simplifying type conversions by doing them in the higher-level language, calling Julia functions +via `@cfunction` pointers eliminates the dynamic-dispatch overhead required by `jl_call` (for which all of the +arguments are "boxed"), and should have performance equivalent to native C function pointers. ## Memory Management diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 59af063ce8487..c333aeb56c5d9 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -394,7 +394,7 @@ Julia applies the following order and associativity of operations, from highest |:-------------- |:------------------------------------------------------------------------------------------------- |:-------------------------- | | Syntax | `.` followed by `::` | Left | | Exponentiation | `^` | Right | -| Unary | `+ - √` | Right[^1] | +| Unary | `+ - ! ~ ¬ √ ∛ ∜ ⋆ ± ∓ <: >:` | Right[^1] | | Bitshifts | `<< >> >>>` | Left | | Fractions | `//` | Left | | Multiplication | `* / % & \ ÷` | Left[^2] | diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 4745ae886e8d0..6b90990a6dd7c 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -173,6 +173,8 @@ The function `f` exists, but no method is defined for this combination of argume Closest candidates are: f(!Matched::Number, ::Number) @ Main none:1 + f(!Matched::Float64, !Matched::Float64) + @ Main none:1 Stacktrace: [...] diff --git a/pkgimage.mk b/pkgimage.mk index 9a46a8d581bf8..c9de49d2f8421 100644 --- a/pkgimage.mk +++ b/pkgimage.mk @@ -69,6 +69,9 @@ cache-debug-$1: $$(BUILDDIR)/stdlib/$1.debug.image .SECONDARY: $$(BUILDDIR)/stdlib/$1.release.image $$(BUILDDIR)/stdlib/$1.debug.image endef +# Note: you can check for the correctness of this tree by running `JULIA_DEBUG=nested_precomp make` and looking +# out for `Debug: Nested precompilation` logs. + # no dependencies $(eval $(call stdlib_builder,MozillaCACerts_jll,)) $(eval $(call stdlib_builder,ArgTools,)) @@ -77,7 +80,6 @@ $(eval $(call stdlib_builder,Base64,)) $(eval $(call stdlib_builder,CRC32c,)) $(eval $(call stdlib_builder,FileWatching,)) $(eval $(call stdlib_builder,Libdl,)) -$(eval $(call stdlib_builder,Logging,)) $(eval $(call stdlib_builder,Mmap,)) $(eval $(call stdlib_builder,NetworkOptions,)) $(eval $(call stdlib_builder,SHA,)) @@ -106,6 +108,7 @@ $(eval $(call stdlib_builder,OpenBLAS_jll,Artifacts Libdl)) $(eval $(call stdlib_builder,Markdown,Base64)) $(eval $(call stdlib_builder,Printf,Unicode)) $(eval $(call stdlib_builder,Random,SHA)) +$(eval $(call stdlib_builder,Logging,StyledStrings)) $(eval $(call stdlib_builder,Tar,ArgTools,SHA)) $(eval $(call stdlib_builder,DelimitedFiles,Mmap)) $(eval $(call stdlib_builder,JuliaSyntaxHighlighting,StyledStrings)) diff --git a/src/builtins.c b/src/builtins.c index 412ccaf8bab04..29aec53ae5a40 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2378,6 +2378,7 @@ jl_fptr_args_t jl_get_builtin_fptr(jl_datatype_t *dt) jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_atomic_load_relaxed(&dt->name->mt->defs); jl_method_instance_t *mi = jl_atomic_load_relaxed(&entry->func.method->unspecialized); jl_code_instance_t *ci = jl_atomic_load_relaxed(&mi->cache); + assert(ci->owner == jl_nothing); return jl_atomic_load_relaxed(&ci->specptr.fptr1); } diff --git a/src/gf.c b/src/gf.c index e8a5f7450b724..00613cf9da486 100644 --- a/src/gf.c +++ b/src/gf.c @@ -316,7 +316,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a jl_atomic_store_relaxed(&m->unspecialized, mi); jl_gc_wb(m, mi); - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, jl_nothing, jl_nothing, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, codeinst); @@ -437,11 +437,13 @@ JL_DLLEXPORT jl_value_t *jl_call_in_typeinf_world(jl_value_t **args, int nargs) return ret; } -JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +STATIC_INLINE jl_value_t *_jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT { jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache); while (codeinst) { - if (jl_atomic_load_relaxed(&codeinst->min_world) <= min_world && max_world <= jl_atomic_load_relaxed(&codeinst->max_world)) { + if (jl_atomic_load_relaxed(&codeinst->min_world) <= min_world && + max_world <= jl_atomic_load_relaxed(&codeinst->max_world) && + jl_egal(codeinst->owner, owner)) { jl_value_t *code = jl_atomic_load_relaxed(&codeinst->inferred); if (code && (code == jl_nothing || jl_ir_flag_inferred(code))) return (jl_value_t*)codeinst; @@ -450,24 +452,37 @@ JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *mi, size_t mi } return (jl_value_t*)jl_nothing; } -JL_DLLEXPORT jl_value_t *(*const jl_rettype_inferred_addr)(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT = jl_rettype_inferred; + +JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +{ + return (jl_value_t*)_jl_rettype_inferred(owner, mi, min_world, max_world); +} + +JL_DLLEXPORT jl_value_t *jl_rettype_inferred_native(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +{ + return (jl_value_t*)_jl_rettype_inferred(jl_nothing, mi, min_world, max_world); +} + +JL_DLLEXPORT jl_value_t *(*const jl_rettype_inferred_addr)(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT = jl_rettype_inferred_native; JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred( jl_method_instance_t *mi JL_PROPAGATES_ROOT, jl_value_t *rettype, size_t min_world, size_t max_world) { + jl_value_t *owner = jl_nothing; // TODO: owner should be arg jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache); while (codeinst) { if (jl_atomic_load_relaxed(&codeinst->min_world) == min_world && jl_atomic_load_relaxed(&codeinst->max_world) == max_world && + jl_egal(codeinst->owner, owner) && jl_egal(codeinst->rettype, rettype)) { return codeinst; } codeinst = jl_atomic_load_relaxed(&codeinst->next); } codeinst = jl_new_codeinst( - mi, rettype, (jl_value_t*)jl_any_type, NULL, NULL, + mi, owner, rettype, (jl_value_t*)jl_any_type, NULL, NULL, 0, min_world, max_world, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, codeinst); return codeinst; @@ -484,7 +499,8 @@ JL_DLLEXPORT jl_code_instance_t *jl_get_codeinst_for_src( } JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( - jl_method_instance_t *mi, jl_value_t *rettype, jl_value_t *exctype, + jl_method_instance_t *mi, jl_value_t *owner, + jl_value_t *rettype, jl_value_t *exctype, jl_value_t *inferred_const, jl_value_t *inferred, int32_t const_flags, size_t min_world, size_t max_world, uint32_t ipo_effects, uint32_t effects, jl_value_t *analysis_results, @@ -496,6 +512,7 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_instance_t), jl_code_instance_type); codeinst->def = mi; + codeinst->owner = owner; jl_atomic_store_relaxed(&codeinst->min_world, min_world); jl_atomic_store_relaxed(&codeinst->max_world, max_world); codeinst->rettype = rettype; @@ -548,7 +565,7 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) if (!jl_is_svec(specializations)) { jl_method_instance_t *mi = (jl_method_instance_t*)specializations; assert(jl_is_method_instance(mi)); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi); return 1; } @@ -558,7 +575,7 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); if ((jl_value_t*)mi != jl_nothing) { assert(jl_is_method_instance(mi)); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi); } } @@ -678,7 +695,7 @@ JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f) size_t i, l; for (i = 0, l = jl_array_nrows(unspec); i < l; i++) { jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(unspec, i); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_type_infer(mi, world, 1); } JL_GC_POP(); @@ -1627,41 +1644,6 @@ JL_DLLEXPORT jl_value_t *jl_debug_method_invalidation(int state) return jl_nothing; } -// call external callbacks registered with this method_instance -static void invalidate_external(jl_method_instance_t *mi, size_t max_world) { - jl_array_t *callbacks = mi->callbacks; - if (callbacks) { - // AbstractInterpreter allows for MethodInstances to be present in non-local caches - // inform those caches about the invalidation. - JL_TRY { - size_t i, l = jl_array_nrows(callbacks); - jl_value_t **args; - JL_GC_PUSHARGS(args, 3); - // these arguments are constant per call - args[1] = (jl_value_t*)mi; - args[2] = jl_box_uint32(max_world); - - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - - jl_value_t **cbs = (jl_value_t**)jl_array_ptr_data(callbacks); - for (i = 0; i < l; i++) { - args[0] = cbs[i]; - jl_apply(args, 3); - } - ct->world_age = last_age; - JL_GC_POP(); - } - JL_CATCH { - jl_printf((JL_STREAM*)STDERR_FILENO, "error in invalidation callback: "); - jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception()); - jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); - jlbacktrace(); // written to STDERR_FILENO - } - } -} - static void _invalidate_backedges(jl_method_instance_t *replaced_mi, size_t max_world, int depth); // recursively invalidate cached methods that had an edge to a replaced method @@ -1690,7 +1672,6 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma codeinst = jl_atomic_load_relaxed(&codeinst->next); } JL_GC_PUSH1(&replaced); - invalidate_external(replaced, max_world); // recurse to all backedges to update their valid range also _invalidate_backedges(replaced, max_world, depth + 1); JL_GC_POP(); @@ -1839,7 +1820,6 @@ static int invalidate_mt_cache(jl_typemap_entry_t *oldentry, void *closure0) } } if (intersects) { - // TODO call invalidate_external here? if (_jl_debug_method_invalidation) { jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi); jl_value_t *loctag = jl_cstr_to_string("invalidate_mt_cache"); @@ -1924,7 +1904,6 @@ static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *m jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); if ((jl_value_t*)mi != jl_nothing) { invalidated = 1; - invalidate_external(mi, max_world); invalidate_backedges(mi, max_world, "jl_method_table_disable"); } } @@ -2202,7 +2181,6 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry) jl_array_del_end(backedges, nb - insb); } jl_array_ptr_1d_push(oldmi, (jl_value_t*)mi); - invalidate_external(mi, max_world); if (_jl_debug_method_invalidation && invalidated) { jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi); loctag = jl_cstr_to_string("jl_method_table_insert"); @@ -2302,7 +2280,7 @@ static jl_tupletype_t *lookup_arg_type_tuple(jl_value_t *arg1 JL_PROPAGATES_ROOT return jl_lookup_arg_tuple_type(arg1, args, nargs, 1); } -JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt) +JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt) { jl_methtable_t *mt = NULL; if (_mt == jl_nothing) @@ -2311,7 +2289,10 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, si assert(jl_isa(_mt, (jl_value_t*)jl_methtable_type)); mt = (jl_methtable_t*) _mt; } - return jl_mt_assoc_by_type(mt, tt, world); + jl_method_instance_t* mi = jl_mt_assoc_by_type(mt, tt, world); + if (!mi) + return jl_nothing; + return (jl_value_t*) mi; } JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world) @@ -2503,7 +2484,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t jl_code_instance_t *unspec = jl_atomic_load_relaxed(&unspecmi->cache); jl_callptr_t unspec_invoke = NULL; if (unspec && (unspec_invoke = jl_atomic_load_acquire(&unspec->invoke))) { - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); void *unspec_fptr = jl_atomic_load_relaxed(&unspec->specptr.fptr); @@ -2530,7 +2511,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t compile_option == JL_OPTIONS_COMPILE_MIN) { jl_code_info_t *src = jl_code_for_interpreter(mi, world); if (!jl_code_requires_compiler(src, 0)) { - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); jl_atomic_store_release(&codeinst->invoke, jl_fptr_interpret_call); @@ -2565,7 +2546,8 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t // only these care about the exact specTypes, otherwise we can use it directly return ucache; } - codeinst = jl_new_codeinst(mi, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, + codeinst = jl_new_codeinst(mi, jl_nothing, + (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); void *unspec_fptr = jl_atomic_load_relaxed(&ucache->specptr.fptr); if (unspec_fptr) { @@ -2815,10 +2797,10 @@ static jl_method_instance_t *jl_get_compile_hint_specialization(jl_tupletype_t * static void _generate_from_hint(jl_method_instance_t *mi, size_t world) { - jl_value_t *codeinst = jl_rettype_inferred(mi, world, world); + jl_value_t *codeinst = jl_rettype_inferred_native(mi, world, world); if (codeinst == jl_nothing) { (void)jl_type_infer(mi, world, 1); - codeinst = jl_rettype_inferred(mi, world, world); + codeinst = jl_rettype_inferred_native(mi, world, world); } if (codeinst != jl_nothing) { if (jl_atomic_load_relaxed(&((jl_code_instance_t*)codeinst)->invoke) == jl_fptr_const_return) @@ -2857,10 +2839,10 @@ JL_DLLEXPORT void jl_compile_method_instance(jl_method_instance_t *mi, jl_tuplet jl_method_instance_t *mi2 = jl_specializations_get_linfo(mi->def.method, (jl_value_t*)types2, tpenv2); JL_GC_POP(); jl_atomic_store_relaxed(&mi2->precompiled, 1); - if (jl_rettype_inferred(mi2, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi2, world, world) == jl_nothing) (void)jl_type_infer(mi2, world, 1); if (jl_typeinf_func && jl_atomic_load_relaxed(&mi->def.method->primary_world) <= tworld) { - if (jl_rettype_inferred(mi2, tworld, tworld) == jl_nothing) + if (jl_rettype_inferred_native(mi2, tworld, tworld) == jl_nothing) (void)jl_type_infer(mi2, tworld, 1); } } diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 138bde4a0830a..a72058f10f42d 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -112,7 +112,6 @@ XX(jl_enter_handler) \ XX(jl_enter_threaded_region) \ XX(jl_environ) \ - XX(jl_eof_error) \ XX(jl_eqtable_get) \ XX(jl_eqtable_pop) \ XX(jl_eqtable_put) \ @@ -239,8 +238,6 @@ XX(jl_method_lookup_by_tt) \ XX(jl_method_lookup) \ XX(jl_gf_invoke_lookup_worlds) \ - XX(jl_git_branch) \ - XX(jl_git_commit) \ XX(jl_global_event_loop) \ XX(jl_has_empty_intersection) \ XX(jl_has_free_typevars) \ @@ -436,7 +433,6 @@ XX(jl_stderr_obj) \ XX(jl_stderr_stream) \ XX(jl_stdin_stream) \ - XX(jl_stdout_obj) \ XX(jl_stdout_stream) \ XX(jl_stored_inline) \ XX(jl_string_ptr) \ @@ -516,7 +512,6 @@ XX(jl_vprintf) \ XX(jl_wakeup_thread) \ XX(jl_write_compiler_output) \ - XX(jl_yield) \ #define JL_RUNTIME_EXPORTED_FUNCS_WIN(XX) \ XX(jl_setjmp) \ diff --git a/src/jl_uv.c b/src/jl_uv.c index dca08f5ddd91d..e447faf8fa9c2 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -39,21 +39,24 @@ static void walk_print_cb(uv_handle_t *h, void *arg) const char *type = uv_handle_type_name(h->type); if (!type) type = ""; + size_t resource_id; // fits an int or pid_t on Unix, HANDLE or PID on Windows uv_os_fd_t fd; if (h->type == UV_PROCESS) - fd = uv_process_get_pid((uv_process_t*)h); - else if (uv_fileno(h, &fd)) - fd = (uv_os_fd_t)-1; + resource_id = (size_t)uv_process_get_pid((uv_process_t*)h); + else if (uv_fileno(h, &fd) == 0) + resource_id = (size_t)fd; + else + resource_id = -1; const char *pad = " "; // 16 spaces - int npad = fd == -1 ? 0 : snprintf(NULL, 0, "%zd", (size_t)fd); + int npad = resource_id == -1 ? 0 : snprintf(NULL, 0, "%zd", resource_id); if (npad < 0) npad = 0; npad += strlen(type); pad += npad < strlen(pad) ? npad : strlen(pad); - if (fd == -1) + if (resource_id == -1) jl_safe_printf(" %s %s%p->%p\n", type, pad, (void*)h, (void*)h->data); else - jl_safe_printf(" %s[%zd] %s%p->%p\n", type, (size_t)fd, pad, (void*)h, (void*)h->data); + jl_safe_printf(" %s[%zd] %s%p->%p\n", type, resource_id, pad, (void*)h, (void*)h->data); } static void wait_empty_func(uv_timer_t *t) @@ -662,25 +665,6 @@ JL_DLLEXPORT int jl_fs_read(uv_os_fd_t handle, char *data, size_t len) return ret; } -JL_DLLEXPORT int jl_fs_read_byte(uv_os_fd_t handle) -{ - uv_fs_t req; - unsigned char c; - uv_buf_t buf[1]; - buf[0].base = (char*)&c; - buf[0].len = 1; - int ret = uv_fs_read(unused_uv_loop_arg, &req, handle, buf, 1, -1, NULL); - uv_fs_req_cleanup(&req); - switch (ret) { - case -1: return ret; - case 0: jl_eof_error(); - case 1: return (int)c; - default: - assert(0 && "jl_fs_read_byte: Invalid return value from uv_fs_read"); - return -1; - } -} - JL_DLLEXPORT int jl_fs_close(uv_os_fd_t handle) { uv_fs_t req; @@ -1129,31 +1113,39 @@ static inline int ishexchar(char c) JL_DLLEXPORT int jl_ispty(uv_pipe_t *pipe) { - if (pipe->type != UV_NAMED_PIPE) return 0; + char namebuf[0]; size_t len = 0; - if (uv_pipe_getpeername(pipe, NULL, &len) != UV_ENOBUFS) return 0; + if (pipe->type != UV_NAMED_PIPE) + return 0; + if (uv_pipe_getpeername(pipe, namebuf, &len) != UV_ENOBUFS) + return 0; char *name = (char*)alloca(len + 1); - if (uv_pipe_getpeername(pipe, name, &len)) return 0; + if (uv_pipe_getpeername(pipe, name, &len)) + return 0; name[len] = '\0'; // return true if name matches regex: // ^\\\\?\\pipe\\(msys|cygwin)-[0-9a-z]{16}-[pt]ty[1-9][0-9]*- //jl_printf(JL_STDERR,"pipe_name: %s\n", name); int n = 0; - if (!strncmp(name,"\\\\?\\pipe\\msys-",14)) + if (!strncmp(name, "\\\\?\\pipe\\msys-", 14)) n = 14; - else if (!strncmp(name,"\\\\?\\pipe\\cygwin-",16)) + else if (!strncmp(name, "\\\\?\\pipe\\cygwin-", 16)) n = 16; else return 0; //jl_printf(JL_STDERR,"prefix pass\n"); name += n; for (int n = 0; n < 16; n++) - if (!ishexchar(*name++)) return 0; + if (!ishexchar(*name++)) + return 0; //jl_printf(JL_STDERR,"hex pass\n"); - if ((*name++)!='-') return 0; - if (*name != 'p' && *name != 't') return 0; + if ((*name++)!='-') + return 0; + if (*name != 'p' && *name != 't') + return 0; name++; - if (*name++ != 't' || *name++ != 'y') return 0; + if (*name++ != 't' || *name++ != 'y') + return 0; //jl_printf(JL_STDERR,"tty pass\n"); return 1; } diff --git a/src/jlapi.c b/src/jlapi.c index bde8b4f9f1245..276a792b2cd66 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -437,20 +437,6 @@ JL_DLLEXPORT jl_value_t *jl_call3(jl_function_t *f, jl_value_t *a, return v; } -/** - * @brief Yield to the Julia scheduler. - * - * Yields control to the Julia scheduler, allowing other Julia tasks to run. - */ -JL_DLLEXPORT void jl_yield(void) -{ - static jl_function_t *yieldfunc = NULL; - if (yieldfunc == NULL) - yieldfunc = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("yield")); - if (yieldfunc != NULL) - jl_call0(yieldfunc); -} - /** * @brief Get a field from a Julia object. * @@ -619,41 +605,6 @@ JL_DLLEXPORT const char *jl_ver_string(void) return JULIA_VERSION_STRING; } -// return char* from String field in Base.GIT_VERSION_INFO -static const char *git_info_string(const char *fld) -{ - static jl_value_t *GIT_VERSION_INFO = NULL; - if (!GIT_VERSION_INFO) - GIT_VERSION_INFO = jl_get_global(jl_base_module, jl_symbol("GIT_VERSION_INFO")); - jl_value_t *f = jl_get_field(GIT_VERSION_INFO, fld); - assert(jl_is_string(f)); - return jl_string_data(f); -} - -/** - * @brief Get the name of the Git branch for the Julia build. - * - * @return A C string containing the name of the Git branch. - */ -JL_DLLEXPORT const char *jl_git_branch(void) -{ - static const char *branch = NULL; - if (!branch) branch = git_info_string("branch"); - return branch; -} - -/** - * @brief Get the Git commit hash for the Julia build. - * - * @return A C string containing the Git commit hash. - */ -JL_DLLEXPORT const char *jl_git_commit(void) -{ - static const char *commit = NULL; - if (!commit) commit = git_info_string("commit"); - return commit; -} - /** * @brief Convert a Julia value to a tagged value. * diff --git a/src/jloptions.c b/src/jloptions.c index 5d627687a38be..fa5d4ff43ee04 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -110,7 +110,7 @@ static const char opts[] = " --handle-signals={yes*|no} Enable or disable Julia's default signal handlers\n" " --sysimage-native-code={yes*|no}\n" " Use native code from system image if available\n" - " --compiled-modules={yes*|no|existing}\n" + " --compiled-modules={yes*|no|existing|strict}\n" " Enable or disable incremental precompilation of modules\n" " --pkgimages={yes*|no|existing}\n" " Enable or disable usage of native code caching in the form of pkgimages ($)\n\n" @@ -464,8 +464,10 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_NO; else if (!strcmp(optarg,"existing")) jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_EXISTING; + else if (!strcmp(optarg,"strict")) + jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_STRICT; else - jl_errorf("julia: invalid argument to --compiled-modules={yes|no|existing} (%s)", optarg); + jl_errorf("julia: invalid argument to --compiled-modules={yes|no|existing|strict} (%s)", optarg); break; case opt_pkgimages: if (!strcmp(optarg,"yes")) diff --git a/src/jltypes.c b/src/jltypes.c index 84e90303affaa..bf7561fc29e1b 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3265,25 +3265,23 @@ void jl_init_types(void) JL_GC_DISABLED jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(10, + jl_perm_symsvec(9, "def", "specTypes", "sparam_vals", "uninferred", "backedges", - "callbacks", "cache", "inInference", "cache_with_orig", "precompiled"), - jl_svec(10, + jl_svec(9, jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), jl_any_type, jl_simplevector_type, jl_any_type, jl_array_any_type, jl_any_type, - jl_any_type, jl_bool_type, jl_bool_type, jl_bool_type), @@ -3291,7 +3289,7 @@ void jl_init_types(void) JL_GC_DISABLED 0, 1, 3); // These fields should be constant, but Serialization wants to mutate them in initialization //const static uint32_t method_instance_constfields[1] = { 0x00000007 }; // (1<<0)|(1<<1)|(1<<2); - const static uint32_t method_instance_atomicfields[1] = { 0x00000248 }; // (1<<3)|(1<<6)|(1<<9); + const static uint32_t method_instance_atomicfields[1] = { 0x00000128 }; // (1<<3)|(1<<5)|(1<<8); //Fields 4 and 5 must be protected by method->write_lock, and thus all operations on jl_method_instance_t are threadsafe. TODO: except inInference //jl_method_instance_type->name->constfields = method_instance_constfields; jl_method_instance_type->name->atomicfields = method_instance_atomicfields; @@ -3299,8 +3297,9 @@ void jl_init_types(void) JL_GC_DISABLED jl_code_instance_type = jl_new_datatype(jl_symbol("CodeInstance"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(16, + jl_perm_symsvec(17, "def", + "owner", "next", "min_world", "max_world", @@ -3312,11 +3311,12 @@ void jl_init_types(void) JL_GC_DISABLED //"absolute_max", "ipo_purity_bits", "purity_bits", "analysis_results", - "isspecsig", "precompile", "relocatability", + "specsigflags", "precompile", "relocatability", "invoke", "specptr"), // function object decls - jl_svec(16, + jl_svec(17, jl_method_instance_type, jl_any_type, + jl_any_type, jl_ulong_type, jl_ulong_type, jl_any_type, @@ -3333,11 +3333,11 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_any_type), // fptrs jl_emptysvec, 0, 1, 1); - jl_svecset(jl_code_instance_type->types, 1, jl_code_instance_type); - const static uint32_t code_instance_constfields[1] = { 0b0000010101110001 }; // Set fields 1, 5-7, 9, 11 as const - const static uint32_t code_instance_atomicfields[1] = { 0b1101001010001110 }; // Set fields 2-4, 8, 10, 13, 15-16 as atomic - //Fields 3-4 are only operated on by construction and deserialization, so are const at runtime - //Fields 11 and 15 must be protected by locks, and thus all operations on jl_code_instance_t are threadsafe + jl_svecset(jl_code_instance_type->types, 2, jl_code_instance_type); + const static uint32_t code_instance_constfields[1] = { 0b00000101011100011 }; // Set fields 1, 2, 6-8, 10, 12 as const + const static uint32_t code_instance_atomicfields[1] = { 0b11011010100011100 }; // Set fields 3-5, 9, 11, 13-14, 16-17 as atomic + //Fields 4-5 are only operated on by construction and deserialization, so are const at runtime + //Fields 12 and 16 must be protected by locks, and thus all operations on jl_code_instance_t are threadsafe jl_code_instance_type->name->constfields = code_instance_constfields; jl_code_instance_type->name->atomicfields = code_instance_atomicfields; @@ -3476,9 +3476,9 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_methtable_type->types, 9, jl_uint8_type); jl_svecset(jl_methtable_type->types, 10, jl_uint8_type); jl_svecset(jl_method_type->types, 12, jl_method_instance_type); - jl_svecset(jl_method_instance_type->types, 6, jl_code_instance_type); - jl_svecset(jl_code_instance_type->types, 14, jl_voidpointer_type); + jl_svecset(jl_method_instance_type->types, 5, jl_code_instance_type); jl_svecset(jl_code_instance_type->types, 15, jl_voidpointer_type); + jl_svecset(jl_code_instance_type->types, 16, jl_voidpointer_type); jl_svecset(jl_binding_type->types, 1, jl_globalref_type); jl_svecset(jl_binding_type->types, 2, jl_binding_type); diff --git a/src/jsvm-emscripten/asyncify_setup.js b/src/jsvm-emscripten/asyncify_setup.js deleted file mode 100644 index 6783206602fd0..0000000000000 --- a/src/jsvm-emscripten/asyncify_setup.js +++ /dev/null @@ -1,144 +0,0 @@ -Module.preRun.push(function() { - if (typeof Asyncify !== "undefined") { - Asyncify.instrumentWasmExports = function (exports) { return exports; }; - Asyncify.handleSleep = function (startAsync) { - if (ABORT) return; - Module['noExitRuntime'] = true; - if (Asyncify.state === Asyncify.State.Normal) { - // Prepare to sleep. Call startAsync, and see what happens: - // if the code decided to call our callback synchronously, - // then no async operation was in fact begun, and we don't - // need to do anything. - var reachedCallback = false; - var reachedAfterCallback = false; - var task = get_current_task(); - startAsync(function(returnValue) { - assert(!returnValue || typeof returnValue === 'number'); // old emterpretify API supported other stuff - if (ABORT) return; - Asyncify.returnValue = returnValue || 0; - reachedCallback = true; - if (!reachedAfterCallback) { - // We are happening synchronously, so no need for async. - return; - } - schedule_and_wait(task); - }); - reachedAfterCallback = true; - if (!reachedCallback) { - Module['_jl_task_wait'](); - } - } else if (Asyncify.state === Asyncify.State.Rewinding) { - // Stop a resume. - finish_schedule_task(); - } else { - abort('invalid state: ' + Asyncify.state); - } - return Asyncify.returnValue; - }; - } -}); - -function get_current_task() { - return Module['_jl_get_current_task'](); -} - -function get_root_task() { - return Module['_jl_get_root_task'](); -} - -function task_ctx_ptr(task) { - return Module["_task_ctx_ptr"](task); -} - -function ctx_save(ctx) { - var stackPtr = stackSave(); - - // Save the bottom of the C stack in the task context. It simultaneously - // serves as the top of the asyncify stack. - HEAP32[ctx + 4 >> 2] = stackPtr; - - Asyncify.state = Asyncify.State.Unwinding; - Module['_asyncify_start_unwind'](ctx); - if (Browser.mainLoop.func) { - Browser.mainLoop.pause(); - } -} - -function do_start_task(old_stack) -{ - try { - // start_task is always the entry point for any task - Module['_start_task'](); - } catch(e) { - stackRestore(old_stack) - if (e !== e+0 && e !== 'killed') throw e; - maybe_schedule_next(); - return; - } - // Either unwind or normal exit. In either case, we're back at the main task - if (Asyncify.state === Asyncify.State.Unwinding) { - // We just finished unwinding for a sleep. - Asyncify.state = Asyncify.State.Normal; - Module['_asyncify_stop_unwind'](); - } - stackRestore(old_stack); - maybe_schedule_next(); -} - -function schedule_and_wait(task) { - Module['_jl_schedule_task'](task); - Module['_jl_task_wait'](); -} - -function finish_schedule_task() { - Asyncify.state = Asyncify.State.Normal; - Module['_asyncify_stop_rewind'](); -} - -next_ctx = 0; -next_need_start = true; -function set_next_ctx(ctx, needs_start) { - next_ctx = ctx; - next_need_start = needs_start; -} - -function root_ctx() { - return task_ctx_ptr(get_root_task()) -} - -function ctx_switch(lastt_ctx) { - if (lastt_ctx == root_ctx()) { - // If we're in the root context, switch to - // the new ctx now, else we'll get there after - // unwinding. - return schedule_next() - } else if (lastt_ctx == 0) { - throw 'killed'; - } else { - return ctx_save(lastt_ctx); - } -} - -function schedule_next() -{ - old_stack = stackSave(); - var next_task_stack = HEAP32[next_ctx + 4 >> 2]; - if (!next_need_start) { - Asyncify.state = Asyncify.State.Rewinding; - Module['_asyncify_start_rewind'](next_ctx); - if (Browser.mainLoop.func) { - Browser.mainLoop.resume(); - } - } - next_ctx = -1; - stackRestore(next_task_stack); - do_start_task(old_stack) -} - -function maybe_schedule_next() { - assert(next_ctx != -1); - if (next_ctx == root_ctx() || next_ctx == 0) { - return; - } - schedule_next() -} diff --git a/src/jsvm-emscripten/task.js b/src/jsvm-emscripten/task.js deleted file mode 100644 index ba695a5a40052..0000000000000 --- a/src/jsvm-emscripten/task.js +++ /dev/null @@ -1,15 +0,0 @@ -mergeInto(LibraryManager.library, { - jl_set_fiber: function(ctx) { - set_next_ctx(ctx, false); - return ctx_switch(0) - }, - jl_swap_fiber: function(lastt_ctx, ctx) { - set_next_ctx(ctx, false); - return ctx_switch(lastt_ctx) - }, - jl_start_fiber: function(lastt_ctx, ctx) { - set_next_ctx(ctx, true); - return ctx_switch(lastt_ctx) - } -}); - diff --git a/src/julia.h b/src/julia.h index 7d143a3daa3fc..852b671f744f6 100644 --- a/src/julia.h +++ b/src/julia.h @@ -391,7 +391,6 @@ struct _jl_method_instance_t { jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sig _Atomic(jl_value_t*) uninferred; // cached uncompressed code, for generated functions, top-level thunks, or the interpreter jl_array_t *backedges; // list of method-instances which call this method-instance; `invoke` records (invokesig, caller) pairs - jl_array_t *callbacks; // list of callback functions to inform external caches about invalidations _Atomic(struct _jl_code_instance_t*) cache; uint8_t inInference; // flags to tell if inference is running on this object uint8_t cache_with_orig; // !cache_with_specTypes @@ -412,6 +411,7 @@ typedef struct _jl_opaque_closure_t { typedef struct _jl_code_instance_t { JL_DATA_TYPE jl_method_instance_t *def; // method this is specialized from + jl_value_t *owner; // Compiler token this belongs to, `jl_nothing` is reserved for native _Atomic(struct _jl_code_instance_t*) next; // pointer to the next cache entry // world range for which this object is valid to use @@ -2003,7 +2003,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_tuple_int(jl_value_t **v, JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *v, jl_value_t *vt, size_t i); JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOTED, size_t *idxs, size_t nidxs); -JL_DLLEXPORT void JL_NORETURN jl_eof_error(void); // Return the exception currently being handled, or `jl_nothing`. // @@ -2173,9 +2172,6 @@ JL_DLLEXPORT jl_value_t *jl_call2(jl_function_t *f JL_MAYBE_UNROOTED, jl_value_t JL_DLLEXPORT jl_value_t *jl_call3(jl_function_t *f JL_MAYBE_UNROOTED, jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE_UNROOTED, jl_value_t *c JL_MAYBE_UNROOTED); -// interfacing with Task runtime -JL_DLLEXPORT void jl_yield(void); - // async signal handling ------------------------------------------------------ JL_DLLEXPORT void jl_install_sigint_handler(void); @@ -2409,7 +2405,6 @@ JL_DLLEXPORT int jl_termios_size(void); // showing and std streams JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT; @@ -2494,6 +2489,7 @@ JL_DLLEXPORT int jl_generating_output(void) JL_NOTSAFEPOINT; #define JL_OPTIONS_USE_SYSIMAGE_NATIVE_CODE_YES 1 #define JL_OPTIONS_USE_SYSIMAGE_NATIVE_CODE_NO 0 +#define JL_OPTIONS_USE_COMPILED_MODULES_STRICT 3 #define JL_OPTIONS_USE_COMPILED_MODULES_EXISTING 2 #define JL_OPTIONS_USE_COMPILED_MODULES_YES 1 #define JL_OPTIONS_USE_COMPILED_MODULES_NO 0 @@ -2510,8 +2506,6 @@ JL_DLLEXPORT extern int jl_ver_minor(void); JL_DLLEXPORT extern int jl_ver_patch(void); JL_DLLEXPORT extern int jl_ver_is_release(void); JL_DLLEXPORT extern const char *jl_ver_string(void); -JL_DLLEXPORT const char *jl_git_branch(void); -JL_DLLEXPORT const char *jl_git_commit(void); // nullable struct representations typedef struct { @@ -2551,7 +2545,7 @@ typedef struct { int gcstack_arg; // Pass the ptls value as an argument with swiftself int use_jlplt; // Whether to use the Julia PLT mechanism or emit symbols directly - // Cache access. Default: jl_rettype_inferred. + // Cache access. Default: jl_rettype_inferred_native. jl_codeinstance_lookup_t lookup; } jl_cgparams_t; extern JL_DLLEXPORT int jl_default_debug_info_kind; diff --git a/src/julia_internal.h b/src/julia_internal.h index e140dfa205d8e..14b8b4f43ee92 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -669,7 +669,8 @@ jl_method_instance_t *jl_get_unspecialized_from_mi(jl_method_instance_t *method jl_method_instance_t *jl_get_unspecialized(jl_method_t *def JL_PROPAGATES_ROOT); JL_DLLEXPORT jl_code_instance_t* jl_new_codeinst( - jl_method_instance_t *mi, jl_value_t *rettype, jl_value_t *exctype, + jl_method_instance_t *mi, jl_value_t *owner, + jl_value_t *rettype, jl_value_t *exctype, jl_value_t *inferred_const, jl_value_t *inferred, int32_t const_flags, size_t min_world, size_t max_world, uint32_t ipo_effects, uint32_t effects, jl_value_t *analysis_results, @@ -809,7 +810,7 @@ JL_DLLEXPORT int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT; jl_value_t *jl_call_scm_on_ast_and_loc(const char *funcname, jl_value_t *expr, jl_module_t *inmodule, const char *file, int line); -JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt); +JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt); JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world); jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs); @@ -1021,7 +1022,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*); JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module); JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache); jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp); -JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *li JL_PROPAGATES_ROOT, size_t min_world, size_t max_world); +JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *li JL_PROPAGATES_ROOT, size_t min_world, size_t max_world); JL_DLLEXPORT jl_code_instance_t *jl_method_compiled(jl_method_instance_t *mi JL_PROPAGATES_ROOT, size_t world) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_value_t *type, size_t world); JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo( diff --git a/src/julia_threads.h b/src/julia_threads.h index 292c11f61d60d..1c64a722850f2 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -30,7 +30,6 @@ JL_DLLEXPORT int8_t jl_threadpoolid(int16_t tid) JL_NOTSAFEPOINT; // JL_HAVE_ASM -- mostly setjmp // JL_HAVE_ASM && JL_HAVE_UNW_CONTEXT -- libunwind-based // JL_HAVE_UNW_CONTEXT -- libunwind-based -// JL_HAVE_ASYNCIFY -- task switching based on the binary asyncify transform // JL_HAVE_UCONTEXT -- posix standard API, requires syscall for resume // JL_HAVE_SIGALTSTACK -- requires several syscall for start, setjmp for resume @@ -45,8 +44,7 @@ typedef struct { #if !defined(JL_HAVE_UCONTEXT) && \ !defined(JL_HAVE_ASM) && \ !defined(JL_HAVE_UNW_CONTEXT) && \ - !defined(JL_HAVE_SIGALTSTACK) && \ - !defined(JL_HAVE_ASYNCIFY) + !defined(JL_HAVE_SIGALTSTACK) #if (defined(_CPU_X86_64_) || defined(_CPU_X86_) || defined(_CPU_AARCH64_) || \ defined(_CPU_ARM_) || defined(_CPU_PPC64_)) #define JL_HAVE_ASM @@ -57,8 +55,6 @@ typedef struct { //#define JL_HAVE_UNW_CONTEXT //#elif defined(_OS_LINUX_) //#define JL_HAVE_UNW_CONTEXT -#elif defined(_OS_EMSCRIPTEN_) -#define JL_HAVE_ASYNCIFY #elif !defined(JL_HAVE_ASM) #define JL_HAVE_UNW_CONTEXT // optimistically? #endif @@ -67,19 +63,6 @@ typedef struct { #if (!defined(JL_HAVE_UNW_CONTEXT) && defined(JL_HAVE_ASM)) || defined(JL_HAVE_SIGALTSTACK) typedef jl_stack_context_t _jl_ucontext_t; #endif -#if defined(JL_HAVE_ASYNCIFY) -#if defined(_COMPILER_TSAN_ENABLED_) -#error TSAN not currently supported with asyncify -#endif -typedef struct { - // This is the extent of the asyncify stack, but because the top of the - // asyncify stack (stacktop) is also the bottom of the C stack, we can - // reuse stacktop for both. N.B.: This matches the layout of the - // __asyncify_data struct. - void *stackbottom; - void *stacktop; -} _jl_ucontext_t; -#endif #pragma GCC visibility push(default) #if defined(JL_HAVE_UNW_CONTEXT) #define UNW_LOCAL_ONLY diff --git a/src/method.c b/src/method.c index 3d3cc4cb7ea4e..88d43fb4b22ee 100644 --- a/src/method.c +++ b/src/method.c @@ -488,7 +488,6 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) mi->sparam_vals = jl_emptysvec; jl_atomic_store_relaxed(&mi->uninferred, NULL); mi->backedges = NULL; - mi->callbacks = NULL; jl_atomic_store_relaxed(&mi->cache, NULL); mi->inInference = 0; mi->cache_with_orig = 0; diff --git a/src/opaque_closure.c b/src/opaque_closure.c index 0b0d1052bd449..45b08fee668db 100644 --- a/src/opaque_closure.c +++ b/src/opaque_closure.c @@ -153,7 +153,7 @@ JL_DLLEXPORT jl_opaque_closure_t *jl_new_opaque_closure_from_code_info(jl_tuplet sigtype = jl_argtype_with_function(env, (jl_value_t*)argt); jl_method_instance_t *mi = jl_specializations_get_linfo((jl_method_t*)root, sigtype, jl_emptysvec); - inst = jl_new_codeinst(mi, rt_ub, (jl_value_t*)jl_any_type, NULL, (jl_value_t*)ci, + inst = jl_new_codeinst(mi, jl_nothing, rt_ub, (jl_value_t*)jl_any_type, NULL, (jl_value_t*)ci, 0, world, world, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, inst); diff --git a/src/options.h b/src/options.h index da8d38e1b6a38..69b31ea918008 100644 --- a/src/options.h +++ b/src/options.h @@ -109,6 +109,7 @@ // When not using COPY_STACKS the task-system is less memory efficient so // you probably want to choose a smaller default stack size (factor of 8-10) +#if !defined(JL_STACK_SIZE) #if defined(_COMPILER_ASAN_ENABLED_) || defined(_COMPILER_MSAN_ENABLED_) #define JL_STACK_SIZE (64*1024*1024) #elif defined(_P64) @@ -116,6 +117,7 @@ #else #define JL_STACK_SIZE (2*1024*1024) #endif +#endif // allow a suspended Task to restart on a different thread #define MIGRATE_TASKS diff --git a/src/rtutils.c b/src/rtutils.c index a4cfa28039805..1ab881e613564 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -219,14 +219,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOT jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); } -JL_DLLEXPORT void JL_NORETURN jl_eof_error(void) -{ - jl_datatype_t *eof_error = - (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError")); - assert(eof_error != NULL); - jl_throw(jl_new_struct(eof_error)); -} - JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t) { if (!jl_isa(x,t)) @@ -546,14 +538,6 @@ JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT fflush(stderr); } -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT -{ - if (jl_base_module == NULL) - return NULL; - jl_binding_t *stdout_obj = jl_get_module_binding(jl_base_module, jl_symbol("stdout"), 0); - return stdout_obj ? jl_atomic_load_relaxed(&stdout_obj->value) : NULL; -} - JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT { if (jl_base_module == NULL) diff --git a/src/stackwalk.c b/src/stackwalk.c index 6efb177927637..37f239609504e 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -1087,8 +1087,6 @@ static void jl_rec_backtrace(jl_task_t *t) JL_NOTSAFEPOINT #pragma message("jl_rec_backtrace not defined for ASM/SETJMP on unknown system") (void)c; #endif -#elif defined(JL_HAVE_ASYNCIFY) - #pragma message("jl_rec_backtrace not defined for ASYNCIFY") #elif defined(JL_HAVE_SIGALTSTACK) #pragma message("jl_rec_backtrace not defined for SIGALTSTACK") #else diff --git a/src/staticdata.c b/src/staticdata.c index 8489fa116688e..0d38dddb79aaf 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -803,7 +803,6 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ // so must not be present here record_field_change((jl_value_t**)&mi->uninferred, NULL); record_field_change((jl_value_t**)&mi->backedges, NULL); - record_field_change((jl_value_t**)&mi->callbacks, NULL); record_field_change((jl_value_t**)&mi->cache, NULL); } else { @@ -835,6 +834,11 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ if (s->incremental && jl_is_code_instance(v)) { jl_code_instance_t *ci = (jl_code_instance_t*)v; // make sure we don't serialize other reachable cache entries of foreign methods + // Should this now be: + // if (ci !in ci->defs->cache) + // record_field_change((jl_value_t**)&ci->next, NULL); + // Why are we checking that the method/module this originates from is in_image? + // and then disconnect this CI? if (jl_object_in_image((jl_value_t*)ci->def->def.value)) { // TODO: if (ci in ci->defs->cache) record_field_change((jl_value_t**)&ci->next, NULL); @@ -2392,7 +2396,6 @@ static void strip_specializations_(jl_method_instance_t *mi) if (jl_options.strip_ir) { record_field_change((jl_value_t**)&mi->uninferred, NULL); record_field_change((jl_value_t**)&mi->backedges, NULL); - record_field_change((jl_value_t**)&mi->callbacks, NULL); } } diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 199724e54ae00..fc7a59d9d0bf9 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -239,11 +239,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list) assert(found == 0 || found == 1 || found == 2); assert(stack.len == 0); if (found == 1 && jl_atomic_load_relaxed(&ci->max_world) == ~(size_t)0) { - void **bp = ptrhash_bp(&visited, mi); - if (*bp != (void*)((char*)HT_NOTFOUND + 3)) { - *bp = (void*)((char*)HT_NOTFOUND + 3); - jl_array_ptr_1d_push(new_ext_cis, (jl_value_t*)ci); - } + jl_array_ptr_1d_push(new_ext_cis, (jl_value_t*)ci); } } } @@ -634,6 +630,32 @@ JL_DLLEXPORT uint8_t jl_match_cache_flags(uint8_t flags) return flags >= current_flags; } +// return char* from String field in Base.GIT_VERSION_INFO +static const char *git_info_string(const char *fld) +{ + static jl_value_t *GIT_VERSION_INFO = NULL; + if (!GIT_VERSION_INFO) + GIT_VERSION_INFO = jl_get_global(jl_base_module, jl_symbol("GIT_VERSION_INFO")); + jl_value_t *f = jl_get_field(GIT_VERSION_INFO, fld); + assert(jl_is_string(f)); + return jl_string_data(f); +} + +static const char *jl_git_branch(void) +{ + static const char *branch = NULL; + if (!branch) branch = git_info_string("branch"); + return branch; +} + +static const char *jl_git_commit(void) +{ + static const char *commit = NULL; + if (!commit) commit = git_info_string("commit"); + return commit; +} + + // "magic" string and version header of .ji file static const int JI_FORMAT_VERSION = 12; static const char JI_MAGIC[] = "\373jli\r\n\032\n"; // based on PNG signature @@ -1162,13 +1184,23 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(ext_ci_list, i); if (jl_atomic_load_relaxed(&ci->max_world) == WORLD_AGE_REVALIDATION_SENTINEL) { assert(jl_atomic_load_relaxed(&ci->min_world) == minworld); - ptrhash_put(&cis_pending_validation, (void*)ci->def, (void*)ci); + void **bp = ptrhash_bp(&cis_pending_validation, (void*)ci->def); + assert(!jl_atomic_load_relaxed(&ci->next)); + if (*bp == HT_NOTFOUND) + *bp = (void*)ci; + else { + // Do ci->owner bifurcates the cache, we temporarily + // form a linked list of all the CI that need to be connected later + jl_code_instance_t *prev_ci = (jl_code_instance_t *)*bp; + jl_atomic_store_relaxed(&ci->next, prev_ci); + *bp = (void*)ci; + } } else { assert(jl_atomic_load_relaxed(&ci->min_world) == 1); assert(jl_atomic_load_relaxed(&ci->max_world) == ~(size_t)0); jl_method_instance_t *caller = ci->def; - if (jl_atomic_load_relaxed(&ci->inferred) && jl_rettype_inferred(caller, minworld, ~(size_t)0) == jl_nothing) { + if (jl_atomic_load_relaxed(&ci->inferred) && jl_rettype_inferred(ci->owner, caller, minworld, ~(size_t)0) == jl_nothing) { jl_mi_cache_insert(caller, ci); } //jl_static_show((JL_STREAM*)ios_stderr, (jl_value_t*)caller); @@ -1211,18 +1243,26 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a // Update any external CIs and add them to the cache. assert(jl_is_code_instance(ci)); jl_code_instance_t *codeinst = (jl_code_instance_t*)ci; - assert(jl_atomic_load_relaxed(&codeinst->min_world) == minworld); - assert(jl_atomic_load_relaxed(&codeinst->max_world) == WORLD_AGE_REVALIDATION_SENTINEL); - assert(jl_atomic_load_relaxed(&codeinst->inferred)); - jl_atomic_store_relaxed(&codeinst->max_world, maxvalid); - - if (jl_rettype_inferred(caller, minworld, maxvalid) != jl_nothing) { - // We already got a code instance for this world age range from somewhere else - we don't need - // this one. - continue; + while (codeinst) { + jl_code_instance_t *next_ci = jl_atomic_load_relaxed(&codeinst->next); + jl_atomic_store_relaxed(&codeinst->next, NULL); + + jl_value_t *owner = codeinst->owner; + JL_GC_PROMISE_ROOTED(owner); + + assert(jl_atomic_load_relaxed(&codeinst->min_world) == minworld); + assert(jl_atomic_load_relaxed(&codeinst->max_world) == WORLD_AGE_REVALIDATION_SENTINEL); + assert(jl_atomic_load_relaxed(&codeinst->inferred)); + jl_atomic_store_relaxed(&codeinst->max_world, maxvalid); + + if (jl_rettype_inferred(owner, caller, minworld, maxvalid) != jl_nothing) { + // We already got a code instance for this world age range from somewhere else - we don't need + // this one. + } else { + jl_mi_cache_insert(caller, codeinst); + } + codeinst = next_ci; } - - jl_mi_cache_insert(caller, codeinst); } else { // Likely internal. Find the CI already in the cache hierarchy. diff --git a/src/task.c b/src/task.c index 8905b49e87f8e..4bf12250b7d2c 100644 --- a/src/task.c +++ b/src/task.c @@ -134,18 +134,11 @@ static inline void sanitizer_finish_switch_fiber(jl_task_t *last, jl_task_t *cur #define ROOT_TASK_STACK_ADJUSTMENT 3000000 #endif -#ifdef JL_HAVE_ASYNCIFY -// Switching logic is implemented in JavaScript -#define STATIC_OR_JS JL_DLLEXPORT -#else -#define STATIC_OR_JS static -#endif - static char *jl_alloc_fiber(_jl_ucontext_t *t, size_t *ssize, jl_task_t *owner) JL_NOTSAFEPOINT; -STATIC_OR_JS void jl_set_fiber(jl_ucontext_t *t); -STATIC_OR_JS void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t); -STATIC_OR_JS void jl_start_fiber_swap(jl_ucontext_t *savet, jl_ucontext_t *t); -STATIC_OR_JS void jl_start_fiber_set(jl_ucontext_t *t); +static void jl_set_fiber(jl_ucontext_t *t); +static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t); +static void jl_start_fiber_swap(jl_ucontext_t *savet, jl_ucontext_t *t); +static void jl_start_fiber_set(jl_ucontext_t *t); #ifdef ALWAYS_COPY_STACKS # ifndef COPY_STACKS @@ -1172,47 +1165,6 @@ JL_DLLEXPORT jl_task_t *jl_get_current_task(void) return pgcstack == NULL ? NULL : container_of(pgcstack, jl_task_t, gcstack); } - -#ifdef JL_HAVE_ASYNCIFY -JL_DLLEXPORT jl_ucontext_t *task_ctx_ptr(jl_task_t *t) -{ - return &t->ctx.ctx; -} - -JL_DLLEXPORT jl_value_t *jl_get_root_task(void) -{ - jl_task_t *ct = jl_current_task; - return (jl_value_t*)ct->ptls->root_task; -} - -JL_DLLEXPORT void jl_task_wait() -{ - static jl_function_t *wait_func = NULL; - if (!wait_func) { - wait_func = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("wait")); - } - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - jl_apply(&wait_func, 1); - ct->world_age = last_age; -} - -JL_DLLEXPORT void jl_schedule_task(jl_task_t *task) -{ - static jl_function_t *sched_func = NULL; - if (!sched_func) { - sched_func = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("schedule")); - } - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - jl_value_t *args[] = {(jl_value_t*)sched_func, (jl_value_t*)task}; - jl_apply(args, 2); - ct->world_age = last_age; -} -#endif - // Do one-time initializations for task system void jl_init_tasks(void) JL_GC_DISABLED { @@ -1247,10 +1199,10 @@ void jl_init_tasks(void) JL_GC_DISABLED } #if defined(_COMPILER_ASAN_ENABLED_) -STATIC_OR_JS void NOINLINE JL_NORETURN _start_task(void); +static void NOINLINE JL_NORETURN _start_task(void); #endif -STATIC_OR_JS void NOINLINE JL_NORETURN JL_NO_ASAN start_task(void) +static void NOINLINE JL_NORETURN JL_NO_ASAN start_task(void) { CFI_NORETURN #if defined(_COMPILER_ASAN_ENABLED_) @@ -1266,7 +1218,7 @@ CFI_NORETURN _start_task(); } -STATIC_OR_JS void NOINLINE JL_NORETURN _start_task(void) +static void NOINLINE JL_NORETURN _start_task(void) { CFI_NORETURN #endif diff --git a/stdlib/Dates/src/conversions.jl b/stdlib/Dates/src/conversions.jl index 30f1f2581d1fa..0d413d2cf53a1 100644 --- a/stdlib/Dates/src/conversions.jl +++ b/stdlib/Dates/src/conversions.jl @@ -84,7 +84,7 @@ today() = Date(now()) Return a `DateTime` corresponding to the user's system time as UTC/GMT. For other time zones, see the TimeZones.jl package. -# Example +# Examples ```julia julia> now(UTC) 2023-01-04T10:52:24.864 diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 257e86064c2fb..3980ad3a7245f 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -472,7 +472,7 @@ end Describes the ISO8601 formatting for a date and time. This is the default value for `Dates.format` of a `DateTime`. -# Example +# Examples ```jldoctest julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), ISODateTimeFormat) "2018-08-08T12:00:43.001" @@ -486,7 +486,7 @@ default_format(::Type{DateTime}) = ISODateTimeFormat Describes the ISO8601 formatting for a date. This is the default value for `Dates.format` of a `Date`. -# Example +# Examples ```jldoctest julia> Dates.format(Date(2018, 8, 8), ISODateFormat) "2018-08-08" @@ -500,7 +500,7 @@ default_format(::Type{Date}) = ISODateFormat Describes the ISO8601 formatting for a time. This is the default value for `Dates.format` of a `Time`. -# Example +# Examples ```jldoctest julia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat) "12:00:43.001" @@ -514,7 +514,7 @@ default_format(::Type{Time}) = ISOTimeFormat Describes the RFC1123 formatting for a date and time. -# Example +# Examples ```jldoctest julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format) "Wed, 08 Aug 2018 12:00:43" @@ -538,7 +538,7 @@ pattern given in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> DateTime("2020-01-01", "yyyy-mm-dd") 2020-01-01T00:00:00 @@ -578,7 +578,7 @@ in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> Date("2020-01-01", "yyyy-mm-dd") 2020-01-01 @@ -618,7 +618,7 @@ in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> Time("12:34pm", "HH:MMp") 12:34:00 diff --git a/stdlib/FileWatching/test/runtests.jl b/stdlib/FileWatching/test/runtests.jl index 9ba6456d20a98..b9ad8d9bc7777 100644 --- a/stdlib/FileWatching/test/runtests.jl +++ b/stdlib/FileWatching/test/runtests.jl @@ -161,7 +161,7 @@ test2_12992() ####################################################################### # This section tests file watchers. # ####################################################################### -F_GETPATH = Sys.islinux() || Sys.iswindows() || Sys.isapple() # platforms where F_GETPATH is available +F_GETPATH = Sys.islinux() || Sys.iswindows() || Sys.isapple() || Sys.isfreebsd() # platforms where F_GETPATH is available F_PATH = F_GETPATH ? "afile.txt" : "" dir = mktempdir() file = joinpath(dir, "afile.txt") diff --git a/stdlib/GMP_jll/Project.toml b/stdlib/GMP_jll/Project.toml index 9f3b917257bfa..c8fcfe4f2b845 100644 --- a/stdlib/GMP_jll/Project.toml +++ b/stdlib/GMP_jll/Project.toml @@ -1,6 +1,6 @@ name = "GMP_jll" uuid = "781609d7-10c4-51f6-84f2-b8444358ff6d" -version = "6.2.1+6" +version = "6.3.0+0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" diff --git a/stdlib/GMP_jll/test/runtests.jl b/stdlib/GMP_jll/test/runtests.jl index 7c0d877945231..b2b35b98cbe17 100644 --- a/stdlib/GMP_jll/test/runtests.jl +++ b/stdlib/GMP_jll/test/runtests.jl @@ -4,5 +4,5 @@ using Test, Libdl, GMP_jll @testset "GMP_jll" begin vn = VersionNumber(unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar})))) - @test vn == v"6.2.1" + @test vn == v"6.3.0" end diff --git a/stdlib/InteractiveUtils/src/editless.jl b/stdlib/InteractiveUtils/src/editless.jl index 74fc5c6becfbd..5b87dc0c57d40 100644 --- a/stdlib/InteractiveUtils/src/editless.jl +++ b/stdlib/InteractiveUtils/src/editless.jl @@ -77,7 +77,7 @@ already work: - pycharm - bbedit -# Example: +# Examples The following defines the usage of terminal-based `emacs`: diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index a840dd7ea43bb..939098464e148 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -36,6 +36,10 @@ function gen_call_with_extracted_types(__module__, fcn, ex0, kws=Expr[]) if Meta.isexpr(ex0, :ref) ex0 = replace_ref_begin_end!(ex0) end + # assignments get bypassed: @edit a = f(x) <=> @edit f(x) + if isa(ex0, Expr) && ex0.head == :(=) && isa(ex0.args[1], Symbol) && isempty(kws) + return gen_call_with_extracted_types(__module__, fcn, ex0.args[2]) + end if isa(ex0, Expr) if ex0.head === :do && Meta.isexpr(get(ex0.args, 1, nothing), :call) if length(ex0.args) != 2 diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index 94c0c42e2d2da..346b111c785f7 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -284,7 +284,7 @@ try @which x = 1 error("unexpected") catch err13464 - @test startswith(err13464.msg, "expression is not a function call, or is too complex") + @test startswith(err13464.msg, "expression is not a function call") end module MacroTest diff --git a/stdlib/LibUV_jll/Project.toml b/stdlib/LibUV_jll/Project.toml index 605c1115b3d34..8089516c1df14 100644 --- a/stdlib/LibUV_jll/Project.toml +++ b/stdlib/LibUV_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUV_jll" uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+14" +version = "2.0.1+15" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 4ba540d42b261..d1d2a156b1ed4 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -346,7 +346,7 @@ eigvals(A::AbstractMatrix{T}; kws...) where T = """ For a scalar input, `eigvals` will return a scalar. -# Example +# Examples ```jldoctest julia> eigvals(-2) -2 diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index 6f5a631cf9164..4cefc661741be 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -64,11 +64,10 @@ transpose(F::AdjointFactorization{<:Real}) = F.parent conj(A::TransposeFactorization) = adjoint(A.parent) conj(A::AdjointFactorization) = transpose(A.parent) +# These functions expect a non-zero info to be positive, indicating the position where a problem was detected checkpositivedefinite(info) = info == 0 || throw(PosDefException(info)) -checknonsingular(info, ::RowMaximum) = info == 0 || throw(SingularException(info)) -checknonsingular(info, ::RowNonZero) = info == 0 || throw(SingularException(info)) -checknonsingular(info, ::NoPivot) = info == 0 || throw(ZeroPivotException(info)) -checknonsingular(info) = checknonsingular(info, RowMaximum()) +checknonsingular(info) = info == 0 || throw(SingularException(info)) +checknozeropivot(info) = info == 0 || throw(ZeroPivotException(info)) """ issuccess(F::Factorization) @@ -78,16 +77,13 @@ Test that a factorization of a matrix succeeded. !!! compat "Julia 1.6" `issuccess(::CholeskyPivoted)` requires Julia 1.6 or later. +# Examples + ```jldoctest julia> F = cholesky([1 0; 0 1]); julia> issuccess(F) true - -julia> F = lu([1 0; 0 0]; check = false); - -julia> issuccess(F) -false ``` """ issuccess(F::Factorization) diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 25e32a8ab0828..be32f1e863ff1 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -21,6 +21,7 @@ The individual components of the factorization `F::LU` can be accessed via [`get Iterating the factorization produces the components `F.L`, `F.U`, and `F.p`. # Examples + ```jldoctest julia> A = [4 3; 6 3] 2×2 Matrix{Int64}: @@ -50,7 +51,7 @@ true struct LU{T,S<:AbstractMatrix{T},P<:AbstractVector{<:Integer}} <: Factorization{T} factors::S ipiv::P - info::BlasInt + info::BlasInt # Can be negative to indicate failed unpivoted factorization function LU{T,S,P}(factors, ipiv, info) where {T, S<:AbstractMatrix{T}, P<:AbstractVector{<:Integer}} require_one_based_indexing(factors) @@ -76,16 +77,25 @@ Base.iterate(S::LU, ::Val{:done}) = nothing adjoint(F::LU{<:Real}) = TransposeFactorization(F) transpose(F::LU{<:Real}) = TransposeFactorization(F) +function _check_lu_success(info, allowsingular) + if info < 0 # zero pivot error from unpivoted LU + checknozeropivot(-info) + else + allowsingular || checknonsingular(info) + end +end + # the following method is meant to catch calls to lu!(A::LAPACKArray) without a pivoting strategy -lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true) = lu!(A, RowMaximum(); check=check) -function lu!(A::StridedMatrix{T}, ::RowMaximum; check::Bool = true) where {T<:BlasFloat} +lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true, allowsingular::Bool = false) = lu!(A, RowMaximum(); check, allowsingular) +function lu!(A::StridedMatrix{T}, ::RowMaximum; check::Bool = true, allowsingular::Bool = false) where {T<:BlasFloat} lpt = LAPACK.getrf!(A; check) - check && checknonsingular(lpt[3]) + check && _check_lu_success(lpt[3], allowsingular) return LU{T,typeof(lpt[1]),typeof(lpt[2])}(lpt[1], lpt[2], lpt[3]) end -function lu!(A::HermOrSym{T}, pivot::Union{RowMaximum,NoPivot,RowNonZero} = lupivottype(T); check::Bool = true) where {T} +function lu!(A::HermOrSym{T}, pivot::Union{RowMaximum,NoPivot,RowNonZero} = lupivottype(T); + check::Bool = true, allowsingular::Bool = false) where {T} copytri!(A.data, A.uplo, isa(A, Hermitian)) - lu!(A.data, pivot; check = check) + lu!(A.data, pivot; check, allowsingular) end # for backward compatibility # TODO: remove towards Julia v2 @@ -93,13 +103,16 @@ end @deprecate lu!(A::Union{StridedMatrix,HermOrSym,Tridiagonal}, ::Val{false}; check::Bool = true) lu!(A, NoPivot(); check=check) """ - lu!(A, pivot = RowMaximum(); check = true) -> LU + lu!(A, pivot = RowMaximum(); check = true, allowsingular = false) -> LU `lu!` is the same as [`lu`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorization produces a number not representable by the element type of `A`, e.g. for integer types. +!!! compat "Julia 1.11" + The `allowsingular` keyword argument was added in Julia 1.11. + # Examples ```jldoctest julia> A = [4. 3.; 6. 3.] @@ -129,10 +142,10 @@ Stacktrace: [...] ``` """ -lu!(A::AbstractMatrix, pivot::Union{RowMaximum,NoPivot,RowNonZero} = lupivottype(eltype(A)); check::Bool = true) = - generic_lufact!(A, pivot; check = check) +lu!(A::AbstractMatrix, pivot::Union{RowMaximum,NoPivot,RowNonZero} = lupivottype(eltype(A)); + check::Bool = true, allowsingular::Bool = false) = generic_lufact!(A, pivot; check, allowsingular) function generic_lufact!(A::AbstractMatrix{T}, pivot::Union{RowMaximum,NoPivot,RowNonZero} = lupivottype(T); - check::Bool = true) where {T} + check::Bool = true, allowsingular::Bool = false) where {T} check && LAPACK.chkfinite(A) # Extract values m, n = size(A) @@ -188,7 +201,12 @@ function generic_lufact!(A::AbstractMatrix{T}, pivot::Union{RowMaximum,NoPivot,R end end end - check && checknonsingular(info, pivot) + if pivot === NoPivot() + # Use a negative value to distinguish a failed factorization (zero in pivot + # position during unpivoted LU) from a valid but rank-deficient factorization + info = -info + end + check && _check_lu_success(info, allowsingular) return LU{T,typeof(A),typeof(ipiv)}(A, ipiv, convert(BlasInt, info)) end @@ -215,7 +233,7 @@ lupivottype(::Type{T}) where {T} = RowMaximum() # for all other types we must promote to a type which is stable under division """ - lu(A, pivot = RowMaximum(); check = true) -> F::LU + lu(A, pivot = RowMaximum(); check = true, allowsingular = false) -> F::LU Compute the LU factorization of `A`. @@ -223,6 +241,10 @@ When `check = true`, an error is thrown if the decomposition fails. When `check = false`, responsibility for checking the decomposition's validity (via [`issuccess`](@ref)) lies with the user. +By default, with `check = true`, an error is also thrown when the decomposition +produces valid factors, but the upper-triangular factor `U` is rank-deficient. This may be changed by +passing `allowsingular = true`. + In most cases, if `A` is a subtype `S` of `AbstractMatrix{T}` with an element type `T` supporting `+`, `-`, `*` and `/`, the return type is `LU{T,S{T}}`. @@ -240,7 +262,8 @@ One of the following pivoting strategies can be selected via the optional `pivot to be factorized rows. (This corresponds to the typical choice in hand calculations, and is also useful for more general algebraic number types that support [`iszero`](@ref) but not `abs` or `<`.) -* `NoPivot()`: pivoting turned off (may fail if a zero entry is encountered). +* `NoPivot()`: pivoting turned off (will fail if a zero entry is encountered in + a pivot position, even when `allowsingular = true`). The individual components of the factorization `F` can be accessed via [`getproperty`](@ref): @@ -269,6 +292,9 @@ The relationship between `F` and `A` is | [`logabsdet`](@ref) | ✓ | ✓ | | [`size`](@ref) | ✓ | ✓ | +!!! compat "Julia 1.11" + The `allowsingular` keyword argument was added in Julia 1.11. + # Examples ```jldoctest julia> A = [4 3; 6 3] @@ -294,6 +320,17 @@ julia> l, u, p = lu(A); # destructuring via iteration julia> l == F.L && u == F.U && p == F.p true + +julia> lu([1 2; 1 2], allowsingular = true) +LU{Float64, Matrix{Float64}, Vector{Int64}} +L factor: +2×2 Matrix{Float64}: + 1.0 0.0 + 1.0 1.0 +U factor (rank-deficient): +2×2 Matrix{Float64}: + 1.0 2.0 + 0.0 0.0 ``` """ lu(A::AbstractMatrix{T}, args...; kwargs...) where {T} = @@ -309,9 +346,9 @@ _lucopy(A::HermOrSym, T) = copymutable_oftype(A, T) _lucopy(A::Tridiagonal, T) = copymutable_oftype(A, T) lu(S::LU) = S -function lu(x::Number; check::Bool=true) +function lu(x::Number; check::Bool=true, allowsingular::Bool=false) info = x == 0 ? one(BlasInt) : zero(BlasInt) - check && checknonsingular(info) + check && _check_lu_success(info, allowsingular) return LU(fill(x, 1, 1), BlasInt[1], info) end @@ -357,17 +394,47 @@ end Base.propertynames(F::LU, private::Bool=false) = (:L, :U, :p, :P, (private ? fieldnames(typeof(F)) : ())...) -issuccess(F::LU) = F.info == 0 + +""" + issuccess(F::LU; allowsingular = false) + +Test that the LU factorization of a matrix succeeded. By default a +factorization that produces a valid but rank-deficient U factor is considered a +failure. This can be changed by passing `allowsingular = true`. + +!!! compat "Julia 1.11" + The `allowsingular` keyword argument was added in Julia 1.11. + +# Examples + +```jldoctest +julia> F = lu([1 2; 1 2], check = false); + +julia> issuccess(F) +false + +julia> issuccess(F, allowsingular = true) +true +``` +""" +function issuccess(F::LU; allowsingular::Bool=false) + # A negative info is always a failure, a positive info indicates a valid but rank-deficient U factor + F.info == 0 || (allowsingular && F.info > 0) +end function show(io::IO, mime::MIME{Symbol("text/plain")}, F::LU) - if issuccess(F) + if F.info < 0 + print(io, "Failed factorization of type $(typeof(F))") + else summary(io, F); println(io) println(io, "L factor:") show(io, mime, F.L) - println(io, "\nU factor:") + if F.info > 0 + println(io, "\nU factor (rank-deficient):") + else + println(io, "\nU factor:") + end show(io, mime, F.U) - else - print(io, "Failed factorization of type $(typeof(F))") end end @@ -494,7 +561,8 @@ inv!(A::LU{T,<:StridedMatrix}) where {T} = inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(copy(A)) # Tridiagonal -function lu!(A::Tridiagonal{T,V}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) where {T,V} +function lu!(A::Tridiagonal{T,V}, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); + check::Bool = true, allowsingular::Bool = false) where {T,V} n = size(A, 1) has_du2_defined = isdefined(A, :du2) && length(A.du2) == max(0, n-2) if has_du2_defined @@ -502,16 +570,17 @@ function lu!(A::Tridiagonal{T,V}, pivot::Union{RowMaximum,NoPivot} = RowMaximum( else du2 = similar(A.d, max(0, n-2))::V end - _lu_tridiag!(A.dl, A.d, A.du, du2, Vector{BlasInt}(undef, n), pivot, check) + _lu_tridiag!(A.dl, A.d, A.du, du2, Vector{BlasInt}(undef, n), pivot, check, allowsingular) end -function lu!(F::LU{<:Any,<:Tridiagonal}, A::Tridiagonal, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); check::Bool = true) +function lu!(F::LU{<:Any,<:Tridiagonal}, A::Tridiagonal, pivot::Union{RowMaximum,NoPivot} = RowMaximum(); + check::Bool = true, allowsingular::Bool = false) B = F.factors size(B) == size(A) || throw(DimensionMismatch()) copyto!(B, A) - _lu_tridiag!(B.dl, B.d, B.du, B.du2, F.ipiv, pivot, check) + _lu_tridiag!(B.dl, B.d, B.du, B.du2, F.ipiv, pivot, check, allowsingular) end # See dgttrf.f -@inline function _lu_tridiag!(dl, d, du, du2, ipiv, pivot, check) +@inline function _lu_tridiag!(dl, d, du, du2, ipiv, pivot, check, allowsingular) T = eltype(d) V = typeof(d) @@ -575,7 +644,7 @@ end end end end - check && checknonsingular(info, pivot) + check && _check_lu_success(info, allowsingular) return LU{T,Tridiagonal{T,V},typeof(ipiv)}(Tridiagonal{T,V}(dl, d, du, du2), ipiv, convert(BlasInt, info)) end diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index d0066ddecbfe0..21047dad8fcd9 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -269,10 +269,34 @@ end end end +_conjugation(::Symmetric) = transpose +_conjugation(::Hermitian) = adjoint + diag(A::Symmetric) = symmetric.(diag(parent(A)), sym_uplo(A.uplo)) diag(A::Hermitian) = hermitian.(diag(parent(A)), sym_uplo(A.uplo)) -isdiag(A::HermOrSym) = isdiag(A.uplo == 'U' ? UpperTriangular(A.data) : LowerTriangular(A.data)) +function applytri(f, A::HermOrSym) + if A.uplo == 'U' + f(UpperTriangular(A.data)) + else + f(LowerTriangular(A.data)) + end +end + +function applytri(f, A::HermOrSym, B::HermOrSym) + if A.uplo == B.uplo == 'U' + f(UpperTriangular(A.data), UpperTriangular(B.data)) + elseif A.uplo == B.uplo == 'L' + f(LowerTriangular(A.data), LowerTriangular(B.data)) + elseif A.uplo == 'U' + f(UpperTriangular(A.data), UpperTriangular(_conjugation(B)(B.data))) + else # A.uplo == 'L' + f(UpperTriangular(_conjugation(A)(A.data)), UpperTriangular(B.data)) + end +end +parentof_applytri(f, args...) = applytri(parent ∘ f, args...) + +isdiag(A::HermOrSym) = applytri(isdiag, A) # For A<:Union{Symmetric,Hermitian}, similar(A[, neweltype]) should yield a matrix with the same # symmetry type, uplo flag, and underlying storage type as A. The following methods cover these cases. @@ -314,8 +338,8 @@ Hermitian{T,S}(A::Hermitian) where {T,S<:AbstractMatrix{T}} = Hermitian{T,S}(con AbstractMatrix{T}(A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), sym_uplo(A.uplo)) AbstractMatrix{T}(A::Hermitian{T}) where {T} = copy(A) -copy(A::Symmetric{T,S}) where {T,S} = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) -copy(A::Hermitian{T,S}) where {T,S} = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) +copy(A::Symmetric) = (Symmetric(parentof_applytri(copy, A), sym_uplo(A.uplo))) +copy(A::Hermitian) = (Hermitian(parentof_applytri(copy, A), sym_uplo(A.uplo))) function copyto!(dest::Symmetric, src::Symmetric) if src.uplo == dest.uplo @@ -389,9 +413,9 @@ transpose(A::Hermitian) = Transpose(A) real(A::Symmetric{<:Real}) = A real(A::Hermitian{<:Real}) = A -real(A::Symmetric) = Symmetric(real(A.data), sym_uplo(A.uplo)) -real(A::Hermitian) = Hermitian(real(A.data), sym_uplo(A.uplo)) -imag(A::Symmetric) = Symmetric(imag(A.data), sym_uplo(A.uplo)) +real(A::Symmetric) = Symmetric(parentof_applytri(real, A), sym_uplo(A.uplo)) +real(A::Hermitian) = Hermitian(parentof_applytri(real, A), sym_uplo(A.uplo)) +imag(A::Symmetric) = Symmetric(parentof_applytri(imag, A), sym_uplo(A.uplo)) Base.copy(A::Adjoint{<:Any,<:Symmetric}) = Symmetric(copy(adjoint(A.parent.data)), ifelse(A.parent.uplo == 'U', :L, :U)) @@ -401,8 +425,9 @@ Base.copy(A::Transpose{<:Any,<:Hermitian}) = tr(A::Symmetric) = tr(A.data) # to avoid AbstractMatrix fallback (incl. allocations) tr(A::Hermitian) = real(tr(A.data)) -Base.conj(A::HermOrSym) = typeof(A)(conj(A.data), A.uplo) -Base.conj!(A::HermOrSym) = typeof(A)(conj!(A.data), A.uplo) +Base.conj(A::Symmetric) = Symmetric(parentof_applytri(conj, A), sym_uplo(A.uplo)) +Base.conj(A::Hermitian) = Hermitian(parentof_applytri(conj, A), sym_uplo(A.uplo)) +Base.conj!(A::HermOrSym) = typeof(A)(parentof_applytri(conj!, A), A.uplo) # tril/triu function tril(A::Hermitian, k::Integer=0) @@ -496,21 +521,14 @@ for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Uni end end -(-)(A::Symmetric) = Symmetric(-A.data, sym_uplo(A.uplo)) -(-)(A::Hermitian) = Hermitian(-A.data, sym_uplo(A.uplo)) +(-)(A::Symmetric) = Symmetric(parentof_applytri(-, A), sym_uplo(A.uplo)) +(-)(A::Hermitian) = Hermitian(parentof_applytri(-, A), sym_uplo(A.uplo)) ## Addition/subtraction -for f ∈ (:+, :-), (Wrapper, conjugation) ∈ ((:Hermitian, :adjoint), (:Symmetric, :transpose)) - @eval begin - function $f(A::$Wrapper, B::$Wrapper) - if A.uplo == B.uplo - return $Wrapper($f(parent(A), parent(B)), sym_uplo(A.uplo)) - elseif A.uplo == 'U' - return $Wrapper($f(parent(A), $conjugation(parent(B))), :U) - else - return $Wrapper($f($conjugation(parent(A)), parent(B)), :U) - end - end +for f ∈ (:+, :-), Wrapper ∈ (:Hermitian, :Symmetric) + @eval function $f(A::$Wrapper, B::$Wrapper) + uplo = A.uplo == B.uplo ? sym_uplo(A.uplo) : (:U) + $Wrapper(parentof_applytri($f, A, B), uplo) end end @@ -555,12 +573,12 @@ function dot(x::AbstractVector, A::RealHermSymComplexHerm, y::AbstractVector) end # Scaling with Number -*(A::Symmetric, x::Number) = Symmetric(A.data*x, sym_uplo(A.uplo)) -*(x::Number, A::Symmetric) = Symmetric(x*A.data, sym_uplo(A.uplo)) -*(A::Hermitian, x::Real) = Hermitian(A.data*x, sym_uplo(A.uplo)) -*(x::Real, A::Hermitian) = Hermitian(x*A.data, sym_uplo(A.uplo)) -/(A::Symmetric, x::Number) = Symmetric(A.data/x, sym_uplo(A.uplo)) -/(A::Hermitian, x::Real) = Hermitian(A.data/x, sym_uplo(A.uplo)) +*(A::Symmetric, x::Number) = Symmetric(parentof_applytri(y -> y * x, A), sym_uplo(A.uplo)) +*(x::Number, A::Symmetric) = Symmetric(parentof_applytri(y -> x * y, A), sym_uplo(A.uplo)) +*(A::Hermitian, x::Real) = Hermitian(parentof_applytri(y -> y * x, A), sym_uplo(A.uplo)) +*(x::Real, A::Hermitian) = Hermitian(parentof_applytri(y -> x * y, A), sym_uplo(A.uplo)) +/(A::Symmetric, x::Number) = Symmetric(parentof_applytri(y -> y/x, A), sym_uplo(A.uplo)) +/(A::Hermitian, x::Real) = Hermitian(parentof_applytri(y -> y/x, A), sym_uplo(A.uplo)) factorize(A::HermOrSym) = _factorize(A) function _factorize(A::HermOrSym{T}; check::Bool=true) where T diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index ae7373ee79bca..07c2fe410769d 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -946,7 +946,7 @@ function ldiv!(A::Tridiagonal, B::AbstractVecOrMat) B[i+1,j] -= fact*B[i,j] end else - checknonsingular(i, RowMaximum()) + checknonsingular(i) end i < n-1 && (dl[i] = 0) else @@ -967,7 +967,7 @@ function ldiv!(A::Tridiagonal, B::AbstractVecOrMat) end end end - iszero(d[n]) && checknonsingular(n, RowMaximum()) + iszero(d[n]) && checknonsingular(n) # backward substitution for j in 1:nrhs B[n,j] /= d[n] diff --git a/stdlib/LinearAlgebra/test/lu.jl b/stdlib/LinearAlgebra/test/lu.jl index d96510549caa5..a4cbdbe3eb9b9 100644 --- a/stdlib/LinearAlgebra/test/lu.jl +++ b/stdlib/LinearAlgebra/test/lu.jl @@ -245,9 +245,13 @@ end @test_throws ZeroPivotException lu!(copy(A), NoPivot(); check = true) @test !issuccess(lu(A, NoPivot(); check = false)) @test !issuccess(lu!(copy(A), NoPivot(); check = false)) - F = lu(A; check = false) + F = lu(A, NoPivot(); check = false) @test sprint((io, x) -> show(io, "text/plain", x), F) == "Failed factorization of type $(typeof(F))" + F2 = lu(A; allowsingular = true) + @test !issuccess(F2) + @test issuccess(F2, allowsingular = true) + @test occursin("U factor (rank-deficient)", sprint((io, x) -> show(io, "text/plain", x), F2)) end @testset "conversion" begin diff --git a/stdlib/LinearAlgebra/test/symmetric.jl b/stdlib/LinearAlgebra/test/symmetric.jl index b3e0b7b560e7a..d3b24ccf78b0b 100644 --- a/stdlib/LinearAlgebra/test/symmetric.jl +++ b/stdlib/LinearAlgebra/test/symmetric.jl @@ -470,6 +470,42 @@ end end end +@testset "non-isbits algebra" begin + for ST in (Symmetric, Hermitian), uplo in (:L, :U) + M = Matrix{Complex{BigFloat}}(undef,2,2) + M[1,1] = rand() + M[2,2] = rand() + M[1+(uplo==:L), 1+(uplo==:U)] = rand(ComplexF64) + S = ST(M, uplo) + MS = Matrix(S) + @test real(S) == real(MS) + @test imag(S) == imag(MS) + @test conj(S) == conj(MS) + @test conj!(copy(S)) == conj(MS) + @test -S == -MS + @test S + S == MS + MS + @test S - S == MS - MS + @test S*2 == 2*S == 2*MS + @test S/2 == MS/2 + end + @testset "mixed uplo" begin + Mu = Matrix{Complex{BigFloat}}(undef,2,2) + Mu[1,1] = Mu[2,2] = 3 + Mu[1,2] = 2 + 3im + Ml = Matrix{Complex{BigFloat}}(undef,2,2) + Ml[1,1] = Ml[2,2] = 4 + Ml[2,1] = 4 + 5im + for ST in (Symmetric, Hermitian) + Su = ST(Mu, :U) + MSu = Matrix(Su) + Sl = ST(Ml, :L) + MSl = Matrix(Sl) + @test Su + Sl == Sl + Su == MSu + MSl + @test Su - Sl == -(Sl - Su) == MSu - MSl + end + end +end + # bug identified in PR #52318: dot products of quaternionic Hermitian matrices, # or any number type where conj(a)*conj(b) ≠ conj(a*b): @testset "dot Hermitian quaternion #52318" begin @@ -932,4 +968,11 @@ end end end +@testset "conj for immutable" begin + S = Symmetric(reshape((1:16)*im, 4, 4)) + @test conj(S) == conj(Array(S)) + H = Hermitian(reshape((1:16)*im, 4, 4)) + @test conj(H) == conj(Array(H)) +end + end # module TestSymmetric diff --git a/stdlib/Logging/Project.toml b/stdlib/Logging/Project.toml index ce69112733d5e..3fc288e25f0b7 100644 --- a/stdlib/Logging/Project.toml +++ b/stdlib/Logging/Project.toml @@ -2,6 +2,9 @@ name = "Logging" uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" version = "1.11.0" +[deps] +StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" + [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/stdlib/Logging/docs/src/index.md b/stdlib/Logging/docs/src/index.md index ed17c23efdba6..6d0af3ac21321 100644 --- a/stdlib/Logging/docs/src/index.md +++ b/stdlib/Logging/docs/src/index.md @@ -313,6 +313,8 @@ Logging.Debug Logging.Info Logging.Warn Logging.Error +Logging.BelowMinLevel +Logging.AboveMaxLevel Logging.@create_log_macro ``` diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 1d45296c907d1..0922e9fcc66c9 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -12,10 +12,10 @@ Log levels less than `min_level` are filtered out. Message formatting can be controlled by setting keyword arguments: * `meta_formatter` is a function which takes the log event metadata - `(level, _module, group, id, file, line)` and returns a color (as would be - passed to printstyled), prefix and suffix for the log message. The - default is to prefix with the log level and a suffix containing the module, - file and line location. + `(level, _module, group, id, file, line)` and returns a face name (used in + the constructed [`AnnotatedString`](@ref Base.AnnotatedString)), prefix and + suffix for the log message. The default is to prefix with the log level and + a suffix containing the module, file and line location. * `show_limited` limits the printing of large data structures to something which can fit on the screen by setting the `:limit` `IOContext` key during formatting. @@ -59,10 +59,10 @@ showvalue(io, ex::Exception) = showerror(io, ex) function default_logcolor(level::LogLevel) level in keys(custom_log_levels) ? custom_log_levels[level][2] : - level < Info ? Base.debug_color() : - level < Warn ? Base.info_color() : - level < Error ? Base.warn_color() : - Base.error_color() + level < Info ? :log_debug : + level < Warn ? :log_info : + level < Error ? :log_warn : + :log_error end function default_metafmt(level::LogLevel, _module, group, id, file, line) @@ -104,6 +104,8 @@ function termlength(str) return N end +termlength(str::Base.AnnotatedString) = textwidth(str) + function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id, filepath, line; kwargs...) @nospecialize @@ -146,6 +148,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Format lines as text with appropriate indentation and with a box # decoration on the left. color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String} + color = StyledStrings.Face(foreground=StyledStrings.Legacy.legacy_color(color)) minsuffixpad = 2 buf = IOBuffer() iob = IOContext(buf, stream) @@ -159,19 +162,19 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module nonpadwidth = 2 + length(suffix) end for (i, (indent, msg)) in enumerate(msglines) - boxstr = length(msglines) == 1 ? "[ " : - i == 1 ? "┌ " : - i < length(msglines) ? "│ " : - "└ " - printstyled(iob, boxstr, bold=true, color=color) + boxstr = length(msglines) == 1 ? "[" : + i == 1 ? "┌" : + i < length(msglines) ? "│" : + "└" + print(iob, styled"{$color,bold:$boxstr} ") if i == 1 && !isempty(prefix) - printstyled(iob, prefix, " ", bold=true, color=color) + print(iob, styled"{$color,bold:$prefix} ") end print(iob, " "^indent, msg) if i == length(msglines) && !isempty(suffix) npad = max(0, justify_width - nonpadwidth) + minsuffixpad print(iob, " "^npad) - printstyled(iob, suffix, color=:light_black) + print(iob, styled"{shadow:$suffix}") end println(iob) end diff --git a/stdlib/Logging/src/Logging.jl b/stdlib/Logging/src/Logging.jl index 83e93ee396361..c05d3b7227c34 100644 --- a/stdlib/Logging/src/Logging.jl +++ b/stdlib/Logging/src/Logging.jl @@ -8,11 +8,13 @@ and available by default. """ module Logging +using StyledStrings + # Import the CoreLogging implementation into Logging as new const bindings. # Doing it this way (rather than with import) makes these symbols accessible to # tab completion. for sym in [ - :LogLevel, :BelowMinLevel, :AboveMaxLevel, + :LogLevel, :AbstractLogger, :NullLogger, :handle_message, :shouldlog, :min_enabled_level, :catch_exceptions, @@ -31,13 +33,11 @@ for sym in [ end """ - @create_log_macro(name::Symbol, level::Int, color::Union{Int,Symbol}) - -Creates a custom log macro like `@info`, `@warn` etc. with a given `name`, `level` and -`color`. The macro created is named with the lowercase form of `name` but the given form -is used for the printing. + @create_log_macro(name::Symbol, level::Int, face::Union{Symbol, StyledStrings.Face}) -The available color keys can be seen by typing `Base.text_colors` in the help mode of the REPL +Creates a custom log macro like `@info`, `@warn` etc. with a given `name`, +`level` to be displayed with `face`. The macro created is named with the +lowercase form of `name` but the given form is used for the printing. ```julia-repl julia> @create_log_macro(:MyLog, 200, :magenta) @@ -90,6 +90,18 @@ const Warn = Base.CoreLogging.Warn Alias for [`LogLevel(2000)`](@ref LogLevel). """ const Error = Base.CoreLogging.Error +""" + BelowMinLevel + +Alias for [`LogLevel(-1_000_001)`](@ref LogLevel). +""" +const BelowMinLevel = Base.CoreLogging.BelowMinLevel +""" + AboveMaxLevel + +Alias for [`LogLevel(1_000_001)`](@ref LogLevel). +""" +const AboveMaxLevel = Base.CoreLogging.AboveMaxLevel using Base.CoreLogging: closed_stream diff --git a/stdlib/Logging/test/runtests.jl b/stdlib/Logging/test/runtests.jl index e0fc6a0bc3770..1a86c884295b4 100644 --- a/stdlib/Logging/test/runtests.jl +++ b/stdlib/Logging/test/runtests.jl @@ -54,24 +54,24 @@ end @testset "Default metadata formatting" begin @test Logging.default_metafmt(Logging.Debug, Base, :g, :i, expanduser("~/somefile.jl"), 42) == - (:blue, "Debug:", "@ Base ~/somefile.jl:42") + (:log_debug, "Debug:", "@ Base ~/somefile.jl:42") @test Logging.default_metafmt(Logging.Info, Main, :g, :i, "a.jl", 1) == - (:cyan, "Info:", "") + (:log_info, "Info:", "") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", 2) == - (:yellow, "Warning:", "@ Main b.jl:2") + (:log_warn, "Warning:", "@ Main b.jl:2") @test Logging.default_metafmt(Logging.Error, Main, :g, :i, "", 0) == - (:light_red, "Error:", "@ Main :0") + (:log_error, "Error:", "@ Main :0") # formatting of nothing @test Logging.default_metafmt(Logging.Warn, nothing, :g, :i, "b.jl", 2) == - (:yellow, "Warning:", "@ b.jl:2") + (:log_warn, "Warning:", "@ b.jl:2") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, nothing, 2) == - (:yellow, "Warning:", "@ Main") + (:log_warn, "Warning:", "@ Main") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", nothing) == - (:yellow, "Warning:", "@ Main b.jl") + (:log_warn, "Warning:", "@ Main b.jl") @test Logging.default_metafmt(Logging.Warn, nothing, :g, :i, nothing, 2) == - (:yellow, "Warning:", "") + (:log_warn, "Warning:", "") @test Logging.default_metafmt(Logging.Warn, Main, :g, :i, "b.jl", 2:5) == - (:yellow, "Warning:", "@ Main b.jl:2-5") + (:log_warn, "Warning:", "@ Main b.jl:2-5") end function dummy_metafmt(level, _module, group, id, file, line) @@ -256,9 +256,9 @@ end # Basic colorization test @test genmsg("line1\nline2", color=true) == """ - \e[36m\e[1m┌ \e[22m\e[39m\e[36m\e[1mPREFIX \e[22m\e[39mline1 - \e[36m\e[1m│ \e[22m\e[39mline2 - \e[36m\e[1m└ \e[22m\e[39m\e[90mSUFFIX\e[39m + \e[36m\e[1m┌\e[39m\e[22m \e[36m\e[1mPREFIX\e[39m\e[22m line1 + \e[36m\e[1m│\e[39m\e[22m line2 + \e[36m\e[1m└\e[39m\e[22m \e[90mSUFFIX\e[39m """ end @@ -302,8 +302,7 @@ end @testset "Docstrings" begin undoc = Docs.undocumented_names(Logging) - @test_broken isempty(undoc) - @test undoc == [:AboveMaxLevel, :BelowMinLevel] + @test isempty(undoc) end end diff --git a/stdlib/Markdown/src/render/html.jl b/stdlib/Markdown/src/render/html.jl index 3831e6acc7bb9..e7d436f2ccbda 100644 --- a/stdlib/Markdown/src/render/html.jl +++ b/stdlib/Markdown/src/render/html.jl @@ -191,7 +191,7 @@ writing to an (optional) `io` stream or returning a string. One can alternatively use `show(io, "text/html", md)` or `repr("text/html", md)`, which differ in that they wrap the output in a `
...
` element. -# Example +# Examples ```jldoctest julia> html(md"hello _world_") "

hello world

\\n" diff --git a/stdlib/Markdown/src/render/latex.jl b/stdlib/Markdown/src/render/latex.jl index 03bb78ba3efec..df52b2849f2b0 100644 --- a/stdlib/Markdown/src/render/latex.jl +++ b/stdlib/Markdown/src/render/latex.jl @@ -175,7 +175,7 @@ writing to an (optional) `io` stream or returning a string. One can alternatively use `show(io, "text/latex", md)` or `repr("text/latex", md)`. -# Example +# Examples ```jldoctest julia> latex(md"hello _world_") "hello \\\\emph{world}\\n\\n" diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index cd779b8868a37..621cd6f9021fb 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -527,25 +527,7 @@ function find_start_brace(s::AbstractString; c_start='(', c_end=')') return (startind:lastindex(s), method_name_end) end -struct REPLInterpreterCache - dict::IdDict{MethodInstance,CodeInstance} -end -REPLInterpreterCache() = REPLInterpreterCache(IdDict{MethodInstance,CodeInstance}()) -const REPL_INTERPRETER_CACHE = REPLInterpreterCache() - -function get_code_cache() - # XXX Avoid storing analysis results into the cache that persists across precompilation, - # as [sys|pkg]image currently doesn't support serializing externally created `CodeInstance`. - # Otherwise, `CodeInstance`s created by `REPLInterpreter`, that are much less optimized - # that those produced by `NativeInterpreter`, will leak into the native code cache, - # potentially causing runtime slowdown. - # (see https://github.com/JuliaLang/julia/issues/48453). - if Base.generating_output() - return REPLInterpreterCache() - else - return REPL_INTERPRETER_CACHE - end -end +struct REPLCacheToken end struct REPLInterpreter <: CC.AbstractInterpreter limit_aggressive_inference::Bool @@ -553,32 +535,21 @@ struct REPLInterpreter <: CC.AbstractInterpreter inf_params::CC.InferenceParams opt_params::CC.OptimizationParams inf_cache::Vector{CC.InferenceResult} - code_cache::REPLInterpreterCache function REPLInterpreter(limit_aggressive_inference::Bool=false; world::UInt = Base.get_world_counter(), inf_params::CC.InferenceParams = CC.InferenceParams(; aggressive_constant_propagation=true, unoptimize_throw_blocks=false), opt_params::CC.OptimizationParams = CC.OptimizationParams(), - inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[], - code_cache::REPLInterpreterCache = get_code_cache()) - return new(limit_aggressive_inference, world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(limit_aggressive_inference, world, inf_params, opt_params, inf_cache) end end CC.InferenceParams(interp::REPLInterpreter) = interp.inf_params CC.OptimizationParams(interp::REPLInterpreter) = interp.opt_params CC.get_inference_world(interp::REPLInterpreter) = interp.world CC.get_inference_cache(interp::REPLInterpreter) = interp.inf_cache -CC.code_cache(interp::REPLInterpreter) = CC.WorldView(interp.code_cache, CC.WorldRange(interp.world)) -CC.get(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default) -CC.getindex(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance) = getindex(wvc.cache.dict, mi) -CC.haskey(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance) = haskey(wvc.cache.dict, mi) -function CC.setindex!(wvc::CC.WorldView{REPLInterpreterCache}, ci::CodeInstance, mi::MethodInstance) - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.dict, replaced) - end - return setindex!(wvc.cache.dict, ci, mi) -end +CC.cache_owner(::REPLInterpreter) = REPLCacheToken() # REPLInterpreter is only used for type analysis, so it should disable optimization entirely CC.may_optimize(::REPLInterpreter) = false @@ -1165,7 +1136,7 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff if ex === nothing ex = arg else - ex = Expr(:., out, QuoteNode(arg)) + ex = Expr(:., ex, QuoteNode(arg)) end else # invalid expression ex = nothing diff --git a/stdlib/REPL/src/precompile.jl b/stdlib/REPL/src/precompile.jl index 0eea4c140e39b..7299742eaef1c 100644 --- a/stdlib/REPL/src/precompile.jl +++ b/stdlib/REPL/src/precompile.jl @@ -4,8 +4,14 @@ module Precompile # Can't use this during incremental: `@eval Module() begin`` import ..REPL +# Prepare this staging area with all the loaded packages available +for (_pkgid, _mod) in Base.loaded_modules + if !(_pkgid.name in ("Main", "Core", "Base", "REPL")) + eval(:(const $(Symbol(_mod)) = $_mod)) + end +end -# Ugly hack for our cache file to not have a dependency edge on FakePTYs. +# Ugly hack for our cache file to not have a dependency edge on the FakePTYs file. Base._track_dependencies[] = false try Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl")) @@ -172,10 +178,10 @@ generate_precompile_statements() = try end close(precompile_copy) wait(buffer_reader) - close(statements_step) return :ok end !PARALLEL_PRECOMPILATION && wait(step) + bind(statements_step, step) # Make statements unique statements = Set{String}() @@ -205,7 +211,7 @@ generate_precompile_statements() = try end end - fetch(step) == :ok || throw("Collecting precompiles failed.") + fetch(step) == :ok || throw("Collecting precompiles failed: $(c.excp)") return nothing finally GC.gc(true); GC.gc(false); # reduce memory footprint diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 7fd36e3d147e6..0a73a944ec8ea 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -2232,6 +2232,11 @@ let s = "using .Issue52922.Inn" @test res @test "Inner1" in c end +let s = "using .Issue52922.Inner1." + c, r, res = test_complete_context(s) + @test res + @test "Inner12" in c +end let s = "using .Inner1.Inn" c, r, res = test_complete_context(s, Issue52922) @test res diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl index bf5819f6388c6..4ee9e07a58430 100644 --- a/stdlib/Sockets/src/addrinfo.jl +++ b/stdlib/Sockets/src/addrinfo.jl @@ -55,7 +55,7 @@ end Gets all of the IP addresses of the `host`. Uses the operating system's underlying `getaddrinfo` implementation, which may do a DNS lookup. -# Example +# Examples ```julia-repl julia> getalladdrinfo("google.com") 2-element Array{IPAddr,1}: @@ -362,7 +362,7 @@ are not guaranteed to be unique beyond their network segment, therefore routers do not forward them. Link-local addresses are from the address blocks `169.254.0.0/16` or `fe80::/10`. -# Example +# Examples ```julia filter(!islinklocaladdr, getipaddrs()) ``` diff --git a/stdlib/TOML/src/TOML.jl b/stdlib/TOML/src/TOML.jl index 64d715ceef832..858b75a2e0eff 100644 --- a/stdlib/TOML/src/TOML.jl +++ b/stdlib/TOML/src/TOML.jl @@ -110,7 +110,7 @@ const ParserError = Internals.ParserError """ - print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}) + print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::IdSet{<:AbstractDict}) Write `data` as TOML syntax to the stream `io`. If the keyword argument `sorted` is set to `true`, sort tables according to the function given by the keyword argument `by`. If the keyword argument diff --git a/stdlib/TOML/src/print.jl b/stdlib/TOML/src/print.jl index 06e4f08f35c46..91ea4fd392e4b 100644 --- a/stdlib/TOML/src/print.jl +++ b/stdlib/TOML/src/print.jl @@ -146,7 +146,7 @@ function print_table(f::MbyFunc, io::IO, a::AbstractDict, indent::Int = 0, first_block::Bool = true, sorted::Bool = false, - inline_tables::Base.IdSet, + inline_tables::IdSet, by::Function = identity, ) @@ -223,7 +223,7 @@ end # API # ####### -print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) -print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) -print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) -print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) +print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) +print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) +print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) +print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) diff --git a/stdlib/TOML/test/print.jl b/stdlib/TOML/test/print.jl index 9698a2871ae27..79a87b9f0f13f 100644 --- a/stdlib/TOML/test/print.jl +++ b/stdlib/TOML/test/print.jl @@ -148,7 +148,7 @@ d = Dict( "y" => inline_dict, "z" => [1,2,3], ) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, inline_dict) @test toml_str(d; sorted=true, inline_tables) == """ @@ -165,7 +165,7 @@ d = Dict("deps" => Dict( "LocalPkg" => Dict("path" => "LocalPkg"), "Example" => Dict("url" => "https://github.com/JuliaLang/Example.jl"))) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) push!(inline_tables, d["sources"]["Example"]) @@ -180,7 +180,7 @@ Example = {url = "https://github.com/JuliaLang/Example.jl"} LocalPkg = {path = "LocalPkg"} """ -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) s = """ [deps] diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index 3241ff13ca029..e68efdfb6ebf5 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -322,8 +322,12 @@ function finish(ts::CustomTestSet) # just record if we're not the top-level parent if get_testset_depth() > 0 record(get_testset(), ts) + return ts end - ts + + # so the results are printed if we are at the top level + Test.print_test_results(ts) + return ts end ``` @@ -338,6 +342,45 @@ And using that testset looks like: end ``` +In order to use a custom testset and have the recorded results printed as part of any outer default testset, +also define `Test.get_test_counts`. This might look like so: + +```julia +using Test: AbstractTestSet, Pass, Fail, Error, Broken, get_test_counts, TestCounts, format_duration + +function Test.get_test_counts(ts::CustomTestSet) + passes, fails, errors, broken = 0, 0, 0, 0 + # cumulative results + c_passes, c_fails, c_errors, c_broken = 0, 0, 0, 0 + + for t in ts.results + # count up results + isa(t, Pass) && (passes += 1) + isa(t, Fail) && (fails += 1) + isa(t, Error) && (errors += 1) + isa(t, Broken) && (broken += 1) + # handle children + if isa(t, AbstractTestSet) + tc = get_test_counts(t)::TestCounts + c_passes += tc.passes + tc.cumulative_passes + c_fails += tc.fails + tc.cumulative_fails + c_errors += tc.errors + tc.cumulative_errors + c_broken += tc.broken + tc.cumulative_broken + end + end + # get a duration, if we have one + duration = format_duration(ts) + return TestCounts(true, passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration) +end +``` + +```@docs +Test.TestCounts +Test.get_test_counts +Test.format_duration +Test.print_test_results +``` + ## Test utilities ```@docs diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 25d7b0c3127ab..ddd62ca9a10f8 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1114,6 +1114,27 @@ function record(ts::DefaultTestSet, t::Union{Fail, Error}; print_result::Bool=TE return t end +""" + print_verbose(::AbstractTestSet) -> Bool + +Whether printing involving this `AbstractTestSet` should be verbose or not. + +Defaults to `false`. +""" +function print_verbose end + +""" + results(::AbstractTestSet) + +Return an iterator of results aggregated by this `AbstractTestSet`, if any were recorded. + +Defaults to the empty tuple. +""" +function results end + +print_verbose(ts::DefaultTestSet) = ts.verbose +results(ts::DefaultTestSet) = ts.results + # When a DefaultTestSet finishes, it records itself to its parent # testset, if there is one. This allows for recursive printing of # the results at the end of the tests @@ -1121,26 +1142,42 @@ record(ts::DefaultTestSet, t::AbstractTestSet) = push!(ts.results, t) @specialize -function print_test_errors(ts::DefaultTestSet) - for t in ts.results +""" + print_test_errors(::AbstractTestSet) + +Prints the errors that were recorded by this `AbstractTestSet` after it +was `finish`ed. +""" +function print_test_errors(ts::AbstractTestSet) + for t in results(ts) if isa(t, Error) || isa(t, Fail) println("Error in testset $(ts.description):") show(t) println() - elseif isa(t, DefaultTestSet) + elseif isa(t, AbstractTestSet) print_test_errors(t) end end end -function print_test_results(ts::DefaultTestSet, depth_pad=0) +""" + print_test_results(ts::AbstractTestSet, depth_pad=0) + +Print the results of an `AbstractTestSet` as a formatted table. + +`depth_pad` refers to how much padding should be added in front of all output. + +Called inside of `Test.finish`, if the `finish`ed testset is the topmost +testset. +""" +function print_test_results(ts::AbstractTestSet, depth_pad=0) # Calculate the overall number for each type so each of # the test result types are aligned - passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration = get_test_counts(ts) - total_pass = passes + c_passes - total_fail = fails + c_fails - total_error = errors + c_errors - total_broken = broken + c_broken + tc = get_test_counts(ts) + total_pass = tc.passes + tc.cumulative_passes + total_fail = tc.fails + tc.cumulative_fails + total_error = tc.errors + tc.cumulative_errors + total_broken = tc.broken + tc.cumulative_broken dig_pass = total_pass > 0 ? ndigits(total_pass) : 0 dig_fail = total_fail > 0 ? ndigits(total_fail) : 0 dig_error = total_error > 0 ? ndigits(total_error) : 0 @@ -1153,14 +1190,13 @@ function print_test_results(ts::DefaultTestSet, depth_pad=0) fail_width = dig_fail > 0 ? max(length("Fail"), dig_fail) : 0 error_width = dig_error > 0 ? max(length("Error"), dig_error) : 0 broken_width = dig_broken > 0 ? max(length("Broken"), dig_broken) : 0 - total_width = dig_total > 0 ? max(length("Total"), dig_total) : 0 - duration_width = max(length("Time"), length(duration)) + total_width = max(textwidth("Total"), dig_total) + duration_width = max(textwidth("Time"), textwidth(tc.duration)) # Calculate the alignment of the test result counts by # recursively walking the tree of test sets - align = max(get_alignment(ts, 0), length("Test Summary:")) + align = max(get_alignment(ts, 0), textwidth("Test Summary:")) # Print the outer test set header once - pad = total == 0 ? "" : " " - printstyled(rpad("Test Summary:", align, " "), " |", pad; bold=true) + printstyled(rpad("Test Summary:", align, " "), " |", " "; bold=true) if pass_width > 0 printstyled(lpad("Pass", pass_width, " "), " "; bold=true, color=:green) end @@ -1173,15 +1209,16 @@ function print_test_results(ts::DefaultTestSet, depth_pad=0) if broken_width > 0 printstyled(lpad("Broken", broken_width, " "), " "; bold=true, color=Base.warn_color()) end - if total_width > 0 + if total_width > 0 || total == 0 printstyled(lpad("Total", total_width, " "), " "; bold=true, color=Base.info_color()) end - if ts.showtiming + timing = isdefined(ts, :showtiming) ? ts.showtiming : false + if timing printstyled(lpad("Time", duration_width, " "); bold=true) end println() # Recursively print a summary at every level - print_counts(ts, depth_pad, align, pass_width, fail_width, error_width, broken_width, total_width, duration_width, ts.showtiming) + print_counts(ts, depth_pad, align, pass_width, fail_width, error_width, broken_width, total_width, duration_width, timing) end @@ -1199,11 +1236,11 @@ function finish(ts::DefaultTestSet; print_results::Bool=TESTSET_PRINT_ENABLE[]) record(parent_ts, ts) return ts end - passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration = get_test_counts(ts) - total_pass = passes + c_passes - total_fail = fails + c_fails - total_error = errors + c_errors - total_broken = broken + c_broken + tc = get_test_counts(ts) + total_pass = tc.passes + tc.cumulative_passes + total_fail = tc.fails + tc.cumulative_fails + total_error = tc.errors + tc.cumulative_errors + total_broken = tc.broken + tc.cumulative_broken total = total_pass + total_fail + total_error + total_broken if print_results @@ -1253,100 +1290,165 @@ function filter_errors(ts::DefaultTestSet) efs end -# Recursive function that counts the number of test results of each -# type directly in the testset, and totals across the child testsets +""" + TestCounts + +Holds the state for recursively gathering the results of a test set for display purposes. + +Fields: + + * `customized`: Whether the function `get_test_counts` was customized for the `AbstractTestSet` + this counts object is for. If a custom method was defined, always pass `true` + to the constructor. + * `passes`: The number of passing `@test` invocations. + * `fails`: The number of failing `@test` invocations. + * `errors`: The number of erroring `@test` invocations. + * `broken`: The number of broken `@test` invocations. + * `passes`: The cumulative number of passing `@test` invocations. + * `fails`: The cumulative number of failing `@test` invocations. + * `errors`: The cumulative number of erroring `@test` invocations. + * `broken`: The cumulative number of broken `@test` invocations. + * `duration`: The total duration the `AbstractTestSet` in question ran for, as a formatted `String`. +""" +struct TestCounts + customized::Bool + passes::Int + fails::Int + errors::Int + broken::Int + cumulative_passes::Int + cumulative_fails::Int + cumulative_errors::Int + cumulative_broken::Int + duration::String +end + +"""" + get_test_counts(::AbstractTestSet) -> TestCounts + +Recursive function that counts the number of test results of each +type directly in the testset, and totals across the child testsets. + +Custom `AbstractTestSet` should implement this function to get their totals +counted & displayed with `DefaultTestSet` as well. + +If this is not implemented for a custom `TestSet`, the printing falls back to +reporting `x` for failures and `?s` for the duration. +""" +function get_test_counts end + +get_test_counts(ts::AbstractTestSet) = TestCounts(false, 0,0,0,0,0,0,0,0, format_duration(ts)) + function get_test_counts(ts::DefaultTestSet) passes, fails, errors, broken = ts.n_passed, 0, 0, 0 + # cumulative results c_passes, c_fails, c_errors, c_broken = 0, 0, 0, 0 for t in ts.results isa(t, Fail) && (fails += 1) isa(t, Error) && (errors += 1) isa(t, Broken) && (broken += 1) - if isa(t, DefaultTestSet) - np, nf, ne, nb, ncp, ncf, nce , ncb, duration = get_test_counts(t) - c_passes += np + ncp - c_fails += nf + ncf - c_errors += ne + nce - c_broken += nb + ncb + if isa(t, AbstractTestSet) + tc = get_test_counts(t)::TestCounts + c_passes += tc.passes + tc.cumulative_passes + c_fails += tc.fails + tc.cumulative_fails + c_errors += tc.errors + tc.cumulative_errors + c_broken += tc.broken + tc.cumulative_broken end end + duration = format_duration(ts) ts.anynonpass = (fails + errors + c_fails + c_errors > 0) + return TestCounts(true, passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration) +end + +""" + format_duration(::AbstractTestSet) + +Return a formatted string for printing the duration the testset ran for. + +If not defined, falls back to `"?s"`. +""" +format_duration(::AbstractTestSet) = "?s" + +function format_duration(ts::DefaultTestSet) (; time_start, time_end) = ts - duration = if isnothing(time_end) - "" + isnothing(time_end) && return "" + + dur_s = time_end - time_start + if dur_s < 60 + string(round(dur_s, digits = 1), "s") else - dur_s = time_end - time_start - if dur_s < 60 - string(round(dur_s, digits = 1), "s") - else - m, s = divrem(dur_s, 60) - s = lpad(string(round(s, digits = 1)), 4, "0") - string(round(Int, m), "m", s, "s") - end + m, s = divrem(dur_s, 60) + s = lpad(string(round(s, digits = 1)), 4, "0") + string(round(Int, m), "m", s, "s") end - return passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration end +print_verbose(::AbstractTestSet) = false +results(::AbstractTestSet) = () + # Recursive function that prints out the results at each level of # the tree of test sets -function print_counts(ts::DefaultTestSet, depth, align, +function print_counts(ts::AbstractTestSet, depth, align, pass_width, fail_width, error_width, broken_width, total_width, duration_width, showtiming) # Count results by each type at this level, and recursively # through any child test sets - passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken, duration = get_test_counts(ts) - subtotal = passes + fails + errors + broken + c_passes + c_fails + c_errors + c_broken + tc = get_test_counts(ts) + fallbackstr = tc.customized ? " " : "x" + subtotal = tc.passes + tc.fails + tc.errors + tc.broken + + tc.cumulative_passes + tc.cumulative_fails + tc.cumulative_errors + tc.cumulative_broken # Print test set header, with an alignment that ensures all # the test results appear above each other print(rpad(string(" "^depth, ts.description), align, " "), " | ") - np = passes + c_passes - if np > 0 - printstyled(lpad(string(np), pass_width, " "), " ", color=:green) + n_passes = tc.passes + tc.cumulative_passes + if n_passes > 0 + printstyled(lpad(string(n_passes), pass_width, " "), " ", color=:green) elseif pass_width > 0 # No passes at this level, but some at another level - print(lpad(" ", pass_width), " ") + printstyled(lpad(fallbackstr, pass_width, " "), " ", color=:green) end - nf = fails + c_fails - if nf > 0 - printstyled(lpad(string(nf), fail_width, " "), " ", color=Base.error_color()) + n_fails = tc.fails + tc.cumulative_fails + if n_fails > 0 + printstyled(lpad(string(n_fails), fail_width, " "), " ", color=Base.error_color()) elseif fail_width > 0 # No fails at this level, but some at another level - print(lpad(" ", fail_width), " ") + printstyled(lpad(fallbackstr, fail_width, " "), " ", color=Base.error_color()) end - ne = errors + c_errors - if ne > 0 - printstyled(lpad(string(ne), error_width, " "), " ", color=Base.error_color()) + n_errors = tc.errors + tc.cumulative_errors + if n_errors > 0 + printstyled(lpad(string(n_errors), error_width, " "), " ", color=Base.error_color()) elseif error_width > 0 # No errors at this level, but some at another level - print(lpad(" ", error_width), " ") + printstyled(lpad(fallbackstr, error_width, " "), " ", color=Base.error_color()) end - nb = broken + c_broken - if nb > 0 - printstyled(lpad(string(nb), broken_width, " "), " ", color=Base.warn_color()) + n_broken = tc.broken + tc.cumulative_broken + if n_broken > 0 + printstyled(lpad(string(n_broken), broken_width, " "), " ", color=Base.warn_color()) elseif broken_width > 0 # None broken at this level, but some at another level - print(lpad(" ", broken_width), " ") + printstyled(lpad(fallbackstr, broken_width, " "), " ", color=Base.warn_color()) end - if np == 0 && nf == 0 && ne == 0 && nb == 0 - printstyled(lpad("None", total_width, " "), " ", color=Base.info_color()) + if n_passes == 0 && n_fails == 0 && n_errors == 0 && n_broken == 0 + total_str = tc.customized ? string(subtotal) : "?" + printstyled(lpad(total_str, total_width, " "), " ", color=Base.info_color()) else printstyled(lpad(string(subtotal), total_width, " "), " ", color=Base.info_color()) end if showtiming - printstyled(lpad(string(duration), duration_width, " ")) + printstyled(lpad(tc.duration, duration_width, " ")) end println() # Only print results at lower levels if we had failures or if the user - # wants. - if (np + nb != subtotal) || (ts.verbose) - for t in ts.results - if isa(t, DefaultTestSet) + # wants. Requires the given `AbstractTestSet` to have a vector of results + if ((n_passes + n_broken != subtotal) || print_verbose(ts)) + for t in results(ts) + if isa(t, AbstractTestSet) print_counts(t, depth + 1, align, pass_width, fail_width, error_width, broken_width, total_width, duration_width, ts.showtiming) end diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index 7b3838903ce10..42d3eaf8eaa48 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -55,7 +55,7 @@ most `n` times. See also: [`LogRecord`](@ref). -## Example +## Examples ```jldoctest julia> using Test, Logging diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index ecabe85250906..460e2eadf42b7 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -468,11 +468,11 @@ end end @testset "ts results" begin @test isa(ts, Test.DefaultTestSet) - passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken = Test.get_test_counts(ts) - total_pass = passes + c_passes - total_fail = fails + c_fails - total_error = errors + c_errors - total_broken = broken + c_broken + tc = Test.get_test_counts(ts) + total_pass = tc.passes + tc.cumulative_passes + total_fail = tc.fails + tc.cumulative_fails + total_error = tc.errors + tc.cumulative_errors + total_broken = tc.broken + tc.cumulative_broken @test total_pass == 24 @test total_fail == 6 @test total_error == 6 @@ -1604,3 +1604,109 @@ end @test res isa CustomTestSetModule.CustomTestSet end end + +struct CustomPrintingTestSet <: AbstractTestSet + description::String + passes::Int + errors::Int + fails::Int + broken::Int +end + +function Test.finish(cpts::CustomPrintingTestSet) + if Test.get_testset_depth() != 0 + push!(Test.get_current_testset(), cpts) + # printing is handled by the parent + return cpts + end + + Test.print_testset_results(cpts) + cpts +end + +@testset "Custom testsets participate in printing" begin + mktemp() do f, _ + write(f, + """ + using Test + + mutable struct CustomPrintingTestSet <: Test.AbstractTestSet + description::String + passes::Int + fails::Int + errors::Int + broken::Int + end + CustomPrintingTestSet(desc::String) = CustomPrintingTestSet(desc, 0,0,0,0) + + Test.record(cpts::CustomPrintingTestSet, ::Test.Pass) = cpts.passes += 1 + Test.record(cpts::CustomPrintingTestSet, ::Test.Error) = cpts.errors += 1 + Test.record(cpts::CustomPrintingTestSet, ::Test.Fail) = cpts.fails += 1 + Test.record(cpts::CustomPrintingTestSet, ::Test.Broken) = cpts.broken += 1 + Test.get_test_counts(ts::CustomPrintingTestSet) = Test.TestCounts( + true, + ts.passes, + ts.fails, + ts.errors, + ts.broken, + 0, + 0, + 0, + 0, + Test.format_duration(ts)) + + function Test.finish(cpts::CustomPrintingTestSet) + if Test.get_testset_depth() != 0 + Test.record(Test.get_testset(), cpts) + # printing is handled by the parent + return cpts + end + + Test.print_test_results(cpts) + cpts + end + + struct NonRecordingTestSet <: Test.AbstractTestSet + description::String + end + Test.record(nrts::NonRecordingTestSet, ::Test.Result) = nrts + Test.finish(nrts::NonRecordingTestSet) = Test.record(Test.get_testset(), nrts) + + @testset "outer" begin + @testset "a" begin + @test true + end + @testset CustomPrintingTestSet "custom" begin + @test false + @test true + @test_broken false + @test error() + end + @testset NonRecordingTestSet "no-record" begin + @test false + @test true + @test_broken false + @test error() + end + @testset "b" begin + @test true + end + end + """) + + # this tests both the `TestCounts` parts as well as the fallback `x`s + expected = r""" + Test Summary: | Pass Fail Error Broken Total Time + outer | 3 1 1 1 6 \s*\d*.\ds + a | 1 1 \s*\d*.\ds + custom | 1 1 1 1 4 \s*?s + no-record | x x x x ? \s*?s + b | 1 1 \s*\d*.\ds + ERROR: Some tests did not pass: 3 passed, 1 failed, 1 errored, 1 broken. + """ + + cmd = `$(Base.julia_cmd()) --startup-file=no --color=no $f` + result = read(pipeline(ignorestatus(cmd), stderr=devnull), String) + @test occursin(expected, result) + end +end diff --git a/test/compiler/AbstractInterpreter.jl b/test/compiler/AbstractInterpreter.jl index 77636bfba9a17..c0b320009b8ec 100644 --- a/test/compiler/AbstractInterpreter.jl +++ b/test/compiler/AbstractInterpreter.jl @@ -368,7 +368,7 @@ let NoinlineModule = Module() # it should work for cached results method = only(methods(inlined_usually, (Float64,Float64,Float64,))) mi = CC.specialize_method(method, Tuple{typeof(inlined_usually),Float64,Float64,Float64}, Core.svec()) - @test haskey(interp.code_cache.dict, mi) + @test CC.haskey(CC.code_cache(interp), mi) let src = code_typed1((Float64,Float64,Float64); interp) do x, y, z inlined_usually(x, y, z) end @@ -442,7 +442,8 @@ function custom_lookup(mi::MethodInstance, min_world::UInt, max_world::UInt) end end end - return CONST_INVOKE_INTERP.code_cache.dict[mi] + # XXX: This seems buggy, custom_lookup should probably construct the absint on demand. + return CC.getindex(CC.code_cache(CONST_INVOKE_INTERP), mi) end let # generate cache diff --git a/test/compiler/EscapeAnalysis/EAUtils.jl b/test/compiler/EscapeAnalysis/EAUtils.jl index 2a4f04f8f79ea..87228aaf2858a 100644 --- a/test/compiler/EscapeAnalysis/EAUtils.jl +++ b/test/compiler/EscapeAnalysis/EAUtils.jl @@ -62,7 +62,7 @@ __clear_cache!() = empty!(GLOBAL_EA_CODE_CACHE) # imports import .CC: AbstractInterpreter, NativeInterpreter, WorldView, WorldRange, - InferenceParams, OptimizationParams, get_world_counter, get_inference_cache, code_cache, + InferenceParams, OptimizationParams, get_world_counter, get_inference_cache, ipo_dataflow_analysis!, cache_result! # usings using Core: @@ -71,11 +71,7 @@ using .CC: InferenceResult, OptimizationState, IRCode using .EA: analyze_escapes, ArgEscapeCache, EscapeInfo, EscapeState -struct CodeCache - cache::IdDict{MethodInstance,CodeInstance} -end -CodeCache() = CodeCache(IdDict{MethodInstance,CodeInstance}()) -const GLOBAL_CODE_CACHE = CodeCache() +struct EAToken end # when working outside of Core.Compiler, # cache entire escape state for later inspection and debugging @@ -86,7 +82,7 @@ struct EscapeCacheInfo end struct EscapeCache - cache::IdDict{MethodInstance,EscapeCacheInfo} + cache::IdDict{MethodInstance,EscapeCacheInfo} # TODO(aviatesk) Should this be CodeInstance to EscapeCacheInfo? end EscapeCache() = EscapeCache(IdDict{MethodInstance,EscapeCacheInfo}()) const GLOBAL_ESCAPE_CACHE = EscapeCache() @@ -102,17 +98,15 @@ mutable struct EscapeAnalyzer <: AbstractInterpreter const inf_params::InferenceParams const opt_params::OptimizationParams const inf_cache::Vector{InferenceResult} - const code_cache::CodeCache const escape_cache::EscapeCache const entry_mi::MethodInstance result::EscapeResultForEntry function EscapeAnalyzer(world::UInt, entry_mi::MethodInstance, - code_cache::CodeCache=GLOBAL_CODE_CACHE, escape_cache::EscapeCache=GLOBAL_ESCAPE_CACHE) inf_params = InferenceParams() opt_params = OptimizationParams() inf_cache = InferenceResult[] - return new(world, inf_params, opt_params, inf_cache, code_cache, escape_cache, entry_mi) + return new(world, inf_params, opt_params, inf_cache, escape_cache, entry_mi) end end @@ -120,28 +114,7 @@ CC.InferenceParams(interp::EscapeAnalyzer) = interp.inf_params CC.OptimizationParams(interp::EscapeAnalyzer) = interp.opt_params CC.get_inference_world(interp::EscapeAnalyzer) = interp.world CC.get_inference_cache(interp::EscapeAnalyzer) = interp.inf_cache - -struct EscapeAnalyzerCacheView - code_cache::CodeCache - escape_cache::EscapeCache -end - -function CC.code_cache(interp::EscapeAnalyzer) - worlds = WorldRange(CC.get_inference_world(interp)) - return WorldView(EscapeAnalyzerCacheView(interp.code_cache, interp.escape_cache), worlds) -end -CC.haskey(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance) = haskey(wvc.cache.code_cache.cache, mi) -CC.get(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance, default) = get(wvc.cache.code_cache.cache, mi, default) -CC.getindex(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance) = getindex(wvc.cache.code_cache.cache, mi) -function CC.setindex!(wvc::WorldView{EscapeAnalyzerCacheView}, ci::CodeInstance, mi::MethodInstance) - wvc.cache.code_cache.cache[mi] = ci - # register the callback on invalidation - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.code_cache.cache, replaced) - delete!(wvc.cache.escape_cache.cache, replaced) - end - return wvc -end +CC.cache_owner(::EscapeAnalyzer) = EAToken() function CC.ipo_dataflow_analysis!(interp::EscapeAnalyzer, ir::IRCode, caller::InferenceResult) # run EA on all frames that have been optimized diff --git a/test/compiler/interpreter_exec.jl b/test/compiler/interpreter_exec.jl index ce0704be15178..31f3f510cf4a2 100644 --- a/test/compiler/interpreter_exec.jl +++ b/test/compiler/interpreter_exec.jl @@ -20,13 +20,18 @@ let m = Meta.@lower 1 + 1 ReturnNode(SSAValue(6)), ] nstmts = length(src.code) - src.ssavaluetypes = Any[ Any for _ = 1:nstmts ] + src.ssavaluetypes = nstmts src.ssaflags = fill(UInt8(0x00), nstmts) src.codelocs = fill(Int32(1), nstmts) - src.inferred = true + @test !src.inferred Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src)) global test29262 = true @test :a === @eval $m + compile_mode = @ccall jl_get_module_compile(@__MODULE__()::Module)::Cint + if compile_mode == 3 + # implies `Base.Experimental.@compiler_options compile=min` + @test !src.inferred + end global test29262 = false @test :b === @eval $m end @@ -61,13 +66,19 @@ let m = Meta.@lower 1 + 1 ReturnNode(SSAValue(18)), ] nstmts = length(src.code) - src.ssavaluetypes = Any[ Any for _ = 1:nstmts ] + src.ssavaluetypes = nstmts src.ssaflags = fill(UInt8(0x00), nstmts) src.codelocs = fill(Int32(1), nstmts) - src.inferred = true + @test !src.inferred Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src)) global test29262 = true @test (:b, :a, :c, :c) === @eval $m + compile_mode = @ccall jl_get_module_compile(@__MODULE__()::Module)::Cint + if compile_mode == 3 + # implies `Base.Experimental.@compiler_options compile=min` + @test !src.inferred + end + src.ssavaluetypes = nstmts global test29262 = false @test (:b, :a, :c, :b) === @eval $m end @@ -98,27 +109,18 @@ let m = Meta.@lower 1 + 1 ReturnNode(SSAValue(11)), ] nstmts = length(src.code) - src.ssavaluetypes = Any[ Any for _ = 1:nstmts ] + src.ssavaluetypes = nstmts src.ssaflags = fill(UInt8(0x00), nstmts) src.codelocs = fill(Int32(1), nstmts) - src.inferred = true + @test !src.inferred Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src)) global test29262 = true @test :a === @eval $m + compile_mode = @ccall jl_get_module_compile(@__MODULE__()::Module)::Cint + if compile_mode == 3 + # implies `Base.Experimental.@compiler_options compile=min` + @test !src.inferred + end global test29262 = false @test :b === @eval $m end - -# https://github.com/JuliaLang/julia/issues/47065 -# `Core.Compiler.sort!` should be able to handle a big list -let n = 1000 - ex = :(return 1) - for _ in 1:n - ex = :(rand() < .1 && $(ex)) - end - @eval global function f_1000_blocks() - $ex - return 0 - end -end -@test f_1000_blocks() == 0 diff --git a/test/compiler/invalidation.jl b/test/compiler/invalidation.jl index e3263156499c8..d5e86ca533f05 100644 --- a/test/compiler/invalidation.jl +++ b/test/compiler/invalidation.jl @@ -7,51 +7,28 @@ include("irutils.jl") using Test const CC = Core.Compiler -import Core: MethodInstance, CodeInstance -import .CC: WorldRange, WorldView -struct InvalidationTesterCache - dict::IdDict{MethodInstance,CodeInstance} -end -InvalidationTesterCache() = InvalidationTesterCache(IdDict{MethodInstance,CodeInstance}()) - -const INVALIDATION_TESTER_CACHE = InvalidationTesterCache() +struct InvalidationTesterToken end struct InvalidationTester <: CC.AbstractInterpreter world::UInt inf_params::CC.InferenceParams opt_params::CC.OptimizationParams inf_cache::Vector{CC.InferenceResult} - code_cache::InvalidationTesterCache function InvalidationTester(; world::UInt = Base.get_world_counter(), inf_params::CC.InferenceParams = CC.InferenceParams(), opt_params::CC.OptimizationParams = CC.OptimizationParams(), - inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[], - code_cache::InvalidationTesterCache = INVALIDATION_TESTER_CACHE) - return new(world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(world, inf_params, opt_params, inf_cache) end end -struct InvalidationTesterCacheView - dict::IdDict{MethodInstance,CodeInstance} -end - CC.InferenceParams(interp::InvalidationTester) = interp.inf_params CC.OptimizationParams(interp::InvalidationTester) = interp.opt_params CC.get_inference_world(interp::InvalidationTester) = interp.world CC.get_inference_cache(interp::InvalidationTester) = interp.inf_cache -CC.code_cache(interp::InvalidationTester) = WorldView(InvalidationTesterCacheView(interp.code_cache.dict), WorldRange(interp.world)) -CC.get(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default) -CC.getindex(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance) = getindex(wvc.cache.dict, mi) -CC.haskey(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance) = haskey(wvc.cache.dict, mi) -function CC.setindex!(wvc::WorldView{InvalidationTesterCacheView}, ci::CodeInstance, mi::MethodInstance) - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.dict, replaced) - # Core.println("[InvalidationTester] ", replaced) # debug - end - setindex!(wvc.cache.dict, ci, mi) -end +CC.cache_owner(::InvalidationTester) = InvalidationTesterToken() # basic functionality test # ------------------------ @@ -63,33 +40,55 @@ basic_caller(x) = basic_callee(x) @test Base.return_types((Float64,); interp=InvalidationTester()) do x basic_caller(x) end |> only === Float64 -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee + +let mi = Base.method_instance(basic_callee, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller + +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end # this redefinition below should invalidate the cache +const BASIC_CALLER_WORLD = Base.get_world_counter() basic_callee(x) = x, x -@test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee -end -@test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller +@test !isdefined(Base.method_instance(basic_callee, (Float64,)), :cache) +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == BASIC_CALLER_WORLD end # re-run inference and check the result is updated (and new cache exists) @test Base.return_types((Float64,); interp=InvalidationTester()) do x basic_caller(x) end |> only === Tuple{Float64,Float64} -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee +let mi = Base.method_instance(basic_callee, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller + +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world != typemax(UInt) end + # backedge optimization # --------------------- @@ -115,24 +114,47 @@ begin take!(GLOBAL_BUFFER) @test rt === Any @test any(iscall((src, pr48932_callee)), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee + + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_callee)))) + # Base.method_instance(pr48932_callee, (Any,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + + # In cache due to Base.return_types(pr48932_callee, (Any,)) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller + let mi = Base.method_instance(pr48932_caller, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test 42 == pr48932_caller(42) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we didn't add the backedge from `pr48932_callee` to `pr48932_caller`: # this redefinition below should invalidate the cache of `pr48932_callee` but not that of `pr48932_caller` pr48932_callee(x) = (print(GLOBAL_BUFFER, x); nothing) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee - end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee)))) + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_caller)))) + # Base.method_instance(pr48932_callee, (Any,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test isnothing(pr48932_caller(42)) @test "42" == String(take!(GLOBAL_BUFFER)) end @@ -159,23 +181,41 @@ begin take!(GLOBAL_BUFFER) @test rt === Nothing @test any(iscall((src, pr48932_callee_inferable)), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inferable + + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable)))) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_unuse + let mi = Base.method_instance(pr48932_caller_unuse, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test isnothing(pr48932_caller_unuse(42)) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we didn't add the backedge from `pr48932_callee_inferable` to `pr48932_caller_unuse`: # this redefinition below should invalidate the cache of `pr48932_callee_inferable` but not that of `pr48932_caller_unuse` pr48932_callee_inferable(x) = (print(GLOBAL_BUFFER, "foo"); x) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inferable - end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_unuse + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable)))) + let mi = Base.method_instance(pr48932_caller_unuse, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end @test isnothing(pr48932_caller_unuse(42)) @test "foo" == String(take!(GLOBAL_BUFFER)) @@ -201,24 +241,43 @@ begin take!(GLOBAL_BUFFER) @test rt === Any @test any(isinvoke(:pr48932_callee_inlined), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inlined + + let mi = Base.method_instance(pr48932_callee_inlined, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_inlined + let mi = Base.method_instance(pr48932_caller_inlined, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test 42 == pr48932_caller_inlined(42) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we added the backedge from `pr48932_callee_inlined` to `pr48932_caller_inlined`: # this redefinition below should invalidate the cache of `pr48932_callee_inlined` but not that of `pr48932_caller_inlined` @noinline pr48932_callee_inlined(@nospecialize x) = (print(GLOBAL_BUFFER, x); nothing) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inlined - end - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_inlined + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inlined)))) + let mi = Base.method_instance(pr48932_caller_inlined, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world != typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world != typemax(UInt) end + @test isnothing(pr48932_caller_inlined(42)) @test "42" == String(take!(GLOBAL_BUFFER)) end diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index 2e14fdb8d3013..9345c2e26db33 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -1787,3 +1787,17 @@ let code = Any[ @test !any(iscall((ir, getfield)), ir.stmts.stmt) @test length(ir.cfg.blocks[end].stmts) == 1 end + +# https://github.com/JuliaLang/julia/issues/47065 +# `Core.Compiler.sort!` should be able to handle a big list +let n = 1000 + ex = :(return 1) + for _ in 1:n + ex = :(rand() < .1 && $(ex)) + end + @eval global function f_1000_blocks() + $ex + return 0 + end +end +@test f_1000_blocks() == 0 diff --git a/test/compiler/newinterp.jl b/test/compiler/newinterp.jl index 4b2cabcf33c3b..1157a52ebbcbe 100644 --- a/test/compiler/newinterp.jl +++ b/test/compiler/newinterp.jl @@ -9,39 +9,29 @@ Defines new `NewInterpreter <: AbstractInterpreter` whose cache is separated from the native code cache, satisfying the minimum interface requirements. """ macro newinterp(InterpName) - InterpCacheName = esc(Symbol(string(InterpName, "Cache"))) + InterpCacheName = QuoteNode(Symbol(string(InterpName, "Cache"))) InterpName = esc(InterpName) C = Core CC = Core.Compiler quote - struct $InterpCacheName - dict::IdDict{$C.MethodInstance,$C.CodeInstance} - end - $InterpCacheName() = $InterpCacheName(IdDict{$C.MethodInstance,$C.CodeInstance}()) struct $InterpName <: $CC.AbstractInterpreter meta # additional information world::UInt inf_params::$CC.InferenceParams opt_params::$CC.OptimizationParams inf_cache::Vector{$CC.InferenceResult} - code_cache::$InterpCacheName function $InterpName(meta = nothing; world::UInt = Base.get_world_counter(), inf_params::$CC.InferenceParams = $CC.InferenceParams(), opt_params::$CC.OptimizationParams = $CC.OptimizationParams(), - inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[], - code_cache::$InterpCacheName = $InterpCacheName()) - return new(meta, world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[]) + return new(meta, world, inf_params, opt_params, inf_cache) end end $CC.InferenceParams(interp::$InterpName) = interp.inf_params $CC.OptimizationParams(interp::$InterpName) = interp.opt_params $CC.get_inference_world(interp::$InterpName) = interp.world $CC.get_inference_cache(interp::$InterpName) = interp.inf_cache - $CC.code_cache(interp::$InterpName) = $CC.WorldView(interp.code_cache, $CC.WorldRange(interp.world)) - $CC.get(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance, default) = get(wvc.cache.dict, mi, default) - $CC.getindex(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = getindex(wvc.cache.dict, mi) - $CC.haskey(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = haskey(wvc.cache.dict, mi) - $CC.setindex!(wvc::$CC.WorldView{$InterpCacheName}, ci::$C.CodeInstance, mi::$C.MethodInstance) = setindex!(wvc.cache.dict, ci, mi) + $CC.cache_owner(::$InterpName) = $InterpCacheName end end diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index bab11d3ead522..3a90ee6308d53 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -92,11 +92,15 @@ let cfg = CFG(BasicBlock[ end end -for compile in ("min", "yes") - cmd = `$(Base.julia_cmd()) --compile=$compile interpreter_exec.jl` - if !success(pipeline(Cmd(cmd, dir=@__DIR__); stdout=stdout, stderr=stderr)) - error("Interpreter test failed, cmd : $cmd") - end +# test code execution with the default compile-mode +module CompilerExecTest +include("interpreter_exec.jl") +end + +# test code execution with the interpreter mode (compile=min) +module InterpreterExecTest +Base.Experimental.@compiler_options compile=min +include("interpreter_exec.jl") end # PR #32145 diff --git a/test/core.jl b/test/core.jl index a2c3b3cff9e6b..aa16380c8a866 100644 --- a/test/core.jl +++ b/test/core.jl @@ -14,7 +14,7 @@ include("testenv.jl") # sanity tests that our built-in types are marked correctly for const fields for (T, c) in ( (Core.CodeInfo, []), - (Core.CodeInstance, [:def, :rettype, :exctype, :rettype_const, :ipo_purity_bits, :analysis_results]), + (Core.CodeInstance, [:def, :owner, :rettype, :exctype, :rettype_const, :ipo_purity_bits, :analysis_results]), (Core.Method, [#=:name, :module, :file, :line, :primary_world, :sig, :slot_syms, :external_mt, :nargs, :called, :nospecialize, :nkw, :isva, :is_for_opaque_closure, :constprop=#]), (Core.MethodInstance, [#=:def, :specTypes, :sparam_vals=#]), (Core.MethodTable, [:module]), @@ -32,7 +32,7 @@ end # sanity tests that our built-in types are marked correctly for atomic fields for (T, c) in ( (Core.CodeInfo, []), - (Core.CodeInstance, [:next, :min_world, :max_world, :inferred, :purity_bits, :invoke, :specptr, :precompile]), + (Core.CodeInstance, [:next, :min_world, :max_world, :inferred, :purity_bits, :invoke, :specptr, :specsigflags, :precompile]), (Core.Method, [:primary_world, :deleted_world]), (Core.MethodInstance, [:uninferred, :cache, :precompiled]), (Core.MethodTable, [:defs, :leafcache, :cache, :max_args]), diff --git a/test/dict.jl b/test/dict.jl index f44c6d696bc74..ca8a598de0b81 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -162,6 +162,30 @@ end # issue #39117 @test Dict(t[1]=>t[2] for t in zip((1,"2"), (2,"2"))) == Dict{Any,Any}(1=>2, "2"=>"2") + + @testset "issue #33147" begin + expected = try; Base._throw_dict_kv_error(); catch e; e; end + @test_throws expected Dict(i for i in 1:2) + @test_throws expected Dict(nothing for i in 1:2) + @test_throws expected Dict(() for i in 1:2) + @test_throws expected Dict((i, i, i) for i in 1:2) + @test_throws expected Dict(nothing) + @test_throws expected Dict((1,)) + @test_throws expected Dict(1:2) + @test_throws expected Dict(((),)) + @test_throws expected IdDict(((),)) + @test_throws expected WeakKeyDict(((),)) + @test_throws expected IdDict(nothing) + @test_throws expected WeakKeyDict(nothing) + @test Dict(1:0) isa Dict + @test Dict(()) isa Dict + try + Dict(i => error("$i") for i in 1:3) + catch ex + @test ex isa ErrorException + @test length(Base.current_exceptions()) == 1 + end + end end @testset "empty tuple ctor" begin diff --git a/test/errorshow.jl b/test/errorshow.jl index a12224554fd11..932122682983e 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -78,8 +78,12 @@ Base.show_method_candidates(buf, Base.MethodError(method_c1,(1, "", ""))) Base.show_method_candidates(buf, Base.MethodError(method_c1,(1., "", ""))) @test occursin("\n\nClosest candidates are:\n method_c1(::Float64, ::AbstractString...)$cmod$cfile$c1line\n", String(take!(buf))) -# Have no matches so should return empty +# Have no matches, but still print up to 3 Base.show_method_candidates(buf, Base.MethodError(method_c1,(1, 1, 1))) +@test occursin("\n\nClosest candidates are:\n method_c1(!Matched::Float64, !Matched::AbstractString...)$cmod$cfile$c1line\n", String(take!(buf))) + +function nomethodsfunc end +Base.show_method_candidates(buf, Base.MethodError(nomethodsfunc,(1, 1, 1))) @test isempty(String(take!(buf))) # matches the implicit constructor -> convert method @@ -1161,3 +1165,6 @@ end # issue #47559" @test_throws("MethodError: no method matching invoke Returns(::Any, ::Val{N}) where N", invoke(Returns, Tuple{Any,Val{N}} where N, 1, Val(1))) + +f33793(x::Float32, y::Float32) = 1 +@test_throws "\nClosest candidates are:\n f33793(!Matched::Float32, !Matched::Float32)\n" f33793(Float64(0.0), Float64(0.0)) diff --git a/test/filesystem.jl b/test/filesystem.jl index c9bab69c586b3..566ca08ec910e 100644 --- a/test/filesystem.jl +++ b/test/filesystem.jl @@ -44,5 +44,5 @@ end @testset "Base.Filesystem docstrings" begin undoc = Docs.undocumented_names(Base.Filesystem) @test_broken isempty(undoc) - @test undoc == [:File, :Filesystem, :JL_O_APPEND, :JL_O_ASYNC, :JL_O_CLOEXEC, :JL_O_CREAT, :JL_O_DIRECT, :JL_O_DIRECTORY, :JL_O_DSYNC, :JL_O_EXCL, :JL_O_FSYNC, :JL_O_LARGEFILE, :JL_O_NDELAY, :JL_O_NOATIME, :JL_O_NOCTTY, :JL_O_NOFOLLOW, :JL_O_NONBLOCK, :JL_O_PATH, :JL_O_RANDOM, :JL_O_RDONLY, :JL_O_RDWR, :JL_O_RSYNC, :JL_O_SEQUENTIAL, :JL_O_SHORT_LIVED, :JL_O_SYNC, :JL_O_TEMPORARY, :JL_O_TMPFILE, :JL_O_TRUNC, :JL_O_WRONLY, :S_IRGRP, :S_IROTH, :S_IRUSR, :S_IRWXG, :S_IRWXO, :S_IRWXU, :S_IWGRP, :S_IWOTH, :S_IWUSR, :S_IXGRP, :S_IXOTH, :S_IXUSR, :cptree, :futime, :rename, :sendfile, :unlink] + @test undoc == [:File, :Filesystem, :cptree, :futime, :rename, :sendfile, :unlink] end diff --git a/test/misc.jl b/test/misc.jl index e0961c538921a..d2a8fabd119c5 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1287,6 +1287,51 @@ end end end +module KwdefWithEsc + const Int1 = Int + const val1 = 42 + macro define_struct() + quote + @kwdef struct $(esc(:Struct)) + a + b = val1 + c::Int1 + d::Int1 = val1 + + $(esc(quote + e + f = val2 + g::Int2 + h::Int2 = val2 + end)) + + $(esc(:(i = val2))) + $(esc(:(j::Int2))) + $(esc(:(k::Int2 = val2))) + + l::$(esc(:Int2)) + m::$(esc(:Int2)) = val1 + + n = $(esc(:val2)) + o::Int1 = $(esc(:val2)) + + $(esc(:p)) + $(esc(:q)) = val1 + $(esc(:s))::Int1 + $(esc(:t))::Int1 = val1 + end + end + end +end + +module KwdefWithEsc_TestModule + using ..KwdefWithEsc + const Int2 = Int + const val2 = 42 + KwdefWithEsc.@define_struct() +end +@test isdefined(KwdefWithEsc_TestModule, :Struct) + @testset "exports of modules" begin for (_, mod) in Base.loaded_modules mod === Main && continue # Main exports everything diff --git a/test/namedtuple.jl b/test/namedtuple.jl index 0d9c6f420ced1..9c16d24b0c575 100644 --- a/test/namedtuple.jl +++ b/test/namedtuple.jl @@ -94,6 +94,9 @@ end conv_res = @test_throws MethodError convert(NamedTuple{(:a,),Tuple{I}} where I<:AbstractString, (;a=1)) @test conv_res.value.f === convert && conv_res.value.args === (AbstractString, 1) + + conv6 = convert(NamedTuple{(:a,),Tuple{NamedTuple{(:b,), Tuple{Int}}}}, ((1,),)) + @test conv6 === (a = (b = 1,),) end @test NamedTuple{(:a,:c)}((b=1,z=2,c=3,aa=4,a=5)) === (a=5, c=3) diff --git a/test/precompile.jl b/test/precompile.jl index 1eed9b1418a63..90086ff7b7385 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -469,6 +469,7 @@ precompile_test_harness(false) do dir # and their dependencies Dict(Base.PkgId(Base.root_module(Base, :SHA)) => Base.module_build_id(Base.root_module(Base, :SHA))), Dict(Base.PkgId(Base.root_module(Base, :Markdown)) => Base.module_build_id(Base.root_module(Base, :Markdown))), + Dict(Base.PkgId(Base.root_module(Base, :StyledStrings)) => Base.module_build_id(Base.root_module(Base, :StyledStrings))), # and their dependencies Dict(Base.PkgId(Base.root_module(Base, :Base64)) => Base.module_build_id(Base.root_module(Base, :Base64))), ) @@ -1693,13 +1694,14 @@ precompile_test_harness("Issue #46558") do load_path @test (@eval $Foo.foo(1)) == 2 end +# TODO: Decide if we need to keep supporting this. precompile_test_harness("issue #46296") do load_path write(joinpath(load_path, "CodeInstancePrecompile.jl"), """ module CodeInstancePrecompile mi = first(Base.specializations(first(methods(identity)))) - ci = Core.CodeInstance(mi, Any, Any, nothing, nothing, zero(Int32), typemin(UInt), + ci = Core.CodeInstance(mi, nothing, Any, Any, nothing, nothing, zero(Int32), typemin(UInt), typemax(UInt), zero(UInt32), zero(UInt32), nothing, 0x00) __init__() = @assert ci isa Core.CodeInstance @@ -1710,6 +1712,69 @@ precompile_test_harness("issue #46296") do load_path (@eval (using CodeInstancePrecompile)) end +precompile_test_harness("AbstractInterpreter caching") do load_path + write(joinpath(load_path, "SimpleModule.jl"), + """ + module SimpleModule + basic_callee(x) = x + basic_caller(x) = basic_callee(x) + end + """) + write(joinpath(load_path, "CustomAbstractInterpreterCaching.jl"), + """ + module CustomAbstractInterpreterCaching + import SimpleModule: basic_caller, basic_callee + module Custom + const CC = Core.Compiler + + struct InvalidationTesterToken end + + struct InvalidationTester <: CC.AbstractInterpreter + world::UInt + inf_params::CC.InferenceParams + opt_params::CC.OptimizationParams + inf_cache::Vector{CC.InferenceResult} + function InvalidationTester(; + world::UInt = Base.get_world_counter(), + inf_params::CC.InferenceParams = CC.InferenceParams(), + opt_params::CC.OptimizationParams = CC.OptimizationParams(), + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(world, inf_params, opt_params, inf_cache) + end + end + + CC.InferenceParams(interp::InvalidationTester) = interp.inf_params + CC.OptimizationParams(interp::InvalidationTester) = interp.opt_params + CC.get_inference_world(interp::InvalidationTester) = interp.world + CC.get_inference_cache(interp::InvalidationTester) = interp.inf_cache + CC.cache_owner(::InvalidationTester) = InvalidationTesterToken() + end + + Base.return_types((Float64,)) do x + basic_caller(x) + end + Base.return_types((Float64,); interp=Custom.InvalidationTester()) do x + basic_caller(x) + end + end + """) + Base.compilecache(Base.PkgId("CustomAbstractInterpreterCaching")) + (@eval begin + using CustomAbstractInterpreterCaching + let m = only(methods(CustomAbstractInterpreterCaching.basic_callee)) + mi = only(Base.specializations(m)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === CustomAbstractInterpreterCaching.Custom.InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + end + end) +end + precompile_test_harness("Recursive types") do load_path write(joinpath(load_path, "RecursiveTypeDef.jl"), """ diff --git a/test/ranges.jl b/test/ranges.jl index 8933ab0047c86..549078bab45fe 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -3,6 +3,9 @@ using Base.Checked: checked_length using InteractiveUtils: code_llvm +isdefined(Main, :OffsetArrays) || @eval Main include("testhelpers/OffsetArrays.jl") +using .Main.OffsetArrays + @testset "range construction" begin @test_throws ArgumentError range(start=1, step=1, stop=2, length=10) @test_throws ArgumentError range(start=1, step=1, stop=10, length=11) @@ -232,9 +235,23 @@ end @test cmp_sn2(Tw(xw/yw), astuple(x/y)..., slopbits) end end + @testset "high precision of varying types" begin + x = Float32(π) + y = Float64(Base.MathConstants.γ) + @test Base.mul12(x, y)[1] ≈ Base.mul12(Float64(π), y)[1] rtol=1e-6 + @test Base.mul12(x, y)[2] ≈ Base.mul12(Float64(π), y)[2] atol=1e-15 + @test Base.div12(x, y)[1] ≈ Base.div12(Float64(π), y)[1] rtol=1e-6 + @test Base.div12(x, y)[2] ≈ Base.div12(Float64(π), y)[2] atol=1e-15 + xtp = Base.TwicePrecision{Float32}(π) + ytp = Base.TwicePrecision{Float64}(Base.MathConstants.γ) + @test Float32(xtp + ytp) ≈ Float32(Base.TwicePrecision{Float64}(π) + ytp) + end x1 = Base.TwicePrecision{Float64}(1) x0 = Base.TwicePrecision{Float64}(0) + @test eltype(x1) == Float64 + @test eltype(typeof(x1)) == Float64 + @test zero(typeof(x1)) === x0 xinf = Base.TwicePrecision{Float64}(Inf) @test Float64(x1+x0) == 1 @test Float64(x1+0) == 1 @@ -545,6 +562,13 @@ end @test sort(1:10, rev=true) == 10:-1:1 @test sort(-3:3, by=abs) == [0,-1,1,-2,2,-3,3] @test partialsort(1:10, 4) == 4 + + @testset "offset ranges" begin + x = OffsetArrays.IdOffsetRange(values=4:13, indices=4:13) + @test sort(x) === x === sort!(x) + @test sortperm(x) == eachindex(x) + @test issorted(x[sortperm(x)]) + end end @testset "in" begin @test 0 in UInt(0):100:typemax(UInt) diff --git a/test/reflection.jl b/test/reflection.jl index f81605622a806..c4e941fa7bb1a 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1006,8 +1006,9 @@ end @testset "lookup mi" begin @test 1+1 == 2 - mi1 = @ccall jl_method_lookup_by_tt(Tuple{typeof(+), Int, Int}::Any, Base.get_world_counter()::Csize_t, nothing::Any)::Ref{Core.MethodInstance} + mi1 = Base.method_instance(+, (Int, Int)) @test mi1.def.name == :+ + # Note `jl_method_lookup` doesn't returns CNull if not found mi2 = @ccall jl_method_lookup(Any[+, 1, 1]::Ptr{Any}, 3::Csize_t, Base.get_world_counter()::Csize_t)::Ref{Core.MethodInstance} @test mi1 == mi2 end diff --git a/test/sets.jl b/test/sets.jl index 2e7e19c5c1cdf..c490e66793cb4 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -899,8 +899,8 @@ end b = [2, 3, 1, 3] ua = unique(a) ub = unique(b) - for TA in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), - TB in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), + for TA in (Tuple, identity, Set, BitSet, IdSet{Int}), + TB in (Tuple, identity, Set, BitSet, IdSet{Int}), uA = false:true, uB = false:true A = TA(uA ? ua : a) @@ -921,7 +921,7 @@ end @test !issetequal(B, A) @test !issetequal(B)(A) @test !issetequal(A)(B) - for T = (Tuple, identity, Set, BitSet, Base.IdSet{Int}) + for T = (Tuple, identity, Set, BitSet, IdSet{Int}) @test issetequal(A, T(A)) @test issetequal(B, T(B)) end @@ -982,7 +982,7 @@ end c = [3] d = [4] e = [5] - A = Base.IdSet{Vector{Int}}([a, b, c, d]) + A = IdSet{Vector{Int}}([a, b, c, d]) @test !isempty(A) B = copy(A) @test A ⊆ B diff --git a/test/spawn.jl b/test/spawn.jl index 4ae4b3368bef6..831eac493d4aa 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -23,7 +23,7 @@ havebb = false function _tryonce_download_from_cache(desired_url::AbstractString) cache_url = "https://cache.julialang.org/$(desired_url)" - cache_output_filename = joinpath(mktempdir(), "myfile") + cache_output_filename = joinpath(mktempdir(), "busybox") cache_response = Downloads.request( cache_url; output = cache_output_filename, @@ -1032,3 +1032,10 @@ let effects = Base.infer_effects(x -> `a $x`, (Any,)) @test !Core.Compiler.is_noub(effects) @test !Core.Compiler.is_consistent(effects) end + +# Test that Cmd accepts various AbstractStrings +@testset "AbstractStrings" begin + args = split("-l /tmp") + @assert eltype(args) != String + @test Cmd(["ls", args...]) == `ls -l /tmp` +end diff --git a/test/subarray.jl b/test/subarray.jl index a556260c4717e..0606ed00e6a7a 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -1031,3 +1031,28 @@ end av2 = view(av, 2:2, 2:2, 1:1) @test parentindices(av2) === (view(inds[1], 2:2, 2:2, 1:1),) end + +@testset "isassigned" begin + a = Vector{BigFloat}(undef, 5) + a[2] = 0 + for v in (view(a, 2:3), # FastContiguousSubArray + view(a, 2:2:4), # FastSubArray + view(a, [2:2:4;]), # SlowSubArray + ) + @test !isassigned(v, 0) # out-of-bounds + @test isassigned(v, 1) # inbounds and assigned + @test !isassigned(v, 2) # inbounds but not assigned + @test !isassigned(v, 4) # out-of-bounds + end + + a = Array{BigFloat}(undef,3,3,3) + a[1,1,1] = 0 + for v in (view(a, :, 1:3, 1), # FastContiguousSubArray + view(a, 1, :, 1:2), # FastSubArray + ) + @test !isassigned(v, 0, 0) # out-of-bounds + @test isassigned(v, 1, 1) # inbounds and assigned + @test !isassigned(v, 1, 2) # inbounds but not assigned + @test !isassigned(v, 3, 3) # out-of-bounds + end +end diff --git a/test/testdefs.jl b/test/testdefs.jl index e8f62858d1cbb..b96c95045f2bd 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -82,9 +82,11 @@ function runtests(name, path, isolate=true; seed=nothing) rss = Sys.maxrss() #res_and_time_data[1] is the testset ts = res_and_time_data[1] - passes, fails, errors, broken, c_passes, c_fails, c_errors, c_broken = Test.get_test_counts(ts) + tc = Test.get_test_counts(ts) # simplify our stored data to just contain the counts - res_and_time_data = (TestSetException(passes+c_passes, fails+c_fails, errors+c_errors, broken+c_broken, Test.filter_errors(ts)), + res_and_time_data = (TestSetException(tc.passes+tc.cumulative_passes, tc.fails+tc.cumulative_fails, + tc.errors+tc.cumulative_errors, tc.broken+tc.cumulative_broken, + Test.filter_errors(ts)), res_and_time_data[2], res_and_time_data[3], res_and_time_data[4],