luaur_code_gen/records/
shared_code_allocator.rs1use crate::records::code_allocator::CodeAllocator;
2use crate::records::native_module::NativeModule;
3use crate::records::native_module_ref::NativeModuleRef;
4use crate::type_aliases::module_id::ModuleId;
5use crate::type_aliases::native_proto_exec_data_ptr::NativeProtoExecDataPtr;
6use alloc::boxed::Box;
7use alloc::collections::BTreeMap;
8use alloc::vec::Vec;
9use core::sync::atomic::{AtomicUsize, Ordering};
10
11#[derive(Debug)]
12pub struct SharedCodeAllocator {
13 pub(crate) identified_modules: BTreeMap<ModuleId, Box<NativeModule>>,
14 pub(crate) anonymous_module_count: AtomicUsize,
15 pub(crate) code_allocator: *mut CodeAllocator,
16}
17
18impl SharedCodeAllocator {
19 pub fn erase_native_module_if_unreferenced(&mut self, native_module: &NativeModule) {
20 self.shared_code_allocator_erase_native_module_if_unreferenced(native_module);
21 }
22
23 pub fn get_or_insert_native_module(
24 &mut self,
25 module_id: &ModuleId,
26 native_protos: Vec<NativeProtoExecDataPtr>,
27 data: *const u8,
28 data_size: usize,
29 code: *const u8,
30 code_size: usize,
31 ) -> (NativeModuleRef, bool) {
32 use luaur_common::FFlag;
33
34 let existing_module = self.try_get_native_module_with_lock_held(module_id);
35 if !existing_module.native_module.is_null() {
36 return (existing_module, false);
37 }
38
39 unsafe {
40 if FFlag::LuauCodegenFreeBlocks.get() {
41 let result = (*self.code_allocator).allocate(data, data_size, code, code_size);
42
43 if result.start.is_null() {
44 return (NativeModuleRef::default(), false);
45 }
46
47 let native_module = Box::new(
48 NativeModule::native_module_shared_code_allocator_optional_module_id_code_allocation_data_vector_native_proto_exec_data_ptr(
49 self as *mut SharedCodeAllocator,
50 &Some(*module_id),
51 result,
52 native_protos,
53 ),
54 );
55 let native_module_ptr: *const NativeModule = &*native_module;
56 self.identified_modules.insert(*module_id, native_module);
57
58 (
59 NativeModuleRef::native_module_ref_native_module(native_module_ptr),
60 true,
61 )
62 } else {
63 let mut native_data = core::ptr::null_mut();
64 let mut native_data_size = 0;
65 let mut code_start = core::ptr::null_mut();
66
67 if !(*self.code_allocator).allocate_deprecated(
68 data,
69 data_size,
70 code,
71 code_size,
72 &mut native_data,
73 &mut native_data_size,
74 &mut code_start,
75 ) {
76 return (NativeModuleRef::default(), false);
77 }
78
79 let native_module = Box::new(
80 NativeModule::native_module_shared_code_allocator_optional_module_id_u8_vector_native_proto_exec_data_ptr(
81 self as *mut SharedCodeAllocator,
82 &Some(*module_id),
83 code_start,
84 native_protos,
85 ),
86 );
87 let native_module_ptr: *const NativeModule = &*native_module;
88 self.identified_modules.insert(*module_id, native_module);
89
90 (
91 NativeModuleRef::native_module_ref_native_module(native_module_ptr),
92 true,
93 )
94 }
95 }
96 }
97
98 pub fn insert_anonymous_native_module(
99 &mut self,
100 native_protos: Vec<NativeProtoExecDataPtr>,
101 data: *const u8,
102 data_size: usize,
103 code: *const u8,
104 code_size: usize,
105 ) -> NativeModuleRef {
106 self.shared_code_allocator_insert_anonymous_native_module(
107 native_protos,
108 data,
109 data_size,
110 code,
111 code_size,
112 )
113 }
114
115 pub fn operator_assign_copy(
116 &mut self,
117 _other: &SharedCodeAllocator,
118 ) -> &mut SharedCodeAllocator {
119 unreachable!("Deleted operator=");
120 }
121
122 pub fn operator_assign_move(
123 &mut self,
124 _other: &mut SharedCodeAllocator,
125 ) -> &mut SharedCodeAllocator {
126 unreachable!("Deleted operator=");
127 }
128
129 pub fn shared_code_allocator_move(&mut self) {
130 unreachable!("Deleted constructor");
131 }
132
133 pub fn shared_code_allocator_code_allocator(&mut self, code_allocator: *mut CodeAllocator) {
134 self.identified_modules.clear();
135 self.anonymous_module_count = AtomicUsize::new(0);
136 self.code_allocator = code_allocator;
137 }
138
139 pub fn shared_code_allocator_copy(&mut self) {
140 unreachable!("Deleted constructor");
141 }
142
143 pub fn try_get_native_module(&self, module_id: &ModuleId) -> NativeModuleRef {
144 self.try_get_native_module_with_lock_held(module_id)
145 }
146
147 pub fn try_get_native_module_with_lock_held(&self, module_id: &ModuleId) -> NativeModuleRef {
148 match self.identified_modules.get(module_id) {
149 Some(native_module) => unsafe {
150 NativeModuleRef::native_module_ref_native_module(&**native_module)
151 },
152 None => NativeModuleRef::default(),
153 }
154 }
155}
156
157impl Default for SharedCodeAllocator {
158 fn default() -> Self {
159 Self {
160 identified_modules: BTreeMap::new(),
161 anonymous_module_count: AtomicUsize::new(0),
162 code_allocator: core::ptr::null_mut(),
163 }
164 }
165}
166
167impl Drop for SharedCodeAllocator {
168 fn drop(&mut self) {
169 crate::macros::codegen_assert::CODEGEN_ASSERT!(self.identified_modules.is_empty());
170 crate::macros::codegen_assert::CODEGEN_ASSERT!(
171 self.anonymous_module_count.load(Ordering::Relaxed) == 0
172 );
173 }
174}