• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37662

25 Oct 2023 07:08AM UTC coverage: 87.999% (+1.5%) from 86.476%
#37662

push

local

web-flow
Improve efficiency of minimum/maximum(::Diagonal) (#30236)

```
julia> DM = Diagonal(rand(100));

julia> @btime minimum($DM);    # before
  27.987 μs (0 allocations: 0 bytes)

julia> @btime minimum($DM);    # after
  246.091 ns (0 allocations: 0 bytes)
```

8 of 8 new or added lines in 1 file covered. (100.0%)

74065 of 84166 relevant lines covered (88.0%)

12219725.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.97
/base/refpointer.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Ref{T}
5

6
An object that safely references data of type `T`. This type is guaranteed to point to
7
valid, Julia-allocated memory of the correct type. The underlying data is protected from
8
freeing by the garbage collector as long as the `Ref` itself is referenced.
9

10
In Julia, `Ref` objects are dereferenced (loaded or stored) with `[]`.
11

12
Creation of a `Ref` to a value `x` of type `T` is usually written `Ref(x)`.
13
Additionally, for creating interior pointers to containers (such as Array or Ptr),
14
it can be written `Ref(a, i)` for creating a reference to the `i`-th element of `a`.
15

16
`Ref{T}()` creates a reference to a value of type `T` without initialization.
17
For a bitstype `T`, the value will be whatever currently resides in the memory
18
allocated. For a non-bitstype `T`, the reference will be undefined and attempting to
19
dereference it will result in an error, "UndefRefError: access to undefined reference".
20

21
To check if a `Ref` is an undefined reference, use [`isassigned(ref::RefValue)`](@ref).
22
For example, `isassigned(Ref{T}())` is `false` if `T` is not a bitstype.
23
If `T` is a bitstype, `isassigned(Ref{T}())` will always be true.
24

25
When passed as a `ccall` argument (either as a `Ptr` or `Ref` type), a `Ref`
26
object will be converted to a native pointer to the data it references.
27
For most `T`, or when converted to a `Ptr{Cvoid}`, this is a pointer to the
28
object data. When `T` is an `isbits` type, this value may be safely mutated,
29
otherwise mutation is strictly undefined behavior.
30

31
As a special case, setting `T = Any` will instead cause the creation of a
32
pointer to the reference itself when converted to a `Ptr{Any}`
33
(a `jl_value_t const* const*` if T is immutable, else a `jl_value_t *const *`).
34
When converted to a `Ptr{Cvoid}`, it will still return a pointer to the data
35
region as for any other `T`.
36

37
A `C_NULL` instance of `Ptr` can be passed to a `ccall` `Ref` argument to initialize it.
38

39
# Use in broadcasting
40
`Ref` is sometimes used in broadcasting in order to treat the referenced values as a scalar.
41

42
# Examples
43

44
```jldoctest
45
julia> r = Ref(5) # Create a Ref with an initial value
46
Base.RefValue{Int64}(5)
47

48
julia> r[] # Getting a value from a Ref
49
5
50

51
julia> r[] = 7 # Storing a new value in a Ref
52
7
53

54
julia> r # The Ref now contains 7
55
Base.RefValue{Int64}(7)
56

57
julia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # Treat reference values as scalar during broadcasting
58
3-element BitVector:
59
 1
60
 0
61
 0
62

63
julia> Ref{Function}()  # Undefined reference to a non-bitstype, Function
64
Base.RefValue{Function}(#undef)
65

66
julia> try
67
           Ref{Function}()[] # Dereferencing an undefined reference will result in an error
68
       catch e
69
           println(e)
70
       end
71
UndefRefError()
72

73
julia> Ref{Int64}()[]; # A reference to a bitstype refers to an undetermined value if not given
74

75
julia> isassigned(Ref{Int64}()) # A reference to a bitstype is always assigned
76
true
77
```
78
"""
79
Ref
80

81
# C NUL-terminated string pointers; these can be used in ccall
82
# instead of Ptr{Cchar} and Ptr{Cwchar_t}, respectively, to enforce
83
# a check for embedded NUL chars in the string (to avoid silent truncation).
84
if Int === Int64
85
    primitive type Cstring  64 end
86
    primitive type Cwstring 64 end
87
else
88
    primitive type Cstring  32 end
89
    primitive type Cwstring 32 end
90
end
91

92

93
### General Methods for Ref{T} type
94

95
eltype(x::Type{<:Ref{T}}) where {T} = @isdefined(T) ? T : Any
1,577,107✔
96
convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x
×
97
size(x::Ref) = ()
1✔
98
axes(x::Ref) = ()
1,577,133✔
99
length(x::Ref) = 1
×
100
isempty(x::Ref) = false
×
101
ndims(x::Ref) = 0
1✔
102
ndims(::Type{<:Ref}) = 0
1,577,203✔
103
iterate(r::Ref) = (r[], nothing)
2✔
104
iterate(r::Ref, s) = nothing
2✔
105
IteratorSize(::Type{<:Ref}) = HasShape{0}()
2✔
106

107
# create Ref objects for general object conversion
108
unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x)
84,880,696✔
109
unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x)
×
110

111
convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)::RefValue{T}
26,910,898✔
112

113
### Methods for a Ref object that is backed by an array at index i
114
struct RefArray{T,A<:AbstractArray{T},R} <: Ref{T}
115
    x::A
116
    i::Int
117
    roots::R # should be either ::Nothing or ::Any
118
    RefArray{T,A,R}(x,i,roots=nothing) where {T,A<:AbstractArray{T},R} = new(x,i,roots)
39,876✔
119
end
120
RefArray(x::AbstractArray{T}, i::Int, roots::Any) where {T} = RefArray{T,typeof(x),Any}(x, i, roots)
×
121
RefArray(x::AbstractArray{T}, i::Int=1, roots::Nothing=nothing) where {T} = RefArray{T,typeof(x),Nothing}(x, i, nothing)
67,272✔
122
RefArray(x::AbstractArray{T}, i::Integer, roots::Any) where {T} = RefArray{T,typeof(x),Any}(x, Int(i), roots)
×
123
RefArray(x::AbstractArray{T}, i::Integer, roots::Nothing=nothing) where {T} = RefArray{T,typeof(x),Nothing}(x, Int(i), nothing)
8,076✔
124
convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1)
9✔
125

126
function unsafe_convert(P::Union{Type{Ptr{T}},Type{Ptr{Cvoid}}}, b::RefArray{T})::P where T
79✔
127
    if allocatedinline(T)
79✔
128
        p = pointer(b.x, b.i)
2,238✔
129
    elseif isconcretetype(T) && ismutabletype(T)
×
130
        p = pointer_from_objref(b.x[b.i])
×
131
    else
132
        # see comment on equivalent branch for RefValue
133
        p = pointerref(Ptr{Ptr{Cvoid}}(pointer(b.x, b.i)), 1, Core.sizeof(Ptr{Cvoid}))
×
134
    end
135
    return p
79✔
136
end
137
function unsafe_convert(::Type{Ptr{Any}}, b::RefArray{Any})::Ptr{Any}
×
138
    return pointer(b.x, b.i)
×
139
end
140

141
###
142
if is_primary_base_module
143
    Ref(x::Any) = RefValue(x)
11,284,953✔
144
    Ref{T}() where {T} = RefValue{T}() # Ref{T}()
39,128,209✔
145
    Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x)
43,101,978✔
146

147
    Ref(x::Ref, i::Integer) = (i != 1 && error("Ref only has one element"); x)
×
148
    Ref(x::Ptr{T}, i::Integer) where {T} = x + (i - 1) * Core.sizeof(T)
×
149

150
    # convert Arrays to pointer arrays for ccall
151
    # For example `["a", "b"]` to Ptr{Cstring} for `char **argv`
152
    function Ref{P}(a::Array{T}) where P<:Union{Ptr,Cwstring,Cstring} where T
2,202✔
153
        if (isbitstype(T) ? T <: Ptr || T <: Union{Cwstring,Cstring} : T <: eltype(P))
×
154
            # this Array already has the right memory layout for the requested Ref
155
            # but the wrong eltype for the constructor
156
            return RefArray{P,typeof(a),Nothing}(a, 1, nothing) # effectively a no-op
×
157
        else
158
            ptrs = Vector{P}(undef, length(a)+1)
2,202✔
159
            roots = Vector{Any}(undef, length(a))
2,202✔
160
            for i = 1:length(a)
4,403✔
161
                root = cconvert(P, a[i])
45,002✔
162
                ptrs[i] = unsafe_convert(P, root)::P
45,002✔
163
                roots[i] = root
45,002✔
164
            end
87,803✔
165
            ptrs[length(a)+1] = C_NULL
2,202✔
166
            return RefArray{P,typeof(ptrs),typeof(roots)}(ptrs, 1, roots)
2,202✔
167
        end
168
    end
169
    Ref(x::AbstractArray, i::Integer) = RefArray(x, i)
37,665✔
170
end
171

172
cconvert(::Type{Ptr{P}}, a::Array{P}) where {P<:Union{Ptr,Cwstring,Cstring}} = a
×
173
cconvert(::Type{Ref{P}}, a::Array{P}) where {P<:Union{Ptr,Cwstring,Cstring}} = a
×
174
cconvert(::Type{Ptr{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)
2,159✔
175
cconvert(::Type{Ref{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)
43✔
176

177
# pass NTuple{N,T} as Ptr{T}/Ref{T}
178
cconvert(::Type{Ref{T}}, t::NTuple{N,T}) where {N,T} = Ref{NTuple{N,T}}(t)
4✔
179
cconvert(::Type{Ref{T}}, r::Ref{NTuple{N,T}}) where {N,T} = r
3✔
180
unsafe_convert(::Type{Ref{T}}, r::Ref{NTuple{N,T}}) where {N,T} =
7✔
181
    convert(Ptr{T}, unsafe_convert(Ptr{NTuple{N,T}}, r))
182
unsafe_convert(::Type{Ptr{T}}, r::Ref{NTuple{N,T}}) where {N,T} =
51,973✔
183
    convert(Ptr{T}, unsafe_convert(Ptr{NTuple{N,T}}, r))
184
unsafe_convert(::Type{Ptr{T}}, r::Ptr{NTuple{N,T}}) where {N,T} =
×
185
    convert(Ptr{T}, r)
186

187
###
188

189
getindex(b::RefArray) = b.x[b.i]
37,641✔
190
setindex!(b::RefArray, x) = (b.x[b.i] = x; b)
2✔
191

192
###
193

194
"""
195
    LLVMPtr{T, AS}
196

197
A pointer type that more closely resembles LLVM semantics: It includes the pointer address
198
space, and will be passed as an actual pointer instead of an integer.
199

200
This type is mainly used to interface with code that has strict requirements about pointers,
201
e.g., intrinsics that are selected based on the address space, or back-ends that require
202
pointers to be identifiable by their types.
203
"""
204
Core.LLVMPtr
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc