Skip to main content

shape_jit/ffi/object/
object_ops.rs

1// Heap allocation audit (PR-9 V8 Gap Closure):
2//   Category A (NaN-boxed returns): 2 sites
3//     jit_box(HK_JIT_OBJECT, ...) — jit_new_object, jit_object_rest
4//   Category B (intermediate/consumed): 0 sites
5//   Category C (heap islands): 2 sites (jit_new_object, jit_object_rest)
6//!
7//! Object Creation and Manipulation Operations
8//!
9//! Functions for creating objects, setting properties, and object_rest.
10
11use std::collections::HashMap;
12
13use super::super::super::context::JITContext;
14// super::super::super::jit_array::JitArray removed — see jit_array.rs
15// SURFACE comment. The HK_ARRAY arms of `jit_set_prop` and `jit_object_rest`
16// now route to surface-and-stop per ADR-006 §2.7.4 / W10 jit-playbook §5.
17use crate::ffi::jit_kinds::*;
18use crate::ffi::value_ffi::*;
19
20// ============================================================================
21// Object Creation and Manipulation
22// ============================================================================
23
24/// Create a new object from key-value pairs on stack
25#[inline(always)]
26pub extern "C" fn jit_new_object(ctx: *mut JITContext, field_count: usize) -> u64 {
27    unsafe {
28        if ctx.is_null() || field_count > 64 {
29            return TAG_NULL;
30        }
31
32        let ctx_ref = &mut *ctx;
33
34        // Check both bounds
35        if ctx_ref.stack_ptr < field_count * 2 || ctx_ref.stack_ptr > 512 {
36            return TAG_NULL;
37        }
38
39        // Pop field_count * 2 values (key, value pairs)
40        // AUDIT(C6): heap island — values inserted into this HashMap may themselves
41        // be JitAlloc pointers (strings, arrays, nested objects). These inner
42        // allocations escape into the HashMap without GC tracking.
43        // When GC feature enabled, route through gc_allocator.
44        let mut map = HashMap::new();
45        for _ in 0..field_count {
46            // Pop value, then key
47            ctx_ref.stack_ptr -= 1;
48            let value = ctx_ref.stack[ctx_ref.stack_ptr];
49            ctx_ref.stack_ptr -= 1;
50            let key_bits = ctx_ref.stack[ctx_ref.stack_ptr];
51
52            // Key should be a string
53            if is_heap_kind(key_bits, HK_STRING) {
54                let key = unbox_string(key_bits).to_string();
55                map.insert(key, value);
56            }
57        }
58
59        unified_box(HK_JIT_OBJECT, map)
60    }
61}
62
63/// Set property on object or array (returns the modified container)
64#[inline(always)]
65pub extern "C" fn jit_set_prop(obj_bits: u64, key_bits: u64, value_bits: u64) -> u64 {
66    unsafe {
67        match heap_kind(obj_bits) {
68            Some(HK_JIT_OBJECT) => {
69                // Object with string key
70                if !is_heap_kind(key_bits, HK_STRING) {
71                    return obj_bits;
72                }
73                let obj = unified_unbox_mut::<HashMap<String, u64>>(obj_bits);
74                let key = unbox_string(key_bits).to_string();
75                let old_bits = obj.get(&key).copied().unwrap_or(TAG_NULL);
76                super::super::gc::jit_write_barrier(old_bits, value_bits);
77                obj.insert(key, value_bits);
78                obj_bits
79            }
80            Some(HK_ARRAY) => {
81                // SURFACE (W10 jit-playbook §5 / ADR-006 §2.7.4): the
82                // numeric-index, range-splice, and per-element write
83                // paths all walked the deleted `JitArray` heap layout
84                // (`from_heap_bits_mut` / `set_boxed` / `from_vec`).
85                // Kinded rebuild reads the receiver as
86                // `Arc<TypedArrayData>` per-element-kind arm
87                // (§2.7.6/Q8) and dispatches per the JIT-stamped
88                // element kind (§2.7.5). Until then, leave the
89                // container untouched and signal failure to the
90                // caller via the unmodified `obj_bits` handle.
91                let _ = (key_bits, value_bits);
92                todo!(
93                    "phase-2c §2.7.4 / W10 jit-playbook §5: JitArray \
94                     rebuild — jit_set_prop (HK_ARRAY arm). The deleted \
95                     UnifiedArray layout blocks index/range writes; \
96                     kinded rebuild reads Arc<TypedArrayData> per \
97                     ADR-006 §2.7.6/Q8."
98                )
99            }
100            _ => obj_bits,
101        }
102    }
103}
104
105/// ObjectRest: create a new object excluding specified keys
106///
107/// SURFACE (W10 jit-playbook §5 / ADR-006 §2.7.4): the keys argument
108/// was decoded via the deleted `JitArray::from_heap_bits` walk. Kinded
109/// rebuild reads `Arc<TypedArrayData>` of `NativeKind::String` element
110/// kind per §2.7.6/Q8 and threads each element's kind through the
111/// exclude-set construction.
112#[inline(always)]
113pub extern "C" fn jit_object_rest(_obj_bits: u64, _keys_bits: u64) -> u64 {
114    todo!(
115        "phase-2c §2.7.4 / W10 jit-playbook §5: JitArray rebuild — \
116         jit_object_rest. The keys array walk decoded the deleted \
117         UnifiedArray layout; kinded rebuild reads Arc<TypedArrayData> \
118         of Arc<String> elements per ADR-006 §2.7.6/Q8."
119    )
120}