diff --git a/.mailmap b/.mailmap index 1bf5d878c8c54..bcb3c842a7605 100644 --- a/.mailmap +++ b/.mailmap @@ -199,8 +199,9 @@ M. Prentis Peter Peter -Rafael Fourquet -Rafael Fourquet +Rafael Fourquet +Rafael Fourquet +Rafael Fourquet Dan Wlasiuk Dan Wlasiuk diff --git a/.travis.yml b/.travis.yml index e93f329e7dcbf..fc3961a3e02d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,7 +61,7 @@ before_install: ln -s /usr/bin/g++-5 $HOME/bin/x86_64-linux-gnu-g++; gcc --version; BAR="bar -i 30"; - BUILDOPTS="-j5 VERBOSE=1 FORCE_ASSERTIONS=1 LLVM_ASSERTIONS=1 USECCACHE=1 USE_BINARYBUILDER_LIBUV=0 USE_BINARYBUILDER_UNWIND=0 USE_BINARYBUILDER_LLVM=0"; + BUILDOPTS="-j5 VERBOSE=1 FORCE_ASSERTIONS=1 LLVM_ASSERTIONS=1 USECCACHE=1 USE_BINARYBUILDER_LIBUV=0 USE_BINARYBUILDER_LIBUNWIND=0 USE_BINARYBUILDER_LLVM=0"; echo "override ARCH=$ARCH" >> Make.user; sudo sh -c "echo 0 > /proc/sys/net/ipv6/conf/lo/disable_ipv6"; export JULIA_CPU_THREADS=4; diff --git a/Make.inc b/Make.inc index 3084d12c54b32..79a38b0ca9642 100644 --- a/Make.inc +++ b/Make.inc @@ -980,7 +980,7 @@ else endif # BinaryBuilder options. We default to "on" for all the projects listed in BB_PROJECTS, -# but only if contrib/normalize_triplet.py works for our requested triplet +# but only if contrib/normalize_triplet.py works for our requested triplet. ifeq ($(shell python $(JULIAHOME)/contrib/normalize_triplet.py $(or $(XC_HOST),$(XC_HOST),$(BUILD_MACHINE)) >/dev/null 2>/dev/null; echo $$?),0) USE_BINARYBUILDER ?= 1 else @@ -991,8 +991,23 @@ USE_BINARYBUILDER ?= 0 endif # This is the set of projects that BinaryBuilder dependencies are hooked up for. -BB_PROJECTS := OPENBLAS LLVM SUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 MPFR CURL LIBGIT2 PCRE LIBUV UNWIND DSFMT OBJCONV -$(foreach proj,$(BB_PROJECTS),$(if $(USE_BINARYBUILDER_$(proj)),,$(eval USE_BINARYBUILDER_$(proj) ?= $(USE_BINARYBUILDER)))) +BB_PROJECTS := OPENBLAS LLVM SUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV +define SET_BB_DEFAULT +# First, check to see if BB is disabled on a global setting +ifeq ($$(USE_BINARYBUILDER),0) +USE_BINARYBUILDER_$(1) ?= 0 +else +# If it's not, check to see if it's disabled by a USE_SYSTEM_xxx flag +ifeq ($$(USE_SYSTEM_$(1)),1) +USE_BINARYBUILDER_$(1) ?= 0 +else +USE_BINARYBUILDER_$(1) ?= 1 +endif +endif +endef +$(foreach proj,$(BB_PROJECTS),$(eval $(call SET_BB_DEFAULT,$(proj)))) + + # Use the Assertions build BINARYBUILDER_LLVM_ASSERTS ?= 0 @@ -1227,6 +1242,19 @@ LDFLAGS += -cxxlib-nostd -static-intel endif endif +# Some special restrictions on BB usage: +ifeq ($(USE_SYSTEM_BLAS),1) +# Since the names don't line up (`BLAS` vs. `OPENBLAS`), manually gate: +USE_BINARYBUILDER_OPENBLAS := 0 +# Disable BB SuiteSparse if we're using system BLAS +USE_BINARYBUILDER_SUITESPARSE := 0 +endif + +ifeq ($(USE_SYSTEM_LIBM),1) +# If we're using system libm, disable BB OpenLibm +USE_BINARYBUILDER_OPENLIBM := 0 +endif + # Make tricks define dir_target @@ -1319,6 +1347,7 @@ JULCOLOR:="\033[34;1m" GOAL=$(subst ','\'',$(subst $(abspath $(JULIAHOME))/,,$(abspath $@))) PRINT_CC = printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$(GOAL)$(ENDCOLOR); $(1) +PRINT_ANALYZE = printf ' %b %b\n' $(CCCOLOR)ANALYZE$(ENDCOLOR) $(SRCCOLOR)$(GOAL)$(ENDCOLOR); $(1) PRINT_LINK = printf ' %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$(GOAL)$(ENDCOLOR); $(1) PRINT_PERL = printf ' %b %b\n' $(PERLCOLOR)PERL$(ENDCOLOR) $(BINCOLOR)$(GOAL)$(ENDCOLOR); $(1) PRINT_FLISP = printf ' %b %b\n' $(FLISPCOLOR)FLISP$(ENDCOLOR) $(BINCOLOR)$(GOAL)$(ENDCOLOR); $(1) @@ -1327,6 +1356,7 @@ PRINT_JULIA = printf ' %b %b\n' $(JULIACOLOR)JULIA$(ENDCOLOR) $(BINCOLOR)$(GO else QUIET_MAKE = PRINT_CC = echo '$(subst ','\'',$(1))'; $(1) +PRINT_ANALYZE = echo '$(subst ','\'',$(1))'; $(1) PRINT_LINK = echo '$(subst ','\'',$(1))'; $(1) PRINT_PERL = echo '$(subst ','\'',$(1))'; $(1) PRINT_FLISP = echo '$(subst ','\'',$(1))'; $(1) diff --git a/Makefile b/Makefile index 55c778e5259c6..a37f2c95500dc 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ all: debug release # sort is used to remove potential duplicates DIRS := $(sort $(build_bindir) $(build_depsbindir) $(build_libdir) $(build_private_libdir) $(build_libexecdir) $(build_includedir) $(build_includedir)/julia $(build_sysconfdir)/julia $(build_datarootdir)/julia $(build_datarootdir)/julia/stdlib $(build_man1dir)) ifneq ($(BUILDROOT),$(JULIAHOME)) -BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src ui doc deps stdlib test test/embedding test/llvmpasses) +BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src src/clangsa ui doc deps stdlib test test/embedding test/llvmpasses) BUILDDIRMAKE := $(addsuffix /Makefile,$(BUILDDIRS)) $(BUILDROOT)/sysimage.mk DIRS := $(DIRS) $(BUILDDIRS) $(BUILDDIRMAKE): | $(BUILDDIRS) diff --git a/NEWS.md b/NEWS.md index 8cef63e5808ab..613bb1c74349d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -21,6 +21,8 @@ Build system changes New library functions --------------------- +* `findfirst`, `findlast`, `findnext` and `findprev` now accept a character as first argument + to search for that character in a string passed as the second argument ([#31664]). * New `findall(pattern, string)` method where `pattern` is a string or regex ([#31834]). Standard library changes @@ -34,6 +36,11 @@ Standard library changes functions that operate on the array(s) as a whole (and are not explicitly broadcasted across their elements). Previously, the functions `+`, `-`, `*`, `/`, `conj`, `real` and `imag` returned the unwrapped element when operating over zero-dimensional arrays ([#32122]). +* `IPAddr` subtypes now behave like scalars when used in broadcasting ([#32133]). + +#### Libdl + +* `dlopen()` can now be invoked in `do`-block syntax, similar to `open()`. #### LinearAlgebra @@ -47,6 +54,12 @@ Standard library changes #### Dates +* Fixed `repr` such that it displays `Time` as it would be entered in Julia ([#32103]). + +#### Sockets + +* `getipaddrs` returns IP addresses in the order provided by libuv ([#32260]). +* `getipaddr` prefers to return the first `IPv4` interface address provided by libuv ([#32260]). #### Statistics diff --git a/base/asyncevent.jl b/base/asyncevent.jl index 1ada6a94cfbc8..2299993bd2ea0 100644 --- a/base/asyncevent.jl +++ b/base/asyncevent.jl @@ -87,21 +87,11 @@ mutable struct Timer interval ≥ 0 || throw(ArgumentError("timer cannot have negative repeat interval of $interval seconds")) this = new(Libc.malloc(_sizeof_uv_timer), ThreadSynchronizer(), true) - err = ccall(:uv_timer_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), eventloop(), this) - if err != 0 - #TODO: this codepath is currently not tested - Libc.free(this.handle) - this.handle = C_NULL - throw(_UVError("uv_timer_init", err)) - end - - associate_julia_struct(this.handle, this) - finalizer(uvfinalize, this) - - ccall(:jl_uv_update_time, Cvoid, (Ptr{Cvoid},), eventloop()) - ccall(:jl_uv_timer_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, UInt64, UInt64), - this, uv_jl_timercb::Ptr{Cvoid}, + ccall(:jl_uv_update_timer_start, Cvoid, + (Ptr{Cvoid}, Any, Ptr{Cvoid}, Ptr{Cvoid}, UInt64, UInt64), + eventloop(), this, this.handle, uv_jl_timercb::Ptr{Cvoid}, UInt64(round(timeout * 1000)) + 1, UInt64(round(interval * 1000))) + finalizer(uvfinalize, this) return this end end @@ -124,7 +114,6 @@ isopen(t::Union{Timer, AsyncCondition}) = t.isopen function close(t::Union{Timer, AsyncCondition}) if t.handle != C_NULL && isopen(t) t.isopen = false - isa(t, Timer) && ccall(:jl_uv_timer_stop, Cint, (Ptr{Cvoid},), t) ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), t) end nothing diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 12290f4dfc780..93851e5ba37bc 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -61,8 +61,8 @@ function typeinf(frame::InferenceState) for caller in frames caller.min_valid = min_valid caller.max_valid = max_valid - caller.src.min_world = min_valid % Int - caller.src.max_world = max_valid % Int + caller.src.min_world = min_valid + caller.src.max_world = max_valid if cached cache_result(caller.result, min_valid, max_valid) end diff --git a/base/complex.jl b/base/complex.jl index 878c4201d3a2e..aaa424648d438 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -259,7 +259,11 @@ julia> conj(1 + 3im) conj(z::Complex) = Complex(real(z),-imag(z)) abs(z::Complex) = hypot(real(z), imag(z)) abs2(z::Complex) = real(z)*real(z) + imag(z)*imag(z) -inv(z::Complex) = conj(z)/abs2(z) +function inv(z::Complex) + c, d = reim(z) + (isinf(c) | isinf(d)) && return complex(copysign(zero(c), c), flipsign(-zero(d), d)) + complex(c, -d)/(c * c + d * d) +end inv(z::Complex{<:Integer}) = inv(float(z)) +(z::Complex) = Complex(+real(z), +imag(z)) @@ -346,7 +350,7 @@ function /(a::Complex{T}, b::Complex{T}) where T<:Real end inv(z::Complex{<:Union{Float16,Float32}}) = - oftype(z, conj(widen(z))/abs2(widen(z))) + oftype(z, inv(widen(z))) /(z::Complex{T}, w::Complex{T}) where {T<:Union{Float16,Float32}} = oftype(z, widen(z)*inv(widen(w))) @@ -430,6 +434,7 @@ end function inv(w::ComplexF64) c, d = reim(w) + (isinf(c) | isinf(d)) && return complex(copysign(0.0, c), flipsign(-0.0, d)) half = 0.5 two = 2.0 cd = max(abs(c), abs(d)) diff --git a/base/errorshow.jl b/base/errorshow.jl index 149ae703d03f0..7b1b7f8947152 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -33,11 +33,7 @@ function showerror(io::IO, ex::BoundsError) print(io, "BoundsError") if isdefined(ex, :a) print(io, ": attempt to access ") - if isa(ex.a, AbstractArray) - summary(io, ex.a) - else - show(io, MIME"text/plain"(), ex.a) - end + summary(io, ex.a) if isdefined(ex, :i) !isa(ex.a, AbstractArray) && print(io, "\n ") print(io, " at index [") diff --git a/base/gmp.jl b/base/gmp.jl index dbc46f75a3617..c7596c23fe73c 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -52,9 +52,8 @@ mutable struct BigInt <: Signed size::Cint d::Ptr{Limb} - function BigInt() - b = new(zero(Cint), zero(Cint), C_NULL) - MPZ.init!(b) + function BigInt(; nbits::Integer=0) + b = MPZ.init2!(new(), nbits) finalizer(cglobal((:__gmpz_clear, :libgmp)), b) return b end @@ -130,7 +129,7 @@ module MPZ # - a method modifying its input has a "!" appendend to its name, according to Julia's conventions # - some convenient methods are added (in addition to the pure MPZ ones), e.g. `add(a, b) = add!(BigInt(), a, b)` # and `add!(x, a) = add!(x, x, a)`. -using .Base.GMP: BigInt, Limb +using .Base.GMP: BigInt, Limb, BITS_PER_LIMB const mpz_t = Ref{BigInt} const bitcnt_t = Culong @@ -145,11 +144,14 @@ realloc2(a) = realloc2!(BigInt(), a) sizeinbase(a::BigInt, b) = Int(ccall((:__gmpz_sizeinbase, :libgmp), Csize_t, (mpz_t, Cint), a, b)) -for op in (:add, :sub, :mul, :fdiv_q, :tdiv_q, :fdiv_r, :tdiv_r, :gcd, :lcm, :and, :ior, :xor) +for (op, nbits) in (:add => :(BITS_PER_LIMB*(1 + max(abs(a.size), abs(b.size)))), + :sub => :(BITS_PER_LIMB*(1 + max(abs(a.size), abs(b.size)))), + :mul => 0, :fdiv_q => 0, :tdiv_q => 0, :fdiv_r => 0, :tdiv_r => 0, + :gcd => 0, :lcm => 0, :and => 0, :ior => 0, :xor => 0) op! = Symbol(op, :!) @eval begin $op!(x::BigInt, a::BigInt, b::BigInt) = (ccall($(gmpz(op)), Cvoid, (mpz_t, mpz_t, mpz_t), x, a, b); x) - $op(a::BigInt, b::BigInt) = $op!(BigInt(), a, b) + $op(a::BigInt, b::BigInt) = $op!(BigInt(nbits=$nbits), a, b) $op!(x::BigInt, b::BigInt) = $op!(x, x, b) end end diff --git a/base/initdefs.jl b/base/initdefs.jl index 479f3bd4479d2..be6cf5a409aae 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -217,7 +217,7 @@ function init_load_path() HOME_PROJECT[] = project === nothing ? nothing : project == "" ? nothing : - project == "@." ? current_project() : abspath(project) + project == "@." ? current_project() : abspath(expanduser(project)) append!(empty!(LOAD_PATH), paths) end diff --git a/base/math.jl b/base/math.jl index 0a9fac443c602..f990f8b6282df 100644 --- a/base/math.jl +++ b/base/math.jl @@ -521,7 +521,7 @@ sqrt(x::Real) = sqrt(float(x)) """ hypot(x, y) -Compute the hypotenuse ``\\sqrt{x^2+y^2}`` avoiding overflow and underflow. +Compute the hypotenuse ``\\sqrt{|x|^2+|y|^2}`` avoiding overflow and underflow. # Examples ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" @@ -535,6 +535,9 @@ ERROR: DomainError with -2.914184810805068e18: sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)). Stacktrace: [...] + +julia> hypot(3, 4im) +5.0 ``` """ hypot(x::Number, y::Number) = hypot(promote(x, y)...) @@ -566,7 +569,16 @@ end """ hypot(x...) -Compute the hypotenuse ``\\sqrt{\\sum x_i^2}`` avoiding overflow and underflow. +Compute the hypotenuse ``\\sqrt{\\sum |x_i|^2}`` avoiding overflow and underflow. + +# Examples +```jldoctest +julia> hypot(-5.7) +5.7 + +julia> hypot(3, 4im, 12.0) +13.0 +``` """ hypot(x::Number...) = sqrt(sum(abs2(y) for y in x)) diff --git a/base/meta.jl b/base/meta.jl index fb4513b639251..7a85594249301 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -20,7 +20,7 @@ See also the manual section about [QuoteNode](@ref man-quote-node). # Examples ```jldoctest -julia> eval(quot(:x)) +julia> eval(Meta.quot(:x)) :x julia> dump(Meta.quot(:x)) diff --git a/base/operators.jl b/base/operators.jl index e151f203b7f41..bf22c6ff553d9 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -160,11 +160,11 @@ isless(x::AbstractFloat, y::Real ) = (!isnan(x) & (isnan(y) | signless(x function ==(T::Type, S::Type) @_pure_meta - T<:S && S<:T + return ccall(:jl_types_equal, Cint, (Any, Any), T, S) != 0 end function !=(T::Type, S::Type) @_pure_meta - !(T == S) + return !(T == S) end ==(T::TypeVar, S::Type) = false ==(T::Type, S::TypeVar) = false diff --git a/base/process.jl b/base/process.jl index cc492a6dedb2d..721838229024a 100644 --- a/base/process.jl +++ b/base/process.jl @@ -628,32 +628,46 @@ function eachline(cmd::AbstractCmd; keep::Bool=false) return EachLine(out, keep=keep, ondone=ondone)::EachLine end -function open(cmds::AbstractCmd, mode::AbstractString, other::Redirectable=devnull) +""" + open(command, mode::AbstractString, stdio=devnull) + +Run `command` asynchronously. Like `open(command, stdio; read, write)` except specifying +the read and write flags via a mode string instead of keyword arguments. +Possible mode strings are: + +| Mode | Description | Keywords | +|:-----|:------------|:---------------------------------| +| `r` | read | none | +| `w` | write | `write = true` | +| `r+` | read, write | `read = true, write = true` | +| `w+` | read, write | `read = true, write = true` | +""" +function open(cmds::AbstractCmd, mode::AbstractString, stdio::Redirectable=devnull) if mode == "r+" || mode == "w+" - return open(cmds, other, read = true, write = true) + return open(cmds, stdio, read = true, write = true) elseif mode == "r" - return open(cmds, other) + return open(cmds, stdio) elseif mode == "w" - return open(cmds, other, write = true) + return open(cmds, stdio, write = true) else - throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\"")) + throw(ArgumentError("mode must be \"r\", \"w\", \"r+\", or \"w+\", not $(repr(mode))")) end end # return a Process object to read-to/write-from the pipeline """ - open(command, other=devnull; write::Bool = false, read::Bool = !write) + open(command, stdio=devnull; write::Bool = false, read::Bool = !write) Start running `command` asynchronously, and return a `process::IO` object. If `read` is -true, then reads from the process come from the process's standard output and `other` optionally +true, then reads from the process come from the process's standard output and `stdio` optionally specifies the process's standard input stream. If `write` is true, then writes go to -the process's standard input and `other` optionally specifies the process's standard output +the process's standard input and `stdio` optionally specifies the process's standard output stream. The process's standard error stream is connected to the current global `stderr`. """ -function open(cmds::AbstractCmd, other::Redirectable=devnull; write::Bool=false, read::Bool=!write) +function open(cmds::AbstractCmd, stdio::Redirectable=devnull; write::Bool=false, read::Bool=!write) if read && write - other === devnull || throw(ArgumentError("no stream can be specified for `other` in read-write mode")) + stdio === devnull || throw(ArgumentError("no stream can be specified for `stdio` in read-write mode")) in = PipeEndpoint() out = PipeEndpoint() processes = _spawn(cmds, Any[in, out, stderr]) @@ -661,14 +675,14 @@ function open(cmds::AbstractCmd, other::Redirectable=devnull; write::Bool=false, processes.out = out elseif read out = PipeEndpoint() - processes = _spawn(cmds, Any[other, out, stderr]) + processes = _spawn(cmds, Any[stdio, out, stderr]) processes.out = out elseif write in = PipeEndpoint() - processes = _spawn(cmds, Any[in, other, stderr]) + processes = _spawn(cmds, Any[in, stdio, stderr]) processes.in = in else - other === devnull || throw(ArgumentError("no stream can be specified for `other` in no-access mode")) + stdio === devnull || throw(ArgumentError("no stream can be specified for `stdio` in no-access mode")) processes = _spawn(cmds, Any[devnull, devnull, stderr]) end return processes diff --git a/base/reducedim.jl b/base/reducedim.jl index 44a72a9a25b9d..996729be8bc4c 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -162,7 +162,7 @@ reducedim_init(f, op::typeof(|), A::AbstractArray, region) = reducedim_initarray # specialize to make initialization more efficient for common cases let - BitIntFloat = Union{BitInteger, Math.IEEEFloat} + BitIntFloat = Union{BitInteger, IEEEFloat} T = Union{ [AbstractArray{t} for t in uniontypes(BitIntFloat)]..., [AbstractArray{Complex{t}} for t in uniontypes(BitIntFloat)]...} diff --git a/base/reflection.jl b/base/reflection.jl index 084a885fb0cae..77f67e68852b1 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1329,10 +1329,10 @@ has_bottom_parameter(t::Union) = has_bottom_parameter(t.a) & has_bottom_paramete has_bottom_parameter(t::TypeVar) = t.ub == Bottom || has_bottom_parameter(t.ub) has_bottom_parameter(::Any) = false -min_world(m::Core.CodeInstance) = reinterpret(UInt, m.min_world) -max_world(m::Core.CodeInstance) = reinterpret(UInt, m.max_world) -min_world(m::Core.CodeInfo) = reinterpret(UInt, m.min_world) -max_world(m::Core.CodeInfo) = reinterpret(UInt, m.max_world) +min_world(m::Core.CodeInstance) = m.min_world +max_world(m::Core.CodeInstance) = m.max_world +min_world(m::Core.CodeInfo) = m.min_world +max_world(m::Core.CodeInfo) = m.max_world get_world_counter() = ccall(:jl_get_world_counter, UInt, ()) diff --git a/base/show.jl b/base/show.jl index 15c90023dc017..037c66ae95f50 100644 --- a/base/show.jl +++ b/base/show.jl @@ -381,9 +381,14 @@ end function show_function(io::IO, f::Function, compact::Bool) ft = typeof(f) mt = ft.name.mt - if isdefined(mt, :module) && isdefined(mt.module, mt.name) && + if mt === Symbol.name.mt + # uses shared method table + show_default(io, f) + elseif compact + print(io, mt.name) + elseif isdefined(mt, :module) && isdefined(mt.module, mt.name) && getfield(mt.module, mt.name) === f - if compact || is_exported_from_stdlib(mt.name, mt.module) || mt.module === Main + if is_exported_from_stdlib(mt.name, mt.module) || mt.module === Main print(io, mt.name) else print(io, mt.module, ".", mt.name) @@ -701,7 +706,7 @@ function show_delim_array(io::IO, itr, op, delim, cl, delim_one, i1=1, n=typemax y = iterate(itr) first = true i0 = i1-1 - while i1 > 2 && y !== nothing + while i1 > 1 && y !== nothing y = iterate(itr, y[2]) i1 -= 1 end @@ -1849,6 +1854,7 @@ function summary(x) summary(io, x) String(take!(io)) end +summary(io::IO, t::Tuple) = print(io, t) ## `summary` for AbstractArrays # sizes such as 0-dimensional, 4-dimensional, 2x3 diff --git a/base/special/ldexp_exp.jl b/base/special/ldexp_exp.jl index 6d7500107af85..3ea0f39373ece 100644 --- a/base/special/ldexp_exp.jl +++ b/base/special/ldexp_exp.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + # This code is a Julia translation of the C code from Openlibm (http://www.openlibm.org/) # with the following license: diff --git a/base/stream.jl b/base/stream.jl index 49e5f0834cfe7..900439718708c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -81,7 +81,7 @@ const StatusOpen = 3 # handle is usable const StatusActive = 4 # handle is listening for read/write/connect events const StatusClosing = 5 # handle is closing / being closed const StatusClosed = 6 # handle is closed -const StatusEOF = 7 # handle is a TTY that has seen an EOF event +const StatusEOF = 7 # handle is a TTY that has seen an EOF event (pretends to be closed until reseteof is called) const StatusPaused = 8 # handle is Active, but not consuming events, and will transition to Open if it receives an event function uv_status_string(x) s = x.status @@ -315,7 +315,7 @@ function isopen(x::Union{LibuvStream, LibuvServer}) if x.status == StatusUninit || x.status == StatusInit throw(ArgumentError("$x is not initialized")) end - x.status != StatusClosed && x.status != StatusEOF + return x.status != StatusClosed && x.status != StatusEOF end function check_open(x::Union{LibuvStream, LibuvServer}) @@ -407,7 +407,7 @@ function close(stream::Union{LibuvStream, LibuvServer}) end lock(stream.closenotify) try - if isopen(stream) + if isopen(stream) || stream.status == StatusEOF should_wait = uv_handle_data(stream) != C_NULL if stream.status != StatusClosing ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle) @@ -1191,7 +1191,7 @@ end function eof(s::BufferStream) wait_readnb(s, 1) - return !isopen(s) && bytesavailable(s)<=0 + return !isopen(s) && bytesavailable(s) <= 0 end # If buffer_writes is called, it will delay notifying waiters till a flush is called. diff --git a/base/strings/basic.jl b/base/strings/basic.jl index d7c9cb279f7e4..98709d6fb470e 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -384,12 +384,12 @@ julia> thisind("α", 3) 3 julia> thisind("α", 4) -ERROR: BoundsError: attempt to access "α" +ERROR: BoundsError: attempt to access String at index [4] [...] julia> thisind("α", -1) -ERROR: BoundsError: attempt to access "α" +ERROR: BoundsError: attempt to access String at index [-1] [...] ``` @@ -440,7 +440,7 @@ julia> prevind("α", 1) 0 julia> prevind("α", 0) -ERROR: BoundsError: attempt to access "α" +ERROR: BoundsError: attempt to access String at index [0] [...] @@ -500,7 +500,7 @@ julia> nextind("α", 1) 3 julia> nextind("α", 3) -ERROR: BoundsError: attempt to access "α" +ERROR: BoundsError: attempt to access String at index [3] [...] diff --git a/base/strings/search.jl b/base/strings/search.jl index 8b62b34bc2d07..6e3ff7e2133a0 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -104,6 +104,25 @@ julia> findfirst("Julia", "JuliaLang") findfirst(pattern::AbstractString, string::AbstractString) = findnext(pattern, string, firstindex(string)) +""" + findfirst(ch::AbstractChar, string::AbstractString) + +Find the first occurrence of character `ch` in `string`. + +!!! compat "Julia 1.3" + This method requires at least Julia 1.3. + +# Examples +```jldoctest +julia> findfirst('a', "happy") +2 + +julia> findfirst('z', "happy") === nothing +true +``` +""" +findfirst(ch::AbstractChar, string::AbstractString) = findfirst(==(ch), string) + # AbstractString implementation of the generic findnext interface function findnext(testf::Function, s::AbstractString, i::Integer) z = ncodeunits(s) + 1 @@ -255,6 +274,26 @@ julia> findnext("Lang", "JuliaLang", 2) """ findnext(t::AbstractString, s::AbstractString, i::Integer) = _search(s, t, i) +""" + findnext(ch::AbstractChar, string::AbstractString, start::Integer) + +Find the next occurrence of character `ch` in `string` starting at position `start`. + +!!! compat "Julia 1.3" + This method requires at least Julia 1.3. + +# Examples +```jldoctest +julia> findnext(`z`, "Hello to the world", 1) === nothing +true + +julia> findnext(`o`, "Hello to the world", 6) +8 +``` +""" +findnext(ch::AbstractChar, string::AbstractString, ind::Integer) = + findnext(==(ch), string, ind) + """ findlast(pattern::AbstractString, string::AbstractString) @@ -273,6 +312,25 @@ julia> findfirst("Julia", "JuliaLang") findlast(pattern::AbstractString, string::AbstractString) = findprev(pattern, string, lastindex(string)) +""" + findlast(ch::AbstractChar, string::AbstractString) + +Find the last occurrence of character `ch` in `string`. + +!!! compat "Julia 1.3" + This method requires at least Julia 1.3. + +# Examples +```jldoctest +julia> findlast('p', "happy") +4 + +julia> findlast('z', "happy") === nothing +true +``` +""" +findlast(ch::AbstractChar, string::AbstractString) = findlast(==(ch), string) + # AbstractString implementation of the generic findprev interface function findprev(testf::Function, s::AbstractString, i::Integer) if i < 1 @@ -428,6 +486,26 @@ julia> findprev("Julia", "JuliaLang", 6) """ findprev(t::AbstractString, s::AbstractString, i::Integer) = _rsearch(s, t, i) +""" + findprev(ch::AbstractChar, string::AbstractString, start::Integer) + +Find the previous occurrence of character `ch` in `string` starting at position `start`. + +!!! compat "Julia 1.3" + This method requires at least Julia 1.3. + +# Examples +```jldoctest +julia> findprev('z', "Hello to the world", 18) === nothing +true + +julia> findprev('o', "Hello to the world", 18) +15 +``` +""" +findprev(ch::AbstractChar, string::AbstractString, ind::Integer) = + findprev(==(ch), string, ind) + """ occursin(needle::Union{AbstractString,Regex,AbstractChar}, haystack::AbstractString) diff --git a/base/strings/util.jl b/base/strings/util.jl index d624c612cd29c..b97a76a24b3e8 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -243,7 +243,7 @@ function lpad( n::Integer, p::Union{AbstractChar,AbstractString}=' ', ) :: String - m = n - length(s) + m = signed(n) - length(s) m ≤ 0 && return string(s) l = length(p) q, r = divrem(m, l) @@ -270,7 +270,7 @@ function rpad( n::Integer, p::Union{AbstractChar,AbstractString}=' ', ) :: String - m = n - length(s) + m = signed(n) - length(s) m ≤ 0 && return string(s) l = length(p) q, r = divrem(m, l) diff --git a/base/task.jl b/base/task.jl index 5f75b97249127..af8c2c5c302b4 100644 --- a/base/task.jl +++ b/base/task.jl @@ -184,6 +184,7 @@ end # NOTE: you can only wait for scheduled tasks function wait(t::Task) + t === current_task() && error("deadlock detected: cannot wait on current task") if !istaskdone(t) lock(t.donenotify) try @@ -197,6 +198,7 @@ function wait(t::Task) if istaskfailed(t) throw(t.exception) end + nothing end fetch(@nospecialize x) = x @@ -410,14 +412,25 @@ end function enq_work(t::Task) (t.state == :runnable && t.queue === nothing) || error("schedule: Task not runnable") tid = Threads.threadid(t) - if t.sticky || tid != 0 + # Note there are three reasons a Task might be put into a sticky queue + # even if t.sticky == false: + # 1. The Task's stack is currently being used by the scheduler for a certain thread. + # 2. There is only 1 thread. + # 3. The multiq is full (can be fixed by making it growable). + if t.sticky || tid != 0 || Threads.nthreads() == 1 if tid == 0 tid = Threads.threadid() + ccall(:jl_set_task_tid, Cvoid, (Any, Cint), t, tid-1) end push!(Workqueues[tid], t) else tid = 0 - ccall(:jl_enqueue_task, Cvoid, (Any,), t) + if ccall(:jl_enqueue_task, Cint, (Any,), t) != 0 + # if multiq is full, give to a random thread (TODO fix) + tid = mod(time_ns() % Int, Threads.nthreads()) + 1 + ccall(:jl_set_task_tid, Cvoid, (Any, Cint), t, tid-1) + push!(Workqueues[tid], t) + end end ccall(:jl_wakeup_thread, Cvoid, (Int16,), (tid - 1) % Int16) return t @@ -560,29 +573,11 @@ function trypoptask(W::StickyWorkqueue) end @noinline function poptaskref(W::StickyWorkqueue) - gettask = () -> trypoptask(W) - task = ccall(:jl_task_get_next, Any, (Any,), gettask) - ## Below is a reference implementation for `jl_task_get_next`, which currently lives in C - #local task - #while true - # task = trypoptask(W) - # task === nothing || break - # if !Threads.in_threaded_loop[] && Threads.threadid() == 1 - # if process_events(true) == 0 - # task = trypoptask(W) - # task === nothing || break - # # if there are no active handles and no runnable tasks, just - # # wait for signals. - # pause() - # end - # else - # if Threads.threadid() == 1 - # process_events(false) - # end - # ccall(:jl_gc_safepoint, Cvoid, ()) - # ccall(:jl_cpu_pause, Cvoid, ()) - # end - #end + task = trypoptask(W) + if !(task isa Task) + gettask = () -> trypoptask(W) + task = ccall(:jl_task_get_next, Any, (Any,), gettask)::Task + end return Ref(task) end diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index 2c1b0503518ed..c5e889078b286 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -138,6 +138,7 @@ function add_license_line!(unprocessed::Vector, src::AbstractString, new_license isempty(lines) && (push!(unprocessed, path); continue) isempty(old_license) || check_lines!(path, lines, old_license, prefix, true) check_lines!(path, lines, new_license, prefix, false) + isempty(lines) && continue # file consisting of just license header # check shebang file linenum = license_linenum(lines[1]) if !isempty(strip(lines[linenum])) diff --git a/contrib/delete-all-rpaths.sh b/contrib/delete-all-rpaths.sh index a37a4b8e10a77..22e18e0a44c93 100755 --- a/contrib/delete-all-rpaths.sh +++ b/contrib/delete-all-rpaths.sh @@ -1,4 +1,5 @@ #!/bin/sh +# This file is a part of Julia. License is MIT: https://julialang.org/license [ "$(uname)" = Darwin ] || { echo "Requires Darwin." 2>&1; exit 1; } diff --git a/contrib/mac/framework/Julia.h b/contrib/mac/framework/Julia.h index ae1a6995d0cf9..7e70489ef2e6b 100644 --- a/contrib/mac/framework/Julia.h +++ b/contrib/mac/framework/Julia.h @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + #include #include #include diff --git a/contrib/refresh_bb_tarballs.sh b/contrib/refresh_bb_tarballs.sh index cd7bb3f2be865..d732b04362461 100755 --- a/contrib/refresh_bb_tarballs.sh +++ b/contrib/refresh_bb_tarballs.sh @@ -1,4 +1,5 @@ #!/bin/sh +# This file is a part of Julia. License is MIT: https://julialang.org/license # Invoke this with no arguments to refresh all tarballs, or with a project name to refresh only that project. # diff --git a/contrib/windows/build-installer.nsi b/contrib/windows/build-installer.nsi index 5de6d91cfa91e..f4ad3443d8500 100644 --- a/contrib/windows/build-installer.nsi +++ b/contrib/windows/build-installer.nsi @@ -52,7 +52,7 @@ FunctionEnd Function createDesktopLink ${NSD_GetState} $Checkbox $0 ${If} $0 <> 0 - CreateShortCut "$DESKTOP\julia.lnk" "$INSTDIR\bin\julia.exe" + CreateShortCut "$DESKTOP\julia.lnk" "$INSTDIR\bin\julia.exe" "" "$INSTDIR\bin\julia.exe" 0 ${EndIf} FunctionEnd @@ -107,7 +107,7 @@ Section "Dummy Section" SecDummy SetOutPath $INSTDIR File /a /r "julia-${Commit}\*" WriteUninstaller "$INSTDIR\uninstall.exe" - CreateShortcut "$INSTDIR\julia.lnk" "$INSTDIR\bin\julia.exe" + CreateShortcut "$INSTDIR\julia.lnk" "$INSTDIR\bin\julia.exe" "" "$INSTDIR\bin\julia.exe" 0 # ARP entries WriteRegStr HKCU "${ARP}" \ diff --git a/contrib/windows/icon-readme.md b/contrib/windows/icon-readme.md new file mode 100755 index 0000000000000..08c446dc74259 --- /dev/null +++ b/contrib/windows/icon-readme.md @@ -0,0 +1,23 @@ + +Generate the logo +```julia +using Luxor +Drawing(325, 325, joinpath(pwd(), "julia-dots.svg")) +origin() +translate(0, 25) +juliacircles(100) +finish() +``` + +Create the ico file +```sh +#!/bin/bash + +for size in 16 20 24 32 40 48 64 128 256; do + rsvg-convert -w $size -h $size julia-dots.svg -o $size.png +done + +convert 256.png 128.png 64.png 48.png 40.png 32.png 24.png 20.png 16.png julia.ico + +rm 256.png 128.png 64.png 48.png 40.png 32.png 24.png 20.png 16.png +``` diff --git a/contrib/windows/julia.ico b/contrib/windows/julia.ico old mode 100644 new mode 100755 index 5466a7f3586e9..5f340eacbd179 Binary files a/contrib/windows/julia.ico and b/contrib/windows/julia.ico differ diff --git a/contrib/windows/julia.rc b/contrib/windows/julia.rc index 3c76c59ab1f41..fb2b179401cd6 100644 --- a/contrib/windows/julia.rc +++ b/contrib/windows/julia.rc @@ -18,7 +18,7 @@ BEGIN VALUE "FileDescription", "Julia Programming Language" VALUE "FileVersion", JLVER_STR VALUE "InternalName", "julia" - VALUE "LegalCopyright", "MIT Licensed" + VALUE "LegalCopyright", "(c) 2009-2019 Julia Language" VALUE "OriginalFilename", "julia.exe" VALUE "ProductName", "Julia" VALUE "ProductVersion", JLVER_STR diff --git a/deps/Versions.make b/deps/Versions.make index e26d64b2df2c4..5eeeef27efee2 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -5,7 +5,7 @@ PCRE_BB_REL = 0 DSFMT_VER = 2.2.3 DSFMT_BB_REL = 0 OPENBLAS_VER = 0.3.5 -OPENBLAS_BB_REL = 1 +OPENBLAS_BB_REL = 2 LAPACK_VER = 3.5.0 SUITESPARSE_VER = 5.4.0 SUITESPARSE_BB_REL = 2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/md5 deleted file mode 100644 index 3dcb93d281005..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e7bdee6a6978f2cbc900fa32ef492854 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/sha512 deleted file mode 100644 index 4c2c48e5de56d..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -286f84e14600617e46eb3d3bfd14dee24845385f9c3a764ce4a925d1a2d31defad9adcbba83956952c940c1e90dbf06e9d995d83176858392290e9f3bf93dc01 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/md5 deleted file mode 100644 index 1376bb06eae0e..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -263e0d085b723b7ec4d01838841ff3ee diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/sha512 deleted file mode 100644 index 0ef72f2aeb5b1..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -977bc0754829ecceb9b4d8c4fa00bf972b1d42d5975d005472400f7429feddebfb1fe5930fabf9378ad552d3d771d31b984588816062da1a48df373b7b1228bc diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/md5 deleted file mode 100644 index 1da34a4a8ef79..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -1a5602d74db720b49ae6cc81f0dace96 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/sha512 deleted file mode 100644 index 3d7d2e271a207..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-gnu-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -a42d3ee2904152538890266cabc30f4487a2b1e4c98a4dfa831d7bd42ffc0904a4cc587d9cee06cc07a46be727f7943914359f10f686ecd0e26f926ac04523dc diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/md5 deleted file mode 100644 index d5429a91195a5..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b68c8f87ba525da59d3ce41dadefc1ce diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/sha512 deleted file mode 100644 index efff55d0029c1..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -3eeb0d6bab2a2084bd6cef5a7cdcbb7ba9fd810add7f41ae25d227b3a374a200c0273278171525f3e67f72fce2485c50665e8b506b86604cd1966ae576e196c2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/md5 deleted file mode 100644 index 6d096f6cf6769..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ea0c8c2a9db5b9be0ab1e092b76afca2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/sha512 deleted file mode 100644 index a0a4321f57ebb..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -c142559c03571421eb72909bd305894c87c15a781d2b40d15d9996b69c7f027331b498fc2374a3477a7c8a8405afda5e8da4f0d2b9c205b730bf83065f5f6abc diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/md5 deleted file mode 100644 index 9d35c51ffcfc1..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b8710afad990120835ba26b41a9960c9 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/sha512 deleted file mode 100644 index 5e0c168ab41a1..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.aarch64-linux-musl-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -7b522018b4c02ed21c623d612199f1230c00cbe583ef8f3f6a64b685f38f77c2559d5043684b07d98eed0ef53649da8efcd0d93ec355f332d2e36b494b678659 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/md5 deleted file mode 100644 index 6703857508076..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -8c5723161d0d8cd8fdb19ba7d78a3e2e diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/sha512 deleted file mode 100644 index fefca48417060..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -fdec45cd4d25279496e08acec67bb21a19baced49ad35a9141651ea3a97f07159cd69651ca3c734ffa94cbf341b22ff0a13d1d615365fb7caecfb847ef5717e9 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/md5 deleted file mode 100644 index b4865f7a786cb..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -dbf33f89fe63b67f0b4e1eb6c479d7f9 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/sha512 deleted file mode 100644 index 06dc50f9059b4..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -13a5496d516ac6925b76918ffcc564ddaf4da1d7074e803a127d69e233d8c536650618b6775683eeafe0476c0fbb3ff85f5a76caedaa36c389ff4584901b7e89 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/md5 deleted file mode 100644 index 8e70545e496dd..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -217840cf4bcc2874c1b19aceab3ebe64 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/sha512 deleted file mode 100644 index a1fd61b15559d..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-gnueabihf-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -9fd866d18ce6632b1e6a65122535289e5dcd260cfb430900acaa7413ee51c8344ca8dc7958a0f5e68d14f5526de06b1c23d84276ee2eae54ad08c052ac18ddee diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/md5 deleted file mode 100644 index 8a8a117fb8c36..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b6319b5b891eddcdff8d32f094565fe1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/sha512 deleted file mode 100644 index d90dc5e610926..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -6fd68da70076596ab16a493cd574afdf1740f0734659d0ff8cf1a3c293191c524b99f80453a2a368a362b987d3681cbcdfec8db3edfc668666652ef25623c64d diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/md5 deleted file mode 100644 index 3c34ba323c9ee..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -329ae468ca4c70d3e1a9b420caa8d4e9 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/sha512 deleted file mode 100644 index 3a7e19009e3c9..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -448a474f4015e249ec4ff0c199a5ed7ed16e5ed836b3f51cf6da23de3a20a8c06ecbf9ce1f81c0d10cf6e2441dddf88feff23dc14dd3281f1a2670f58b40bf61 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/md5 deleted file mode 100644 index ba13c7d83ca0c..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -9d42d4a77d2de9fbeb9347b742178417 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/sha512 deleted file mode 100644 index 58472df703951..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.arm-linux-musleabihf-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -41c0ca1c37526d362676bdeedf7fcf0b962b3a151b954c8b576a51594b9447c7e8d5bb5cf559afcc8b475041d8230bada00f24851c9b41259c841461e11979a3 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/md5 deleted file mode 100644 index 5f91d1818513d..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -a3e70794241cace350cf9a2e62924970 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/sha512 deleted file mode 100644 index a132a6c8f8a12..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -382db2c8a8f5d4846f5c0a97e4ff6788a1cd64986afaf7cb04ccb8a30cf5d95077000ac23cef1be434eca9243990f5b57cccb6c85f673af8c3d6bdbcabc0bf11 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/md5 deleted file mode 100644 index 9f80027ff0c75..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -632440a7aa473e1578514e9661b54e57 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/sha512 deleted file mode 100644 index 351b08eb50074..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -a70e3fa94d82ef7627da5316a143d7e7fe13e343d87bc911fa176784ebaf7765edf86071e23ebee9a90af45656986bf460d5e6ae625b556d6e98651ef5466c41 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/md5 deleted file mode 100644 index 551aabe2b0f39..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -1024754603b9cfe4efaafaae570667c2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/sha512 deleted file mode 100644 index 6027dc7b2e09c..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-gnu-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8017c6f87694ce9a3d7260dda9ba9da224cf6741afa8f7a9b3381ce3a174a690f1dcf6ae149d2efc12e245a80e2060c0137fdd06934466a9950ab460b83f9de8 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/md5 deleted file mode 100644 index 70f131a4caa4f..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -264e7a054dfa8943771e3601bad54afa diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/sha512 deleted file mode 100644 index dcef40ec1339b..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -685db01127485d6bdfe9b09519df8009919b5822e72a2f90fdaa7cf459cbbc7a3b088f659a7e8bf5581fb246ca72ed29cb619a7d59ee5e887acc8fcde5b32e28 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/md5 deleted file mode 100644 index 7c77230842749..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -d10c66984952c61b6d5592b4f868441a diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/sha512 deleted file mode 100644 index ef3313f723da2..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -09b2f7ef9b0714aa200e0629bbd4479d86359df2ae5e302401dbc0b8cb0b48cc9581b0c59c55b60bb8eb8fcc708823dc6095f5dba10a7e9441855480df9a84d3 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/md5 deleted file mode 100644 index 0729c8a1d29b4..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -44401fc99bfce6426732585b5f1041b0 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/sha512 deleted file mode 100644 index f43da5902dd9a..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-linux-musl-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -2ace1bcc1dbfdf970f7d918ef063ff1fc28c7544cd12dc29537323340f3fc7795860521ca9ab0846743bb1c9a86f840589136e3000e73a938d5c5793b3841adb diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/md5 deleted file mode 100644 index 0534748118b0c..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ba247273bd873c3ef197fd28bad26fa7 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/sha512 deleted file mode 100644 index 38ab40ba0bc5b..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -898cd3e950947fe2c6a63f3c01190940f50bc9a7853280b40b3ff1f4e97edeb8b1a8e2863091ab59833d04f33c7901ef6eec689bac0e18eb8816788b435e9f43 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/md5 deleted file mode 100644 index e9683849b9b4d..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -12181786711e96ce3065c93303b4d6a8 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/sha512 deleted file mode 100644 index d0029630b3dc7..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f039bad2310e7f0cc77d38a52b8ed097449d321c1cc875505b1228ddcb251837ff83b96baf08d64b1d50abe0d3c3d707f5b047c942fe3b0e1f2b6bb42baf63d4 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/md5 deleted file mode 100644 index 18543539e7f63..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -82973454e669cf7e7dfe3a3fea7855e8 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/sha512 deleted file mode 100644 index dbdf3ef0b2c95..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.i686-w64-mingw32-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -6c16dda2d864f9005e9683559a2dabaf4219bf623d00eefac1654e864228acc69bac4e8ca392fa66289ae4b85394c3222e62ad770a7eb23fd7e0f60a4a336afd diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/md5 deleted file mode 100644 index 28d3c5881cbbb..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -8286ff436acbc1e913e5b91ac092dfab diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 deleted file mode 100644 index f0f28f5b841d3..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -9fb6e92b5f55797d1052cd3cde2fbc505fc4bdc71ede36596afae58d9f1c9d590b25874b4737556edb26aeb4ba496c68cc42b1d3fc9458fb236bebcfeecd8eae diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/md5 deleted file mode 100644 index f334d7c073688..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -29f180d127ffb6e8cdbda84a56583d72 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 deleted file mode 100644 index cf7f03bacaf8d..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -b88923466b35e99144888d1bc0eaf7ad071c03dea5c131a0cbf2f656dcaeac6e01d828429f7d06cb7ca371e6e94b8df34780be5cd8abed1232ce87d0b285336b diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/md5 deleted file mode 100644 index fa861da38739e..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -f596396c143bd3f5127961cc4879f466 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 deleted file mode 100644 index 3e6ecfdf61238..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f9fa067716f8a7de879b0883300b58bd35d84a247309a9118516653f763b309a55f18e727bbebd22b1fc337fecfc6e89e88285fea140d28a5297ef748a56dc37 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/md5 deleted file mode 100644 index 0130c514deb0f..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e95a1dccfda94470b7f9a73ea69f54be diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/sha512 deleted file mode 100644 index 2f2741f491e21..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f9a85ab5c2682506f386807a385ce987b8174280cea6574973168ef9b894c70eaa44069bc012716369aff6a385a3d6b702fce072eb809577b42182ceb9425d96 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/md5 deleted file mode 100644 index 584f50652f99b..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -9321019c8df77a9906744372f68dd7fa diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/sha512 deleted file mode 100644 index e05032022a631..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -5beb2cb810f5eb15d88ef11c535ea2cec111db3c37463593f7d0599bab3b667ead48022a5fbfaf13bbd3e5a5eaf27f7e9650a6b93530fb8d901237e5a4becc04 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/md5 deleted file mode 100644 index b275077d454f9..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -02d9695224b412599f488e6609659733 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/sha512 deleted file mode 100644 index a2fd81bc90b3f..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-apple-darwin14-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f0ca29ca9317a667c00f4d4abc54c76913f00a014435cb38d89cbcf7a1acae6243b952b03ba83d6364c7ccb259bc73f3c523ab967143f23023ceee429f8db423 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/md5 deleted file mode 100644 index fdd9ae5ae0776..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -7335302c32b7312f7fe1baa968843fb0 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/sha512 deleted file mode 100644 index 14fa834bbbe16..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -0ea8b27800b55bccea50ed12375ef6d6f3f170c8f43f8c1a5069daff84708fe6147a543e6f6691696511767fdae8cc11c21b7e345ae8d66a97b3bfc9d8d08e53 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/md5 deleted file mode 100644 index ba0b25c9b40a7..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -822f466ae7d0b6679d03dbd8585a013f diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/sha512 deleted file mode 100644 index 56c5af73a2a85..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -b63078c9adb4e04f91d79c73e77b74c8c5048fbac6e7333411c5c4a4766ff6dd04d0be307d4745d14a6e4fa9e68f3fe6301f7d2a01cb9a4d14d1a3fbb7be27af diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/md5 deleted file mode 100644 index 453a4df5d2756..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -ccc32c921492a71458e94b819e909222 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/sha512 deleted file mode 100644 index ed20426118390..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-gnu-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -17c18fb0c68458c73481136cf3fca5f5402a5c969e4824cbae665fea0db97d586abb55b0b11150032d510e6d99b96525220fa523be6310619b28f92ef5e8ade3 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/md5 deleted file mode 100644 index 04bc7bab4eebf..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -bf3264c9d17103f9f24207d4caa99f0d diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/sha512 deleted file mode 100644 index 40d5d5a6e584b..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f97f2f0fd2770cda7ad7bb9054e541f1f7cd02e9c0fe1343129d4cc5ff36d5f918bc4a2a15be9e569de9f51e83d88b01e0935743963d47cc583063c01b42bd6b diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/md5 deleted file mode 100644 index af78ac87734bf..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -6285a6281c0297582d9bac5b9b703276 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/sha512 deleted file mode 100644 index 06a601c305ffe..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e700ddf90c9130282f5021ea31cb45750ec6221017b0cf04fe0adc8872b2faf408a389e6285aad8f40ae77f149295ef591dfdfbbaf82506180bfbab7274f7668 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/md5 deleted file mode 100644 index 55e398465b526..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -3422a5e0e9f5fb513b9f622c54aa1738 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/sha512 deleted file mode 100644 index f4335aec93426..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-linux-musl-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -04499062d8b408ca67d0821857c59767af5bf5b63d34bec12b688c76f6dd189ea5259f90f55541266262d450d31cdf6ed4b6094290214f8e50db5e9d578d7a89 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 deleted file mode 100644 index d209413ec52c1..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -2f9d2d3ba3dd8795a0a5f7d51585dac7 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 deleted file mode 100644 index a98c643ed80be..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -3e519a123f0cacd20e3a02986c6f6700c1848ceda51ae6f57385e4314b21301fb8dbe7c053ba839d1b9a876ac444fbb72795220bbc39f2fefbf6ea362b5e1d3f diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 deleted file mode 100644 index 079ee8ac73976..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -074216cd3e1b25584e169261a5438c24 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 deleted file mode 100644 index 253191bd51694..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -d1f9f98caef821f5951c24ac01d9c83cb965d380ee687e3fa74edf5dee38b33c70ee6edcb8e4f22ecaa0be9d4dc75dcaba53a408a160c8459aa88c2d6d1cb741 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 deleted file mode 100644 index c1a0e60dd764a..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -c9ce1f9cc6715b39a3526946da1531a6 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 deleted file mode 100644 index 479749a59fe6c..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -c420e4df91c022a7ae9e33c59234e918c42f67776971ac37a12638cb833a7e959fc1955a37c032fca863e3674d7f9ca915657db66d77d21a292734484f228909 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/md5 deleted file mode 100644 index 190c1291443ab..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -1dd1480e20562a5a3e68a6c8f05fa78f diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/sha512 deleted file mode 100644 index 5e03e5ab35db8..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8ed77800a2677d6f4beb7a5f74277da94c6f48b478881b79bf78f64f231d7f264aaffdb9d5960e3e6ca1884537091f9744cac1313b8e6605808d87390ca52801 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/md5 deleted file mode 100644 index f16cfc31487ad..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -e8224db17d67300482aad424f15a0394 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/sha512 deleted file mode 100644 index 9845b1a62702a..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -b8206363591dc15d8bd7e1d604f8b50b29955b378e378b7002ca5d0a9404a1c2f452f57a492f4ec620d98b8a297df5f4e4a5683fcfaa263589951fb9f034ddb7 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/md5 deleted file mode 100644 index 092558bf2dc91..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -a89adc41795565b3724322e7b7c720f1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/sha512 deleted file mode 100644 index 023b1c7c54afc..0000000000000 --- a/deps/checksums/OpenBLAS.v0.3.5-1.x86_64-w64-mingw32-gcc8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -3886c78bba70184a433f4e2660522f42bab85ce2e23b24e8b27a5a26870e96aa780193615c3aa6c45f397747b1f1bd199af70a4dfba27e0a203207e15c2bd142 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..0ff730e27bbd5 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +14d62da838b053ab78c3c84a8df7c429 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..b6d2b6523c322 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +0141f903dbc62ccdcf01d8722ce7b03c74d94c661be796c1a242b0f385f891c15daf015331029b8ed692867d2e7f8303fa3d5c443ee65a9cfb9b78e3663617ab diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..13d91016ca6ea --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +a16f6e2bffd56d76735d64a36852f650 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..a7e5183c80e27 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +cc164665889562b2e86c4387f85175bd20bd665fc0ce2842a28107eea7f67d49f58067c2face4d768fffec7eb6ca17450c9f07b927b897bed4114e43bde0e83a diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..f50a76bcdb99b --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +8d492b89b0b1c09e620647976df19512 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..1c908038d6288 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-gnu-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +ff3de25afefc10577c7860cd3fb9496585b763aad683ee39ccbbb596223910ace4b8411fc1f20a3b5708098cafcfe31b873009cf12777cd9b9c4b8d462122fd6 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..6d5f519ff9b3b --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +9d7a69fe6ed99592087f3b81c6b1c8a1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..90cf64b1c40b0 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +7c2029a0e9f9efc59813f99fd220a7c8796989db47758857da31b8c794d92de167f35992d399301d79641f79f3b2831afe83af1e85ad99fe4153248dbe5badaf diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..e679b3a09153d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +93a1250c75e7cec00a52c091a6fa89cc diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..f5a13bfe372a7 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +1949277d8a762c2f0d8bd37fcc10d97420b82d5a96da2987323ec7d6954b36b7eae52732499e7a054adae1b395158e46eda41daf1e0008c23a02fe4f8059ee3c diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..e73b73e93ab95 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +f8e98218f3a832972531924b770cf8fe diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..28b66a95b06f8 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.aarch64-linux-musl-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +7a4064f5e79dd11cc14d85dc1e37fd923cebaebc92483a1c90e7a73b072d789a87fb3b0c46bfd0668307e4bb32c2c4af3f190eac2da934f37d61d81b980a878b diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..425aa69633ad5 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +636d2d2c14abc9e3b14d1dc546ad8935 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..33056420be53d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +3394f5ee2f35c168e7f6be9c0653dd157e7da49040b9ec94d6f4d6d1ad2736cdc6f10f6626f08548238c3a11b69ffefa159c5495d1fe58855c0c41c2383641fd diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..359a29ce73ba3 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +a336efef9cf11945477b2bb805282810 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..35b378898f5df --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +8c0e558aa047f60a5e695229b0f7585363448dd2b61c0a193bdf00d27fffecd3a9c37a0e423821af7beb909c874074fe7a1d4d4cec623bd964205ee20d2e3b23 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..306b7bd150621 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +28dd6d175a5a6fe86a4d01f9031b76cf diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..0944fab6b0cae --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-gnueabihf-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +986cabd473a353731479036db91f4a462fe6b389ddee35aacb3f66a15df8e1d38956c385d3ef02e399bde70458a3fc6b769466db652f4495abd7d7d2ff0b26b1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..d7a989258cf1e --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +1487ee7fb0ff0e2824be40dfa79badff diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..856c33f5ca046 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +ecd8abcb46bd26e72e6ccda2ef463521629dcf6132dd065079b8da71e7291c0561c801bf7c94a467b6aa2839539ee990ccf4b4ea5160f492fb704b2ffcfe0283 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..8b940c0392ebe --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +c478e1ae81917a27fffbdef01829d79e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..92d6a1791620b --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +22aef28d214c41556fc45ffc3903073bd7f5b44ec6714f4c9d8f50757200c89c3da3e61d96ab587dc353ec4e88b67b8c553c938ecb32261347b1e3c5e8901c0e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..33248b04076f8 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +fb6116f48854a9e183d6c6773e889756 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..debea1328236c --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.arm-linux-musleabihf-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +33edfa3fe05f2e6a246eda391813e8db30ed744789032e499cbfb4e1f9f73c67ce6e439dc7ca4795d8b38b9dab6420979f51ef818511e8601398144ef41f7b2e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..88150070e1dbe --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +15c38ae63c6c70bbcf7e52bff16ec915 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..86c389ba825ae --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +5f2464ad3b56cec0ca343f301460819141dec3217cf15b171da657768571eae77313ce156d56fd5cc76c6d95758597015dc7d04e209c0ffb0dcbeedb99d788e0 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..8f3b533c8a12e --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +ad1c639472af0e6245f8faa5cbf65f57 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..32f1d34614434 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +fe85b545b4e0787fc1b6c1f2948a4db09eafe365c1bf52a5979430f014d23a8713bb7c1ff29264fa02e16736b9407c7aaf56416354dd3c1e2e2ae9b32a00f5d2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..2811baa62830a --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +e25cb820b2eb0d593fb0c875ae2086a1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..813e18b37d218 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-gnu-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +6b5d4f21609f9382d01b4e5c4b7becbf61b50aa3c20f0db6a78736506ad83b0ec7225790f1127d1601bb96ea3318d3704b18e71fd6c1559006147525cb2b3389 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..a25e0ac9cd1ee --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +f2c96e84acbded44c263270367b6cf9f diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..ac7fd7a98cd88 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +3d0d2fac80ec4760c96740e4607086b192d3309ae5bd5b43288655137b5a2a4c78448b283cd50c935f2ad742348bb4770213446c31216972ed1ecf520e34c629 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..517b093841772 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +520372fb05206ac794ff2ac5d23234b4 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..0d6b5fce24b0b --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +92ffc6f2d0fbf6c79dba8f47f44ca7ca11a12e5e6ad43e88d166ba66fcc2b82f62f914ef97ae0831267309ee10c450e191ae0dae51eaf969315e4d3539a8ab57 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..dc6f97866ad07 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +c94c117ba0d7eeeb59df74ffe3733431 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..5ecad97d852d6 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-linux-musl-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +dd11c827b50e5983ed7705dcebfb50249ebbaf661a371d7d0e4f2a8d7401d9999def5bf2491c2461a4dd9b582e714d9350c70298ef388cb32a4d38060a124d88 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..8e0ecf2ae8175 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +fb8b0d915623c27936ea293a2eb2850e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..c051be3ce60c7 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +e3600b813bc7ba5f736899348bf34965f3affead6fadc71555b8bc5e338b06e90a6865a409186604b0fc2d3bdf84ff2e2bf103909cbf7c253dfaff030bbe21fb diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..ca619b7d00e22 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +5b9eabe82ad7de280d739f2d594e8fdc diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..5382db5450f90 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +a532481b46d1d7999618676b5d9eba5fd527d25dca5ac2666d9a2258245d77aef742bb2909ff70543d7a06e5182a99fd6c356f3c59c8aff822f9280cbcaa9cf3 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..5d4006dab8d1d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +d02eacbfb41fe7827331865396707b4b diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..4519f15a3ee78 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.i686-w64-mingw32-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +8c58b822ecfef7192cf36ff391bf34087eecad299c4417da06fdd990c2e71daf8b717770eabeca7e5b67a020b415b9294d44ac897ccb503a1a34943cd563efc5 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..5a551dbca1f2f --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +d1e4a5d1a43e018b67532fa98081206e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..a9738af935abd --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +4357a9f323739c90e6f1e0797be0d8f11e36fbfa9f8a64a6050833244a786166a8391e2c73b1f8130fa83db3d57b58fd48bf2081ba79992b452ffec57d1759a2 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..9e59162e95545 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +2c7930c84ea6cd11c69aa25941087f5c diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..fc2938fabcf47 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +a53d47e1d7ff25258b20394195e374c9f986b2e7edb0dd66c314a5f12a7d28b4518e5ab87fe5f0feaac99c2f2961292b1ce1d5436ea83104bf089d3d08607d93 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..9de6c1c372789 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +1b881141039ba34a7f2c29cef9305062 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..809915d1f951d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.powerpc64le-linux-gnu-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +23ab0524b4403e002bdf280f83fb955de11176fdf7cfaed3f9197993f7c09ad5c1fea14dc6402f1756272aa5e427ffd904418db4de02ea9efbc96de60baf6ee5 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..8e4794e0c1e90 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +eda2584e55dc066e5549048b84b35f05 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..8a2877a50c43a --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +3034f82dc2e06f8f3474ffd6c9692d58186edb59f5f32578de9c21777fbff9def9abe000ca79ae5044be82825f70fab4a9612bbc8df7b0d23dfc77fa28b8f363 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..31a0759103425 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +aa649a88f904208bc3e979af833c9ecd diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..ec02f2fc3d2f7 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +c2d7c3a718106de87777beea3addd658ce06f7f1ed5973c5d17fcf97d958741a19df114f62771afc77a7f2c5e25f8302471772cafa30ee40ef7cdfebcec8477b diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..6b0b046be9baa --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +f3c53bfaabc5027cd95838524ed1ab4e diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..2ac1f2ad3fcab --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-apple-darwin14-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +cd40f1510f66071551ef1d752a64dada6cf82128b725030d8bab7a3cd4b25397b3504763f165498c7231f9c2577c5eddee4cd8b7d8810526221b15d3647ad9cc diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..29cb2f9ae2f68 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +d6452ff5d4fd1cf1d77239d22cf6a1b5 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..75e512ab6563a --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +801c374ee8e8f296e6b84536d2d719bee35e1f0380d947ea119d0a5ebfa7151e358a6228078b516338a4957580de63b3fa083d5be08be2930832c105286cfc49 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..6abba7cc4e1b3 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +124282a831a7d39036a7d3b391d513ec diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..f197900f95b54 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +2ff54c2700e5c1c1dd8bca51cbe8654aa364e5b57f871b6f2701f4a5412ff0ad64ce173fbd9ce7443b6625177e4d645991736966bfbf3fdbdc66bc96fc22d4a5 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..5fdab5acc4caa --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +e0822060b13864f9b0a4416149d89336 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..1364968afd6b5 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-gnu-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +8beca6be0853117eae41b84e984601fd61ef15fd5f6555f1d71375d60a22693cdbfbfac93ec76dd14fa476a6d474b29e8c7efe96a4acb2e90433fe8f325690e1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..0b8f5e81d8145 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +4c3dffaacf774f5838cd2d0f178a4e67 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..65b9bd3cb1598 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +9552f805840c48ed24d65ac858ac13db158cb3579753400c778a3aabac39b20d47a59ab36c86293e5c8b15837e8567e8635792f5ee426be83d26cc6de7bfdcb0 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..e3e217878cb5a --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +d0724e5fd3ffdb759e293724f4b9fa73 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..b0ea95ed0220d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +00b6d2eb995e0c1d973e6d30bd70b92d7d2c5f6d14f9cb1788b16d772e91faef8b095e3ae13729c168088fe005caf2e303d51b9414c243b4e12d8beee7547d3d diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..f7b5eba54c30d --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +36258813bf0e72e1566bd73816bd7b6a diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..f7c773c4f3834 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-linux-musl-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +289903f344b251e122dd76bb0c9e097323e2da1f3995391dc9882098346355767c8d4933e6d1cc98074f3d85bb326aac5785b716dd6198d122e48f2c7fd072d4 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..3f7656c4b0f73 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +457e4f86c5f482d777f41a24eb9642e1 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..7b67ada7f99b8 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +acd3f8b3d42e1fa4c46d82bc9c60042d91985d41b440fd7259b4370b93b19287792d8b14fa7d5a5510945b5201f225aadbbc96ff2edee0ab2c1a254624647247 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..9132655c248fd --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +e57e4cb36402d9acb3d1a89a88e37826 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..ba5d1fb77c43e --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +b372b1d6fbaacb2e4c9baf585e1c6fa85a72ff37e9dc644a27308586edffa5e1c5c7e0be4245fb965e7cd0c6686f284d0112be60d5456e0892b097737756f4cf diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..a9ec847feb1a1 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +61b60d24090c00e38cf8b6af83fd884f diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..47d269f26f87a --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-unknown-freebsd11.1-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +7f6cf4818134353462b08d23ed1adf4360653e58eb848b56bf49aee3c3f591ec91999048f4c1540001a35d15bc5e7795eb09ad8cb549663d56f7613c987b4b7c diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/md5 new file mode 100644 index 0000000000000..cb8220313e440 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/md5 @@ -0,0 +1 @@ +f5c0d5d809ddcf721ae1dc68eaf2c0c4 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/sha512 new file mode 100644 index 0000000000000..7e8c7609b2b04 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc4.tar.gz/sha512 @@ -0,0 +1 @@ +395bdc4a316cf55206966c858bf7320d0f66cdf2f7d6393cc8b3dfd74fc4983a59dc522ac8c18534c6ecde5bf877af57dbc088c83fa6dd8270326f587ceecd6a diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/md5 new file mode 100644 index 0000000000000..a6c82f8f63eb1 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/md5 @@ -0,0 +1 @@ +f40e5bc882602ea1298089a92350bf5a diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/sha512 new file mode 100644 index 0000000000000..72ce16a123776 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc7.tar.gz/sha512 @@ -0,0 +1 @@ +c4bc4b6922a57a9806ad007bd3e0655206717acf722e4e794b709f8b06efd6106d4b4e943276061a7632e7191e307317e3f3a205ff46e8ef3b9c0ea8634fe4f3 diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/md5 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/md5 new file mode 100644 index 0000000000000..09801e687c899 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/md5 @@ -0,0 +1 @@ +617c4587e25dc495446d389fa323c45f diff --git a/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/sha512 b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/sha512 new file mode 100644 index 0000000000000..38bc2a3bf33a6 --- /dev/null +++ b/deps/checksums/OpenBLAS.v0.3.5-2.x86_64-w64-mingw32-gcc8.tar.gz/sha512 @@ -0,0 +1 @@ +63938a2e8ee30807cbeca92589d79d3c438f2aed3eb818735c3ab28e6a6d9835fb7cf250ea7c05fdc8949ba32769f394e6981be46c71b19a389a9b00501962ee diff --git a/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/md5 b/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/md5 deleted file mode 100644 index 5ab28fd10c4ad..0000000000000 --- a/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -f70104dab096fbb2f029fb57ce83f321 diff --git a/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/sha512 b/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/sha512 deleted file mode 100644 index 317972b4a4c6e..0000000000000 --- a/deps/checksums/libuv-2348256acf5759a544e5ca7935f638d2bc091d60.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -c8bf3c736a60feb0c6994aa7cd1b80e1a45bd6096aa66db320ddfc27b59a0797d303338ea75978619173e4f0a680254f3db29c9f6d1b84361030cc11c7729c98 diff --git a/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/md5 b/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/md5 new file mode 100644 index 0000000000000..af1f3c39ccba2 --- /dev/null +++ b/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/md5 @@ -0,0 +1 @@ +029014b8630e06ee92809c0b9220bcad diff --git a/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/sha512 b/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/sha512 new file mode 100644 index 0000000000000..4dfab9dffe1cb --- /dev/null +++ b/deps/checksums/libuv-26dbe5672c33fc885462c509fe2a9b36f35866fd.tar.gz/sha512 @@ -0,0 +1 @@ +23cd3319e1f0ff1bd06908e4c69c98dc67163d49ad4d7f94a6a6aba7c4d292dc5a505086660b00eb0f76afa212e1799e44fd541cc377913129dea484bd9cda3b diff --git a/deps/libuv.version b/deps/libuv.version index ca06025c4bfd6..65d844ff66bef 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -1,2 +1,2 @@ LIBUV_BRANCH=julia-uv2-1.24.0 -LIBUV_SHA1=2348256acf5759a544e5ca7935f638d2bc091d60 +LIBUV_SHA1=26dbe5672c33fc885462c509fe2a9b36f35866fd diff --git a/deps/unwind.mk b/deps/unwind.mk index 055debc07974d..20e3133858450 100644 --- a/deps/unwind.mk +++ b/deps/unwind.mk @@ -1,6 +1,6 @@ ## UNWIND ## -ifneq ($(USE_BINARYBUILDER_UNWIND),1) +ifneq ($(USE_BINARYBUILDER_LIBUNWIND),1) LIBUNWIND_CFLAGS := -U_FORTIFY_SOURCE $(fPIC) LIBUNWIND_CPPFLAGS := @@ -102,7 +102,7 @@ fastcheck-osxunwind: check-osxunwind check-osxunwind: compile-osxunwind install-osxunwind: $(build_prefix)/manifest/osxunwind -else # USE_BINARYBUILDER_UNWIND +else # USE_BINARYBUILDER_LIBUNWIND UNWIND_BB_URL_BASE := https://github.com/JuliaPackaging/Yggdrasil/releases/download/LibUnwind-v$(UNWIND_VER)-$(UNWIND_BB_REL) UNWIND_BB_NAME := LibUnwind.v$(UNWIND_VER) diff --git a/doc/Manifest.toml b/doc/Manifest.toml index 08534fa4b968e..16f331529d58e 100644 --- a/doc/Manifest.toml +++ b/doc/Manifest.toml @@ -18,10 +18,10 @@ uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" version = "0.7.0" [[Documenter]] -deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "Pkg", "REPL", "Random", "Test", "Unicode"] -git-tree-sha1 = "04d40966cddd2ea5d227e7130484b57ac4718596" +deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Unicode"] +git-tree-sha1 = "38509269fc99a9bc450fdb9e17e805021f3e5b1b" uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.22.1" +version = "0.22.4" [[DocumenterLaTeX]] deps = ["Documenter", "Test"] diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 54c069a630392..2104d96cbf4a0 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -178,7 +178,7 @@ Julia function. The arguments to [`@cfunction`](@ref) are: !!! note Currently, only the platform-default C calling convention is supported. This means that `@cfunction`-generated pointers cannot be used in calls where WINAPI expects `stdcall` - function on 32-bit windows, but can be used on WIN64 (where `stdcall` is unified with the + function on 32-bit Windows, but can be used on WIN64 (where `stdcall` is unified with the C calling convention). A classic example is the standard C library `qsort` function, declared as: diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 77d1e966c6d01..5a2cd50358cbc 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -819,8 +819,8 @@ some ideas that might help to understand Julia's definition. therefore its length is `1`. * Zero-dimensional arrays don't natively have any dimensions into which you index -- they’re just `A[]`. We can apply the same "trailing one" rule for them - as for all other array dimensionalities, so you can indeed index them as - `A[1]`, `A[1,1]`, etc. + as for all other array dimensionalities, so you can indeed index them as `A[1]`, `A[1,1]`, etc; see + [Omitted and extra indices](@ref). It is also important to understand the differences to ordinary scalars. Scalars are not mutable containers (even though they are iterable and define things diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 1010baa050c65..e3b5935618ca4 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -202,14 +202,13 @@ Using an index less than 1 or greater than `end` raises an error: ```jldoctest helloworldstring julia> str[0] -ERROR: BoundsError: attempt to access "Hello, world.\n" +ERROR: BoundsError: attempt to access String at index [0] [...] julia> str[end+1] -ERROR: BoundsError: attempt to access "Hello, world.\n" +ERROR: BoundsError: attempt to access String at index [15] -Stacktrace: [...] ``` diff --git a/src/Makefile b/src/Makefile index f8d60738bd5f4..e2365b68f170b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -57,9 +57,9 @@ LLVMLINK := ifeq ($(JULIACODEGEN),LLVM) SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-muladd \ - llvm-late-gc-lowering llvm-lower-handlers llvm-gc-invariant-verifier \ - llvm-propagate-addrspaces llvm-multiversioning llvm-alloc-opt cgmemmgr \ - llvm-api + llvm-final-gc-lowering llvm-pass-helpers llvm-late-gc-lowering \ + llvm-lower-handlers llvm-gc-invariant-verifier llvm-propagate-addrspaces \ + llvm-multiversioning llvm-alloc-opt cgmemmgr llvm-api FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --includedir) LLVM_LIBS := all ifeq ($(USE_POLLY),1) @@ -213,6 +213,9 @@ $(BUILDDIR)/disasm.o $(BUILDDIR)/disasm.dbg.obj: $(SRCDIR)/debuginfo.h $(SRCDIR) $(BUILDDIR)/jitlayers.o $(BUILDDIR)/jitlayers.dbg.obj: $(SRCDIR)/jitlayers.h $(BUILDDIR)/builtins.o $(BUILDDIR)/builtins.dbg.obj: $(SRCDIR)/table.c $(BUILDDIR)/staticdata.o $(BUILDDIR)/staticdata.dbg.obj: $(SRCDIR)/processor.h +$(BUILDDIR)/llvm-final-gc-lowering.o $(BUILDDIR)/llvm-final-gc-lowering.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h +$(BUILDDIR)/llvm-late-gc-lowering.o $(BUILDDIR)/llvm-late-gc-lowering.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h +$(BUILDDIR)/llvm-pass-helpers.o $(BUILDDIR)/llvm-pass-helpers.dbg.obj: $(SRCDIR)/llvm-pass-helpers.h $(BUILDDIR)/gc.o $(BUILDDIR)/gc.dbg.obj: $(SRCDIR)/gc.h $(BUILDDIR)/gc-debug.o $(BUILDDIR)/gc-debug.dbg.obj: $(SRCDIR)/gc.h $(BUILDDIR)/gc-pages.o $(BUILDDIR)/gc-pages.dbg.obj: $(SRCDIR)/gc.h @@ -323,13 +326,34 @@ clean-support: cleanall: clean clean-flisp clean-support -analyzegc: +$(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT): $(SRCDIR)/clangsa/GCChecker.cpp + @$(call PRINT_CC, $(CXX) -g -shared -o $@ -DCLANG_PLUGIN -I$(build_includedir) $(shell $(LLVM_CONFIG_HOST) --cxxflags) $(CPPFLAGS) $(CFLAGS) $< $(shell $(LLVM_CONFIG_HOST) --ldflags) $(LDFLAGS) -L$(build_libdir) -lclangAnalysis -lclangStaticAnalyzerCore -lclangASTMatchers -lclangAST -lclangLex -lclangBasic) + +# Throw an error if a proper version of `clang` is not available. +analyzegc-deps-check: ifeq ($(USE_BINARYBUILDER_LLVM),0) ifneq ($(BUILD_LLVM_CLANG),1) $(error Clang must be available to use the clang analyzer. Either build it (BUILD_LLVM_CLANG) or use BinaryBuilder) endif endif - $(MAKE) -C clangsa - $(build_depsbindir)/clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang $(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -Xclang -analyzer-checker=core,julia.GCChecker --analyzer-no-default-checks -fcolor-diagnostics -Werror -x c $(RUNTIME_C_SRCS:%=$(SRCDIR)/%.c) -.PHONY: default all debug release clean cleanall clean-* libccalltest libllvmcalltest julia_flisp.boot.inc.phony + +define CLANG_ANALYZE +clang-sa-$(1): $$(build_shlibdir)/libGCCheckerPlugin.$$(SHLIB_EXT) | analyzegc-deps-check + @$$(call PRINT_ANALYZE, $$(build_depsbindir)/clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang $$(build_shlibdir)/libGCCheckerPlugin.$$(SHLIB_EXT) $$(CPPFLAGS) $$(CFLAGS) $$(DEBUGFLAGS) -Xclang -analyzer-checker=core$$(COMMA)julia.GCChecker --analyzer-no-default-checks -fcolor-diagnostics -Werror -x c $$(SRCDIR)/$(1).c) +.PHONY: clang-sa-$(1) + +# Add this as a target of `analyzegc` +analyzegc: clang-sa-$(1) +endef + +# Build a Makefile target for each file we want to analyze +$(foreach S,$(RUNTIME_C_SRCS),$(eval $(call CLANG_ANALYZE,$(S)))) + +# Note that for a default install, you will need to have run the following +# before attempting this static analysis, so that all necessary headers +# and dependencies are properly installed: +# make -c deps install-libuv install-utf8proc install-unwind +analyzegc: $(BUILDDIR)/julia_version.h $(BUILDDIR)/julia_flisp.boot.inc + +.PHONY: default all debug release clean cleanall clean-* libccalltest libllvmcalltest julia_flisp.boot.inc.phony analyzegc diff --git a/src/array.c b/src/array.c index 1afceb7054a56..5256ccf7266d0 100644 --- a/src/array.c +++ b/src/array.c @@ -471,6 +471,8 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a) JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len) { size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size + if (sz < len) // overflow + jl_throw(jl_memory_exception); if (len == 0) return jl_an_empty_string; jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining @@ -483,6 +485,8 @@ JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len) JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len) { size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size + if (sz < len) // overflow + jl_throw(jl_memory_exception); if (len == 0) return jl_an_empty_string; jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining diff --git a/src/ccall.cpp b/src/ccall.cpp index 707aead0d9f7d..17842c506cf60 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -87,7 +87,7 @@ static bool runtime_sym_gvs(const char *f_lib, const char *f_name, MT &&M, symMap = &libgv.second; libsym = jl_get_library(f_lib); assert(libsym != NULL); - *(void**)jl_emit_and_add_to_shadow(libptrgv) = libsym; + *jl_emit_and_add_to_shadow(libptrgv) = libsym; } else { libptrgv = iter->second.first; @@ -116,7 +116,7 @@ static bool runtime_sym_gvs(const char *f_lib, const char *f_name, MT &&M, (*symMap)[f_name] = std::make_pair(llvmgv, addr); if (symaddr) *symaddr = addr; - *(void**)jl_emit_and_add_to_shadow(llvmgv) = addr; + *jl_emit_and_add_to_shadow(llvmgv) = addr; } else { if (symaddr) @@ -238,7 +238,7 @@ static GlobalVariable *emit_plt_thunk( GlobalVariable *got = new GlobalVariable(*M, T_pvoidfunc, false, GlobalVariable::ExternalLinkage, nullptr, gname); - *(void**)jl_emit_and_add_to_shadow(got) = symaddr; + *jl_emit_and_add_to_shadow(got) = symaddr; BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", plt); IRBuilder<> irbuilder(b0); Value *ptr = runtime_sym_lookup(irbuilder, funcptype, f_lib, f_name, plt, libptrgv, @@ -1426,7 +1426,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) // method involving `jl_dlsym()` on Linux platforms instead. #ifdef _OS_LINUX_ jl_ptls_t (*p)(void); - jl_dlsym(jl_dlopen(nullptr, 0), "jl_get_ptls_states", (void **)&p, 0); + void *handle = jl_dlopen(nullptr, 0); + jl_dlsym(handle, "jl_get_ptls_states", (void **)&p, 0); + jl_dlclose(handle); return p; #else return &jl_get_ptls_states; diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index 823ca0f1091b6..ebba6467528e1 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -96,9 +96,10 @@ static bool check_fd_or_close(int fd) { if (fd == -1) return false; - fcntl(fd, F_SETFD, FD_CLOEXEC); - fchmod(fd, S_IRWXU); - if (ftruncate(fd, jl_page_size) != 0) { + int err = fcntl(fd, F_SETFD, FD_CLOEXEC); + assert(err == 0); + if (fchmod(fd, S_IRWXU) != 0 || + ftruncate(fd, jl_page_size) != 0) { close(fd); return false; } diff --git a/src/clangsa/GCChecker.cpp b/src/clangsa/GCChecker.cpp index a70129e0eb387..e51857edcd4c8 100644 --- a/src/clangsa/GCChecker.cpp +++ b/src/clangsa/GCChecker.cpp @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + #include "clang/Tooling/Tooling.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Frontend/FrontendActions.h" @@ -10,7 +12,11 @@ #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" #include "clang/StaticAnalyzer/Checkers/SValExplainer.h" +#if LLVM_VERSION_MAJOR >= 9 +#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" +#else #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" +#endif #include namespace { @@ -205,14 +211,16 @@ namespace { } PDP VisitNode(const ExplodedNode *N, +#if LLVM_VERSION_MAJOR <= 8 const ExplodedNode *PrevN, +#endif BugReporterContext &BRC, BugReport &BR) override; }; class GCValueBugVisitor #if LLVM_VERSION_MAJOR >= 7 - : public BugReporterVisitor + : public BugReporterVisitor { #else : public BugReporterVisitorImpl { #endif @@ -234,7 +242,9 @@ namespace { const ExplodedNode *N, PathDiagnosticLocation Pos, BugReporterContext &BRC, BugReport &BR); PDP VisitNode(const ExplodedNode *N, +#if LLVM_VERSION_MAJOR <= 8 const ExplodedNode *PrevN, +#endif BugReporterContext &BRC, BugReport &BR) override; }; @@ -315,8 +325,12 @@ namespace Helpers { } PDP GCChecker::GCBugVisitor::VisitNode( - const ExplodedNode *N, const ExplodedNode *PrevN, + const ExplodedNode *N, +#if LLVM_VERSION_MAJOR <= 8 + const ExplodedNode *, +#endif BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *PrevN = N->getFirstPred(); unsigned NewGCDepth = N->getState()->get(); unsigned OldGCDepth = PrevN->getState()->get(); if (NewGCDepth != OldGCDepth) { @@ -410,8 +424,12 @@ PDP GCChecker::GCValueBugVisitor::ExplainNoPropagation( } PDP GCChecker::GCValueBugVisitor::VisitNode( - const ExplodedNode *N, const ExplodedNode *PrevN, + const ExplodedNode *N, +#if LLVM_VERSION_MAJOR <= 8 + const ExplodedNode *, +#endif BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *PrevN = N->getFirstPred(); const ValueState *NewValueState = N->getState()->get(Sym); const ValueState *OldValueState = PrevN->getState()->get(Sym); const Stmt *Stmt = PathDiagnosticLocation::getStmt(N); @@ -1516,7 +1534,11 @@ extern "C" const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING; extern "C" void clang_registerCheckers (CheckerRegistry ®istry) { - registry.addChecker("julia.GCChecker", - "Validates julia gc invariants"); + registry.addChecker("julia.GCChecker", + "Validates julia gc invariants" +#if LLVM_VERSION_MAJOR >= 8 + ,"https://docs.julialang.org/en/v1/devdocs/gc-sa/" +#endif + ); } #endif diff --git a/src/clangsa/Makefile b/src/clangsa/Makefile deleted file mode 100644 index 81791eb61eb61..0000000000000 --- a/src/clangsa/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -JULIAHOME := $(abspath $(SRCDIR)/../..) -BUILDDIR := . -include $(JULIAHOME)/Make.inc - -$(build_shlibdir)/libGCCheckerPlugin.$(SHLIB_EXT): $(SRCDIR)/GCChecker.cpp - @$(call PRINT_CC, $(CXX) -g -shared -fno-rtti -fPIC -o $@ -std=c++11 -DCLANG_PLUGIN -I$(build_includedir) -I$(LLVM_SRC_DIR)/include -L$(build_libdir) $< -lclangAnalysis -lclangStaticAnalyzerCore -lclangASTMatchers -lclangAST -lclangLex -lclangBasic) diff --git a/src/codegen.cpp b/src/codegen.cpp index 71a52d126c146..02ddbbdd37a53 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1101,11 +1101,7 @@ jl_code_instance_t *jl_compile_linfo(jl_method_instance_t *mi, jl_code_info_t *s if (codeinst->min_world <= world && world <= codeinst->max_world) { jl_llvm_functions_t decls = codeinst->functionObjectsDecls; bool already_compiled = params->cached && decls.functionObject != NULL; - if (!src) { - if (already_compiled || codeinst->invoke == jl_fptr_const_return) - goto locked_out; - } - else if (already_compiled) { + if (already_compiled) { goto locked_out; } } @@ -1634,6 +1630,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *mi, size_t world, bool getwrapper, return returninfo.decl; } } + assert(decls.functionObject); auto f = Function::Create(jl_func_sig, GlobalVariable::ExternalLinkage, decls.functionObject); add_return_attr(f, Attribute::NonNull); f->addFnAttr(Thunk); diff --git a/src/common_symbols1.inc b/src/common_symbols1.inc index 064ae5a3c8772..aa14098e9fbc9 100644 --- a/src/common_symbols1.inc +++ b/src/common_symbols1.inc @@ -99,4 +99,3 @@ jl_symbol("UInt"), jl_symbol("haskey"), jl_symbol("setproperty!"), jl_symbol("promote"), -jl_symbol("undef"), diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index cdc31ec1d57cb..64ca23ad29078 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -1,3 +1,4 @@ +jl_symbol("undef"), jl_symbol("Vector"), jl_symbol("parent"), jl_symbol("_promote"), @@ -251,4 +252,3 @@ jl_symbol("Complex"), jl_symbol("checked_add"), jl_symbol("mod"), jl_symbol("unsafe_write"), -jl_symbol("libuv.jl"), diff --git a/src/datatype.c b/src/datatype.c index ac5606ced893b..ed132c8ace059 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -85,6 +85,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) t->isbitstype = 0; t->zeroinit = 0; t->isinlinealloc = 0; + t->has_concrete_subtype = 1; t->layout = NULL; t->names = NULL; return t; @@ -309,6 +310,12 @@ void jl_compute_field_offsets(jl_datatype_t *st) st->isbitstype = jl_is_datatype(fld) && ((jl_datatype_t*)fld)->isbitstype; if (!st->zeroinit) st->zeroinit = (jl_is_datatype(fld) && ((jl_datatype_t*)fld)->isinlinealloc) ? ((jl_datatype_t*)fld)->zeroinit : 1; + if (i < st->ninitialized) { + if (fld == jl_bottom_type) + st->has_concrete_subtype = 0; + else + st->has_concrete_subtype &= !jl_is_datatype(fld) || ((jl_datatype_t *)fld)->has_concrete_subtype; + } } if (st->isbitstype) { st->isinlinealloc = 1; @@ -852,6 +859,8 @@ JL_DLLEXPORT jl_value_t *jl_new_structt(jl_datatype_t *type, jl_value_t *tup) jl_ptls_t ptls = jl_get_ptls_states(); if (!jl_is_tuple(tup)) jl_type_error("new", (jl_value_t*)jl_tuple_type, tup); + if (type->layout == NULL) + jl_type_error("new", (jl_value_t *)jl_datatype_type, (jl_value_t *)type); size_t nargs = jl_nfields(tup); size_t nf = jl_datatype_nfields(type); JL_NARGS(new, nf, nf); @@ -866,8 +875,6 @@ JL_DLLEXPORT jl_value_t *jl_new_structt(jl_datatype_t *type, jl_value_t *tup) } return type->instance; } - if (type->layout == NULL) - jl_type_error("new", (jl_value_t*)jl_datatype_type, (jl_value_t*)type); jl_value_t *jv = jl_gc_alloc(ptls, jl_datatype_size(type), type); jl_value_t *fi = NULL; JL_GC_PUSH2(&jv, &fi); diff --git a/src/dump.c b/src/dump.c index 06eff3ca3c292..9e363e84e2614 100644 --- a/src/dump.c +++ b/src/dump.c @@ -369,7 +369,8 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_ | (dt->isdispatchtuple << 2) | (dt->isbitstype << 3) | (dt->zeroinit << 4) - | (dt->isinlinealloc << 5)); + | (dt->isinlinealloc << 5) + | (dt->has_concrete_subtype << 6)); if (!dt->abstract) { write_uint16(s->s, dt->ninitialized); } @@ -1403,6 +1404,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v dt->isbitstype = (memflags >> 3) & 1; dt->zeroinit = (memflags >> 4) & 1; dt->isinlinealloc = (memflags >> 5) & 1; + dt->has_concrete_subtype = (memflags >> 6) & 1; dt->types = NULL; dt->parameters = NULL; dt->name = NULL; @@ -2605,7 +2607,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_code_instance_ jl_value_t *slotnames = jl_deserialize_value(&s, NULL); if (!jl_is_string(slotnames)) slotnames = m->slot_syms; - code->slotnames = jl_uncompress_argnames(m->slot_syms); + code->slotnames = jl_uncompress_argnames(slotnames); size_t nstmt = jl_array_len(code->code); code->codelocs = (jl_value_t*)jl_alloc_array_1d(jl_array_int32_type, nstmt); @@ -3072,6 +3074,7 @@ static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t while (1) { entry = jl_typemap_assoc_by_type( mt->defs, (jl_value_t*)sig, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/(~(size_t)0) >> 1); + assert(entry); jl_method_t *_new = (jl_method_t*)entry->func.value; world = lowerbound_dependent_world_set(_new->primary_world, dependent_worlds); if (world == _new->primary_world) { @@ -3304,7 +3307,8 @@ void jl_init_serializer(void) jl_voidpointer_type, jl_newvarnode_type, jl_abstractstring_type, jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type), jl_emptytuple_type, jl_array_uint8_type, jl_code_info_type, - jl_typeofbottom_type, jl_namedtuple_type, jl_array_int32_type, + jl_typeofbottom_type, jl_typeofbottom_type->super, + jl_namedtuple_type, jl_array_int32_type, jl_typedslot_type, jl_uint32_type, jl_uint64_type, jl_type_type_mt, jl_nonfunction_mt, diff --git a/src/flisp/Makefile b/src/flisp/Makefile index d1d92ab4c87bf..a667f93793ac4 100644 --- a/src/flisp/Makefile +++ b/src/flisp/Makefile @@ -100,3 +100,5 @@ clean: rm -f $(BUILDDIR)/*.a rm -f $(BUILDDIR)/$(EXENAME)$(EXE) rm -f $(BUILDDIR)/$(EXENAME)-debug$(EXE) + +.PHONY: flisp-deps diff --git a/src/gc.c b/src/gc.c index f1bc2d6f1e84c..0fe4b1fdc460a 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2499,7 +2499,9 @@ static void mark_roots(jl_gc_mark_cache_t *gc_cache, jl_gc_mark_sp_t *sp) gc_mark_queue_obj(gc_cache, sp, jl_main_module); // tasks +#ifdef JULIA_ENABLE_THREADING jl_gc_mark_enqueued_tasks(gc_cache, sp); +#endif // invisible builtin values if (jl_an_empty_vec_any != NULL) diff --git a/src/gf.c b/src/gf.c index 394613c326fe0..1e872bec2e5b4 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2379,7 +2379,16 @@ JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_value_t *ty) if (!mt->kwsorter) { JL_LOCK(&mt->writelock); if (!mt->kwsorter) { - mt->kwsorter = jl_new_generic_function_with_supertype(mt->name, mt->module, jl_function_type, 1); + jl_sym_t *name; + if (mt == jl_nonfunction_mt) { + name = mt->name; + } + else { + jl_datatype_t *dt = (jl_datatype_t*)jl_argument_datatype(ty); + assert(jl_is_datatype(dt)); + name = dt->name->name; + } + mt->kwsorter = jl_new_generic_function_with_supertype(name, mt->module, jl_function_type, 1); jl_gc_wb(mt, mt->kwsorter); } JL_UNLOCK(&mt->writelock); @@ -2573,19 +2582,7 @@ int jl_has_concrete_subtype(jl_value_t *typ) typ = jl_unwrap_vararg(typ); if (!jl_is_datatype(typ)) return 1; - if (((jl_datatype_t*)typ)->name == jl_namedtuple_typename) - return jl_has_concrete_subtype(jl_tparam1(typ)); - jl_svec_t *fields = jl_get_fieldtypes((jl_datatype_t*)typ); - size_t i, l = jl_svec_len(fields); - if (l != ((jl_datatype_t*)typ)->ninitialized) - if (((jl_datatype_t*)typ)->name != jl_tuple_typename) - return 1; - for (i = 0; i < l; i++) { - jl_value_t *ft = jl_svecref(fields, i); - if (!jl_has_concrete_subtype(ft)) - return 0; - } - return 1; + return ((jl_datatype_t*)typ)->has_concrete_subtype; } // TODO: separate the codegen and typeinf locks diff --git a/src/init.c b/src/init.c index 306cadbfa19db..1c0f6564e5ff4 100644 --- a/src/init.c +++ b/src/init.c @@ -160,11 +160,11 @@ static void jl_uv_exitcleanup_add(uv_handle_t *handle, struct uv_shutdown_queue struct uv_shutdown_queue_item *item = (struct uv_shutdown_queue_item*)malloc(sizeof(struct uv_shutdown_queue_item)); item->h = handle; item->next = NULL; - JL_UV_LOCK(); - if (queue->last) queue->last->next = item; - if (!queue->first) queue->first = item; + if (queue->last) + queue->last->next = item; + if (!queue->first) + queue->first = item; queue->last = item; - JL_UV_UNLOCK(); } static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg) @@ -297,8 +297,8 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) // force libuv to spin until everything has finished closing loop->stop_flag = 0; - JL_UV_UNLOCK(); while (uv_run(loop, UV_RUN_DEFAULT)) { } + JL_UV_UNLOCK(); // TODO: Destroy threads @@ -397,6 +397,7 @@ static void *init_stdio_handle(const char *stdio, uv_os_fd_t fd, int readable) { int nullfd; nullfd = open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH /* 0666 */); + assert(nullfd != -1); dup2(nullfd, fd); close(nullfd); } @@ -627,11 +628,6 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_options.outputbc = abspath(jl_options.outputbc, 0); if (jl_options.machine_file) jl_options.machine_file = abspath(jl_options.machine_file, 0); - if (jl_options.project - && strcmp(jl_options.project, "@.") != 0 - && strcmp(jl_options.project, "@") != 0 - && strcmp(jl_options.project, "") != 0) - jl_options.project = abspath(jl_options.project, 0); if (jl_options.output_code_coverage) jl_options.output_code_coverage = absformat(jl_options.output_code_coverage); diff --git a/src/interpreter.c b/src/interpreter.c index 4fb7c40289112..396b590beed2b 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -835,17 +835,13 @@ SECT_INTERP CALLBACK_ABI void *jl_interpret_call_callback(interpreter_state *s, locals[1] = (jl_value_t*)stmts; s->locals = locals + 2; s->src = src; - size_t nargs; - int isva; if (jl_is_module(args->mi->def.value)) { s->module = args->mi->def.module; - nargs = 0; - isva = 0; } else { s->module = args->mi->def.method->module; - nargs = args->mi->def.method->nargs; - isva = args->mi->def.method->isva ? 1 : 0; + size_t nargs = args->mi->def.method->nargs; + int isva = args->mi->def.method->isva ? 1 : 0; size_t i; s->locals[0] = args->f; for (i = 1; i < nargs - isva; i++) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index cd68699728c53..0b46d80ba2fcb 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -126,6 +126,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createLowerExcHandlersPass()); PM->add(createGCInvariantVerifierPass(false)); PM->add(createLateLowerGCFramePass()); + PM->add(createFinalLowerGCPass()); PM->add(createLowerPTLSPass(dump_native)); } PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "loopinfo" as LLVM parallel loop @@ -241,6 +242,7 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createLowerExcHandlersPass()); PM->add(createGCInvariantVerifierPass(false)); PM->add(createLateLowerGCFramePass()); + PM->add(createFinalLowerGCPass()); // Remove dead use of ptls PM->add(createDeadCodeEliminationPass()); PM->add(createLowerPTLSPass(dump_native)); @@ -433,9 +435,9 @@ JuliaOJIT::JuliaOJIT(TargetMachine &TM) // Make sure SectionMemoryManager::getSymbolAddressInProcess can resolve // symbols in the program as well. The nullptr argument to the function // tells DynamicLibrary to load the program, not a library. - std::string *ErrorStr = nullptr; - if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, ErrorStr)) - report_fatal_error("FATAL: unable to dlopen self\n" + *ErrorStr); + std::string ErrorStr; + if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrorStr)) + report_fatal_error("FATAL: unable to dlopen self\n" + ErrorStr); } void JuliaOJIT::addGlobalMapping(StringRef Name, uint64_t Addr) @@ -873,7 +875,7 @@ static std::map jl_value_to_llvm; // // then add a global mapping to the current value (usually from calloc'd space) // to the execution engine to make it valid for the current session (with the current value) -void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit) +void** jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit) { PointerType *T = cast(gv->getType()->getElementType()); // pointer is the only supported type here @@ -896,7 +898,7 @@ void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit) } // make the pointer valid for this session - void *slot = calloc(1, sizeof(void*)); + void **slot = (void**)calloc(1, sizeof(void*)); jl_ExecutionEngine->addGlobalMapping(gv, slot); return slot; } @@ -1150,7 +1152,7 @@ GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M) GlobalVariable *gv = new GlobalVariable(*M, T_pjlvalue, false, GlobalVariable::ExternalLinkage, NULL, gvname.str()); - *(void**)jl_emit_and_add_to_shadow(gv, addr) = addr; + *jl_emit_and_add_to_shadow(gv, addr) = addr; return gv; } diff --git a/src/jitlayers.h b/src/jitlayers.h index 1056146f1697c..464625ec2467e 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -38,7 +38,7 @@ typedef struct {Value *gv; int32_t index;} jl_value_llvm; // uses 1-based indexi void addTargetPasses(legacy::PassManagerBase *PM, TargetMachine *TM); void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, bool lower_intrinsics=true, bool dump_native=false); -void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL); +void** jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL); void* jl_get_globalvar(GlobalVariable *gv); GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M); void jl_add_to_shadow(Module *m); @@ -195,6 +195,7 @@ JL_DLLEXPORT extern LLVMContext jl_LLVMContext; Pass *createLowerPTLSPass(bool imaging_mode); Pass *createCombineMulAddPass(); +Pass *createFinalLowerGCPass(); Pass *createLateLowerGCFramePass(); Pass *createLowerExcHandlersPass(); Pass *createGCInvariantVerifierPass(bool Strong); diff --git a/src/jl_uv.c b/src/jl_uv.c index 6f95aa1818c60..fc4eb147cc755 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -190,14 +190,16 @@ JL_DLLEXPORT void jl_uv_req_set_data(uv_req_t *req, void *data) { req->data = da JL_DLLEXPORT void *jl_uv_handle_data(uv_handle_t *handle) { return handle->data; } JL_DLLEXPORT void *jl_uv_write_handle(uv_write_t *req) { return req->handle; } +extern volatile unsigned _threadedregion; + JL_DLLEXPORT int jl_run_once(uv_loop_t *loop) { jl_ptls_t ptls = jl_get_ptls_states(); - if (loop) { + if (loop && (_threadedregion || ptls->tid == 0)) { jl_gc_safepoint_(ptls); JL_UV_LOCK(); loop->stop_flag = 0; - int r = uv_run(loop,UV_RUN_ONCE); + int r = uv_run(loop, UV_RUN_ONCE); JL_UV_UNLOCK(); return r; } @@ -207,13 +209,14 @@ JL_DLLEXPORT int jl_run_once(uv_loop_t *loop) JL_DLLEXPORT int jl_process_events(uv_loop_t *loop) { jl_ptls_t ptls = jl_get_ptls_states(); - if (loop) { + if (loop && (_threadedregion || ptls->tid == 0)) { jl_gc_safepoint_(ptls); - JL_UV_LOCK(); - loop->stop_flag = 0; - int r = uv_run(loop,UV_RUN_NOWAIT); - JL_UV_UNLOCK(); - return r; + if (jl_mutex_trylock(&jl_uv_mutex)) { + loop->stop_flag = 0; + int r = uv_run(loop, UV_RUN_NOWAIT); + JL_UV_UNLOCK(); + return r; + } } return 0; } @@ -1082,36 +1085,29 @@ JL_DLLEXPORT int jl_queue_work(work_cb_t work_func, void *work_args, void *work_ return 0; } -JL_DLLEXPORT void jl_uv_stop(uv_loop_t* loop) +JL_DLLEXPORT void jl_uv_update_timer_start(uv_loop_t* loop, jl_value_t* jltimer, + uv_timer_t* uvtimer, uv_timer_cb cb, + uint64_t timeout, uint64_t repeat) { JL_UV_LOCK(); - uv_stop(loop); - // TODO: use memory/compiler fence here instead of the lock - JL_UV_UNLOCK(); -} + int err = uv_timer_init(loop, uvtimer); + if (err) + abort(); -JL_DLLEXPORT void jl_uv_update_time(uv_loop_t* loop) -{ - JL_UV_LOCK(); + jl_uv_associate_julia_struct((uv_handle_t*)uvtimer, jltimer); uv_update_time(loop); + err = uv_timer_start(uvtimer, cb, timeout, repeat); + if (err) + abort(); JL_UV_UNLOCK(); } -JL_DLLEXPORT int jl_uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, - uint64_t timeout, uint64_t repeat) -{ - JL_UV_LOCK(); - int r = uv_timer_start(handle, cb, timeout, repeat); - JL_UV_UNLOCK(); - return r; -} - -JL_DLLEXPORT int jl_uv_timer_stop(uv_timer_t* handle) +JL_DLLEXPORT void jl_uv_stop(uv_loop_t* loop) { JL_UV_LOCK(); - int r = uv_timer_stop(handle); + uv_stop(loop); + // TODO: use memory/compiler fence here instead of the lock JL_UV_UNLOCK(); - return r; } JL_DLLEXPORT int jl_uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, diff --git a/src/jltypes.c b/src/jltypes.c index 057f66d42d53c..a1f9d7459825d 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -819,8 +819,21 @@ static int within_typevar(jl_value_t *t, jl_value_t *vlb, jl_value_t *vub) struct _jl_typestack_t; typedef struct _jl_typestack_t jl_typestack_t; -static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, - int cacheable, jl_typestack_t *stack); +static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, + int cacheable, jl_typestack_t *stack, jl_typeenv_t *env); + +// Build an environment mapping a TypeName's parameters to parameter values. +// This is the environment needed for instantiating a type's supertype and field types. +static jl_value_t *inst_datatype_env(jl_value_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, + int cacheable, jl_typestack_t *stack, jl_typeenv_t *env, int c) +{ + if (jl_is_datatype(dt)) + return inst_datatype_inner((jl_datatype_t*)dt, p, iparams, ntp, cacheable, stack, env); + assert(jl_is_unionall(dt)); + jl_unionall_t *ua = (jl_unionall_t*)dt; + jl_typeenv_t e = { ua->var, iparams[c], env }; + return inst_datatype_env(ua->body, p, iparams, ntp, cacheable, stack, &e, c + 1); +} jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n) { @@ -836,12 +849,13 @@ jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n) if (jl_is_datatype(u) && n == jl_nparams((jl_datatype_t*)u) && ((jl_datatype_t*)u)->name->wrapper == tc) { int cacheable = 1; - for(i=0; i < n; i++) { + for (i = 0; i < n; i++) { if (jl_has_free_typevars(params[i])) { - cacheable = 0; break; + cacheable = 0; + break; } } - return inst_datatype((jl_datatype_t*)u, NULL, params, n, cacheable, NULL); + return inst_datatype_env(tc, NULL, params, n, cacheable, NULL, NULL, 0); } } JL_GC_PUSH1(&tc); @@ -1068,6 +1082,8 @@ static jl_value_t *normalize_vararg(jl_value_t *va) return va; } +static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals, jl_typeenv_t *prev, jl_typestack_t *stack); + static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, int cacheable, jl_typestack_t *stack, jl_typeenv_t *env) { @@ -1262,6 +1278,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value if (cacheable && !ndt->abstract) ndt->uid = jl_assign_type_uid(); + jl_datatype_t *primarydt = ((jl_datatype_t*)jl_unwrap_unionall(tn->wrapper)); if (istuple || isnamedtuple) { ndt->super = jl_any_type; } @@ -1273,10 +1290,12 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value jl_cache_type_(ndt); } jl_svec_t *ftypes = dt->types; + if (ftypes == NULL) + ftypes = primarydt->types; if (ftypes == NULL || dt->super == NULL) { // in the process of creating this type definition: // need to instantiate the super and types fields later - assert(inside_typedef && !istuple && !isnamedtuple); + assert((inside_typedef || primarydt->super) && !istuple && !isnamedtuple); arraylist_push(&partial_inst, ndt); } else if (!isnamedtuple && !istuple) { @@ -1287,7 +1306,10 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value } else if (cacheable) { // recursively instantiate the types of the fields - ndt->types = inst_ftypes(ftypes, env, stack); + if (dt->types == NULL) + ndt->types = jl_compute_fieldtypes(ndt); + else + ndt->types = inst_ftypes(ftypes, env, stack); jl_gc_wb(ndt, ndt->types); } } @@ -1315,25 +1337,6 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value return (jl_value_t*)ndt; } -// Build an environment mapping a TypeName's parameters to parameter values. -// This is the environment needed for instantiating a type's supertype and field types. -static jl_value_t *inst_datatype_env(jl_value_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, - int cacheable, jl_typestack_t *stack, jl_typeenv_t *env, int c) -{ - if (jl_is_datatype(dt)) - return inst_datatype_inner((jl_datatype_t*)dt, p, iparams, ntp, cacheable, stack, env); - assert(jl_is_unionall(dt)); - jl_unionall_t *ua = (jl_unionall_t*)dt; - jl_typeenv_t e = { ua->var, iparams[c], env }; - return inst_datatype_env(ua->body, p, iparams, ntp, cacheable, stack, &e, c+1); -} - -static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, - int cacheable, jl_typestack_t *stack) -{ - return inst_datatype_env(dt->name->wrapper, p, iparams, ntp, cacheable, stack, NULL, 0); -} - static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec_t *params) { int cacheable = 1; @@ -1342,9 +1345,7 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec if (!jl_is_concrete_type(p[i])) cacheable = 0; } - jl_datatype_t *ndt = (jl_datatype_t*)inst_datatype(jl_anytuple_type, params, p, np, - cacheable, NULL); - return ndt; + return (jl_datatype_t*)inst_datatype_inner(jl_anytuple_type, params, p, np, cacheable, NULL, NULL); } JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type(jl_svec_t *params) @@ -1359,12 +1360,12 @@ JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np) jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p) { - return (jl_datatype_t*)inst_datatype(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL); + return (jl_datatype_t*)inst_datatype_inner(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL, NULL); } jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np) { - return (jl_datatype_t*)inst_datatype(jl_anytuple_type, NULL, p, np, 1, NULL); + return (jl_datatype_t*)inst_datatype_inner(jl_anytuple_type, NULL, p, np, 1, NULL, NULL); } static jl_svec_t *inst_ftypes(jl_svec_t *p, jl_typeenv_t *env, jl_typestack_t *stack) @@ -1393,7 +1394,7 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_ jl_svec_t *tp = tt->parameters; size_t ntp = jl_svec_len(tp); // Instantiate NTuple{3,Int} - // Note this does not instantiate Tuple{Vararg{Int,3}}; that's done in inst_datatype + // Note this does not instantiate Tuple{Vararg{Int,3}}; that's done in inst_datatype_inner if (jl_is_va_tuple(tt) && ntp == 1) { // If this is a Tuple{Vararg{T,N}} with known N, expand it to // a fixed-length tuple @@ -1419,12 +1420,13 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_ jl_value_t **iparams; int onstack = ntp < jl_page_size/sizeof(jl_value_t*); JL_GC_PUSHARGS(iparams, onstack ? ntp : 1); - jl_svec_t *ip_heap=NULL; + jl_svec_t *ip_heap = NULL; if (!onstack) { ip_heap = jl_alloc_svec(ntp); iparams[0] = (jl_value_t*)ip_heap; iparams = jl_svec_data(ip_heap); } + int bound = 0; int cacheable = 1; if (jl_is_va_tuple(tt)) cacheable = 0; @@ -1435,12 +1437,14 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_ iparams[i] = pi; if (ip_heap) jl_gc_wb(ip_heap, pi); + bound |= (pi != elt); if (cacheable && !jl_is_concrete_type(pi)) cacheable = 0; } - jl_value_t *result = inst_datatype((jl_datatype_t*)tt, ip_heap, iparams, ntp, cacheable, stack); + if (bound) + t = inst_datatype_inner(tt, ip_heap, iparams, ntp, cacheable, stack, env); JL_GC_POP(); - return result; + return t; } static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t *stack, int check) @@ -1451,44 +1455,38 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t while (e != NULL) { if (e->var == (jl_tvar_t*)t) { jl_value_t *val = e->val; - // TODO jb/subtype this seems unnecessary - //if (check && !jl_is_typevar(val) && !within_typevar(val, (jl_tvar_t*)t)) { - // jl_type_error_rt("type parameter", - // jl_symbol_name(((jl_tvar_t*)t)->name), t, val); - //} return val; } e = e->prev; } - return (jl_value_t*)t; + return t; } if (jl_is_unionall(t)) { - if (!jl_has_free_typevars(t)) - return t; jl_unionall_t *ua = (jl_unionall_t*)t; - jl_value_t *res=NULL, *lb=ua->var->lb, *ub=ua->var->ub; - JL_GC_PUSH3(&lb, &ub, &res); - res = jl_new_struct(jl_unionall_type, ua->var, NULL); - if (jl_has_bound_typevars(ua->var->lb, env)) - lb = inst_type_w_(ua->var->lb, env, stack, check); - if (jl_has_bound_typevars(ua->var->ub, env)) - ub = inst_type_w_(ua->var->ub, env, stack, check); - if (lb != ua->var->lb || ub != ua->var->ub) { - ((jl_unionall_t*)res)->var = jl_new_typevar(ua->var->name, lb, ub); - jl_gc_wb(res, ((jl_unionall_t*)res)->var); + jl_value_t *lb = NULL; + jl_value_t *var = NULL; + jl_value_t *newbody = NULL; + JL_GC_PUSH3(&lb, &var, &newbody); + lb = inst_type_w_(ua->var->lb, env, stack, check); + var = inst_type_w_(ua->var->ub, env, stack, check); + if (lb != ua->var->lb || var != ua->var->ub) { + var = (jl_value_t*)jl_new_typevar(ua->var->name, lb, var); + } + else { + var = (jl_value_t*)ua->var; } - jl_typeenv_t newenv = { ua->var, (jl_value_t*)((jl_unionall_t*)res)->var, env }; - jl_value_t *newbody = inst_type_w_(ua->body, &newenv, stack, check); + jl_typeenv_t newenv = { ua->var, var, env }; + newbody = inst_type_w_(ua->body, &newenv, stack, check); if (newbody == (jl_value_t*)jl_emptytuple_type) { // NTuple{0} => Tuple{} can make a typevar disappear - res = (jl_value_t*)jl_emptytuple_type; + t = (jl_value_t*)jl_emptytuple_type; } - else { - ((jl_unionall_t*)res)->body = newbody; - jl_gc_wb(res, newbody); + else if (newbody != ua->body || var != (jl_value_t*)ua->var) { + // if t's parameters are not bound in the environment, return it uncopied (#9378) + t = jl_new_struct(jl_unionall_type, var, newbody); } JL_GC_POP(); - return res; + return t; } if (jl_is_uniontype(t)) { jl_uniontype_t *u = (jl_uniontype_t*)t; @@ -1496,23 +1494,19 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t jl_value_t *b = NULL; JL_GC_PUSH2(&a, &b); b = inst_type_w_(u->b, env, stack, check); - jl_value_t *res; - if (a == u->a && b == u->b) { - res = t; - } - else { + if (a != u->a || b != u->b) { jl_value_t *uargs[2] = {a, b}; - res = jl_type_union(uargs, 2); + t = jl_type_union(uargs, 2); } JL_GC_POP(); - return res; + return t; } if (!jl_is_datatype(t)) return t; jl_datatype_t *tt = (jl_datatype_t*)t; jl_svec_t *tp = tt->parameters; if (tp == jl_emptysvec) - return (jl_value_t*)t; + return t; jl_typename_t *tn = tt->name; if (tn == jl_tuple_typename) return inst_tuple_w_(t, env, stack, check); @@ -1520,19 +1514,19 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t jl_value_t **iparams; JL_GC_PUSHARGS(iparams, ntp); int cacheable = 1, bound = 0; - for(i=0; i < ntp; i++) { + for (i = 0; i < ntp; i++) { jl_value_t *elt = jl_svecref(tp, i); - iparams[i] = inst_type_w_(elt, env, stack, check); - bound |= (iparams[i] != elt); - if (cacheable && jl_has_free_typevars(iparams[i])) + jl_value_t *pi = inst_type_w_(elt, env, stack, check); + iparams[i] = pi; + bound |= (pi != elt); + if (cacheable && jl_has_free_typevars(pi)) cacheable = 0; } // if t's parameters are not bound in the environment, return it uncopied (#9378) - if (!bound) { JL_GC_POP(); return (jl_value_t*)t; } - - jl_value_t *result = inst_datatype((jl_datatype_t*)tt, NULL, iparams, ntp, cacheable, stack); + if (bound) + t = inst_datatype_inner(tt, NULL, iparams, ntp, cacheable, stack, env); JL_GC_POP(); - return result; + return t; } static jl_value_t *instantiate_with(jl_value_t *t, jl_value_t **env, size_t n, jl_typeenv_t *te) @@ -1549,13 +1543,13 @@ jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n) return instantiate_with(t, env, n, NULL); } -static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals, jl_typeenv_t *prev) +static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals, jl_typeenv_t *prev, jl_typestack_t *stack) { jl_typeenv_t en = { env->var, vals[0], prev }; if (jl_is_unionall(env->body)) - return _jl_instantiate_type_in_env(ty, (jl_unionall_t*)env->body, vals + 1, &en); + return _jl_instantiate_type_in_env(ty, (jl_unionall_t*)env->body, vals + 1, &en, stack); else - return inst_type_w_(ty, &en, NULL, 1); + return inst_type_w_(ty, &en, stack, 1); } JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals) @@ -1563,7 +1557,7 @@ JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_ jl_value_t *typ = ty; if (jl_is_unionall(env)) { JL_TRY { - typ = _jl_instantiate_type_in_env(ty, env, vals, NULL); + typ = _jl_instantiate_type_in_env(ty, env, vals, NULL, NULL); } JL_CATCH { typ = jl_bottom_type; @@ -1713,7 +1707,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->names = jl_perm_symsvec(20, + jl_datatype_type->name->names = jl_perm_symsvec(21, "name", "super", "parameters", @@ -1732,9 +1726,10 @@ void jl_init_types(void) JL_GC_DISABLED "isbitstype", "zeroinit", "isinlinealloc", + "has_concrete_subtype", "llvm::StructType", "llvm::DIType"); - jl_datatype_type->types = jl_svec(20, + jl_datatype_type->types = jl_svec(21, jl_typename_type, jl_datatype_type, jl_simplevector_type, @@ -1743,7 +1738,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type); + jl_any_type, jl_any_type, jl_any_type); jl_datatype_type->instance = NULL; jl_datatype_type->uid = jl_assign_type_uid(); jl_datatype_type->struct_decl = NULL; @@ -1971,8 +1966,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_type_type, // TupleType jl_any_type, // TupleType jl_any_type, // SimpleVector{TupleType} - jl_long_type, // Int - jl_long_type, // Int + jl_ulong_type, // UInt + jl_ulong_type, // UInt jl_any_type, // Any jl_bool_type, jl_bool_type, @@ -2105,8 +2100,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_any_type, jl_any_type, - jl_long_type, - jl_long_type, + jl_ulong_type, + jl_ulong_type, jl_bool_type, jl_bool_type, jl_bool_type, @@ -2142,8 +2137,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_module_type, jl_symbol_type, jl_int32_type, - jl_long_type, - jl_long_type, + jl_ulong_type, + jl_ulong_type, jl_type_type, jl_any_type, // Union{Array, Nothing} jl_any_type, // TypeMap @@ -2199,8 +2194,8 @@ void jl_init_types(void) JL_GC_DISABLED jl_svec(11, jl_method_instance_type, jl_any_type, - jl_long_type, - jl_long_type, + jl_ulong_type, + jl_ulong_type, jl_any_type, jl_any_type, jl_any_type, @@ -2299,8 +2294,9 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_datatype_type->types, 15, jl_bool_type); jl_svecset(jl_datatype_type->types, 16, jl_bool_type); jl_svecset(jl_datatype_type->types, 17, jl_bool_type); - jl_svecset(jl_datatype_type->types, 18, jl_voidpointer_type); + jl_svecset(jl_datatype_type->types, 18, jl_bool_type); jl_svecset(jl_datatype_type->types, 19, jl_voidpointer_type); + jl_svecset(jl_datatype_type->types, 20, jl_voidpointer_type); jl_svecset(jl_typename_type->types, 1, jl_module_type); jl_svecset(jl_typename_type->types, 6, jl_long_type); jl_svecset(jl_typename_type->types, 3, jl_type_type); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index cde0ad9bc845a..171e607977021 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1444,10 +1444,8 @@ (define (expand-update-operator- op op= lhs rhs declT) (let* ((e (remove-argument-side-effects lhs)) (newlhs (car e)) - (temp (and (eq? op= '|.=|) (pair? newlhs) (make-ssavalue))) - (newlhs (if (and temp (eq? (car newlhs) 'ref)) - (ref-to-view newlhs) - newlhs)) + (temp (and (eq? op= '|.=|) (pair? newlhs) (not (eq? (car newlhs) 'ref)) + (make-ssavalue))) (e (if temp (cons temp (append (cdr e) (list `(= ,temp ,newlhs)))) e)) diff --git a/src/julia.h b/src/julia.h index d425fe49b9e55..e0c3028a08656 100644 --- a/src/julia.h +++ b/src/julia.h @@ -442,6 +442,7 @@ typedef struct _jl_datatype_t { uint8_t isbitstype; // relevant query for C-api and type-parameters uint8_t zeroinit; // if one or more fields requires zero-initialization uint8_t isinlinealloc; // if this is allocated inline + uint8_t has_concrete_subtype; // If clear, no value will have this datatype void *struct_decl; //llvm::Type* void *ditype; // llvm::MDNode* to be used as llvm::DIType(ditype) } jl_datatype_t; diff --git a/src/julia_threads.h b/src/julia_threads.h index bc6ca7a395408..a626da27c7d65 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -154,9 +154,14 @@ struct _jl_tls_states_t { volatile int8_t gc_state; volatile int8_t in_finalizer; int8_t disable_gc; + jl_thread_heap_t heap; + uv_mutex_t sleep_lock; + uv_cond_t wake_signal; volatile sig_atomic_t defer_signal; struct _jl_task_t *current_task; +#ifdef MIGRATE_TASKS struct _jl_task_t *previous_task; +#endif struct _jl_task_t *root_task; void *stackbase; size_t stacksize; @@ -173,7 +178,6 @@ struct _jl_tls_states_t { // this is limited to the few places we do synchronous IO // we can make this more general (similar to defer_signal) if necessary volatile sig_atomic_t io_wait; - jl_thread_heap_t heap; #ifndef _OS_WINDOWS_ // These are only used on unix now pthread_t system_id; @@ -289,6 +293,8 @@ JL_DLLEXPORT void (jl_gc_safepoint)(void); JL_DLLEXPORT void jl_gc_enable_finalizers(jl_ptls_t ptls, int on); +JL_DLLEXPORT void jl_wakeup_thread(int16_t tid); + #ifdef __cplusplus } #endif diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp new file mode 100644 index 0000000000000..a68b2fc193ed8 --- /dev/null +++ b/src/llvm-final-gc-lowering.cpp @@ -0,0 +1,357 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm-version.h" +#include "codegen_shared.h" +#include "julia.h" +#include "julia_internal.h" +#include "llvm-pass-helpers.h" + +#define DEBUG_TYPE "final_gc_lowering" +#if JL_LLVM_VERSION < 70000 +#define LLVM_DEBUG DEBUG +#endif + +using namespace llvm; + +// The final GC lowering pass. This pass lowers platform-agnostic GC +// intrinsics to platform-dependent instruction sequences. The +// intrinsics it targets are those produced by the late GC frame +// lowering pass. +// +// This pass targets typical back-ends for which the standard Julia +// runtime library is available. Atypical back-ends should supply +// their own lowering pass. +struct FinalLowerGC: public FunctionPass, private JuliaPassContext { + static char ID; + FinalLowerGC() : FunctionPass(ID) + { } + +private: + Function *queueRootFunc; + Function *poolAllocFunc; + Function *bigAllocFunc; + CallInst *ptlsStates; + + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + bool runOnFunction(Function &F) override; + + // Lowers a `julia.new_gc_frame` intrinsic. + Value *lowerNewGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.push_gc_frame` intrinsic. + void lowerPushGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.pop_gc_frame` intrinsic. + void lowerPopGCFrame(CallInst *target, Function &F); + + // Lowers a `julia.get_gc_frame_slot` intrinsic. + Value *lowerGetGCFrameSlot(CallInst *target, Function &F); + + // Lowers a `julia.gc_alloc_bytes` intrinsic. + Value *lowerGCAllocBytes(CallInst *target, Function &F); + + // Lowers a `julia.queue_gc_root` intrinsic. + Value *lowerQueueGCRoot(CallInst *target, Function &F); + + Instruction *getPgcstack(Instruction *ptlsStates); +}; + +Value *FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 1); + unsigned nRoots = cast(target->getArgOperand(0))->getLimitedValue(INT_MAX); + + // Create the GC frame. + AllocaInst *gcframe = new AllocaInst( + T_prjlvalue, + 0, + ConstantInt::get(T_int32, nRoots + 2)); + gcframe->insertAfter(target); + gcframe->takeName(target); + + // Zero out the GC frame. + BitCastInst *tempSlot_i8 = new BitCastInst(gcframe, Type::getInt8PtrTy(F.getContext()), ""); + tempSlot_i8->insertAfter(gcframe); + Type *argsT[2] = {tempSlot_i8->getType(), T_int32}; + Function *memset = Intrinsic::getDeclaration(F.getParent(), Intrinsic::memset, makeArrayRef(argsT)); +#if JL_LLVM_VERSION >= 70000 + Value *args[4] = { + tempSlot_i8, // dest + ConstantInt::get(Type::getInt8Ty(F.getContext()), 0), // val + ConstantInt::get(T_int32, sizeof(jl_value_t*)*(nRoots+2)), // len + ConstantInt::get(Type::getInt1Ty(F.getContext()), 0)}; // volatile +#else + Value *args[5] = { + tempSlot_i8, // dest + ConstantInt::get(Type::getInt8Ty(F.getContext()), 0), // val + ConstantInt::get(T_int32, sizeof(jl_value_t*)*(nRoots+2)), // len + ConstantInt::get(T_int32, 0), // align + ConstantInt::get(Type::getInt1Ty(F.getContext()), 0)}; // volatile +#endif + CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); + zeroing->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); + zeroing->insertAfter(tempSlot_i8); + + return gcframe; +} + +void FinalLowerGC::lowerPushGCFrame(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 2); + auto gcframe = target->getArgOperand(0); + unsigned nRoots = cast(target->getArgOperand(1))->getLimitedValue(INT_MAX); + + IRBuilder<> builder(target->getContext()); + builder.SetInsertPoint(&*(++BasicBlock::iterator(target))); + Instruction *inst = + builder.CreateStore( + ConstantInt::get(T_size, nRoots << 1), + builder.CreateBitCast( + builder.CreateConstGEP1_32(gcframe, 0), + T_size->getPointerTo())); + inst->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); + Value *pgcstack = builder.Insert(getPgcstack(ptlsStates)); + inst = builder.CreateStore( + builder.CreateLoad(pgcstack), + builder.CreatePointerCast( + builder.CreateConstGEP1_32(gcframe, 1), + PointerType::get(T_ppjlvalue, 0))); + inst->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); + builder.CreateStore(gcframe, builder.CreateBitCast(pgcstack, + PointerType::get(PointerType::get(T_prjlvalue, 0), 0))); +} + +void FinalLowerGC::lowerPopGCFrame(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 1); + auto gcframe = target->getArgOperand(0); + + IRBuilder<> builder(target->getContext()); + builder.SetInsertPoint(target); + Instruction *gcpop = + cast(builder.CreateConstGEP1_32(gcframe, 1)); + Instruction *inst = builder.CreateLoad(gcpop); + inst->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); + inst = builder.CreateStore( + inst, + builder.CreateBitCast( + builder.Insert(getPgcstack(ptlsStates)), + PointerType::get(T_prjlvalue, 0))); + inst->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); +} + +Value *FinalLowerGC::lowerGetGCFrameSlot(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 2); + auto gcframe = target->getArgOperand(0); + auto index = target->getArgOperand(1); + + // Initialize an IR builder. + IRBuilder<> builder(target->getContext()); + builder.SetInsertPoint(target); + + // The first two slots are reserved, so we'll add two to the index. + index = builder.CreateAdd(index, ConstantInt::get(T_int32, 2)); + + // Lower the intrinsic as a GEP. + auto gep = builder.CreateGEP(gcframe, index); + gep->takeName(target); + return gep; +} + +Value *FinalLowerGC::lowerQueueGCRoot(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 1); + target->setCalledFunction(queueRootFunc); + return target; +} + +Instruction *FinalLowerGC::getPgcstack(Instruction *ptlsStates) +{ + Constant *offset = ConstantInt::getSigned(T_int32, offsetof(jl_tls_states_t, pgcstack) / sizeof(void*)); + return GetElementPtrInst::Create( + nullptr, + ptlsStates, + ArrayRef(offset), + "jl_pgcstack"); +} + +Value *FinalLowerGC::lowerGCAllocBytes(CallInst *target, Function &F) +{ + assert(target->getNumArgOperands() == 2); + auto sz = (size_t)cast(target->getArgOperand(1))->getZExtValue(); + // This is strongly architecture and OS dependent + int osize; + int offset = jl_gc_classify_pools(sz, &osize); + IRBuilder<> builder(target); + builder.SetCurrentDebugLocation(target->getDebugLoc()); + auto ptls = target->getArgOperand(0); + CallInst *newI; + if (offset < 0) { + newI = builder.CreateCall( + bigAllocFunc, + { ptls, ConstantInt::get(T_size, sz + sizeof(void*)) }); + } + else { + auto pool_offs = ConstantInt::get(T_int32, offset); + auto pool_osize = ConstantInt::get(T_int32, osize); + newI = builder.CreateCall(poolAllocFunc, { ptls, pool_offs, pool_osize }); + } + newI->setAttributes(newI->getCalledFunction()->getAttributes()); + newI->takeName(target); + return newI; +} + +bool FinalLowerGC::doInitialization(Module &M) { + // Initialize platform-agnostic references. + initAll(M); + + // Initialize platform-specific references. + queueRootFunc = getOrDeclare(jl_well_known::GCQueueRoot); + poolAllocFunc = getOrDeclare(jl_well_known::GCPoolAlloc); + bigAllocFunc = getOrDeclare(jl_well_known::GCBigAlloc); + + GlobalValue *functionList[] = {queueRootFunc, poolAllocFunc, bigAllocFunc}; + unsigned j = 0; + for (unsigned i = 0; i < sizeof(functionList) / sizeof(void*); i++) { + if (!functionList[i]) + continue; + if (i != j) + functionList[j] = functionList[i]; + j++; + } + if (j != 0) + appendToCompilerUsed(M, ArrayRef(functionList, j)); + return true; +} + +bool FinalLowerGC::doFinalization(Module &M) +{ + auto used = M.getGlobalVariable("llvm.compiler.used"); + if (!used) + return false; + GlobalValue *functionList[] = {queueRootFunc, poolAllocFunc, bigAllocFunc}; + SmallPtrSet InitAsSet( + functionList, + functionList + sizeof(functionList) / sizeof(void*)); + bool changed = false; + SmallVector init; + ConstantArray *CA = dyn_cast(used->getInitializer()); + for (auto &Op : CA->operands()) { + Constant *C = cast_or_null(Op); + if (InitAsSet.count(C->stripPointerCasts())) { + changed = true; + continue; + } + init.push_back(C); + } + if (!changed) + return false; + used->eraseFromParent(); + if (init.empty()) + return true; + ArrayType *ATy = ArrayType::get(T_pint8, init.size()); + used = new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, + ConstantArray::get(ATy, init), "llvm.compiler.used"); + used->setSection("llvm.metadata"); + return true; +} + +template +static void replaceInstruction( + Instruction *oldInstruction, + Value *newInstruction, + TIterator &it) +{ + if (newInstruction != oldInstruction) { + oldInstruction->replaceAllUsesWith(newInstruction); + it = oldInstruction->eraseFromParent(); + } + else { + ++it; + } +} + +bool FinalLowerGC::runOnFunction(Function &F) +{ + LLVM_DEBUG(dbgs() << "FINAL GC LOWERING: Processing function " << F.getName() << "\n"); + // Check availability of functions again since they might have been deleted. + initFunctions(*F.getParent()); + if (!ptls_getter) + return true; + + // Look for a call to 'julia.ptls_states'. + ptlsStates = getPtls(F); + if (!ptlsStates) + return true; + + // Acquire intrinsic functions. + auto newGCFrameFunc = getOrNull(jl_intrinsics::newGCFrame); + auto pushGCFrameFunc = getOrNull(jl_intrinsics::pushGCFrame); + auto popGCFrameFunc = getOrNull(jl_intrinsics::popGCFrame); + auto getGCFrameSlotFunc = getOrNull(jl_intrinsics::getGCFrameSlot); + auto GCAllocBytesFunc = getOrNull(jl_intrinsics::GCAllocBytes); + auto queueGCRootFunc = getOrNull(jl_intrinsics::queueGCRoot); + + // Lower all calls to supported intrinsics. + for (BasicBlock &BB : F) { + for (auto it = BB.begin(); it != BB.end();) { + auto *CI = dyn_cast(&*it); + if (!CI) { + ++it; + continue; + } + + auto callee = CI->getCalledValue(); + + if (callee == newGCFrameFunc) { + replaceInstruction(CI, lowerNewGCFrame(CI, F), it); + } + else if (callee == pushGCFrameFunc) { + lowerPushGCFrame(CI, F); + it = CI->eraseFromParent(); + } + else if (callee == popGCFrameFunc) { + lowerPopGCFrame(CI, F); + it = CI->eraseFromParent(); + } + else if (callee == getGCFrameSlotFunc) { + replaceInstruction(CI, lowerGetGCFrameSlot(CI, F), it); + } + else if (callee == GCAllocBytesFunc) { + replaceInstruction(CI, lowerGCAllocBytes(CI, F), it); + } + else if (callee == queueGCRootFunc) { + replaceInstruction(CI, lowerQueueGCRoot(CI, F), it); + } + else { + ++it; + } + } + } + + return true; +} + +char FinalLowerGC::ID = 0; +static RegisterPass X("FinalLowerGC", "Final GC intrinsic lowering pass", false, false); + +Pass *createFinalLowerGCPass() +{ + return new FinalLowerGC(); +} + +extern "C" JL_DLLEXPORT void LLVMExtraAddFinalLowerGCPass(LLVMPassManagerRef PM) +{ + unwrap(PM)->add(createFinalLowerGCPass()); +} diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 05ce1f12d1190..185ceae9dd706 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -30,6 +30,7 @@ #include "julia.h" #include "julia_internal.h" #include "julia_assert.h" +#include "llvm-pass-helpers.h" #define DEBUG_TYPE "late_lower_gcroot" #if JL_LLVM_VERSION < 70000 @@ -304,17 +305,11 @@ namespace llvm { void initializeLateLowerGCFramePass(PassRegistry &Registry); } -extern std::pair tbaa_make_child(const char *name, MDNode *parent=nullptr, bool isConstant=false); -struct LateLowerGCFrame: public FunctionPass { +struct LateLowerGCFrame: public FunctionPass, private JuliaPassContext { static char ID; LateLowerGCFrame() : FunctionPass(ID) { llvm::initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); - tbaa_gcframe = tbaa_make_child("jtbaa_gcframe").first; - MDNode *tbaa_data; - MDNode *tbaa_data_scalar; - std::tie(tbaa_data, tbaa_data_scalar) = tbaa_make_child("jtbaa_data"); - tbaa_tag = tbaa_make_child("jtbaa_tag", tbaa_data_scalar).first; } protected: @@ -326,28 +321,6 @@ struct LateLowerGCFrame: public FunctionPass { } private: - Type *T_prjlvalue; - Type *T_ppjlvalue; - Type *T_size; - Type *T_int8; - Type *T_int32; - Type *T_pint8; - Type *T_pjlvalue; - Type *T_pjlvalue_der; - Type *T_ppjlvalue_der; - MDNode *tbaa_gcframe; - MDNode *tbaa_tag; - Function *ptls_getter; - Function *gc_flush_func; - Function *gc_preserve_begin_func; - Function *gc_preserve_end_func; - Function *pointer_from_objref_func; - Function *alloc_obj_func; - Function *typeof_func; - Function *write_barrier_func; - Function *queueroot_func; - Function *pool_alloc_func; - Function *big_alloc_func; CallInst *ptlsStates; void MaybeNoteDef(State &S, BBState &BBS, Value *Def, const std::vector &SafepointsSoFar, SmallVector &&RefinedPtr = SmallVector()); @@ -369,17 +342,12 @@ struct LateLowerGCFrame: public FunctionPass { State LocalScan(Function &F); void ComputeLiveness(State &S); void ComputeLiveSets(State &S); - void PushGCFrame(AllocaInst *gcframe, unsigned NRoots, Instruction *InsertAfter); - void PopGCFrame(AllocaInst *gcframe, Instruction *InsertBefore); std::vector ColorRoots(const State &S); void PlaceGCFrameStore(State &S, unsigned R, unsigned MinColorRoot, const std::vector &Colors, Value *GCFrame, Instruction *InsertionPoint); void PlaceGCFrameStores(State &S, unsigned MinColorRoot, const std::vector &Colors, Value *GCFrame); void PlaceRootsAndUpdateCalls(std::vector &Colors, State &S, std::map>); bool doInitialization(Module &M) override; - void reinitFunctions(Module &M); - bool doFinalization(Module &) override; bool runOnFunction(Function &F) override; - Instruction *get_pgcstack(Instruction *ptlsStates); bool CleanupIR(Function &F, State *S=nullptr); void NoteUseChain(State &S, BBState &BBS, User *TheUser); SmallVector GetPHIRefinements(PHINode *phi, State &S); @@ -1619,44 +1587,6 @@ std::vector LateLowerGCFrame::ColorRoots(const State &S) { return Colors; } -Instruction *LateLowerGCFrame::get_pgcstack(Instruction *ptlsStates) -{ - Constant *offset = ConstantInt::getSigned(T_int32, offsetof(jl_tls_states_t, pgcstack) / sizeof(void*)); - return GetElementPtrInst::Create(nullptr, - ptlsStates, - ArrayRef(offset), - "jl_pgcstack"); -} - -void LateLowerGCFrame::PushGCFrame(AllocaInst *gcframe, unsigned NRoots, Instruction *InsertAfter) { - IRBuilder<> builder(gcframe->getContext()); - builder.SetInsertPoint(&*(++BasicBlock::iterator(InsertAfter))); - Instruction *inst = - builder.CreateStore(ConstantInt::get(T_size, NRoots << 1), - builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_size->getPointerTo())); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - Value *pgcstack = builder.Insert(get_pgcstack(ptlsStates)); - inst = builder.CreateStore(builder.CreateLoad(pgcstack), - builder.CreatePointerCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(T_ppjlvalue,0))); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - builder.CreateStore(gcframe, builder.CreateBitCast(pgcstack, - PointerType::get(PointerType::get(T_prjlvalue, 0), 0))); -} - -void LateLowerGCFrame::PopGCFrame(AllocaInst *gcframe, Instruction *InsertBefore) { - IRBuilder<> builder(InsertBefore->getContext()); - builder.SetInsertPoint(InsertBefore); // set insert *before* Ret - Instruction *gcpop = - (Instruction*)builder.CreateConstGEP1_32(gcframe, 1); - Instruction *inst = builder.CreateLoad(gcpop); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - inst = builder.CreateStore(inst, - builder.CreateBitCast( - builder.Insert(get_pgcstack(ptlsStates)), - PointerType::get(T_prjlvalue, 0))); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); -} - // Size of T is assumed to be `sizeof(void*)` Value *LateLowerGCFrame::EmitTagPtr(IRBuilder<> &builder, Type *T, Value *V) { @@ -1755,30 +1685,36 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) { UpdatePtrNumbering(CI, ASCI, S); } else if (alloc_obj_func && callee == alloc_obj_func) { assert(CI->getNumArgOperands() == 3); - auto sz = (size_t)cast(CI->getArgOperand(1))->getZExtValue(); - // This is strongly architecture and OS dependent - int osize; - int offset = jl_gc_classify_pools(sz, &osize); + + // Initialize an IR builder. IRBuilder<> builder(CI); builder.SetCurrentDebugLocation(CI->getDebugLoc()); - auto ptls = CI->getArgOperand(0); - CallInst *newI; - if (offset < 0) { - newI = builder.CreateCall(big_alloc_func, - {ptls, ConstantInt::get(T_size, - sz + sizeof(void*))}); - } - else { - auto pool_offs = ConstantInt::get(T_int32, offset); - auto pool_osize = ConstantInt::get(T_int32, osize); - newI = builder.CreateCall(pool_alloc_func, {ptls, pool_offs, pool_osize}); - } - newI->setAttributes(newI->getCalledFunction()->getAttributes()); + + // Create a call to the `julia.gc_alloc_bytes` intrinsic, which is like + // `julia.gc_alloc_obj` except it doesn't set the tag. + auto allocBytesIntrinsic = getOrDeclare(jl_intrinsics::GCAllocBytes); + auto newI = builder.CreateCall( + allocBytesIntrinsic, + { + CI->getArgOperand(0), + builder.CreateIntCast( + CI->getArgOperand(1), + allocBytesIntrinsic->getFunctionType()->getParamType(1), + false) + }); newI->takeName(CI); - auto store = builder.CreateStore(CI->getArgOperand(2), - EmitTagPtr(builder, T_prjlvalue, newI)); + + // Set the tag. + auto store = builder.CreateStore( + CI->getArgOperand(2), + EmitTagPtr(builder, T_prjlvalue, newI)); store->setMetadata(LLVMContext::MD_tbaa, tbaa_tag); + + // Replace uses of the call to `julia.gc_alloc_obj` with the call to + // `julia.gc_alloc_bytes`. CI->replaceAllUsesWith(newI); + + // Update the pointer numbering. UpdatePtrNumbering(CI, newI, S); } else if (typeof_func && callee == typeof_func) { assert(CI->getNumArgOperands() == 1); @@ -1887,7 +1823,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) { auto trigTerm = SplitBlockAndInsertIfThen(chldNotMarked, mayTrigTerm, false, MDB.createBranchWeights(Weights)); builder.SetInsertPoint(trigTerm); - builder.CreateCall(queueroot_func, parent); + builder.CreateCall(getOrDeclare(jl_intrinsics::queueGCRoot), parent); CI->eraseFromParent(); } if (maxframeargs == 0 && Frame) { @@ -1938,18 +1874,21 @@ void LateLowerGCFrame::PlaceGCFrameStore(State &S, unsigned R, unsigned MinColor const std::vector &Colors, Value *GCFrame, Instruction *InsertionPoint) { Value *Val = GetPtrForNumber(S, R, InsertionPoint); - Value *args[1] = { - ConstantInt::get(T_int32, Colors[R]+MinColorRoot) - }; - GetElementPtrInst *gep = GetElementPtrInst::Create(T_prjlvalue, GCFrame, makeArrayRef(args)); - gep->insertBefore(InsertionPoint); + + // Get the slot address. + auto slotAddress = CallInst::Create( + getOrDeclare(jl_intrinsics::getGCFrameSlot), + {GCFrame, ConstantInt::get(T_int32, Colors[R] + MinColorRoot)}); + + slotAddress->insertBefore(InsertionPoint); + Val = MaybeExtractUnion(std::make_pair(Val, -1), InsertionPoint); // Pointee types don't have semantics, so the optimizer is // free to rewrite them if convenient. We need to change // it back here for the store. if (Val->getType() != T_prjlvalue) Val = new BitCastInst(Val, T_prjlvalue, "", InsertionPoint); - new StoreInst(Val, gep, InsertionPoint); + new StoreInst(Val, slotAddress, InsertionPoint); } void LateLowerGCFrame::PlaceGCFrameStores(State &S, unsigned MinColorRoot, @@ -1986,43 +1925,28 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector &Colors, State // Insert instructions for the actual gc frame if (MaxColor != -1 || S.Allocas.size() != 0) { unsigned NRoots = MaxColor + 1 + S.Allocas.size(); - // Create GC Frame - AllocaInst *gcframe = new AllocaInst(T_prjlvalue, 0, - ConstantInt::get(T_int32, NRoots + 2), "gcframe"); + // Create and push a GC frame. + auto gcframe = CallInst::Create( + getOrDeclare(jl_intrinsics::newGCFrame), + {ConstantInt::get(T_int32, NRoots)}, + "gcframe"); gcframe->insertBefore(&*F->getEntryBlock().begin()); - // Zero out gcframe - BitCastInst *tempSlot_i8 = new BitCastInst(gcframe, Type::getInt8PtrTy(F->getContext()), ""); - tempSlot_i8->insertAfter(gcframe); - Type *argsT[2] = {tempSlot_i8->getType(), T_int32}; - Function *memset = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memset, makeArrayRef(argsT)); -#if JL_LLVM_VERSION >= 70000 - Value *args[4] = { - tempSlot_i8, // dest - ConstantInt::get(Type::getInt8Ty(F->getContext()), 0), // val - ConstantInt::get(T_int32, sizeof(jl_value_t*)*(NRoots+2)), // len - ConstantInt::get(Type::getInt1Ty(F->getContext()), 0)}; // volatile -#else - Value *args[5] = { - tempSlot_i8, // dest - ConstantInt::get(Type::getInt8Ty(F->getContext()), 0), // val - ConstantInt::get(T_int32, sizeof(jl_value_t*)*(NRoots+2)), // len - ConstantInt::get(T_int32, 0), // align - ConstantInt::get(Type::getInt1Ty(F->getContext()), 0)}; // volatile -#endif - CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); - zeroing->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - zeroing->insertAfter(tempSlot_i8); - // Push GC Frame - PushGCFrame(gcframe, NRoots, ptlsStates); + + auto pushGcframe = CallInst::Create( + getOrDeclare(jl_intrinsics::pushGCFrame), + {gcframe, ConstantInt::get(T_int32, NRoots)}); + pushGcframe->insertAfter(ptlsStates); + // Replace Allocas - unsigned AllocaSlot = 2; + unsigned AllocaSlot = 0; for (AllocaInst *AI : S.Allocas) { - Value *args[1] = { - ConstantInt::get(T_int32, AllocaSlot++) - }; - GetElementPtrInst *gep = GetElementPtrInst::Create(T_prjlvalue, gcframe, makeArrayRef(args)); - gep->insertAfter(gcframe); - gep->takeName(AI); + // Pick a slot for the alloca. + auto slotAddress = CallInst::Create( + getOrDeclare(jl_intrinsics::getGCFrameSlot), + {gcframe, ConstantInt::get(T_int32, AllocaSlot++)}); + slotAddress->insertAfter(gcframe); + slotAddress->takeName(AI); + // Check for lifetime intrinsics on this alloca, we can't keep them // because we're changing the semantics std::vector ToDelete; @@ -2035,7 +1959,7 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector &Colors, State }, AI); for (CallInst *II : ToDelete) II->eraseFromParent(); - AI->replaceAllUsesWith(gep); + AI->replaceAllUsesWith(slotAddress); AI->eraseFromParent(); } unsigned MinColorRoot = AllocaSlot; @@ -2044,154 +1968,32 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector &Colors, State // Insert GCFrame pops for(Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { if (isa(I->getTerminator())) { - PopGCFrame(gcframe, I->getTerminator()); + auto popGcframe = CallInst::Create( + getOrDeclare(jl_intrinsics::popGCFrame), + {gcframe}); + popGcframe->insertBefore(I->getTerminator()); } } } } -void LateLowerGCFrame::reinitFunctions(Module &M) { - ptls_getter = M.getFunction("julia.ptls_states"); - gc_flush_func = M.getFunction("julia.gcroot_flush"); - gc_preserve_begin_func = M.getFunction("llvm.julia.gc_preserve_begin"); - gc_preserve_end_func = M.getFunction("llvm.julia.gc_preserve_end"); - pointer_from_objref_func = M.getFunction("julia.pointer_from_objref"); - typeof_func = M.getFunction("julia.typeof"); - write_barrier_func = M.getFunction("julia.write_barrier"); - alloc_obj_func = M.getFunction("julia.gc_alloc_obj"); -} - bool LateLowerGCFrame::doInitialization(Module &M) { - ptls_getter = M.getFunction("julia.ptls_states"); - auto &ctx = M.getContext(); - T_size = M.getDataLayout().getIntPtrType(ctx); - T_int8 = Type::getInt8Ty(ctx); - T_pint8 = PointerType::get(T_int8, 0); - T_int32 = Type::getInt32Ty(ctx); - if ((write_barrier_func = M.getFunction("julia.write_barrier"))) { - T_prjlvalue = write_barrier_func->getFunctionType()->getParamType(0); - if (!(queueroot_func = M.getFunction("jl_gc_queue_root"))) { - queueroot_func = Function::Create(FunctionType::get(Type::getVoidTy(ctx), - {T_prjlvalue}, false), - Function::ExternalLinkage, "jl_gc_queue_root", &M); - queueroot_func->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - } - else { - queueroot_func = nullptr; - } - pool_alloc_func = nullptr; - big_alloc_func = nullptr; - if ((alloc_obj_func = M.getFunction("julia.gc_alloc_obj"))) { - T_prjlvalue = alloc_obj_func->getReturnType(); - if (!(pool_alloc_func = M.getFunction("jl_gc_pool_alloc"))) { - std::vector args(0); - args.push_back(T_pint8); - args.push_back(T_int32); - args.push_back(T_int32); - pool_alloc_func = Function::Create(FunctionType::get(T_prjlvalue, args, false), - Function::ExternalLinkage, "jl_gc_pool_alloc", &M); - pool_alloc_func->setAttributes(AttributeList::get(M.getContext(), - alloc_obj_func->getAttributes().getFnAttributes(), - alloc_obj_func->getAttributes().getRetAttributes(), - None)); - } - if (!(big_alloc_func = M.getFunction("jl_gc_big_alloc"))) { - std::vector args(0); - args.push_back(T_pint8); - args.push_back(T_size); - big_alloc_func = Function::Create(FunctionType::get(T_prjlvalue, args, false), - Function::ExternalLinkage, "jl_gc_big_alloc", &M); - big_alloc_func->setAttributes(AttributeList::get(M.getContext(), - alloc_obj_func->getAttributes().getFnAttributes(), - alloc_obj_func->getAttributes().getRetAttributes(), - None)); - } - auto T_jlvalue = cast(T_prjlvalue)->getElementType(); - T_pjlvalue = PointerType::get(T_jlvalue, 0); - T_ppjlvalue = PointerType::get(T_pjlvalue, 0); - T_pjlvalue_der = PointerType::get(T_jlvalue, AddressSpace::Derived); - T_ppjlvalue_der = PointerType::get(T_prjlvalue, AddressSpace::Derived); - } - else if (ptls_getter) { - auto functype = ptls_getter->getFunctionType(); - T_ppjlvalue = cast(functype->getReturnType())->getElementType(); - T_pjlvalue = cast(T_ppjlvalue)->getElementType(); - auto T_jlvalue = cast(T_pjlvalue)->getElementType(); - T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked); - T_pjlvalue_der = PointerType::get(T_jlvalue, AddressSpace::Derived); - T_ppjlvalue_der = PointerType::get(T_prjlvalue, AddressSpace::Derived); - } - else { - T_ppjlvalue = nullptr; - T_prjlvalue = nullptr; - T_pjlvalue = nullptr; - T_pjlvalue_der = nullptr; - T_ppjlvalue_der = nullptr; - } - GlobalValue *function_list[] = {queueroot_func, pool_alloc_func, big_alloc_func}; - unsigned j = 0; - for (unsigned i = 0; i < sizeof(function_list) / sizeof(void*); i++) { - if (!function_list[i]) - continue; - if (i != j) - function_list[j] = function_list[i]; - j++; - } - if (j != 0) - appendToCompilerUsed(M, ArrayRef(function_list, j)); - return true; -} - -bool LateLowerGCFrame::doFinalization(Module &M) -{ - auto used = M.getGlobalVariable("llvm.compiler.used"); - if (!used) - return false; - GlobalValue *function_list[] = {queueroot_func, pool_alloc_func, big_alloc_func}; - SmallPtrSet InitAsSet(function_list, - function_list + sizeof(function_list) / sizeof(void*)); - bool changed = false; - SmallVector Init; - ConstantArray *CA = dyn_cast(used->getInitializer()); - for (auto &Op : CA->operands()) { - Constant *C = cast_or_null(Op); - if (InitAsSet.count(C->stripPointerCasts())) { - changed = true; - continue; - } - Init.push_back(C); - } - if (!changed) - return false; - used->eraseFromParent(); - if (Init.empty()) - return true; - ArrayType *ATy = ArrayType::get(T_pint8, Init.size()); - used = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, - ConstantArray::get(ATy, Init), "llvm.compiler.used"); - used->setSection("llvm.metadata"); + // Initialize platform-agnostic references. + initAll(M); return true; } bool LateLowerGCFrame::runOnFunction(Function &F) { LLVM_DEBUG(dbgs() << "GC ROOT PLACEMENT: Processing function " << F.getName() << "\n"); // Check availability of functions again since they might have been deleted. - reinitFunctions(*F.getParent()); + initFunctions(*F.getParent()); if (!ptls_getter) return CleanupIR(F); - ptlsStates = nullptr; - for (auto I = F.getEntryBlock().begin(), E = F.getEntryBlock().end(); - ptls_getter && I != E; ++I) { - if (CallInst *callInst = dyn_cast(&*I)) { - if (callInst->getCalledValue() == ptls_getter) { - ptlsStates = callInst; - break; - } - } - } + + ptlsStates = getPtls(F); if (!ptlsStates) return CleanupIR(F); + State S = LocalScan(F); ComputeLiveness(S); std::vector Colors = ColorRoots(S); diff --git a/src/llvm-pass-helpers.cpp b/src/llvm-pass-helpers.cpp new file mode 100644 index 0000000000000..7efb5394c968a --- /dev/null +++ b/src/llvm-pass-helpers.cpp @@ -0,0 +1,274 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license +// +// This file implements common functionality that is useful for the late GC frame +// lowering and final GC intrinsic lowering passes. See the corresponding header +// for docs. + +#include +#include +#include +#include + +#include + +#include "llvm-version.h" +#include "codegen_shared.h" +#include "julia_assert.h" +#include "llvm-pass-helpers.h" + +using namespace llvm; + +extern std::pair tbaa_make_child(const char *name, MDNode *parent=nullptr, bool isConstant=false); + +JuliaPassContext::JuliaPassContext() + : T_size(nullptr), T_int8(nullptr), T_int32(nullptr), + T_pint8(nullptr), T_jlvalue(nullptr), T_prjlvalue(nullptr), + T_ppjlvalue(nullptr), T_pjlvalue(nullptr), T_pjlvalue_der(nullptr), + T_ppjlvalue_der(nullptr), ptls_getter(nullptr), gc_flush_func(nullptr), + gc_preserve_begin_func(nullptr), gc_preserve_end_func(nullptr), + pointer_from_objref_func(nullptr), alloc_obj_func(nullptr), + typeof_func(nullptr), write_barrier_func(nullptr), module(nullptr) +{ + tbaa_gcframe = tbaa_make_child("jtbaa_gcframe").first; + MDNode *tbaa_data; + MDNode *tbaa_data_scalar; + std::tie(tbaa_data, tbaa_data_scalar) = tbaa_make_child("jtbaa_data"); + tbaa_tag = tbaa_make_child("jtbaa_tag", tbaa_data_scalar).first; +} + +void JuliaPassContext::initFunctions(Module &M) +{ + module = &M; + + ptls_getter = M.getFunction("julia.ptls_states"); + gc_flush_func = M.getFunction("julia.gcroot_flush"); + gc_preserve_begin_func = M.getFunction("llvm.julia.gc_preserve_begin"); + gc_preserve_end_func = M.getFunction("llvm.julia.gc_preserve_end"); + pointer_from_objref_func = M.getFunction("julia.pointer_from_objref"); + typeof_func = M.getFunction("julia.typeof"); + write_barrier_func = M.getFunction("julia.write_barrier"); + alloc_obj_func = M.getFunction("julia.gc_alloc_obj"); +} + +void JuliaPassContext::initAll(Module &M) +{ + // First initialize the functions. + initFunctions(M); + + // Then initialize types and metadata nodes. + auto &ctx = M.getContext(); + T_size = M.getDataLayout().getIntPtrType(ctx); + T_int8 = Type::getInt8Ty(ctx); + T_pint8 = PointerType::get(T_int8, 0); + T_int32 = Type::getInt32Ty(ctx); + + // Find 'jl_value_t' by searching through the module's + // identified struct types. This is a much more robust way + // to find 'jl_value_t' than an ad-hoc search through + // intrinsics that may or may not be defined in the module. + T_jlvalue = nullptr; + for (auto type : M.getIdentifiedStructTypes()) { + if (type->hasName() && type->getName() == "jl_value_t") { + T_jlvalue = type; + break; + } + } + + // If 'jl_value_t' doesn't exist yet then we'll just define it. + if (!T_jlvalue) { + T_jlvalue = StructType::create(ctx, "jl_value_t"); + } + + // Construct derived types. + T_pjlvalue = PointerType::get(T_jlvalue, 0); + T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked); + T_ppjlvalue = PointerType::get(T_pjlvalue, 0); + T_pjlvalue_der = PointerType::get(T_jlvalue, AddressSpace::Derived); + T_ppjlvalue_der = PointerType::get(T_prjlvalue, AddressSpace::Derived); +} + +llvm::CallInst *JuliaPassContext::getPtls(llvm::Function &F) const +{ + for (auto I = F.getEntryBlock().begin(), E = F.getEntryBlock().end(); + ptls_getter && I != E; ++I) { + if (CallInst *callInst = dyn_cast(&*I)) { + if (callInst->getCalledValue() == ptls_getter) { + return callInst; + } + } + } + return nullptr; +} + +llvm::Function *JuliaPassContext::getOrNull( + const jl_intrinsics::IntrinsicDescription &desc) const +{ + return module->getFunction(desc.name); +} + +llvm::Function *JuliaPassContext::getOrDeclare( + const jl_intrinsics::IntrinsicDescription &desc) +{ + auto local = getOrNull(desc); + if (local) { + // If the function exists already, then we'll + // just return it. + return local; + } + else { + // Otherwise, we'll declare it and add it to the module. + // Declare the function. + auto func = desc.declare(*this); + // Add it to the function list. + module->getFunctionList().push_back(func); + // Return the newly created function. + return func; + } +} + +namespace jl_intrinsics { + static const char *GET_GC_FRAME_SLOT_NAME = "julia.get_gc_frame_slot"; + static const char *GC_ALLOC_BYTES_NAME = "julia.gc_alloc_bytes"; + static const char *NEW_GC_FRAME_NAME = "julia.new_gc_frame"; + static const char *PUSH_GC_FRAME_NAME = "julia.push_gc_frame"; + static const char *POP_GC_FRAME_NAME = "julia.pop_gc_frame"; + static const char *QUEUE_GC_ROOT_NAME = "julia.queue_gc_root"; + + // Annotates a function with attributes suitable for GC allocation + // functions. Specifically, the return value is marked noalias and nonnull. + // The allocation size is set to the first argument. + static Function *addGCAllocAttributes(Function *target, LLVMContext &context) + { + target->addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); + target->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); + target->addFnAttr(Attribute::getWithAllocSizeArgs(context, 1, None)); // returns %1 bytes + return target; + } + + const IntrinsicDescription getGCFrameSlot( + GET_GC_FRAME_SLOT_NAME, + [](const JuliaPassContext &context) { + return Function::Create( + FunctionType::get( + PointerType::get(context.T_prjlvalue, 0), + {PointerType::get(context.T_prjlvalue, 0), context.T_int32}, + false), + Function::ExternalLinkage, + GET_GC_FRAME_SLOT_NAME); + }); + + const IntrinsicDescription GCAllocBytes( + GC_ALLOC_BYTES_NAME, + [](const JuliaPassContext &context) { + auto intrinsic = Function::Create( + FunctionType::get( + context.T_prjlvalue, + { context.T_pint8, context.T_size }, + false), + Function::ExternalLinkage, + GC_ALLOC_BYTES_NAME); + + return addGCAllocAttributes(intrinsic, context.getLLVMContext()); + }); + + const IntrinsicDescription newGCFrame( + NEW_GC_FRAME_NAME, + [](const JuliaPassContext &context) { + auto intrinsic = Function::Create( + FunctionType::get(PointerType::get(context.T_prjlvalue, 0), {context.T_int32}, false), + Function::ExternalLinkage, + NEW_GC_FRAME_NAME); + intrinsic->addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); + intrinsic->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); + + return intrinsic; + }); + + const IntrinsicDescription pushGCFrame( + PUSH_GC_FRAME_NAME, + [](const JuliaPassContext &context) { + return Function::Create( + FunctionType::get( + Type::getVoidTy(context.getLLVMContext()), + {PointerType::get(context.T_prjlvalue, 0), context.T_int32}, + false), + Function::ExternalLinkage, + PUSH_GC_FRAME_NAME); + }); + + const IntrinsicDescription popGCFrame( + POP_GC_FRAME_NAME, + [](const JuliaPassContext &context) { + return Function::Create( + FunctionType::get( + Type::getVoidTy(context.getLLVMContext()), + {PointerType::get(context.T_prjlvalue, 0)}, + false), + Function::ExternalLinkage, + POP_GC_FRAME_NAME); + }); + + const IntrinsicDescription queueGCRoot( + QUEUE_GC_ROOT_NAME, + [](const JuliaPassContext &context) { + auto intrinsic = Function::Create( + FunctionType::get( + Type::getVoidTy(context.getLLVMContext()), + { context.T_prjlvalue }, + false), + Function::ExternalLinkage, + QUEUE_GC_ROOT_NAME); + intrinsic->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); + return intrinsic; + }); +} + +namespace jl_well_known { + static const char *GC_BIG_ALLOC_NAME = "jl_gc_big_alloc"; + static const char *GC_POOL_ALLOC_NAME = "jl_gc_pool_alloc"; + static const char *GC_QUEUE_ROOT_NAME = "jl_gc_queue_root"; + + using jl_intrinsics::addGCAllocAttributes; + + const WellKnownFunctionDescription GCBigAlloc( + GC_BIG_ALLOC_NAME, + [](const JuliaPassContext &context) { + auto bigAllocFunc = Function::Create( + FunctionType::get( + context.T_prjlvalue, + { context.T_pint8, context.T_size }, + false), + Function::ExternalLinkage, + GC_BIG_ALLOC_NAME); + + return addGCAllocAttributes(bigAllocFunc, context.getLLVMContext()); + }); + + const WellKnownFunctionDescription GCPoolAlloc( + GC_POOL_ALLOC_NAME, + [](const JuliaPassContext &context) { + auto poolAllocFunc = Function::Create( + FunctionType::get( + context.T_prjlvalue, + { context.T_pint8, context.T_int32, context.T_int32 }, + false), + Function::ExternalLinkage, + GC_POOL_ALLOC_NAME); + + return addGCAllocAttributes(poolAllocFunc, context.getLLVMContext()); + }); + + const WellKnownFunctionDescription GCQueueRoot( + GC_QUEUE_ROOT_NAME, + [](const JuliaPassContext &context) { + auto func = Function::Create( + FunctionType::get( + Type::getVoidTy(context.getLLVMContext()), + { context.T_prjlvalue }, + false), + Function::ExternalLinkage, + GC_QUEUE_ROOT_NAME); + func->addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); + return func; + }); +} diff --git a/src/llvm-pass-helpers.h b/src/llvm-pass-helpers.h new file mode 100644 index 0000000000000..71cab27e76ceb --- /dev/null +++ b/src/llvm-pass-helpers.h @@ -0,0 +1,157 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#ifndef LLVM_PASS_HELPERS_H +#define LLVM_PASS_HELPERS_H + +#include +#include +#include +#include +#include +#include +#include + +struct JuliaPassContext; + +// A namespace for Julia intrinsic descriptions. +namespace jl_intrinsics { + // A description of an intrinsic that can be used to find existing + // intrinsics and declare new intrinsics if necessary. + struct IntrinsicDescription final { + // The type of function that declares an intrinsic. + typedef llvm::Function *(*DeclarationFunction)(const JuliaPassContext&); + + // Creates an intrinsic description with a particular + // name and declaration function. + IntrinsicDescription( + const llvm::StringRef &name, + const DeclarationFunction &declare) + : name(name), declare(declare) + { } + + // The intrinsic's name. + llvm::StringRef name; + // A function that declares the intrinsic in a module. + DeclarationFunction declare; + }; +} + +// A data structure that can read Julia-specific intrinsics +// from modules or add them if they're not available yet. +// Mainly useful for building Julia-specific LLVM passes. +struct JuliaPassContext { + // Standard types. + llvm::Type *T_size; + llvm::Type *T_int8; + llvm::Type *T_int32; + llvm::PointerType *T_pint8; + + // Types derived from 'jl_value_t'. + llvm::Type *T_jlvalue; + llvm::PointerType *T_prjlvalue; + llvm::PointerType *T_ppjlvalue; + llvm::PointerType *T_pjlvalue; + llvm::PointerType *T_pjlvalue_der; + llvm::PointerType *T_ppjlvalue_der; + + // TBAA metadata nodes. + llvm::MDNode *tbaa_gcframe; + llvm::MDNode *tbaa_tag; + + // Intrinsics. + llvm::Function *ptls_getter; + llvm::Function *gc_flush_func; + llvm::Function *gc_preserve_begin_func; + llvm::Function *gc_preserve_end_func; + llvm::Function *pointer_from_objref_func; + llvm::Function *alloc_obj_func; + llvm::Function *typeof_func; + llvm::Function *write_barrier_func; + + // Creates a pass context. Type and function pointers + // are set to `nullptr`. Metadata nodes are initialized. + JuliaPassContext(); + + // Populates a pass context by inspecting a module. + // Also sets the current module to the given module. + void initAll(llvm::Module &M); + + // Initializes a pass context's functions only. + // Also sets the current module to the given module. + void initFunctions(llvm::Module &M); + + // Gets the LLVM context for this pass context. + llvm::LLVMContext &getLLVMContext() const + { + return module->getContext(); + } + + // Gets a call to the `julia.ptls_states` intrinisc in the entry + // point of the given function, if there exists such a call. + // Otherwise, `nullptr` is returned. + llvm::CallInst *getPtls(llvm::Function &F) const; + + // Gets the intrinsic or well-known function that conforms to + // the given description if it exists in the module. If not, + // `nullptr` is returned. + llvm::Function *getOrNull( + const jl_intrinsics::IntrinsicDescription &desc) const; + + // Gets the intrinsic or well-known function that conforms to + // the given description if it exists in the module. If not, + // declares the intrinsic or well-known function and adds it + // to the module. + llvm::Function *getOrDeclare( + const jl_intrinsics::IntrinsicDescription &desc); + +private: + llvm::Module *module; +}; + +namespace jl_intrinsics { + // `julia.get_gc_frame_slot`: an intrinsic that creates a + // pointer to a GC frame slot. + extern const IntrinsicDescription getGCFrameSlot; + + // `julia.gc_alloc_bytes`: an intrinsic that allocates + // the bytes for an object, but does not initialize the + // tag field. That is, its semantics and signature are + // the same as for `julia.gc_alloc_obj`, except that + // the object's tag field is neither initialized nor + // passed as an argument. + extern const IntrinsicDescription GCAllocBytes; + + // `julia.new_gc_frame`: an intrinsic that creates a new GC frame. + extern const IntrinsicDescription newGCFrame; + + // `julia.push_gc_frame`: an intrinsic that pushes a GC frame. + extern const IntrinsicDescription pushGCFrame; + + // `julia.pop_gc_frame`: an intrinsic that pops a GC frame. + extern const IntrinsicDescription popGCFrame; + + // `julia.queue_gc_root`: an intrinsic that queues a GC root. + extern const IntrinsicDescription queueGCRoot; +} + +// A namespace for well-known Julia runtime function descriptions. +namespace jl_well_known { + // A description of a well-known function that can be used to + // find existing declarations of that function and create new + // declarations if necessary. + // + // Aliased to `jl_intrinsics::IntrinsicDescription` because + // intrinsic descriptions are essentially the same thing. + typedef jl_intrinsics::IntrinsicDescription WellKnownFunctionDescription; + + // `jl_gc_big_alloc`: allocates bytes. + extern const WellKnownFunctionDescription GCBigAlloc; + + // `jl_gc_pool_alloc`: allocates bytes. + extern const WellKnownFunctionDescription GCPoolAlloc; + + // `jl_gc_queue_root`: queues a GC root. + extern const WellKnownFunctionDescription GCQueueRoot; +} + +#endif diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index 13563b2b73059..21b10ccd10249 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -1,4 +1,5 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license + #include "llvm-version.h" #define DEBUG_TYPE "lower_simd_loop" diff --git a/src/macroexpand.scm b/src/macroexpand.scm index e1d607885b10d..77d0fbb1781ae 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -414,6 +414,14 @@ (body (cadr e)) (m (caddr e))) (resolve-expansion-vars-with-new-env body env m parent-scope inarg #t))) + ((tuple) + (cons (car e) + (map (lambda (x) + (if (assignment? x) + `(= ,(unescape (cadr x)) + ,(resolve-expansion-vars-with-new-env x env m parent-scope inarg)) + (resolve-expansion-vars-with-new-env x env m parent-scope inarg))) + (cdr e)))) ;; todo: trycatch (else diff --git a/src/module.c b/src/module.c index ae7520e09830f..af8b5ce8d3f2c 100644 --- a/src/module.c +++ b/src/module.c @@ -500,6 +500,10 @@ JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT) { jl_binding_t *bp = jl_get_binding_wr(m, var, 1); + // In a release build, simply ignore conflicting assignments (for backwards compatibility). + // However, we want to start asserting that they do not occur, since that can cause `val` + // not to be rooted when the caller expected it to be. + assert(!bp->constp); if (!bp->constp) { bp->value = val; jl_gc_wb(m, val); @@ -509,6 +513,7 @@ JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *va JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT) { jl_binding_t *bp = jl_get_binding_wr(m, var, 1); + assert(!bp->constp); if (!bp->constp) { bp->value = val; bp->constp = 1; diff --git a/src/options.h b/src/options.h index 37b1a38401009..00e61d7b38fb7 100644 --- a/src/options.h +++ b/src/options.h @@ -113,11 +113,14 @@ #define JL_STACK_SIZE (2*1024*1024) #endif +// allow a suspended Task to restart on a different thread +//#define MIGRATE_TASKS + // threading options ---------------------------------------------------------- // controls for when threads sleep #define THREAD_SLEEP_THRESHOLD_NAME "JULIA_THREAD_SLEEP_THRESHOLD" -#define DEFAULT_THREAD_SLEEP_THRESHOLD 1e9 // cycles (1e9==1sec@1GHz) +#define DEFAULT_THREAD_SLEEP_THRESHOLD 4*1000*1000 // nanoseconds (4ms) // defaults for # threads #define NUM_THREADS_NAME "JULIA_NUM_THREADS" diff --git a/src/partr.c b/src/partr.c index c3bc397652bda..a64915bbca16f 100644 --- a/src/partr.c +++ b/src/partr.c @@ -14,7 +14,19 @@ extern "C" { #endif -#define JULIA_ENABLE_PARTR + +// thread sleep state + +static int16_t sleep_check_state; // status of the multi-queue. possible values: + +// no thread should be sleeping--there might be work in the multi-queue. +static const int16_t not_sleeping = 0; + +// it is acceptable for a thread to be sleeping if its sticky queue is empty. +// sleep_check_state == sleeping + 1 + tid means thread tid is checking the multi-queue +// to see if it is safe to transition to sleeping. +static const int16_t sleeping = 1; + #ifdef JULIA_ENABLE_THREADING @@ -34,10 +46,10 @@ typedef struct taskheap_tag { /* multiqueue parameters */ static const int16_t heap_d = 8; -static const int heap_c = 4; +static const int heap_c = 16; /* size of each heap */ -static const int tasks_per_heap = 8192; // TODO: this should be smaller by default, but growable! +static const int tasks_per_heap = 16384; // TODO: this should be smaller by default, but growable! /* the multiqueue's heaps */ static taskheap_t *heaps; @@ -46,13 +58,7 @@ static int16_t heap_p; /* unbias state for the RNG */ static uint64_t cong_unbias; -/* for thread sleeping */ -uv_mutex_t sleep_lock; -uv_cond_t sleep_alarm; - -/* multiq_init() - */ static inline void multiq_init(void) { heap_p = heap_c * jl_n_threads; @@ -67,8 +73,6 @@ static inline void multiq_init(void) } -/* sift_up() - */ static inline void sift_up(taskheap_t *heap, int16_t idx) { if (idx > 0) { @@ -83,8 +87,6 @@ static inline void sift_up(taskheap_t *heap, int16_t idx) } -/* sift_down() - */ static inline void sift_down(taskheap_t *heap, int16_t idx) { if (idx < heap->ntasks) { @@ -103,8 +105,6 @@ static inline void sift_down(taskheap_t *heap, int16_t idx) } -/* multiq_insert() - */ static inline int multiq_insert(jl_task_t *task, int16_t priority) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -117,7 +117,7 @@ static inline int multiq_insert(jl_task_t *task, int16_t priority) if (heaps[rn].ntasks >= tasks_per_heap) { jl_mutex_unlock_nogc(&heaps[rn].lock); - jl_error("multiq insertion failed, increase #tasks per heap"); + // multiq insertion failed, increase #tasks per heap return -1; } @@ -132,8 +132,6 @@ static inline int multiq_insert(jl_task_t *task, int16_t priority) } -/* multiq_deletemin() - */ static inline jl_task_t *multiq_deletemin(void) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -182,6 +180,63 @@ static inline jl_task_t *multiq_deletemin(void) } +void jl_gc_mark_enqueued_tasks(jl_gc_mark_cache_t *gc_cache, jl_gc_mark_sp_t *sp) +{ + int16_t i, j; + for (i = 0; i < heap_p; ++i) + for (j = 0; j < heaps[i].ntasks; ++j) + jl_gc_mark_queue_obj_explicit(gc_cache, sp, (jl_value_t *)heaps[i].tasks[j]); +} + + +static int multiq_check_empty(void) +{ + int16_t i; + for (i = 0; i < heap_p; ++i) { + if (heaps[i].ntasks != 0) + return 0; + } + return 1; +} + + +static int sleep_check_now(int16_t tid) +{ + while (1) { + int16_t state = jl_atomic_load(&sleep_check_state); + if (state > sleeping) { + // if some thread is already checking, the decision of that thread + // is correct for us also + do { + state = jl_atomic_load(&sleep_check_state); + } while (state > sleeping); + if (state == not_sleeping) + return 0; + } + else if (state == not_sleeping) { + int16_t checking_for_sleeping = sleeping + 1 + tid; + // transition from sleeping ==> checking + if (jl_atomic_bool_compare_exchange(&sleep_check_state, not_sleeping, + checking_for_sleeping)) { + if (multiq_check_empty()) { + // transition from checking ==> sleeping + if (jl_atomic_bool_compare_exchange(&sleep_check_state, checking_for_sleeping, + sleeping)) + return 1; + } + else { + // transition from checking ==> not_sleeping + jl_atomic_store(&sleep_check_state, not_sleeping); + return 0; + } + } + continue; + } + assert(state == sleeping); + return 1; + } +} + // parallel task runtime // --- @@ -192,9 +247,10 @@ void jl_init_threadinginfra(void) /* initialize the synchronization trees pool and the multiqueue */ multiq_init(); - /* initialize the sleep mechanism */ - uv_mutex_init(&sleep_lock); - uv_cond_init(&sleep_alarm); + jl_ptls_t ptls = jl_get_ptls_states(); + uv_mutex_init(&ptls->sleep_lock); + uv_cond_init(&ptls->wake_signal); + sleep_check_state = not_sleeping; } @@ -212,6 +268,12 @@ void jl_threadfun(void *arg) jl_init_root_task(stack_lo, stack_hi); jl_ptls_t ptls = jl_get_ptls_states(); + + // set up sleep mechanism for this thread + uv_mutex_init(&ptls->sleep_lock); + uv_cond_init(&ptls->wake_signal); + + // wait for all threads jl_gc_state_set(ptls, JL_GC_STATE_SAFE, 0); uv_barrier_wait(targ->barrier); @@ -223,28 +285,103 @@ void jl_threadfun(void *arg) jl_finish_task(jl_current_task, jl_nothing); // noreturn } -JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) + +// enqueue the specified task for execution +JL_DLLEXPORT int jl_enqueue_task(jl_task_t *task) { - jl_ptls_t ptls = jl_get_ptls_states(); - /* ensure thread tid is awake if necessary */ - if (ptls->tid != tid && !_threadedregion && tid != -1) { - uv_mutex_lock(&sleep_lock); - uv_cond_broadcast(&sleep_alarm); // TODO: make this uv_cond_signal / just wake up correct thread - uv_mutex_unlock(&sleep_lock); + if (multiq_insert(task, task->prio) == -1) + return 1; + return 0; +} + + +// sleep_check_after_threshold() -- if sleep_threshold ns have passed, return 1 +static int sleep_check_after_threshold(uint64_t *start_cycles) +{ + if (!(*start_cycles)) { + *start_cycles = jl_hrtime(); + return 0; } - if (_threadedregion && jl_uv_mutex.owner != jl_thread_self()) - jl_wake_libuv(); - else - uv_stop(jl_global_event_loop()); + uint64_t elapsed_cycles = jl_hrtime() - (*start_cycles); + if (elapsed_cycles >= DEFAULT_THREAD_SLEEP_THRESHOLD) { + *start_cycles = 0; + return 1; + } + return 0; } -// enqueue the specified task for execution -JL_DLLEXPORT void jl_enqueue_task(jl_task_t *task) +static void wake_thread(int16_t self, int16_t tid) { - multiq_insert(task, task->prio); + if (self != tid) { + jl_ptls_t other = jl_all_tls_states[tid]; + uv_mutex_lock(&other->sleep_lock); + uv_cond_signal(&other->wake_signal); + uv_mutex_unlock(&other->sleep_lock); + } } +#else // JULIA_ENABLE_THREADING + +static int sleep_check_now(int16_t tid) +{ + (void)tid; + return 1; +} + +static int sleep_check_after_threshold(uint64_t *start_cycles) +{ + (void)start_cycles; + return 1; +} + +#endif + +/* ensure thread tid is awake if necessary */ +JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) +{ + int16_t self = jl_get_ptls_states()->tid; + int16_t uvlock = jl_atomic_load_acquire(&jl_uv_mutex.owner); + if (tid == self) { + // we're already awake, but make sure we'll exit uv_run + if (uvlock == self) + uv_stop(jl_global_event_loop()); + } +#ifdef JULIA_ENABLE_THREADING + else { + // check if the other threads might be sleeping + if (jl_atomic_load_acquire(&sleep_check_state) != not_sleeping) { + if (tid == -1) { + // something added to the multi-queue: notify all threads + // in the future, we might want to instead wake some fraction of threads, + // and let each of those wake additional threads if they find work + int16_t state = jl_atomic_exchange(&sleep_check_state, not_sleeping); + if (state == sleeping) { + for (tid = 0; tid < jl_n_threads; tid++) + wake_thread(self, tid); + } + } + else { + // something added to the sticky-queue: notify that thread + wake_thread(self, tid); + } + // check if we need to notify uv_run too + if (uvlock != self) + jl_wake_libuv(); + } + } +#endif +} + + +JL_DLLEXPORT void jl_set_task_tid(jl_task_t *task, int tid) JL_NOTSAFEPOINT +{ + // Try to acquire the lock on this task. + // If this fails, we'll check for that error later (in jl_switchto). + if (jl_atomic_load_acquire(&task->tid) != tid) { + jl_atomic_compare_exchange(&task->tid, -1, tid); + } +} // get the next runnable task from the multiq static jl_task_t *get_next_task(jl_value_t *getsticky) @@ -252,20 +389,22 @@ static jl_task_t *get_next_task(jl_value_t *getsticky) jl_task_t *task = (jl_task_t*)jl_apply(&getsticky, 1); if (jl_typeis(task, jl_task_type)) { int self = jl_get_ptls_states()->tid; - if (jl_atomic_load_acquire(&task->tid) != self) { - jl_atomic_compare_exchange(&task->tid, -1, self); - } + jl_set_task_tid(task, self); return task; } +#ifdef JULIA_ENABLE_THREADING return multiq_deletemin(); +#else + return NULL; +#endif } +extern volatile unsigned _threadedregion; JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *getsticky) { jl_ptls_t ptls = jl_get_ptls_states(); - // spin briefly before blocking when the workqueue is empty - size_t spin_count = 0; + uint64_t start_cycles = 0; jl_task_t *task; while (1) { @@ -274,66 +413,96 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *getsticky) if (task) return task; - if (!_threadedregion) { - spin_count = 0; - if (ptls->tid == 0) { - if (jl_run_once(jl_global_event_loop()) == 0) { - task = get_next_task(getsticky); - if (task) - return task; -#ifdef _OS_WINDOWS_ - Sleep(INFINITE); -#else - pause(); +#ifdef JULIA_ENABLE_THREADING + jl_cpu_pause(); + if (!multiq_check_empty()) { + start_cycles = 0; + continue; + } #endif - } + + jl_cpu_pause(); + if (sleep_check_after_threshold(&start_cycles) || (!_threadedregion && ptls->tid == 0)) { + if (!sleep_check_now(ptls->tid)) + continue; + task = get_next_task(getsticky); + if (task) + return task; + // one thread should win this race and watch the event loop + // inside a threaded region, any thread can listen for IO messages, + // although none are allowed to create new ones + // outside of threaded regions, all IO is permitted, + // but only on thread 1 + int uvlock = 0; + if (_threadedregion) { + uvlock = jl_mutex_trylock(&jl_uv_mutex); } - else { - int sleepnow = 0; - uv_mutex_lock(&sleep_lock); - if (!_threadedregion) { - sleepnow = 1; + else if (ptls->tid == 0) { + uvlock = 1; + JL_UV_LOCK(); + } + if (uvlock) { + int active = 1; + if (jl_atomic_load(&jl_uv_n_waiters) != 0) { + // but if we won the race against someone who actually needs + // the lock to do real work, we need to let them have it instead + JL_UV_UNLOCK(); } else { - uv_mutex_unlock(&sleep_lock); + // otherwise, block until someone asks us for the lock + task = get_next_task(getsticky); + if (task) { + JL_UV_UNLOCK(); + return task; + } + uv_loop_t *loop = jl_global_event_loop(); + loop->stop_flag = 0; + active = uv_run(loop, UV_RUN_ONCE); + JL_UV_UNLOCK(); + // optimization: check again first if we added work for ourself + task = get_next_task(getsticky); + if (task) + return task; + // or someone else might have + if (jl_atomic_load(&sleep_check_state) != sleeping) { + start_cycles = 0; + continue; + } + // otherwise, we got a spurious wakeup since some other + // thread just wanted to steal libuv from us, + // just go right back to sleep on the other wake signal + // to let them take it from us without conflict } - if (sleepnow) { - int8_t gc_state = jl_gc_safe_enter(ptls); - uv_cond_wait(&sleep_alarm, &sleep_lock); - uv_mutex_unlock(&sleep_lock); - jl_gc_safe_leave(ptls, gc_state); + if (!_threadedregion && active && ptls->tid == 0) { + // thread 0 is the only thread permitted to run the event loop + // so it needs to stay alive + start_cycles = 0; + continue; } } - } - else { - if (++spin_count > 1000 && jl_atomic_load(&jl_uv_n_waiters) == 0 && jl_mutex_trylock(&jl_uv_mutex)) { + // the other threads will just wait for on signal to resume + int8_t gc_state = jl_gc_safe_enter(ptls); + uv_mutex_lock(&ptls->sleep_lock); + while (jl_atomic_load(&sleep_check_state) == sleeping) { task = get_next_task(getsticky); - if (task) { - JL_UV_UNLOCK(); - return task; - } - uv_loop_t *loop = jl_global_event_loop(); - loop->stop_flag = 0; - uv_run(loop, UV_RUN_ONCE); - JL_UV_UNLOCK(); - } - else { - jl_cpu_pause(); + if (task) + break; + uv_cond_wait(&ptls->wake_signal, &ptls->sleep_lock); } + uv_mutex_unlock(&ptls->sleep_lock); + jl_gc_safe_leave(ptls, gc_state); + start_cycles = 0; + if (task) + return task; + } + else { + // maybe check the kernel for new messages too + if (jl_atomic_load(&jl_uv_n_waiters) == 0) + jl_process_events(jl_global_event_loop()); } } } - -void jl_gc_mark_enqueued_tasks(jl_gc_mark_cache_t *gc_cache, jl_gc_mark_sp_t *sp) -{ - for (int16_t i = 0; i < heap_p; ++i) - for (int16_t j = 0; j < heaps[i].ntasks; ++j) - jl_gc_mark_queue_obj_explicit(gc_cache, sp, (jl_value_t *)heaps[i].tasks[j]); -} - -#endif // JULIA_ENABLE_THREADING - #ifdef __cplusplus } #endif diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 9376fd1b92aae..220dfed1b2d5d 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -272,7 +272,7 @@ jl_value_t *jl_get_cfunction_trampoline( // not found, allocate a new one size_t n = jl_svec_len(fill); - void **nval = (void**)malloc(sizeof(void**) * (n + 1)); + void **nval = (void**)malloc(sizeof(void*) * (n + 1)); nval[0] = (void*)fobj; jl_value_t *result; JL_TRY { diff --git a/src/staticdata.c b/src/staticdata.c index 26d2d693eaf7f..0d160ddba7410 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -985,7 +985,7 @@ static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t bas offset -= NBOX_C; if (offset < 256) return (uintptr_t)jl_box_uint8(offset); - offset -= 256; + // offset -= 256; assert(0 && "corrupt relocation item id"); case BuiltinFunctionRef: assert(offset < sizeof(id_to_fptrs) / sizeof(*id_to_fptrs) && "unknown function pointer ID"); diff --git a/src/subtype.c b/src/subtype.c index 07ce0b0cf710b..cf57373318046 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -188,15 +188,20 @@ static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) JL_N // quickly test that two types are identical static int obviously_egal(jl_value_t *a, jl_value_t *b) { + if (a == (jl_value_t*)jl_typeofbottom_type->super) + a = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself + if (b == (jl_value_t*)jl_typeofbottom_type->super) + b = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself if (a == b) return 1; if (jl_typeof(a) != jl_typeof(b)) return 0; if (jl_is_datatype(a)) { - jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b; + jl_datatype_t *ad = (jl_datatype_t*)a; + jl_datatype_t *bd = (jl_datatype_t*)b; if (ad->name != bd->name) return 0; if (ad->isconcretetype || bd->isconcretetype) return 0; size_t i, np = jl_nparams(ad); if (np != jl_nparams(bd)) return 0; - for(i=0; i < np; i++) { + for (i = 0; i < np; i++) { if (!obviously_egal(jl_tparam(ad,i), jl_tparam(bd,i))) return 0; } @@ -216,22 +221,52 @@ static int obviously_egal(jl_value_t *a, jl_value_t *b) static int obviously_unequal(jl_value_t *a, jl_value_t *b) { + if (a == (jl_value_t*)jl_typeofbottom_type->super) + a = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself + if (b == (jl_value_t*)jl_typeofbottom_type->super) + b = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself if (a == b) return 0; - if (jl_is_concrete_type(a) || jl_is_concrete_type(b)) - return 1; - if (jl_is_unionall(a)) a = jl_unwrap_unionall(a); - if (jl_is_unionall(b)) b = jl_unwrap_unionall(b); + if (jl_is_unionall(a)) + a = jl_unwrap_unionall(a); + if (jl_is_unionall(b)) + b = jl_unwrap_unionall(b); if (jl_is_datatype(a)) { - if (b == jl_bottom_type) return 1; + if (b == jl_bottom_type) + return 1; if (jl_is_datatype(b)) { - jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b; + jl_datatype_t *ad = (jl_datatype_t*)a; + jl_datatype_t *bd = (jl_datatype_t*)b; if (ad->name != bd->name) return 1; - size_t i, np = jl_nparams(ad); - if (np != jl_nparams(bd)) return 1; - for(i=0; i < np; i++) { - if (obviously_unequal(jl_tparam(ad,i), jl_tparam(bd,i))) + int istuple = (ad->name == jl_tuple_typename); + if (jl_is_concrete_type(a) || jl_is_concrete_type(b)) { + if (!istuple && ad->name != jl_type_typename) // HACK: can't properly normalize Tuple{Float64} == Tuple{<:Float64} like types or Type{T} types + return 1; + } + size_t i, np; + if (istuple) { + size_t na = jl_nparams(ad), nb = jl_nparams(bd); + if (jl_is_va_tuple(ad)) { + na -= 1; + if (jl_is_va_tuple(bd)) + nb -= 1; + } + else if (jl_is_va_tuple(bd)) { + nb -= 1; + } + else if (na != nb) { + return 1; + } + np = na < nb ? na : nb; + } + else { + np = jl_nparams(ad); + if (np != jl_nparams(bd)) + return 1; + } + for (i = 0; i < np; i++) { + if (obviously_unequal(jl_tparam(ad, i), jl_tparam(bd, i))) return 1; } } @@ -245,7 +280,9 @@ static int obviously_unequal(jl_value_t *a, jl_value_t *b) if (jl_is_long(b) && jl_unbox_long(a) != jl_unbox_long(b)) return 1; } - else if (jl_is_long(b)) return 1; + else if (jl_is_long(b)) { + return 1; + } if ((jl_is_symbol(a) || jl_is_symbol(b)) && a != b) return 1; return 0; @@ -1387,6 +1424,28 @@ JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t) return sz; } +// compute the minimum bound on the number of concrete types that are subtypes of `t` +// returns 0, 1, or many (2+) +static int concrete_min(jl_value_t *t) +{ + if (jl_is_unionall(t)) + t = jl_unwrap_unionall(t); + if (jl_is_datatype(t)) { + if (jl_is_type_type(t)) + return 0; // Type{T} may have the concrete supertype `typeof(T)`, so don't try to handle them here + return jl_is_concrete_type(t) ? 1 : 2; + } + if (jl_is_typevar(t)) + return 0; // could be 0 or more, since we didn't track if it was unbound + if (jl_is_uniontype(t)) { + int count = concrete_min(((jl_uniontype_t*)t)->a); + if (count > 1) + return count; + return count + concrete_min(((jl_uniontype_t*)t)->b); + } + return 2; // up to infinite +} + // quickly compute if x seems like a possible subtype of y // especially optimized for x isa concrete type // returns true if it could be easily determined, with the result in subtype @@ -1402,6 +1461,10 @@ JL_DLLEXPORT int jl_obvious_subtype(jl_value_t *x, jl_value_t *y, int *subtype) x = jl_unwrap_unionall(x); if (jl_is_unionall(y)) y = jl_unwrap_unionall(y); + if (x == (jl_value_t*)jl_typeofbottom_type->super) + x = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself + if (y == (jl_value_t*)jl_typeofbottom_type->super) + y = (jl_value_t*)jl_typeofbottom_type; // supertype(typeof(Union{})) is equal to, although distinct from, itself if (x == y || y == (jl_value_t*)jl_any_type) { *subtype = 1; return 1; @@ -1503,9 +1566,10 @@ JL_DLLEXPORT int jl_obvious_subtype(jl_value_t *x, jl_value_t *y, int *subtype) } int i, npx = jl_nparams(x), npy = jl_nparams(y); jl_vararg_kind_t vx = JL_VARARG_NONE; + jl_vararg_kind_t vy = JL_VARARG_NONE; jl_value_t *vxt = NULL; - int vy = 0; int nparams_expanded_x = npx; + int nparams_expanded_y = npy; if (istuple) { if (npx > 0) { jl_value_t *xva = jl_tparam(x, npx - 1); @@ -1517,22 +1581,39 @@ JL_DLLEXPORT int jl_obvious_subtype(jl_value_t *x, jl_value_t *y, int *subtype) nparams_expanded_x += jl_vararg_length(xva); } } - vy = npy > 0 && jl_is_vararg_type(jl_tparam(y, npy - 1)); - } - if (npx != npy || vx != JL_VARARG_NONE || vy) { - if ((vx == JL_VARARG_NONE || vx == JL_VARARG_UNBOUND) && !vy) { - *subtype = 0; - return 1; + if (npy > 0) { + jl_value_t *yva = jl_tparam(y, npy - 1); + vy = jl_vararg_kind(yva); + if (vy != JL_VARARG_NONE) { + nparams_expanded_y -= 1; + if (vy == JL_VARARG_INT) + nparams_expanded_y += jl_vararg_length(yva); + } } - if ((vx == JL_VARARG_NONE || vx == JL_VARARG_INT) && - nparams_expanded_x < npy - vy) { - *subtype = 0; - return 1; // number of fixed parameters in x could be fewer than in y + // if the nparams aren't equal, or at least one of them is a typevar (uncertain), they may be obviously disjoint + if (nparams_expanded_x != nparams_expanded_y || (vx != JL_VARARG_NONE && vx != JL_VARARG_INT) || (vy != JL_VARARG_NONE && vy != JL_VARARG_INT)) { + // we have a stronger bound on x if: + if (vy == JL_VARARG_NONE || vy == JL_VARARG_INT) { // the bound on y is certain + if (vx == JL_VARARG_NONE || vx == JL_VARARG_INT || vx == JL_VARARG_UNBOUND || // and the bound on x is also certain + nparams_expanded_x > nparams_expanded_y || npx > nparams_expanded_y) { // or x is unknown, but definitely longer than y + *subtype = 0; + return 1; // number of fixed parameters in x are more than declared in y + } + } + if (nparams_expanded_x < nparams_expanded_y) { + *subtype = 0; + return 1; // number of fixed parameters in x could be fewer than in y + } + uncertain = 1; } - // TODO: Can do better here for the JL_VARARG_INT case. - uncertain = 1; } - for (i = 0; i < npy - vy; i++) { + else if (npx != npy) { + *subtype = 0; + return 1; + } + + // inspect the fixed parameters in y against x + for (i = 0; i < npy - (vy == JL_VARARG_NONE ? 0 : 1); i++) { jl_value_t *a = i >= (npx - (vx == JL_VARARG_NONE ? 0 : 1)) ? vxt : jl_tparam(x, i); jl_value_t *b = jl_tparam(y, i); if (iscov || jl_is_typevar(b)) { @@ -1569,6 +1650,60 @@ JL_DLLEXPORT int jl_obvious_subtype(jl_value_t *x, jl_value_t *y, int *subtype) } } } + if (i < npx) { + // there are elements left in x (possibly just a Vararg), check them against the Vararg tail of y too + assert(vy != JL_VARARG_NONE && istuple && iscov); + jl_value_t *a1 = (vx != JL_VARARG_NONE && i == npx - 1) ? vxt : jl_tparam(x, i); + jl_value_t *b = jl_unwrap_vararg(jl_tparam(y, i)); + if (nparams_expanded_x > npy && jl_is_typevar(b) && concrete_min(a1) > 1) { + // diagonal rule for 2 or more elements: they must all be concrete on the LHS + *subtype = 0; + return 1; + } + if (jl_is_type_type(a1) && jl_is_type(jl_tparam0(a1))) { + a1 = jl_typeof(jl_tparam0(a1)); + } + for (; i < npx; i++) { + jl_value_t *a = (vx != JL_VARARG_NONE && i == npx - 1) ? vxt : jl_tparam(x, i); + if (i > npy && jl_is_typevar(b)) { // i == npy implies a == a1 + // diagonal rule: all the later parameters are also constrained to be type-equal to the first + jl_value_t *a2 = a; + if (jl_is_type_type(a) && jl_is_type(jl_tparam0(a))) { + // if a is exactly Type{T}, then use the concrete typeof(T) instead here + a2 = jl_typeof(jl_tparam0(a)); + } + if (!obviously_egal(a1, a2)) { + if (jl_obvious_subtype(a2, a1, subtype)) { + if (!*subtype) + return 1; + if (jl_has_free_typevars(a1)) // a1 is actually more constrained that this + uncertain = 1; + } + else { + uncertain = 1; + } + if (jl_obvious_subtype(a1, a2, subtype)) { + if (!*subtype) + return 1; + if (jl_has_free_typevars(a2)) // a2 is actually more constrained that this + uncertain = 1; + } + else { + uncertain = 1; + } + } + } + if (jl_obvious_subtype(a, b, subtype)) { + if (!*subtype) + return 1; + if (jl_has_free_typevars(b)) // b is actually more constrained that this + uncertain = 1; + } + else { + uncertain = 1; + } + } + } if (uncertain) return 0; *subtype = 1; @@ -1598,13 +1733,8 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, #ifdef NDEBUG if (obvious_subtype == 0) return obvious_subtype; - else if (jl_has_free_typevars(y)) - obvious_subtype = 3; else if (envsz == 0) return obvious_subtype; -#else - if (jl_has_free_typevars(y)) - obvious_subtype = 3; #endif } else { @@ -1612,7 +1742,11 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, } init_stenv(&e, env, envsz); int subtype = forall_exists_subtype(x, y, &e, 0); - assert(obvious_subtype == 3 || obvious_subtype == subtype); + assert(obvious_subtype == 3 || obvious_subtype == subtype || jl_has_free_typevars(x) || jl_has_free_typevars(y)); +#ifndef NDEBUG + if (obvious_subtype == 0 || (obvious_subtype == 1 && envsz == 0)) + subtype = obvious_subtype; // this ensures that running in a debugger doesn't change the result +#endif return subtype; } @@ -1637,16 +1771,90 @@ JL_DLLEXPORT int jl_subtype(jl_value_t *x, jl_value_t *y) JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { - if (obviously_egal(a, b)) return 1; - if (obviously_unequal(a, b)) return 0; + if (obviously_egal(a, b)) + return 1; + if (obviously_unequal(a, b)) + return 0; + // the following is an interleaved version of: + // return jl_subtype(a, b) && jl_subtype(b, a) + // where we try to do the fast checks before the expensive ones if (jl_is_datatype(a) && !jl_is_concrete_type(b)) { - // if one type looks more likely to be abstract, check it on the left + // if one type looks simpler, check it on the right // first in order to reject more quickly. jl_value_t *temp = a; a = b; b = temp; } - return jl_subtype(a, b) && jl_subtype(b, a); + // first check if a <: b has an obvious answer + int subtype_ab = 2; + if (b == (jl_value_t*)jl_any_type || a == jl_bottom_type) { + subtype_ab = 1; + } + else if (jl_typeof(a) == jl_typeof(b) && + (jl_is_unionall(b) || jl_is_uniontype(b)) && + jl_egal(a, b)) { + subtype_ab = 1; + } + else if (jl_obvious_subtype(a, b, &subtype_ab)) { +#ifdef NDEBUG + if (subtype_ab == 0) + return 0; +#endif + } + else { + subtype_ab = 3; + } + // next check if b <: a has an obvious answer + int subtype_ba = 2; + if (a == (jl_value_t*)jl_any_type || b == jl_bottom_type) { + subtype_ba = 1; + } + else if (jl_typeof(b) == jl_typeof(a) && + (jl_is_unionall(a) || jl_is_uniontype(a)) && + jl_egal(b, a)) { + subtype_ba = 1; + } + else if (jl_obvious_subtype(b, a, &subtype_ba)) { +#ifdef NDEBUG + if (subtype_ba == 0) + return 0; +#endif + } + else { + subtype_ba = 3; + } + // finally, do full subtyping for any inconclusive test + jl_stenv_t e; +#ifdef NDEBUG + if (subtype_ab != 1) +#endif + { + init_stenv(&e, NULL, 0); + int subtype = forall_exists_subtype(a, b, &e, 0); + assert(subtype_ab == 3 || subtype_ab == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); +#ifndef NDEBUG + if (subtype_ab != 0 && subtype_ab != 1) // ensures that running in a debugger doesn't change the result +#endif + subtype_ab = subtype; +#ifdef NDEBUG + if (subtype_ab == 0) + return 0; +#endif + } +#ifdef NDEBUG + if (subtype_ba != 1) +#endif + { + init_stenv(&e, NULL, 0); + int subtype = forall_exists_subtype(b, a, &e, 0); + assert(subtype_ba == 3 || subtype_ba == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); +#ifndef NDEBUG + if (subtype_ba != 0 && subtype_ba != 1) // ensures that running in a debugger doesn't change the result +#endif + subtype_ba = subtype; + } + // all tests successful + return subtype_ab && subtype_ba; } JL_DLLEXPORT int jl_is_not_broken_subtype(jl_value_t *a, jl_value_t *b) @@ -1869,14 +2077,16 @@ static int subtype_in_env_existential(jl_value_t *x, jl_value_t *y, jl_stenv_t * int8_t *rs = (int8_t*)malloc(len); int n = 0; v = e->vars; - while (v != NULL) { + while (n < len) { + assert(v != NULL); rs[n++] = v->right; v->right = 1; v = v->prev; } int issub = subtype_in_env(x, y, e); n = 0; v = e->vars; - while (v != NULL) { + while (n < len) { + assert(v != NULL); v->right = rs[n++]; v = v->prev; } diff --git a/src/support/Makefile b/src/support/Makefile index 22d80c8a99805..b5aa95b6d02d8 100644 --- a/src/support/Makefile +++ b/src/support/Makefile @@ -61,11 +61,11 @@ endif release: $(BUILDDIR)/libsupport.a debug: $(BUILDDIR)/libsupport-debug.a -$(BUILDDIR)/libsupport.a: $(OBJS) +$(BUILDDIR)/libsupport.a: $(OBJS) | $(BUILDIR) rm -rf $@ @$(call PRINT_LINK, $(AR) -rcs $@ $^) -$(BUILDDIR)/libsupport-debug.a: $(DOBJS) +$(BUILDDIR)/libsupport-debug.a: $(DOBJS) | $(BUILDDIR) rm -rf $@ @$(call PRINT_LINK, $(AR) -rcs $@ $^) diff --git a/src/symbol.c b/src/symbol.c index 9ef47bf0ef459..533c54c48b7a2 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -119,9 +119,9 @@ JL_DLLEXPORT jl_sym_t *jl_gensym(void) { char name[16]; char *n; - n = uint2str(&name[2], sizeof(name)-2, gs_ctr, 10); + uint32_t ctr = jl_atomic_fetch_add(&gs_ctr, 1); + n = uint2str(&name[2], sizeof(name)-2, ctr, 10); *(--n) = '#'; *(--n) = '#'; - gs_ctr++; return jl_symbol(n); } @@ -135,9 +135,9 @@ JL_DLLEXPORT jl_sym_t *jl_tagged_gensym(const char *str, int32_t len) char *n; name[0] = '#'; name[1] = '#'; name[2+len] = '#'; memcpy(name+2, str, len); - n = uint2str(gs_name, sizeof(gs_name), gs_ctr, 10); + uint32_t ctr = jl_atomic_fetch_add(&gs_ctr, 1); + n = uint2str(gs_name, sizeof(gs_name), ctr, 10); memcpy(name+3+len, n, sizeof(gs_name)-(n-gs_name)); - gs_ctr++; jl_sym_t *sym = _jl_symbol(name, len+3+sizeof(gs_name)-(n-gs_name)-1); if (len >= 256) free(name); return sym; diff --git a/src/sys.c b/src/sys.c index ecb973e0c288f..9632765801fe2 100644 --- a/src/sys.c +++ b/src/sys.c @@ -493,7 +493,9 @@ JL_DLLEXPORT long jl_getpagesize(void) #else JL_DLLEXPORT long jl_getpagesize(void) { - return sysconf(_SC_PAGESIZE); + long page_size = sysconf(_SC_PAGESIZE); + assert(page_size != -1); + return page_size; } #endif diff --git a/src/task.c b/src/task.c index 2c0797d051571..807c9ed2ae3f8 100644 --- a/src/task.c +++ b/src/task.c @@ -151,14 +151,14 @@ void JL_NORETURN jl_finish_task(jl_task_t *t, jl_value_t *resultval JL_MAYBE_UNR { jl_ptls_t ptls = jl_get_ptls_states(); JL_SIGATOMIC_BEGIN(); + t->result = resultval; + jl_gc_wb(t, t->result); if (t->exception != jl_nothing) - t->state = failed_sym; + jl_atomic_store_release(&t->state, failed_sym); else - t->state = done_sym; + jl_atomic_store_release(&t->state, done_sym); if (t->copy_stack) // early free of stkbuf t->stkbuf = NULL; - t->result = resultval; - jl_gc_wb(t, t->result); // ensure that state is cleared ptls->in_finalizer = 0; ptls->in_pure_callback = 0; @@ -287,7 +287,9 @@ static void ctx_switch(jl_ptls_t ptls, jl_task_t **pt) ptls->pgcstack = t->gcstack; ptls->world_age = t->world_age; t->gcstack = NULL; +#ifdef MIGRATE_TASKS ptls->previous_task = lastt; +#endif ptls->current_task = t; jl_ucontext_t *lastt_ctx = (killed ? NULL : &lastt->ctx); @@ -366,17 +368,26 @@ JL_DLLEXPORT void jl_switchto(jl_task_t **pt) ctx_switch(ptls, pt); +#ifdef MIGRATE_TASKS ptls = refetch_ptls(); t = ptls->previous_task; assert(t->tid == ptls->tid); if (!t->sticky && !t->copy_stack) t->tid = -1; +#elif defined(NDEBUG) + (void)refetch_ptls(); +#else + assert(ptls == refetch_ptls()); +#endif + ct = ptls->current_task; #ifdef ENABLE_TIMINGS assert(blk == ct->timing_stack); if (blk) jl_timing_block_start(blk); +#else + (void)ct; #endif jl_gc_unsafe_leave(ptls, gc_state); @@ -561,9 +572,11 @@ static void NOINLINE JL_NORETURN start_task(void) jl_task_t *t = ptls->current_task; jl_value_t *res; +#ifdef MIGRATE_TASKS jl_task_t *pt = ptls->previous_task; if (!pt->sticky && !pt->copy_stack) pt->tid = -1; +#endif t->started = 1; if (t->exception != jl_nothing) { diff --git a/src/threading.c b/src/threading.c index 67f9317d6f136..caa477cdbfd12 100644 --- a/src/threading.c +++ b/src/threading.c @@ -473,7 +473,7 @@ void jl_start_threads(void) #endif -unsigned volatile _threadedregion; // HACK: prevent the root task from sleeping +unsigned volatile _threadedregion; // HACK: keep track of whether it is safe to do IO // simple fork/join mode code JL_DLLEXPORT void jl_threading_run(jl_value_t *func) @@ -505,19 +505,19 @@ JL_DLLEXPORT void jl_threading_run(jl_value_t *func) args2[0] = schd_func; args2[1] = (jl_value_t*)t; jl_apply(args2, 2); +#ifdef JULIA_ENABLE_THREADING if (i == 1) { // let threads know work is coming (optimistic) - uv_mutex_lock(&sleep_lock); - uv_cond_broadcast(&sleep_alarm); - uv_mutex_unlock(&sleep_lock); + jl_wakeup_thread(-1); } +#endif } +#ifdef JULIA_ENABLE_THREADING if (nthreads > 2) { // let threads know work is ready (guaranteed) - uv_mutex_lock(&sleep_lock); - uv_cond_broadcast(&sleep_alarm); - uv_mutex_unlock(&sleep_lock); + jl_wakeup_thread(-1); } +#endif // join with all tasks JL_TRY { for (int i = 0; i < nthreads; i++) { @@ -533,8 +533,8 @@ JL_DLLEXPORT void jl_threading_run(jl_value_t *func) JL_UV_UNLOCK(); jl_rethrow(); } - _threadedregion -= 1; // make sure no threads are sitting in the event loop + _threadedregion -= 1; jl_wake_libuv(); // make sure no more callbacks will run while user code continues // outside thread region and might touch an I/O object. diff --git a/src/threading.h b/src/threading.h index a7a6911411705..072b7264841c2 100644 --- a/src/threading.h +++ b/src/threading.h @@ -14,10 +14,6 @@ extern "C" { extern jl_ptls_t *jl_all_tls_states JL_GLOBALLY_ROOTED; /* thread local storage */ extern JL_DLLEXPORT int jl_n_threads; /* # threads we're actually using */ -extern volatile unsigned _threadedregion; // HACK: prevent tasks from sleeping in threaded regions - -extern uv_mutex_t sleep_lock; -extern uv_cond_t sleep_alarm; typedef struct _jl_threadarg_t { int16_t tid; diff --git a/stdlib/Dates/src/query.jl b/stdlib/Dates/src/query.jl index 3004f7bb88c7d..547bf22ec34a7 100644 --- a/stdlib/Dates/src/query.jl +++ b/stdlib/Dates/src/query.jl @@ -122,7 +122,29 @@ dayofweek(dt::TimeType) = dayofweek(days(dt)) const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = 1, 2, 3, 4, 5, 6, 7 const Mon, Tue, Wed, Thu, Fri, Sat, Sun = 1, 2, 3, 4, 5, 6, 7 - +for (ii, day_ind, short_day, long_day) in ((1, "first", :Mon, :Monday), (2, "second", :Tue, :Tuesday), (3, "third", :Wed, :Wednesday), (4, "fourth", :Thu, :Thursday), (5, "fifth", :Fri, :Friday), (6, "sixth", :Sat, :Saturday), (7, "seventh", :Sun, :Sunday)) + short_name = string(short_day) + long_name = string(long_day) + name_ind = day_ind + ind_str = string(ii) + @eval begin + @doc """ + $($long_name) + $($short_name) + + The $($name_ind) day of the week. + + # Examples + ```jldoctest + julia> $($long_name) + $($ind_str) + + julia> $($short_name) + $($ind_str) + ``` + """ ($long_day, $short_day) + end +end dayname(day::Integer, locale::DateLocale) = locale.days_of_week[day] dayabbr(day::Integer, locale::DateLocale) = locale.days_of_week_abbr[day] dayname(day::Integer; locale::AbstractString="english") = dayname(day, LOCALES[locale]) diff --git a/stdlib/DelimitedFiles/src/DelimitedFiles.jl b/stdlib/DelimitedFiles/src/DelimitedFiles.jl index 99bd0a7217cae..2a545eb413bae 100644 --- a/stdlib/DelimitedFiles/src/DelimitedFiles.jl +++ b/stdlib/DelimitedFiles/src/DelimitedFiles.jl @@ -226,7 +226,7 @@ readdlm(input, dlm::AbstractChar, T::Type, eol::AbstractChar; opts...) = readdlm_auto(input, dlm, T, eol, false; opts...) readdlm_auto(input::Vector{UInt8}, dlm::AbstractChar, T::Type, eol::AbstractChar, auto::Bool; opts...) = - readdlm_string(String(input), dlm, T, eol, auto, val_opts(opts)) + readdlm_string(String(copyto!(Base.StringVector(length(input)), input)), dlm, T, eol, auto, val_opts(opts)) readdlm_auto(input::IO, dlm::AbstractChar, T::Type, eol::AbstractChar, auto::Bool; opts...) = readdlm_string(read(input, String), dlm, T, eol, auto, val_opts(opts)) function readdlm_auto(input::AbstractString, dlm::AbstractChar, T::Type, eol::AbstractChar, auto::Bool; opts...) diff --git a/stdlib/DelimitedFiles/test/runtests.jl b/stdlib/DelimitedFiles/test/runtests.jl index c1a9700d09d99..900d97ace2122 100644 --- a/stdlib/DelimitedFiles/test/runtests.jl +++ b/stdlib/DelimitedFiles/test/runtests.jl @@ -288,6 +288,12 @@ let data = "\"1\",\"灣\"\"灣灣灣灣\",\"3\"" @test readdlm(IOBuffer(data), ',') == Any[1 "灣\"灣灣灣灣" 3] end +# reading from a byte array (#16731) +let data = Vector{UInt8}("1,2,3\n4,5,6"), origdata = copy(data) + @test readdlm(data, ',') == [1 2 3; 4 5 6] + @test data == origdata +end + # issue #11484: useful error message for invalid readdlm filepath arguments @test_throws ArgumentError readdlm(tempdir()) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index df859f10aaa6c..3caf002b3cd30 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -248,7 +248,8 @@ function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_std print(out, '\n') flush(out) - disable_nagle(sock) + Sockets.nagle(sock, false) + Sockets.quickack(sock, true) if ccall(:jl_running_on_valgrind,Cint,()) != 0 println(out, "PID = $(getpid())") @@ -1180,18 +1181,6 @@ function interrupt(pids::AbstractVector=workers()) end end - -function disable_nagle(sock) - # disable nagle on all OSes - ccall(:uv_tcp_nodelay, Cint, (Ptr{Cvoid}, Cint), sock.handle, 1) - @static if Sys.islinux() - # tcp_quickack is a linux only option - if ccall(:jl_tcp_quickack, Cint, (Ptr{Cvoid}, Cint), sock.handle, 1) < 0 - @warn "Networking unoptimized ( Error enabling TCP_QUICKACK : $(Libc.strerror(Libc.errno())) )" maxlog=1 - end - end -end - wp_bind_addr(p::LocalProcess) = p.bind_addr wp_bind_addr(p) = p.config.bind_addr diff --git a/stdlib/Distributed/src/clusterserialize.jl b/stdlib/Distributed/src/clusterserialize.jl index f1293b926efb1..e21ac32dc39d6 100644 --- a/stdlib/Distributed/src/clusterserialize.jl +++ b/stdlib/Distributed/src/clusterserialize.jl @@ -158,6 +158,15 @@ end function deserialize_global_from_main(s::ClusterSerializer, sym) sym_isconst = deserialize(s) v = deserialize(s) + if isdefined(Main, sym) && (sym_isconst || isconst(Main, sym)) + if isequal(getfield(Main, sym), v) + # same value; ok + return nothing + else + @warn "Cannot transfer global variable $sym; it already has a value." + return nothing + end + end if sym_isconst ccall(:jl_set_const, Cvoid, (Any, Any, Any), Main, sym, v) else diff --git a/stdlib/Distributed/src/macros.jl b/stdlib/Distributed/src/macros.jl index 4285073ec90a3..d85e2af8f2e7d 100644 --- a/stdlib/Distributed/src/macros.jl +++ b/stdlib/Distributed/src/macros.jl @@ -172,7 +172,7 @@ Equivalent to calling `remotecall_eval(Main, procs, expr)`. """ macro everywhere(ex) procs = GlobalRef(@__MODULE__, :procs) - return esc(:(@everywhere $procs() $ex)) + return esc(:($(Distributed).@everywhere $procs() $ex)) end macro everywhere(procs, ex) diff --git a/stdlib/Distributed/src/precompile.jl b/stdlib/Distributed/src/precompile.jl index c6a57e1b2bcc2..06eb22c91d587 100644 --- a/stdlib/Distributed/src/precompile.jl +++ b/stdlib/Distributed/src/precompile.jl @@ -6,28 +6,28 @@ precompile(Tuple{typeof(Distributed.init_worker), String, Distributed.DefaultClu precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Distributed.set_valid_processes), Tuple{Array{Int64, 1}}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.Worker, Array{Int64, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.LocalProcess, Array{Int64, 1}}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.Worker, Array{Int64, 1}}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.LocalProcess, Array{Int64, 1}}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.Worker, Array{Int64, 1}}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.set_valid_processes), Distributed.LocalProcess, Array{Int64, 1}}) precompile(Tuple{typeof(Distributed.default_addprocs_params)}) precompile(Tuple{typeof(Distributed.topology), Symbol}) precompile(Tuple{typeof(Base.popfirst!), Array{Distributed.WorkerConfig, 1}}) precompile(Tuple{typeof(Distributed.workers)}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#addprocs_locked")), Array{Any, 1}, typeof(Distributed.addprocs_locked), Distributed.SSHManager}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##addprocs_locked")), Array{Any, 1}, typeof(Distributed.addprocs_locked), Distributed.SSHManager}) precompile(Tuple{typeof(Distributed.check_addprocs_args), Array{Any, 1}}) precompile(Tuple{Type{Distributed.SSHManager}, Array{Any, 1}}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#addprocs")), Array{Any, 1}, typeof(Distributed.addprocs), Distributed.SSHManager}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#addprocs_locked")), Array{Any, 1}, typeof(Distributed.addprocs_locked), Distributed.LocalManager}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#addprocs")), Array{Any, 1}, typeof(Distributed.addprocs), Distributed.LocalManager}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##addprocs")), Array{Any, 1}, typeof(Distributed.addprocs), Distributed.SSHManager}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##addprocs_locked")), Array{Any, 1}, typeof(Distributed.addprocs_locked), Distributed.LocalManager}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##addprocs")), Array{Any, 1}, typeof(Distributed.addprocs), Distributed.LocalManager}) precompile(Tuple{typeof(Distributed.check_master_connect)}) precompile(Tuple{typeof(Distributed.terminate_all_workers)}) precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Base.exit), Tuple{}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Base.exit), Distributed.LocalProcess}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.LocalProcess}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.LocalProcess}) precompile(Tuple{typeof(Distributed.set_worker_state), Distributed.Worker, Distributed.WorkerState}) precompile(Tuple{typeof(Distributed.set_worker_state), Distributed.LocalProcess, Distributed.WorkerState}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#rmprocs")), Array{Any, 1}, typeof(Distributed.rmprocs), Array{Int64, 1}}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##rmprocs")), Array{Any, 1}, typeof(Distributed.rmprocs), Array{Int64, 1}}) precompile(Tuple{typeof(Distributed.interrupt), Array{Int64, 1}}) precompile(Tuple{typeof(Distributed.flush_gc_msgs)}) precompile(Tuple{typeof(Distributed.addprocs), Int64}) @@ -36,7 +36,8 @@ precompile(Tuple{typeof(Distributed.launch), Distributed.LocalManager, Base.Dict precompile(Tuple{typeof(Distributed.start_worker), Base.PipeEndpoint, String}) precompile(Tuple{typeof(Distributed.socket_reuse_port)}) precompile(Tuple{typeof(Distributed.flush_gc_msgs)}) -precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPServer}) +precompile(Tuple{typeof(Sockets.nagle), Sockets.TCPServer, Bool}) +precompile(Tuple{typeof(Sockets.quickack), Sockets.TCPServer, Bool}) precompile(Tuple{typeof(Distributed.next_tunnel_port)}) precompile(Tuple{typeof(Base._delete!), Base.Dict{Int64, Union{Distributed.Worker, Distributed.LocalProcess}}, Int64}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.JoinPGRPMsg, Bool}) @@ -66,8 +67,8 @@ precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Any, Any}, Distributed.RRID precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) precompile(Tuple{Type{Distributed.ResultMsg}, Distributed.RemoteException}) precompile(Tuple{Type{Distributed.ResultMsg}, Symbol}) precompile(Tuple{typeof(Distributed.send_msg_now), Sockets.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) @@ -85,7 +86,8 @@ precompile(Tuple{typeof(Distributed.process_hdr), Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.deserialize_msg), Distributed.ClusterSerializer{Sockets.TCPSocket}}) precompile(Tuple{typeof(Distributed.null_id), Distributed.RRID}) precompile(Tuple{typeof(Distributed.deliver_result), Sockets.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) -precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPSocket}) +precompile(Tuple{typeof(Sockets.nagle), Sockets.TCPSocket, Bool}) +precompile(Tuple{typeof(Sockets.quickack), Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.message_handler_loop), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.process_tcp_streams), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{Type{Distributed.JoinPGRPMsg}, Int64, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Symbol, Bool}) @@ -116,8 +118,8 @@ precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distribut precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) precompile(Tuple{Type{Distributed.ResultMsg}, Distributed.RemoteException}) precompile(Tuple{Type{Distributed.ResultMsg}, Symbol}) precompile(Tuple{typeof(Distributed.send_msg_now), Sockets.TCPSocket, Distributed.MsgHeader, Distributed.ResultMsg}) @@ -126,7 +128,6 @@ precompile(Tuple{typeof(Distributed.deregister_worker), Distributed.ProcessGroup precompile(Tuple{typeof(Distributed.process_hdr), Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.null_id), Distributed.RRID}) precompile(Tuple{typeof(Distributed.deliver_result), Sockets.TCPSocket, Symbol, Distributed.RRID, Distributed.RemoteException}) -precompile(Tuple{typeof(Distributed.disable_nagle), Sockets.TCPSocket}) precompile(Tuple{typeof(Distributed.message_handler_loop), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Distributed.process_tcp_streams), Sockets.TCPSocket, Sockets.TCPSocket, Bool}) precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union}}) @@ -160,8 +161,8 @@ precompile(Tuple{typeof(Base.hash), Distributed.RemoteChannel{Base.Channel{Any}} precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Nothing}, Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.Worker, Distributed.RRID, Distributed.WorkerPool}) precompile(Tuple{typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.LocalProcess, Distributed.RRID, Distributed.WorkerPool}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.Worker, Distributed.RRID, Distributed.WorkerPool}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.LocalProcess, Distributed.RRID, Distributed.WorkerPool}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.Worker, Distributed.RRID, Distributed.WorkerPool}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Distributed.put_ref), Distributed.LocalProcess, Distributed.RRID, Distributed.WorkerPool}) precompile(Tuple{typeof(Base.finalizer), Distributed.RemoteChannel{Base.Channel{Any}}, typeof(Distributed.finalize_ref)}) precompile(Tuple{typeof(Distributed.test_existing_ref), Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{Type{Distributed.RemoteChannel{T} where T<:Base.AbstractChannel}, Int64}) @@ -189,10 +190,10 @@ precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerialize precompile(Tuple{typeof(Distributed.finalize_ref), Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Distributed.send_del_client), Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Base.:(==)), Distributed.RemoteChannel{Base.Channel{Any}}, Distributed.RemoteChannel{Base.Channel{Any}}}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Base.open), Distributed.LocalProcess, typeof(Base.read), String}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Base.open), Distributed.Worker, typeof(Base.read), String}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) -precompile(Tuple{getfield(Distributed, Symbol("#kw#rmprocs")), Array{Any, 1}, typeof(Distributed.rmprocs), Array{Int64, 1}}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Base.open), Distributed.LocalProcess, typeof(Base.read), String}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Distributed.remotecall_fetch), typeof(Base.open), Distributed.Worker, typeof(Base.read), String}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) +precompile(Tuple{getfield(Distributed, Symbol("#kw##rmprocs")), Array{Any, 1}, typeof(Distributed.rmprocs), Array{Int64, 1}}) precompile(Tuple{Type{Distributed.Future}, Int64}) precompile(Tuple{typeof(Distributed.flush_gc_msgs), Distributed.Worker}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Base.exit), Distributed.Worker}) diff --git a/stdlib/Distributed/src/process_messages.jl b/stdlib/Distributed/src/process_messages.jl index dba6791162d3d..7361d4d057e65 100644 --- a/stdlib/Distributed/src/process_messages.jl +++ b/stdlib/Distributed/src/process_messages.jl @@ -131,10 +131,12 @@ function process_messages(r_stream::TCPSocket, w_stream::TCPSocket, incoming::Bo end function process_tcp_streams(r_stream::TCPSocket, w_stream::TCPSocket, incoming::Bool) - disable_nagle(r_stream) + Sockets.nagle(r_stream, false) + Sockets.quickack(r_stream, true) wait_connected(r_stream) if r_stream != w_stream - disable_nagle(w_stream) + Sockets.nagle(w_stream, false) + Sockets.quickack(w_stream, true) wait_connected(w_stream) end message_handler_loop(r_stream, w_stream, incoming) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 90ecb16f82230..f1f439fd6c8e9 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -1614,6 +1614,18 @@ for T in (UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64) @test n == 55 end +# issue #28966 +let code = """ + import Distributed + Distributed.addprocs(1) + Distributed.@everywhere f() = myid() + for w in Distributed.workers() + @assert Distributed.remotecall_fetch(f, w) == w + end + """ + @test success(`$(Base.julia_cmd()) --startup-file=no -e $code`) +end + # Run topology tests last after removing all workers, since a given # cluster at any time only supports a single topology. rmprocs(workers()) diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 31e4450edf761..4f0de2131fc5e 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -75,6 +75,7 @@ function challenge_prompt(cmd::Cmd, challenges; timeout::Integer=60, debug::Bool sleep(3) process_running(p) && kill(p, Base.SIGKILL) end + wait(p) end for (challenge, response) in challenges diff --git a/stdlib/LibGit2/test/online.jl b/stdlib/LibGit2/test/online.jl index 7c7029d3f064c..888af97fe0a69 100644 --- a/stdlib/LibGit2/test/online.jl +++ b/stdlib/LibGit2/test/online.jl @@ -68,7 +68,8 @@ mktempdir() do dir error("unexpected") catch ex @test isa(ex, LibGit2.Error.GitError) - @test ex.code == LibGit2.Error.EAUTH + # Return code seems to vary, see #32186, #32219 + @test ex.code ∈ (LibGit2.Error.EAUTH, LibGit2.Error.ERROR) end Base.shred!(cred) end diff --git a/stdlib/Libdl/src/Libdl.jl b/stdlib/Libdl/src/Libdl.jl index 14bb8f43ff94a..bd1316bfc6fbb 100644 --- a/stdlib/Libdl/src/Libdl.jl +++ b/stdlib/Libdl/src/Libdl.jl @@ -113,6 +113,33 @@ function dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND; t return ret end +""" + dlopen(f::Function, args...; kwargs...) + +Wrapper for usage with `do` blocks to automatically close the dynamic library once +control flow leaves the `do` block scope. + +# Example +```julia +vendor = dlopen("libblas") do lib + if Libdl.dlsym(lib, :openblas_set_num_threads; throw_error=false) !== nothing + return :openblas + else + return :other + end +end +``` +""" +function dlopen(f::Function, args...; kwargs...) + hdl = nothing + try + hdl = dlopen(args...; kwargs...) + f(hdl) + finally + dlclose(hdl) + end +end + """ dlopen_e(libfile::AbstractString [, flags::Integer]) diff --git a/stdlib/Libdl/test/runtests.jl b/stdlib/Libdl/test/runtests.jl index 1c6696907411c..4279e71612c43 100644 --- a/stdlib/Libdl/test/runtests.jl +++ b/stdlib/Libdl/test/runtests.jl @@ -196,6 +196,18 @@ let dl = C_NULL end end +# test do-block dlopen +Libdl.dlopen(abspath(joinpath(private_libdir, "libccalltest"))) do dl + fptr = Libdl.dlsym(dl, :set_verbose) + @test fptr !== nothing + @test_throws ErrorException Libdl.dlsym(dl, :foo) + + fptr = Libdl.dlsym_e(dl, :set_verbose) + @test fptr != C_NULL + fptr = Libdl.dlsym_e(dl, :foo) + @test fptr == C_NULL +end + # test dlclose # If dl is NULL, jl_dlclose should return -1 and dlclose should return false # dlclose should return true on success and false on failure diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 1db9a6ed9d8a5..fbf69e8c76676 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -287,20 +287,24 @@ The following table summarizes the types of matrix factorizations that have been Julia. Details of their associated methods can be found in the [Standard Functions](@ref) section of the Linear Algebra documentation. -| Type | Description | -|:----------------- |:-------------------------------------------------------------------------------------------------------------- | -| `Cholesky` | [Cholesky factorization](https://en.wikipedia.org/wiki/Cholesky_decomposition) | -| `CholeskyPivoted` | [Pivoted](https://en.wikipedia.org/wiki/Pivot_element) Cholesky factorization | -| `LU` | [LU factorization](https://en.wikipedia.org/wiki/LU_decomposition) | -| `LUTridiagonal` | LU factorization for [`Tridiagonal`](@ref) matrices | -| `QR` | [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | -| `QRCompactWY` | Compact WY form of the QR factorization | -| `QRPivoted` | Pivoted [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | -| `Hessenberg` | [Hessenberg decomposition](http://mathworld.wolfram.com/HessenbergDecomposition.html) | -| `Eigen` | [Spectral decomposition](https://en.wikipedia.org/wiki/Eigendecomposition_(matrix)) | -| `SVD` | [Singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) | -| `GeneralizedSVD` | [Generalized SVD](https://en.wikipedia.org/wiki/Generalized_singular_value_decomposition#Higher_order_version) | - +| Type | Description | +|:------------------ |:-------------------------------------------------------------------------------------------------------------- | +| `BunchKaufman` | Bunch-Kaufman factorization | +| `Cholesky` | [Cholesky factorization](https://en.wikipedia.org/wiki/Cholesky_decomposition) | +| `CholeskyPivoted` | [Pivoted](https://en.wikipedia.org/wiki/Pivot_element) Cholesky factorization | +| `LDLt` | [LDL(T) factorization](https://en.wikipedia.org/wiki/Cholesky_decomposition#LDL_decomposition) | +| `LU` | [LU factorization](https://en.wikipedia.org/wiki/LU_decomposition) | +| `QR` | [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | +| `QRCompactWY` | Compact WY form of the QR factorization | +| `QRPivoted` | Pivoted [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | +| `LQ` | [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) of `transpose(A)` | +| `Hessenberg` | [Hessenberg decomposition](http://mathworld.wolfram.com/HessenbergDecomposition.html) | +| `Eigen` | [Spectral decomposition](https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix) | +| `GeneralizedEigen` | [Generalized spectral decomposition](https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix#Generalized_eigenvalue_problem) | +| `SVD` | [Singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) | +| `GeneralizedSVD` | [Generalized SVD](https://en.wikipedia.org/wiki/Generalized_singular_value_decomposition#Higher_order_version) | +| `Schur` | [Schur decomposition](https://en.wikipedia.org/wiki/Schur_decomposition) | +| `GeneralizedSchur` | [Generalized Schur decomposition](https://en.wikipedia.org/wiki/Schur_decomposition#Generalized_Schur_decomposition) | @@ -329,25 +333,34 @@ LinearAlgebra.UnitLowerTriangular LinearAlgebra.UnitUpperTriangular LinearAlgebra.UpperHessenberg LinearAlgebra.UniformScaling +LinearAlgebra.Factorization +LinearAlgebra.LU LinearAlgebra.lu LinearAlgebra.lu! +LinearAlgebra.Cholesky +LinearAlgebra.CholeskyPivoted LinearAlgebra.cholesky LinearAlgebra.cholesky! LinearAlgebra.lowrankupdate LinearAlgebra.lowrankdowndate LinearAlgebra.lowrankupdate! LinearAlgebra.lowrankdowndate! +LinearAlgebra.LDLt LinearAlgebra.ldlt LinearAlgebra.ldlt! -LinearAlgebra.qr -LinearAlgebra.qr! LinearAlgebra.QR LinearAlgebra.QRCompactWY LinearAlgebra.QRPivoted -LinearAlgebra.lq! +LinearAlgebra.qr +LinearAlgebra.qr! +LinearAlgebra.LQ LinearAlgebra.lq +LinearAlgebra.lq! +LinearAlgebra.BunchKaufman LinearAlgebra.bunchkaufman LinearAlgebra.bunchkaufman! +LinearAlgebra.Eigen +LinearAlgebra.GeneralizedEigen LinearAlgebra.eigvals LinearAlgebra.eigvals! LinearAlgebra.eigmax @@ -355,12 +368,17 @@ LinearAlgebra.eigmin LinearAlgebra.eigvecs LinearAlgebra.eigen LinearAlgebra.eigen! +LinearAlgebra.Hessenberg LinearAlgebra.hessenberg LinearAlgebra.hessenberg! -LinearAlgebra.schur! +LinearAlgebra.Schur +LinearAlgebra.GeneralizedSchur LinearAlgebra.schur +LinearAlgebra.schur! LinearAlgebra.ordschur LinearAlgebra.ordschur! +LinearAlgebra.SVD +LinearAlgebra.GeneralizedSVD LinearAlgebra.svd LinearAlgebra.svd! LinearAlgebra.svdvals diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index 65e4c8d2e8463..ef75bdc226692 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -4,6 +4,65 @@ ## LD for BunchKaufman, UL for CholeskyDense, LU for LUDense and ## define size methods for Factorization types using it. +""" + BunchKaufman <: Factorization + +Matrix factorization type of the Bunch-Kaufman factorization of a symmetric or +Hermitian matrix `A` as `P'UDU'P` or `P'LDL'P`, depending on whether the upper +(the default) or the lower triangle is stored in `A`. If `A` is complex symmetric +then `U'` and `L'` denote the unconjugated transposes, i.e. `transpose(U)` and +`transpose(L)`, respectively. This is the return type of [`bunchkaufman`](@ref), +the corresponding matrix factorization function. + +If `S::BunchKaufman` is the factorization object, the components can be obtained +via `S.D`, `S.U` or `S.L` as appropriate given `S.uplo`, and `S.p`. + +Iterating the decomposition produces the components `S.D`, `S.U` or `S.L` +as appropriate given `S.uplo`, and `S.p`. + +# Examples +```jldoctest +julia> A = [1 2; 2 3] +2×2 Array{Int64,2}: + 1 2 + 2 3 + +julia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A) +BunchKaufman{Float64,Array{Float64,2}} +D factor: +2×2 Tridiagonal{Float64,Array{Float64,1}}: + -0.333333 0.0 + 0.0 3.0 +U factor: +2×2 UnitUpperTriangular{Float64,Array{Float64,2}}: + 1.0 0.666667 + ⋅ 1.0 +permutation: +2-element Array{Int64,1}: + 1 + 2 + +julia> d, u, p = S; # destructuring via iteration + +julia> d == S.D && u == S.U && p == S.p +true + +julia> S = bunchkaufman(Symmetric(A, :L)) +BunchKaufman{Float64,Array{Float64,2}} +D factor: +2×2 Tridiagonal{Float64,Array{Float64,1}}: + 3.0 0.0 + 0.0 -0.333333 +L factor: +2×2 UnitLowerTriangular{Float64,Array{Float64,2}}: + 1.0 ⋅ + 0.666667 1.0 +permutation: +2-element Array{Int64,1}: + 2 + 1 +``` +""" struct BunchKaufman{T,S<:AbstractMatrix} <: Factorization{T} LD::S ipiv::Vector{BlasInt} @@ -59,8 +118,8 @@ end """ bunchkaufman(A, rook::Bool=false; check = true) -> S::BunchKaufman -Compute the Bunch-Kaufman [^Bunch1977] factorization of a `Symmetric` or -`Hermitian` matrix `A` as ``P'*U*D*U'*P`` or ``P'*L*D*L'*P``, depending on +Compute the Bunch-Kaufman [^Bunch1977] factorization of a symmetric or +Hermitian matrix `A` as `P'*U*D*U'*P` or `P'*L*D*L'*P`, depending on which triangle is stored in `A`, and return a `BunchKaufman` object. Note that if `A` is complex symmetric then `U'` and `L'` denote the unconjugated transposes, i.e. `transpose(U)` and `transpose(L)`. @@ -90,7 +149,7 @@ julia> A = [1 2; 2 3] 1 2 2 3 -julia> S = bunchkaufman(A) +julia> S = bunchkaufman(A) # A gets wrapped internally by Symmetric(A) BunchKaufman{Float64,Array{Float64,2}} D factor: 2×2 Tridiagonal{Float64,Array{Float64,1}}: @@ -109,6 +168,21 @@ julia> d, u, p = S; # destructuring via iteration julia> d == S.D && u == S.U && p == S.p true + +julia> S = bunchkaufman(Symmetric(A, :L)) +BunchKaufman{Float64,Array{Float64,2}} +D factor: +2×2 Tridiagonal{Float64,Array{Float64,1}}: + 3.0 0.0 + 0.0 -0.333333 +L factor: +2×2 UnitLowerTriangular{Float64,Array{Float64,2}}: + 1.0 ⋅ + 0.666667 1.0 +permutation: +2-element Array{Int64,1}: + 2 + 1 ``` """ bunchkaufman(A::AbstractMatrix{T}, rook::Bool=false; check::Bool = true) where {T} = diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 14444b6d00f4f..794d6f5959b94 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -27,7 +27,48 @@ # the cost would be extra unnecessary/unused fields for the unpivoted Cholesky and runtime # checks of those fields before calls to LAPACK to check which version of the Cholesky # factorization the type represents. +""" + Cholesky <: Factorization + +Matrix factorization type of the Cholesky factorization of a dense symmetric/Hermitian +positive definite matrix `A`. This is the return type of [`cholesky`](@ref), +the corresponding matrix factorization function. + +The triangular Cholesky factor can be obtained from the factorization `F::Cholesky` +via `F.L` and `F.U`. + +# Examples +```jldoctest +julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.] +3×3 Array{Float64,2}: + 4.0 12.0 -16.0 + 12.0 37.0 -43.0 + -16.0 -43.0 98.0 + +julia> C = cholesky(A) +Cholesky{Float64,Array{Float64,2}} +U factor: +3×3 UpperTriangular{Float64,Array{Float64,2}}: + 2.0 6.0 -8.0 + ⋅ 1.0 5.0 + ⋅ ⋅ 3.0 + +julia> C.U +3×3 UpperTriangular{Float64,Array{Float64,2}}: + 2.0 6.0 -8.0 + ⋅ 1.0 5.0 + ⋅ ⋅ 3.0 +julia> C.L +3×3 LowerTriangular{Float64,Array{Float64,2}}: + 2.0 ⋅ ⋅ + 6.0 1.0 ⋅ + -8.0 5.0 3.0 + +julia> C.L * C.U == A +true +``` +""" struct Cholesky{T,S<:AbstractMatrix} <: Factorization{T} factors::S uplo::Char @@ -43,6 +84,38 @@ Cholesky(A::AbstractMatrix{T}, uplo::Symbol, info::Integer) where {T} = Cholesky(A::AbstractMatrix{T}, uplo::AbstractChar, info::Integer) where {T} = Cholesky{T,typeof(A)}(A, uplo, info) +""" + CholeskyPivoted + +Matrix factorization type of the pivoted Cholesky factorization of a dense symmetric/Hermitian +positive semi-definite matrix `A`. This is the return type of [`cholesky(_, Val(true))`](@ref), +the corresponding matrix factorization function. + +The triangular Cholesky factor can be obtained from the factorization `F::CholeskyPivoted` +via `F.L` and `F.U`. + +# Examples +```jldoctest +julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.] +3×3 Array{Float64,2}: + 4.0 12.0 -16.0 + 12.0 37.0 -43.0 + -16.0 -43.0 98.0 + +julia> C = cholesky(A, Val(true)) +CholeskyPivoted{Float64,Array{Float64,2}} +U factor with rank 3: +3×3 UpperTriangular{Float64,Array{Float64,2}}: + 9.89949 -4.34366 -1.61624 + ⋅ 4.25825 1.1694 + ⋅ ⋅ 0.142334 +permutation: +3-element Array{Int64,1}: + 3 + 2 + 1 +``` +""" struct CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T} factors::S uplo::Char diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 841abd22a80c8..928f470f2415a 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -1,6 +1,52 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # Eigendecomposition +""" + Eigen <: Factorization + +Matrix factorization type of the eigenvalue/spectral decomposition of a square +matrix `A`. This is the return type of [`eigen`](@ref), the corresponding matrix +factorization function. + +If `F::Eigen` is the factorization object, the eigenvalues can be obtained via +`F.values` and the eigenvectors as the columns of the matrix `F.vectors`. +(The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) + +Iterating the decomposition produces the components `F.values` and `F.vectors`. + +# Examples +```jldoctest +julia> F = eigen([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) +Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}} +eigenvalues: +3-element Array{Float64,1}: + 1.0 + 3.0 + 18.0 +eigenvectors: +3×3 Array{Float64,2}: + 1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 1.0 + +julia> F.values +3-element Array{Float64,1}: + 1.0 + 3.0 + 18.0 + +julia> F.vectors +3×3 Array{Float64,2}: + 1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 1.0 + +julia> vals, vecs = F; # destructuring via iteration + +julia> vals == F.values && vecs == F.vectors +true +``` +""" struct Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} values::U vectors::S @@ -11,6 +57,57 @@ Eigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) where {T,V} = Eigen{T,V,typeof(vectors),typeof(values)}(values, vectors) # Generalized eigenvalue problem. +""" + GeneralizedEigen <: Factorization + +Matrix factorization type of the generalized eigenvalue/spectral decomposition of +`A` and `B`. This is the return type of [`eigen`](@ref), the corresponding +matrix factorization function, when called with two matrix arguments. + +If `F::GeneralizedEigen` is the factorization object, the eigenvalues can be obtained via +`F.values` and the eigenvectors as the columns of the matrix `F.vectors`. +(The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.) + +Iterating the decomposition produces the components `F.values` and `F.vectors`. + +# Examples +```jldoctest +julia> A = [1 0; 0 -1] +2×2 Array{Int64,2}: + 1 0 + 0 -1 + +julia> B = [0 1; 1 0] +2×2 Array{Int64,2}: + 0 1 + 1 0 + +julia> F = eigen(A, B) +GeneralizedEigen{Complex{Float64},Complex{Float64},Array{Complex{Float64},2},Array{Complex{Float64},1}} +eigenvalues: +2-element Array{Complex{Float64},1}: + 0.0 + 1.0im + 0.0 - 1.0im +eigenvectors: +2×2 Array{Complex{Float64},2}: + 0.0-1.0im 0.0+1.0im + -1.0-0.0im -1.0+0.0im + +julia> F.values +2-element Array{Complex{Float64},1}: +0.0 - 1.0im +0.0 + 1.0im + +julia> F.vectors +2×2 Array{Complex{Float64},2}: +0.0+1.0im 0.0-1.0im +-1.0+0.0im -1.0-0.0im + +julia> vals, vecs = F; # destructuring via iteration + +julia> vals == F.values && vecs == F.vectors +true +""" struct GeneralizedEigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} values::U vectors::S diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index c90f1b8c087d5..848dbdc09aa86 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -1,7 +1,14 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license ## Matrix factorizations and decompositions +""" + LinearAlgebra.Factorization +Abstract type for [matrix factorizations](https://en.wikipedia.org/wiki/Matrix_decomposition) +a.k.a. matrix decompositions. +See [online documentation](@ref man-linalg-factorizations) for a list of available +matrix factorizations. +""" abstract type Factorization{T} end eltype(::Type{<:Factorization{T}}) where {T} = T diff --git a/stdlib/LinearAlgebra/src/hessenberg.jl b/stdlib/LinearAlgebra/src/hessenberg.jl index 7c0fd1dad3652..4e0c4b002a6fc 100644 --- a/stdlib/LinearAlgebra/src/hessenberg.jl +++ b/stdlib/LinearAlgebra/src/hessenberg.jl @@ -14,6 +14,13 @@ Efficient algorithms are implemented for `H \\ b`, `det(H)`, and similar. See also the [`hessenberg`](@ref) function to factor any matrix into a similar upper-Hessenberg matrix. +If `F::Hessenberg` is the factorization object, the unitary matrix can be accessed +with `F.Q` and the Hessenberg matrix with `F.H`. When `Q` is extracted, the resulting +type is the `HessenbergQ` object, and may be converted to a regular matrix with +[`convert(Array, _)`](@ref) (or `Array(_)` for short). + +Iterating the decomposition produces the factors `F.Q` and `F.H`. + # Examples ```jldoctest julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16] @@ -25,10 +32,10 @@ julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16] julia> UpperHessenberg(A) 4×4 UpperHessenberg{Int64,Array{Int64,2}}: - 1 2 3 4 - 5 6 7 8 - ⋅ 10 11 12 - ⋅ ⋅ 15 16 + 1 2 3 4 + 5 6 7 8 + ⋅ 10 11 12 + ⋅ ⋅ 15 16 ``` """ struct UpperHessenberg{T,S<:AbstractMatrix{T}} <: AbstractMatrix{T} @@ -557,4 +564,4 @@ logabsdet(F::Hessenberg) = logabsdet(F.H; shift=F.μ) function logdet(F::Hessenberg) d,s = logabsdet(F) return d + log(s) -end \ No newline at end of file +end diff --git a/stdlib/LinearAlgebra/src/ldlt.jl b/stdlib/LinearAlgebra/src/ldlt.jl index 2cc84dd2cc8bc..595e6124dc545 100644 --- a/stdlib/LinearAlgebra/src/ldlt.jl +++ b/stdlib/LinearAlgebra/src/ldlt.jl @@ -1,5 +1,26 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + LDLt <: Factorization + +Matrix factorization type of the `LDLt` factorization of a real [`SymTridiagonal`](@ref) +matrix `S` such that `S = L*Diagonal(d)*L'`, where `L` is a [`UnitLowerTriangular`](@ref) +matrix and `d` is a vector. The main use of an `LDLt` factorization `F = ldlt(S)` +is to solve the linear system of equations `Sx = b` with `F\\b`. This is the +return type of [`ldlt`](@ref), the corresponding matrix factorization function. + +# Examples +```jldoctest +julia> S = SymTridiagonal([3., 4., 5.], [1., 2.]) +3×3 SymTridiagonal{Float64,Array{Float64,1}}: + 3.0 1.0 ⋅ + 1.0 4.0 2.0 + ⋅ 2.0 5.0 + +julia> F = ldlt(S) +LDLt{Float64,SymTridiagonal{Float64,Array{Float64,1}}}([3.0 0.3333333333333333 0.0; 0.3333333333333333 3.6666666666666665 0.5454545454545455; 0.0 0.5454545454545455 3.909090909090909]) +``` +""" struct LDLt{T,S<:AbstractMatrix{T}} <: Factorization{T} data::S diff --git a/stdlib/LinearAlgebra/src/lq.jl b/stdlib/LinearAlgebra/src/lq.jl index 4c7e055ed9c9d..0d86d92677953 100644 --- a/stdlib/LinearAlgebra/src/lq.jl +++ b/stdlib/LinearAlgebra/src/lq.jl @@ -1,7 +1,41 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # LQ Factorizations +""" + LQ <: Factorization + +Matrix factorization type of the `LQ` factorization of a matrix `A`. The `LQ` +decomposition is the `QR` decomposition of `transpose(A)`. This is the return +type of [`lq`](@ref), the corresponding matrix factorization function. + +If `S::LQ` is the factorization object, the lower triangular component can be +obtained via `S.L`, and the orthogonal/unitary component via `S.Q`, such that +`A ≈ S.L*S.Q`. + +Iterating the decomposition produces the components `S.L` and `S.Q`. + +# Examples +```jldoctest +julia> A = [5. 7.; -2. -4.] +2×2 Array{Float64,2}: + 5.0 7.0 + -2.0 -4.0 +julia> S = lq(A) +LQ{Float64,Array{Float64,2}} with factors L and Q: +[-8.60233 0.0; 4.41741 -0.697486] +[-0.581238 -0.813733; -0.813733 0.581238] + +julia> S.L * S.Q +2×2 Array{Float64,2}: + 5.0 7.0 + -2.0 -4.0 + +julia> l, q = S; # destructuring via iteration + +julia> l == S.L && q == S.Q +true +""" struct LQ{T,S<:AbstractMatrix{T}} <: Factorization{T} factors::S τ::Vector{T} diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index 5748acd7eb0c0..00f0fa3253a75 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -3,6 +3,50 @@ #################### # LU Factorization # #################### +""" + LU <: Factorization + +Matrix factorization type of the `LU` factorization of a square matrix `A`. This +is the return type of [`lu`](@ref), the corresponding matrix factorization function. + +The individual components of the factorization `F::LU` can be accessed via `getproperty`: + +| Component | Description | +|:----------|:-----------------------------------------| +| `F.L` | `L` (unit lower triangular) part of `LU` | +| `F.U` | `U` (upper triangular) part of `LU` | +| `F.p` | (right) permutation `Vector` | +| `F.P` | (right) permutation `Matrix` | + +Iterating the factorization produces the components `F.L`, `F.U`, and `F.p`. + +# Examples +```jldoctest +julia> A = [4 3; 6 3] +2×2 Array{Int64,2}: + 4 3 + 6 3 + +julia> F = lu(A) +LU{Float64,Array{Float64,2}} +L factor: +2×2 Array{Float64,2}: + 1.0 0.0 + 1.5 1.0 +U factor: +2×2 Array{Float64,2}: + 4.0 3.0 + 0.0 -1.5 + +julia> F.L * F.U == A[F.p, :] +true + +julia> l, u, p = lu(A); # destructuring via iteration + +julia> l == F.L && u == F.U && p == F.p +true +``` +""" struct LU{T,S<:AbstractMatrix{T}} <: Factorization{T} factors::S ipiv::Vector{BlasInt} diff --git a/stdlib/LinearAlgebra/src/matmul.jl b/stdlib/LinearAlgebra/src/matmul.jl index c9cf328eeb294..d3a3a6a5bdaa9 100644 --- a/stdlib/LinearAlgebra/src/matmul.jl +++ b/stdlib/LinearAlgebra/src/matmul.jl @@ -41,9 +41,10 @@ function *(transx::Transpose{<:Any,<:StridedVector{T}}, y::StridedVector{T}) whe end # Matrix-vector multiplication -function (*)(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} +function (*)(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S<:Real} TS = promote_op(matprod, T, S) - mul!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) + y = isconcretetype(TS) ? convert(AbstractVector{TS}, x) : x + mul!(similar(x, TS, size(A,1)), A, y) end function (*)(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} TS = promote_op(matprod, T, S) diff --git a/stdlib/LinearAlgebra/src/schur.jl b/stdlib/LinearAlgebra/src/schur.jl index 8cb785eb7a0d9..9457f71b415af 100644 --- a/stdlib/LinearAlgebra/src/schur.jl +++ b/stdlib/LinearAlgebra/src/schur.jl @@ -1,6 +1,52 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # Schur decomposition +""" + Schur <: Factorization + +Matrix factorization type of the Schur factorization of a matrix `A`. This is the +return type of [`schur(_)`](@ref), the corresponding matrix factorization function. + +If `F::Schur` is the factorization object, the (quasi) triangular Schur factor can +be obtained via either `F.Schur` or `F.T` and the orthogonal/unitary Schur vectors +via `F.vectors` or `F.Z` such that `A = F.vectors * F.Schur * F.vectors'`. The +eigenvalues of `A` can be obtained with `F.values`. + +Iterating the decomposition produces the components `F.T`, `F.Z`, and `F.values`. + +# Examples +```jldoctest +julia> A = [5. 7.; -2. -4.] +2×2 Array{Float64,2}: + 5.0 7.0 + -2.0 -4.0 + +julia> F = schur(A) +Schur{Float64,Array{Float64,2}} +T factor: +2×2 Array{Float64,2}: + 3.0 9.0 + 0.0 -2.0 +Z factor: +2×2 Array{Float64,2}: + 0.961524 0.274721 + -0.274721 0.961524 +eigenvalues: +2-element Array{Float64,1}: + 3.0 + -2.0 + +julia> F.vectors * F.Schur * F.vectors' +2×2 Array{Float64,2}: + 5.0 7.0 + -2.0 -4.0 + +julia> t, z, vals = F; # destructuring via iteration + +julia> t == F.T && z == F.Z && vals == F.values +true +``` +""" struct Schur{Ty,S<:AbstractMatrix} <: Factorization{Ty} T::S Z::S @@ -155,6 +201,23 @@ included or both excluded via `select`. ordschur(schur::Schur, select::Union{Vector{Bool},BitVector}) = Schur(_ordschur(schur.T, schur.Z, select)...) +""" + GeneralizedSchur <: Factorization + +Matrix factorization type of the generalized Schur factorization of two matrices +`A` and `B`. This is the return type of [`schur(_, _)`](@ref), the corresponding +matrix factorization function. + +If `F::GeneralizedSchur` is the factorization object, the (quasi) triangular Schur +factors can be obtained via `F.S` and `F.T`, the left unitary/orthogonal Schur +vectors via `F.left` or `F.Q`, and the right unitary/orthogonal Schur vectors can +be obtained with `F.right` or `F.Z` such that `A=F.left*F.S*F.right'` and +`B=F.left*F.T*F.right'`. The generalized eigenvalues of `A` and `B` can be obtained +with `F.α./F.β`. + +Iterating the decomposition produces the components `F.S`, `F.T`, `F.Q`, `F.Z`, +`F.α`, and `F.β`. +""" struct GeneralizedSchur{Ty,M<:AbstractMatrix} <: Factorization{Ty} S::M T::M diff --git a/stdlib/LinearAlgebra/src/svd.jl b/stdlib/LinearAlgebra/src/svd.jl index 76d9fcb934633..89b7501811230 100644 --- a/stdlib/LinearAlgebra/src/svd.jl +++ b/stdlib/LinearAlgebra/src/svd.jl @@ -1,6 +1,43 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # Singular Value Decomposition +""" + SVD <: Factorization + +Matrix factorization type of the singular value decomposition (SVD) of a matrix `A`. +This is the return type of [`svd(_)`](@ref), the corresponding matrix factorization function. + +If `F::SVD` is the factorization object, `U`, `S`, `V` and `Vt` can be obtained +via `F.U`, `F.S`, `F.V` and `F.Vt`, such that `A = U * Diagonal(S) * Vt`. +The singular values in `S` are sorted in descending order. + +Iterating the decomposition produces the components `U`, `S`, and `V`. + +# Examples +```jldoctest +julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.] +4×5 Array{Float64,2}: + 1.0 0.0 0.0 0.0 2.0 + 0.0 0.0 3.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.0 + 0.0 2.0 0.0 0.0 0.0 + +julia> F = svd(A) +SVD{Float64,Float64,Array{Float64,2}}([0.0 1.0 0.0 0.0; 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0; 0.0 0.0 1.0 0.0], [3.0, 2.23606797749979, 2.0, 0.0], [-0.0 0.0 … -0.0 0.0; 0.44721359549995787 0.0 … 0.0 0.8944271909999157; -0.0 1.0 … -0.0 0.0; 0.0 0.0 … 1.0 0.0]) + +julia> F.U * Diagonal(F.S) * F.Vt +4×5 Array{Float64,2}: + 1.0 0.0 0.0 0.0 2.0 + 0.0 0.0 3.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.0 + 0.0 2.0 0.0 0.0 0.0 + +julia> u, s, v = F; # destructuring via iteration + +julia> u == F.U && s == F.S && v == F.V +true +``` +""" struct SVD{T,Tr,M<:AbstractArray{T}} <: Factorization{T} U::M S::Vector{Tr} @@ -100,6 +137,11 @@ julia> F.U * Diagonal(F.S) * F.Vt 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 + +julia> u, s, v = F; # destructuring via iteration + +julia> u == F.U && s == F.S && v == F.V +true ``` """ function svd(A::StridedVecOrMat{T}; full::Bool = false) where T @@ -200,6 +242,59 @@ size(A::SVD, dim::Integer) = dim == 1 ? size(A.U, dim) : size(A.Vt, dim) size(A::SVD) = (size(A, 1), size(A, 2)) # Generalized svd +""" + GeneralizedSVD <: Factorization + +Matrix factorization type of the generalized singular value decomposition (SVD) +of two matrices `A` and `B`, such that `A = F.U*F.D1*F.R0*F.Q'` and +`B = F.V*F.D2*F.R0*F.Q'`. This is the return type of [`svd(_, _)`](@ref), the +corresponding matrix factorization function. + +For an M-by-N matrix `A` and P-by-N matrix `B`, + +- `U` is a M-by-M orthogonal matrix, +- `V` is a P-by-P orthogonal matrix, +- `Q` is a N-by-N orthogonal matrix, +- `D1` is a M-by-(K+L) diagonal matrix with 1s in the first K entries, +- `D2` is a P-by-(K+L) matrix whose top right L-by-L block is diagonal, +- `R0` is a (K+L)-by-N matrix whose rightmost (K+L)-by-(K+L) block is + nonsingular upper block triangular, + +`K+L` is the effective numerical rank of the matrix `[A; B]`. + +Iterating the decomposition produces the components `U`, `V`, `Q`, `D1`, `D2`, and `R0`. + +The entries of `F.D1` and `F.D2` are related, as explained in the LAPACK +documentation for the +[generalized SVD](http://www.netlib.org/lapack/lug/node36.html) and the +[xGGSVD3](http://www.netlib.org/lapack/explore-html/d6/db3/dggsvd3_8f.html) +routine which is called underneath (in LAPACK 3.6.0 and newer). + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> F = svd(A, B); + +julia> F.U*F.D1*F.R0*F.Q' +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> F.V*F.D2*F.R0*F.Q' +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 +``` +""" struct GeneralizedSVD{T,S} <: Factorization{T} U::S V::S diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 14bae24d8c020..8b855370445c9 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -74,6 +74,12 @@ implemented for a custom type, so should be `symmetric_type`, and vice versa. function symmetric_type(::Type{T}) where {S, T<:AbstractMatrix{S}} return Symmetric{Union{S, promote_op(transpose, S), symmetric_type(S)}, T} end +function symmetric_type(::Type{T}) where {S<:Number, T<:AbstractMatrix{S}} + return Symmetric{S, T} +end +function symmetric_type(::Type{T}) where {S<:AbstractMatrix, T<:AbstractMatrix{S}} + return Symmetric{AbstractMatrix, T} +end symmetric_type(::Type{T}) where {T<:Number} = T struct Hermitian{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T} @@ -147,9 +153,15 @@ The type of the object returned by `hermitian(::T, ::Symbol)`. For matrices, thi appropriately typed `Hermitian`, for `Number`s, it is the original type. If `hermitian` is implemented for a custom type, so should be `hermitian_type`, and vice versa. """ -function hermitian_type(::Type{T}) where {S,T<:AbstractMatrix{S}} +function hermitian_type(::Type{T}) where {S, T<:AbstractMatrix{S}} return Hermitian{Union{S, promote_op(adjoint, S), hermitian_type(S)}, T} end +function hermitian_type(::Type{T}) where {S<:Number, T<:AbstractMatrix{S}} + return Hermitian{S, T} +end +function hermitian_type(::Type{T}) where {S<:AbstractMatrix, T<:AbstractMatrix{S}} + return Hermitian{AbstractMatrix, T} +end hermitian_type(::Type{T}) where {T<:Number} = T for (S, H) in ((:Symmetric, :Hermitian), (:Hermitian, :Symmetric)) diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 6a1ca14841bf1..4341adfe2ca71 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -491,10 +491,10 @@ end M = randn(T, 5, 5) MM = [randn(T, 2, 2) for _ in 1:2, _ in 1:2] for transform in (identity, adjoint, transpose, Adjoint, Transpose) - @test lmul!(transform(D), copy(M)) == *(transform(Matrix(D)), M) - @test rmul!(copy(M), transform(D)) == *(M, transform(Matrix(D))) - @test lmul!(transform(DD), copy(MM)) == *(transform(fullDD), MM) - @test rmul!(copy(MM), transform(DD)) == *(MM, transform(fullDD)) + @test lmul!(transform(D), copy(M)) ≈ *(transform(Matrix(D)), M) + @test rmul!(copy(M), transform(D)) ≈ *(M, transform(Matrix(D))) + @test lmul!(transform(DD), copy(MM)) ≈ *(transform(fullDD), MM) + @test rmul!(copy(MM), transform(DD)) ≈ *(MM, transform(fullDD)) end end end diff --git a/stdlib/LinearAlgebra/test/matmul.jl b/stdlib/LinearAlgebra/test/matmul.jl index bf929c3ba3b12..bc3d3d8607afa 100644 --- a/stdlib/LinearAlgebra/test/matmul.jl +++ b/stdlib/LinearAlgebra/test/matmul.jl @@ -508,4 +508,13 @@ end @test success(pipeline(cmd; stdout=stdout, stderr=stderr)) end +struct A32092 + x::Float64 +end +Base.:+(x::Float64, a::A32092) = x + a.x +Base.:*(x::Float64, a::A32092) = x * a.x +@testset "Issue #32092" begin + @test ones(2, 2) * [A32092(1.0), A32092(2.0)] == fill(3.0, (2,)) +end + end # module TestMatmul diff --git a/stdlib/Markdown/src/GitHub/table.jl b/stdlib/Markdown/src/GitHub/table.jl index b09301403443c..b8652e00121e4 100644 --- a/stdlib/Markdown/src/GitHub/table.jl +++ b/stdlib/Markdown/src/GitHub/table.jl @@ -138,12 +138,15 @@ function rst(io::IO, md::Table) end function term(io::IO, md::Table, columns) + margin_str = " "^margin cells = mapmap(x -> terminline_string(io, x), md.rows) padcells!(cells, md.align, len = ansi_length) for i = 1:length(cells) + print(io, margin_str) join(io, cells[i], " ") if i == 1 println(io) + print(io, margin_str) join(io, ["–"^ansi_length(cells[i][j]) for j = 1:length(cells[1])], " ") end i < length(cells) && println(io) diff --git a/stdlib/Markdown/src/Markdown.jl b/stdlib/Markdown/src/Markdown.jl index 052a6fc36d217..35b3851febd0e 100644 --- a/stdlib/Markdown/src/Markdown.jl +++ b/stdlib/Markdown/src/Markdown.jl @@ -8,6 +8,9 @@ module Markdown import Base: show, ==, with_output_color using Base64: stringmime +# Margin for printing in terminal. +const margin = 2 + include("parse/config.jl") include("parse/util.jl") include("parse/parse.jl") diff --git a/stdlib/Markdown/src/render/terminal/render.jl b/stdlib/Markdown/src/render/terminal/render.jl index 90924c928cfad..3edc16e62a3bf 100644 --- a/stdlib/Markdown/src/render/terminal/render.jl +++ b/stdlib/Markdown/src/render/terminal/render.jl @@ -2,7 +2,6 @@ include("formatting.jl") -const margin = 2 cols(io) = displaysize(io)[2] function term(io::IO, content::Vector, cols) diff --git a/stdlib/Markdown/test/runtests.jl b/stdlib/Markdown/test/runtests.jl index 6c5f82278eddf..251ad4cc4bd45 100644 --- a/stdlib/Markdown/test/runtests.jl +++ b/stdlib/Markdown/test/runtests.jl @@ -244,6 +244,21 @@ let doc = Markdown.parse( @test !occursin("3. ", sprint(term, doc)) end +# Testing margin when printing Tables to the terminal. +@test sprint(term, md""" +| R | +|---| +| L | +""") == " R\n –\n L" + +@test sprint(term, md""" +!!! note "Tables in admonitions" + + | R | + |---| + | L | +""") == " │ Tables in admonitions\n │\n │ R\n │ –\n │ L" + # HTML output @test md"foo *bar* baz" |> html == "

