Coverage Report

Created: 2025-11-20 14:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/src/execution/resumable.rs
Line
Count
Source
1
use core::num::NonZeroU32;
2
3
use alloc::{
4
    sync::{Arc, Weak},
5
    vec::Vec,
6
};
7
8
use crate::{
9
    addrs::FuncAddr,
10
    core::slotmap::{SlotMap, SlotMapKey},
11
    rw_spinlock::RwSpinLock,
12
    value_stack::Stack,
13
    Value,
14
};
15
16
#[derive(Debug)]
17
pub(crate) struct Resumable {
18
    pub(crate) stack: Stack,
19
    pub(crate) pc: usize,
20
    pub(crate) stp: usize,
21
    pub(crate) current_func_addr: FuncAddr,
22
    pub(crate) maybe_fuel: Option<u32>,
23
}
24
25
#[derive(Default)]
26
pub(crate) struct Dormitory(pub(crate) Arc<RwSpinLock<SlotMap<Resumable>>>);
27
28
impl Dormitory {
29
    #[allow(unused)]
30
1
    pub(crate) fn new() -> Self {
31
1
        Self::default()
32
1
    }
33
34
8
    pub(crate) fn insert(&self, resumable: Resumable) -> InvokedResumableRef {
35
8
        let key = self.0.write().insert(resumable);
36
8
37
8
        InvokedResumableRef {
38
8
            dormitory: Arc::downgrade(&self.0),
39
8
            key,
40
8
        }
41
8
    }
42
}
43
44
pub struct InvokedResumableRef {
45
    pub(crate) dormitory: Weak<RwSpinLock<SlotMap<Resumable>>>,
46
    pub(crate) key: SlotMapKey<Resumable>,
47
}
48
49
pub struct FreshResumableRef {
50
    pub(crate) func_addr: FuncAddr,
51
    pub(crate) params: Vec<Value>,
52
    pub(crate) maybe_fuel: Option<u32>,
53
}
54
55
/// An object associated to a resumable that is held internally.
56
pub enum ResumableRef {
57
    /// indicates this resumable has never been invoked/resumed to.
58
    Fresh(FreshResumableRef),
59
    /// indicates this resumable has been invoked/resumed to at least once.
60
    Invoked(InvokedResumableRef),
61
}
62
63
impl Drop for InvokedResumableRef {
64
8
    fn drop(&mut self) {
65
8
        let Some(
dormitory7
) = self.dormitory.upgrade() else {
66
            // Either the dormitory was already dropped or `self` was used to finish execution.
67
1
            return;
68
        };
69
70
7
        dormitory.write().remove(&self.key)
71
7
            .expect("that the resumable could not have been removed already, because then this self could not exist or the dormitory weak pointer would have been None");
72
8
    }
73
}
74
75
/// Represents the state of a possibly interrupted resumable.
76
pub enum RunState {
77
    /// represents a resumable that has executed completely with return values `values` and possibly remaining fuel
78
    /// `maybe_remaining_fuel` (has `Some(remaining_fuel)` for fuel-metered operations and `None` otherwise)
79
    Finished {
80
        values: Vec<Value>,
81
        maybe_remaining_fuel: Option<u32>,
82
    },
83
    /// represents a resumable that has ran out of fuel during execution, missing at least `required_fuel` units of fuel
84
    /// to continue further execution.
85
    Resumable {
86
        resumable_ref: ResumableRef,
87
        required_fuel: NonZeroU32,
88
    },
89
}
90
91
#[cfg(test)]
92
mod test {
93
    use crate::{addrs::FuncAddr, value_stack::Stack};
94
95
    use super::{Dormitory, Resumable};
96
97
    /// Test that a dormitory can be constructed and that a resumable can be inserted
98
    #[test]
99
1
    fn dormitory_constructor() {
100
1
        let dorm = Dormitory::new();
101
1
102
1
        let resumable = Resumable {
103
1
            stack: Stack::new(),
104
1
            pc: 11,
105
1
            stp: 13,
106
1
            current_func_addr: FuncAddr::INVALID,
107
1
            maybe_fuel: None,
108
1
        };
109
1
110
1
        dorm.insert(resumable);
111
1
    }
112
}