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}