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.
This commit is contained in:
30
examples/ffi-jni-call-03-methodid-sharing.sx
Normal file
30
examples/ffi-jni-call-03-methodid-sharing.sx
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user