From c57494983924eab3a6dff19a917e50afc9147a3f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 6 Jun 2017 11:30:32 -0400 Subject: [PATCH] Treat bounds check in isassigned as, well, bounds check The change to `isassigned(::SimpleVector, ...)` and `isassigned(::BitArray, ...)` are currently no op since they will unlikely be inlined. The `SimpleVector` version is also currently unsafe to inline. These might change with a better inlining heuristic (#22210) and a smarter GC frame allocation pass (#21888). --- base/array.jl | 2 +- base/essentials.jl | 2 +- base/multidimensional.jl | 2 +- test/boundscheck_exec.jl | 10 ++++++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/base/array.jl b/base/array.jl index 858eef12fe343..371f56059f668 100644 --- a/base/array.jl +++ b/base/array.jl @@ -96,7 +96,7 @@ sizeof(a::Array) = elsize(a) * length(a) function isassigned(a::Array, i::Int...) @_inline_meta ii = (sub2ind(size(a), i...) % UInt) - 1 - ii < length(a) % UInt || return false + @boundscheck ii < length(a) % UInt || return false ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii) == 1 end diff --git a/base/essentials.jl b/base/essentials.jl index d16e1ed107204..02e5a6815cad6 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -294,7 +294,7 @@ false function isassigned end function isassigned(v::SimpleVector, i::Int) - 1 <= i <= length(v) || return false + @boundscheck 1 <= i <= length(v) || return false x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) return x != C_NULL end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index a78d5adcac241..0f125757aca10 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1229,7 +1229,7 @@ end @nexprs $N d->begin l = size(B,d) stride *= l - 1 <= I_{d-1} <= l || return false + @boundscheck 1 <= I_{d-1} <= l || return false index += (I_d - 1) * stride end return isassigned(B, index) diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index e6ec13fd2da41..df2deea73cb51 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -209,4 +209,14 @@ else @test_throws BoundsError V1() end +# This tests both the bounds check elision and the behavior of `jl_array_isassigned` +# For `isbits` array the `ccall` should return a constant `true` and does not access +# the array +inbounds_isassigned(a, i) = @inbounds return isassigned(a, i) +if bc_opt == bc_default || bc_opt == bc_off + @test inbounds_isassigned(Int[], 2) == true +else + @test inbounds_isassigned(Int[], 2) == false +end + end