Files
sx/examples/ffi-jni-call-03-methodid-sharing.sx
agra 13018ef3b4 ffi 1.16: lock in pre-caching #jni_call IR shape
Adds `examples/ffi-jni-call-03-methodid-sharing.sx` with two
`#jni_call` sites against the same (class, method, sig). Today each
site emits its own `GetObjectClass` + `GetMethodID` + `Call<Type>Method`
sequence (8 vtable indirections total for the two-call test); 1.17
will collapse the two `GetMethodID` calls into a single cached
`jmethodID` static slot populated at module init, mirroring the
`OBJC_SELECTOR_REFERENCES_*` shape that 1.5 introduced for `#objc_call`.

Runtime is a no-op — `unused_jni` is reachable through a
runtime-readable `g_should_call` global that stays false, so the JNI
dereferences never execute. A plain `if false` would get
constant-folded, taking the function definition out of the IR
entirely; the global keeps both the function and its body present
for the IR-snapshot harness.

IR snapshot at `tests/expected/ffi-jni-call-03-methodid-sharing.ir`
locks the pre-caching shape. The next commit (1.17) updates it to the
collapsed shape.

113/113 host tests pass.
2026-05-19 21:41:26 +03:00

31 lines
1.0 KiB
Plaintext

// Phase 1 step 1.16 (PLAN-FFI.md): two `#jni_call` sites against the
// same (class, method, sig) tuple. Today each site emits its own
// `GetObjectClass` + `GetMethodID` call (no caching yet); after 1.17
// the lowering collapses to one cached `jmethodID` per unique
// (class, method, sig).
//
// Runtime: unreachable. The JNI dispatch is all indirect through
// `*env` — no external symbol declarations — so the IR loads cleanly
// into the host JIT, and the dereferences never execute because the
// guarding `g_should_call` global stays false. A plain `if false`
// would get constant-folded, taking the `unused_jni` body out of the
// IR with it; the runtime-readable global keeps the call alive so
// the JNI lowering is visible to the IR snapshot.
#import "modules/std.sx";
g_should_call : bool = false;
unused_jni :: (env: *void, target: *void) {
#jni_call(void)(env, target, "noop", "()V");
#jni_call(void)(env, target, "noop", "()V");
}
main :: () -> s32 {
if g_should_call {
unused_jni(null, null);
}
print("ok\n");
0;
}