RFR: 8263452: Javac slow compilation due to algorithmic complexity

Jan Lahoda jlahoda at openjdk.java.net
Thu Apr 29 09:48:53 UTC 2021


On Fri, 16 Apr 2021 08:49:57 GMT, Joel Borggrén-Franck <jfranck at openjdk.org> wrote:

>> Consider a class that extends its enclosing class. There are a few places in javac where javac does some actions for the supertype and enclosing class, doing these actions twice in this scenario. If the enclosing class also extends its enclosing class, and its enclosing type does as well, etc., these checks are done for the enclosing classes, and the number of actions grows exponentially.
>> 
>> Even though this seems like a rare case, we can improve javac by avoiding redoing the checks that were already done. There are two parts:
>> -`Check.checkNonCyclicDecl` will not record the hierarchy is acyclic if a supertype uses a full-qualified name, as it considers the hierarchy to be "partial", as it only considers hierarchies non-partial if all super AST nodes are filled with class symbols. The proposed solution is to not mark the hierarchy as partial if a part of the FQN is attributed as a package symbol. As a side tweak, the cycle detector is now proposed to be a Set rather than a List, to improve lookup times.
>> -in `attribClass`, first the superclass and enclosing class of the current class are attributed, but these are done even if already done, and in the case of the class hierarchy described here these no-op attributions can be done very many times. The proposed fix is to do the attribution of super/enclosing only once.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 5096:
> 
>> 5094:             // First, attribute superclass.
>> 5095:             if (st.hasTag(CLASS))
>> 5096:                 attribClass((ClassSymbol)st.tsym);
> 
> This looks like a guarding against a special case of attributing something twice. Did you consider pushing this into attribClass instead so that calling it a second time is a no-op?

@jbf, sorry, I missed you comment.

I was thinking of using `Flags.UNATTRIBUTED` and skipping this whole method. I was a bit worried about a case where a class from source has a supertype from classfile (which never has `UNATTRIBUTED`), which has a supertype from source - by using `UNATTRIBUTED`, we could get to a state where this supertype attribution wouldn't attribute the super-supertype from source. Using another flag is an attempt to avoid this issue completely - the cost is using one more flag out of a limited pool of flags, of course.

-------------

PR: https://git.openjdk.java.net/jdk/pull/3523


More information about the compiler-dev mailing list