Skip to content

Commit

Permalink
Implement Rt<[T; N]>
Browse files Browse the repository at this point in the history
This will remove even more allocations from function calls
  • Loading branch information
CeleritasCelery committed Dec 22, 2023
1 parent dcc6587 commit 54d88f8
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 21 deletions.
46 changes: 42 additions & 4 deletions src/core/gc/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ where
}
}

impl<'new, T, const N: usize> WithLifetime<'new> for [T; N]
where
T: WithLifetime<'new>,
{
type Out = [<T as WithLifetime<'new>>::Out; N];
unsafe fn with_lifetime(self) -> Self::Out {
// work around since we can't transmute arrays
let ptr = &self as *const [T; N] as *const Self::Out;
let value = unsafe { ptr.read() };
std::mem::forget(self);
value
}
}

impl<'new, T> WithLifetime<'new> for Vec<T>
where
T: WithLifetime<'new>,
Expand Down Expand Up @@ -445,6 +459,34 @@ impl<T> Rt<Option<T>> {
}
}

impl<T, I, const N: usize> Index<I> for Rt<[T; N]>
where
[Rt<T>]: Index<I>,
{
type Output = <[Rt<T>] as Index<I>>::Output;

fn index(&self, index: I) -> &Self::Output {
let slice = unsafe { std::mem::transmute::<&[T], &[Rt<T>]>(&self.inner) };
Index::index(slice, index)
}
}

impl<T, I, const N: usize> IndexMut<I> for Rt<[T; N]>
where
[Rt<T>]: IndexMut<I>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
let slice = unsafe { std::mem::transmute::<&mut [T], &mut [Rt<T>]>(&mut self.inner) };
IndexMut::index_mut(slice, index)
}
}

impl<T, const N: usize> AsRef<[Rt<T>]> for Rt<[T; N]> {
fn as_ref(&self) -> &[Rt<T>] {
unsafe { std::mem::transmute::<&[T], &[Rt<T>]>(&self.inner) }
}
}

impl<T> Rt<Vec<T>> {
// This is not safe to expose pub(crate) because you could call pop and get
// an owned Rt
Expand All @@ -465,10 +507,6 @@ impl<T> Rt<Vec<T>> {
self.as_mut_ref().pop();
}

pub(crate) fn clear(&mut self) {
self.as_mut_ref().clear();
}

pub(crate) fn swap_remove(&mut self, index: usize) {
self.as_mut_ref().swap_remove(index);
}
Expand Down
8 changes: 8 additions & 0 deletions src/core/gc/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ impl<T: Trace> Trace for [T] {
}
}

impl<T: Trace, const N: usize> Trace for [T; N] {
fn trace(&self, stack: &mut Vec<RawObj>) {
for x in self {
x.trace(stack);
}
}
}

impl<T: Trace> Trace for Vec<T> {
fn trace(&self, stack: &mut Vec<RawObj>) {
for x in self {
Expand Down
20 changes: 8 additions & 12 deletions src/fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,18 +436,16 @@ fn sort<'ob>(

root!(tmp, nil(), cx);
root!(vec, cx);
// TODO: Use an array
root!(args, Vec::new(), cx);
root!(args, [nil(), nil()], cx);
// A simple insertion sort
// TODO: use a better sort like tim sort
for i in 1..len {
tmp.set(&vec[i]);
let mut j = i;
while j > 0 {
args.clear();
args.push(&vec[j - 1]);
args.push(&*tmp);
match predicate.call(args, None, env, cx) {
args[0].set(&vec[j - 1]);
args[1].set(&*tmp);
match predicate.call(&args[..], None, env, cx) {
Ok(cmp) => {
if cmp != nil() {
break;
Expand Down Expand Up @@ -690,21 +688,19 @@ fn maphash(
}
};

// TODO: Use array
root!(args, Vec::new(), cx);
root!(args, [nil(), nil()], cx);
loop {
{
let mut view = table.bind(cx).untag().try_borrow_mut()?;
let Some(idx) = get_idx(&mut view) else { break };
let (key, val) = view.get_index(idx).unwrap();
args.push(*key);
args.push(*val);
args[0].set(*key);
args[1].set(*val);
}
if let Err(e) = function.call(args, None, env, cx) {
if let Err(e) = function.call(&args[..], None, env, cx) {
table.bind(cx).untag().try_borrow_mut().unwrap().iter_next = 0;
return Err(e.into());
}
args.clear();
}
table.bind(cx).untag().try_borrow_mut().unwrap().iter_next = 0;
Ok(false)
Expand Down
8 changes: 3 additions & 5 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,9 @@ impl Interpreter<'_, '_> {
let closure_fn: Result<&Rt<Gc<Function>>, _> = closure_fn.try_into();
if let Ok(closure_fn) = closure_fn {
root!(closure_fn, cx);
// TODO: use array
root!(args, Vec::new(), cx);
args.push(form.bind(cx));
args.push(env);
return closure_fn.call(args, None, self.env, cx);
let args = [form.bind(cx), env];
root!(args, cx);
return closure_fn.call(&args[..], None, self.env, cx);
}
}
}
Expand Down

0 comments on commit 54d88f8

Please sign in to comment.