pub struct GlobalState {Show 64 fields
pub parser_hook: Option<ParserHook>,
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 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 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 sweepgc_cursor: usize,
pub weak_tables_registry: Vec<GcWeak<LuaTable>>,
pub gc_tracked_long_strings: Vec<(GcWeak<LuaString>, usize)>,
pub pending_finalizers: Vec<GcRef<LuaTable>>,
pub to_be_finalized: Vec<GcRef<LuaTable>>,
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 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.
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.
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§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§sweepgc_cursor: usize§weak_tables_registry: Vec<GcWeak<LuaTable>>Phase-B cross-table weak-sweep registry.
lua_types::value::sweep_weak_tables iterates this list at
collectgarbage("collect") time to clear entries whose weak target
is held only by other weak slots. Holds Weak<LuaTable> so the
registry itself does not pin tables that the user has dropped.
Replaced by the proper weak / ephemeron / allweak lists when
Phase D’s incremental sweep lands.
gc_tracked_long_strings: Vec<(GcWeak<LuaString>, usize)>Phase-B long-string allocation tracker.
Each entry pairs a Weak<LuaString> with the byte count that was
added to gc_debt at allocation time. collectgarbage("count") walks
the list and reclaims gc_debt for entries whose weak target has been
dropped, so the Lua-visible memory total tracks live long-string bytes.
Short strings are interned and bounded in size, so they are not tracked
individually. Replaced by Phase D’s real allocator accounting.
pending_finalizers: Vec<GcRef<LuaTable>>Phase-B pending-finalizer registry.
Each entry is a strong GcRef<LuaTable> to a table whose metatable
carried __gc at the time setmetatable was called. The strong ref
pins the table so a normal Rc::drop does not destroy it before its
__gc metamethod runs. The Phase-B finalizer sweep
(crate::api::run_pending_finalizers) scans this list, takes any
entry whose strong count is 1 (only this list holds it — i.e. the
user has dropped every reference), and invokes its __gc before
releasing the ref. Replaced by finobj / tobefnz when the real
incremental GC lands in Phase D.
to_be_finalized: Vec<GcRef<LuaTable>>Tables identified by the most recent collect_via_heap mark phase as
reachable only through pending_finalizers (i.e. the user has dropped
every reference). Their __gc runs the next time
run_pending_finalizers executes; entries are then cleared. Traced as
strong roots so they survive the sweep that scheduled them.
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)>>§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 total_bytes(&self) -> usize
pub fn total_bytes(&self) -> usize
Total live bytes allocated (GCdebt + totalbytes).
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: GC color management deferred to Phase D; always returns the initial white bit.
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) -> u8
pub fn set_gc_pause_param(&mut self, p: u8)
pub fn gc_stepmul_param(&self) -> u8
pub fn set_gc_stepmul_param(&mut self, p: u8)
pub fn set_gc_genmajormul(&mut self, p: u8)
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.