Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buffer types for array backend #48728

Closed
wants to merge 87 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
3b4bfb8
SimpleBuffer type modeled after SimpleVector
Tokazama Feb 9, 2023
af35dd8
initialize type
Tokazama Feb 9, 2023
c6cd7fd
add tags for buffer type
Tokazama Feb 10, 2023
c50f5b7
Fix codegen
Tokazama Feb 10, 2023
7e8ea0c
add dedicated hash
Tokazama Feb 10, 2023
cf00f92
fix typo
Tokazama Feb 10, 2023
2965d18
apply for sbuf
Tokazama Feb 10, 2023
97167e5
builds but doesn't work
Tokazama Feb 10, 2023
b2093ea
Add Julia side code
Tokazama Feb 10, 2023
2c0e068
enforce 8-bit values for SimpleBuffer
Tokazama Feb 18, 2023
5c7c7cf
internal 8-bit methods
Tokazama Feb 19, 2023
0172e85
Support eltype for SimpleBuffer
Tokazama Feb 20, 2023
7bd19bb
proper size for gc and more constructors
Tokazama Feb 20, 2023
3424c11
Merge branch 'master' into buffers
Tokazama Feb 20, 2023
4604d77
escape analysis on buffers
Tokazama Feb 21, 2023
17b0b11
mutable vs immutable buffers
Tokazama Feb 21, 2023
f702552
julia implimentation of immutable instantiation
Tokazama Feb 21, 2023
7231a62
Merge branch 'master' into buffers
Tokazama Feb 21, 2023
a4d55c5
Merge branch 'master' into buffers
Tokazama Feb 23, 2023
ad66f13
support malloced buffers
Tokazama Feb 24, 2023
0d6f1f4
remove ImmutableBuffer
Tokazama Feb 24, 2023
b6fe4dc
Fix malloc assigned set and ref
Tokazama Feb 25, 2023
6134dfe
Initial GC code for malloced buffers
Tokazama Feb 25, 2023
645670f
Merge branch 'master' into buffers
Tokazama Feb 25, 2023
86a4164
try to make buffer fxns names similar to arrays
Tokazama Feb 25, 2023
83e05c5
fix some typos
Tokazama Feb 25, 2023
494e418
fix bufset
Tokazama Feb 25, 2023
f015c52
fix malloc gc
Tokazama Feb 25, 2023
33acdd4
delete unsafe_freeze!
Tokazama Mar 2, 2023
5f16c17
Merge branch 'master' into buffers
Tokazama Mar 6, 2023
7bf1658
Placeholder code for codegen and cgutils
Tokazama Mar 6, 2023
5cf285a
buflen -> bufferlen and make it Core.Intrinsics.bufferlen
Tokazama Mar 10, 2023
f66a109
Merge branch 'master' into buffers
Tokazama Mar 10, 2023
b397ce3
preliminary work on buffer ptr codegen
Tokazama Mar 12, 2023
ea7fc86
Merge branch 'master' into buffers
Tokazama Mar 12, 2023
13f5954
Fixes for union types
Tokazama Mar 12, 2023
5b041b5
try fixing more codegen
Tokazama Mar 13, 2023
26dd306
Pull out escape analysis for buffer in own file
Tokazama Mar 13, 2023
2e9d985
Don't mess with includes in compiler module
Tokazama Mar 13, 2023
7ef4010
Fix subtyping for Buffer and LLVMPtr
Tokazama Mar 15, 2023
30da4e7
fix alignment issues
Tokazama Mar 15, 2023
29a8316
Cleanup/fix alignment code
Tokazama Mar 15, 2023
27b510b
Fix malloced object size
Tokazama Mar 15, 2023
af7803a
Fix fix isassigned for Buffer and bufset codegen
Tokazama Mar 15, 2023
0b7c6cf
Fix summarysize now that gc should be working
Tokazama Mar 16, 2023
5ee9b9c
jl_buffer_any_type and tests
Tokazama Mar 17, 2023
a04cec5
Merge branch 'master' into buffers
Tokazama Mar 17, 2023
6717a09
Fix copy
Tokazama Mar 17, 2023
5df4eca
fix typos
Tokazama Mar 17, 2023
29bd0b3
move more to buffers.c and fix accidental array methods in buffer met…
Tokazama Mar 18, 2023
39ce1db
grow buffer
Tokazama Mar 18, 2023
206c18b
add basics for buffer resizing methods
Tokazama Mar 19, 2023
35220ba
Merge branch 'master' into buffers
Tokazama Mar 20, 2023
88e3283
Support resizeable buffer
Tokazama Mar 21, 2023
7bf413d
Make sure effect is eventually fixed
Tokazama Mar 22, 2023
5b0ccd8
Fix bufferlen effects and support unsafe_copyto!
Tokazama Mar 23, 2023
0f1b236
add windows malloc
Tokazama Mar 23, 2023
9991d57
mark bits for shared and newly allocated data field
Tokazama Mar 25, 2023
52b8072
Can use limited number of resizing methods for raw buffers
Tokazama Mar 29, 2023
4dd43e1
Merge branch 'master' into buffers
Tokazama Mar 29, 2023
004f3e5
Start moving more functionality to Julia
Tokazama Apr 10, 2023
3dd2b4c
Merge branch 'master' into buffers
Tokazama Apr 10, 2023
dc3ac72
Fix more commit conflicts
Tokazama Apr 10, 2023
ff5e422
Merge branch 'master' into buffers
Tokazama Apr 10, 2023
d68892a
`get_buffer_value` is a pure Julia version of getindex and allocate m…
Tokazama Apr 10, 2023
b1bc8c7
improve temporary assumed effects hack for buffer pointers
Tokazama Apr 11, 2023
c2f7ba5
Merge branch 'master' into buffers
Tokazama Apr 11, 2023
eb550f5
Fix recent changes to codegen.cpp
Tokazama Apr 11, 2023
7ad80dd
Merge branch 'master' into buffers
Tokazama Apr 11, 2023
d8a40bf
Significant performance improvement on Julia implementation of getters
Tokazama Apr 12, 2023
a3bef23
Merge branch 'master' into buffers
Tokazama Apr 12, 2023
18da8a2
Fix buffer size calculation
Tokazama Apr 12, 2023
5904b3f
setting values that contain pointers
Tokazama Apr 15, 2023
0099b36
Restructure layout stuff
Tokazama Apr 16, 2023
5abe6c4
Merge branch 'master' into buffers
Tokazama Apr 16, 2023
5ad2f66
Directly allocate buffers from Julia
Tokazama Apr 17, 2023
89b1bf3
Fix moving pointers when copying
Tokazama Apr 20, 2023
b672ce4
Merge branch 'master' into buffers
Tokazama Apr 20, 2023
a517561
All Julia unsafe_copyto!
Tokazama Apr 20, 2023
e6b3be6
copy for boxed types and begin native resizing
Tokazama Apr 21, 2023
b26baf4
Remove C code that is fully replaced by Julia impl
Tokazama Apr 21, 2023
2668d1a
Retry resizing methods
Tokazama Apr 25, 2023
e2ace7f
Merge branch 'master' into buffers
Tokazama Apr 25, 2023
649e500
Remove `bufref` and `bufset` codegen
Tokazama Apr 26, 2023
cbf5b2c
More tests for resizing
Tokazama Apr 27, 2023
654ac8f
Merge branch 'master' into buffers
Tokazama Apr 27, 2023
0652811
Remove unintended find/replace changes in flisp
Tokazama Apr 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
get_buffer_value is a pure Julia version of getindex and allocate m…
…ostly in Julia

It's slower for everything but bits types, likely due to a complete lack
of assumed effects. Attempts to hack around this by annotating pointer
access haven't been successful yet so this can't yet replace getindex
Tokazama committed Apr 10, 2023
commit d68892a95710d6e0a7198f30362d219b76d693c3
119 changes: 74 additions & 45 deletions base/buffers.jl
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ struct ElementLayout
@_foldable_meta
sz = RefValue{Csize_t}(0)
al = RefValue{Csize_t}(0)
cnt = ccall(:jl_islayout_inline, Cint, (Any, Ptr{Csize_t}, Ptr{Csize_t}), T, sz, al) != 0
cnt = ccall(:jl_islayout_inline, Cint, (Any, Ptr{Csize_t}, Ptr{Csize_t}), T, sz, al)
# the number of inline elements represented at each position
# 0 : boxed pointer
# 1 : one type
@@ -99,79 +99,80 @@ struct BufferLayout
end
end

function allocate_buffer(::Type{T}, len::Int) where {T}
lyt = BufferLayout(T, len)
if lyt.isinline
buf = ccall(:jl_gc_alloc_buffer_inline, Buffer{T}, (Any, Csize_t, Csize_t), Buffer{T}, len, lyt.object_size)
else
buf = ccall(:jl_gc_malloc_buffer, Buffer{T}, (Any, Csize_t, Csize_t, Csize_t), Buffer{T}, len, lyt.data_size, lyt.object_size)
end
if lyt.element_layout.requires_initialization
ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), buf, 0, lyt.data_size)
elseif BUFFER_IMPL_NULL && lyt.elsize === 1
t = @_gc_preserve_begin buf
unsafe_store!(unsafe_convert(Ptr{UInt8}, buf) + len, 0x00)
@_gc_preserve_end t
end
return buf
# hack to get proper effects for `pointer(b)` when we know that `b` is preserved from
# garbage collection
function _preserved_pointer(b::BufferType{T}) where {T}
@_nothrow_meta
@_effect_free_terminates_locally_meta
unsafe_convert(Ptr{T}, b)
end

