From eb415fe4e658a579ef9588e0b57368803d71ac95 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 22 Jun 2018 15:32:54 +0700 Subject: [PATCH] DfaMemoryStateImpl: do not add distinct classes when constants are obviously distinct (cherry picked from commit b3a0e44a1e858f1e54632654f3f7c57e27d1f638) --- .../dataFlow/DfaMemoryStateImpl.java | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) 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 e11014311e14..d325a0772e02 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 @@ -30,6 +30,7 @@ import com.intellij.psi.util.PropertyUtilBase; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.ObjectUtils; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import gnu.trove.TIntObjectHashMap; @@ -959,8 +960,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState { return true; } + ThreeState equalByConstants = equalByConstant(c1Index, c2Index); + if (equalByConstants != ThreeState.UNSURE) return equalByConstants.toBoolean() != isNegated; if (!isNegated) { //Equals - if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return true; if (isUnstableValue(dfaLeft) || isUnstableValue(dfaRight)) return true; if (!uniteClasses(c1Index, c2Index)) return false; @@ -975,7 +977,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState { myCachedNonTrivialEqClasses = null; } else { // Not Equals - if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return false; if (isNull(dfaLeft) && isPrimitive(dfaRight) || isNull(dfaRight) && isPrimitive(dfaLeft)) return true; myDistinctClasses.addUnordered(c1Index, c2Index); } @@ -992,7 +993,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState { return true; } - if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return false; + ThreeState equalByConstants = equalByConstant(c1Index, c2Index); + if (equalByConstants != ThreeState.UNSURE) return !equalByConstants.toBoolean(); if (isNull(dfaLeft) && isPrimitive(dfaRight) || isNull(dfaRight) && isPrimitive(dfaLeft)) return true; myCachedHash = null; return myDistinctClasses.addOrdered(c1Index, c2Index); @@ -1025,17 +1027,35 @@ public class DfaMemoryStateImpl implements DfaMemoryState { c2 == null && c1 instanceof PsiVariable; } - private boolean areCompatibleConstants(int i1, int i2) { - Double dv1 = getDoubleValue(i1); - return dv1 != null && dv1.equals(getDoubleValue(i2)); + @NotNull + private ThreeState equalByConstant(int i1, int i2) { + if (i1 == i2) return ThreeState.YES; + EqClass ec1 = myEqClasses.get(i1); + EqClass ec2 = myEqClasses.get(i2); + if (ec1 == null || ec2 == null) return ThreeState.UNSURE; + DfaValue constOrBox1 = ec1.findConstant(true); + DfaValue constOrBox2 = ec2.findConstant(true); + if (constOrBox1 == null || constOrBox2 == null) return ThreeState.UNSURE; + if (constOrBox1 instanceof DfaConstValue && constOrBox2 instanceof DfaConstValue) { + return areConstantsEqual((DfaConstValue)constOrBox1, (DfaConstValue)constOrBox2); + } + if (constOrBox1 instanceof DfaBoxedValue && constOrBox2 instanceof DfaBoxedValue) { + DfaValue wrapped1 = ((DfaBoxedValue)constOrBox1).getWrappedValue(); + DfaValue wrapped2 = ((DfaBoxedValue)constOrBox2).getWrappedValue(); + if (wrapped1 instanceof DfaConstValue && wrapped2 instanceof DfaConstValue && + areConstantsEqual((DfaConstValue)wrapped1, (DfaConstValue)wrapped2) == ThreeState.NO) { + return ThreeState.NO; + } + } + return ThreeState.UNSURE; } - @Nullable - private Double getDoubleValue(int eqClassIndex) { - EqClass ec = myEqClasses.get(eqClassIndex); - DfaValue dfaConst = ec == null ? null : ec.findConstant(false); - Object constValue = dfaConst instanceof DfaConstValue ? ((DfaConstValue)dfaConst).getValue() : null; - return constValue instanceof Number ? ((Number)constValue).doubleValue() : null; + private static ThreeState areConstantsEqual(DfaConstValue const1, DfaConstValue const2) { + Number value1 = ObjectUtils.tryCast(const1.getValue(), Number.class); + Number value2 = ObjectUtils.tryCast(const2.getValue(), Number.class); + if (value1 == null || value2 == null) return ThreeState.UNSURE; + if (value1 instanceof Long && value2 instanceof Long) return ThreeState.fromBoolean(value1.equals(value2)); + return ThreeState.fromBoolean(value1.doubleValue() == value2.doubleValue()); } @Override