Enable hooks support for LuaJIT

This commit is contained in:
Alex Orlenko 2020-06-07 19:10:46 +01:00
parent 0a13a9631d
commit efcaef3db7
4 changed files with 45 additions and 66 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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 {

View File

@ -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();
assert_eq!(*output, vec![2, 3, 4]); 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]);
}
Ok(()) Ok(())
} }
@ -71,14 +82,26 @@ fn function_calls() -> Result<()> {
) )
.exec()?; .exec()?;
lua.remove_hook();
let output = output.lock().unwrap(); let output = output.lock().unwrap();
assert_eq!( if cfg!(feature = "luajit") && lua.load("jit.version_num").eval::<i64>()? >= 20100 {
*output, assert_eq!(
vec![ *output,
(None, Some("main".to_string())), vec![
(Some("len".to_string()), Some("C".to_string())) (None, Some("main".to_string())),
] (Some("len".to_string()), Some("Lua".to_string()))
); ]
);
} else {
assert_eq!(
*output,
vec![
(None, Some("main".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),