From e2f7b2ffdc33c22f6d9cc50b96081930afdb8e01 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 30 Oct 2018 16:08:17 -0400 Subject: [PATCH] rearrange inlining of `ensureroom` and speed it up (#27874) * rearrange inlining of `ensureroom` and speed it up --- base/array.jl | 12 ++++++++++-- base/iobuffer.jl | 19 +++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/base/array.jl b/base/array.jl index a6364188b8977..9e8da6c384ba0 100644 --- a/base/array.jl +++ b/base/array.jl @@ -267,11 +267,19 @@ offset `do`. Return `dest`. """ function copyto!(dest::Array{T}, doffs::Integer, src::Array{T}, soffs::Integer, n::Integer) where T n == 0 && return dest - n > 0 || throw(ArgumentError(string("tried to copy n=", n, " elements, but n should be nonnegative"))) + n > 0 || _throw_argerror(n) if soffs < 1 || doffs < 1 || soffs+n-1 > length(src) || doffs+n-1 > length(dest) throw(BoundsError()) end unsafe_copyto!(dest, doffs, src, soffs, n) + return dest +end + +# Outlining this because otherwise a catastrophic inference slowdown +# occurs, see discussion in #27874 +function _throw_argerror(n) + @_noinline_meta + throw(ArgumentError(string("tried to copy n=", n, " elements, but n should be nonnegative"))) end copyto!(dest::Array{T}, src::Array{T}) where {T} = copyto!(dest, 1, src, 1, length(src)) @@ -284,7 +292,7 @@ function fill!(dest::Array{T}, x) where T for i in 1:length(dest) @inbounds dest[i] = xT end - dest + return dest end """ diff --git a/base/iobuffer.jl b/base/iobuffer.jl index dec5735d2ed3b..7633581508a9b 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -289,11 +289,9 @@ function compact(io::GenericIOBuffer) return io end -@inline ensureroom(io::GenericIOBuffer, nshort::Int) = ensureroom(io, UInt(nshort)) -@inline function ensureroom(io::GenericIOBuffer, nshort::UInt) +@noinline function ensureroom_slowpath(io::GenericIOBuffer, nshort::UInt) io.writable || throw(ArgumentError("ensureroom failed, IOBuffer is not writeable")) if !io.seekable - nshort >= 0 || throw(ArgumentError("ensureroom failed, requested number of bytes must be ≥ 0, got $nshort")) if !ismarked(io) && io.ptr > 1 && io.size <= io.ptr - 1 io.ptr = 1 io.size = 0 @@ -308,9 +306,18 @@ end end end end - n = min(nshort + (io.append ? io.size : io.ptr-1), io.maxsize) - if n > length(io.data) - resize!(io.data, n) + return +end + +@inline ensureroom(io::GenericIOBuffer, nshort::Int) = ensureroom(io, UInt(nshort)) +@inline function ensureroom(io::GenericIOBuffer, nshort::UInt) + if !io.writable || (!io.seekable && io.ptr > 1) + ensureroom_slowpath(io, nshort) + end + n = min((nshort % Int) + (io.append ? io.size : io.ptr-1), io.maxsize) + l = length(io.data) + if n > l + _growend!(io.data, (n - l) % UInt) end return io end