1mod call_info;
2mod callbacks;
3mod lifecycle;
4mod thread;
5
6pub(crate) use crate::memory::allocator::VmAllocator;
7pub use crate::memory::allocator::{LuaAllocator, SystemLuaAllocator, VM_ALLOC_ALIGN};
8pub use call_info::{CallInfo, CallInfoCursor, RawCallInfo, RawCallInfoSaved};
9pub use callbacks::{
10 AllocateCallback, EmbedderGc, EmbedderMark, ExecutionCallbackStorage, ExecutionClose,
11 ExecutionCounterData, ExecutionDestroy, ExecutionDisable, ExecutionEnter,
12 ExecutionInlineFunction, ExecutionInterrupt, ExecutionMemorySize, ExecutionTypeMapping,
13 GcInterrupt, GcInterruptCallback, GcPhase, InterruptKind, InterruptRequest, LuaCallbacks,
14 LuaExecutionCallbacks, PatternInterrupt, ProtectedErrorAction, ProtectedErrorCallback,
15 UserAtomCallback, UserThreadCallback,
16};
17pub use lifecycle::ThreadLifecycle;
18pub(crate) use lifecycle::open_main_state;
19pub use thread::{RawLuaState, ThreadState};
20
21use core::cell::UnsafeCell;
22use core::ptr::NonNull;
23
24use crate::call::LuaProtectedErrorFrame;
25use crate::function::RawUpVal;
26use crate::gc::{GcStats, RawGcObject};
27use crate::handle::RawHandle;
28use crate::handle::sealed::Sealed;
29use crate::memory::{LUA_MEMORY_CATEGORIES, LUA_SIZE_CLASSES, RawLuaPage};
30use crate::metamethod::TM_N;
31use crate::string::{RawTString, StringTable};
32use crate::table::RawLuaTable;
33use crate::thread::{LUA_MIN_STACK, LUAI_MAX_NATIVE_CALLS, Thread};
34use crate::types::LUA_T_COUNT;
35use crate::userdata::{LuaUserdataDirectAccessData, UserdataTypeRegistry};
36use crate::value::{RawTValue, TValue};
37
38#[repr(C)]
39pub struct RawMainState {
40 pub state: RawLuaState,
41 pub global: RawGlobalState,
42}
43
44#[repr(C)]
45pub struct RawGlobalState {
46 pub string_table: StringTable,
47 pub(crate) allocator: NonNull<VmAllocator>,
48 pub current_white: u8,
49 pub gc_state: u8,
50 pub gray: *mut RawGcObject,
51 pub gray_again: *mut RawGcObject,
52 pub weak: *mut RawGcObject,
53 pub gc_threshold: usize,
54 pub total_bytes: usize,
55 pub gc_goal: i32,
56 pub gc_step_mul: i32,
57 pub gc_step_size: i32,
58 pub free_pages: [*mut RawLuaPage; LUA_SIZE_CLASSES],
59 pub free_gco_pages: [*mut RawLuaPage; LUA_SIZE_CLASSES],
60 pub all_pages: *mut RawLuaPage,
61 pub all_gco_pages: *mut RawLuaPage,
62 pub sweep_gco_page: *mut RawLuaPage,
63 pub main_thread: *mut RawLuaState,
64 pub uv_head: RawUpVal,
65 pub mt: [*mut RawLuaTable; LUA_T_COUNT],
66 pub tt_name: [*mut RawTString; LUA_T_COUNT],
67 pub tm_name: [*mut RawTString; TM_N],
68 pub pseudo_temp: RawTValue,
69 pub registry: RawTValue,
70 pub registry_free: i32,
71 pub protected_error: *mut LuaProtectedErrorFrame,
72 pub rng_state: u64,
73 pub ptr_enc_key: [u64; 4],
74 pub cb: LuaCallbacks,
75 pub ecb: LuaExecutionCallbacks,
76 pub ecb_data: ExecutionCallbackStorage,
77 pub(crate) userdata_type_registry: UnsafeCell<UserdataTypeRegistry>,
78 pub userdata_direct: [LuaUserdataDirectAccessData; crate::userdata::USERDATA_INTERNAL_LIMIT],
79 pub memcat_bytes: [usize; LUA_MEMORY_CATEGORIES],
80 pub userdata_gc: [Option<crate::userdata::LuaDestructor>; crate::userdata::USERDATA_TAG_LIMIT],
81 pub userdata_mark:
82 [Option<crate::userdata::LuaUserdataMark>; crate::userdata::USERDATA_TAG_LIMIT],
83 pub userdata_mt: [*mut RawLuaTable; crate::userdata::USERDATA_TAG_LIMIT],
84 pub weak_registry: RawTValue,
85 pub weak_registry_free: i32,
86 pub embedder_gc: Option<EmbedderGc>,
87 pub light_userdata_name: [*mut RawTString; crate::userdata::LIGHT_USERDATA_TAG_LIMIT],
88 pub userdata_direct_fields: [*mut RawLuaTable; crate::userdata::USERDATA_INTERNAL_LIMIT],
89 pub gc_stats: GcStats,
90 pub last_proto_id: u32,
91}
92
93#[derive(Clone, Copy, PartialEq, Eq)]
94#[repr(transparent)]
95pub struct GlobalState {
104 raw: NonNull<RawGlobalState>,
105}
106
107#[allow(
108 clippy::missing_safety_doc,
109 reason = "GlobalState's shared raw-handle contract is documented on GlobalState"
110)]
111impl GlobalState {
112 pub const unsafe fn from_raw(raw: NonNull<RawGlobalState>) -> Self {
113 Self { raw }
114 }
115
116 pub unsafe fn main_thread(&self) -> Thread {
117 unsafe {
118 Thread::from_raw(NonNull::new_unchecked(
119 self.as_ptr().as_ref().unwrap_unchecked().main_thread,
120 ))
121 }
122 }
123
124 pub fn encode_pointer(&self, pointer: usize) -> usize {
125 let keys = unsafe { self.as_ptr().as_ref().unwrap_unchecked().ptr_enc_key };
126
127 ((keys[0] as usize)
128 .wrapping_mul(pointer)
129 .wrapping_add(keys[2] as usize))
130 ^ ((keys[1] as usize)
131 .wrapping_mul(pointer)
132 .wrapping_add(keys[3] as usize))
133 }
134
135 pub fn registry(&self) -> TValue {
136 unsafe { TValue::from_raw(NonNull::new_unchecked(&raw mut (*self.as_ptr()).registry)) }
137 }
138
139 pub fn pseudo_temp(&self) -> TValue {
140 unsafe {
141 TValue::from_raw(NonNull::new_unchecked(
142 &raw mut (*self.as_ptr()).pseudo_temp,
143 ))
144 }
145 }
146
147 pub fn registry_free(&self) -> i32 {
148 unsafe { (*self.as_ptr()).registry_free }
149 }
150
151 pub fn set_registry_free(&self, registry_free: i32) {
152 unsafe {
153 (*self.as_ptr()).registry_free = registry_free;
154 }
155 }
156
157 pub(crate) fn weak_registry(&self) -> TValue {
158 unsafe {
159 TValue::from_raw(NonNull::new_unchecked(
160 &raw mut (*self.as_ptr()).weak_registry,
161 ))
162 }
163 }
164
165 pub(crate) fn weak_registry_free(&self) -> i32 {
166 unsafe { (*self.as_ptr()).weak_registry_free }
167 }
168
169 pub(crate) fn set_weak_registry_free(&self, registry_free: i32) {
170 unsafe {
171 (*self.as_ptr()).weak_registry_free = registry_free;
172 }
173 }
174
175 pub(crate) fn embedder_gc(&self) -> Option<EmbedderGc> {
176 unsafe { (*self.as_ptr()).embedder_gc }
177 }
178
179 pub(crate) fn set_embedder_gc(&self, callback: Option<EmbedderGc>) {
180 unsafe {
181 (*self.as_ptr()).embedder_gc = callback;
182 }
183 }
184}
185
186impl Sealed for GlobalState {}
187
188impl RawHandle for GlobalState {
189 type Raw = RawGlobalState;
190
191 fn as_ptr(&self) -> *mut Self::Raw {
192 self.raw.as_ptr()
193 }
194}
195
196impl AsRef<GlobalState> for GlobalState {
197 fn as_ref(&self) -> &GlobalState {
198 self
199 }
200}
201
202pub(crate) const THREAD_STATUS_OK: u8 = 0;
203pub(crate) const THREAD_STATUS_YIELD: u8 = 1;
204pub(crate) const THREAD_STATUS_ERR_RUN: u8 = 2;
205pub(crate) const THREAD_STATUS_ERR_SYNTAX: u8 = 3;
206pub(crate) const THREAD_STATUS_ERR_MEM: u8 = 4;
207pub(crate) const THREAD_STATUS_ERR_ERR: u8 = 5;
208pub(crate) const THREAD_STATUS_BREAK: u8 = 6;
209pub(crate) const THREAD_STATUS_SCHEDULED_REENTRY: u8 = 0x7f;
210
211pub const LUA_MEMERRMSG: &[u8] = b"not enough memory";
212pub const LUA_ERRERRMSG: &[u8] = b"error in error handling";
213
214pub(crate) const LUA_EXECUTION_CALLBACK_STORAGE: usize = 512;
216
217pub const EXTRA_STACK: usize = 5;
218pub const BASIC_CI_SIZE: usize = 8;
219pub const BASIC_STACK_SIZE: usize = 2 * LUA_MIN_STACK;
220pub const INITIAL_STACK_SIZE: usize = BASIC_STACK_SIZE + EXTRA_STACK;
221pub const MAX_NATIVE_CALLS_HARD: u16 = LUAI_MAX_NATIVE_CALLS + (LUAI_MAX_NATIVE_CALLS >> 3);
222pub const LUA_CALLINFO_RETURN: u32 = 1 << 0;
223pub const LUA_CALLINFO_HANDLE: u32 = 1 << 1;
224pub const LUA_CALLINFO_NATIVE: u32 = 1 << 2;
225pub const LUA_CALLINFO_OP_YIELD: u32 = 1 << 3;
226
227pub const LUA_OK: i32 = THREAD_STATUS_OK as i32;
228pub const LUA_YIELD: i32 = THREAD_STATUS_YIELD as i32;
229pub const LUA_ERRRUN: i32 = THREAD_STATUS_ERR_RUN as i32;
230pub const LUA_ERRSYNTAX: i32 = THREAD_STATUS_ERR_SYNTAX as i32;
231pub const LUA_ERRMEM: i32 = THREAD_STATUS_ERR_MEM as i32;
232pub const LUA_ERRERR: i32 = THREAD_STATUS_ERR_ERR as i32;
233pub const LUA_BREAK: i32 = THREAD_STATUS_BREAK as i32;