low_luajit/lua/jit.rs
1use core::ops::BitOr;
2use crate::{LuaState, ffi};
3
4/// Mode flags used to toggle/flush JIT compilation.
5///
6/// This enum is used by the following functions:
7/// - [`LuaState::jit_set_mode`].
8/// - [`LuaState::jit_set_engine`].
9/// - [`LuaState::jit_set_function`].
10///
11/// Functions using `JITMode` directly usually allow passing `true`/`false` as an alternative to [`JITMode::On`]/[`JITMode::Off`].
12#[repr(i32)]
13#[derive(Debug, PartialEq, Eq)]
14pub enum JITMode {
15 Off = ffi::LUAJIT_MODE_OFF,
16 On = ffi::LUAJIT_MODE_ON,
17 Flush = ffi::LUAJIT_MODE_FLUSH,
18}
19
20impl From<bool> for JITMode {
21 /// Converts `true` into [`JITMode::On`] and `false` into [`JITMode::Off`].
22 #[inline]
23 fn from(value: bool) -> Self {
24 if value { Self::On } else { Self::Off }
25 }
26}
27
28impl BitOr<JITMode> for i32 {
29 type Output = i32;
30
31 #[inline]
32 fn bitor(self, rhs: JITMode) -> Self::Output {
33 rhs as i32 | self
34 }
35}
36
37/// JIT compiler engine handling functions.
38impl LuaState {
39 /// Generic JIT compiler engine mode controller function.
40 ///
41 /// `mode` should be a `LUAJIT_MODE_*` constant (see the [`ffi`] module) or'd with a [`JITMode`] flag.
42 ///
43 /// Returns `true` on success, `false` otherwise.
44 ///
45 /// # Panics
46 ///
47 /// Panics if `mode` uses `LUAJIT_MODE_FUNC`, `LUAJIT_MODE_ALLFUNC`, or `LUAJIT_MODE_ALLSUBFUNC` and `index` is out of bounds.
48 ///
49 /// Additionally, this function will always panic if `mode` uses `LUAJIT_MODE_WRAPCFUNC`.
50 // Use `LuaState::wrap_cfunctions` instead. (TODO)
51 #[inline]
52 pub fn jit_set_mode(&self, index: i32, mode: i32) -> bool {
53 let masked_mode = mode & ffi::LUAJIT_MODE_MASK;
54 assert!(masked_mode != ffi::LUAJIT_MODE_WRAPCFUNC, "cannot set `LUAJIT_MODE_WRAPCFUNC` by calling `LuaState::jit_set_mode`");
55 assert!(
56 (masked_mode != ffi::LUAJIT_MODE_FUNC && masked_mode != ffi::LUAJIT_MODE_ALLFUNC && masked_mode != ffi::LUAJIT_MODE_ALLSUBFUNC) ||
57 self.is_index_ok(index),
58 "cannot set the JIT compilation mode of the function at index {index}, as there are only {} elements", self.get_top()
59 );
60
61 // SAFETY: self.0 is always valid and mode is not LUAJIT_MODE_WRAPCFUNC.
62 unsafe { ffi::luaJIT_setmode(self.0, index, mode) != 0 }
63 }
64
65 /// Sets the entire JIT compiler on or off or flushes the cached compiled code.
66 ///
67 /// This function always returns `true` unless the version of LuaJIT being used was compiled without the JIT compiler.
68 #[inline]
69 pub fn jit_set_engine(&self, mode: impl Into<JITMode>) -> bool {
70 self.jit_set_mode(0, ffi::LUAJIT_MODE_ENGINE | mode.into())
71 }
72
73 /// Sets JIT compilation on or off, or flushes already compiled code, for the specified functions.
74 ///
75 /// If `to_self` is `true`, the function at the given `index` will be affected.
76 /// If `to_subs` is `true`, the *sub-functions* of the function at the given `index` will be affected.
77 ///
78 /// If `index` is `0`, the function that called the currently running [`CFunction`] will be used in the above cases.
79 ///
80 /// *(This function only applies to Lua functions, as [`CFunction`]s cannot be JIT compiled.)*
81 ///
82 /// This function will return `true` if at least one function was affected, `false` otherwise.
83 /// If the version of LuaJIT being used was compiled without the JIT compiler no function can be affected.
84 ///
85 /// # Panics
86 ///
87 /// Panics if `index` is out of bounds.
88 ///
89 /// [`CFunction`]: ./type.CFunction.html
90 #[inline]
91 pub fn jit_set_function(&self, index: i32, mode: impl Into<JITMode>, to_self: bool, to_subs: bool) -> bool {
92 self.jit_set_mode(index, match (to_self, to_subs) {
93 (true, false) => ffi::LUAJIT_MODE_FUNC,
94 (true, true) => ffi::LUAJIT_MODE_ALLFUNC,
95 (false, true) => ffi::LUAJIT_MODE_ALLSUBFUNC,
96 (false, false) => return false,
97 } | mode.into())
98 }
99
100 /// Flushes the given root `trace` and all of its side traces from the cache.
101 ///
102 /// The code for the trace will be retained as long as there are any other traces which link to it.
103 #[inline]
104 pub fn jit_flush_trace(&self, trace: u32) {
105 self.jit_set_mode(trace.cast_signed(), ffi::LUAJIT_MODE_TRACE | JITMode::Flush);
106 }
107}