function bufref(b::BufferType{T}, i::Int) where {T}
function get_buffer_value(b::BufferType{T}, i::Int, bounds_check::Bool, assigned_check::Bool) where {T}
lyt = ElementLayout(T)
idx0 = i - 1
if lyt.nvariants === 0
@boundscheck 1 <= i <= length(b) || throw(BoundsError(b, i))
bounds_check && (1 <= i <= length(b) || throw(BoundsError(b, i)))
t = @_gc_preserve_begin b
p = unsafe_convert(Ptr{T}, b) + ((i - 1) * lyt.elsize)
out = ccall(:jl_value_ptr, Ref{T}, (Ptr{Cvoid},), unsafe_load(Base.unsafe_convert(Ptr{Ptr{Cvoid}}, p)))
p = _preserved_pointer(b) + (idx0 * Core.sizeof(Ptr{Cvoid}))
pt = unsafe_load(unsafe_convert(Ptr{Ptr{T}}, p))
assigned_check || (pt === C_NULL && throw(UndefRefError()))
out = unsafe_load(pt)
@_gc_preserve_end t
return out
elseif lyt.nvariants === 1
@boundscheck 1 <= i <= length(b) || throw(BoundsError(b, i))
t = @_gc_preserve_begin b
out = unsafe_load(unsafe_convert(Ptr{T}, b) + ((i - 1) * lyt.elsize))
@_gc_preserve_end t
bounds_check && (1 <= i <= length(b) || throw(BoundsError(b, i)))
if isdefined(T, :instance)
return getfield(T, :instance)
else
t = @_gc_preserve_begin b
out = unsafe_load(_preserved_pointer(b) + (idx0 * lyt.elsize))
@_gc_preserve_end t
return out
end
else
len = length(b)
@boundscheck 1 <= i <= len || throw(BoundsError(b, i))
bounds_check && (1 <= i <= len || throw(BoundsError(b, i)))
t = @_gc_preserve_begin b
idx = i - 1
p = unsafe_convert(Ptr{T}, b)
tag = unsafe_load(unsafe_convert(Ptr{UInt8}, p) + (lyt.elsize * len) + idx)
p = _preserved_pointer(b)
tag = unsafe_load(unsafe_convert(Ptr{UInt8}, p) + (lyt.elsize * len) + idx0)
vt = tag_to_variant(T, tag)
if isdefined(vt, :instance)
out = vt.instance
else
out = unsafe_load(unsafe_convert(Ptr{vt}, p) + (idx * lyt.elsize))
out = unsafe_load(unsafe_convert(Ptr{vt}, p) + (idx0 * lyt.elsize))
end
@_gc_preserve_end t
return out
end
return out
end

