Skip to content

Commit

Permalink
Try out unsafe approach from #169
Browse files Browse the repository at this point in the history
After:
```
$ rake compile:release && rake bench:host_call
[...]

Calculating -------------------------------------
Call host func (4 args)
                        519.910k (± 1.3%) i/s -      2.608M in   5.016526s
Call host func (16 args)
                        440.924k (± 0.6%) i/s -      2.243M in   5.086693s
Call host func (64 args)
                        277.404k (± 1.2%) i/s -      1.412M in   5.089372s
Call host func (128 args)
                        144.274k (± 0.7%) i/s -    734.910k in   5.094121s
Call host func (256 args)
                         55.141k (± 1.1%) i/s -    279.990k in   5.078321s
```
  • Loading branch information
jbourassa committed Apr 23, 2023
1 parent cb6125b commit 88e7444
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions ext/src/ruby_api/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,39 @@ impl<'a> Func<'a> {
[] => Ok(().into_value()),
[result] => result.to_ruby_value(store),
_ => {
let mut ruby_values : Vec<Value> = Vec::with_capacity(results.len());
for result in results {
// Q: can this trigger GC?
ruby_values.push(result.to_ruby_value(store)?);
let fake_values = unsafe { std::mem::transmute(results.as_slice()) };
let array = RArray::from_slice::<Value>(fake_values);
let array_slice = unsafe { rarray_as_mut_slice(array, results.len()) };
let results_iter = results.iter().enumerate();
assert!(array_slice.len() == results_iter.len());

for (i, result) in results.iter().enumerate() {
array_slice[i] = result.to_ruby_value(store).map_err(|e| {
// If we fail along the way, zero out the array just to be safe
let _ = array.clear();
e
})?;
}
Ok(*RArray::from_slice(&ruby_values))

Ok(array.into())
}
}
}
}

/// Converts an `RArray` into a mutable slice.
///
/// # Safety
/// The capacity of the array must be known in advance for this to be safe, since we provide mutable access to the array's contents.
unsafe fn rarray_as_mut_slice<'a>(array: RArray, capacity: usize) -> &'a mut [Value] {
let array_slice = unsafe { array.as_slice() };
let ptr = array_slice.as_ptr();
let array_slice = unsafe { std::slice::from_raw_parts_mut(ptr as *mut Value, capacity) };

array_slice
}


impl From<&Func<'_>> for wasmtime::Extern {
fn from(func: &Func) -> Self {
Self::Func(func.get())
Expand Down

0 comments on commit 88e7444

Please sign in to comment.