refactor(backend): extract JNI slot cache into ffi_ctors.zig (A7.3 slice 2a)
Move getOrCreateJniSlots (the cls/methodid slot-cache builder) out of emit_llvm.zig into the FfiCtors backend *LLVMEmitter facade. Behavior-preserving — self.* -> self.e.* only. - FfiCtors gains getOrCreateJniSlots (pub). The jni_slots cache + mangleJniKey stay on LLVMEmitter; mangleJniKey is widened to pub (the facade calls it back, like lazyDeclareCRuntime/emitPrivateCString), and JniSlotPair is widened to pub (the facade returns it; the call site consumes it). 1 call site routed via ffiCtors(). - emitJniConstructor intentionally NOT moved in this slice: it is emission-heavy (resolveRef/mapRef/coerceArg/getRefIRType/extractSlicePtr/loadJniFn/ emitCStringGlobal — 100+ internal callers for the first two), so relocating it would pub-expose the emitter's core value-emission machinery. Consistent with A7.2 keeping emitFieldValueGet in emit_llvm.zig. Pending an explicit decision. Gate: zig build, zig build test, bash tests/run_examples.sh -> 361/0 (JNI anchors 1402/1408/1418/1425 green, no churn).
This commit is contained in:
@@ -4,6 +4,7 @@ const c = llvm.c;
|
||||
const emit = @import("../../ir/emit_llvm.zig");
|
||||
|
||||
const LLVMEmitter = emit.LLVMEmitter;
|
||||
const JniSlotPair = LLVMEmitter.JniSlotPair;
|
||||
|
||||
/// Obj-C / JNI runtime-constructor emission (architecture phase A7.3), extracted
|
||||
/// from `LLVMEmitter`. A backend `*LLVMEmitter` facade (field `e`): it builds the
|
||||
@@ -473,4 +474,36 @@ pub const FfiCtors = struct {
|
||||
|
||||
_ = i32_ty;
|
||||
}
|
||||
|
||||
/// Return `{cls_slot, mid_slot}` global pair for the
|
||||
/// `(name, sig)` literal — created on first lookup, shared across
|
||||
/// later `#jni_call` sites with the same literal pair. Both
|
||||
/// slots are zero-initialized `ptr`; the call-site lowering does
|
||||
/// lazy population on first dispatch. The cache (`jni_slots`) +
|
||||
/// `mangleJniKey` stay on `LLVMEmitter`.
|
||||
pub fn getOrCreateJniSlots(self: FfiCtors, name: []const u8, sig: []const u8) JniSlotPair {
|
||||
// Compose the key from name + a separator + sig. The separator
|
||||
// is a byte that can't appear in a JNI method name or signature
|
||||
// (NUL), so the same key never collides across distinct pairs.
|
||||
const key = std.fmt.allocPrint(self.e.alloc, "{s}\x00{s}", .{ name, sig }) catch unreachable;
|
||||
if (self.e.jni_slots.get(key)) |existing| {
|
||||
self.e.alloc.free(key);
|
||||
return existing;
|
||||
}
|
||||
const mangled = self.e.mangleJniKey(name, sig);
|
||||
defer self.e.alloc.free(mangled);
|
||||
const cls_name = std.fmt.allocPrintSentinel(self.e.alloc, "SX_JNI_CLS_{s}", .{mangled}, 0) catch unreachable;
|
||||
defer self.e.alloc.free(cls_name);
|
||||
const mid_name = std.fmt.allocPrintSentinel(self.e.alloc, "SX_JNI_MID_{s}", .{mangled}, 0) catch unreachable;
|
||||
defer self.e.alloc.free(mid_name);
|
||||
const cls_slot = c.LLVMAddGlobal(self.e.llvm_module, self.e.cached_ptr, cls_name.ptr);
|
||||
c.LLVMSetLinkage(cls_slot, c.LLVMInternalLinkage);
|
||||
c.LLVMSetInitializer(cls_slot, c.LLVMConstNull(self.e.cached_ptr));
|
||||
const mid_slot = c.LLVMAddGlobal(self.e.llvm_module, self.e.cached_ptr, mid_name.ptr);
|
||||
c.LLVMSetLinkage(mid_slot, c.LLVMInternalLinkage);
|
||||
c.LLVMSetInitializer(mid_slot, c.LLVMConstNull(self.e.cached_ptr));
|
||||
const pair = JniSlotPair{ .cls_slot = cls_slot, .mid_slot = mid_slot };
|
||||
self.e.jni_slots.put(key, pair) catch unreachable;
|
||||
return pair;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user