wasmer/backend/sys/entities/
exception.rs

1//! Data types, functions and traits for `sys` runtime's `Tag` implementation.
2use std::any::Any;
3
4use wasmer_types::{TagType, Type};
5use wasmer_vm::{StoreHandle, StoreId};
6
7use crate::{
8    AsStoreMut, AsStoreRef, BackendTag, Tag, Value,
9    sys::vm::{VMExceptionObj, VMExceptionRef},
10};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13/// A WebAssembly `exnref` in the `sys` runtime.
14pub(crate) struct Exception {
15    exnref: wasmer_vm::VMExceptionRef,
16}
17
18impl Exception {
19    /// Creates a new exception with the given tag and payload, and also creates
20    /// a reference to it, returning the reference.
21    #[allow(irrefutable_let_patterns)]
22    pub fn new(store: &mut impl AsStoreMut, tag: &crate::sys::tag::Tag, payload: &[Value]) -> Self {
23        if !tag.is_from_store(store) {
24            panic!("cannot create Exception with Tag from another Store");
25        }
26
27        let store_objects = store.as_store_ref().objects().as_sys();
28        let store_id = store_objects.id();
29
30        let tag_ty = tag.handle.get(store_objects).signature.params();
31
32        if tag_ty.len() != payload.len() {
33            panic!("payload length mismatch");
34        }
35
36        let values = payload
37            .iter()
38            .enumerate()
39            .map(|(i, v)| {
40                if v.ty() != tag_ty[i] {
41                    panic!("payload type mismatch");
42                }
43                v.as_raw(store)
44            })
45            .collect::<Vec<_>>()
46            .into_boxed_slice();
47
48        let ctx = store.objects_mut().as_sys_mut();
49        let exception = wasmer_vm::VMExceptionObj::new(tag.handle.internal_handle(), values);
50        let exn_handle = wasmer_vm::StoreHandle::new(ctx, exception);
51        let exnref = wasmer_vm::VMExceptionRef(exn_handle);
52
53        Self { exnref }
54    }
55
56    pub fn exnref(&self) -> wasmer_vm::VMExceptionRef {
57        self.exnref.clone()
58    }
59
60    pub fn from_exnref(exnref: wasmer_vm::VMExceptionRef) -> Self {
61        Self { exnref }
62    }
63
64    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
65        self.exnref.0.store_id() == store.as_store_ref().objects().id()
66    }
67
68    pub fn tag(&self, store: &impl AsStoreRef) -> crate::sys::tag::Tag {
69        if !self.is_from_store(store) {
70            panic!("Exception is from another Store");
71        }
72        let ctx = store.as_store_ref().objects().as_sys();
73        let exception = self.exnref.0.get(ctx);
74        let tag_handle = exception.tag();
75        crate::sys::tag::Tag {
76            handle: unsafe { StoreHandle::from_internal(ctx.id(), tag_handle) },
77        }
78    }
79
80    pub fn payload(&self, store: &mut impl AsStoreMut) -> Vec<Value> {
81        if !self.is_from_store(store) {
82            panic!("Exception is from another Store");
83        }
84        let ctx = store.as_store_ref().objects().as_sys();
85        let exception = self.exnref.0.get(ctx);
86        let params_ty = exception.tag().get(ctx).signature.params().to_vec();
87        let payload_ptr = exception.payload();
88
89        assert_eq!(params_ty.len(), payload_ptr.len());
90
91        params_ty
92            .iter()
93            .zip(unsafe { payload_ptr.as_ref().iter() })
94            .map(|(ty, raw)| unsafe { Value::from_raw(store, *ty, *raw) })
95            .collect()
96    }
97}
98
99#[cfg(feature = "artifact-size")]
100impl loupe::MemoryUsage for Exception {
101    fn size_of_val(&self, tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
102        std::mem::size_of::<Self>()
103    }
104}