Skip to content

Commit

Permalink
Use pointer arithmetic to remove dynamic dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
JoJoJet committed Oct 12, 2022
1 parent 0e3d993 commit 407b8c0
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::all)]
#![feature(pointer_byte_offsets)]

use bevy::{
ecs::{
Expand All @@ -13,9 +14,8 @@ pub trait DynQuery: 'static {}

pub trait DynQueryMarker<Trait: ?Sized + DynQuery> {
type Covered: Component<Storage = TableStorage>;
/// Casts an untyped pointer to a trait object pointer,
/// with a vtable corresponding to `Self::Covered`.
fn cast(_: *mut u8) -> *mut Trait;
/// Returns a pointer to a trait object with concrete type `Self::Covered`
fn null_ptr() -> *mut Trait;
}

pub trait RegisterExt {
Expand All @@ -39,7 +39,9 @@ impl RegisterExt for World {
registry.components.push(component_id);
registry.meta.push(TraitImplMeta {
size_bytes: std::mem::size_of::<C>(),
dyn_ctor: DynCtor { cast: <(C,)>::cast },
dyn_ctor: DynCtor {
null_ptr: <(C,)>::null_ptr(),
},
});
self
}
Expand Down Expand Up @@ -92,8 +94,8 @@ macro_rules! impl_dyn_query {
$crate::DynQueryMarker<dyn $trait> for (T,)
{
type Covered = T;
fn cast(ptr: *mut u8) -> *mut dyn $trait {
ptr as *mut T as *mut _
fn null_ptr() -> *mut dyn $trait {
::std::ptr::null_mut::<T>() as *mut _
}
}

Expand Down Expand Up @@ -172,7 +174,7 @@ pub struct ReadTraitComponentsFetch<'w, Trait: ?Sized + DynQuery> {
/// Turns an untyped pointer into a trait object pointer,
/// for a specific erased concrete type.
struct DynCtor<Trait: ?Sized> {
cast: unsafe fn(*mut u8) -> *mut Trait,
null_ptr: *mut Trait,
}

impl<T: ?Sized> Copy for DynCtor<T> {}
Expand All @@ -182,12 +184,15 @@ impl<T: ?Sized> Clone for DynCtor<T> {
}
}

unsafe impl<T: ?Sized> Send for DynCtor<T> {}
unsafe impl<T: ?Sized> Sync for DynCtor<T> {}

impl<Trait: ?Sized> DynCtor<Trait> {
unsafe fn cast(self, ptr: Ptr) -> &Trait {
&*(self.cast)(ptr.as_ptr())
&*self.null_ptr.byte_add(ptr.as_ptr() as usize)
}
unsafe fn cast_mut(self, ptr: PtrMut) -> &mut Trait {
&mut *(self.cast)(ptr.as_ptr())
&mut *self.null_ptr.byte_add(ptr.as_ptr() as usize)
}
}

Expand Down

0 comments on commit 407b8c0

Please sign in to comment.