diff --git a/base/Base.jl b/base/Base.jl index 24f07dfef6de7f..9d0a44b7a1f5dd 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -34,6 +34,8 @@ ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Base, is_primary_base_module) macro inline() Expr(:meta, :inline) end macro noinline() Expr(:meta, :noinline) end +macro _boundscheck() Expr(:boundscheck) end + # Try to help prevent users from shooting them-selves in the foot # with ambiguities by defining a few common and critical operations # (and these don't need the extra convert code) diff --git a/base/boot.jl b/base/boot.jl index 30c340a3cc403a..122fb3f40fa112 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -268,11 +268,12 @@ ccall(:jl_toplevel_eval_in, Any, (Any, Any), macro nospecialize(x) _expr(:meta, :nospecialize, x) end +Expr(@nospecialize args...) = _expr(args...) _is_internal(__module__) = __module__ === Core # can be used in place of `@assume_effects :foldable` (supposed to be used for bootstrapping) macro _foldable_meta() - return _is_internal(__module__) && _expr(:meta, _expr(:purity, + return _is_internal(__module__) && Expr(:meta, Expr(:purity, #=:consistent=#true, #=:effect_free=#true, #=:nothrow=#false, @@ -283,6 +284,11 @@ macro _foldable_meta() #=:noub=#true)) end +macro inline() Expr(:meta, :inline) end +macro noinline() Expr(:meta, :noinline) end + +macro _boundscheck() Expr(:boundscheck) end + # n.b. the effects and model of these is refined in inference abstractinterpretation.jl TypeVar(@nospecialize(n)) = _typevar(n::Symbol, Union{}, Any) TypeVar(@nospecialize(n), @nospecialize(ub)) = _typevar(n::Symbol, Union{}, ub) @@ -309,16 +315,11 @@ kwftype(@nospecialize(t)) = typeof(kwcall) Union{}(a...) = throw(ArgumentError("cannot construct a value of type Union{} for return result")) kwcall(kwargs, ::Type{Union{}}, a...) = Union{}(a...) -Expr(@nospecialize args...) = _expr(args...) - abstract type Exception end struct ErrorException <: Exception msg::AbstractString end -macro inline() Expr(:meta, :inline) end -macro noinline() Expr(:meta, :noinline) end - struct BoundsError <: Exception a::Any i::Any @@ -509,14 +510,14 @@ const undef = UndefInitializer() const Memory{T} = GenericMemory{:not_atomic, T, CPU} const MemoryRef{T} = GenericMemoryRef{:not_atomic, T, CPU} GenericMemoryRef(mem::GenericMemory) = memoryref(mem) -eval(Core, :(GenericMemoryRef(ref::GenericMemoryRef, i::Integer) = memoryref(ref, Int(i), $(Expr(:boundscheck))))) -eval(Core, :(GenericMemoryRef(mem::GenericMemory, i::Integer) = memoryref(memoryref(mem), Int(i), $(Expr(:boundscheck))))) +GenericMemoryRef(ref::GenericMemoryRef, i::Integer) = memoryref(ref, Int(i), @_boundscheck) +GenericMemoryRef(mem::GenericMemory, i::Integer) = memoryref(memoryref(mem), Int(i), @_boundscheck) MemoryRef(mem::Memory) = memoryref(mem) -eval(Core, :(MemoryRef(ref::MemoryRef, i::Integer) = memoryref(ref, Int(i), $(Expr(:boundscheck))))) -eval(Core, :(MemoryRef(mem::Memory, i::Integer) = memoryref(memoryref(mem), Int(i), $(Expr(:boundscheck))))) +MemoryRef(ref::MemoryRef, i::Integer) = memoryref(ref, Int(i), @_boundscheck) +MemoryRef(mem::Memory, i::Integer) = memoryref(memoryref(mem), Int(i), @_boundscheck) MemoryRef{T}(mem::Memory{T}) where {T} = memoryref(mem) -eval(Core, :(MemoryRef{T}(ref::MemoryRef{T}, i::Integer) where {T} = memoryref(ref, Int(i), $(Expr(:boundscheck))))) -eval(Core, :(MemoryRef{T}(mem::Memory{T}, i::Integer) where {T} = memoryref(memoryref(mem), Int(i), $(Expr(:boundscheck))))) +MemoryRef{T}(ref::MemoryRef{T}, i::Integer) where {T} = memoryref(ref, Int(i), @_boundscheck) +MemoryRef{T}(mem::Memory{T}, i::Integer) where {T} = memoryref(memoryref(mem), Int(i), @_boundscheck) # construction helpers for Array new_as_memoryref(self::Type{GenericMemoryRef{isatomic,T,addrspace}}, m::Int) where {T,isatomic,addrspace} = memoryref(fieldtype(self, :mem)(undef, m)) diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 997e6989312f38..b81268215578cc 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -28,6 +28,8 @@ include(mod, x) = Core.include(mod, x) macro inline() Expr(:meta, :inline) end macro noinline() Expr(:meta, :noinline) end +macro _boundscheck() Expr(:boundscheck) end + convert(::Type{Any}, Core.@nospecialize x) = x convert(::Type{T}, x::T) where {T} = x diff --git a/base/essentials.jl b/base/essentials.jl index ece48a0e772eec..a8a3ec3c153824 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -13,8 +13,8 @@ length(a::Array) = getfield(getfield(getfield(a, :ref), :mem), :length) length(a::GenericMemory) = getfield(a, :length) throw_boundserror(A, I) = (@noinline; throw(BoundsError(A, I))) -eval(:(getindex(A::GenericMemory{:not_atomic}, i::Int) = memoryrefget(memoryref(memoryref(A), i, $(Expr(:boundscheck))), :not_atomic, false))) -eval(:(getindex(A::GenericMemoryRef{:not_atomic}) = memoryrefget(A, :not_atomic, $(Expr(:boundscheck))))) +getindex(A::GenericMemory{:not_atomic}, i::Int) = memoryrefget(memoryref(memoryref(A), i, @_boundscheck), :not_atomic, false) +getindex(A::GenericMemoryRef{:not_atomic}) = memoryrefget(A, :not_atomic, @_boundscheck) # multidimensional getindex will be defined later on @@ -786,20 +786,19 @@ macro goto(name::Symbol) end # linear indexing -eval(:(function getindex(A::Array, i::Int) - @boundscheck ult_int(bitcast(UInt, sub_int(i, 1)), bitcast(UInt, length(A))) || throw_boundserror(A, (i,)) - memoryrefget(memoryref(getfield(A, :ref), i, false), :not_atomic, false) - end)) +function getindex(A::Array, i::Int) + @boundscheck ult_int(bitcast(UInt, sub_int(i, 1)), bitcast(UInt, length(A))) || throw_boundserror(A, (i,)) + memoryrefget(memoryref(getfield(A, :ref), i, false), :not_atomic, false) +end # simple Array{Any} operations needed for bootstrap function setindex!(A::Array{Any}, @nospecialize(x), i::Int) @boundscheck ult_int(bitcast(UInt, sub_int(i, 1)), bitcast(UInt, length(A))) || throw_boundserror(A, (i,)) memoryrefset!(memoryref(getfield(A, :ref), i, false), x, :not_atomic, false) return A end -@eval setindex!(A::Memory{Any}, @nospecialize(x), i::Int) = (memoryrefset!(memoryref(memoryref(A), i, $(Expr(:boundscheck))), x, :not_atomic, $(Expr(:boundscheck))); A) -@eval setindex!(A::MemoryRef{T}, x) where {T} = memoryrefset!(A, convert(T, x), :not_atomic, $(Expr(:boundscheck))) -@eval setindex!(A::MemoryRef{Any}, @nospecialize(x)) = memoryrefset!(A, x, :not_atomic, $(Expr(:boundscheck))) - +setindex!(A::Memory{Any}, @nospecialize(x), i::Int) = (memoryrefset!(memoryref(memoryref(A), i, @_boundscheck), x, :not_atomic, @_boundscheck); A) +setindex!(A::MemoryRef{T}, x) where {T} = memoryrefset!(A, convert(T, x), :not_atomic, @_boundscheck) +setindex!(A::MemoryRef{Any}, @nospecialize(x)) = memoryrefset!(A, x, :not_atomic, @_boundscheck) # SimpleVector diff --git a/base/genericmemory.jl b/base/genericmemory.jl index ec33cb67a40972..06d64708113e3a 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -64,7 +64,7 @@ function isassigned(a::Memory, i::Int) return @inbounds memoryref_isassigned(GenericMemoryRef(a, i), :not_atomic, false) end -@eval isassigned(a::GenericMemoryRef) = memoryref_isassigned(a, :not_atomic, $(Expr(:boundscheck))) +isassigned(a::GenericMemoryRef) = memoryref_isassigned(a, :not_atomic, @_boundscheck) ## copy ## function unsafe_copyto!(dest::MemoryRef{T}, src::MemoryRef{T}, n) where {T} @@ -182,14 +182,12 @@ getindex(A::Memory, c::Colon) = copy(A) ## Indexing: setindex! ## -@eval begin function setindex!(A::Memory{T}, x, i1::Int) where {T} val = x isa T ? x : convert(T,x)::T - ref = memoryref(memoryref(A), i1, $(Expr(:boundscheck))) - memoryrefset!(ref, val, :not_atomic, $(Expr(:boundscheck))) + ref = memoryref(memoryref(A), i1, @_boundscheck) + memoryrefset!(ref, val, :not_atomic, @_boundscheck) return A end -end function setindex!(A::Memory{T}, x, i1::Int, i2::Int, I::Int...) where {T} @inline @boundscheck (i2 == 1 && all(==(1), I)) || throw_boundserror(A, (i1, i2, I...)) diff --git a/base/tuple.jl b/base/tuple.jl index 339aafac171b19..c2e0a478cca48f 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -28,8 +28,8 @@ firstindex(@nospecialize t::Tuple) = 1 lastindex(@nospecialize t::Tuple) = length(t) size(@nospecialize(t::Tuple), d::Integer) = (d == 1) ? length(t) : throw(ArgumentError("invalid tuple dimension $d")) axes(@nospecialize t::Tuple) = (OneTo(length(t)),) -@eval getindex(@nospecialize(t::Tuple), i::Int) = getfield(t, i, $(Expr(:boundscheck))) -@eval getindex(@nospecialize(t::Tuple), i::Integer) = getfield(t, convert(Int, i), $(Expr(:boundscheck))) +getindex(@nospecialize(t::Tuple), i::Int) = getfield(t, i, @_boundscheck) +getindex(@nospecialize(t::Tuple), i::Integer) = getfield(t, convert(Int, i), @_boundscheck) __inbounds_getindex(@nospecialize(t::Tuple), i::Int) = getfield(t, i, false) __inbounds_getindex(@nospecialize(t::Tuple), i::Integer) = getfield(t, convert(Int, i), false) getindex(t::Tuple, r::AbstractArray{<:Any,1}) = (eltype(t)[t[ri] for ri in r]...,)