pub struct GlobalState {Show 76 fields
pub parser_hook: Option<ParserHook>,
pub cli_argv: Option<Vec<Vec<u8>>>,
pub cli_preload: Option<fn(&mut LuaState) -> Result<(), LuaError>>,
pub lua_version: LuaVersion,
pub file_loader_hook: Option<FileLoaderHook>,
pub file_open_hook: Option<FileOpenHook>,
pub stdout_hook: Option<OutputHook>,
pub stderr_hook: Option<OutputHook>,
pub stdin_hook: Option<InputHook>,
pub env_hook: Option<EnvHook>,
pub unix_time_hook: Option<UnixTimeHook>,
pub cpu_clock_hook: Option<CpuClockHook>,
pub local_offset_hook: Option<LocalOffsetHook>,
pub entropy_hook: Option<EntropyHook>,
pub temp_name_hook: Option<TempNameHook>,
pub popen_hook: Option<PopenHook>,
pub file_remove_hook: Option<FileRemoveHook>,
pub file_rename_hook: Option<FileRenameHook>,
pub os_execute_hook: Option<OsExecuteHook>,
pub dynlib_load_hook: Option<DynLibLoadHook>,
pub dynlib_symbol_hook: Option<DynLibSymbolHook>,
pub dynlib_unload_hook: Option<DynLibUnloadHook>,
pub totalbytes: isize,
pub sandbox: SandboxLimits,
pub gc_debt: isize,
pub gc_estimate: usize,
pub lastatomic: usize,
pub strt: StringPool,
pub l_registry: LuaValue,
pub external_roots: ExternalRootSet,
pub globals: LuaValue,
pub loaded: LuaValue,
pub nilvalue: LuaValue,
pub seed: u32,
pub currentwhite: u8,
pub gcstate: u8,
pub gckind: u8,
pub gcstopem: bool,
pub genminormul: u8,
pub genmajormul: u8,
pub gcstp: u8,
pub gcemergency: bool,
pub gcpause: u8,
pub gcstepmul: u8,
pub gcstepsize: u8,
pub gc55_params: [i64; 6],
pub sweepgc_cursor: usize,
pub weak_tables_registry: Vec<GcWeak<LuaTable>>,
pub pending_finalizers: Vec<FinalizerObject>,
pub to_be_finalized: Vec<FinalizerObject>,
pub gc_finalizer_error: Option<LuaValue>,
pub twups: Vec<GcRef<LuaState>>,
pub panic: Option<LuaCFunction>,
pub mainthread: Option<GcRef<LuaState>>,
pub threads: HashMap<u64, ThreadRegistryEntry>,
pub main_thread_value: GcRef<LuaThread>,
pub current_thread_id: u64,
pub main_thread_id: u64,
pub next_thread_id: u64,
pub memerrmsg: GcRef<LuaString>,
pub tmname: Vec<GcRef<LuaString>>,
pub mt: [Option<GcRef<LuaTable>>; 9],
pub strcache: [[GcRef<LuaString>; 2]; 53],
pub interned_lt: HashMap<Box<[u8]>, GcRef<LuaString>>,
pub warnf: Option<Box<dyn FnMut(&[u8], bool)>>,
pub warn_mode: WarnMode,
pub test_warn_enabled: bool,
pub test_warn_on: bool,
pub test_warn_mode: TestWarnMode,
pub test_warn_last_to_cont: bool,
pub test_warn_buffer: Vec<u8>,
pub c_functions: Vec<LuaCallable>,
pub heap: Heap,
pub cross_thread_upvals: HashMap<(u64, StackIdx), LuaValue>,
pub suspended_parent_stacks: Vec<Vec<LuaValue>>,
pub suspended_parent_open_upvals: Vec<Vec<GcRef<UpVal>>>,
}Expand description
Process-wide state shared by all Lua threads.
types.tsv: global_State → GlobalState
Not exposed directly at the API; accessed via state.global() / state.global_mut().
Fields§
§parser_hook: Option<ParserHook>Phase-B hook for the Lua text parser. Set by the embedder (lua-cli
or stdlib host) to bridge the cyclic crate split between lua-vm and
lua-parse: when f_parser decides the chunk is text, it invokes
this hook instead of the parser stub. None leaves the stub in place
so unit tests that never load text still work.
cli_argv: Option<Vec<Vec<u8>>>Transient slot carrying the CLI’s argv into the pmain C closure.
Mirrors lua.c’s lua_pushinteger(argc)/lua_pushlightuserdata(argv)
arguments to pmain: a lua-rs C closure cannot capture Rust values, so
lua-cli’s run parks argv here, pushes a zero-arg pmain closure,
and pcall_ks it; pmain take()s it back out. Lives on GlobalState
to keep lua-cli free of unsafe light-userdata round-tripping.
cli_preload: Option<fn(&mut LuaState) -> Result<(), LuaError>>Transient slot carrying the CLI’s native-module preload callback into
the pmain C closure, paired with GlobalState::cli_argv. The type
matches lua-cli::interp::run’s preload parameter.
lua_version: LuaVersionThe Lua language version this state speaks. The single source of truth
for version-gated behavior in the layers that read the state (parser,
stdlib openers). The embedder sets this from the [Lua] instance’s
lua_types::LuaVersion at construction; it defaults to
lua_types::LuaVersion::V54 so any state built without an explicit
version keeps the existing 5.4 behavior unchanged.
file_loader_hook: Option<FileLoaderHook>Phase-B hook for reading a Lua source file from disk. Set by lua-cli
(or any embedder that wants require/loadfile to reach the file
system) since std::fs is banned in lua-stdlib. None makes
loadfile and the Lua-file searcher report a file-not-found error.
file_open_hook: Option<FileOpenHook>Phase-B hook for opening a file handle for read/write/append. Set by
lua-cli since std::fs is banned in lua-stdlib. None causes
io.open and io.output(name) to return an error; standard output and
error are controlled separately through output hooks/native fallbacks.
stdout_hook: Option<OutputHook>Hook for host stdout. When absent, native builds fall back to Rust stdout
for compatibility; bare wasm32-unknown-unknown reports stdout
unavailable instead of touching a stubbed stdio implementation.
stderr_hook: Option<OutputHook>Hook for host stderr. See GlobalState::stdout_hook.
stdin_hook: Option<InputHook>Hook for host stdin. When absent, native builds fall back to Rust stdin
for compatibility; bare wasm32-unknown-unknown behaves like EOF.
env_hook: Option<EnvHook>Hook for host environment lookups. None makes os.getenv return nil.
unix_time_hook: Option<UnixTimeHook>Hook for host wall-clock time. Required for os.time() and os.date()
without an explicit timestamp under bare WASM.
cpu_clock_hook: Option<CpuClockHook>Hook for host program CPU time. Backs os.clock. When unset, native builds
use a monotonic wall-clock baseline and bare WASM reports it unavailable.
local_offset_hook: Option<LocalOffsetHook>Hook for the host’s local timezone offset at a given instant. Backs the
local-time semantics of os.date (non-! formats) and os.time. When
unset, both use UTC, matching the prior behaviour and keeping the
os.date/os.time round-trip exact under bare WASM.
entropy_hook: Option<EntropyHook>Hook for host entropy. Used by default math.randomseed and table sort
pivot randomisation; absent hooks fall back to deterministic seeds.
temp_name_hook: Option<TempNameHook>Hook for host temporary filenames. Used by os.tmpname and io.tmpfile.
popen_hook: Option<PopenHook>Phase-G hook for spawning a child process and connecting one stream
(stdin or stdout) to a Lua file handle. Set by lua-cli since
std::process::Command is banned in lua-stdlib. None causes
io.popen to raise a Lua error rather than panic.
file_remove_hook: Option<FileRemoveHook>Phase-B hook for removing a file. Set by lua-cli since std::fs is
banned in lua-stdlib. None causes os.remove to return an error.
file_rename_hook: Option<FileRenameHook>Phase-B hook for renaming a file. Set by lua-cli since std::fs is
banned in lua-stdlib. None causes os.rename to return an error.
os_execute_hook: Option<OsExecuteHook>Phase-G hook for executing a shell command. Set by lua-cli since
std::process is banned in lua-stdlib. None causes os.execute
to report no shell available (matching C-Lua’s system(NULL) == 0).
dynlib_load_hook: Option<DynLibLoadHook>Phase-D-3.5 hook for loading a dynamic library (dlopen /
LoadLibraryEx). Set by lua-cli since libloading is FFI and
requires unsafe, which is banned in lua-stdlib. None causes
package.loadlib to return the "absent" fallback shape.
dynlib_symbol_hook: Option<DynLibSymbolHook>Phase-D-3.5 hook for resolving a symbol in a previously loaded
dynamic library (dlsym / GetProcAddress). Set by lua-cli.
None is treated as “absent” by package.loadlib.
dynlib_unload_hook: Option<DynLibUnloadHook>Phase-D-3.5 hook for unloading a dynamic library (dlclose /
FreeLibrary). Set by lua-cli. None keeps libraries loaded
until process exit, which matches libloading’s safety model.
totalbytes: isize§sandbox: SandboxLimitsPer-runtime sandbox budget shared across all threads. Inactive by
default (interval == 0); see SandboxLimits.
gc_debt: isize§gc_estimate: usize§lastatomic: usize§strt: StringPool§l_registry: LuaValue§external_roots: ExternalRootSetExternal Rust handles root their referents here while they are live.
Traced from GlobalState::trace.
globals: LuaValue§loaded: LuaValue§nilvalue: LuaValue§seed: u32§currentwhite: u8§gcstate: u8§gckind: u8§gcstopem: bool§genminormul: u8§genmajormul: u8§gcstp: u8§gcemergency: bool§gcpause: u8§gcstepmul: u8§gcstepsize: u8§gc55_params: [i64; 6]Lua 5.5 collectgarbage("param", name [, value]) storage, indexed by
[Gc55Param]: [minormul, majorminor, minormajor, pause, stepmul, stepsize]. The 5.5 GC parameters use a wider value range than the
packed u8 fields above, so they get their own storage. This is a
faithful-shape backing store: it preserves the read-current /
write-returns-old contract and the upstream default values, without
claiming to retune the incremental collector. Initialized to the
values observed on the reference lua5.5.0 binary.
sweepgc_cursor: usize§weak_tables_registry: Vec<GcWeak<LuaTable>>Cross-table weak-sweep registry.
Heap collection snapshots this list before mark, then the post-mark
weak-table pass clears entries whose weak target is held only by other
weak slots. The registry holds GcWeak<LuaTable> so it does not pin
dead weak tables after sweep removes their heap allocation token.
Replaced by proper weak / ephemeron / allweak cohorts once the
Lua-style generational lists land.
pending_finalizers: Vec<FinalizerObject>Finalizable tables and userdata whose metatable carried __gc when
installed. This mirrors C-Lua’s finobj list: entries are deliberately
not traced as roots, so a mark phase can detect when an object is
reachable only through the finalizer registry.
to_be_finalized: Vec<FinalizerObject>Finalizable objects promoted by the most recent atomic mark phase
because they were otherwise unreachable. This mirrors C-Lua’s
tobefnz list and is traced as a temporary root so the object survives
until its __gc call runs.
gc_finalizer_error: Option<LuaValue>Error raised by a __gc finalizer during an explicit collectgarbage
on 5.2 / 5.3, parked here for the collectgarbage wrapper to re-raise.
C-Lua re-throws the wrapped error in __gc metamethod (%s) directly out
of GCTM via luaD_throw. The Rust api::gc entry point returns i32
(its many callers cannot all thread a Result), so the explicit-collect
path stashes the wrapped error here and the collectgarbage built-in
drains it into the Result<usize, LuaError> it already returns. Only
the explicit-collect path sets this; the automatic GC-step and close
paths never do (matching GCTM(L, 0) and the dispatch-loop swallow).
twups: Vec<GcRef<LuaState>>§panic: Option<LuaCFunction>§mainthread: Option<GcRef<LuaState>>§threads: HashMap<u64, ThreadRegistryEntry>Registry of all live coroutine threads, keyed by ThreadId. Phase E-1
replaces the thread_token placeholder with a real id-indexed map so
coroutine.create allocates a fresh LuaState, registers it, and
returns a value that resolves back to the same state on every
coroutine.status / coroutine.resume call.
Each entry pairs the per-thread LuaState with the canonical
GcRef<LuaThread> value, so two LuaValue::Thread pushes of the
same id share GcRef::ptr_eq identity. The main thread is NOT
stored here — its LuaState is owned externally by the embedder.
main_thread_id is reserved as 0 and a LuaValue::Thread
carrying id 0 is recognized as the main thread by lookup helpers.
main_thread_value: GcRef<LuaThread>Cached LuaValue::Thread payload for the main thread (id 0).
Built once during new_state so every push_thread on the main
thread shares the same GcRef<LuaThread> and thus compares
pointer-equal under LuaValue::PartialEq.
current_thread_id: u64Identity of the currently-running thread. 0 (main) until a
coroutine resume swaps it in slice 02b. The Phase E-1 slice
always leaves this at main_thread_id because resume is not yet
implemented.
main_thread_id: u64Identity of the main thread. Convention: 0. Held as a field so
the lookup helpers can read it without hard-coding the constant.
next_thread_id: u64Monotonic counter handing out fresh ids in new_thread. Starts
at 1 because 0 is reserved for the main thread.
memerrmsg: GcRef<LuaString>§tmname: Vec<GcRef<LuaString>>§mt: [Option<GcRef<LuaTable>>; 9]§strcache: [[GcRef<LuaString>; 2]; 53]§interned_lt: HashMap<Box<[u8]>, GcRef<LuaString>>Stable intern map for the public LuaString type. Distinct from
strt (which keys internal LuaStringImpl) because the parser and
stdlib need pointer-equality across intern_str calls so
GcRef::ptr_eq can resolve variable identity. Without this map each
call allocates a fresh GcRef and locals/upvalues fail to resolve.
warnf: Option<Box<dyn FnMut(&[u8], bool)>>§warn_mode: WarnModeState of the default warning handler (the warnfoff/warnfon/
warnfcont chain from upstream lauxlib.c). luaL_openlibs installs
warnfoff, so warnings start disabled until warn("@on"). Only
consulted when no custom warnf was installed via the C API.
test_warn_enabled: booltestC/ltests warning sink, enabled only by the CLI’s LUA_RS_TESTC
support. It mirrors ltests.c’s warnf: a separate on/off bit, an
output mode (normal, allow, store), and a continuation buffer so
multi-part warnings can be asserted via global _WARN.
test_warn_on: bool§test_warn_mode: TestWarnMode§test_warn_last_to_cont: bool§test_warn_buffer: Vec<u8>§c_functions: Vec<LuaCallable>Registry of native LuaCFunction pointers. Lua-types cannot reference
LuaState, so LuaClosure::LightC carries a usize index into this
vector instead of the real function pointer. push_c_function
registers the function and stores the resulting index in the closure.
heap: HeapPhase-D heap. Owns the allgc intrusive list and runs collections.
During Phase A-C this is paused=true, so allocations don’t auto-
register and step is a no-op. Phase D-1d wires unpause() after
state initialization, at which point step runs during VM dispatch.
cross_thread_upvals: HashMap<(u64, StackIdx), LuaValue>Phase E-3 cross-thread open-upvalue mirror. Maps (thread_id, stack_idx)
to the live value of an open upvalue whose home thread is currently
suspended while another thread runs. coroutine.resume snapshots the
parent’s open upvalues into this map before yielding control to the
child, and reads the (possibly mutated) values back into the parent’s
stack when the child suspends or returns. From the running thread’s
perspective, upvalue_get / upvalue_set consult the mirror whenever
an open upvalue’s thread_id does not match current_thread_id.
This avoids a stack refactor: the parent’s LuaState is held by a
&mut reference up the call stack during resume, so its stack cannot
be reached directly through any Rc<RefCell<_>>. The mirror is the
shared scratchpad that bridges the gap for the duration of a resume.
suspended_parent_stacks: Vec<Vec<LuaValue>>Phase F-1.a workaround for GC use-after-free across coroutine boundaries.
When aux_resume switches to a child thread, the parent’s live stack
values would otherwise become unreachable to the tracer for the duration
of the resume (the parent LuaState is held only as a stack-borrowed
&mut up the call chain and is not part of any traced root set). To
keep those values alive, aux_resume pushes a snapshot of the parent
stack here before transferring control, and pops it on suspension or
completion. The tracer visits every snapshot as a GC root via the
Trace for GlobalState impl in trace_impls.rs.
Phase F-2.b added a reachability-driven thread sweep that supersedes most of this, but the snapshot still guards values that live only on the parent’s stack (i.e. not yet rooted by any thread node).
suspended_parent_open_upvals: Vec<Vec<GcRef<UpVal>>>Open-upvalue handles belonging to the same suspended parent windows as
suspended_parent_stacks. Stack snapshots keep the pointed-to values
alive; this roots the UpVal objects themselves so a GC inside the
child coroutine cannot sweep entries still present in the parent’s
openupval list.
Implementations§
Source§impl GlobalState
impl GlobalState
Sourcepub fn sandbox_active(&self) -> bool
pub fn sandbox_active(&self) -> bool
True while a sandbox instruction/memory budget is active on this runtime.
Sourcepub fn total_bytes(&self) -> usize
pub fn total_bytes(&self) -> usize
Total live bytes allocated, as reported by the collector-owned heap accounting model.
macros.tsv: gettotalbytes → g.total_bytes()
Sourcepub fn get_thread(&self, id: u64) -> Option<&ThreadRegistryEntry>
pub fn get_thread(&self, id: u64) -> Option<&ThreadRegistryEntry>
Look up the coroutine LuaState registered under id. Returns
None for the main-thread id (the main LuaState is owned by
the embedder, not stored in threads) and for ids that were
never issued or have already been closed.
Sourcepub fn thread_value_for(&self, id: u64) -> Option<GcRef<LuaThread>>
pub fn thread_value_for(&self, id: u64) -> Option<GcRef<LuaThread>>
Return the canonical GcRef<LuaThread> for id. For the main
thread that’s main_thread_value; for a coroutine it’s the
value stored in the registry. Returns None if id is unknown.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Returns true when the state has been fully initialized.
macros.tsv: completestate → g.is_complete()
PORT NOTE: C uses g->nilvalue being nil as the “complete” signal.
We replicate the same logic: nilvalue == Nil means complete.
Sourcepub fn current_white(&self) -> u8
pub fn current_white(&self) -> u8
Returns the “current white” GC color bitmask.
macros.tsv: luaC_white → g.current_white()
PORT NOTE: the effective dual-white collector state lives in
lua_gc::Heap; this field preserves the translated global_State
shape for code that still reads the upstream bitmask.
Sourcepub fn other_white(&self) -> u8
pub fn other_white(&self) -> u8
Returns the “other white” GC color bitmask.
macros.tsv: otherwhite → g.other_white()
Sourcepub fn is_gen_mode(&self) -> bool
pub fn is_gen_mode(&self) -> bool
Returns true if the GC is in generational mode.
macros.tsv: isdecGCmodegen → g.is_gen_mode()
Sourcepub fn gc_running(&self) -> bool
pub fn gc_running(&self) -> bool
Returns true if the GC is currently running.
macros.tsv: gcrunning → g.gc_running()
Sourcepub fn keep_invariant(&self) -> bool
pub fn keep_invariant(&self) -> bool
Returns true while the GC is in its propagation phase.
macros.tsv: keepinvariant → g.keep_invariant()
Sourcepub fn is_sweep_phase(&self) -> bool
pub fn is_sweep_phase(&self) -> bool
Returns true while the GC is in a sweep phase.
macros.tsv: issweepphase → g.is_sweep_phase()
pub fn gc_debt(&self) -> isize
pub fn set_gc_debt(&mut self, d: isize)
pub fn gc_at_pause(&self) -> bool
pub fn gc_pause_param(&self) -> i32
pub fn set_gc_pause_param(&mut self, p: i32)
pub fn gc_stepmul_param(&self) -> i32
pub fn set_gc_stepmul_param(&mut self, p: i32)
pub fn gc_genmajormul_param(&self) -> i32
pub fn set_gc_genmajormul(&mut self, p: i32)
Sourcepub fn gc55_param(&mut self, idx: usize, value: i64) -> i64
pub fn gc55_param(&mut self, idx: usize, value: i64) -> i64
Lua 5.5 collectgarbage("param", name [, value]). idx is the 0-based
param index (minormul=0 .. stepsize=5). When value >= 0 the param is
set; the previous value is always returned.
pub fn gc_stop_flags(&self) -> u8
pub fn set_gc_stop_flags(&mut self, f: u8)
pub fn stop_gc_internal(&mut self) -> u8
pub fn set_gc_stop_user(&mut self)
pub fn clear_gc_stop(&mut self)
pub fn is_gc_running(&self) -> bool
Sourcepub fn is_gc_stopped_internally(&self) -> bool
pub fn is_gc_stopped_internally(&self) -> bool
True when the GC has been disabled internally (state setup, mid-GC,
or while closing); user-stop via collectgarbage("stop") does NOT
set this bit, so lua_gc continues to honour Count/Step/etc.
Sourcepub fn tm_name<T: TmIndex>(&self, tm: T) -> Option<GcRef<LuaString>>
pub fn tm_name<T: TmIndex>(&self, tm: T) -> Option<GcRef<LuaString>>
Returns the interned __xxx name string for tag method tm, or
None if tmname has not yet been initialised (early bootstrap).
macros.tsv: getshrstr(G(L)->tmname[tm]) → g.tm_name(tm).
PORT NOTE: The lua-vm crate carries two distinct TagMethod enums
(one in lua-types, one in crate::tagmethods) with identical
#[repr(u8)] ordering. The TmIndex trait bridges them so callers
from either side can index tmname uniformly.