@@ -955,6 +955,8 @@ private boolean isGlobalInitStmt(ImSet s, ImVar v) {
955955 }
956956
957957 private void collectGenericUsages (Element element ) {
958+ // Cache expensive recursive submethod checks within this traversal.
959+ Map <ImMethod , Boolean > hasGenericSubmethodCache = new IdentityHashMap <>();
958960 element .accept (new Element .DefaultVisitor () {
959961 @ Override
960962 public void visit (ImFunctionCall f ) {
@@ -969,10 +971,19 @@ public void visit(ImMethodCall mc) {
969971 super .visit (mc );
970972 ImMethod method = mc .getMethod ();
971973 boolean hasTypeArgs = !mc .getTypeArguments ().isEmpty ();
972- // Interface/base dispatch methods can be non-generic but still require specialization
973- // when they dispatch to generic implementors.
974- boolean needsDispatchSpecialization =
975- methodImplementationIsGeneric (method ) || hasGenericSubmethodImplementation (method );
974+ boolean needsDispatchSpecialization = false ;
975+ // If type args are present, specialization is unconditional, so avoid extra checks.
976+ if (!hasTypeArgs ) {
977+ // Interface/base dispatch methods can be non-generic but still require specialization
978+ // when they dispatch to generic implementors.
979+ needsDispatchSpecialization = methodImplementationIsGeneric (method );
980+ if (!needsDispatchSpecialization ) {
981+ needsDispatchSpecialization = hasGenericSubmethodCache .computeIfAbsent (
982+ method ,
983+ EliminateGenerics .this ::hasGenericSubmethodImplementation
984+ );
985+ }
986+ }
976987 if (hasTypeArgs || needsDispatchSpecialization ) {
977988 dbg ("COLLECT GenericMethodCall: method=" + mc .getMethod ().getName () + " " + id (mc .getMethod ())
978989 + " impl=" + (mc .getMethod ().getImplementation () == null ? "null" : (mc .getMethod ().getImplementation ().getName () + " " + id (mc .getMethod ().getImplementation ())))
0 commit comments