Skip to content

Commit e9be788

Browse files
committed
Initialize Luau inliner flags before VM creation and compilation
1 parent dc06aac commit e9be788

5 files changed

Lines changed: 52 additions & 6 deletions

File tree

‎src/chunk.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ impl Compiler {
396396
///
397397
/// Returns [`Error::SyntaxError`] if the source code is invalid.
398398
pub fn compile(&self, source: impl AsRef<[u8]>) -> Result<Vec<u8>> {
399+
#[cfg(feature = "luau-jit")]
400+
crate::luau::init_jit_flags();
401+
399402
use std::cell::RefCell;
400403
use std::ffi::CStr;
401404
use std::os::raw::{c_char, c_int};

‎src/luau/mod.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ use crate::types::MaybeSend;
1919
pub use heap_dump::HeapDump;
2020
pub use require::{FsRequirer, NavigateError, Require};
2121

22+
#[cfg(feature = "luau-jit")]
23+
pub(crate) fn init_jit_flags() {
24+
static INIT: std::sync::Once = std::sync::Once::new();
25+
INIT.call_once(|| {
26+
// These process-global flags must be set before any VM or compiler uses them.
27+
let _ = Lua::set_fflag("LuauCallFeedback", true);
28+
let _ = Lua::set_fflag("LuauEmitCallFeedback", true);
29+
let _ = Lua::set_fflag("LuauCIProto", true);
30+
let _ = Lua::set_fflag("LuauPromoteProto", true);
31+
let _ = Lua::set_fflag("LuauVirtualBcBuilder", true);
32+
});
33+
}
34+
2235
// Since Luau has some missing standard functions, we re-implement them here
2336

2437
impl Lua {

‎src/state.rs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl JitOptions {
288288

289289
/// Toggles the runtime bytecode inliner.
290290
///
291-
/// Disabled by default. Changing this option does not affect already loaded functions.
291+
/// Disabled by default. Enable before compiling and executing code.
292292
#[must_use]
293293
pub const fn inliner(mut self, enabled: bool) -> Self {
294294
self.inliner = enabled;
@@ -1325,8 +1325,6 @@ impl Lua {
13251325
unsafe {
13261326
let state = lua.main_state();
13271327
if options.inliner {
1328-
let _ = Self::set_fflag("LuauCallFeedback", true);
1329-
let _ = Self::set_fflag("LuauEmitCallFeedback", true);
13301328
ffi::luau_enable_jit_inliner(state);
13311329
} else {
13321330
ffi::luau_disable_jit_inliner(state);
@@ -1336,11 +1334,16 @@ impl Lua {
13361334

13371335
/// Sets Luau feature flag (global setting).
13381336
///
1337+
/// Flags must be configured before creating any Lua VMs or compiling any Luau code.
1338+
/// This function must not run concurrently with any other Luau operation, including itself.
1339+
/// Changing flags later can cause data races or invalidate compiled bytecode.
1340+
///
13391341
/// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
13401342
#[cfg(feature = "luau")]
13411343
#[doc(hidden)]
13421344
#[allow(clippy::result_unit_err)]
13431345
pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1346+
// TODO: Make this function unsafe in the next breaking release.
13441347
if let Ok(name) = std::ffi::CString::new(name)
13451348
&& unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 }
13461349
{

‎src/state/raw.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ impl RawLua {
130130
}
131131

132132
pub(super) unsafe fn new(libs: StdLib, options: &LuaOptions) -> XRc<ReentrantMutex<Self>> {
133+
#[cfg(feature = "luau-jit")]
134+
crate::luau::init_jit_flags();
135+
133136
let mem_state: *mut MemoryState = Box::into_raw(Box::default());
134137
#[cfg(feature = "lua55")]
135138
let mut state = {

‎tests/luau.rs‎

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,19 +390,31 @@ fn test_fflags() {
390390
#[cfg(feature = "luau-jit")]
391391
#[test]
392392
fn test_jit_inliner() -> Result<()> {
393+
let compiler = Compiler::new();
394+
let bytecode = compiler.compile("return 42")?;
395+
393396
let lua = Lua::new();
397+
lua.enable_jit(false);
398+
lua.sandbox(true)?;
394399
lua.set_jit_options(mlua::state::JitOptions::new().inliner(true));
395400

401+
// Enabling the inliner must not change global compiler flags.
402+
assert_eq!(compiler.compile("return 42")?, bytecode);
403+
396404
// An inlinable helper called in a hot loop.
397405
let sum = lua
398406
.load(
399407
r#"
400408
local function add(a, b)
401-
return a + b
409+
return a + b + 0.5
410+
end
411+
local function caller(a, b)
412+
local sum = add(a, b)
413+
return sum - 0.5
402414
end
403415
local sum = 0
404416
for i = 1, 1000 do
405-
sum = add(sum, i)
417+
sum = caller(sum, i)
406418
end
407419
return sum
408420
"#,
@@ -508,11 +520,23 @@ fn test_heap_dump() -> Result<()> {
508520
Ok(())
509521
}
510522

523+
#[cfg(not(target_arch = "wasm32"))]
511524
#[test]
512525
fn test_integer64_type() -> Result<()> {
513-
let lua = Lua::new();
526+
// Isolate process-global flag changes from other tests' VMs and compilers.
527+
if std::env::var_os("MLUA_TEST_INTEGER64_TYPE").is_none() {
528+
assert!(
529+
std::process::Command::new(std::env::current_exe()?)
530+
.args(["--exact", "test_integer64_type"])
531+
.env("MLUA_TEST_INTEGER64_TYPE", "1")
532+
.status()?
533+
.success()
534+
);
535+
return Ok(());
536+
}
514537

515538
_ = Lua::set_fflag("LuauIntegerType2", true);
539+
let lua = Lua::new();
516540

517541
let integer_lib = lua.globals().get::<Table>("integer")?;
518542
let n = integer_lib.call_function::<i64>("create", 42)?;

0 commit comments

Comments
 (0)