substrate_wasmtime_runtime/
table.rs1use crate::vmcontext::{VMCallerCheckedAnyfunc, VMTableDefinition};
6use crate::Trap;
7use std::cell::RefCell;
8use std::convert::{TryFrom, TryInto};
9use wasmtime_environ::wasm::TableElementType;
10use wasmtime_environ::{ir, TablePlan, TableStyle};
11
12#[derive(Debug)]
14pub struct Table {
15 vec: RefCell<Vec<VMCallerCheckedAnyfunc>>,
16 maximum: Option<u32>,
17}
18
19impl Table {
20 pub fn new(plan: &TablePlan) -> Self {
22 match plan.table.ty {
23 TableElementType::Func => (),
24 TableElementType::Val(ty) => {
25 unimplemented!("tables of types other than anyfunc ({})", ty)
26 }
27 };
28 match plan.style {
29 TableStyle::CallerChecksSignature => Self {
30 vec: RefCell::new(vec![
31 VMCallerCheckedAnyfunc::default();
32 usize::try_from(plan.table.minimum).unwrap()
33 ]),
34 maximum: plan.table.maximum,
35 },
36 }
37 }
38
39 pub fn size(&self) -> u32 {
41 self.vec.borrow().len().try_into().unwrap()
42 }
43
44 pub fn grow(&self, delta: u32) -> Option<u32> {
50 let size = self.size();
51 let new_len = match size.checked_add(delta) {
52 Some(len) => {
53 if let Some(max) = self.maximum {
54 if len > max {
55 return None;
56 }
57 }
58 len
59 }
60 None => {
61 return None;
62 }
63 };
64 self.vec.borrow_mut().resize(
65 usize::try_from(new_len).unwrap(),
66 VMCallerCheckedAnyfunc::default(),
67 );
68 Some(size)
69 }
70
71 pub fn get(&self, index: u32) -> Option<VMCallerCheckedAnyfunc> {
75 self.vec.borrow().get(index as usize).cloned()
76 }
77
78 pub fn set(&self, index: u32, func: VMCallerCheckedAnyfunc) -> Result<(), ()> {
84 match self.vec.borrow_mut().get_mut(index as usize) {
85 Some(slot) => {
86 *slot = func;
87 Ok(())
88 }
89 None => Err(()),
90 }
91 }
92
93 pub fn copy(
100 dst_table: &Self,
101 src_table: &Self,
102 dst_index: u32,
103 src_index: u32,
104 len: u32,
105 ) -> Result<(), Trap> {
106 if src_index
109 .checked_add(len)
110 .map_or(true, |n| n > src_table.size())
111 || dst_index
112 .checked_add(len)
113 .map_or(true, |m| m > dst_table.size())
114 {
115 return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds));
116 }
117
118 let srcs = src_index..src_index + len;
119 let dsts = dst_index..dst_index + len;
120
121 if dst_index <= src_index {
126 for (s, d) in (srcs).zip(dsts) {
127 dst_table.set(d, src_table.get(s).unwrap()).unwrap();
128 }
129 } else {
130 for (s, d) in srcs.rev().zip(dsts.rev()) {
131 dst_table.set(d, src_table.get(s).unwrap()).unwrap();
132 }
133 }
134
135 Ok(())
136 }
137
138 pub fn vmtable(&self) -> VMTableDefinition {
140 let mut vec = self.vec.borrow_mut();
141 VMTableDefinition {
142 base: vec.as_mut_ptr() as *mut u8,
143 current_elements: vec.len().try_into().unwrap(),
144 }
145 }
146}