Skip to content

feat: Add per-class identityMode via @JS macro parameter#3

Merged
krodak merged 1 commit intomainfrom
feat/per-class-identity-mode
Apr 21, 2026
Merged

feat: Add per-class identityMode via @JS macro parameter#3
krodak merged 1 commit intomainfrom
feat/per-class-identity-mode

Conversation

@krodak
Copy link
Copy Markdown
Collaborator

@krodak krodak commented Apr 21, 2026

Overview

Add identityMode: Bool parameter to the @JS macro, enabling per-class opt-in to pointer identity caching. Identity is resolved entirely at codegen time - no runtime option.

@JS(identityMode: true)
class BuildingBridged { ... }  // identity caching enabled

@JS
class TemporaryObject { ... }  // no caching (default)

@JS(identityMode: false)
class ExplicitlyUncached { ... }  // explicitly opted out, even if config says pointer

Resolution: @JS(identityMode: true/false) > bridge-js.config.json > default (off).

The runtime options.identityMode override has been removed. Benchmarking both modes requires separate builds. This keeps the generated code simple: each class's __construct either passes __identityCache or null to __wrap, no runtime branching.

Links

What changed

  • Macros.swift - Added identityMode: Bool = false parameter to @JS macro.
  • BridgeJSSkeleton.swift - Added identityMode: Bool? to ExportedClass.
  • SwiftToSkeleton.swift - Added extractIdentityMode parser, same pattern as extractNamespace/extractEnumStyle.
  • BridgeJSLink.swift - Per-class codegen: classes with identity get __identityCache passed to __wrap, others get null. Removed global shouldUseIdentityMap, identityMode runtime variable, and hasIdentitySupport check. Added shouldUseIdentityCache(for:) helper.
  • instantiate.d.ts / index.js / index.d.ts - Removed identityMode from InstantiateOptions and Options types. Removed runtime pass-through in node/browser init.
  • IdentityModeClass.swift - Test input with @JS(identityMode: true), plain @JS, and @JS(identityMode: false).
  • BridgeJSLinkTests.swift - Tests: per-class annotation parsing, config "pointer" + class override, skeleton-level assertions.
  • All snapshot files - Updated with simplified per-class codegen.

Tested

  • swift test --package-path ./Plugins/BridgeJS - 107 tests pass
  • ./Utilities/format.swift - clean
  • ./Utilities/bridge-js-generate.sh - generated files up to date

@krodak krodak force-pushed the feat/per-class-identity-mode branch 3 times, most recently from f898b82 to f290715 Compare April 21, 2026 14:09
@krodak
Copy link
Copy Markdown
Collaborator Author

krodak commented Apr 21, 2026

Benchmark Results (PR #3 vs PR #2)

Release build, adaptive sampling with IQR outlier removal. arm64-apple-macosx26.0, Node.js v22.22.0.

Moving identity mode from runtime flag to codegen-time decision improved performance across the board. V8 JIT optimizes better when __construct passes the cache directly (no runtime conditional) and __wrap checks a parameter instead of a global variable.

Scenario No identity PR #2 pointer PR #3 pointer vs baseline
passBothWaysRoundtrip (1M) 245 ms 64 ms 48 ms 5.1x faster
swiftConsumesSameObject (1M) 21 ms 30 ms 11 ms 1.9x faster
churnObjects (100k) 133 ms 117 ms 111 ms 1.2x faster
swiftCreatesObject (1M) 696 ms 2147 ms 2216 ms 3.2x slower

swiftConsumesSameObject flipped from 1.4x slower (PR #2) to 1.9x faster (PR #3) because the non-identity __wrap path no longer checks a global flag.

Memory unchanged: 271 MiB → 41 MiB peak heap (6.6x), 271 MiB → 21 MiB retained (12.9x).

@krodak krodak force-pushed the feat/per-class-identity-mode branch from f290715 to b6b052f Compare April 21, 2026 16:47
Add identityMode: Bool parameter to @js macro. When set to true on a class,
that class uses pointer identity caching. When false or not set, the class
uses the bridge-js.config.json default.

Identity is resolved entirely at codegen time - no runtime option. Classes
with identity mode get static __identityCache passed to __wrap. Classes
without it pass null. No runtime branching in __construct.

Resolution: @js(identityMode: true/false) > bridge-js.config.json > default (off).
@krodak krodak force-pushed the feat/per-class-identity-mode branch from b6b052f to b47bd9c Compare April 21, 2026 18:00
@krodak krodak merged commit 34c5d0d into main Apr 21, 2026
9 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant