8326616: tools/javac/patterns/Exhaustiveness.java intermittently Timeout signalled after 480 seconds

Reviewed-by: abimpoudis
This commit is contained in:
Jan Lahoda 2024-09-09 05:34:09 +00:00
parent 79d761358c
commit a18d9d84cd
2 changed files with 40 additions and 54 deletions

View File

@ -827,30 +827,33 @@ public class Flow {
}
}
Set<PatternDescription> patterns = patternSet;
boolean genericPatternsExpanded = false;
boolean useHashes = true;
try {
boolean repeat = true;
while (repeat) {
Set<PatternDescription> 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<PatternDescription> reduceNestedPatterns(Set<PatternDescription> patterns) {
private Set<PatternDescription> reduceNestedPatterns(Set<PatternDescription> 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<PatternDescription> expandGenericPatterns(Set<PatternDescription> patterns) {
var newPatterns = new HashSet<PatternDescription>(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<PatternDescription> toExpand = Set.of(rpOne.nested[i]);
Set<PatternDescription> 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<Symbol> 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<PatternDescription> removeCoveredRecordPatterns(Set<PatternDescription> patterns) {
Set<Symbol> existingBindings = patterns.stream()
.filter(pd -> pd instanceof BindingPattern)

View File

@ -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
###########################################################################
#