revm_context_interface/
local.rs1use core::{
3 cell::{Ref, RefCell},
4 ops::Range,
5};
6use std::{rc::Rc, string::String, vec::Vec};
7
8#[derive(Debug, Clone)]
10pub struct FrameStack<T> {
11 stack: Vec<T>,
12 index: Option<usize>,
13}
14
15impl<T> Default for FrameStack<T> {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl<T: Default> FrameStack<T> {
22 pub fn new_prealloc(len: usize) -> Self {
25 let mut stack = Vec::with_capacity(len);
26 for _ in 0..len {
27 stack.push(T::default());
28 }
29 Self { stack, index: None }
30 }
31}
32
33impl<T> FrameStack<T> {
34 pub fn new() -> Self {
36 Self {
38 stack: Vec::with_capacity(8),
39 index: None,
40 }
41 }
42
43 #[inline]
45 pub fn start_init(&mut self) -> OutFrame<'_, T> {
46 self.index = None;
47 if self.stack.is_empty() {
48 self.stack.reserve(8);
49 }
50 self.out_frame_at(0)
51 }
52
53 #[inline]
59 pub unsafe fn end_init(&mut self, token: FrameToken) {
60 token.assert();
61 if self.stack.is_empty() {
62 unsafe { self.stack.set_len(1) };
63 }
64 self.index = Some(0);
65 }
66
67 #[inline]
69 pub fn index(&self) -> Option<usize> {
70 self.index
71 }
72
73 #[inline]
80 pub unsafe fn push(&mut self, token: FrameToken) {
81 token.assert();
82 let index = self.index.as_mut().unwrap();
83 *index += 1;
84 debug_assert!(
86 *index < self.stack.capacity(),
87 "Stack capacity is not enough for index"
88 );
89 if *index == self.stack.len() {
91 unsafe { self.stack.set_len(self.stack.len() + 1) };
92 }
93 }
94
95 #[inline]
98 pub fn clear(&mut self) {
99 self.index = None;
100 }
101
102 #[inline]
104 pub fn pop(&mut self) {
105 self.index = self.index.unwrap_or(0).checked_sub(1);
106 }
107
108 #[inline]
110 pub fn get(&mut self) -> &mut T {
111 debug_assert!(
112 self.stack.capacity() > self.index.unwrap(),
113 "Stack capacity is not enough for index"
114 );
115 unsafe { &mut *self.stack.as_mut_ptr().add(self.index.unwrap()) }
116 }
117
118 #[inline]
120 pub fn get_next(&mut self) -> OutFrame<'_, T> {
121 if self.index.unwrap() + 1 == self.stack.capacity() {
122 self.stack.reserve(8);
124 }
125 self.out_frame_at(self.index.unwrap() + 1)
126 }
127
128 fn out_frame_at(&mut self, idx: usize) -> OutFrame<'_, T> {
129 unsafe {
130 OutFrame::new_maybe_uninit(self.stack.as_mut_ptr().add(idx), idx < self.stack.len())
131 }
132 }
133}
134
135#[allow(missing_debug_implementations)]
137pub struct OutFrame<'a, T> {
138 ptr: *mut T,
139 init: bool,
140 lt: core::marker::PhantomData<&'a mut T>,
141}
142
143impl<'a, T> OutFrame<'a, T> {
144 pub fn new_init(slot: &'a mut T) -> Self {
146 unsafe { Self::new_maybe_uninit(slot, true) }
147 }
148
149 pub fn new_uninit(slot: &'a mut core::mem::MaybeUninit<T>) -> Self {
151 unsafe { Self::new_maybe_uninit(slot.as_mut_ptr(), false) }
152 }
153
154 pub unsafe fn new_maybe_uninit(ptr: *mut T, init: bool) -> Self {
162 Self {
163 ptr,
164 init,
165 lt: Default::default(),
166 }
167 }
168
169 pub fn get(&mut self, f: impl FnOnce() -> T) -> &mut T {
171 if !self.init {
172 self.do_init(f);
173 }
174 unsafe { &mut *self.ptr }
175 }
176
177 #[inline(never)]
178 #[cold]
179 fn do_init(&mut self, f: impl FnOnce() -> T) {
180 unsafe {
181 self.init = true;
182 self.ptr.write(f());
183 }
184 }
185
186 pub unsafe fn get_unchecked(&mut self) -> &mut T {
192 debug_assert!(self.init, "OutFrame must be initialized before use");
193 unsafe { &mut *self.ptr }
194 }
195
196 pub fn consume(self) -> FrameToken {
198 FrameToken(self.init)
199 }
200}
201
202#[allow(missing_debug_implementations)]
204pub struct FrameToken(bool);
205
206impl FrameToken {
207 #[cfg_attr(debug_assertions, track_caller)]
209 pub fn assert(self) {
210 assert!(self.0, "FrameToken must be initialized before use");
211 }
212}
213
214pub trait LocalContextTr {
216 fn shared_memory_buffer(&self) -> &Rc<RefCell<Vec<u8>>>;
218
219 fn shared_memory_buffer_slice(&self, range: Range<usize>) -> Option<Ref<'_, [u8]>> {
221 let buffer = self.shared_memory_buffer();
222 buffer.borrow().get(range.clone())?;
223 Some(Ref::map(buffer.borrow(), |b| {
224 b.get(range).unwrap_or_default()
225 }))
226 }
227
228 fn clear(&mut self);
230
231 fn set_precompile_error_context(&mut self, _output: String);
236
237 fn take_precompile_error_context(&mut self) -> Option<String>;
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246
247 #[test]
248 fn frame_stack() {
249 let mut stack = FrameStack::new_prealloc(1);
250 let mut frame = stack.start_init();
251 *frame.get(|| 2) += 1;
253
254 let token = frame.consume();
255 unsafe { stack.end_init(token) };
256
257 assert_eq!(stack.index(), Some(0));
258 assert_eq!(stack.stack.len(), 1);
259
260 let a = stack.get();
261 assert_eq!(a, &mut 1);
262 let mut b = stack.get_next();
263 assert!(!b.init);
264 assert_eq!(b.get(|| 2), &mut 2);
265 let token = b.consume(); unsafe { stack.push(token) };
267
268 assert_eq!(stack.index(), Some(1));
269 assert_eq!(stack.stack.len(), 2);
270 let a = stack.get();
271 assert_eq!(a, &mut 2);
272 let b = stack.get_next();
273 assert!(!b.init);
274
275 stack.pop();
276
277 assert_eq!(stack.index(), Some(0));
278 assert_eq!(stack.stack.len(), 2);
279 let a = stack.get();
280 assert_eq!(a, &mut 1);
281 let mut b = stack.get_next();
282 assert!(b.init);
283 assert_eq!(unsafe { b.get_unchecked() }, &mut 2);
284 }
285}