A few small performance improvements

When 'debug_assertions' is not enabled, don't bother doing asserts in
stack_guard / stack_err_guard.  Also, add an optional feature not enabled by
default to disable LUA_USE_APICHECK in release mode.  Once the bugs in rlua that
allow you to trigger LUA_USE_APICHECK are fixed, this feature will be the
default behavior.
This commit is contained in:
kyren 2018-02-09 01:20:44 -05:00
parent de4d21f8ea
commit 84b009da03
3 changed files with 63 additions and 46 deletions

View File

@ -22,6 +22,12 @@ default = ["builtin-lua"]
# * LUA_NUMBER as double # * LUA_NUMBER as double
# * LUA_EXTRASPACE is sizeof(void*) # * LUA_EXTRASPACE is sizeof(void*)
builtin-lua = ["gcc"] builtin-lua = ["gcc"]
# Don't define LUA_USE_APICHECK if we are in release mode. When
# debug_assertions are enabled, LUA_USE_APICHECK is enabled regardless. There
# are still a few known ways to trigger LUA_USE_APICHECK checks with rlua, but
# when these bugs are fixed, this option will go away and this behavior will be
# the default.
disable-lua-apicheck = []
[dependencies] [dependencies]
libc = { version = "0.2" } libc = { version = "0.2" }

View File

@ -21,10 +21,9 @@ fn main() {
config.define("LUA_USE_WINDOWS", None); config.define("LUA_USE_WINDOWS", None);
} }
// Enables lua api checking, which has a slight performance penalty. We if cfg!(debug_assertions) || !cfg!(feature = "disable-lua-apicheck") {
// could allow disabling this via cfg one day when there is much more config.define("LUA_USE_APICHECK", None);
// confidence in the soundness of the API. }
config.define("LUA_USE_APICHECK", None);
config config
.include("lua") .include("lua")

View File

@ -24,25 +24,29 @@ pub unsafe fn stack_guard<F, R>(state: *mut ffi::lua_State, change: c_int, op: F
where where
F: FnOnce() -> R, F: FnOnce() -> R,
{ {
let expected = ffi::lua_gettop(state) + change; if cfg!(debug_assertions) {
lua_internal_assert!( let expected = ffi::lua_gettop(state) + change;
state, lua_internal_assert!(
expected >= 0, state,
"too many stack values would be popped" expected >= 0,
); "too many stack values would be popped"
);
let res = op(); let res = op();
let top = ffi::lua_gettop(state); let top = ffi::lua_gettop(state);
lua_internal_assert!( lua_internal_assert!(
state, state,
ffi::lua_gettop(state) == expected, ffi::lua_gettop(state) == expected,
"expected stack to be {}, got {}", "expected stack to be {}, got {}",
expected, expected,
top top
); );
res res
} else {
op()
}
} }
// Run an operation on a lua_State and automatically clean up the stack before // Run an operation on a lua_State and automatically clean up the stack before
@ -58,37 +62,45 @@ pub unsafe fn stack_err_guard<F, R>(state: *mut ffi::lua_State, change: c_int, o
where where
F: FnOnce() -> Result<R>, F: FnOnce() -> Result<R>,
{ {
let expected = ffi::lua_gettop(state) + change; if cfg!(debug_assertions) {
lua_internal_assert!( let expected = ffi::lua_gettop(state) + change;
state,
expected >= 0,
"too many stack values would be popped"
);
let res = op();
let top = ffi::lua_gettop(state);
if res.is_ok() {
lua_internal_assert!( lua_internal_assert!(
state, state,
ffi::lua_gettop(state) == expected, expected >= 0,
"expected stack to be {}, got {}", "too many stack values would be popped"
expected,
top
); );
} else {
lua_internal_assert!( let res = op();
state,
top >= expected, let top = ffi::lua_gettop(state);
"{} too many stack values popped", if res.is_ok() {
top - expected lua_internal_assert!(
); state,
if top > expected { ffi::lua_gettop(state) == expected,
ffi::lua_settop(state, expected); "expected stack to be {}, got {}",
expected,
top
);
} else {
lua_internal_assert!(
state,
top >= expected,
"{} too many stack values popped",
top - expected
);
if top > expected {
ffi::lua_settop(state, expected);
}
} }
res
} else {
let prev = ffi::lua_gettop(state) + change;
let res = op();
if res.is_err() {
ffi::lua_settop(state, prev);
}
res
} }
res
} }
// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way. // Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.