shape_vm/bytecode/
program_impl.rs1use super::*;
2
3impl BytecodeProgram {
4 fn trait_method_symbol_key(
5 trait_name: &str,
6 type_name: &str,
7 impl_name: Option<&str>,
8 method_name: &str,
9 ) -> String {
10 format!(
11 "{}::{}::{}::{}",
12 trait_name,
13 type_name,
14 impl_name.unwrap_or(DEFAULT_TRAIT_IMPL_SELECTOR),
15 method_name
16 )
17 }
18
19 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn add_constant(&mut self, constant: Constant) -> u16 {
26 if let Some(idx) = self.constants.iter().position(|c| c == &constant) {
28 return idx as u16;
29 }
30
31 let idx = self.constants.len() as u16;
32 self.constants.push(constant);
33 idx
34 }
35
36 pub fn add_string(&mut self, string: String) -> u16 {
39 self.ensure_string_index();
40 if let Some(&idx) = self.string_index.get(&string) {
41 return idx as u16;
42 }
43 let idx = self.strings.len() as u32;
44 self.string_index.insert(string.clone(), idx);
45 self.strings.push(string);
46 idx as u16
47 }
48
49 pub fn intern_string(&mut self, s: &str) -> StringId {
52 self.ensure_string_index();
53 if let Some(&idx) = self.string_index.get(s) {
54 return StringId(idx);
55 }
56 let idx = self.strings.len() as u32;
57 self.string_index.insert(s.to_owned(), idx);
58 self.strings.push(s.to_owned());
59 StringId(idx)
60 }
61
62 pub fn ensure_string_index(&mut self) {
65 if self.string_index.is_empty() && !self.strings.is_empty() {
66 for (i, s) in self.strings.iter().enumerate() {
67 self.string_index.insert(s.clone(), i as u32);
68 }
69 }
70 }
71
72 pub fn resolve_string(&self, id: StringId) -> &str {
76 &self.strings[id.0 as usize]
77 }
78
79 pub fn emit(&mut self, instruction: Instruction) -> usize {
81 let idx = self.instructions.len();
82 self.instructions.push(instruction);
83 idx
84 }
85
86 pub fn current_offset(&self) -> usize {
88 self.instructions.len()
89 }
90
91 pub fn register_trait_method_symbol(
93 &mut self,
94 trait_name: &str,
95 type_name: &str,
96 impl_name: Option<&str>,
97 method_name: &str,
98 function_name: &str,
99 ) {
100 let key = Self::trait_method_symbol_key(trait_name, type_name, impl_name, method_name);
101 self.trait_method_symbols
102 .insert(key, function_name.to_string());
103 }
104
105 pub fn lookup_trait_method_symbol(
107 &self,
108 trait_name: &str,
109 type_name: &str,
110 impl_name: Option<&str>,
111 method_name: &str,
112 ) -> Option<&str> {
113 let key = Self::trait_method_symbol_key(trait_name, type_name, impl_name, method_name);
114 self.trait_method_symbols.get(&key).map(|s| s.as_str())
115 }
116
117 pub fn named_trait_impls_for_method(
121 &self,
122 trait_name: &str,
123 type_name: &str,
124 method_name: &str,
125 ) -> Vec<String> {
126 let prefix = format!("{}::{}::", trait_name, type_name);
127 let suffix = format!("::{}", method_name);
128 let mut names = std::collections::BTreeSet::new();
129
130 for key in self.trait_method_symbols.keys() {
131 if !key.starts_with(&prefix) || !key.ends_with(&suffix) {
132 continue;
133 }
134 let middle = &key[prefix.len()..key.len() - suffix.len()];
135 if middle != DEFAULT_TRAIT_IMPL_SELECTOR && !middle.is_empty() {
136 names.insert(middle.to_string());
137 }
138 }
139
140 names.into_iter().collect()
141 }
142
143 pub fn find_default_trait_impl_for_type_method(
152 &self,
153 type_name: &str,
154 method_name: &str,
155 ) -> Option<&str> {
156 let default_suffix = format!(
159 "::{}::{}::{}",
160 type_name, DEFAULT_TRAIT_IMPL_SELECTOR, method_name
161 );
162 for (key, func_name) in &self.trait_method_symbols {
163 if key.ends_with(&default_suffix) {
164 return Some(func_name.as_str());
165 }
166 }
167 let suffix = format!("::{}", method_name);
169 let type_segment = format!("::{}::", type_name);
170 for (key, func_name) in &self.trait_method_symbols {
171 if key.contains(&type_segment) && key.ends_with(&suffix) {
172 return Some(func_name.as_str());
173 }
174 }
175 None
176 }
177
178 pub(crate) fn merge_append(&mut self, other: BytecodeProgram) {
184 let mut other = other;
185
186 if self.instructions.last().map(|i| i.opcode) == Some(OpCode::Halt) {
188 self.instructions.pop();
189 }
190
191 let const_offset = self.constants.len() as u16;
193 let string_offset = self.strings.len() as u16;
194 let func_offset = self.functions.len() as u16;
195 let foreign_offset = self.foreign_functions.len() as u16;
196 let instr_offset = self.instructions.len();
197
198 for constant in &mut other.constants {
200 if let Constant::Function(id) = constant {
201 *id += func_offset;
202 }
203 }
204
205 for func in &mut other.functions {
207 func.entry_point += instr_offset;
208 }
209
210 for instr in &mut other.instructions {
212 if let Some(ref mut operand) = instr.operand {
213 match operand {
214 Operand::Const(idx) => *idx += const_offset,
215 Operand::Property(idx) => *idx += string_offset,
216 Operand::Function(idx) => idx.0 += func_offset,
217 Operand::Name(id) => id.0 += string_offset as u32,
218 Operand::MethodCall { name, .. } => name.0 += string_offset as u32,
219 Operand::TypedMethodCall { string_id, .. } => {
220 *string_id += string_offset;
221 }
222 Operand::ForeignFunction(idx) => *idx += foreign_offset,
223 Operand::Offset(_)
224 | Operand::Local(_)
225 | Operand::ModuleBinding(_)
226 | Operand::Count(_)
227 | Operand::Builtin(_)
228 | Operand::ColumnIndex(_)
229 | Operand::TypedField { .. }
230 | Operand::TypedObjectAlloc { .. }
231 | Operand::TypedMerge { .. }
232 | Operand::ColumnAccess { .. }
233 | Operand::MatrixDims { .. }
234 | Operand::Width(_)
235 | Operand::TypedLocal(_, _)
236 | Operand::TypedModuleBinding(_, _) => {}
237 }
238 }
239 }
240
241 self.constants.append(&mut other.constants);
243 self.strings.append(&mut other.strings);
244 self.string_index.clear();
246 self.functions.append(&mut other.functions);
247 self.instructions.append(&mut other.instructions);
248
249 self.function_local_storage_hints
251 .append(&mut other.function_local_storage_hints);
252
253 for name in other.module_binding_names {
255 if !self.module_binding_names.contains(&name) {
256 self.module_binding_names.push(name);
257 }
258 }
259
260 self.type_schema_registry.merge(other.type_schema_registry);
262
263 for (key, value) in other.trait_method_symbols {
265 self.trait_method_symbols.entry(key).or_insert(value);
266 }
267
268 for (key, value) in other.expanded_function_defs {
270 self.expanded_function_defs.entry(key).or_insert(value);
271 }
272
273 self.foreign_functions.append(&mut other.foreign_functions);
275
276 for layout in other.native_struct_layouts {
278 if !self
279 .native_struct_layouts
280 .iter()
281 .any(|l| l.name == layout.name)
282 {
283 self.native_struct_layouts.push(layout);
284 }
285 }
286 }
287}