Skip to content

Commit 91e069a

Browse files
committed
Optimize (and simplify) protected mode for Rust function calls
1 parent cacd3dc commit 91e069a

File tree

2 files changed

+27
-37
lines changed

2 files changed

+27
-37
lines changed

src/state/extra.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use super::{Lua, WeakLua};
2727
// Unique key to store `ExtraData` in the registry
2828
static EXTRA_REGISTRY_KEY: u8 = 0;
2929

30-
const WRAPPED_FAILURE_POOL_SIZE: usize = 64;
30+
const WRAPPED_FAILURE_POOL_DEFAULT_CAPACITY: usize = 64;
3131
const REF_STACK_RESERVE: c_int = 1;
3232

3333
/// Data associated with the Lua state.
@@ -60,6 +60,7 @@ pub(crate) struct ExtraData {
6060

6161
// Pool of `WrappedFailure` enums in the ref thread (as userdata)
6262
pub(super) wrapped_failure_pool: Vec<c_int>,
63+
pub(super) wrapped_failure_top: usize,
6364
// Pool of `Thread`s (coroutines) for async execution
6465
#[cfg(feature = "async")]
6566
pub(super) thread_pool: Vec<c_int>,
@@ -160,7 +161,8 @@ impl ExtraData {
160161
ref_stack_size: ffi::LUA_MINSTACK - REF_STACK_RESERVE,
161162
ref_stack_top: ffi::lua_gettop(ref_thread),
162163
ref_free: Vec::new(),
163-
wrapped_failure_pool: Vec::with_capacity(WRAPPED_FAILURE_POOL_SIZE),
164+
wrapped_failure_pool: Vec::with_capacity(WRAPPED_FAILURE_POOL_DEFAULT_CAPACITY),
165+
wrapped_failure_top: 0,
164166
#[cfg(feature = "async")]
165167
thread_pool: Vec::new(),
166168
wrapped_failure_mt_ptr,

src/state/util.rs

+23-35
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ use crate::error::{Error, Result};
77
use crate::state::{ExtraData, RawLua};
88
use crate::util::{self, get_internal_metatable, WrappedFailure};
99

10-
const WRAPPED_FAILURE_POOL_SIZE: usize = 64;
11-
1210
pub(super) struct StateGuard<'a>(&'a RawLua, *mut ffi::lua_State);
1311

1412
impl<'a> StateGuard<'a> {
@@ -42,39 +40,40 @@ where
4240

4341
enum PreallocatedFailure {
4442
New(*mut WrappedFailure),
45-
Existing(i32),
43+
Reserved,
4644
}
4745

4846
impl PreallocatedFailure {
4947
unsafe fn reserve(state: *mut ffi::lua_State, extra: *mut ExtraData) -> Self {
50-
match (*extra).wrapped_failure_pool.pop() {
51-
Some(index) => PreallocatedFailure::Existing(index),
52-
None => {
53-
// We need to check stack for Luau in case when callback is called from interrupt
54-
// See https://github.com/Roblox/luau/issues/446 and mlua #142 and #153
55-
#[cfg(feature = "luau")]
56-
ffi::lua_rawcheckstack(state, 2);
57-
// Place it to the beginning of the stack
58-
let ud = WrappedFailure::new_userdata(state);
59-
ffi::lua_insert(state, 1);
60-
PreallocatedFailure::New(ud)
61-
}
48+
if (*extra).wrapped_failure_top > 0 {
49+
(*extra).wrapped_failure_top -= 1;
50+
return PreallocatedFailure::Reserved;
6251
}
52+
53+
// We need to check stack for Luau in case when callback is called from interrupt
54+
// See https://github.com/Roblox/luau/issues/446 and mlua #142 and #153
55+
#[cfg(feature = "luau")]
56+
ffi::lua_rawcheckstack(state, 2);
57+
// Place it to the beginning of the stack
58+
let ud = WrappedFailure::new_userdata(state);
59+
ffi::lua_insert(state, 1);
60+
PreallocatedFailure::New(ud)
6361
}
6462

63+
#[cold]
6564
unsafe fn r#use(&self, state: *mut ffi::lua_State, extra: *mut ExtraData) -> *mut WrappedFailure {
6665
let ref_thread = (*extra).ref_thread;
6766
match *self {
6867
PreallocatedFailure::New(ud) => {
6968
ffi::lua_settop(state, 1);
7069
ud
7170
}
72-
PreallocatedFailure::Existing(index) => {
71+
PreallocatedFailure::Reserved => {
72+
let index = (*extra).wrapped_failure_pool.pop().unwrap();
7373
ffi::lua_settop(state, 0);
7474
#[cfg(feature = "luau")]
7575
ffi::lua_rawcheckstack(state, 2);
76-
ffi::lua_pushvalue(ref_thread, index);
77-
ffi::lua_xmove(ref_thread, state, 1);
76+
ffi::lua_xpush(ref_thread, state, index);
7877
ffi::lua_pushnil(ref_thread);
7978
ffi::lua_replace(ref_thread, index);
8079
(*extra).ref_free.push(index);
@@ -87,24 +86,13 @@ where
8786
let ref_thread = (*extra).ref_thread;
8887
match self {
8988
PreallocatedFailure::New(_) => {
90-
if (*extra).wrapped_failure_pool.len() < WRAPPED_FAILURE_POOL_SIZE {
91-
ffi::lua_rotate(state, 1, -1);
92-
ffi::lua_xmove(state, ref_thread, 1);
93-
let index = ref_stack_pop(extra);
94-
(*extra).wrapped_failure_pool.push(index);
95-
} else {
96-
ffi::lua_remove(state, 1);
97-
}
98-
}
99-
PreallocatedFailure::Existing(index) => {
100-
if (*extra).wrapped_failure_pool.len() < WRAPPED_FAILURE_POOL_SIZE {
101-
(*extra).wrapped_failure_pool.push(index);
102-
} else {
103-
ffi::lua_pushnil(ref_thread);
104-
ffi::lua_replace(ref_thread, index);
105-
(*extra).ref_free.push(index);
106-
}
89+
ffi::lua_rotate(state, 1, -1);
90+
ffi::lua_xmove(state, ref_thread, 1);
91+
let index = ref_stack_pop(extra);
92+
(*extra).wrapped_failure_pool.push(index);
93+
(*extra).wrapped_failure_top += 1;
10794
}
95+
PreallocatedFailure::Reserved => (*extra).wrapped_failure_top += 1,
10896
}
10997
}
11098
}

0 commit comments

Comments
 (0)