From ff2cd3cc05f44abee81bd21d82e4b8f0f34e1ebe Mon Sep 17 00:00:00 2001 From: Ilya Klyuchnikov Date: Sun, 31 Aug 2014 13:12:44 +0400 Subject: [PATCH] optimizations --- .../bytecodeAnalysis/ClassDataIndexer.java | 115 ++++++------------ .../NullableMethodAnalysis.java | 11 +- 2 files changed, 45 insertions(+), 81 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java index bf19d0d07f6a..f06ad3fa8987 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java @@ -18,8 +18,6 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.codeInspection.bytecodeAnalysis.asm.*; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.NullableLazyValue; import com.intellij.openapi.util.Pair; import com.intellij.util.indexing.DataIndexer; import com.intellij.util.indexing.FileContent; @@ -31,8 +29,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; import java.security.MessageDigest; import java.util.*; -import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG; import static com.intellij.codeInspection.bytecodeAnalysis.Direction.*; +import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG; /** * @author lambdamix @@ -173,13 +171,13 @@ public class ClassDataIndexer implements DataIndexer> processBranchingMethod(final Method method, - final MethodNode methodNode, - final RichControlFlow richControlFlow, - Type[] argumentTypes, - boolean isReferenceResult, - boolean isInterestingResult, - final boolean stable, - boolean jsr) throws AnalyzerException { + final MethodNode methodNode, + final RichControlFlow richControlFlow, + Type[] argumentTypes, + boolean isReferenceResult, + boolean isInterestingResult, + final boolean stable, + boolean jsr) throws AnalyzerException { List> result = new ArrayList>(argumentTypes.length * 4 + 2); boolean maybeLeakingParameter = isInterestingResult; @@ -192,42 +190,25 @@ public class ClassDataIndexer implements DataIndexer origins = new NullableLazyValue() { - @Override - protected boolean[] compute() { - try { - return OriginsAnalysis.resultOrigins(leakingParametersAndFrames.frames, methodNode.instructions, richControlFlow.controlFlow); - } - catch (AnalyzerException e) { - LOG.debug("when processing " + method + " in " + presentableUrl, e); - return null; - } - } - }; + final boolean[] origins = + isInterestingResult ? + OriginsAnalysis.resultOrigins(leakingParametersAndFrames.frames, methodNode.instructions, richControlFlow.controlFlow) : + null; - NotNullLazyValue> outEquation = new NotNullLazyValue>() { - @NotNull - @Override - protected Equation compute() { - if (origins.getValue() != null) { - try { - return new InOutAnalysis(richControlFlow, Out, origins.getValue(), stable).analyze(); - } - catch (AnalyzerException ignored) { - } - } - return new Equation(new Key(method, Out, stable), FINAL_TOP); - } - }; + Equation outEquation = + isInterestingResult ? + new InOutAnalysis(richControlFlow, Out, origins, stable).analyze() : + null; if (isReferenceResult) { - result.add(outEquation.getValue()); - result.add(new Equation(new Key(method, NullableOut, stable), NullableMethodAnalysis.analyze(methodNode, origins.getValue(), jsr))); + result.add(outEquation); + result.add(new Equation(new Key(method, NullableOut, stable), NullableMethodAnalysis.analyze(methodNode, origins, jsr))); } for (int i = 0; i < argumentTypes.length; i++) { @@ -261,47 +242,31 @@ public class ClassDataIndexer implements DataIndexer..." analysis - result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.Null), origins.getValue(), stable).analyze()); - } - else { - // @NotNull, so "null->fail" - result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), FINAL_BOT)); - } - result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.NotNull), origins.getValue(), stable).analyze()); + if (!notNullParam) { + // may be null on some branch, running "null->..." analysis + result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.Null), origins, stable).analyze()); } else { - // result origins analysis failed, approximating to Top - result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), FINAL_TOP)); - result.add(new Equation(new Key(method, new InOut(i, Value.NotNull), stable), FINAL_TOP)); + // @NotNull, so "null->fail" + result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), FINAL_BOT)); } + result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.NotNull), origins, stable).analyze()); } else { // parameter is not leaking, so a contract is the same as for the whole method - result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), outEquation.getValue().rhs)); - result.add(new Equation(new Key(method, new InOut(i, Value.NotNull), stable), outEquation.getValue().rhs)); + result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), outEquation.rhs)); + result.add(new Equation(new Key(method, new InOut(i, Value.NotNull), stable), outEquation.rhs)); } } if (ASMUtils.isBooleanType(argumentTypes[i]) && isInterestingResult) { if (leakingParameters[i]) { - if (origins.getValue() != null) { - // result origins analysis was ok - result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.False), origins.getValue(), stable).analyze()); - result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.True), origins.getValue(), stable).analyze()); - } - else { - // result origins analysis failed, approximating to Top - result.add(new Equation(new Key(method, new InOut(i, Value.False), stable), FINAL_TOP)); - result.add(new Equation(new Key(method, new InOut(i, Value.True), stable), FINAL_TOP)); - } + result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.False), origins, stable).analyze()); + result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.True), origins, stable).analyze()); } else { // parameter is not leaking, so a contract is the same as for the whole method - result.add(new Equation(new Key(method, new InOut(i, Value.False), stable), outEquation.getValue().rhs)); - result.add(new Equation(new Key(method, new InOut(i, Value.True), stable), outEquation.getValue().rhs)); + result.add(new Equation(new Key(method, new InOut(i, Value.False), stable), outEquation.rhs)); + result.add(new Equation(new Key(method, new InOut(i, Value.True), stable), outEquation.rhs)); } } } @@ -309,11 +274,11 @@ public class ClassDataIndexer implements DataIndexer> processNonBranchingMethod(Method method, - Type[] argumentTypes, - ControlFlowGraph graph, - boolean isReferenceResult, - boolean isBooleanResult, - boolean stable) throws AnalyzerException { + Type[] argumentTypes, + ControlFlowGraph graph, + boolean isReferenceResult, + boolean isBooleanResult, + boolean stable) throws AnalyzerException { List> result = new ArrayList>(argumentTypes.length * 4 + 2); CombinedAnalysis analyzer = new CombinedAnalysis(method, graph); analyzer.analyze(); @@ -341,10 +306,10 @@ public class ClassDataIndexer implements DataIndexer> topEquations(Method method, - Type[] argumentTypes, - boolean isReferenceResult, - boolean isInterestingResult, - boolean stable) { + Type[] argumentTypes, + boolean isReferenceResult, + boolean isInterestingResult, + boolean stable) { List> result = new ArrayList>(argumentTypes.length * 4 + 2); if (isReferenceResult) { result.add(new Equation(new Key(method, Out, stable), FINAL_TOP)); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/NullableMethodAnalysis.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/NullableMethodAnalysis.java index 3d6c8312cbf7..5bd34b225b16 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/NullableMethodAnalysis.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/NullableMethodAnalysis.java @@ -18,10 +18,10 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.codeInspection.bytecodeAnalysis.asm.AnalyzerExt; import com.intellij.codeInspection.bytecodeAnalysis.asm.InterpreterExt; import com.intellij.codeInspection.bytecodeAnalysis.asm.LiteAnalyzerExt; -import com.intellij.util.SingletonSet; import gnu.trove.TIntHashSet; import gnu.trove.TIntIterator; import gnu.trove.TIntProcedure; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.tree.*; @@ -40,7 +40,6 @@ import static com.intellij.codeInspection.bytecodeAnalysis.NullableMethodAnalysi interface NullableMethodAnalysisData { Type NullType = Type.getObjectType("null"); Type ThisType = Type.getObjectType("this"); - Type ObjectType = Type.getObjectType("java/lang/Object"); Type CallType = Type.getObjectType("/Call"); final class LabeledNull extends BasicValue { @@ -159,7 +158,7 @@ class NullableMethodAnalysis { Calls calls = ((Calls)result); Set> sum = new HashSet>(calls.keys.size()); for (Key key : calls.keys) { - sum.add(new Product(Value.Null, new SingletonSet(key))); + sum.add(new Product(Value.Null, Collections.singleton(key))); } return new Pending(sum); } @@ -344,7 +343,7 @@ class NullableMethodInterpreter extends BasicInterpreter implements InterpreterE (values.get(0) == ThisValue); MethodInsnNode mNode = ((MethodInsnNode)insn); Method method = new Method(mNode.owner, mNode.name, mNode.desc); - return new Calls(new SingletonSet(new Key(method, Direction.NullableOut, stable))); + return new Calls(Collections.singleton(new Key(method, Direction.NullableOut, stable))); } break; default: @@ -442,7 +441,7 @@ class NullableMethodInterpreter extends BasicInterpreter implements InterpreterE } } - static TIntHashSet merge(TIntHashSet set1, TIntHashSet set2) { + static TIntHashSet merge(@Nullable TIntHashSet set1, TIntHashSet set2) { if (set1 == null || set1.isEmpty()) { return set2; } @@ -463,7 +462,7 @@ class NullableMethodInterpreter extends BasicInterpreter implements InterpreterE } } - static Set merge(Set set1, Set set2) { + static Set merge(@Nullable Set set1, Set set2) { if (set1 == null || set1.isEmpty()) { return set2; }