Enable hooks support for LuaJIT
This commit is contained in:
parent
0a13a9631d
commit
efcaef3db7
13
src/hook.rs
13
src/hook.rs
|
@ -1,8 +1,3 @@
|
||||||
#![cfg_attr(
|
|
||||||
not(any(feature = "lua54", feature = "lua53", feature = "lua52", feature = "lua51")),
|
|
||||||
allow(dead_code)
|
|
||||||
)]
|
|
||||||
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::os::raw::{c_char, c_int};
|
use std::os::raw::{c_char, c_int};
|
||||||
|
@ -18,8 +13,6 @@ use crate::util::callback_error;
|
||||||
/// Lua code executing at the time that the hook function was called. Further information can be
|
/// Lua code executing at the time that the hook function was called. Further information can be
|
||||||
/// found in the [Lua 5.3 documentaton][lua_doc].
|
/// found in the [Lua 5.3 documentaton][lua_doc].
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua54/lua53/lua52/lua51"`
|
|
||||||
///
|
|
||||||
/// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#lua_Debug
|
/// [lua_doc]: https://www.lua.org/manual/5.3/manual.html#lua_Debug
|
||||||
/// [`Lua::set_hook`]: struct.Lua.html#method.set_hook
|
/// [`Lua::set_hook`]: struct.Lua.html#method.set_hook
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -93,9 +86,9 @@ impl<'a> Debug<'a> {
|
||||||
);
|
);
|
||||||
DebugStack {
|
DebugStack {
|
||||||
num_ups: (*self.ar).nups as i32,
|
num_ups: (*self.ar).nups as i32,
|
||||||
#[cfg(any(feature = "lua52", feature = "lua53", feature = "lua54"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
num_params: (*self.ar).nparams as i32,
|
num_params: (*self.ar).nparams as i32,
|
||||||
#[cfg(any(feature = "lua52", feature = "lua53", feature = "lua54"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
is_vararg: (*self.ar).isvararg != 0,
|
is_vararg: (*self.ar).isvararg != 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +122,6 @@ pub struct DebugStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines when a hook function will be called by Lua.
|
/// Determines when a hook function will be called by Lua.
|
||||||
///
|
|
||||||
/// Requires `feature = "lua54/lua53/lua52/lua51"`
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct HookTriggers {
|
pub struct HookTriggers {
|
||||||
/// Before a function call.
|
/// Before a function call.
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -80,6 +80,7 @@ pub use crate::ffi::lua_State;
|
||||||
|
|
||||||
pub use crate::error::{Error, ExternalError, ExternalResult, Result};
|
pub use crate::error::{Error, ExternalError, ExternalResult, Result};
|
||||||
pub use crate::function::Function;
|
pub use crate::function::Function;
|
||||||
|
pub use crate::hook::{Debug, DebugNames, DebugSource, DebugStack, HookTriggers};
|
||||||
pub use crate::lua::{Chunk, GCMode, Lua};
|
pub use crate::lua::{Chunk, GCMode, Lua};
|
||||||
pub use crate::multi::Variadic;
|
pub use crate::multi::Variadic;
|
||||||
pub use crate::scope::Scope;
|
pub use crate::scope::Scope;
|
||||||
|
@ -91,15 +92,6 @@ pub use crate::types::{Integer, LightUserData, Number, RegistryKey};
|
||||||
pub use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
pub use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
||||||
pub use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
pub use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "lua54",
|
|
||||||
feature = "lua53",
|
|
||||||
feature = "lua52",
|
|
||||||
feature = "lua51",
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub use crate::hook::{Debug, DebugNames, DebugSource, DebugStack, HookTriggers};
|
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
pub use crate::thread::AsyncThread;
|
pub use crate::thread::AsyncThread;
|
||||||
|
|
||||||
|
|
33
src/lua.rs
33
src/lua.rs
|
@ -10,6 +10,7 @@ use std::{mem, ptr, str};
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
use crate::function::Function;
|
use crate::function::Function;
|
||||||
|
use crate::hook::{hook_proc, Debug, HookTriggers};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use crate::stdlib::StdLib;
|
use crate::stdlib::StdLib;
|
||||||
use crate::string::String;
|
use crate::string::String;
|
||||||
|
@ -27,15 +28,6 @@ use crate::util::{
|
||||||
};
|
};
|
||||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||||
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "lua54",
|
|
||||||
feature = "lua53",
|
|
||||||
feature = "lua52",
|
|
||||||
feature = "lua51",
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
use crate::hook::{hook_proc, Debug, HookTriggers};
|
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
use {
|
use {
|
||||||
crate::types::AsyncCallback,
|
crate::types::AsyncCallback,
|
||||||
|
@ -430,16 +422,12 @@ impl Lua {
|
||||||
/// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
|
/// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
|
||||||
/// erroring once an instruction limit has been reached.
|
/// erroring once an instruction limit has been reached.
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua54/lua53/lua52/lua51"`
|
|
||||||
///
|
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// Shows each line number of code being executed by the Lua interpreter.
|
/// Shows each line number of code being executed by the Lua interpreter.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", feature = "lua51"))]
|
|
||||||
/// # use mlua::{Lua, HookTriggers, Result};
|
/// # use mlua::{Lua, HookTriggers, Result};
|
||||||
/// # #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", feature = "lua51"))]
|
|
||||||
/// # fn main() -> Result<()> {
|
/// # fn main() -> Result<()> {
|
||||||
/// let lua = Lua::new();
|
/// let lua = Lua::new();
|
||||||
/// lua.set_hook(HookTriggers {
|
/// lua.set_hook(HookTriggers {
|
||||||
|
@ -455,20 +443,10 @@ impl Lua {
|
||||||
/// local z = string.len(x..", "..y)
|
/// local z = string.len(x..", "..y)
|
||||||
/// "#).exec()
|
/// "#).exec()
|
||||||
/// # }
|
/// # }
|
||||||
///
|
|
||||||
/// # #[cfg(not(any(feature = "lua54", feature = "lua53", feature = "lua52", feature = "lua51")))]
|
|
||||||
/// # fn main() {}
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`HookTriggers`]: struct.HookTriggers.html
|
/// [`HookTriggers`]: struct.HookTriggers.html
|
||||||
/// [`HookTriggers.every_nth_instruction`]: struct.HookTriggers.html#field.every_nth_instruction
|
/// [`HookTriggers.every_nth_instruction`]: struct.HookTriggers.html#field.every_nth_instruction
|
||||||
#[cfg(any(
|
|
||||||
feature = "lua54",
|
|
||||||
feature = "lua53",
|
|
||||||
feature = "lua52",
|
|
||||||
feature = "lua51",
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
|
pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>,
|
F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>,
|
||||||
|
@ -484,15 +462,6 @@ impl Lua {
|
||||||
|
|
||||||
/// Remove any hook previously set by `set_hook`. This function has no effect if a hook was not
|
/// Remove any hook previously set by `set_hook`. This function has no effect if a hook was not
|
||||||
/// previously set.
|
/// previously set.
|
||||||
///
|
|
||||||
/// Requires `feature = "lua54/lua53/lua52/lua51"`
|
|
||||||
#[cfg(any(
|
|
||||||
feature = "lua54",
|
|
||||||
feature = "lua53",
|
|
||||||
feature = "lua52",
|
|
||||||
feature = "lua51",
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub fn remove_hook(&self) {
|
pub fn remove_hook(&self) {
|
||||||
// If main_state is not available, then sethook wasn't called.
|
// If main_state is not available, then sethook wasn't called.
|
||||||
let state = match self.main_state {
|
let state = match self.main_state {
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#![cfg(any(
|
#![cfg_attr(
|
||||||
feature = "lua54",
|
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||||
feature = "lua53",
|
feature(link_args)
|
||||||
feature = "lua52",
|
)]
|
||||||
feature = "lua51"
|
|
||||||
))]
|
#[cfg_attr(
|
||||||
|
all(feature = "luajit", target_os = "macos", target_arch = "x86_64"),
|
||||||
|
link_args = "-pagezero_size 10000 -image_base 100000000",
|
||||||
|
allow(unused_attributes)
|
||||||
|
)]
|
||||||
|
extern "system" {}
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -37,8 +42,14 @@ fn line_counts() -> Result<()> {
|
||||||
)
|
)
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
|
lua.remove_hook();
|
||||||
|
|
||||||
let output = output.lock().unwrap();
|
let output = output.lock().unwrap();
|
||||||
|
if cfg!(feature = "luajit") && lua.load("jit.version_num").eval::<i64>()? >= 20100 {
|
||||||
|
assert_eq!(*output, vec![2, 3, 4, 0, 4]);
|
||||||
|
} else {
|
||||||
assert_eq!(*output, vec![2, 3, 4]);
|
assert_eq!(*output, vec![2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -71,7 +82,18 @@ fn function_calls() -> Result<()> {
|
||||||
)
|
)
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
|
lua.remove_hook();
|
||||||
|
|
||||||
let output = output.lock().unwrap();
|
let output = output.lock().unwrap();
|
||||||
|
if cfg!(feature = "luajit") && lua.load("jit.version_num").eval::<i64>()? >= 20100 {
|
||||||
|
assert_eq!(
|
||||||
|
*output,
|
||||||
|
vec![
|
||||||
|
(None, Some("main".to_string())),
|
||||||
|
(Some("len".to_string()), Some("Lua".to_string()))
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*output,
|
*output,
|
||||||
vec![
|
vec![
|
||||||
|
@ -79,6 +101,7 @@ fn function_calls() -> Result<()> {
|
||||||
(Some("len".to_string()), Some("C".to_string()))
|
(Some("len".to_string()), Some("C".to_string()))
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -119,6 +142,10 @@ fn limit_execution_instructions() -> Result<()> {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
let mut max_instructions = 10000;
|
let mut max_instructions = 10000;
|
||||||
|
|
||||||
|
#[cfg(feature = "luajit")]
|
||||||
|
// For LuaJIT disable JIT, as compiled code does not trigger hooks
|
||||||
|
lua.load("jit.off()").exec()?;
|
||||||
|
|
||||||
lua.set_hook(
|
lua.set_hook(
|
||||||
HookTriggers {
|
HookTriggers {
|
||||||
every_nth_instruction: Some(30),
|
every_nth_instruction: Some(30),
|
||||||
|
|
Loading…
Reference in New Issue