Skip to content

Commit

Permalink
Add @inline to Base.reinterpret (JuliaLang#57078)
Browse files Browse the repository at this point in the history
Reinterpret contains quite a bit of code to handle padding, and so
doesn't usually inline for structs. However, it frequently compiles down
to a noop, making an inline unusually valuable.
  • Loading branch information
jakobnissen authored Jan 31, 2025
1 parent dbcdf73 commit 3952c2c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 15 deletions.
1 change: 1 addition & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ julia> reinterpret(Tuple{UInt16, UInt8}, (0x01, 0x0203))
"""
function reinterpret(::Type{Out}, x) where {Out}
@inline
if isprimitivetype(Out) && isprimitivetype(typeof(x))
return bitcast(Out, x)
end
Expand Down
39 changes: 24 additions & 15 deletions base/reinterpretarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -871,25 +871,34 @@ end
return out[]
else
# mismatched padding
GC.@preserve in out begin
ptr_in = unsafe_convert(Ptr{In}, in)
ptr_out = unsafe_convert(Ptr{Out}, out)
return _reinterpret_padding(Out, x)
end
end

if fieldcount(In) > 0 && ispacked(Out)
_copytopacked!(ptr_out, ptr_in)
elseif fieldcount(Out) > 0 && ispacked(In)
_copyfrompacked!(ptr_out, ptr_in)
else
packed = Ref{NTuple{inpackedsize, UInt8}}()
GC.@preserve packed begin
ptr_packed = unsafe_convert(Ptr{NTuple{inpackedsize, UInt8}}, packed)
_copytopacked!(ptr_packed, ptr_in)
_copyfrompacked!(ptr_out, ptr_packed)
end
# If the code reaches this part, it needs to handle padding and is unlikely
# to compile to a noop. Therefore, we don't forcibly inline it.
function _reinterpret_padding(::Type{Out}, x::In) where {Out, In}
inpackedsize = packedsize(In)
in = Ref{In}(x)
out = Ref{Out}()
GC.@preserve in out begin
ptr_in = unsafe_convert(Ptr{In}, in)
ptr_out = unsafe_convert(Ptr{Out}, out)

if fieldcount(In) > 0 && ispacked(Out)
_copytopacked!(ptr_out, ptr_in)
elseif fieldcount(Out) > 0 && ispacked(In)
_copyfrompacked!(ptr_out, ptr_in)
else
packed = Ref{NTuple{inpackedsize, UInt8}}()
GC.@preserve packed begin
ptr_packed = unsafe_convert(Ptr{NTuple{inpackedsize, UInt8}}, packed)
_copytopacked!(ptr_packed, ptr_in)
_copyfrompacked!(ptr_out, ptr_packed)
end
end
return out[]
end
return out[]
end


Expand Down

0 comments on commit 3952c2c

Please sign in to comment.