fast_trap/
fast.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::{EntireHandler, FlowContext, TrapHandler};
use core::{mem::MaybeUninit, ptr::NonNull};

/// 快速路径函数。
pub type FastHandler = extern "C" fn(
    ctx: FastContext,
    a1: usize,
    a2: usize,
    a3: usize,
    a4: usize,
    a5: usize,
    a6: usize,
    a7: usize,
) -> FastResult;

/// 快速路径上下文。
///
/// 将陷入处理器上下文中在快速路径中可安全操作的部分暴露给快速路径函数。
#[repr(transparent)]
pub struct FastContext(&'static mut TrapHandler);

impl FastContext {
    /// 访问陷入上下文的 a0 寄存器。
    ///
    /// 由于 a0 寄存器在快速路径中用于传递上下文指针,
    /// 将陷入上下文的 a0 暂存到陷入处理器上下文中。
    #[inline]
    pub fn a0(&self) -> usize {
        self.0.scratch
    }

    /// 获取控制流上下文。
    #[inline]
    pub fn regs(&mut self) -> &mut FlowContext {
        unsafe { self.0.context.as_mut() }
    }

    /// 交换上下文指针。
    #[inline]
    pub fn swap_context(&mut self, new: NonNull<FlowContext>) -> NonNull<FlowContext> {
        core::mem::replace(&mut self.0.context, new)
    }

    /// 启动一个带有 `argc` 个参数的新上下文。
    #[inline]
    pub fn call(self, argc: usize) -> FastResult {
        unsafe { self.0.context.as_ref().load_others() };
        if argc <= 2 {
            FastResult::FastCall
        } else {
            FastResult::Call
        }
    }

    /// 从快速路径恢复。
    ///
    /// > **NOTICE** 必须先手工调用 `save_args`,或通过其他方式设置参数寄存器。
    #[inline]
    pub fn restore(self) -> FastResult {
        FastResult::Restore
    }

    /// 丢弃当前上下文,并直接切换到另一个上下文。
    #[inline]
    pub fn switch_to(self, others: NonNull<FlowContext>) -> FastResult {
        unsafe { others.as_ref().load_others() };
        self.0.context = others;
        FastResult::Switch
    }

    /// 向完整路径 `f` 传递对象 `t`。
    ///
    /// > **NOTICE** 必须先手工调用 `save_args`,或通过其他方式设置参数寄存器。
    #[inline]
    pub fn continue_with<T: 'static>(self, f: EntireHandler<T>, t: T) -> FastResult {
        // TODO 检查栈溢出
        unsafe { *self.0.locate_fast_mail() = MaybeUninit::new(t) };
        self.0.scratch = f as _;
        FastResult::Continue
    }
}

/// 快速路径处理结果。
#[repr(usize)]
pub enum FastResult {
    /// 调用新上下文,只需设置 2 个或更少参数。
    FastCall = 0,
    /// 调用新上下文,需要设置超过 2 个参数。
    Call = 1,
    /// 从快速路径直接返回。
    Restore = 2,
    /// 直接切换到另一个上下文。
    Switch = 3,
    /// 调用完整路径函数。
    Continue = 4,
}