Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rune: More perf work #879

Merged
merged 1 commit into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions crates/rune/src/runtime/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::alloc::prelude::*;
use crate::alloc::{self, Box, Vec};
use crate::Any;

use super::{IntoOutput, RawAnyGuard, Ref, UnsafeToRef, Value, VmResult};
use super::{IntoOutput, RawAnyGuard, Ref, RuntimeError, UnsafeToRef, Value, VmResult};

/// A vector of bytes.
#[derive(Any, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -452,10 +452,8 @@ impl TryFrom<&[u8]> for Value {
}

impl IntoOutput for &[u8] {
type Output = Bytes;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(vm_try!(Bytes::try_from(self)))
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(Value::try_from(self)?)
}
}
101 changes: 32 additions & 69 deletions crates/rune/src/runtime/inst.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use core::cmp::Ordering;
use core::fmt;
use core::num::NonZeroUsize;

use musli::{Decode, Encode};
use rune_macros::InstDisplay;
use serde::{Deserialize, Serialize};

use crate as rune;
use crate::alloc::prelude::*;
use crate::runtime::{Call, FormatSpec, Memory, Type, Value, VmError, VmResult};
use crate::Hash;

use super::{Call, FormatSpec, Memory, RuntimeError, Type, Value};

/// Pre-canned panic reasons.
///
/// To formulate a custom reason, use
Expand Down Expand Up @@ -1123,56 +1123,37 @@ impl Inst {
}
}

/// The calling convention of a function.
#[derive(
Debug, TryClone, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, Decode,
)]
#[try_clone(copy)]
#[non_exhaustive]
enum OutputKind {
/// Push the produced value onto the stack.
Keep(NonZeroUsize),
/// Discard the produced value, leaving the stack unchanged.
Discard,
}

/// What to do with the output of an instruction.
#[derive(TryClone, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, Decode)]
#[try_clone(copy)]
#[non_exhaustive]
#[musli(transparent)]
#[serde(transparent)]
pub struct Output {
kind: OutputKind,
offset: usize,
}

impl Output {
/// Construct a keep output kind.
#[inline]
pub(crate) fn keep(index: usize) -> Self {
let Some(index) = NonZeroUsize::new(index ^ usize::MAX) else {
panic!("Index {index} is out of bounds")
};

Self {
kind: OutputKind::Keep(index),
}
pub(crate) fn keep(offset: usize) -> Self {
assert_ne!(offset, usize::MAX, "Address is invalid");
Self { offset }
}

/// Construct a discard output kind.
#[inline]
pub(crate) fn discard() -> Self {
Self {
kind: OutputKind::Discard,
}
Self { offset: usize::MAX }
}

/// Check if the output is a keep.
#[inline]
#[inline(always)]
pub(crate) fn as_addr(&self) -> Option<InstAddress> {
match self.kind {
OutputKind::Keep(index) => Some(InstAddress::new(index.get() ^ usize::MAX)),
OutputKind::Discard => None,
if self.offset == usize::MAX {
None
} else {
Some(InstAddress::new(self.offset))
}
}

Expand Down Expand Up @@ -1200,25 +1181,26 @@ impl Output {
/// out.store(stack, number);
/// VmResult::Ok(())
/// }
#[inline]
pub fn store<O>(self, stack: &mut dyn Memory, o: O) -> VmResult<()>
#[inline(always)]
pub fn store<M, O>(self, stack: &mut M, o: O) -> Result<(), RuntimeError>
where
O: IntoOutput<Output: TryInto<Value, Error: Into<VmError>>>,
M: ?Sized + Memory,
O: IntoOutput,
{
if let Some(addr) = self.as_addr() {
let value = vm_try!(o.into_output());
*vm_try!(stack.at_mut(addr)) = vm_try!(value.try_into().map_err(Into::into));
*stack.at_mut(addr)? = o.into_output()?;
}

VmResult::Ok(())
Ok(())
}
}

impl fmt::Display for Output {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
OutputKind::Keep(index) => write!(f, "keep({})", index.get() ^ usize::MAX),
OutputKind::Discard => write!(f, "discard"),
if self.offset == usize::MAX {
write!(f, "discard")
} else {
write!(f, "keep({})", self.offset)
}
}
}
Expand All @@ -1232,53 +1214,36 @@ impl fmt::Debug for Output {

/// Trait used to coerce values into outputs.
pub trait IntoOutput {
#[doc(hidden)]
type Output;

/// Coerce the current value into an output.
fn into_output(self) -> VmResult<Self::Output>;
fn into_output(self) -> Result<Value, RuntimeError>;
}

impl<F, O> IntoOutput for F
where
F: FnOnce() -> O,
O: IntoOutput,
{
type Output = O::Output;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
fn into_output(self) -> Result<Value, RuntimeError> {
self().into_output()
}
}

impl<T, E> IntoOutput for Result<T, E>
where
VmError: From<E>,
T: IntoOutput,
RuntimeError: From<E>,
{
type Output = T;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(vm_try!(self))
}
}

impl<T> IntoOutput for VmResult<T> {
type Output = T;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
self
fn into_output(self) -> Result<Value, RuntimeError> {
self?.into_output()
}
}

impl IntoOutput for Value {
type Output = Value;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(self)
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(self)
}
}

Expand Down Expand Up @@ -1840,10 +1805,8 @@ where
}

