wasmer/backend/sys/entities/
exception.rs1use 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)]
13pub(crate) struct Exception {
15 exnref: wasmer_vm::VMExceptionRef,
16}
17
18impl Exception {
19 #[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}