foo bar baz

\n" @test md"something ***" |> html == "

something ***

\n" @@ -1085,7 +1100,7 @@ t = """ a | b :-- | --: 1 | 2""" -@test sprint(Markdown.term, Markdown.parse(t), 0) == "a b\n– –\n1 2" +@test sprint(Markdown.term, Markdown.parse(t), 0) == " a b\n – –\n 1 2" # test Base.copy let diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index e45227e03fe36..8336874404d1f 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -1015,8 +1015,8 @@ function deserialize(s::AbstractSerializer, ::Type{CodeInfo}) ci.slottypes = deserialize(s) ci.rettype = deserialize(s) ci.parent = deserialize(s) - ci.min_world = deserialize(s) - ci.max_world = deserialize(s) + ci.min_world = reinterpret(UInt, deserialize(s)) + ci.max_world = reinterpret(UInt, deserialize(s)) end ci.inferred = deserialize(s) ci.inlineable = deserialize(s) diff --git a/stdlib/Sockets/docs/src/index.md b/stdlib/Sockets/docs/src/index.md index f993e83480eaa..90acd104182f2 100644 --- a/stdlib/Sockets/docs/src/index.md +++ b/stdlib/Sockets/docs/src/index.md @@ -30,6 +30,8 @@ Sockets.send Sockets.recv Sockets.recvfrom Sockets.setopt +Sockets.nagle +Sockets.quickack ``` ```@meta diff --git a/stdlib/Sockets/src/IPAddr.jl b/stdlib/Sockets/src/IPAddr.jl index c77e1f9887064..dc542d5b42ba8 100644 --- a/stdlib/Sockets/src/IPAddr.jl +++ b/stdlib/Sockets/src/IPAddr.jl @@ -10,6 +10,9 @@ abstract type IPAddr end Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) (dt::Type{<:Integer})(ip::IPAddr) = dt(ip.host)::dt +# Allow IP addresses to broadcast as unwrapped scalars +Base.Broadcast.broadcastable(ip::IPAddr) = Ref(ip) + struct IPv4 <: IPAddr host::UInt32 IPv4(host::UInt32) = new(host) diff --git a/stdlib/Sockets/src/Sockets.jl b/stdlib/Sockets/src/Sockets.jl index 8f55edcf6b533..0c6e867b20639 100644 --- a/stdlib/Sockets/src/Sockets.jl +++ b/stdlib/Sockets/src/Sockets.jl @@ -471,6 +471,31 @@ function connect(sock::LibuvStream, args...) return sock end +""" + nagle(socket::Union{TCPServer, TCPSocket}, enable::Bool) + +Enables or disables Nagle's algorithm on a given TCP server or socket. +""" +function nagle(sock::Union{TCPServer, TCPSocket}, enable::Bool) + # disable or enable Nagle's algorithm on all OSes + ccall(:uv_tcp_nodelay, Cint, (Ptr{Cvoid}, Cint), sock.handle, Cint(!enable)) +end + +""" + quickack(socket::Union{TCPServer, TCPSocket}, enable::Bool) + +On Linux systems, the TCP_QUICKACK is disabled or enabled on `socket`. +""" +function quickack(sock::Union{TCPServer, TCPSocket}, enable::Bool) + @static if Sys.islinux() + # tcp_quickack is a linux only option + if ccall(:jl_tcp_quickack, Cint, (Ptr{Cvoid}, Cint), sock.handle, Cint(enable)) < 0 + @warn "Networking unoptimized ( Error enabling TCP_QUICKACK : $(Libc.strerror(Libc.errno())) )" maxlog=1 + end + end +end + + ## const BACKLOG_DEFAULT = 511 diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl index 8e1e0f084db59..a799a731cbe95 100644 --- a/stdlib/Sockets/src/addrinfo.jl +++ b/stdlib/Sockets/src/addrinfo.jl @@ -234,10 +234,14 @@ ip"fe80::9731:35af:e1c5:6e49" """ function getipaddr(addr_type::Type{T}) where T<:IPAddr addrs = getipaddrs(addr_type) + if length(addrs) == 0 error("No networking interface available") end - return addrs[1] + + # Prefer the first IPv4 address + i = something(findfirst(ip -> ip isa IPv4, addrs), 1) + return addrs[i] end getipaddr() = getipaddr(IPv4) @@ -295,14 +299,5 @@ function getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IP end end ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count) - sort!(addresses, lt=(addr1,addr2) -> begin - if addr1 isa IPv4 && addr2 isa IPv6 - return true - elseif addr1 isa IPv6 && addr2 isa IPv4 - return false - else - return addr1 < addr2 - end - end) return addresses end diff --git a/stdlib/Sockets/test/runtests.jl b/stdlib/Sockets/test/runtests.jl index f60981cdb583f..1263a81d3f381 100644 --- a/stdlib/Sockets/test/runtests.jl +++ b/stdlib/Sockets/test/runtests.jl @@ -79,6 +79,11 @@ end @test_throws MethodError sort([ip"2.3.4.5", ip"1.2.3.4", ip"2001:1:2::1"]) end +@testset "broadcastable" begin + @test size(ip"127.0.0.1" .== ip"127.0.0.1") == () + @test size(ip"::1" .== ip"::1") == () +end + @testset "RFC 5952 Compliance" begin @test repr(ip"2001:db8:0:0:0:0:2:1") == "ip\"2001:db8::2:1\"" @test repr(ip"2001:0db8::0001") == "ip\"2001:db8::1\"" diff --git a/stdlib/SparseArrays/src/SparseArrays.jl b/stdlib/SparseArrays/src/SparseArrays.jl index 87ee6a38a80cb..f8417a1d33628 100644 --- a/stdlib/SparseArrays/src/SparseArrays.jl +++ b/stdlib/SparseArrays/src/SparseArrays.jl @@ -13,7 +13,7 @@ using LinearAlgebra import Base: +, -, *, \, /, &, |, xor, == import LinearAlgebra: mul!, ldiv!, rdiv!, cholesky, adjoint!, diag, eigen, dot, issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!, - cond, diagm, factorize, ishermitian, norm, opnorm, lmul!, rmul!, tril, triu + cond, diagm, factorize, ishermitian, norm, opnorm, lmul!, rmul!, tril, triu, matprod import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, atan, atand, atanh, broadcast!, conj!, cos, cosc, cosd, cosh, cospi, cot, @@ -52,7 +52,6 @@ similar(D::Diagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzero similar(S::SymTridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) similar(M::Tridiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = spzeros(T, dims...) -matprod(x, y) = x*y + x*y const BiTriSym = Union{Bidiagonal,SymTridiagonal,Tridiagonal} function *(A::BiTriSym, B::BiTriSym) TS = promote_op(matprod, eltype(A), eltype(B)) diff --git a/stdlib/SparseArrays/src/abstractsparse.jl b/stdlib/SparseArrays/src/abstractsparse.jl index 973d2df10326b..2ebea517f2292 100644 --- a/stdlib/SparseArrays/src/abstractsparse.jl +++ b/stdlib/SparseArrays/src/abstractsparse.jl @@ -1,4 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license + """ AbstractSparseArray{Tv,Ti,N} @@ -63,21 +64,31 @@ end # The following two methods should be overloaded by concrete types to avoid # allocating the I = findall(...) -_sparse_findnextnz(v::AbstractSparseArray, i::Integer) = (I = findall(!iszero, v); n = searchsortedfirst(I, i); n<=length(I) ? I[n] : nothing) -_sparse_findprevnz(v::AbstractSparseArray, i::Integer) = (I = findall(!iszero, v); n = searchsortedlast(I, i); !iszero(n) ? I[n] : nothing) - -function findnext(f::typeof(!iszero), v::AbstractSparseArray, i::Integer) +_sparse_findnextnz(v::AbstractSparseArray, i) = (I = findall(!iszero, v); n = searchsortedfirst(I, i); n<=length(I) ? I[n] : nothing) +_sparse_findprevnz(v::AbstractSparseArray, i) = (I = findall(!iszero, v); n = searchsortedlast(I, i); !iszero(n) ? I[n] : nothing) + +function findnext(f::Function, v::AbstractSparseArray, i) + # short-circuit the case f == !iszero because that avoids + # allocating e.g. zero(BigInt) for the f(zero(...)) test. + if nnz(v) == length(v) || (f != (!iszero) && f(zero(eltype(v)))) + return invoke(findnext, Tuple{Function,Any,Any}, f, v, i) + end j = _sparse_findnextnz(v, i) while j !== nothing && !f(v[j]) - j = _sparse_findnextnz(v, j+1) + j = _sparse_findnextnz(v, nextind(v, j)) end return j end -function findprev(f::typeof(!iszero), v::AbstractSparseArray, i::Integer) +function findprev(f::Function, v::AbstractSparseArray, i) + # short-circuit the case f == !iszero because that avoids + # allocating e.g. zero(BigInt) for the f(zero(...)) test. + if nnz(v) == length(v) || (f != (!iszero) && f(zero(eltype(v)))) + return invoke(findprev, Tuple{Function,Any,Any}, f, v, i) + end j = _sparse_findprevnz(v, i) while j !== nothing && !f(v[j]) - j = _sparse_findprevnz(v, j-1) + j = _sparse_findprevnz(v, prevind(v, j)) end return j end diff --git a/stdlib/SparseArrays/src/linalg.jl b/stdlib/SparseArrays/src/linalg.jl index b5baa5393f851..4a54d82c3a754 100644 --- a/stdlib/SparseArrays/src/linalg.jl +++ b/stdlib/SparseArrays/src/linalg.jl @@ -50,9 +50,9 @@ function mul!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat, α::Nu C end *(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = - (T = promote_type(TA, Tx); mul!(similar(x, T, A.m), A, x, one(T), zero(T))) + (T = promote_op(matprod, TA, Tx); mul!(similar(x, T, A.m), A, x, one(T), zero(T))) *(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (T = promote_type(TA, Tx); mul!(similar(B, T, (A.m, size(B, 2))), A, B, one(T), zero(T))) + (T = promote_op(matprod, TA, Tx); mul!(similar(B, T, (A.m, size(B, 2))), A, B, one(T), zero(T))) function mul!(C::StridedVecOrMat, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, α::Number, β::Number) A = adjA.parent @@ -76,9 +76,9 @@ function mul!(C::StridedVecOrMat, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::Str C end *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = - (A = adjA.parent; T = promote_type(TA, Tx); mul!(similar(x, T, A.n), adjoint(A), x, one(T), zero(T))) + (A = adjA.parent; T = promote_op(matprod, TA, Tx); mul!(similar(x, T, A.n), adjoint(A), x, one(T), zero(T))) *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (A = adjA.parent; T = promote_type(TA, Tx); mul!(similar(B, T, (A.n, size(B, 2))), adjoint(A), B, one(T), zero(T))) + (A = adjA.parent; T = promote_op(matprod, TA, Tx); mul!(similar(B, T, (A.n, size(B, 2))), adjoint(A), B, one(T), zero(T))) function mul!(C::StridedVecOrMat, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, α::Number, β::Number) A = transA.parent @@ -102,9 +102,9 @@ function mul!(C::StridedVecOrMat, transA::Transpose{<:Any,<:SparseMatrixCSC}, B: C end *(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = - (A = transA.parent; T = promote_type(TA, Tx); mul!(similar(x, T, A.n), transpose(A), x, one(T), zero(T))) + (A = transA.parent; T = promote_op(matprod, TA, Tx); mul!(similar(x, T, A.n), transpose(A), x, one(T), zero(T))) *(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (A = transA.parent; T = promote_type(TA, Tx); mul!(similar(B, T, (A.n, size(B, 2))), transpose(A), B, one(T), zero(T))) + (A = transA.parent; T = promote_op(matprod, TA, Tx); mul!(similar(B, T, (A.n, size(B, 2))), transpose(A), B, one(T), zero(T))) # For compatibility with dense multiplication API. Should be deleted when dense multiplication # API is updated to follow BLAS API. diff --git a/stdlib/SparseArrays/src/sparseconvert.jl b/stdlib/SparseArrays/src/sparseconvert.jl index bdadc3a4729ff..9f4bb6cd452f1 100644 --- a/stdlib/SparseArrays/src/sparseconvert.jl +++ b/stdlib/SparseArrays/src/sparseconvert.jl @@ -76,9 +76,6 @@ For other types return A itself. unwrap(A::Any) = A unwrap(A::AbstractMatrix) = iswrsparse(A) ? convert(SparseMatrixCSC, A) : convert(Array, A) -import Base.copy -copy(A::SubArray{T,2}) where T = getindex(unwrap(parent(A)), A.indices...) - # For pure sparse matrices and vectors return A. # For wrapped sparse matrices or vectors convert to SparseMatrixCSC. # Handle nested wrappers properly. diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index 650fecb706eff..6cd92aa51e0b8 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -1312,36 +1312,34 @@ function findnz(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} return (I, J, V) end -function _sparse_findnextnz(m::SparseMatrixCSC, i::Integer) - if i > length(m) - return nothing - end - row, col = Tuple(CartesianIndices(m)[i]) +function _sparse_findnextnz(m::SparseMatrixCSC, ij::CartesianIndex{2}) + row, col = Tuple(ij) + col > m.n && return nothing + lo, hi = m.colptr[col], m.colptr[col+1] n = searchsortedfirst(m.rowval, row, lo, hi-1, Base.Order.Forward) if lo <= n <= hi-1 - return LinearIndices(m)[m.rowval[n], col] + return CartesianIndex(m.rowval[n], col) end - nextcol = findnext(c->(c>hi), m.colptr, col+1) - nextcol === nothing && return nothing + nextcol = searchsortedfirst(m.colptr, hi + 1, col + 1, length(m.colptr), Base.Order.Forward) + nextcol > length(m.colptr) && return nothing nextlo = m.colptr[nextcol-1] - return LinearIndices(m)[m.rowval[nextlo], nextcol-1] + return CartesianIndex(m.rowval[nextlo], nextcol - 1) end -function _sparse_findprevnz(m::SparseMatrixCSC, i::Integer) - if iszero(i) - return nothing - end - row, col = Tuple(CartesianIndices(m)[i]) +function _sparse_findprevnz(m::SparseMatrixCSC, ij::CartesianIndex{2}) + row, col = Tuple(ij) + iszero(col) && return nothing + lo, hi = m.colptr[col], m.colptr[col+1] n = searchsortedlast(m.rowval, row, lo, hi-1, Base.Order.Forward) if lo <= n <= hi-1 - return LinearIndices(m)[m.rowval[n], col] + return CartesianIndex(m.rowval[n], col) end - prevcol = findprev(c->(c 0 - nzv = nzval[idx] - !isequal(nzv, z) && return idx, nzv - idx -= 1 - end - return zero(idx), z -end - -function _idx_to_cartesian(A::SparseMatrixCSC, idx::Integer) - rowval = rowvals(A) - i = rowval[idx] - j = searchsortedlast(A.colptr, idx, 1, size(A, 2), Base.Order.Forward) - return CartesianIndex(i, j) -end - -function Base.findnext(pred::Function, A::SparseMatrixCSC, ij::CartesianIndex{2}) - if nnz(A) == length(A) || pred(zero(eltype(A))) - return invoke(findnext, Tuple{Function,Any,Any}, pred, A, ij) - end - idx, nzv = _idxfirstnz(A, ij) - while idx > 0 - if pred(nzv) - return _idx_to_cartesian(A, idx) - end - idx, nzv = _idxnextnz(A, idx + 1) - end - return nothing -end - -function Base.findprev(pred::Function, A::SparseMatrixCSC, ij::CartesianIndex{2}) - if nnz(A) == length(A) || pred(zero(eltype(A))) - return invoke(findprev, Tuple{Function,Any,Any}, pred, A, ij) - end - idx, nzv = _idxlastnz(A, ij) - while idx > 0 - if pred(nzv) - return _idx_to_cartesian(A, idx) - end - idx, nzv = _idxprevnz(A, idx - 1) - end - return nothing -end - """ sprand([rng],[type],m,[n],p::AbstractFloat,[rfn]) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index f6ae3c84b2aa3..ed408c9ca7570 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -1584,7 +1584,7 @@ function densemv(A::SparseMatrixCSC, x::AbstractSparseVector; trans::AbstractCha throw(ArgumentError("Invalid trans character $trans")) end xlen == length(x) || throw(DimensionMismatch()) - T = promote_type(eltype(A), eltype(x)) + T = promote_op(matprod, eltype(A), eltype(x)) y = Vector{T}(undef, ylen) if trans == 'N' || trans == 'N' mul!(y, A, x) @@ -1694,7 +1694,7 @@ function _At_or_Ac_mul_B(tfun::Function, A::SparseMatrixCSC{TvA,TiA}, x::Abstrac require_one_based_indexing(A, x) m, n = size(A) length(x) == m || throw(DimensionMismatch()) - Tv = promote_type(TvA, TvX) + Tv = promote_op(matprod, TvA, TvX) Ti = promote_type(TiA, TiX) xnzind = nonzeroinds(x) diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index 836bce0b9eb7a..4adfc3398edd8 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -907,6 +907,14 @@ end @test SparseArrays.densemv(A, x2; trans='C') ≈ Af'x2f @test_throws ArgumentError SparseArrays.densemv(A, x; trans='D') end + + let A = sparse(bitrand(9, 16)), x = sparse(bitrand(16)) + Af = Array(A) + xf = Array(x) + y = SparseArrays.densemv(A, x) + @test isa(y, Vector{Int}) + @test y == Af*xf + end end @testset "sparse A * sparse x -> sparse y" begin let A = sprandn(9, 16, 0.5), x = sprand(16, 0.7), x2 = sprand(9, 0.7) @@ -944,6 +952,35 @@ end @test isa(y, SparseVector{ComplexF64,Int}) @test Array(y) ≈ Af'x2f end + + let A = sparse(bitrand(9, 16)), x = sparse(bitrand(16)), x2 = sparse(bitrand(9)) + Af = Array(A) + xf = Array(x) + x2f = Array(x2) + + y = A*x + @test isa(y, SparseVector{Int, Int}) + @test Array(y) == Af*xf + + y = A'*x2 + @test isa(y, SparseVector{Int, Int}) + @test Array(y) == Af'x2f + end + end + @testset "sparse A * dense x -> dense y" begin + let A = sparse(bitrand(9, 16)), x = Vector(bitrand(16)), x2 = Vector(bitrand(9)) + Af = Array(A) + xf = Array(x) + x2f = Array(x2) + + y = A*x + @test isa(y, Vector{Int}) + @test y == Af*xf + + y = A'*x2 + @test isa(y, Vector{Int}) + @test y == Af'x2f + end end @testset "ldiv ops with triangular matrices and sparse vecs (#14005)" begin m = 10 diff --git a/test/abstractarray.jl b/test/abstractarray.jl index f801d9982176d..9ef96a3211b2a 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -865,8 +865,8 @@ for A in (rand(2), rand(2,3)) end @test Array(values(A)) == A - @test keytype(A) == eltype(keys(A)) - @test valtype(A) == eltype(values(A)) + @test keytype(A) == keytype(typeof(A)) == eltype(keys(A)) + @test valtype(A) == valtype(typeof(A)) == eltype(values(A)) end # nextind and prevind diff --git a/test/arrayops.jl b/test/arrayops.jl index fab2802eb1678..ae7300e8647bb 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -381,6 +381,14 @@ end @test findall(in([1, 2]), 2) == [1] @test findall(in([1, 2]), 3) == [] + + @test sort(findall(Dict(1=>false, 2=>true, 3=>true))) == [2, 3] + + @test findall(true) == [1] + @test findall(false) == Int[] + + @test findall(isodd, 1) == [1] + @test findall(isodd, 2) == Int[] end @testset "setindex! return type" begin rt = Base.return_types(setindex!, Tuple{Array{Int32, 3}, Vector{UInt8}, Vector{Int}, Int16, UnitRange{Int}}) @@ -526,6 +534,7 @@ end @test findfirst(!iszero, a) == 2 @test findfirst(a.==0) == 1 @test findfirst(a.==5) == nothing + @test findfirst(Dict(1=>false, 2=>true)) == 2 @test findfirst(isequal(3), [1,2,4,1,2,3,4]) == 6 @test findfirst(!isequal(1), [1,2,4,1,2,3,4]) == 2 @test findfirst(isodd, [2,4,6,3,9,2,0]) == 4 diff --git a/test/broadcast.jl b/test/broadcast.jl index 3e39d14cfb440..5ee56cf94fe87 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -817,4 +817,8 @@ end let a = rand(5), b = rand(5), c = copy(a) view(identity(a), 1:3) .+= view(b, 1:3) @test a == [(c+b)[1:3]; c[4:5]] + + x = [1] + x[[1,1]] .+= 1 + @test x == [2] end diff --git a/test/clangsa/GCPushPop.cpp b/test/clangsa/GCPushPop.cpp index a3c40de75da98..d8591b7b10473 100644 --- a/test/clangsa/GCPushPop.cpp +++ b/test/clangsa/GCPushPop.cpp @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + // RUN: %clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang %gc_plugin -Xclang -verify -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include -Xclang -analyzer-checker=core,julia.GCChecker -x c++ %s #include "julia.h" diff --git a/test/clangsa/MissingRoots.c b/test/clangsa/MissingRoots.c index 77d220035b4c8..dc612ae4cbe9e 100644 --- a/test/clangsa/MissingRoots.c +++ b/test/clangsa/MissingRoots.c @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + // RUN: %clang --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang %gc_plugin -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include -Xclang -analyzer-checker=core,julia.GCChecker --analyzer-no-default-checks -Xclang -verify -Xclang -verify-ignore-unexpected=note -x c %s #include "julia.h" diff --git a/test/client.jl b/test/client.jl index fafb476be547c..37516fb00ea91 100644 --- a/test/client.jl +++ b/test/client.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + nested_error_expr = quote try __not_a_binding__ diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 92b72955451fd..74d98c2511ad5 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -97,6 +97,13 @@ let exename = `$(Base.julia_cmd()) --startup-file=no` @test startswith(read(`$exename --help`, String), header) end + # ~ expansion in --project and JULIA_PROJECT + if !Sys.iswindows() + expanded = abspath(expanduser("~/foo")) + @test occursin(expanded, readchomp(`$exename --project='~/foo' -E 'Base.active_project()'`)) + @test occursin(expanded, readchomp(setenv(`$exename -E 'Base.active_project()'`, "JULIA_PROJECT"=>"~/foo"))) + end + # --quiet, --banner let t(q,b) = "Base.JLOptions().quiet == $q && Base.JLOptions().banner == $b" @test success(`$exename -e $(t(0, -1))`) diff --git a/test/complex.jl b/test/complex.jl index 2405375f040bf..44cc393dac9f1 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -999,6 +999,46 @@ end end end +@testset "division by Inf, issue#23134" begin + @testset "$T" for T in (Float32, Float64, BigFloat) + @test isequal(one(T) / complex(T(Inf)), complex(zero(T), -zero(T))) + @test isequal(one(T) / complex(T(Inf), one(T)), complex(zero(T), -zero(T))) + @test isequal(one(T) / complex(T(Inf), T(NaN)), complex(zero(T), -zero(T))) + @test isequal(one(T) / complex(T(Inf), T(Inf)), complex(zero(T), -zero(T))) + + @test isequal(one(T) / complex(T(-Inf)), complex(-zero(T), -zero(T))) + @test isequal(one(T) / complex(T(-Inf), one(T)), complex(-zero(T), -zero(T))) + @test isequal(one(T) / complex(T(-Inf), T(NaN)), complex(-zero(T), -zero(T))) + @test isequal(one(T) / complex(T(-Inf), T(Inf)), complex(-zero(T), -zero(T))) + + @test isequal(one(T) / complex(T(Inf),-zero(T)), complex(zero(T), zero(T))) + @test isequal(one(T) / complex(T(Inf),-one(T)), complex(zero(T), zero(T))) + @test isequal(one(T) / complex(T(Inf),T(-NaN)), complex(zero(T), zero(T))) + @test isequal(one(T) / complex(T(Inf),T(-Inf)), complex(zero(T), zero(T))) + + @test isequal(one(T) / complex(T(-Inf),-zero(T)),complex(-zero(T), zero(T))) + @test isequal(one(T) / complex(T(-Inf),-one(T)), complex(-zero(T), zero(T))) + @test isequal(one(T) / complex(T(-Inf),T(-NaN)), complex(-zero(T), zero(T))) + @test isequal(one(T) / complex(T(-Inf),T(-Inf)), complex(-zero(T), zero(T))) + + @test isequal(one(T) / complex(zero(T), T(Inf)), complex(zero(T), -zero(T))) + @test isequal(one(T) / complex(one(T), T(Inf)), complex(zero(T), -zero(T))) + @test isequal(one(T) / complex(T(NaN), T(Inf)), complex(zero(T), -zero(T))) + + @test isequal(one(T) / complex(zero(T), T(-Inf)), complex(zero(T), zero(T))) + @test isequal(one(T) / complex(one(T), T(-Inf)), complex(zero(T), zero(T))) + @test isequal(one(T) / complex(T(NaN), T(-Inf)), complex(zero(T), zero(T))) + + @test isequal(one(T) / complex(-zero(T), T(Inf)), complex(-zero(T), -zero(T))) + @test isequal(one(T) / complex(-one(T), T(Inf)), complex(-zero(T), -zero(T))) + @test isequal(one(T) / complex(T(-NaN), T(Inf)), complex(-zero(T), -zero(T))) + + @test isequal(one(T) / complex(-zero(T), T(-Inf)), complex(-zero(T), zero(T))) + @test isequal(one(T) / complex(-one(T), T(-Inf)), complex(-zero(T), zero(T))) + @test isequal(one(T) / complex(T(-NaN), T(-Inf)), complex(-zero(T), zero(T))) + end +end + @testset "complex^real, issue #14342" begin for T in (Float32, Float64, BigFloat), p in (T(-21//10), -21//10) z = T(2)+0im diff --git a/test/core.jl b/test/core.jl index 8905691d66c02..14375439ebfee 100644 --- a/test/core.jl +++ b/test/core.jl @@ -227,8 +227,8 @@ let ft = Base.datatype_fieldtypes @test ft(elT2.body)[1].parameters[1] === elT2 @test Base.isconcretetype(ft(elT2.body)[1]) end -struct S22624{A,B,C} <: Ref{S22624{Int64,A}}; end -@test @isdefined S22624 +#struct S22624{A,B,C} <: Ref{S22624{Int64,A}}; end +@test_broken @isdefined S22624 # issue #3890 mutable struct A3890{T1} @@ -6976,3 +6976,15 @@ let spvec = sparse_t31649(zeros(Float64,5), Vector{Int64}()) @test convert(Any, nothing) === nothing @test_throws MethodError repr(spvec) end + +# Issue #31062 - Accidental recursion in jl_has_concrete_subtype +struct Bar31062 + x::NTuple{N, Bar31062} where N +end +struct Foo31062 + x::Foo31062 +end +# Use eval to make sure that this actually gets executed and not +# just constant folded by (future) over-eager compiler optimizations +@test isa(Core.eval(@__MODULE__, :(Bar31062(()))), Bar31062) +@test precompile(identity, (Foo31062,)) diff --git a/test/dict.jl b/test/dict.jl index 904cdb9526c57..1f6594d84d88c 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -819,6 +819,8 @@ Dict(1 => rand(2,3), 'c' => "asdf") # just make sure this does not trigger a dep @test WeakKeyDict(a=>i+1 for (i,a) in enumerate([A,B,C]) ) == wkd @test WeakKeyDict([(A,2), (B,3), (C,4)]) == wkd @test WeakKeyDict(Pair(A,2), Pair(B,3), Pair(C,4)) == wkd + @test isa(WeakKeyDict(Pair(A,2), Pair(B,3.0), Pair(C,4)), WeakKeyDict{Array{Int,1},Any}) + @test isa(WeakKeyDict(Pair(convert(Vector{Number}, A),2), Pair(B,3), Pair(C,4)), WeakKeyDict{Any,Int}) @test copy(wkd) == wkd @test length(wkd) == 3 diff --git a/test/embedding/include_and_eval.jl b/test/embedding/include_and_eval.jl index 3b82ba2ea8ba1..8e53187ea4d0b 100644 --- a/test/embedding/include_and_eval.jl +++ b/test/embedding/include_and_eval.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + function f28825() eval(:(1+1)) end diff --git a/test/errorshow.jl b/test/errorshow.jl index 5a85430516ffb..7666b5ca5b6fe 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -225,6 +225,11 @@ let end struct TypeWithIntParam{T <: Integer} end +struct Bounded # not an AbstractArray + bound::Int +end +Base.getindex(b::Bounded, i) = checkindex(Bool, 1:b.bound, i) || throw(BoundsError(b, i)) +Base.summary(io::IO, b::Bounded) = print(io, "$(b.bound)-size Bounded") let undefvar err_str = @except_strbt sqrt(-1) DomainError @test occursin("Try sqrt(Complex(x)).", err_str) @@ -246,6 +251,9 @@ let undefvar err_str = @except_str [5, 4, 3][1:5] BoundsError @test err_str == "BoundsError: attempt to access 3-element Array{$Int,1} at index [1:5]" + err_str = @except_str Bounded(2)[3] BoundsError + @test err_str == "BoundsError: attempt to access 2-size Bounded\n at index [3]" + err_str = @except_str 0::Bool TypeError @test err_str == "TypeError: non-boolean ($Int) used in boolean context" err_str = @except_str 0::AbstractFloat TypeError diff --git a/test/int.jl b/test/int.jl index 4fc0ad0604155..4a93543709a5b 100644 --- a/test/int.jl +++ b/test/int.jl @@ -54,12 +54,15 @@ using Random end end end -@testset "signed" begin +@testset "signed and unsigned" begin @test signed(3) == 3 @test signed(UInt(3)) == 3 @test isa(signed(UInt(3)), Int) @test signed(UInt(0) - 1) == -1 @test_throws InexactError signed(UInt(-3)) + @test signed(true) == 1 + @test unsigned(true) isa Unsigned + @test unsigned(true) == unsigned(1) end @testset "bswap" begin @test bswap(Int8(3)) == 3 diff --git a/test/keywordargs.jl b/test/keywordargs.jl index eacacdc2ea248..781652d4dae8c 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -342,3 +342,14 @@ end @test g() == (1,1) @test g(2) == (2,2) end + +# issue #32074 +function g32074(i::Float32; args...) + hook(i; args...) = args + hook(i; args...) +end +function g32074(i::Int32; args...) + hook(i; args...) = args + hook(i; args...) +end +@test isempty(g32074(Int32(1))) diff --git a/test/llvmpasses/alloc-opt.jl b/test/llvmpasses/alloc-opt.jl index ec2ffc5628bad..a3e68123131ca 100644 --- a/test/llvmpasses/alloc-opt.jl +++ b/test/llvmpasses/alloc-opt.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -# RUN: julia --startup-file=no %s | opt -load libjulia%shlibext -AllocOpt -LateLowerGCFrame -S - | FileCheck %s +# RUN: julia --startup-file=no %s | opt -load libjulia%shlibext -AllocOpt -LateLowerGCFrame -FinalLowerGC -S - | FileCheck %s isz = sizeof(UInt) == 8 ? "i64" : "i32" diff --git a/test/llvmpasses/final-lower-gc.ll b/test/llvmpasses/final-lower-gc.ll new file mode 100644 index 0000000000000..b1776aea8d701 --- /dev/null +++ b/test/llvmpasses/final-lower-gc.ll @@ -0,0 +1,73 @@ +; RUN: opt -load libjulia%shlibext -FinalLowerGC -S %s | FileCheck %s + +%jl_value_t = type opaque +@tag = external addrspace(10) global %jl_value_t + +declare void @boxed_simple(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)*) +declare %jl_value_t addrspace(10)* @jl_box_int64(i64) +declare %jl_value_t*** @julia.ptls_states() +declare void @jl_safepoint() +declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) + +declare noalias nonnull %jl_value_t addrspace(10)** @julia.new_gc_frame(i32) +declare void @julia.push_gc_frame(%jl_value_t addrspace(10)**, i32) +declare %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)**, i32) +declare void @julia.pop_gc_frame(%jl_value_t addrspace(10)**) +declare noalias nonnull %jl_value_t addrspace(10)* @julia.gc_alloc_bytes(i8*, i64) #0 + +attributes #0 = { allocsize(1) } + +define void @gc_frame_lowering(i64 %a, i64 %b) { +top: +; CHECK-LABEL: @gc_frame_lowering +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 + %gcframe = call %jl_value_t addrspace(10)** @julia.new_gc_frame(i32 2) +; CHECK: %ptls = call %jl_value_t*** @julia.ptls_states() + %ptls = call %jl_value_t*** @julia.ptls_states() +; CHECK-NEXT: [[GCFRAME_SIZE_PTR:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 0 +; CHECK-NEXT: [[GCFRAME_SIZE_PTR2:%.*]] = bitcast %jl_value_t addrspace(10)** [[GCFRAME_SIZE_PTR]] to i64* +; CHECK-NEXT: store i64 4, i64* [[GCFRAME_SIZE_PTR2]], !tbaa !0 +; CHECK-NEXT: [[GCFRAME_SLOT:%.*]] = getelementptr %jl_value_t**, %jl_value_t*** %ptls, i32 0 +; CHECK-NEXT: [[PREV_GCFRAME_PTR:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 1 +; CHECK-NEXT: [[PREV_GCFRAME_PTR2:%.*]] = bitcast %jl_value_t addrspace(10)** [[PREV_GCFRAME_PTR]] to %jl_value_t*** +; CHECK-NEXT: [[PREV_GCFRAME:%.*]] = load %jl_value_t**, %jl_value_t*** [[GCFRAME_SLOT]] +; CHECK-NEXT: store %jl_value_t** [[PREV_GCFRAME]], %jl_value_t*** [[PREV_GCFRAME_PTR2]], !tbaa !0 +; CHECK-NEXT: [[GCFRAME_SLOT2:%.*]] = bitcast %jl_value_t*** [[GCFRAME_SLOT]] to %jl_value_t addrspace(10)*** +; CHECK-NEXT: store %jl_value_t addrspace(10)** %gcframe, %jl_value_t addrspace(10)*** [[GCFRAME_SLOT2]] + call void @julia.push_gc_frame(%jl_value_t addrspace(10)** %gcframe, i32 2) + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) +; CHECK: %frame_slot_1 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 3 + %frame_slot_1 = call %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)** %gcframe, i32 1) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %frame_slot_1 + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) +; CHECK: %frame_slot_2 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 2 + %frame_slot_2 = call %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)** %gcframe, i32 0) + store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %frame_slot_2 +; CHECK: call void @boxed_simple(%jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)* %bboxed) + call void @boxed_simple(%jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)* %bboxed) +; CHECK-NEXT: [[PREV_GCFRAME_PTR3:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 1 +; CHECK-NEXT: [[PREV_GCFRAME_PTR4:%.*]] = load %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** [[PREV_GCFRAME_PTR3]], !tbaa !0 +; CHECK-NEXT: [[GCFRAME_SLOT3:%.*]] = getelementptr %jl_value_t**, %jl_value_t*** %ptls, i32 0 +; CHECK-NEXT: [[GCFRAME_SLOT4:%.*]] = bitcast %jl_value_t*** [[GCFRAME_SLOT3]] to %jl_value_t addrspace(10)** +; CHECK-NEXT: store %jl_value_t addrspace(10)* [[PREV_GCFRAME_PTR4]], %jl_value_t addrspace(10)** [[GCFRAME_SLOT4]], !tbaa !0 + call void @julia.pop_gc_frame(%jl_value_t addrspace(10)** %gcframe) +; CHECK-NEXT: ret void + ret void +} + +define %jl_value_t addrspace(10)* @gc_alloc_lowering() { +top: +; CHECK-LABEL: @gc_alloc_lowering + %ptls = call %jl_value_t*** @julia.ptls_states() + %ptls_i8 = bitcast %jl_value_t*** %ptls to i8* +; CHECK: %v = call noalias nonnull %jl_value_t addrspace(10)* @jl_gc_pool_alloc + %v = call %jl_value_t addrspace(10)* @julia.gc_alloc_bytes(i8* %ptls_i8, i64 8) + %0 = bitcast %jl_value_t addrspace(10)* %v to %jl_value_t addrspace(10)* addrspace(10)* + %1 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)* addrspace(10)* %0, i64 -1 + store %jl_value_t addrspace(10)* @tag, %jl_value_t addrspace(10)* addrspace(10)* %1, !tbaa !0 + ret %jl_value_t addrspace(10)* %v +} + +!0 = !{!1, !1, i64 0} +!1 = !{!"jtbaa_gcframe", !2, i64 0} +!2 = !{!"jtbaa"} diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll index eb72e2e580d91..9b048d51433d6 100644 --- a/test/llvmpasses/gcroots.ll +++ b/test/llvmpasses/gcroots.ll @@ -1,4 +1,4 @@ -; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -S %s | FileCheck %s +; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s %jl_value_t = type opaque diff --git a/test/llvmpasses/late-lower-gc.ll b/test/llvmpasses/late-lower-gc.ll new file mode 100644 index 0000000000000..315ce7d4333a0 --- /dev/null +++ b/test/llvmpasses/late-lower-gc.ll @@ -0,0 +1,49 @@ +; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -S %s | FileCheck %s + +%jl_value_t = type opaque +@tag = external addrspace(10) global %jl_value_t + +declare void @boxed_simple(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)*) +declare %jl_value_t addrspace(10)* @jl_box_int64(i64) +declare %jl_value_t*** @julia.ptls_states() +declare void @jl_safepoint() +declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) +declare noalias nonnull %jl_value_t addrspace(10)* @julia.gc_alloc_obj(i8*, i64, %jl_value_t addrspace(10)*) + +define void @gc_frame_lowering(i64 %a, i64 %b) { +top: +; CHECK-LABEL: @gc_frame_lowering +; CHECK: %gcframe = call %jl_value_t addrspace(10)** @julia.new_gc_frame(i32 2) + %ptls = call %jl_value_t*** @julia.ptls_states() +; CHECK: %ptls = call %jl_value_t*** @julia.ptls_states() +; CHECK-NEXT: call void @julia.push_gc_frame(%jl_value_t addrspace(10)** %gcframe, i32 2) +; CHECK-NEXT: call %jl_value_t addrspace(10)* @jl_box_int64 + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) +; CHECK: [[GEP0:%.*]] = call %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]]) +; CHECK-NEXT: store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** [[GEP0]] + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) +; CHECK-NEXT: %bboxed = +; Make sure the same gc slot isn't re-used +; CHECK-NOT: call %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT0]]) +; CHECK: [[GEP1:%.*]] = call %jl_value_t addrspace(10)** @julia.get_gc_frame_slot(%jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT1:[0-9]+]]) +; CHECK-NEXT: store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** [[GEP1]] +; CHECK-NEXT: call void @boxed_simple + call void @boxed_simple(%jl_value_t addrspace(10)* %aboxed, + %jl_value_t addrspace(10)* %bboxed) +; CHECK-NEXT: call void @julia.pop_gc_frame(%jl_value_t addrspace(10)** %gcframe) + ret void +} + +define %jl_value_t addrspace(10)* @gc_alloc_lowering() { +top: +; CHECK-LABEL: @gc_alloc_lowering + %ptls = call %jl_value_t*** @julia.ptls_states() + %ptls_i8 = bitcast %jl_value_t*** %ptls to i8* +; CHECK: %v = call %jl_value_t addrspace(10)* @julia.gc_alloc_bytes(i8* %ptls_i8, [[SIZE_T:i.[0-9]+]] 8) +; CHECK-NEXT: [[V2:%.*]] = bitcast %jl_value_t addrspace(10)* %v to %jl_value_t addrspace(10)* addrspace(10)* +; CHECK-NEXT: [[V_HEADROOM:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)* addrspace(10)* [[V2]], i64 -1 +; CHECK-NEXT: store %jl_value_t addrspace(10)* @tag, %jl_value_t addrspace(10)* addrspace(10)* [[V_HEADROOM]], !tbaa !0 + %v = call noalias %jl_value_t addrspace(10)* @julia.gc_alloc_obj(i8* %ptls_i8, i64 8, %jl_value_t addrspace(10)* @tag) +; CHECK-NEXT: ret %jl_value_t addrspace(10)* %v + ret %jl_value_t addrspace(10)* %v +} diff --git a/test/llvmpasses/refinements.ll b/test/llvmpasses/refinements.ll index f7b9040dd45cb..cc9110b4f1af5 100644 --- a/test/llvmpasses/refinements.ll +++ b/test/llvmpasses/refinements.ll @@ -1,4 +1,4 @@ -; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -S %s | FileCheck %s +; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s %jl_value_t = type opaque diff --git a/test/llvmpasses/returnstwicegc.ll b/test/llvmpasses/returnstwicegc.ll index 0bc649dac0308..20c22b3516060 100644 --- a/test/llvmpasses/returnstwicegc.ll +++ b/test/llvmpasses/returnstwicegc.ll @@ -1,4 +1,4 @@ -; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -S %s | FileCheck %s +; RUN: opt -load libjulia%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s %jl_value_t = type opaque diff --git a/test/llvmpasses/safepoint_stress.jl b/test/llvmpasses/safepoint_stress.jl index baa26952884a5..68736333f23f2 100644 --- a/test/llvmpasses/safepoint_stress.jl +++ b/test/llvmpasses/safepoint_stress.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -# RUN: julia --startup-file=no %s | opt -load libjulia%shlibext -LateLowerGCFrame -S - | FileCheck %s +# RUN: julia --startup-file=no %s | opt -load libjulia%shlibext -LateLowerGCFrame -FinalLowerGC -S - | FileCheck %s println(""" %jl_value_t = type opaque diff --git a/test/misc.jl b/test/misc.jl index bf5969eb4509b..a011e72ee5166 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -130,6 +130,8 @@ let c = Ref(0), @test c[] == 100 end +@test_throws ErrorException("deadlock detected: cannot wait on current task") wait(current_task()) + # test that @sync is lexical (PR #27164) const x27164 = Ref(0) diff --git a/test/reflection.jl b/test/reflection.jl index 3dcadd1850a19..3b015d3a6c1b6 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1,4 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license + using Test # code_native / code_llvm (issue #8239) diff --git a/test/show.jl b/test/show.jl index 86e89be468baa..5f06d9b31f066 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1356,6 +1356,11 @@ end @test summary(Base.OneTo(BigInt(10))) == "10-element Base.OneTo{BigInt}" end +@testset "Tuple summary" begin + @test summary((1,2,3)) == "(1, 2, 3)" + @test summary((:a, "b", 'c')) == "(:a, \"b\", 'c')" +end + # Tests for code_typed linetable annotations function compute_annotations(f, types) src = code_typed(f, types, debuginfo=:source)[1][1] @@ -1496,6 +1501,7 @@ replstrcolor(x) = sprint((io, x) -> show(IOContext(io, :limit => true, :color => @test string(:) == "Colon()" @test string(Iterators.flatten) == "flatten" @test Symbol(Iterators.flatten) === :flatten +@test startswith(string(x->x), "#") # printing of bools and bool arrays @testset "Bool" begin @@ -1514,3 +1520,13 @@ Z = Array{Float64}(undef,0,0) # issue #31065, do not print parentheses for nested dot expressions @test sprint(Base.show_unquoted, :(foo.x.x)) == "foo.x.x" + +@testset "show_delim_array" begin + sdastr(f, n) = # sda: Show Delim Array + sprint((io, x) -> Base.show_delim_array(io, x, "[", ",", "]", false, f, n), Iterators.take(1:f+n, f+n)) + @test sdastr(1, 0) == "[1]" + @test sdastr(1, 1) == "[1]" + @test sdastr(1, 2) == "[1, 2]" + @test sdastr(2, 2) == "[2, 3]" + @test sdastr(3, 3) == "[3, 4, 5]" +end diff --git a/test/strings/basic.jl b/test/strings/basic.jl index af17c4dee095a..25ee4c9ea8ea0 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -606,6 +606,8 @@ end @test repeat(s, 3) === S @test repeat(S, 3) === S*S*S end + # Issue #32160 (string allocation unsigned overflow) + @test_throws OutOfMemoryError repeat('x', typemax(Csize_t)) end @testset "issue #12495: check that logical indexing attempt raises ArgumentError" begin @test_throws ArgumentError "abc"[[true, false, true]] diff --git a/test/strings/search.jl b/test/strings/search.jl index 61aaea463eae8..8de73e5c652e5 100644 --- a/test/strings/search.jl +++ b/test/strings/search.jl @@ -43,6 +43,28 @@ for str in [astr, GenericString(astr)] @test_throws BoundsError findnext(isequal('a'), str, nextind(str,lastindex(str))+1) end +for str in [astr, GenericString(astr)] + @test_throws BoundsError findnext('z', str, 0) + @test_throws BoundsError findnext('∀', str, 0) + @test findfirst('x', str) == nothing + @test findfirst('\0', str) == nothing + @test findfirst('\u80', str) == nothing + @test findfirst('∀', str) == nothing + @test findfirst('H', str) == 1 + @test findfirst('l', str) == 3 + @test findfirst('e', str) == 2 + @test findfirst('u', str) == nothing + @test findnext('l', str, 4) == 4 + @test findnext('l', str, 5) == 11 + @test findnext('l', str, 12) == nothing + @test findfirst(',', str) == 6 + @test findnext(',', str, 7) == nothing + @test findfirst('\n', str) == 14 + @test findnext('\n', str, 15) == nothing + @test_throws BoundsError findnext('ε', str, nextind(str,lastindex(str))+1) + @test_throws BoundsError findnext('a', str, nextind(str,lastindex(str))+1) +end + # ascii backward search for str in [astr] @test findlast(isequal('x'), str) == nothing @@ -61,6 +83,23 @@ for str in [astr] @test findlast(isequal('\n'), str) == 14 end +for str in [astr] + @test findlast('x', str) == nothing + @test findlast('\0', str) == nothing + @test findlast('\u80', str) == nothing + @test findlast('∀', str) == nothing + @test findlast('H', str) == 1 + @test findprev('H', str, 0) == nothing + @test findlast('l', str) == 11 + @test findprev('l', str, 5) == 4 + @test findprev('l', str, 4) == 4 + @test findprev('l', str, 3) == 3 + @test findprev('l', str, 2) == nothing + @test findlast(',', str) == 6 + @test findprev(',', str, 5) == nothing + @test findlast('\n', str) == 14 +end + # utf-8 forward search for str in (u8str, GenericString(u8str)) @test_throws BoundsError findnext(isequal('z'), str, 0) diff --git a/test/strings/util.jl b/test/strings/util.jl index 43d88853c4db9..59024e972021b 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -41,6 +41,9 @@ @test rpad("αβ", 8, "¹₂³") == "αβ¹₂³¹₂³" @test lpad("αβ", 9, "¹₂³") == "¹₂³¹₂³¹αβ" @test rpad("αβ", 9, "¹₂³") == "αβ¹₂³¹₂³¹" + # Issue #32160 (unsigned underflow in lpad/rpad) + @test lpad("xx", UInt(1), " ") == "xx" + @test rpad("xx", UInt(1), " ") == "xx" end # string manipulation diff --git a/test/subtype.jl b/test/subtype.jl index 68b0365a65df0..bd32593d7dda4 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1540,9 +1540,18 @@ end @testintersect(Tuple{Type{<:AbstractVector{T}}, Int} where T, Tuple{Type{Vector}, Any}, Union{}) -@testintersect(Tuple{Type{<:AbstractVector{T}}, Int} where T, - Tuple{Type{Vector{T} where Int<:T<:Int}, Any}, - Tuple{Type{Vector{Int}}, Int}) +#@testintersect(Tuple{Type{<:AbstractVector{T}}, Int} where T, +# Tuple{Type{Vector{T} where Int<:T<:Int}, Any}, +# Tuple{Type{Vector{Int}}, Int}) +@test_broken isequal(_type_intersect(Tuple{Type{<:AbstractVector{T}}, Int} where T, + Tuple{Type{Vector{T} where Int<:T<:Int}, Any}), + Tuple{Type{Vector{Int}}, Int}) +@test isequal_type(_type_intersect(Tuple{Type{<:AbstractVector{T}}, Int} where T, + Tuple{Type{Vector{T} where Int<:T<:Int}, Any}), + Tuple{Type{Vector{Int}}, Int}) +@test isequal_type(_type_intersect(Tuple{Type{Vector{T} where Int<:T<:Int}, Any}, + Tuple{Type{<:AbstractVector{T}}, Int} where T), + Tuple{Type{Vector{Int}}, Int}) let X = LinearAlgebra.Symmetric{T, S} where S<:(AbstractArray{U, 2} where U<:T) where T, Y = Union{LinearAlgebra.Hermitian{T, S} where S<:(AbstractArray{U, 2} where U<:T) where T, LinearAlgebra.Symmetric{T, S} where S<:(AbstractArray{U, 2} where U<:T) where T} @@ -1584,7 +1593,14 @@ let T31805 = Tuple{Type{Tuple{}}, Tuple{Vararg{Int8, A}}} where A, S31805 = Tuple{Type{Tuple{Vararg{Int32, A}}}, Tuple{Vararg{Int16, A}}} where A @test !issub(T31805, S31805) end + @testintersect( Tuple{Array{Tuple{Vararg{Int64,N}},N},Tuple{Vararg{Array{Int64,1},N}}} where N, Tuple{Array{Tuple{Int64},1}, Tuple}, Tuple{Array{Tuple{Int64},1},Tuple{Array{Int64,1}}}) + +# this is is a timing test, so it would fail on debug builds +#let T = Type{Tuple{(Union{Int, Nothing} for i = 1:23)..., Union{String, Nothing}}}, +# S = Type{T} where T<:Tuple{E, Vararg{E}} where E +# @test @elapsed (@test T != S) < 5 +#end diff --git a/test/syntax.jl b/test/syntax.jl index 85951185f4a57..03e2498d6fa58 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1848,6 +1848,9 @@ macro id28992(x) x end @test @id28992(2 ^ -2) == 0.25 @test @id28992(2 .^ -2) == 0.25 +# issue #32121 +@test @id28992((a=1, b=2)) === (a=1, b=2) + # issue #31596 f31596(x; kw...) = x @test f31596((a=1,), b = 1.0) === (a=1,) diff --git a/test/testhelpers/Quaternions.jl b/test/testhelpers/Quaternions.jl index 280965f3a70e1..93b610f283f4b 100644 --- a/test/testhelpers/Quaternions.jl +++ b/test/testhelpers/Quaternions.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module Quaternions export Quaternion diff --git a/test/testhelpers/llvmpasses.jl b/test/testhelpers/llvmpasses.jl index 09f152a064475..0b443c3eb1535 100644 --- a/test/testhelpers/llvmpasses.jl +++ b/test/testhelpers/llvmpasses.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + using InteractiveUtils using Printf diff --git a/test/threads.jl b/test/threads.jl index db0e4c605b37d..be0481a5d72fe 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -640,3 +640,16 @@ let t = Timer(identity, 0.025, interval=0.025) close(t) end end + +# shared workqueue + +function pfib(n::Int) + if n <= 1 + return n + end + t = @task pfib(n-2) + t.sticky = false + schedule(t) + return pfib(n-1) + fetch(t)::Int +end +@test pfib(20) == 6765