From 203a70e40ff260e4510d5a0a7a2069f4ea6f865a Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 3 Jun 2019 16:32:40 +0700 Subject: [PATCH] DfaMemoryStateImpl: avoid exponential blow up of canonicalize calls GitOrigin-RevId: 61c65025d6f6626d500a0174a96d129dc124147e --- .../dataFlow/DfaMemoryStateImpl.java | 12 +++- .../dataFlow/fixture/ManyNestedOptionals.java | 60 +++++++++++++++++++ .../DataFlowInspection8Test.java | 1 + 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ManyNestedOptionals.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index e25386f97319..c3d205e56d8a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -1419,8 +1419,16 @@ public class DfaMemoryStateImpl implements DfaMemoryState { private DfaVariableValue canonicalize(DfaVariableValue var) { DfaVariableValue qualifier = var.getQualifier(); if (qualifier != null) { - EqClass eqClass = getEqClass(qualifier); - return var.withQualifier(eqClass == null ? canonicalize(qualifier) : Objects.requireNonNull(eqClass.getCanonicalVariable())); + Integer index = myIdToEqClassesIndices.get(qualifier.getID()); + if (index == null) { + qualifier = canonicalize(qualifier); + index = myIdToEqClassesIndices.get(qualifier.getID()); + if (index == null) { + return var.withQualifier(qualifier); + } + } + + return var.withQualifier(Objects.requireNonNull(myEqClasses.get(index).getCanonicalVariable())); } return var; } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ManyNestedOptionals.java b/java/java-tests/testData/inspection/dataFlow/fixture/ManyNestedOptionals.java new file mode 100644 index 000000000000..363938468a0d --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ManyNestedOptionals.java @@ -0,0 +1,60 @@ +import java.util.Optional; + +class App { + public static void main(String[] args) { + Optional.of("foo") + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)) + .map(x -> Optional.of(x)); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index cfce24858aa6..359e77503c54 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -246,4 +246,5 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { } public void testLambdaWritesArrayInTry() { doTest(); } + public void testManyNestedOptionals() { doTest(); } } \ No newline at end of file