@@ -78,18 +78,31 @@ private LuaNativeLowering() {}
7878 * can inline and eliminate the generated wrappers.
7979 */
8080 public static void transform (ImProg prog ) {
81+ // Pre-scan: find which BJ functions are actually called, so we only create stubs/wrappers
82+ // for reachable functions. Creating wrappers for all BJ functions in the IM (common.j has
83+ // hundreds of them) would be extremely memory-intensive.
84+ Set <ImFunction > calledBjFuncs = new LinkedHashSet <>();
85+ prog .accept (new Element .DefaultVisitor () {
86+ @ Override
87+ public void visit (ImFunctionCall call ) {
88+ super .visit (call );
89+ if (call .getFunc ().isBj ()) {
90+ calledBjFuncs .add (call .getFunc ());
91+ }
92+ }
93+ });
94+
95+ if (calledBjFuncs .isEmpty ()) {
96+ return ;
97+ }
98+
8199 // Maps original BJ function → replacement (either a IS_NATIVE stub or a nil-safety wrapper)
82100 Map <ImFunction , ImFunction > replacements = new LinkedHashMap <>();
83101 // Nil-safety wrappers are collected separately and added to prog AFTER the traversal,
84102 // so the traversal does not visit their bodies and replace their internal BJ delegate calls.
85103 List <ImFunction > deferredWrappers = new ArrayList <>();
86104
87- // Snapshot to avoid ConcurrentModificationException when createNativeStub adds to prog.getFunctions()
88- List <ImFunction > snapshot = new ArrayList <>(prog .getFunctions ());
89- for (ImFunction f : snapshot ) {
90- if (!f .isBj ()) {
91- continue ;
92- }
105+ for (ImFunction f : calledBjFuncs ) {
93106 String name = f .getName ();
94107
95108 if ("GetHandleId" .equals (name )) {
0 commit comments