From a18d9d84cd92b0b7e7c3c83efab1d81773e3a87c Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 9 Sep 2024 05:34:09 +0000 Subject: [PATCH] 8326616: tools/javac/patterns/Exhaustiveness.java intermittently Timeout signalled after 480 seconds Reviewed-by: abimpoudis --- .../com/sun/tools/javac/comp/Flow.java | 93 ++++++++----------- test/langtools/ProblemList.txt | 1 - 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 792b5ca2346..29ab8435ada 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -827,30 +827,33 @@ public class Flow { } } Set patterns = patternSet; - boolean genericPatternsExpanded = false; + boolean useHashes = true; try { boolean repeat = true; while (repeat) { Set updatedPatterns; updatedPatterns = reduceBindingPatterns(selector.type, patterns); - updatedPatterns = reduceNestedPatterns(updatedPatterns); + updatedPatterns = reduceNestedPatterns(updatedPatterns, useHashes); updatedPatterns = reduceRecordPatterns(updatedPatterns); updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); repeat = !updatedPatterns.equals(patterns); if (checkCovered(selector.type, patterns)) { return true; } - if (!repeat && !genericPatternsExpanded) { + if (!repeat) { //there may be situation like: - //class B extends S1, S2 + //class B permits S1, S2 //patterns: R(S1, B), R(S2, S2) - //this should be joined to R(B, S2), + //this might be joined to R(B, S2), as B could be rewritten to S2 //but hashing in reduceNestedPatterns will not allow that - //attempt to once expand all types to their transitive permitted types, - //on all depth of nesting: - updatedPatterns = expandGenericPatterns(updatedPatterns); - genericPatternsExpanded = true; - repeat = !updatedPatterns.equals(patterns); + //disable the use of hashing, and use subtyping in + //reduceNestedPatterns to handle situations like this: + repeat = useHashes; + useHashes = false; + } else { + //if a reduction happened, make sure hashing in reduceNestedPatterns + //is enabled, as the hashing speeds up the process significantly: + useHashes = true; } patterns = updatedPatterns; } @@ -1023,8 +1026,15 @@ public class Flow { * simplify the pattern. If that succeeds, the original found sub-set * of patterns is replaced with a new set of patterns of the form: * $record($prefix$, $resultOfReduction, $suffix$) + * + * useHashes: when true, patterns will be subject to exact equivalence; + * when false, two binding patterns will be considered equivalent + * if one of them is more generic than the other one; + * when false, the processing will be significantly slower, + * as pattern hashes cannot be used to speed up the matching process */ - private Set reduceNestedPatterns(Set patterns) { + private Set reduceNestedPatterns(Set patterns, + boolean useHashes) { /* implementation note: * finding a sub-set of patterns that only differ in a single * column is time-consuming task, so this method speeds it up by: @@ -1049,13 +1059,13 @@ public class Flow { mismatchingCandidate < nestedPatternsCount; mismatchingCandidate++) { int mismatchingCandidateFin = mismatchingCandidate; - var groupByHashes = + var groupEquivalenceCandidates = current .stream() //error recovery, ignore patterns with incorrect number of nested patterns: .filter(pd -> pd.nested.length == nestedPatternsCount) - .collect(groupingBy(pd -> pd.hashCode(mismatchingCandidateFin))); - for (var candidates : groupByHashes.values()) { + .collect(groupingBy(pd -> useHashes ? pd.hashCode(mismatchingCandidateFin) : 0)); + for (var candidates : groupEquivalenceCandidates.values()) { var candidatesArr = candidates.toArray(RecordPattern[]::new); for (int firstCandidate = 0; @@ -1076,9 +1086,18 @@ public class Flow { RecordPattern rpOther = candidatesArr[nextCandidate]; if (rpOne.recordType.tsym == rpOther.recordType.tsym) { for (int i = 0; i < rpOne.nested.length; i++) { - if (i != mismatchingCandidate && - !rpOne.nested[i].equals(rpOther.nested[i])) { - continue NEXT_PATTERN; + if (i != mismatchingCandidate) { + if (!rpOne.nested[i].equals(rpOther.nested[i])) { + if (useHashes || + //when not using hashes, + //check if rpOne.nested[i] is + //a subtype of rpOther.nested[i]: + !(rpOne.nested[i] instanceof BindingPattern bpOne) || + !(rpOther.nested[i] instanceof BindingPattern bpOther) || + !types.isSubtype(types.erasure(bpOne.type), types.erasure(bpOther.type))) { + continue NEXT_PATTERN; + } + } } } join.append(rpOther); @@ -1086,14 +1105,16 @@ public class Flow { } var nestedPatterns = join.stream().map(rp -> rp.nested[mismatchingCandidateFin]).collect(Collectors.toSet()); - var updatedPatterns = reduceNestedPatterns(nestedPatterns); + var updatedPatterns = reduceNestedPatterns(nestedPatterns, useHashes); updatedPatterns = reduceRecordPatterns(updatedPatterns); updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); updatedPatterns = reduceBindingPatterns(rpOne.fullComponentTypes()[mismatchingCandidateFin], updatedPatterns); if (!nestedPatterns.equals(updatedPatterns)) { - current.removeAll(join); + if (useHashes) { + current.removeAll(join); + } for (PatternDescription nested : updatedPatterns) { PatternDescription[] newNested = @@ -1169,40 +1190,6 @@ public class Flow { return pattern; } - private Set expandGenericPatterns(Set patterns) { - var newPatterns = new HashSet(patterns); - boolean modified; - do { - modified = false; - for (PatternDescription pd : patterns) { - if (pd instanceof RecordPattern rpOne) { - for (int i = 0; i < rpOne.nested.length; i++) { - Set toExpand = Set.of(rpOne.nested[i]); - Set expanded = expandGenericPatterns(toExpand); - if (expanded != toExpand) { - expanded.removeAll(toExpand); - for (PatternDescription exp : expanded) { - PatternDescription[] newNested = Arrays.copyOf(rpOne.nested, rpOne.nested.length); - newNested[i] = exp; - modified |= newPatterns.add(new RecordPattern(rpOne.recordType(), rpOne.fullComponentTypes(), newNested)); - } - } - } - } else if (pd instanceof BindingPattern bp) { - Set permittedSymbols = allPermittedSubTypes(bp.type.tsym, cs -> true); - - if (!permittedSymbols.isEmpty()) { - for (Symbol permitted : permittedSymbols) { - //TODO infer.instantiatePatternType(selectorType, csym); (?) - modified |= newPatterns.add(new BindingPattern(permitted.type)); - } - } - } - } - } while (modified); - return newPatterns; - } - private Set removeCoveredRecordPatterns(Set patterns) { Set existingBindings = patterns.stream() .filter(pd -> pd instanceof BindingPattern) diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index 28926af0254..6ac84faaf7d 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -61,7 +61,6 @@ tools/javac/annotations/typeAnnotations/referenceinfos/Lambda.java tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java 8057687 generic-all emit correct byte code an attributes for type annotations tools/javac/warnings/suppress/TypeAnnotations.java 8057683 generic-all improve ordering of errors with type annotations tools/javac/modules/SourceInSymlinkTest.java 8180263 windows-all fails when run on a subst drive -tools/javac/patterns/Exhaustiveness.java 8326616 generic-all intermittently timeout ########################################################################### #