StatProfilerHTML.jl report
Generated on Mon, 01 Apr 2024 21:01:18
File source code
Line Exclusive Inclusive Code
1 # This file is a part of Julia. License is MIT: https://julialang.org/license
2
3 """
4 Ptr{T}
5
6 A memory address referring to data of type `T`. However, there is no guarantee that the
7 memory is actually valid, or that it actually represents data of the specified type.
8 """
9 Ptr
10
11 ## converting pointers to an appropriate unsigned ##
12
13 """
14 C_NULL
15
16 The C null pointer constant, sometimes used when calling external code.
17 """
18 const C_NULL = bitcast(Ptr{Cvoid}, 0)
19
20 # TODO: deprecate these conversions. C doesn't even allow them.
21
22 # pointer to integer
23 convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x))::T
24
25 # integer to pointer
26 convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x)
27
28 # pointer to pointer
29 convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p
30 convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p)::Ptr{T}
31
32 # object to pointer (when used with ccall)
33
34 """
35 unsafe_convert(T, x)
36
37 Convert `x` to a C argument of type `T`
38 where the input `x` must be the return value of `cconvert(T, ...)`.
39
40 In cases where [`convert`](@ref) would need to take a Julia object
41 and turn it into a `Ptr`, this function should be used to define and perform
42 that conversion.
43
44 Be careful to ensure that a Julia reference to `x` exists as long as the result of this
45 function will be used. Accordingly, the argument `x` to this function should never be an
46 expression, only a variable name or field reference. For example, `x=a.b.c` is acceptable,
47 but `x=[a,b,c]` is not.
48
49 The `unsafe` prefix on this function indicates that using the result of this function after
50 the `x` argument to this function is no longer accessible to the program may cause undefined
51 behavior, including program corruption or segfaults, at any later time.
52
53 See also [`cconvert`](@ref)
54 """
55 function unsafe_convert end
56
57 unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x)
58 unsafe_convert(::Type{Ptr{Int8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{Int8}, (Any,), x)
59 unsafe_convert(::Type{Ptr{UInt8}}, s::String) = ccall(:jl_string_ptr, Ptr{UInt8}, (Any,), s)
60 unsafe_convert(::Type{Ptr{Int8}}, s::String) = ccall(:jl_string_ptr, Ptr{Int8}, (Any,), s)
61 # convert strings to String etc. to pass as pointers
62 cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s)
63 cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s)
64
65 unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = ccall(:jl_array_ptr, Ptr{T}, (Any,), a)
66 unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
67 unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))")
68
69 # unsafe pointer to array conversions
70 """
71 unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)
72
73 Wrap a Julia `Array` object around the data at the address given by `pointer`,
74 without making a copy. The pointer element type `T` determines the array
75 element type. `dims` is either an integer (for a 1d array) or a tuple of the array dimensions.
76 `own` optionally specifies whether Julia should take ownership of the memory,
77 calling `free` on the pointer when the array is no longer referenced.
78
79 This function is labeled "unsafe" because it will crash if `pointer` is not
80 a valid memory address to data of the requested length. Unlike [`unsafe_load`](@ref)
81 and [`unsafe_store!`](@ref), the programmer is responsible also for ensuring that the
82 underlying data is not accessed through two arrays of different element type, similar
83 to the strict aliasing rule in C.
84 """
85 function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
86 p::Ptr{T}, dims::NTuple{N,Int}; own::Bool = false) where {T,N}
87 ccall(:jl_ptr_to_array, Array{T,N}, (Any, Ptr{Cvoid}, Any, Int32),
88 Array{T,N}, p, dims, own)
89 end
90 function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}},
91 p::Ptr{T}, d::Integer; own::Bool = false) where {T}
92 ccall(:jl_ptr_to_array_1d, Array{T,1},
93 (Any, Ptr{Cvoid}, Csize_t, Cint), Array{T,1}, p, d, own)
94 end
95 unsafe_wrap(Atype::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
96 p::Ptr{T}, dims::NTuple{N,<:Integer}; own::Bool = false) where {T,N} =
97 unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own = own)
98
99 """
100 unsafe_load(p::Ptr{T}, i::Integer=1)
101 unsafe_load(p::Ptr{T}, order::Symbol)
102 unsafe_load(p::Ptr{T}, i::Integer, order::Symbol)
103
104 Load a value of type `T` from the address of the `i`th element (1-indexed) starting at `p`.
105 This is equivalent to the C expression `p[i-1]`. Optionally, an atomic memory ordering can
106 be provided.
107
108 The `unsafe` prefix on this function indicates that no validation is performed on the
109 pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
110 that referenced memory is not freed or garbage collected while invoking this function.
111 Incorrect usage may segfault your program or return garbage answers. Unlike C, dereferencing
112 memory region allocated as different type may be valid provided that the types are compatible.
113
114 !!! compat "Julia 1.10"
115 The `order` argument is available as of Julia 1.10.
116
117 See also: [`atomic`](@ref)
118 """
119 1 (2 %) 1 (2 %)
1 (2 %) samples spent in unsafe_load
1 (100 %) (ex.), 1 (100 %) (incl.) when called from getindex line 25
unsafe_load(p::Ptr, i::Integer=1) = pointerref(p, Int(i), 1)
120 unsafe_load(p::Ptr, order::Symbol) = atomic_pointerref(p, order)
121 function unsafe_load(p::Ptr, i::Integer, order::Symbol)
122 unsafe_load(p + (elsize(typeof(p)) * (Int(i) - 1)), order)
123 end
124
125 """
126 unsafe_store!(p::Ptr{T}, x, i::Integer=1)
127 unsafe_store!(p::Ptr{T}, x, order::Symbol)
128 unsafe_store!(p::Ptr{T}, x, i::Integer, order::Symbol)
129
130 Store a value of type `T` to the address of the `i`th element (1-indexed) starting at `p`.
131 This is equivalent to the C expression `p[i-1] = x`. Optionally, an atomic memory ordering
132 can be provided.
133
134 The `unsafe` prefix on this function indicates that no validation is performed on the
135 pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
136 that referenced memory is not freed or garbage collected while invoking this function.
137 Incorrect usage may segfault your program. Unlike C, storing memory region allocated as
138 different type may be valid provided that that the types are compatible.
139
140 !!! compat "Julia 1.10"
141 The `order` argument is available as of Julia 1.10.
142
143 See also: [`atomic`](@ref)
144 """
145 unsafe_store!(p::Ptr{Any}, @nospecialize(x), i::Integer=1) = pointerset(p, x, Int(i), 1)
146 1 (2 %) 1 (2 %)
1 (2 %) samples spent in unsafe_store!
1 (100 %) (ex.), 1 (100 %) (incl.) when called from setindex! line 35
unsafe_store!(p::Ptr{T}, x, i::Integer=1) where {T} = pointerset(p, convert(T,x), Int(i), 1)
147 unsafe_store!(p::Ptr{T}, x, order::Symbol) where {T} = atomic_pointerset(p, x isa T ? x : convert(T,x), order)
148 function unsafe_store!(p::Ptr, x, i::Integer, order::Symbol)
149 unsafe_store!(p + (elsize(typeof(p)) * (Int(i) - 1)), x, order)
150 end
151
152 """
153 unsafe_modify!(p::Ptr{T}, op, x, [order::Symbol]) -> Pair
154
155 These atomically perform the operations to get and set a memory address after applying
156 the function `op`. If supported by the hardware (for example, atomic increment), this may be
157 optimized to the appropriate hardware instruction, otherwise its execution will be
158 similar to:
159
160 y = unsafe_load(p)
161 z = op(y, x)
162 unsafe_store!(p, z)
163 return y => z
164
165 The `unsafe` prefix on this function indicates that no validation is performed on the
166 pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
167 that referenced memory is not freed or garbage collected while invoking this function.
168 Incorrect usage may segfault your program.
169
170 !!! compat "Julia 1.10"
171 This function requires at least Julia 1.10.
172
173 See also: [`modifyproperty!`](@ref Base.modifyproperty!), [`atomic`](@ref)
174 """
175 function unsafe_modify!(p::Ptr, op, x, order::Symbol=:not_atomic)
176 return atomic_pointermodify(p, op, x, order)
177 end
178
179 """
180 unsafe_replace!(p::Ptr{T}, expected, desired,
181 [success_order::Symbol[, fail_order::Symbol=success_order]]) -> (; old, success::Bool)
182
183 These atomically perform the operations to get and conditionally set a memory address to
184 a given value. If supported by the hardware, this may be optimized to the appropriate
185 hardware instruction, otherwise its execution will be similar to:
186
187 y = unsafe_load(p, fail_order)
188 ok = y === expected
189 if ok
190 unsafe_store!(p, desired, success_order)
191 end
192 return (; old = y, success = ok)
193
194 The `unsafe` prefix on this function indicates that no validation is performed on the
195 pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
196 that referenced memory is not freed or garbage collected while invoking this function.
197 Incorrect usage may segfault your program.
198
199 !!! compat "Julia 1.10"
200 This function requires at least Julia 1.10.
201
202 See also: [`replaceproperty!`](@ref Base.replaceproperty!), [`atomic`](@ref)
203 """
204 function unsafe_replace!(p::Ptr{T}, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order) where {T}
205 @inline
206 xT = desired isa T ? desired : convert(T, desired)
207 return atomic_pointerreplace(p, expected, xT, success_order, fail_order)
208 end
209 function unsafe_replace!(p::Ptr{Any}, @nospecialize(expected), @nospecialize(desired), success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
210 return atomic_pointerreplace(p, expected, desired, success_order, fail_order)
211 end
212
213 """
214 unsafe_swap!(p::Ptr{T}, x, [order::Symbol])
215
216 These atomically perform the operations to simultaneously get and set a memory address.
217 If supported by the hardware, this may be optimized to the appropriate hardware
218 instruction, otherwise its execution will be similar to:
219
220 y = unsafe_load(p)
221 unsafe_store!(p, x)
222 return y
223
224 The `unsafe` prefix on this function indicates that no validation is performed on the
225 pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
226 that referenced memory is not freed or garbage collected while invoking this function.
227 Incorrect usage may segfault your program.
228
229 !!! compat "Julia 1.10"
230 This function requires at least Julia 1.10.
231
232 See also: [`swapproperty!`](@ref Base.swapproperty!), [`atomic`](@ref)
233 """
234 function unsafe_swap!(p::Ptr{Any}, x, order::Symbol=:not_atomic)
235 return atomic_pointerswap(p, x, order)
236 end
237 function unsafe_swap!(p::Ptr{T}, x, order::Symbol=:not_atomic) where {T}
238 @inline
239 xT = x isa T ? x : convert(T, x)
240 return atomic_pointerswap(p, xT, order)
241 end
242
243 # convert a raw Ptr to an object reference, and vice-versa
244 """
245 unsafe_pointer_to_objref(p::Ptr)
246
247 Convert a `Ptr` to an object reference. Assumes the pointer refers to a valid heap-allocated
248 Julia object. If this is not the case, undefined behavior results, hence this function is
249 considered "unsafe" and should be used with care.
250
251 See also [`pointer_from_objref`](@ref).
252 """
253 unsafe_pointer_to_objref(x::Ptr) = ccall(:jl_value_ptr, Any, (Ptr{Cvoid},), x)
254
255 """
256 pointer_from_objref(x)
257
258 Get the memory address of a Julia object as a `Ptr`. The existence of the resulting `Ptr`
259 will not protect the object from garbage collection, so you must ensure that the object
260 remains referenced for the whole time that the `Ptr` will be used.
261
262 This function may not be called on immutable objects, since they do not have
263 stable memory addresses.
264
265 See also [`unsafe_pointer_to_objref`](@ref).
266 """
267 function pointer_from_objref(@nospecialize(x))
268 @inline
269 ismutable(x) || error("pointer_from_objref cannot be used on immutable objects")
270 ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x)
271 end
272
273 ## limited pointer arithmetic & comparison ##
274
275 isequal(x::Ptr, y::Ptr) = (x === y)
276 isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y
277
278 ==(x::Ptr, y::Ptr) = UInt(x) == UInt(y)
279 <(x::Ptr, y::Ptr) = UInt(x) < UInt(y)
280 -(x::Ptr, y::Ptr) = UInt(x) - UInt(y)
281
282 +(x::Ptr, y::Integer) = oftype(x, add_ptr(UInt(x), (y % UInt) % UInt))
283 -(x::Ptr, y::Integer) = oftype(x, sub_ptr(UInt(x), (y % UInt) % UInt))
284 +(x::Integer, y::Ptr) = y + x
285
286 unsigned(x::Ptr) = UInt(x)
287 signed(x::Ptr) = Int(x)