Skip to content

Commit

Permalink
copy/swap_bytes refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
tower120 committed May 8, 2024
1 parent 0bec11c commit 2affe62
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 77 deletions.
21 changes: 11 additions & 10 deletions src/any_value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub use raw::{AnyValueRaw, AnyValueTypelessRaw, AnyValueSizelessRaw};
use std::any::TypeId;
use std::{mem, ptr};
use std::mem::{MaybeUninit, size_of};
use crate::{copy_bytes_nonoverlapping, swap_bytes_nonoverlapping};

/// Marker for unknown type.
pub struct Unknown;
Expand Down Expand Up @@ -166,20 +165,22 @@ pub trait AnyValue: AnyValueTypeless {
}

/// Helper function, which utilize type knowledge.
#[inline]
#[inline(always)]
pub(crate) unsafe fn copy_bytes<KnownType: 'static>(
input: *const u8, out: *mut u8, bytes_size: usize
) {
if !Unknown::is::<KnownType>() {
ptr::copy_nonoverlapping(
input as *const KnownType,
out as *mut KnownType,
1);
1
);
} else {
copy_bytes_nonoverlapping(
ptr::copy_nonoverlapping(
input,
out,
bytes_size);
bytes_size
);
}
}

Expand All @@ -197,15 +198,15 @@ pub trait AnyValueSizelessMut: AnyValueSizeless {

/// Mutable [AnyValueTypeless].
pub trait AnyValueTypelessMut: AnyValueTypeless + AnyValueSizelessMut {
#[inline]
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8]{
unsafe{std::slice::from_raw_parts_mut(
self.as_bytes_mut_ptr(),
self.size()
)}
}

#[inline]
#[inline(always)]
unsafe fn swap_unchecked<Other: AnyValueMut>(&mut self, other: &mut Other){
// compile-time check
if !Unknown::is::<Self::Type>() {
Expand All @@ -220,7 +221,7 @@ pub trait AnyValueTypelessMut: AnyValueTypeless + AnyValueSizelessMut {
);
} else {
let bytes = self.as_bytes_mut();
swap_bytes_nonoverlapping(
ptr::swap_nonoverlapping(
bytes.as_mut_ptr(),
other.as_bytes_mut().as_mut_ptr(),
bytes.len()
Expand All @@ -231,7 +232,7 @@ pub trait AnyValueTypelessMut: AnyValueTypeless + AnyValueSizelessMut {

/// Mutable [AnyValue].
pub trait AnyValueMut: AnyValueTypelessMut + AnyValue {
#[inline]
#[inline(always)]
fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T>{
if self.value_typeid() != TypeId::of::<T>(){
None
Expand All @@ -245,7 +246,7 @@ pub trait AnyValueMut: AnyValueTypelessMut + AnyValue {
/// # Panic
///
/// Panics, if type mismatch.
#[inline]
#[inline(always)]
fn swap<Other: AnyValueMut>(&mut self, other: &mut Other){
assert_eq!(self.value_typeid(), other.value_typeid());
unsafe{
Expand Down
52 changes: 1 addition & 51 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,28 +156,7 @@ pub mod element;
use std::ptr;
use std::ops::{Bound, Range, RangeBounds};

// This is faster then ptr::copy_nonoverlapping,
// when count is runtime value, and count is small.
#[inline]
unsafe fn copy_bytes_nonoverlapping(src: *const u8, dst: *mut u8, count: usize){
// Somehow, it looks ok now.
// Tracking issue https://github.com/rust-lang/rust/issues/97022
ptr::copy_nonoverlapping(src, dst, count);
return;

/*// MIRI hack
if cfg!(miri)
// || count >= 128
{
ptr::copy_nonoverlapping(src, dst, count);
return;
}
for i in 0..count{
*dst.add(i) = *src.add(i);
}*/
}

// TODO: remove
// This is faster then ptr::copy,
// when count is runtime value, and count is small.
#[inline]
Expand All @@ -195,35 +174,6 @@ unsafe fn copy_bytes(src: *const u8, dst: *mut u8, count: usize){
}
}


// same as copy_bytes_nonoverlapping but for swap_nonoverlapping.
#[inline]
unsafe fn swap_bytes_nonoverlapping(src: *mut u8, dst: *mut u8, count: usize){
// MIRI hack
if cfg!(miri) {
let mut tmp = Vec::<u8>::new();
tmp.resize(count, 0);

// src -> tmp
ptr::copy_nonoverlapping(src, tmp.as_mut_ptr(), count);
// dst -> src
ptr::copy_nonoverlapping(dst, src, count);
// tmp -> dst
ptr::copy_nonoverlapping(tmp.as_ptr(), dst, count);

return;
}

for i in 0..count{
let src_pos = src.add(i);
let dst_pos = dst.add(i);

let tmp = *src_pos;
*src_pos = *dst_pos;
*dst_pos = tmp;
}
}

#[inline]
fn into_range(
len: usize,
Expand Down
22 changes: 6 additions & 16 deletions src/ops/swap_remove.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::marker::PhantomData;
use std::ptr;
use crate::copy_bytes_nonoverlapping;
use crate::any_value::Unknown;
use crate::any_value::copy_bytes;
use crate::any_vec_ptr::IAnyVecRawPtr;
use crate::any_vec_ptr::utils::{element_mut_ptr_at, element_ptr_at};
use crate::any_vec_raw::AnyVecRaw;
Expand Down Expand Up @@ -49,19 +47,11 @@ impl<'a, AnyVecPtr: IAnyVecRawPtr> Operation for SwapRemove<'a, AnyVecPtr>{
let any_vec_raw = self.any_vec_ptr.any_vec_raw_mut();

if self.element as *const u8 != last_element {
if !Unknown::is::<AnyVecPtr::Element>() {
ptr::copy_nonoverlapping(
last_element as *const AnyVecPtr::Element,
self.element as *mut AnyVecPtr::Element,
1
);
} else {
copy_bytes_nonoverlapping(
last_element,
self.element,
any_vec_raw.element_layout().size()
);
}
copy_bytes::<AnyVecPtr::Element>(
last_element,
self.element,
any_vec_raw.element_layout().size()
);
}

// 3. shrink len `self.any_vec.len -= 1`
Expand Down

0 comments on commit 2affe62

Please sign in to comment.