Skip to main content

shape_jit/ffi/
references.rs

1// Heap allocation audit (PR-9 V8 Gap Closure):
2//   Category A (NaN-boxed returns): 0 sites
3//   Category B (intermediate/consumed): 0 sites
4//   Category C (heap islands): 0 sites
5//   Notes: No jit_box calls. Mutates existing array in-place via jit_unbox_mut.
6//!
7//! Reference FFI Functions for JIT
8//!
9//! Provides the SetIndexRef operation which mutates an array element
10//! in-place through a reference pointer. This is called from JIT code
11//! when a `&array[index] = value` pattern is compiled.
12
13use super::super::jit_array::JitArray;
14use super::super::nan_boxing::*;
15
16/// Set an array element through a reference pointer.
17///
18/// # Arguments
19/// * `ref_ptr` - Pointer to the memory slot holding the NaN-boxed array value
20/// * `index` - NaN-boxed index value (f64 representing integer index)
21/// * `value` - NaN-boxed value to store at arr[index]
22///
23/// # Safety
24/// `ref_ptr` must point to a valid u64 memory location containing a NaN-boxed array.
25#[unsafe(no_mangle)]
26pub extern "C" fn jit_set_index_ref(ref_ptr: *mut u64, index: u64, value: u64) {
27    if ref_ptr.is_null() {
28        return;
29    }
30
31    let array_bits = unsafe { *ref_ptr };
32
33    // Verify it's an array using the unified heap kind check
34    if !is_heap_kind(array_bits, HK_ARRAY) {
35        return;
36    }
37
38    let arr = unsafe { jit_unbox_mut::<JitArray>(array_bits) };
39
40    // Convert index from NaN-boxed f64 to integer
41    let idx = if is_number(index) {
42        unbox_number(index) as i64
43    } else {
44        return;
45    };
46
47    let len = arr.len() as i64;
48    let actual = if idx < 0 { len + idx } else { idx };
49
50    if actual < 0 || actual as usize >= arr.len() {
51        // Out of bounds - extend array if positive index
52        if actual >= 0 {
53            let target = actual as usize;
54            while arr.len() <= target {
55                arr.push(TAG_NULL);
56            }
57            super::gc::jit_write_barrier(TAG_NULL, value);
58            arr.set_boxed(target, value);
59        }
60        return;
61    }
62
63    super::gc::jit_write_barrier(arr[actual as usize], value);
64    arr.set_boxed(actual as usize, value);
65}