ffi M4.0c: -dealloc frees state through captured __sx_allocator
The synthesized -dealloc IMP now loads `state->__sx_allocator` (the
slot captured at +alloc time by M4.0a + M4.0b) and dispatches
`allocator.dealloc(state)` through the inline-protocol fn-ptr at
slot 2. Old behaviour was `free(state)` — went straight to libc,
ignoring whatever allocator the instance was constructed with.
After this commit, the per-instance allocator design from M1.2 A.5
is finally end-to-end correct:
push Context.{ allocator = arena } {
f := SxFoo.alloc(); ← arena.alloc(STATE_SIZE) + capture
// ... use f ...
}
// refcount → 0 ⇒ -dealloc:
// load state->__sx_allocator = arena
// arena.dealloc(state) ← same allocator round-trips
TrackingAllocator now sees the alloc/dealloc pair; the deferred M1.2
A.5 work is done. Closes the loop on M4.0.
The dealloc IMP passes `__sx_default_context` as the implicit __sx_ctx
when invoking the dealloc fn-ptr — the IMP itself has no caller-side
ctx (it's called by Apple's runtime at refcount-zero), and the
default GPA is the right baseline for any nested allocations the
dealloc body might perform.
Each compiler-internal lookup that "can't fail" (Context type,
__sx_default_context global) emits a loud diagnostic instead of
silent fall-through, per the silent-error budget.
184/184 example tests pass; chess on iOS-sim green.
This commit is contained in:
@@ -824,11 +824,15 @@ define void @__SxFoo_dealloc_imp(ptr %0, ptr %1) #0 {
|
||||
entry:
|
||||
%load = load ptr, ptr @__SxFoo_state_ivar, align 8
|
||||
%call = call ptr @object_getIvar(ptr %0, ptr %load)
|
||||
call void @free(ptr %call)
|
||||
%gep = getelementptr inbounds { { ptr, ptr, ptr }, i32 }, ptr %call, i32 0, i32 0
|
||||
%loadN = load { ptr, ptr, ptr }, ptr %gep, align 8
|
||||
%sg = extractvalue { ptr, ptr, ptr } %loadN, 0
|
||||
%sgN = extractvalue { ptr, ptr, ptr } %loadN, 2
|
||||
call void %sgN(ptr @__sx_default_context, ptr %sg, ptr %call)
|
||||
call void @object_setIvar(ptr %0, ptr %load, ptr null)
|
||||
%alloca = alloca { ptr, ptr }, align 8
|
||||
%gep = getelementptr inbounds { ptr, ptr }, ptr %alloca, i32 0, i32 0
|
||||
store ptr %0, ptr %gep, align 8
|
||||
%gepN = getelementptr inbounds { ptr, ptr }, ptr %alloca, i32 0, i32 0
|
||||
store ptr %0, ptr %gepN, align 8
|
||||
%loadN = load ptr, ptr @__SxFoo_class, align 8
|
||||
%gepN = getelementptr inbounds { ptr, ptr }, ptr %alloca, i32 0, i32 1
|
||||
store ptr %loadN, ptr %gepN, align 8
|
||||
|
||||
Reference in New Issue
Block a user