wasmtime_environ/
stack_map.rs

1use cranelift_bitset::CompoundBitSet;
2use serde_derive::{Deserialize, Serialize};
3
4/// A map for determining where live GC references live in a stack frame.
5///
6/// Note that this is currently primarily documented as cranelift's
7/// `binemit::StackMap`, so for detailed documentation about this please read
8/// the docs over there.
9#[derive(Debug, Serialize, Deserialize)]
10pub struct StackMap {
11    bits: CompoundBitSet,
12    frame_size: u32,
13}
14
15impl StackMap {
16    /// Creates a new `StackMap`, typically from a preexisting
17    /// `binemit::StackMap`.
18    pub fn new(frame_size: u32, bits: CompoundBitSet) -> StackMap {
19        StackMap { bits, frame_size }
20    }
21
22    /// Returns the byte size of this stack map's frame.
23    pub fn frame_size(&self) -> u32 {
24        self.frame_size
25    }
26
27    /// Given a frame pointer, get the stack pointer.
28    ///
29    /// # Safety
30    ///
31    /// The `fp` must be the frame pointer at the code offset that this stack
32    /// map is associated with.
33    pub unsafe fn sp(&self, fp: *mut usize) -> *mut usize {
34        let frame_size = usize::try_from(self.frame_size).unwrap();
35        fp.byte_sub(frame_size)
36    }
37
38    /// Given the stack pointer, get a reference to each live GC reference in
39    /// the stack frame.
40    ///
41    /// # Safety
42    ///
43    /// The `sp` must be the stack pointer at the code offset that this stack
44    /// map is associated with.
45    pub unsafe fn live_gc_refs(&self, sp: *mut usize) -> impl Iterator<Item = *mut u32> + '_ {
46        self.bits.iter().map(move |i| {
47            log::trace!("Live GC ref in frame at frame offset {:#x}", i);
48            let ptr_to_gc_ref = sp.byte_add(i);
49
50            // Assert that the pointer is inside this stack map's frame.
51            assert!({
52                let delta = ptr_to_gc_ref as usize - sp as usize;
53                let frame_size = usize::try_from(self.frame_size).unwrap();
54                delta < frame_size
55            });
56
57            ptr_to_gc_ref.cast::<u32>()
58        })
59    }
60}