Skip to content

Commit b3a54ac

Browse files
author
Your Name
committed
reuse same preallocatedfailure in both callback_error_ext and callback_error_ext_yieldable
1 parent 85416fd commit b3a54ac

File tree

3 files changed

+66
-123
lines changed

3 files changed

+66
-123
lines changed

src/state/raw.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ impl RawLua {
11641164
pub(crate) fn create_callback(&self, func: Callback) -> Result<Function> {
11651165
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
11661166
let upvalue = get_userdata::<CallbackUpvalue>(state, ffi::lua_upvalueindex(1));
1167-
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, _state, nargs| {
1167+
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, nargs| {
11681168
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
11691169
// The lock must be already held as the callback is executed
11701170
let rawlua = (*extra).raw_lua();
@@ -1205,7 +1205,7 @@ impl RawLua {
12051205
) -> Result<Function> {
12061206
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
12071207
let upvalue = get_userdata::<LuauContinuationUpvalue>(state, ffi::lua_upvalueindex(1));
1208-
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, _state, nargs| {
1208+
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, nargs| {
12091209
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
12101210
// The lock must be already held as the callback is executed
12111211
let rawlua = (*extra).raw_lua();
@@ -1218,7 +1218,7 @@ impl RawLua {
12181218

12191219
unsafe extern "C-unwind" fn cont_callback(state: *mut ffi::lua_State, status: c_int) -> c_int {
12201220
let upvalue = get_userdata::<LuauContinuationUpvalue>(state, ffi::lua_upvalueindex(1));
1221-
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, _state, nargs| {
1221+
callback_error_ext_yieldable(state, (*upvalue).extra.get(), true, |extra, nargs| {
12221222
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
12231223
// The lock must be already held as the callback is executed
12241224
let rawlua = (*extra).raw_lua();

src/state/util.rs

Lines changed: 61 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,65 @@ impl Drop for StateGuard<'_> {
2424
}
2525
}
2626

27+
pub(crate) enum PreallocatedFailure {
28+
New(*mut WrappedFailure),
29+
Reserved,
30+
}
31+
32+
impl PreallocatedFailure {
33+
unsafe fn reserve(state: *mut ffi::lua_State, extra: *mut ExtraData) -> Self {
34+
if (*extra).wrapped_failure_top > 0 {
35+
(*extra).wrapped_failure_top -= 1;
36+
return PreallocatedFailure::Reserved;
37+
}
38+
39+
// We need to check stack for Luau in case when callback is called from interrupt
40+
// See https://github.com/luau-lang/luau/issues/446 and mlua #142 and #153
41+
#[cfg(feature = "luau")]
42+
ffi::lua_rawcheckstack(state, 2);
43+
// Place it to the beginning of the stack
44+
let ud = WrappedFailure::new_userdata(state);
45+
ffi::lua_insert(state, 1);
46+
PreallocatedFailure::New(ud)
47+
}
48+
49+
#[cold]
50+
unsafe fn r#use(&self, state: *mut ffi::lua_State, extra: *mut ExtraData) -> *mut WrappedFailure {
51+
let ref_thread = (*extra).ref_thread;
52+
match *self {
53+
PreallocatedFailure::New(ud) => {
54+
ffi::lua_settop(state, 1);
55+
ud
56+
}
57+
PreallocatedFailure::Reserved => {
58+
let index = (*extra).wrapped_failure_pool.pop().unwrap();
59+
ffi::lua_settop(state, 0);
60+
#[cfg(feature = "luau")]
61+
ffi::lua_rawcheckstack(state, 2);
62+
ffi::lua_xpush(ref_thread, state, index);
63+
ffi::lua_pushnil(ref_thread);
64+
ffi::lua_replace(ref_thread, index);
65+
(*extra).ref_free.push(index);
66+
ffi::lua_touserdata(state, -1) as *mut WrappedFailure
67+
}
68+
}
69+
}
70+
71+
unsafe fn release(self, state: *mut ffi::lua_State, extra: *mut ExtraData) {
72+
let ref_thread = (*extra).ref_thread;
73+
match self {
74+
PreallocatedFailure::New(_) => {
75+
ffi::lua_rotate(state, 1, -1);
76+
ffi::lua_xmove(state, ref_thread, 1);
77+
let index = ref_stack_pop(extra);
78+
(*extra).wrapped_failure_pool.push(index);
79+
(*extra).wrapped_failure_top += 1;
80+
}
81+
PreallocatedFailure::Reserved => (*extra).wrapped_failure_top += 1,
82+
}
83+
}
84+
}
85+
2786
// An optimized version of `callback_error` that does not allocate `WrappedFailure` userdata
2887
// and instead reuses unused values from previous calls (or allocates new).
2988
pub(crate) unsafe fn callback_error_ext<F, R>(
@@ -41,65 +100,6 @@ where
41100

42101
let nargs = ffi::lua_gettop(state);
43102

44-
enum PreallocatedFailure {
45-
New(*mut WrappedFailure),
46-
Reserved,
47-
}
48-
49-
impl PreallocatedFailure {
50-
unsafe fn reserve(state: *mut ffi::lua_State, extra: *mut ExtraData) -> Self {
51-
if (*extra).wrapped_failure_top > 0 {
52-
(*extra).wrapped_failure_top -= 1;
53-
return PreallocatedFailure::Reserved;
54-
}
55-
56-
// We need to check stack for Luau in case when callback is called from interrupt
57-
// See https://github.com/luau-lang/luau/issues/446 and mlua #142 and #153
58-
#[cfg(feature = "luau")]
59-
ffi::lua_rawcheckstack(state, 2);
60-
// Place it to the beginning of the stack
61-
let ud = WrappedFailure::new_userdata(state);
62-
ffi::lua_insert(state, 1);
63-
PreallocatedFailure::New(ud)
64-
}
65-
66-
#[cold]
67-
unsafe fn r#use(&self, state: *mut ffi::lua_State, extra: *mut ExtraData) -> *mut WrappedFailure {
68-
let ref_thread = (*extra).ref_thread;
69-
match *self {
70-
PreallocatedFailure::New(ud) => {
71-
ffi::lua_settop(state, 1);
72-
ud
73-
}
74-
PreallocatedFailure::Reserved => {
75-
let index = (*extra).wrapped_failure_pool.pop().unwrap();
76-
ffi::lua_settop(state, 0);
77-
#[cfg(feature = "luau")]
78-
ffi::lua_rawcheckstack(state, 2);
79-
ffi::lua_xpush(ref_thread, state, index);
80-
ffi::lua_pushnil(ref_thread);
81-
ffi::lua_replace(ref_thread, index);
82-
(*extra).ref_free.push(index);
83-
ffi::lua_touserdata(state, -1) as *mut WrappedFailure
84-
}
85-
}
86-
}
87-
88-
unsafe fn release(self, state: *mut ffi::lua_State, extra: *mut ExtraData) {
89-
let ref_thread = (*extra).ref_thread;
90-
match self {
91-
PreallocatedFailure::New(_) => {
92-
ffi::lua_rotate(state, 1, -1);
93-
ffi::lua_xmove(state, ref_thread, 1);
94-
let index = ref_stack_pop(extra);
95-
(*extra).wrapped_failure_pool.push(index);
96-
(*extra).wrapped_failure_top += 1;
97-
}
98-
PreallocatedFailure::Reserved => (*extra).wrapped_failure_top += 1,
99-
}
100-
}
101-
}
102-
103103
// We cannot shadow Rust errors with Lua ones, so we need to reserve pre-allocated memory
104104
// to store a wrapped failure (error or panic) *before* we proceed.
105105
let prealloc_failure = PreallocatedFailure::reserve(state, extra);
@@ -167,81 +167,22 @@ pub(crate) unsafe fn callback_error_ext_yieldable<F>(
167167
f: F,
168168
) -> c_int
169169
where
170-
F: FnOnce(*mut ExtraData, *mut ffi::lua_State, c_int) -> Result<c_int>,
170+
F: FnOnce(*mut ExtraData, c_int) -> Result<c_int>,
171171
{
172172
if extra.is_null() {
173173
extra = ExtraData::get(state);
174174
}
175175

176176
let nargs = ffi::lua_gettop(state);
177177

178-
enum PreallocatedFailure {
179-
New(*mut WrappedFailure),
180-
Reserved,
181-
}
182-
183-
impl PreallocatedFailure {
184-
unsafe fn reserve(state: *mut ffi::lua_State, extra: *mut ExtraData) -> Self {
185-
if (*extra).wrapped_failure_top > 0 {
186-
(*extra).wrapped_failure_top -= 1;
187-
return PreallocatedFailure::Reserved;
188-
}
189-
190-
// We need to check stack for Luau in case when callback is called from interrupt
191-
// See https://github.com/luau-lang/luau/issues/446 and mlua #142 and #153
192-
#[cfg(feature = "luau")]
193-
ffi::lua_rawcheckstack(state, 2);
194-
// Place it to the beginning of the stack
195-
let ud = WrappedFailure::new_userdata(state);
196-
ffi::lua_insert(state, 1);
197-
PreallocatedFailure::New(ud)
198-
}
199-
200-
#[cold]
201-
unsafe fn r#use(&self, state: *mut ffi::lua_State, extra: *mut ExtraData) -> *mut WrappedFailure {
202-
let ref_thread = (*extra).ref_thread;
203-
match *self {
204-
PreallocatedFailure::New(ud) => {
205-
ffi::lua_settop(state, 1);
206-
ud
207-
}
208-
PreallocatedFailure::Reserved => {
209-
let index = (*extra).wrapped_failure_pool.pop().unwrap();
210-
ffi::lua_settop(state, 0);
211-
#[cfg(feature = "luau")]
212-
ffi::lua_rawcheckstack(state, 2);
213-
ffi::lua_xpush(ref_thread, state, index);
214-
ffi::lua_pushnil(ref_thread);
215-
ffi::lua_replace(ref_thread, index);
216-
(*extra).ref_free.push(index);
217-
ffi::lua_touserdata(state, -1) as *mut WrappedFailure
218-
}
219-
}
220-
}
221-
222-
unsafe fn release(self, state: *mut ffi::lua_State, extra: *mut ExtraData) {
223-
let ref_thread = (*extra).ref_thread;
224-
match self {
225-
PreallocatedFailure::New(_) => {
226-
ffi::lua_rotate(state, 1, -1);
227-
ffi::lua_xmove(state, ref_thread, 1);
228-
let index = ref_stack_pop(extra);
229-
(*extra).wrapped_failure_pool.push(index);
230-
(*extra).wrapped_failure_top += 1;
231-
}
232-
PreallocatedFailure::Reserved => (*extra).wrapped_failure_top += 1,
233-
}
234-
}
235-
}
236-
237178
// We cannot shadow Rust errors with Lua ones, so we need to reserve pre-allocated memory
238179
// to store a wrapped failure (error or panic) *before* we proceed.
239180
let prealloc_failure = PreallocatedFailure::reserve(state, extra);
240181

241182
match catch_unwind(AssertUnwindSafe(|| {
242183
let rawlua = (*extra).raw_lua();
243184
let _guard = StateGuard::new(rawlua, state);
244-
f(extra, state, nargs)
185+
f(extra, nargs)
245186
})) {
246187
Ok(Ok(r)) => {
247188
let raw = extra.as_ref().unwrap_unchecked().raw_lua();

tests/luau/cont.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,11 @@ fn test_luau_continuation() {
148148
let v = th
149149
.resume::<mlua::MultiValue>(v)
150150
.expect("Failed to load continuation");
151+
println!("v={:?}", v);
151152
let v = th
152153
.resume::<mlua::MultiValue>(v)
153154
.expect("Failed to load continuation");
155+
println!("v={:?}", v);
154156
let v = th
155157
.resume::<mlua::MultiValue>(v)
156158
.expect("Failed to load continuation");

0 commit comments

Comments
 (0)