Skip to content

Commit 6825f4d

Browse files
committed
Improve performance of bounds checking
This address most of the remaining problem in #11595, but it's still about three-fold short of the performance we had before getindex(::SubArray, ...) checked bounds.
1 parent 96087d3 commit 6825f4d

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

base/abstractarray.jl

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ macro _noinline_meta()
123123
end
124124

125125
## Bounds checking ##
126+
@generated function trailingsize{T,N,n}(A::AbstractArray{T,N}, ::Type{Val{n}})
127+
ex = :(size(A, $n))
128+
for m = n+1:N
129+
ex = :($ex * size(A, $m))
130+
end
131+
Expr(:block, Expr(:meta, :inline), ex)
132+
end
133+
126134
_checkbounds(sz, i::Integer) = 1 <= i <= sz
127135
_checkbounds(sz, i::Real) = 1 <= to_index(i) <= sz
128136
_checkbounds(sz, I::AbstractVector{Bool}) = length(I) == sz
@@ -149,17 +157,14 @@ function checkbounds(A::AbstractMatrix, I::Union(Real,AbstractArray,Colon), J::U
149157
end
150158
function checkbounds(A::AbstractArray, I::Union(Real,AbstractArray,Colon), J::Union(Real,AbstractArray,Colon))
151159
@_inline_meta
152-
(_checkbounds(size(A,1), I) && _checkbounds(trailingsize(A,2), J)) || throw_boundserror(A, (I, J))
160+
(_checkbounds(size(A,1), I) && _checkbounds(trailingsize(A,Val{2}), J)) || throw_boundserror(A, (I, J))
153161
end
154-
function checkbounds(A::AbstractArray, I::Union(Real,AbstractArray,Colon)...)
155-
@_inline_meta
156-
n = length(I)
157-
if n > 0
158-
for dim = 1:(n-1)
159-
_checkbounds(size(A,dim), I[dim]) || throw_boundserror(A, I)
160-
end
161-
_checkbounds(trailingsize(A,n), I[n]) || throw_boundserror(A, I)
162-
end
162+
@generated function checkbounds(A::AbstractArray, I::Union(Real,AbstractArray,Colon)...)
163+
meta = Expr(:meta, :inline)
164+
N = length(I)
165+
args = Expr[:(_checkbounds(size(A,$dim), I[$dim]) || throw_boundserror(A, I)) for dim in 1:N-1]
166+
push!(args, :(_checkbounds(trailingsize(A,Val{$N}), I[$N]) || throw_boundserror(A, I)))
167+
Expr(:block, meta, args...)
163168
end
164169

165170
## Bounds-checking without errors ##

0 commit comments

Comments
 (0)