[java-decompiler] unneeded context lookups

master
Roman Shevchenko 9 years ago
parent 77dc5c5f1e
commit 857dc4d023
  1. 4
      src/org/jetbrains/java/decompiler/main/DecompilerContext.java
  2. 13
      src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
  3. 18
      src/org/jetbrains/java/decompiler/main/rels/MethodProcessorRunnable.java
  4. 22
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  5. 22
      src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java
  6. 28
      src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java
  7. 25
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java
  8. 34
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarTypeProcessor.java
  9. 17
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,8 +32,6 @@ public class DecompilerContext {
public static final String CURRENT_CLASS = "CURRENT_CLASS";
public static final String CURRENT_CLASS_WRAPPER = "CURRENT_CLASS_WRAPPER";
public static final String CURRENT_CLASS_NODE = "CURRENT_CLASS_NODE";
public static final String CURRENT_METHOD = "CURRENT_METHOD";
public static final String CURRENT_METHOD_DESCRIPTOR = "CURRENT_METHOD_DESCRIPTOR";
public static final String CURRENT_METHOD_WRAPPER = "CURRENT_METHOD_WRAPPER";
public static final String CURRENT_VAR_PROCESSOR = "CURRENT_VAR_PROCESSOR";

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -73,10 +73,8 @@ public class ClassWrapper {
CounterContainer counter = new CounterContainer();
DecompilerContext.setCounterContainer(counter);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD, mt);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR, MethodDescriptor.parseDescriptor(mt.getDescriptor()));
VarProcessor varProc = new VarProcessor();
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
VarProcessor varProc = new VarProcessor(mt, md);
DecompilerContext.setProperty(DecompilerContext.CURRENT_VAR_PROCESSOR, varProc);
RootStatement root = null;
@ -86,10 +84,10 @@ public class ClassWrapper {
try {
if (mt.containsCode()) {
if (maxSec == 0 || testMode) {
root = MethodProcessorRunnable.codeToJava(mt, varProc);
root = MethodProcessorRunnable.codeToJava(mt, md, varProc);
}
else {
MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, varProc, DecompilerContext.getCurrentContext());
MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, md, varProc, DecompilerContext.getCurrentContext());
Thread mtThread = new Thread(mtProc, "Java decompiler");
long stopAt = System.currentTimeMillis() + maxSec * 1000;
@ -123,7 +121,6 @@ public class ClassWrapper {
}
else {
boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC);
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
int paramCount = 0;
if (thisVar) {

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,14 +29,15 @@ import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import java.io.IOException;
public class MethodProcessorRunnable implements Runnable {
public final Object lock = new Object();
private final StructMethod method;
private final MethodDescriptor methodDescriptor;
private final VarProcessor varProc;
private final DecompilerContext parentContext;
@ -44,8 +45,9 @@ public class MethodProcessorRunnable implements Runnable {
private volatile Throwable error;
private volatile boolean finished = false;
public MethodProcessorRunnable(StructMethod method, VarProcessor varProc, DecompilerContext parentContext) {
public MethodProcessorRunnable(StructMethod method, MethodDescriptor methodDescriptor, VarProcessor varProc, DecompilerContext parentContext) {
this.method = method;
this.methodDescriptor = methodDescriptor;
this.varProc = varProc;
this.parentContext = parentContext;
}
@ -58,7 +60,7 @@ public class MethodProcessorRunnable implements Runnable {
root = null;
try {
root = codeToJava(method, varProc);
root = codeToJava(method, methodDescriptor, varProc);
}
catch (ThreadDeath ex) {
throw ex;
@ -76,7 +78,7 @@ public class MethodProcessorRunnable implements Runnable {
}
}
public static RootStatement codeToJava(StructMethod mt, VarProcessor varProc) throws IOException {
public static RootStatement codeToJava(StructMethod mt, MethodDescriptor md, VarProcessor varProc) throws IOException {
StructClass cl = mt.getClassStruct();
boolean isInitializer = CodeConstants.CLINIT_NAME.equals(mt.getName()); // for now static initializer only
@ -119,7 +121,7 @@ public class MethodProcessorRunnable implements Runnable {
RootStatement root = DomHelper.parseGraph(graph);
FinallyProcessor fProc = new FinallyProcessor(varProc);
FinallyProcessor fProc = new FinallyProcessor(md, varProc);
while (fProc.iterateGraph(mt, root, graph)) {
root = DomHelper.parseGraph(graph);
}
@ -134,7 +136,7 @@ public class MethodProcessorRunnable implements Runnable {
ClearStructHelper.clearStatements(root);
ExprProcessor proc = new ExprProcessor();
ExprProcessor proc = new ExprProcessor(md, varProc);
proc.processStatement(root, cl);
SequenceHelper.condenseSequences(root);
@ -195,7 +197,7 @@ public class MethodProcessorRunnable implements Runnable {
ExitHelper.removeRedundantReturns(root);
SecondaryFunctionsHelper.identifySecondaryFunctions(root);
SecondaryFunctionsHelper.identifySecondaryFunctions(root, varProc);
varProc.setVarDefinitions(root);

@ -42,7 +42,6 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.*;
public class ExprProcessor implements CodeConstants {
public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>";
public static final String UNKNOWN_TYPE_STRING = "<unknown>";
public static final String NULL_TYPE_STRING = "<null>";
@ -50,7 +49,6 @@ public class ExprProcessor implements CodeConstants {
private static final HashMap<Integer, Integer> mapConsts = new HashMap<Integer, Integer>();
static {
// mapConsts.put(new Integer(opc_i2l), new
// Integer(FunctionExprent.FUNCTION_I2L));
// mapConsts.put(new Integer(opc_i2f), new
@ -141,19 +139,18 @@ public class ExprProcessor implements CodeConstants {
private static final String[] typeNames = new String[]{"byte", "char", "double", "float", "int", "long", "short", "boolean",};
private final VarProcessor varProcessor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
private final MethodDescriptor methodDescriptor;
private final VarProcessor varProcessor;
public void processStatement(RootStatement root, StructClass cl) {
public ExprProcessor(MethodDescriptor md, VarProcessor varProc) {
methodDescriptor = md;
varProcessor = varProc;
}
public void processStatement(RootStatement root, StructClass cl) {
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root);
// try {
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// collect finally entry points
Set<String> setFinallyShortRangeEntryPoints = new HashSet<String>();
for (List<FinallyPathWrapper> lst : dgraph.mapShortRangeFinallyPaths.values()) {
@ -534,10 +531,7 @@ public class ExprProcessor implements CodeConstants {
case opc_athrow:
exprlist.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN,
instr.opcode == opc_return ? null : stack.pop(),
instr.opcode == opc_athrow
? null
: ((MethodDescriptor)DecompilerContext
.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret,
instr.opcode == opc_athrow ? null : methodDescriptor.ret,
bytecode_offsets));
break;
case opc_monitorenter:

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,6 +38,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
@ -45,23 +46,22 @@ import java.util.*;
import java.util.Map.Entry;
public class FinallyProcessor {
private final Map<Integer, Integer> finallyBlockIDs = new HashMap<Integer, Integer>();
private final Map<Integer, Integer> catchallBlockIDs = new HashMap<Integer, Integer>();
private final VarProcessor varprocessor;
private final MethodDescriptor methodDescriptor;
private final VarProcessor varProcessor;
public FinallyProcessor(VarProcessor varprocessor) {
this.varprocessor = varprocessor;
public FinallyProcessor(MethodDescriptor md, VarProcessor varProc) {
methodDescriptor = md;
varProcessor = varProc;
}
public boolean iterateGraph(StructMethod mt, RootStatement root, ControlFlowGraph graph) {
// return processStatement(mt, root, graph, root);
return processStatementEx(mt, root, graph);
}
private boolean processStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) {
int bytecode_version = mt.getClassStruct().getBytecodeVersion();
LinkedList<Statement> stack = new LinkedList<Statement>();
@ -87,7 +87,7 @@ public class FinallyProcessor {
fin.setFinally(true);
Integer var = finallyBlockIDs.get(handler.id);
fin.setMonitor(var == null ? null : new VarExprent(var.intValue(), VarType.VARTYPE_INT, varprocessor));
fin.setMonitor(var == null ? null : new VarExprent(var.intValue(), VarType.VARTYPE_INT, varProcessor));
}
else {
@ -190,9 +190,7 @@ public class FinallyProcessor {
}
}
private static Record getFinallyInformation(StructMethod mt, RootStatement root, CatchAllStatement fstat) {
private Record getFinallyInformation(StructMethod mt, RootStatement root, CatchAllStatement fstat) {
Map<BasicBlock, Boolean> mapLast = new HashMap<BasicBlock, Boolean>();
BasicBlockStatement firstBlockStatement = fstat.getHandler().getBasichead();
@ -209,7 +207,7 @@ public class FinallyProcessor {
firstcode = 2;
}
ExprProcessor proc = new ExprProcessor();
ExprProcessor proc = new ExprProcessor(methodDescriptor, varProcessor);
proc.processStatement(root, mt.getClassStruct());
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -56,9 +56,7 @@ public class SecondaryFunctionsHelper {
mapNumComparisons.put(FunctionExprent.FUNCTION_LE, new Integer[]{FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE, null});
}
public static boolean identifySecondaryFunctions(Statement stat) {
public static boolean identifySecondaryFunctions(Statement stat, VarProcessor varProc) {
if (stat.getExprents() == null) {
// if(){;}else{...} -> if(!){...}
if (stat.type == Statement.TYPE_IF) {
@ -100,7 +98,6 @@ public class SecondaryFunctionsHelper {
}
}
boolean replaced = true;
while (replaced) {
replaced = false;
@ -111,13 +108,13 @@ public class SecondaryFunctionsHelper {
Object obj = lstObjects.get(i);
if (obj instanceof Statement) {
if (identifySecondaryFunctions((Statement)obj)) {
if (identifySecondaryFunctions((Statement)obj, varProc)) {
replaced = true;
break;
}
}
else if (obj instanceof Exprent) {
Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true);
Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true, varProc);
if (retexpr != null) {
if (stat.getExprents() == null) {
// only head expressions can be replaced!
@ -136,9 +133,7 @@ public class SecondaryFunctionsHelper {
return false;
}
private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level) {
private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level, VarProcessor varProc) {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent;
@ -202,7 +197,7 @@ public class SecondaryFunctionsHelper {
replaced = false;
for (Exprent expr : exprent.getAllExprents()) {
Exprent retexpr = identifySecondaryFunctions(expr, false);
Exprent retexpr = identifySecondaryFunctions(expr, false, varProc);
if (retexpr != null) {
exprent.replaceExprent(expr, retexpr);
replaced = true;
@ -301,21 +296,20 @@ public class SecondaryFunctionsHelper {
case FunctionExprent.FUNCTION_DCMPG:
int var = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER);
VarType type = lstOperands.get(0).getExprType();
VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new VarExprent(var, type, processor),
new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new VarExprent(var, type, varProc),
ConstExprent.getZeroConstant(type.type)), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(-1), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(1), null)), null);
FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(
new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB,
Arrays.asList(lstOperands.get(0),
lstOperands.get(1)), null), null),
new AssignmentExprent(new VarExprent(var, type, varProc),
new FunctionExprent(FunctionExprent.FUNCTION_SUB, Arrays.asList(lstOperands.get(0), lstOperands.get(1)), null),
null),
ConstExprent.getZeroConstant(type.type)), null);
processor.setVarType(new VarVersionPair(var, 0), type);
varProc.setVarType(new VarVersionPair(var, 0), type);
return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null), iff), fexpr.bytecode);

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,33 +15,37 @@
*/
package org.jetbrains.java.decompiler.modules.decompiler.vars;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.*;
import java.util.Map.Entry;
public class VarProcessor {
private final StructMethod method;
private final MethodDescriptor methodDescriptor;
private Map<VarVersionPair, String> mapVarNames = new HashMap<VarVersionPair, String>();
private VarVersionsProcessor varVersions;
private final Map<VarVersionPair, String> thisVars = new HashMap<VarVersionPair, String>();
private final Set<VarVersionPair> externalVars = new HashSet<VarVersionPair>();
public VarProcessor(StructMethod mt, MethodDescriptor md) {
method = mt;
methodDescriptor = md;
}
public void setVarVersions(RootStatement root) {
varVersions = new VarVersionsProcessor();
varVersions = new VarVersionsProcessor(method, methodDescriptor);
varVersions.setVarVersions(root);
}
public void setVarDefinitions(Statement root) {
mapVarNames = new HashMap<VarVersionPair, String>();
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
new VarDefinitionHelper(root, mt, this).setVarDefinitions();
new VarDefinitionHelper(root, method, this).setVarDefinitions();
}
public void setDebugVarNames(Map<Integer, String> mapDebugVarNames) {
@ -52,12 +56,7 @@ public class VarProcessor {
Map<Integer, Integer> mapOriginalVarIndices = varVersions.getMapOriginalVarIndices();
List<VarVersionPair> listVars = new ArrayList<VarVersionPair>(mapVarNames.keySet());
Collections.sort(listVars, new Comparator<VarVersionPair>() {
@Override
public int compare(VarVersionPair o1, VarVersionPair o2) {
return o1.var - o2.var;
}
});
Collections.sort(listVars, (o1, o2) -> o1.var - o2.var);
Map<String, Integer> mapNames = new HashMap<String, Integer>();

@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,21 +34,34 @@ import java.util.List;
import java.util.Map;
public class VarTypeProcessor {
public static final int VAR_NON_FINAL = 1;
public static final int VAR_EXPLICIT_FINAL = 2;
public static final int VAR_FINAL = 3;
private final StructMethod method;
private final MethodDescriptor methodDescriptor;
private final Map<VarVersionPair, VarType> mapExprentMinTypes = new HashMap<VarVersionPair, VarType>();
private final Map<VarVersionPair, VarType> mapExprentMaxTypes = new HashMap<VarVersionPair, VarType>();
private final Map<VarVersionPair, Integer> mapFinalVars = new HashMap<VarVersionPair, Integer>();
private void setInitVars(RootStatement root) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
public VarTypeProcessor(StructMethod mt, MethodDescriptor md) {
method = mt;
methodDescriptor = md;
}
public void calculateVarTypes(RootStatement root, DirectGraph graph) {
setInitVars(root);
resetExprentTypes(graph);
//noinspection StatementWithEmptyBody
while (!processVarTypes(graph)) ;
}
boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC);
private void setInitVars(RootStatement root) {
boolean thisVar = !method.hasModifier(CodeConstants.ACC_STATIC);
MethodDescriptor md = (MethodDescriptor)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR);
MethodDescriptor md = methodDescriptor;
if (thisVar) {
StructClass cl = (StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS);
@ -90,15 +103,6 @@ public class VarTypeProcessor {
}
}
public void calculateVarTypes(RootStatement root, DirectGraph graph) {
setInitVars(root);
resetExprentTypes(graph);
//noinspection StatementWithEmptyBody
while (!processVarTypes(graph)) ;
}
private static void resetExprentTypes(DirectGraph graph) {
graph.iterateExprents(new DirectGraph.ExprentIterator() {
@Override

@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,6 +26,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatements
import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAConstructorSparseEx;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet;
@ -33,25 +34,27 @@ import java.util.*;
import java.util.Map.Entry;
public class VarVersionsProcessor {
private final StructMethod method;
private Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>();
private VarTypeProcessor typeProcessor;
public void setVarVersions(RootStatement root) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
public VarVersionsProcessor(StructMethod mt, MethodDescriptor md) {
method = mt;
typeProcessor = new VarTypeProcessor(mt, md);
}
public void setVarVersions(RootStatement root) {
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, mt);
ssa.splitVariables(root, method);
FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper();
DirectGraph graph = flattenHelper.buildDirectGraph(root);
mergePhiVersions(ssa, graph);
typeProcessor = new VarTypeProcessor();
typeProcessor.calculateVarTypes(root, graph);
simpleMerge(typeProcessor, graph, mt);
simpleMerge(typeProcessor, graph, method);
// FIXME: advanced merging

Loading…
Cancel
Save