@@ -42,6 +42,8 @@ public class EliminateGenerics {
4242 private final Set <Element > specializedCallSites = Collections .newSetFromMap (new IdentityHashMap <>());
4343 private final Set <Element > recordedErasedStaticAllocations =
4444 Collections .newSetFromMap (new IdentityHashMap <>());
45+ private final Set <ImFunction > scannedFixedStaticCallees =
46+ Collections .newSetFromMap (new IdentityHashMap <>());
4547 private final Table <ImFunction , GenericTypes , ImFunction > specializedFunctions = HashBasedTable .create ();
4648 /** The class each function was moved out of, for calls which name their target without a receiver. */
4749 private final Map <ImFunction , ImClass > functionOwners = new IdentityHashMap <>();
@@ -486,26 +488,25 @@ private void collectGenericNewUse(ImFunctionCall call) {
486488 // The generic callee remains erased, so its body is skipped by collectGenericNewRoots.
487489 // Fixed concrete allocations inside it still name real per-instantiation statics and
488490 // must be registered without cloning the caller for unrelated type arguments.
489- recordFixedErasedStaticAllocations (call .getFunc (),
490- Collections .newSetFromMap (new IdentityHashMap <>()));
491+ recordFixedErasedStaticAllocations (call .getFunc ());
491492 }
492493 }
493494
494- private void recordFixedErasedStaticAllocations (ImFunction function ,
495- Set <ImFunction > visited ) {
496- if (!visited .add (function )) {
495+ private void recordFixedErasedStaticAllocations (ImFunction function ) {
496+ if (!scannedFixedStaticCallees .add (function )) {
497497 return ;
498498 }
499499 function .accept (new Element .DefaultVisitor () {
500500 @ Override
501501 public void visit (ImFunctionCall nestedCall ) {
502502 super .visit (nestedCall );
503- recordErasedConstructorAllocation (nestedCall );
504- if (!nestedCall .getTypeArguments ().isEmpty ()
505- && !typeArgumentsContainTypeVariable (nestedCall .getTypeArguments ())
506- && !(nestedCall .getFunc ().getTrace () instanceof ConstructorDef )) {
507- recordFixedErasedStaticAllocations (nestedCall .getFunc (), visited );
508- }
503+ collectGenericNewUse (nestedCall );
504+ }
505+
506+ @ Override
507+ public void visit (ImMethodCall nestedCall ) {
508+ super .visit (nestedCall );
509+ collectGenericNewUse (nestedCall );
509510 }
510511 });
511512 }
@@ -744,21 +745,25 @@ private void collectGenericNewUse(ImMethodCall call) {
744745 specializedCallSites .add (call );
745746 return ;
746747 }
747- if (!shouldSpecializeTupleArguments (call .getTypeArguments ())
748- && !methodNeedsSpecialization (method ,
749- Collections .newSetFromMap (new IdentityHashMap <>()),
750- Collections .newSetFromMap (new IdentityHashMap <>()))) {
751- return ;
752- }
753748 if (isMissingClassTypeArguments (call , method )) {
754749 addMemberTypeArguments (call , method .attrClass ());
755750 }
756751 if (typeArgumentsContainTypeVariable (call .getTypeArguments ())) {
757- // The receiver's declared type is still generic, which happens when the method is
758- // called straight on a freshly constructed value. The construction states the
759- // instantiation, so take the arguments from it.
752+ // A call directly on a fresh generic construction gets its concrete class arguments
753+ // from that construction before deciding between specialization and fixed-body scan.
760754 useConstructionTypeArguments (call );
761755 }
756+ boolean needsSpecialization = methodNeedsSpecialization (method ,
757+ Collections .newSetFromMap (new IdentityHashMap <>()),
758+ Collections .newSetFromMap (new IdentityHashMap <>()));
759+ if (!shouldSpecializeTupleArguments (call .getTypeArguments ()) && !needsSpecialization ) {
760+ if (!call .getTypeArguments ().isEmpty ()
761+ && !typeArgumentsContainTypeVariable (call .getTypeArguments ())
762+ && method .getImplementation () != null ) {
763+ recordFixedErasedStaticAllocations (method .getImplementation ());
764+ }
765+ return ;
766+ }
762767 if (!call .getTypeArguments ().isEmpty ()
763768 && !typeArgumentsContainTypeVariable (call .getTypeArguments ())) {
764769 genericsUses .add (new GenericMethodCall (call ));
@@ -876,9 +881,10 @@ public void visit(ImAlloc alloc) {
876881
877882 @ Override
878883 public void visit (ImFunctionCall call ) {
884+ boolean dependsOnTypeVariable = typeArgumentsContainTypeVariable (call .getTypeArguments ());
879885 if (constructsClassOwningGenericGlobals (function , call )
880- || translator .isGenericNewMarker (call .getFunc ())
881- || functionNeedsSpecialization (call .getFunc (), visitedFunctions , visitedMethods )) {
886+ || ( dependsOnTypeVariable && ( translator .isGenericNewMarker (call .getFunc ())
887+ || functionNeedsSpecialization (call .getFunc (), visitedFunctions , visitedMethods )))) {
882888 found [0 ] = true ;
883889 return ;
884890 }
@@ -887,7 +893,8 @@ public void visit(ImFunctionCall call) {
887893
888894 @ Override
889895 public void visit (ImMethodCall call ) {
890- if (methodNeedsSpecialization (call .getMethod (), visitedFunctions , visitedMethods )) {
896+ if (typeArgumentsContainTypeVariable (call .getTypeArguments ())
897+ && methodNeedsSpecialization (call .getMethod (), visitedFunctions , visitedMethods )) {
891898 found [0 ] = true ;
892899 return ;
893900 }
0 commit comments