11use super :: convert:: ToWasmVal ;
22use magnus:: { exception:: arg_error, Error , ExceptionClass , Value } ;
3+ use static_assertions:: assert_eq_size;
34use wasmtime:: { FuncType , ValType } ;
45
5- #[ derive( Debug ) ]
6- struct Param < ' a > {
7- index : usize ,
8- ty : ValType ,
9- val : & ' a Value ,
6+ #[ derive( Debug , Copy , Clone ) ]
7+ #[ repr( C ) ]
8+ struct Param {
9+ val : Value ,
10+ index : u32 ,
11+ ty : ValTypeCopy ,
1012}
13+ // Keep `Param` small so copying it to the stack is cheap, typically anything
14+ // less than 3usize is good
15+ assert_eq_size ! ( Param , [ u64 ; 2 ] ) ;
1116
12- impl < ' a > Param < ' a > {
13- pub fn new ( index : usize , ty : ValType , val : & ' a Value ) -> Self {
14- Self { index, ty, val }
17+ impl Param {
18+ pub fn new ( index : u32 , ty : ValType , val : Value ) -> Self {
19+ Self {
20+ index,
21+ ty : ty. into ( ) ,
22+ val,
23+ }
1524 }
1625
17- fn to_wasmtime_val ( & self ) -> Result < wasmtime:: Val , Error > {
18- self . val . to_wasm_val ( & self . ty ) . map_err ( |error| match error {
19- Error :: Error ( class, msg) => {
20- Error :: new ( class, format ! ( "{} (param index {}) " , msg, self . index) )
21- }
22- Error :: Exception ( exception) => Error :: new (
23- ExceptionClass :: from_value ( exception. class ( ) . into ( ) ) . unwrap_or_else ( arg_error) ,
24- format ! ( "{} (param index {}) " , exception, self . index) ,
25- ) ,
26- _ => error,
27- } )
26+ fn to_wasmtime_val ( self ) -> Result < wasmtime:: Val , Error > {
27+ self . val
28+ . to_wasm_val ( self . ty . into ( ) )
29+ . map_err ( |error| match error {
30+ Error :: Error ( class, msg) => {
31+ Error :: new ( class, format ! ( "{} (param at index {})" , msg, self . index) )
32+ }
33+ Error :: Exception ( exception) => Error :: new (
34+ ExceptionClass :: from_value ( exception. class ( ) . into ( ) ) . unwrap_or_else ( arg_error) ,
35+ format ! ( "{} (param at index {})" , exception, self . index) ,
36+ ) ,
37+ _ => error,
38+ } )
2839 }
2940}
3041
@@ -48,10 +59,55 @@ impl<'a> Params<'a> {
4859 pub fn to_vec ( & self ) -> Result < Vec < wasmtime:: Val > , Error > {
4960 let mut vals = Vec :: with_capacity ( self . 0 . params ( ) . len ( ) ) ;
5061 for ( i, ( param, value) ) in self . 0 . params ( ) . zip ( self . 1 . iter ( ) ) . enumerate ( ) {
51- let param = Param :: new ( i, param. clone ( ) , value) ;
62+ let i: u32 = i
63+ . try_into ( )
64+ . map_err ( |_| Error :: new ( arg_error ( ) , "too many params" ) ) ?;
65+ let param = Param :: new ( i, param. clone ( ) , * value) ;
5266 vals. push ( param. to_wasmtime_val ( ) ?) ;
5367 }
5468
5569 Ok ( vals)
5670 }
5771}
72+
73+ /// A [`wasmtime::ValType`] that is [`Copy`], so it can be stays on the stack
74+ ///
75+ /// Note: this can be removed in Wasmtime 8.0 (see https://github.com/bytecodealliance/wasmtime/pull/6138)
76+ #[ derive( Debug , Clone , Copy ) ]
77+ pub enum ValTypeCopy {
78+ I32 ,
79+ I64 ,
80+ F32 ,
81+ F64 ,
82+ V128 ,
83+ FuncRef ,
84+ ExternRef ,
85+ }
86+
87+ impl From < ValType > for ValTypeCopy {
88+ fn from ( ty : ValType ) -> Self {
89+ match ty {
90+ ValType :: I32 => Self :: I32 ,
91+ ValType :: I64 => Self :: I64 ,
92+ ValType :: F32 => Self :: F32 ,
93+ ValType :: F64 => Self :: F64 ,
94+ ValType :: V128 => Self :: V128 ,
95+ ValType :: FuncRef => Self :: FuncRef ,
96+ ValType :: ExternRef => Self :: ExternRef ,
97+ }
98+ }
99+ }
100+
101+ impl From < ValTypeCopy > for ValType {
102+ fn from ( ty : ValTypeCopy ) -> Self {
103+ match ty {
104+ ValTypeCopy :: I32 => Self :: I32 ,
105+ ValTypeCopy :: I64 => Self :: I64 ,
106+ ValTypeCopy :: F32 => Self :: F32 ,
107+ ValTypeCopy :: F64 => Self :: F64 ,
108+ ValTypeCopy :: V128 => Self :: V128 ,
109+ ValTypeCopy :: FuncRef => Self :: FuncRef ,
110+ ValTypeCopy :: ExternRef => Self :: ExternRef ,
111+ }
112+ }
113+ }
0 commit comments