function bufset!(b::BufferType{T}, v::T, i::Int) where {T}
function set_buffer_value!(b::BufferType{T}, v::T, i::Int, bounds_check::Bool) where {T}
lyt = ElementLayout(T)
idx0 = i - 1
if lyt.nvariants === 0
@boundscheck 1 <= i <= length(b) || throw(BoundsError(b, i))
bounds_check && (1 <= i <= length(b) || throw(BoundsError(b, i)))
t = @_gc_preserve_begin b
p = unsafe_convert(Ptr{T}, b) + ((i - 1) * lyt.elsize)
p = unsafe_convert(Ptr{T}, b) + (idx0 * lyt.elsize)
# FIXME this won't work for immutable values
unsafe_store!(unsafe_convert(Ptr{Ptr{Cvoid}}, p), pointer_from_objref(v))
@_gc_preserve_end t
elseif lyt.nvariants === 1
@boundscheck 1 <= i <= length(b) || throw(BoundsError(b, i))
t = @_gc_preserve_begin b
unsafe_store!(unsafe_convert(Ptr{T}, b) + ((i - 1) * lyt.elsize), v)
@_gc_preserve_end t
bounds_check && (1 <= i <= length(b) || throw(BoundsError(b, i)))
if !isdefined(vt, :instance)
t = @_gc_preserve_begin b
unsafe_store!(unsafe_convert(Ptr{T}, b) + (idx0 * lyt.elsize), v)
@_gc_preserve_end t
end
else
len = length(b)
@boundscheck 1 <= i <= len || throw(BoundsError(b, i))
bounds_check && (1 <= i <= len || throw(BoundsError(b, i)))
t = @_gc_preserve_begin b
idx = i - 1
p = unsafe_convert(Ptr{T}, b)
vt = typeof(v)
tag = variant_to_tag(T, vt)
unsafe_store!(convert(Ptr{UInt8}, p) + (lyt.elsize * len) + idx, tag)
unsafe_store!(convert(Ptr{UInt8}, p) + (lyt.elsize * len) + idx0, tag)
if !isdefined(vt, :instance)
unsafe_store!(unsafe_convert(Ptr{vt}, p) + (idx * lyt.elsize), v)
unsafe_store!(unsafe_convert(Ptr{vt}, p) + (idx0 * lyt.elsize), v)
end
@_gc_preserve_end t
end
@@ -200,8 +201,22 @@ DynamicBuffer

if !isdefined(Main, :Base)

Buffer{T}(::UndefInitializer, len::Int) where {T} =
ccall(:jl_new_buffer, Buffer{T}, (Any, Int), Buffer{T}, len)
function Buffer{T}(::UndefInitializer, len::Int) where {T}
lyt = BufferLayout(T, len)
if lyt.isinline
buf = ccall(:jl_gc_alloc_buffer_inline, Buffer{T}, (Any, Csize_t, Csize_t), Buffer{T}, len, lyt.object_size)
else
buf = ccall(:jl_gc_malloc_buffer, Buffer{T}, (Any, Csize_t, Csize_t, Csize_t), Buffer{T}, len, lyt.data_size, lyt.object_size)
end
if lyt.element_layout.requires_initialization
ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), buf, 0, lyt.data_size)
elseif BUFFER_IMPL_NULL && lyt.elsize === 1
t = @_gc_preserve_begin buf
unsafe_store!(unsafe_convert(Ptr{UInt8}, buf) + len, 0x00)
@_gc_preserve_end t
end
return buf
end
Buffer(a::AbstractArray{T}) where {T} = Buffer{T}(a)
function Buffer{T}(a::AbstractArray) where {T}
n = length(a)
@@ -214,8 +229,22 @@ function Buffer{T}(a::AbstractArray) where {T}
return b
end

DynamicBuffer{T}(::UndefInitializer, len::Int) where {T} =
ccall(:jl_new_buffer, DynamicBuffer{T}, (Any, Int), DynamicBuffer{T}, len)
function DynamicBuffer{T}(::UndefInitializer, len::Int) where {T}
lyt = BufferLayout(T, len)
if lyt.isinline
buf = ccall(:jl_gc_alloc_buffer_inline, DynamicBuffer{T}, (Any, Csize_t, Csize_t), DynamicBuffer{T}, len, lyt.object_size)
else
buf = ccall(:jl_gc_malloc_buffer, DynamicBuffer{T}, (Any, Csize_t, Csize_t, Csize_t), DynamicBuffer{T}, len, lyt.data_size, lyt.object_size)
end
if lyt.element_layout.requires_initialization
ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), buf, 0, lyt.data_size)
elseif BUFFER_IMPL_NULL && lyt.elsize === 1
t = @_gc_preserve_begin buf
unsafe_store!(unsafe_convert(Ptr{UInt8}, buf) + len, 0x00)
@_gc_preserve_end t
end
return buf
end
DynamicBuffer(a::AbstractArray{T}) where {T} = Dynamicfer{T}(a)
function DynamicBuffer{T}(a::AbstractArray) where {T}
n = length(a)