Skip to content

Commit

Permalink
Split refpointer into RefValue parts and everything else
Browse files Browse the repository at this point in the history
  • Loading branch information
Keno committed Feb 24, 2018
1 parent 84da967 commit d4929d7
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 69 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ CORE_SRCS := $(addprefix $(JULIAHOME)/, \
base/reduce.jl \
base/reflection.jl \
base/traits.jl \
base/refpointer.jl \
base/refvalue.jl \
base/tuple.jl)
COMPILER_SRCS = $(sort $(shell find $(JULIAHOME)/base/compiler -name \*.jl))
BASE_SRCS := $(sort $(shell find $(JULIAHOME)/base -name \*.jl) $(shell find $(BUILDROOT)/base -name \*.jl))
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ include("number.jl")
include("int.jl")
include("operators.jl")
include("pointer.jl")
include("refpointer.jl")
include("refvalue.jl")

# checked arithmetic
const checked_add = +
Expand Down
99 changes: 32 additions & 67 deletions base/refpointer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,8 @@ convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x
unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x)
unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x)

### Methods for a Ref object that can store a single value of any type

mutable struct RefValue{T} <: Ref{T}
x::T
RefValue{T}() where {T} = new()
RefValue{T}(x) where {T} = new(x)
end
RefValue(x::T) where {T} = RefValue{T}(x)
isassigned(x::RefValue) = isdefined(x, :x)

convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)

function unsafe_convert(P::Type{Ptr{T}}, b::RefValue{T}) where T
if datatype_pointerfree(RefValue{T})
p = pointer_from_objref(b)
elseif isconcretetype(T) && T.mutable
p = pointer_from_objref(b.x)
else
# If the slot is not leaf type, it could be either immutable or not.
# If it is actually an immutable, then we can't take it's pointer directly
# Instead, explicitly load the pointer from the `RefValue`,
# which also ensures this returns same pointer as the one rooted in the `RefValue` object.
p = pointerref(Ptr{Ptr{Cvoid}}(pointer_from_objref(b)), 1, Core.sizeof(Ptr{Cvoid}))
end
return convert(P, p)
end
function unsafe_convert(P::Type{Ptr{Any}}, b::RefValue{Any})
return convert(P, pointer_from_objref(b))
end
unsafe_convert(::Type{Ptr{Cvoid}}, b::RefValue{T}) where {T} = convert(Ptr{Cvoid}, unsafe_convert(Ptr{T}, b))

### Methods for a Ref object that is backed by an array at index i
struct RefArray{T,A<:AbstractArray{T},R} <: Ref{T}
x::A
Expand Down Expand Up @@ -98,52 +69,46 @@ function unsafe_convert(P::Type{Ptr{Any}}, b::RefArray{Any})
end
unsafe_convert(::Type{Ptr{Cvoid}}, b::RefArray{T}) where {T} = convert(Ptr{Cvoid}, unsafe_convert(Ptr{T}, b))

###
if is_primary_base_module
Ref(x::Any) = RefValue(x)
Ref{T}() where {T} = RefValue{T}() # Ref{T}()
Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x)

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

# convert Arrays to pointer arrays for ccall
function Ref{P}(a::Array{<:Union{Ptr,Cwstring,Cstring}}) where P<:Union{Ptr,Cwstring,Cstring}
return RefArray(a) # effectively a no-op
end
function Ref{P}(a::Array{T}) where P<:Union{Ptr,Cwstring,Cstring} where T
if (!isbits(T) && T <: eltype(P))
# this Array already has the right memory layout for the requested Ref
return RefArray(a,1,false) # root something, so that this function is type-stable
else
ptrs = Vector{P}(uninitialized, length(a)+1)
roots = Vector{Any}(uninitialized, length(a))
for i = 1:length(a)
root = cconvert(P, a[i])
ptrs[i] = unsafe_convert(P, root)::P
roots[i] = root
end
ptrs[length(a)+1] = C_NULL
return RefArray(ptrs,1,roots)
end
end
Ref(x::AbstractArray, i::Integer) = RefArray(x, i)
end

cconvert(::Type{Ptr{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a
cconvert(::Type{Ref{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a
cconvert(::Type{Ptr{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)
cconvert(::Type{Ref{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a)

###

getindex(b::RefValue) = b.x
getindex(b::RefArray) = b.x[b.i]

setindex!(b::RefValue, x) = (b.x = x; b)
setindex!(b::RefArray, x) = (b.x[b.i] = x; b)

###

# Base-only constructors on the shared abstract Ref type
if nameof(@__MODULE__) === :Base && is_primary_base_module

Ref(x::Any) = RefValue(x)
Ref{T}() where {T} = RefValue{T}() # Ref{T}()
Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x)
convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)

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

Ref(x::AbstractArray, i::Integer) = RefArray(x, i)

# convert Arrays to pointer arrays for ccall
function Ref{P}(a::Array{<:Union{Ptr,Cwstring,Cstring}}) where P<:Union{Ptr,Cwstring,Cstring}
return RefArray(a) # effectively a no-op
end
function Ref{P}(a::Array{T}) where P<:Union{Ptr,Cwstring,Cstring} where T
if (!isbits(T) && T <: eltype(P))
# this Array already has the right memory layout for the requested Ref
return RefArray(a,1,false) # root something, so that this function is type-stable
else
ptrs = Vector{P}(uninitialized, length(a)+1)
roots = Vector{Any}(uninitialized, length(a))
for i = 1:length(a)
root = cconvert(P, a[i])
ptrs[i] = unsafe_convert(P, root)::P
roots[i] = root
end
end
Ref(x::AbstractArray, i::Integer) = RefArray(x, i)
end

end
31 changes: 31 additions & 0 deletions base/refvalue.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
### Methods for a Ref object that can store a single value of any type

mutable struct RefValue{T} <: Ref{T}
x::T
RefValue{T}() where {T} = new()
RefValue{T}(x) where {T} = new(x)
end
RefValue(x::T) where {T} = RefValue{T}(x)
isassigned(x::RefValue) = isdefined(x, :x)

function unsafe_convert(P::Type{Ptr{T}}, b::RefValue{T}) where T
if datatype_pointerfree(RefValue{T})
p = pointer_from_objref(b)
elseif isconcretetype(T) && T.mutable
p = pointer_from_objref(b.x)
else
# If the slot is not leaf type, it could be either immutable or not.
# If it is actually an immutable, then we can't take it's pointer directly
# Instead, explicitly load the pointer from the `RefValue`,
# which also ensures this returns same pointer as the one rooted in the `RefValue` object.
p = pointerref(Ptr{Ptr{Cvoid}}(pointer_from_objref(b)), 1, Core.sizeof(Ptr{Cvoid}))
end
return convert(P, p)
end
function unsafe_convert(P::Type{Ptr{Any}}, b::RefValue{Any})
return convert(P, pointer_from_objref(b))
end
unsafe_convert(::Type{Ptr{Cvoid}}, b::RefValue{T}) where {T} = convert(Ptr{Cvoid}, unsafe_convert(Ptr{T}, b))

getindex(b::RefValue) = b.x
setindex!(b::RefValue, x) = (b.x = x; b)
1 change: 1 addition & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ include("number.jl")
include("int.jl")
include("operators.jl")
include("pointer.jl")
include("refvalue.jl")
include("refpointer.jl")
include("checked.jl")
using .Checked
Expand Down

0 comments on commit d4929d7

Please sign in to comment.