1use super::super::context::JITContext;
12use super::super::jit_array::JitArray;
13use super::super::nan_boxing::*;
14
15pub fn get_array_elements(array_bits: u64) -> Vec<u64> {
21 if !is_heap_kind(array_bits, HK_ARRAY) {
22 return Vec::new();
23 }
24 let arr = unsafe { jit_unbox::<JitArray>(array_bits) };
25 arr.as_slice().to_vec()
26}
27
28pub fn create_array_from_elements(_ctx: *mut JITContext, elements: &[u64]) -> u64 {
30 let arr = JitArray::from_slice(elements);
31 jit_box(HK_ARRAY, arr)
32}
33
34#[repr(C)]
46pub struct ArrayInfo {
47 pub data_ptr: u64,
48 pub length: u64,
49}
50
51#[unsafe(no_mangle)]
52pub extern "C" fn jit_array_info(array_bits: u64) -> ArrayInfo {
53 if !is_heap_kind(array_bits, HK_ARRAY) {
54 return ArrayInfo {
55 data_ptr: 0,
56 length: 0,
57 };
58 }
59
60 let arr = unsafe { jit_unbox::<JitArray>(array_bits) };
61 ArrayInfo {
62 data_ptr: arr.data as u64,
63 length: arr.len as u64,
64 }
65}
66
67pub extern "C" fn jit_new_array(ctx: *mut JITContext, count: usize) -> u64 {
69 unsafe {
70 if ctx.is_null() || count > 512 {
71 return TAG_NULL;
72 }
73
74 let ctx_ref = &mut *ctx;
75 if ctx_ref.stack_ptr < count || ctx_ref.stack_ptr > 512 {
76 return TAG_NULL;
77 }
78
79 let mut elements = Vec::with_capacity(count);
80 for _ in 0..count {
81 ctx_ref.stack_ptr -= 1;
82 elements.push(ctx_ref.stack[ctx_ref.stack_ptr]);
83 }
84 elements.reverse();
85
86 jit_box(HK_ARRAY, JitArray::from_vec(elements))
87 }
88}
89
90pub extern "C" fn jit_array_get(array_bits: u64, index_bits: u64) -> u64 {
92 unsafe {
93 if !is_heap_kind(array_bits, HK_ARRAY) || !is_number(index_bits) {
94 return TAG_NULL;
95 }
96
97 let arr = jit_unbox::<JitArray>(array_bits);
98 let index = unbox_number(index_bits) as i64;
99
100 let actual_index = if index < 0 {
101 (arr.len() as i64 + index) as usize
102 } else {
103 index as usize
104 };
105
106 arr.get(actual_index).copied().unwrap_or(TAG_NULL)
107 }
108}
109
110pub extern "C" fn jit_array_push(ctx: *mut JITContext, count: i64) -> u64 {
112 unsafe {
113 if ctx.is_null() {
114 return TAG_NULL;
115 }
116
117 let ctx_ref = &mut *ctx;
118 let count = count as usize;
119
120 if ctx_ref.stack_ptr == 0 {
121 return TAG_NULL;
122 }
123 ctx_ref.stack_ptr -= 1;
124 let arg_count_val = ctx_ref.stack[ctx_ref.stack_ptr];
125 let arg_count = if is_number(arg_count_val) {
126 unbox_number(arg_count_val) as usize
127 } else {
128 count.saturating_sub(1)
129 };
130
131 let values_to_push = arg_count.saturating_sub(1);
132
133 let mut values = Vec::with_capacity(values_to_push);
134 for _ in 0..values_to_push {
135 if ctx_ref.stack_ptr == 0 {
136 break;
137 }
138 ctx_ref.stack_ptr -= 1;
139 values.push(ctx_ref.stack[ctx_ref.stack_ptr]);
140 }
141 values.reverse();
142
143 if ctx_ref.stack_ptr == 0 {
144 return TAG_NULL;
145 }
146 ctx_ref.stack_ptr -= 1;
147 let array_bits = ctx_ref.stack[ctx_ref.stack_ptr];
148
149 let mut elements = get_array_elements(array_bits);
150 elements.extend(values);
151
152 create_array_from_elements(ctx, &elements)
153 }
154}
155
156pub extern "C" fn jit_array_pop(array_bits: u64) -> u64 {
158 let mut elements = get_array_elements(array_bits);
159 if elements.is_empty() {
160 return array_bits;
161 }
162 elements.pop();
163 create_array_from_elements(std::ptr::null_mut(), &elements)
164}
165
166pub extern "C" fn jit_array_push_elem(array_bits: u64, value_bits: u64) -> u64 {
169 let mut elements = get_array_elements(array_bits);
170 elements.push(value_bits);
171 create_array_from_elements(std::ptr::null_mut(), &elements)
172}
173
174#[unsafe(no_mangle)]
179pub extern "C" fn jit_array_push_local(array_bits: u64, value_bits: u64) -> u64 {
180 if !is_heap_kind(array_bits, HK_ARRAY) {
181 return array_bits;
182 }
183 let arr = unsafe { jit_unbox_mut::<JitArray>(array_bits) };
184 arr.push(value_bits);
185 array_bits
186}
187
188#[unsafe(no_mangle)]
191pub extern "C" fn jit_array_reserve_local(array_bits: u64, min_capacity: i64) -> u64 {
192 if !is_heap_kind(array_bits, HK_ARRAY) {
193 return array_bits;
194 }
195 if min_capacity <= 0 {
196 return array_bits;
197 }
198 let arr = unsafe { jit_unbox_mut::<JitArray>(array_bits) };
199 arr.reserve(min_capacity as usize);
200 array_bits
201}
202
203pub extern "C" fn jit_array_zip(arr1: u64, arr2: u64) -> u64 {
205 let elements1 = get_array_elements(arr1);
206 let elements2 = get_array_elements(arr2);
207
208 let min_len = elements1.len().min(elements2.len());
209 let mut pairs = Vec::with_capacity(min_len);
210
211 for i in 0..min_len {
212 let pair = JitArray::from_slice(&[elements1[i], elements2[i]]);
213 let pair_bits = jit_box(HK_ARRAY, pair);
214 pairs.push(pair_bits);
215 }
216
217 let result = create_array_from_elements(std::ptr::null_mut(), &pairs);
218 for &pair_bits in &pairs {
220 super::gc::jit_write_barrier(0, pair_bits);
221 }
222 result
223}
224
225pub extern "C" fn jit_array_first(arr_bits: u64) -> u64 {
227 if !is_heap_kind(arr_bits, HK_ARRAY) {
228 return TAG_NULL;
229 }
230 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
231 arr.first().copied().unwrap_or(TAG_NULL)
232}
233
234pub extern "C" fn jit_array_last(arr_bits: u64) -> u64 {
236 if !is_heap_kind(arr_bits, HK_ARRAY) {
237 return TAG_NULL;
238 }
239 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
240 arr.last().copied().unwrap_or(TAG_NULL)
241}
242
243pub extern "C" fn jit_array_min(arr_bits: u64) -> u64 {
245 if !is_heap_kind(arr_bits, HK_ARRAY) {
246 return TAG_NULL;
247 }
248 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
249 if arr.is_empty() {
250 return TAG_NULL;
251 }
252 let mut min_val = f64::INFINITY;
253 for &bits in arr.iter() {
254 if is_number(bits) {
255 let n = unbox_number(bits);
256 if n < min_val {
257 min_val = n;
258 }
259 }
260 }
261 if min_val.is_infinite() {
262 TAG_NULL
263 } else {
264 box_number(min_val)
265 }
266}
267
268pub extern "C" fn jit_array_max(arr_bits: u64) -> u64 {
270 if !is_heap_kind(arr_bits, HK_ARRAY) {
271 return TAG_NULL;
272 }
273 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
274 if arr.is_empty() {
275 return TAG_NULL;
276 }
277 let mut max_val = f64::NEG_INFINITY;
278 for &bits in arr.iter() {
279 if is_number(bits) {
280 let n = unbox_number(bits);
281 if n > max_val {
282 max_val = n;
283 }
284 }
285 }
286 if max_val.is_infinite() {
287 TAG_NULL
288 } else {
289 box_number(max_val)
290 }
291}
292
293pub extern "C" fn jit_slice(arr_bits: u64, start_bits: u64, end_bits: u64) -> u64 {
295 unsafe {
296 if is_heap_kind(arr_bits, HK_STRING) {
298 let s = jit_unbox::<String>(arr_bits);
299
300 let start = if is_number(start_bits) {
301 unbox_number(start_bits) as usize
302 } else {
303 0
304 };
305 let end = if is_number(end_bits) {
306 unbox_number(end_bits) as usize
307 } else {
308 s.len()
309 };
310
311 let start = start.min(s.len());
312 let end = end.min(s.len());
313
314 if start > end {
315 return jit_box(HK_STRING, String::new());
316 }
317
318 let sliced = s[start..end].to_string();
319 return jit_box(HK_STRING, sliced);
320 }
321
322 if !is_heap_kind(arr_bits, HK_ARRAY) {
324 return TAG_NULL;
325 }
326 let arr = jit_unbox::<JitArray>(arr_bits);
327
328 let start = if is_number(start_bits) {
329 unbox_number(start_bits) as usize
330 } else {
331 0
332 };
333 let end = if is_number(end_bits) {
334 unbox_number(end_bits) as usize
335 } else {
336 arr.len()
337 };
338
339 let start = start.min(arr.len());
340 let end = end.min(arr.len());
341
342 if start > end {
343 return jit_box(HK_ARRAY, JitArray::new());
344 }
345
346 let sliced = JitArray::from_slice(&arr.as_slice()[start..end]);
347 jit_box(HK_ARRAY, sliced)
348 }
349}
350
351pub extern "C" fn jit_range(start_bits: u64, end_bits: u64) -> u64 {
353 let start = if is_number(start_bits) {
354 unbox_number(start_bits) as i64
355 } else {
356 0
357 };
358 let end = if is_number(end_bits) {
359 unbox_number(end_bits) as i64
360 } else {
361 0
362 };
363
364 if end > start && (end - start) <= 10000 {
365 let range: Vec<u64> = (start..end).map(|i| box_number(i as f64)).collect();
366 jit_box(HK_ARRAY, JitArray::from_vec(range))
367 } else {
368 jit_box(HK_ARRAY, JitArray::new())
369 }
370}
371
372#[unsafe(no_mangle)]
375pub extern "C" fn jit_array_filled(size_bits: u64, value_bits: u64) -> u64 {
376 if !is_number(size_bits) {
377 return TAG_NULL;
378 }
379
380 let size = unbox_number(size_bits) as usize;
381 if size > 100_000_000 {
383 return TAG_NULL;
384 }
385
386 let mut elements = vec![value_bits; size];
387 let len = elements.len();
388 let cap = elements.len();
389 let data = elements.as_mut_ptr();
390 std::mem::forget(elements);
391
392 let mut typed_data: *mut u64 = std::ptr::null_mut();
393 let mut element_kind = crate::jit_array::ArrayElementKind::Untyped as u8;
394 let mut typed_storage_kind = crate::jit_array::ArrayElementKind::Untyped as u8;
395
396 if value_bits == TAG_BOOL_TRUE || value_bits == TAG_BOOL_FALSE {
397 let byte_len = size.div_ceil(8);
398 let mut bytes = if value_bits == TAG_BOOL_TRUE {
399 vec![0xFFu8; byte_len]
400 } else {
401 vec![0u8; byte_len]
402 };
403 if value_bits == TAG_BOOL_TRUE && !bytes.is_empty() {
404 let rem = size & 7;
405 if rem != 0 {
406 let tail_mask = (1u8 << rem) - 1;
407 if let Some(last) = bytes.last_mut() {
408 *last = tail_mask;
409 }
410 }
411 }
412 typed_data = bytes.as_mut_ptr() as *mut u64;
413 std::mem::forget(bytes);
414 element_kind = crate::jit_array::ArrayElementKind::Bool as u8;
415 typed_storage_kind = crate::jit_array::ArrayElementKind::Bool as u8;
416 }
417
418 let arr = JitArray {
420 data,
421 len: len as u64,
422 cap: cap as u64,
423 typed_data,
424 typed_storage_kind,
425 element_kind,
426 _padding: [0; 6],
427 };
428 jit_box(HK_ARRAY, arr)
429}
430
431#[unsafe(no_mangle)]
434pub extern "C" fn jit_array_reverse(arr_bits: u64) -> u64 {
435 if !is_heap_kind(arr_bits, HK_ARRAY) {
436 return TAG_NULL;
437 }
438 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
439 let mut reversed = arr.as_slice().to_vec();
440 reversed.reverse();
441 jit_box(HK_ARRAY, JitArray::from_vec(reversed))
442}
443
444#[unsafe(no_mangle)]
448pub extern "C" fn jit_array_push_element(arr_bits: u64, element_bits: u64) -> u64 {
449 if !is_heap_kind(arr_bits, HK_ARRAY) {
450 return TAG_NULL;
451 }
452 let arr = unsafe { jit_unbox::<JitArray>(arr_bits) };
453 let mut elements = arr.as_slice().to_vec();
454 elements.push(element_bits);
455 jit_box(HK_ARRAY, JitArray::from_vec(elements))
456}
457
458#[unsafe(no_mangle)]
461pub extern "C" fn jit_hof_array_alloc(capacity: u64) -> u64 {
462 let cap = capacity as usize;
463 if cap > 100_000_000 {
464 return jit_box(HK_ARRAY, JitArray::new());
465 }
466 jit_box(HK_ARRAY, JitArray::with_capacity(cap))
467}
468
469#[unsafe(no_mangle)]
473pub extern "C" fn jit_hof_array_push(array_bits: u64, value_bits: u64) -> u64 {
474 if !is_heap_kind(array_bits, HK_ARRAY) {
475 return array_bits;
476 }
477 let arr = unsafe { jit_unbox_mut::<JitArray>(array_bits) };
478 arr.push(value_bits);
479 array_bits
480}
481
482pub extern "C" fn jit_make_range(start_bits: u64, end_bits: u64) -> u64 {
485 use super::super::context::JITRange;
486
487 let range = JITRange::new(start_bits, end_bits);
488 JITRange::box_range(range)
489}