mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
optimizations
This commit is contained in:
+40
-75
@@ -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<Bytes, HEquations, FileCont
|
||||
}
|
||||
|
||||
private List<Equation<Key, Value>> 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<Equation<Key, Value>> result = new ArrayList<Equation<Key, Value>>(argumentTypes.length * 4 + 2);
|
||||
boolean maybeLeakingParameter = isInterestingResult;
|
||||
@@ -192,42 +190,25 @@ public class ClassDataIndexer implements DataIndexer<Bytes, HEquations, FileCont
|
||||
|
||||
final LeakingParameters leakingParametersAndFrames =
|
||||
maybeLeakingParameter ? leakingParametersAndFrames(method, methodNode, argumentTypes, jsr) : null;
|
||||
|
||||
boolean[] leakingParameters =
|
||||
leakingParametersAndFrames != null ? leakingParametersAndFrames.parameters : null;
|
||||
boolean[] leakingNullableParameters =
|
||||
leakingParametersAndFrames != null ? leakingParametersAndFrames.nullableParameters : null;
|
||||
|
||||
final NullableLazyValue<boolean[]> origins = new NullableLazyValue<boolean[]>() {
|
||||
@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<Equation<Key, Value>> outEquation = new NotNullLazyValue<Equation<Key, Value>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Equation<Key, Value> compute() {
|
||||
if (origins.getValue() != null) {
|
||||
try {
|
||||
return new InOutAnalysis(richControlFlow, Out, origins.getValue(), stable).analyze();
|
||||
}
|
||||
catch (AnalyzerException ignored) {
|
||||
}
|
||||
}
|
||||
return new Equation<Key, Value>(new Key(method, Out, stable), FINAL_TOP);
|
||||
}
|
||||
};
|
||||
Equation<Key, Value> outEquation =
|
||||
isInterestingResult ?
|
||||
new InOutAnalysis(richControlFlow, Out, origins, stable).analyze() :
|
||||
null;
|
||||
|
||||
if (isReferenceResult) {
|
||||
result.add(outEquation.getValue());
|
||||
result.add(new Equation<Key, Value>(new Key(method, NullableOut, stable), NullableMethodAnalysis.analyze(methodNode, origins.getValue(), jsr)));
|
||||
result.add(outEquation);
|
||||
result.add(new Equation<Key, Value>(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<Bytes, HEquations, FileCont
|
||||
}
|
||||
if (isReferenceArg && isInterestingResult) {
|
||||
if (leakingParameters[i]) {
|
||||
if (origins.getValue() != null) {
|
||||
// result origins analysis was ok
|
||||
if (!notNullParam) {
|
||||
// may be null on some branch, running "null->..." analysis
|
||||
result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.Null), origins.getValue(), stable).analyze());
|
||||
}
|
||||
else {
|
||||
// @NotNull, so "null->fail"
|
||||
result.add(new Equation<Key, Value>(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<Key, Value>(new Key(method, new InOut(i, Value.Null), stable), FINAL_TOP));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.NotNull), stable), FINAL_TOP));
|
||||
// @NotNull, so "null->fail"
|
||||
result.add(new Equation<Key, Value>(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<Key, Value>(new Key(method, new InOut(i, Value.Null), stable), outEquation.getValue().rhs));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.NotNull), stable), outEquation.getValue().rhs));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.Null), stable), outEquation.rhs));
|
||||
result.add(new Equation<Key, Value>(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<Key, Value>(new Key(method, new InOut(i, Value.False), stable), FINAL_TOP));
|
||||
result.add(new Equation<Key, Value>(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<Key, Value>(new Key(method, new InOut(i, Value.False), stable), outEquation.getValue().rhs));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.True), stable), outEquation.getValue().rhs));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.False), stable), outEquation.rhs));
|
||||
result.add(new Equation<Key, Value>(new Key(method, new InOut(i, Value.True), stable), outEquation.rhs));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,11 +274,11 @@ public class ClassDataIndexer implements DataIndexer<Bytes, HEquations, FileCont
|
||||
}
|
||||
|
||||
private List<Equation<Key, Value>> 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<Equation<Key, Value>> result = new ArrayList<Equation<Key, Value>>(argumentTypes.length * 4 + 2);
|
||||
CombinedAnalysis analyzer = new CombinedAnalysis(method, graph);
|
||||
analyzer.analyze();
|
||||
@@ -341,10 +306,10 @@ public class ClassDataIndexer implements DataIndexer<Bytes, HEquations, FileCont
|
||||
}
|
||||
|
||||
private List<Equation<Key, Value>> topEquations(Method method,
|
||||
Type[] argumentTypes,
|
||||
boolean isReferenceResult,
|
||||
boolean isInterestingResult,
|
||||
boolean stable) {
|
||||
Type[] argumentTypes,
|
||||
boolean isReferenceResult,
|
||||
boolean isInterestingResult,
|
||||
boolean stable) {
|
||||
List<Equation<Key, Value>> result = new ArrayList<Equation<Key, Value>>(argumentTypes.length * 4 + 2);
|
||||
if (isReferenceResult) {
|
||||
result.add(new Equation<Key, Value>(new Key(method, Out, stable), FINAL_TOP));
|
||||
|
||||
+5
-6
@@ -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<Product<Key, Value>> sum = new HashSet<Product<Key, Value>>(calls.keys.size());
|
||||
for (Key key : calls.keys) {
|
||||
sum.add(new Product<Key, Value>(Value.Null, new SingletonSet<Key>(key)));
|
||||
sum.add(new Product<Key, Value>(Value.Null, Collections.singleton(key)));
|
||||
}
|
||||
return new Pending<Key, Value>(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<Key>(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<Key> merge(Set<Key> set1, Set<Key> set2) {
|
||||
static Set<Key> merge(@Nullable Set<Key> set1, Set<Key> set2) {
|
||||
if (set1 == null || set1.isEmpty()) {
|
||||
return set2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user