impl IntoOutput for &str {
type Output = String;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(vm_try!(String::try_from(self)))
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(Value::try_from(self)?)
}
}
8 changes: 8 additions & 0 deletions crates/rune/src/runtime/stack.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::array;
use core::convert::Infallible;
use core::fmt;
use core::mem::replace;
use core::slice;
Expand All @@ -16,6 +17,13 @@ pub struct StackError {
addr: InstAddress,
}

impl From<Infallible> for StackError {
#[inline]
fn from(value: Infallible) -> Self {
match value {}
}
}

impl fmt::Display for StackError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
20 changes: 8 additions & 12 deletions crates/rune/src/runtime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,16 +561,16 @@ impl Value {
}

/// Construct an empty.
pub fn empty_struct(rtti: Arc<Rtti>) -> VmResult<Self> {
VmResult::Ok(Value::from(vm_try!(Dynamic::new(rtti, []))))
pub fn empty_struct(rtti: Arc<Rtti>) -> alloc::Result<Self> {
Ok(Value::from(Dynamic::new(rtti, [])?))
}

/// Construct a typed tuple.
pub fn tuple_struct(
rtti: Arc<Rtti>,
data: impl IntoIterator<IntoIter: ExactSizeIterator, Item = Value>,
) -> VmResult<Self> {
VmResult::Ok(Value::from(vm_try!(Dynamic::new(rtti, data))))
) -> alloc::Result<Self> {
Ok(Value::from(Dynamic::new(rtti, data)?))
}

/// Drop the interior value.
Expand Down Expand Up @@ -1559,11 +1559,9 @@ impl From<()> for Value {
}

impl IntoOutput for () {
type Output = ();

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(())
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(Value::from(()))
}
}

Expand All @@ -1586,11 +1584,9 @@ impl From<AnyObj> for Value {
}

impl IntoOutput for Inline {
type Output = Inline;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(self)
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(Value::from(self))
}
}

Expand Down
8 changes: 3 additions & 5 deletions crates/rune/src/runtime/value/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::alloc::fmt::TryWrite;
use crate::hash::Hash;
use crate::runtime::{
Access, AccessError, BorrowMut, BorrowRef, Formatter, IntoOutput, ProtocolCaller, Rtti,
RttiKind, Snapshot, TypeInfo, Value, VmResult,
RttiKind, RuntimeError, Snapshot, TypeInfo, Value, VmResult,
};

#[derive(Debug)]
Expand Down Expand Up @@ -471,10 +471,8 @@ fn debug_struct(
}

impl IntoOutput for Dynamic<Arc<Rtti>, Value> {
type Output = Dynamic<Arc<Rtti>, Value>;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(self)
fn into_output(self) -> Result<Value, RuntimeError> {
Ok(Value::from(self))
}
}
12 changes: 4 additions & 8 deletions crates/rune/src/runtime/value/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,9 @@ macro_rules! any_from {
}

impl IntoOutput for $ty {
type Output = $ty;

#[inline]
fn into_output(self) -> VmResult<Self::Output> {
VmResult::Ok(self)
fn into_output(self) -> Result<$crate::runtime::Value, $crate::runtime::RuntimeError> {
Ok(Value::new(self)?)
}
}
)*
Expand All @@ -97,11 +95,9 @@ macro_rules! inline_from {
}

impl $crate::runtime::IntoOutput for $ty {
type Output = $ty;

#[inline]
fn into_output(self) -> $crate::runtime::VmResult<Self::Output> {
$crate::runtime::VmResult::Ok(self)
fn into_output(self) -> Result<$crate::runtime::Value, $crate::runtime::RuntimeError> {
Ok($crate::runtime::Value::from(self))
}
}

Expand Down
16 changes: 4 additions & 12 deletions crates/rune/src/runtime/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2056,10 +2056,7 @@ impl Vm {
.map(take)
.try_collect::<alloc::Vec<Value>>());

vm_try!(out.store(&mut self.stack, || VmResult::Ok(vm_try!(
OwnedTuple::try_from(tuple)
))));

vm_try!(out.store(&mut self.stack, || OwnedTuple::try_from(tuple)));
VmResult::Ok(())
}

Expand All @@ -2073,10 +2070,7 @@ impl Vm {
vm_try!(tuple.try_push(value));
}

vm_try!(out.store(&mut self.stack, || VmResult::Ok(vm_try!(
OwnedTuple::try_from(tuple)
))));

vm_try!(out.store(&mut self.stack, || OwnedTuple::try_from(tuple)));
VmResult::Ok(())
}

Expand Down Expand Up @@ -2867,10 +2861,8 @@ impl Vm {
.lookup_rtti(hash)
.ok_or(VmErrorKind::MissingRtti { hash }));

vm_try!(out.store(&mut self.stack, || Dynamic::<_, Value>::new(
rtti.clone(),
[]
)));
let value = vm_try!(Dynamic::<_, Value>::new(rtti.clone(), []));
vm_try!(out.store(&mut self.stack, value));
VmResult::Ok(())
}

Expand Down
9 changes: 9 additions & 0 deletions crates/rune/src/runtime/vm_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,15 @@ impl From<AccessError> for RuntimeError {
}
}

impl From<StackError> for RuntimeError {
#[inline]
fn from(error: StackError) -> Self {
Self {
error: VmErrorKind::from(error),
}
}
}

impl From<AccessErrorKind> for RuntimeError {
#[inline]
fn from(error: AccessErrorKind) -> Self {
Expand Down