[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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 = "CURRENT_CLASS";
public static final String CURRENT_CLASS_WRAPPER = "CURRENT_CLASS_WRAPPER"; 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_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_METHOD_WRAPPER = "CURRENT_METHOD_WRAPPER";
public static final String CURRENT_VAR_PROCESSOR = "CURRENT_VAR_PROCESSOR"; 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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(); CounterContainer counter = new CounterContainer();
DecompilerContext.setCounterContainer(counter); DecompilerContext.setCounterContainer(counter);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD, mt); MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR, MethodDescriptor.parseDescriptor(mt.getDescriptor())); VarProcessor varProc = new VarProcessor(mt, md);
VarProcessor varProc = new VarProcessor();
DecompilerContext.setProperty(DecompilerContext.CURRENT_VAR_PROCESSOR, varProc); DecompilerContext.setProperty(DecompilerContext.CURRENT_VAR_PROCESSOR, varProc);
RootStatement root = null; RootStatement root = null;
@ -86,10 +84,10 @@ public class ClassWrapper {
try { try {
if (mt.containsCode()) { if (mt.containsCode()) {
if (maxSec == 0 || testMode) { if (maxSec == 0 || testMode) {
root = MethodProcessorRunnable.codeToJava(mt, varProc); root = MethodProcessorRunnable.codeToJava(mt, md, varProc);
} }
else { 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"); Thread mtThread = new Thread(mtProc, "Java decompiler");
long stopAt = System.currentTimeMillis() + maxSec * 1000; long stopAt = System.currentTimeMillis() + maxSec * 1000;
@ -123,7 +121,6 @@ public class ClassWrapper {
} }
else { else {
boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC); boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC);
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
int paramCount = 0; int paramCount = 0;
if (thisVar) { 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import java.io.IOException; import java.io.IOException;
public class MethodProcessorRunnable implements Runnable { public class MethodProcessorRunnable implements Runnable {
public final Object lock = new Object(); public final Object lock = new Object();
private final StructMethod method; private final StructMethod method;
private final MethodDescriptor methodDescriptor;
private final VarProcessor varProc; private final VarProcessor varProc;
private final DecompilerContext parentContext; private final DecompilerContext parentContext;
@ -44,8 +45,9 @@ public class MethodProcessorRunnable implements Runnable {
private volatile Throwable error; private volatile Throwable error;
private volatile boolean finished = false; 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.method = method;
this.methodDescriptor = methodDescriptor;
this.varProc = varProc; this.varProc = varProc;
this.parentContext = parentContext; this.parentContext = parentContext;
} }
@ -58,7 +60,7 @@ public class MethodProcessorRunnable implements Runnable {
root = null; root = null;
try { try {
root = codeToJava(method, varProc); root = codeToJava(method, methodDescriptor, varProc);
} }
catch (ThreadDeath ex) { catch (ThreadDeath ex) {
throw 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(); StructClass cl = mt.getClassStruct();
boolean isInitializer = CodeConstants.CLINIT_NAME.equals(mt.getName()); // for now static initializer only 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); RootStatement root = DomHelper.parseGraph(graph);
FinallyProcessor fProc = new FinallyProcessor(varProc); FinallyProcessor fProc = new FinallyProcessor(md, varProc);
while (fProc.iterateGraph(mt, root, graph)) { while (fProc.iterateGraph(mt, root, graph)) {
root = DomHelper.parseGraph(graph); root = DomHelper.parseGraph(graph);
} }
@ -134,7 +136,7 @@ public class MethodProcessorRunnable implements Runnable {
ClearStructHelper.clearStatements(root); ClearStructHelper.clearStatements(root);
ExprProcessor proc = new ExprProcessor(); ExprProcessor proc = new ExprProcessor(md, varProc);
proc.processStatement(root, cl); proc.processStatement(root, cl);
SequenceHelper.condenseSequences(root); SequenceHelper.condenseSequences(root);
@ -195,7 +197,7 @@ public class MethodProcessorRunnable implements Runnable {
ExitHelper.removeRedundantReturns(root); ExitHelper.removeRedundantReturns(root);
SecondaryFunctionsHelper.identifySecondaryFunctions(root); SecondaryFunctionsHelper.identifySecondaryFunctions(root, varProc);
varProc.setVarDefinitions(root); varProc.setVarDefinitions(root);

@ -42,7 +42,6 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.*; import java.util.*;
public class ExprProcessor implements CodeConstants { public class ExprProcessor implements CodeConstants {
public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>"; public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>";
public static final String UNKNOWN_TYPE_STRING = "<unknown>"; public static final String UNKNOWN_TYPE_STRING = "<unknown>";
public static final String NULL_TYPE_STRING = "<null>"; 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>(); private static final HashMap<Integer, Integer> mapConsts = new HashMap<Integer, Integer>();
static { static {
// mapConsts.put(new Integer(opc_i2l), new // mapConsts.put(new Integer(opc_i2l), new
// Integer(FunctionExprent.FUNCTION_I2L)); // Integer(FunctionExprent.FUNCTION_I2L));
// mapConsts.put(new Integer(opc_i2f), new // 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 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(); FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root); 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 // collect finally entry points
Set<String> setFinallyShortRangeEntryPoints = new HashSet<String>(); Set<String> setFinallyShortRangeEntryPoints = new HashSet<String>();
for (List<FinallyPathWrapper> lst : dgraph.mapShortRangeFinallyPaths.values()) { for (List<FinallyPathWrapper> lst : dgraph.mapShortRangeFinallyPaths.values()) {
@ -534,10 +531,7 @@ public class ExprProcessor implements CodeConstants {
case opc_athrow: case opc_athrow:
exprlist.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN, exprlist.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN,
instr.opcode == opc_return ? null : stack.pop(), instr.opcode == opc_return ? null : stack.pop(),
instr.opcode == opc_athrow instr.opcode == opc_athrow ? null : methodDescriptor.ret,
? null
: ((MethodDescriptor)DecompilerContext
.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret,
bytecode_offsets)); bytecode_offsets));
break; break;
case opc_monitorenter: 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.VarProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructMethod; 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.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
@ -45,23 +46,22 @@ import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class FinallyProcessor { public class FinallyProcessor {
private final Map<Integer, Integer> finallyBlockIDs = new HashMap<Integer, Integer>(); private final Map<Integer, Integer> finallyBlockIDs = new HashMap<Integer, Integer>();
private final Map<Integer, Integer> catchallBlockIDs = 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) { public FinallyProcessor(MethodDescriptor md, VarProcessor varProc) {
this.varprocessor = varprocessor; methodDescriptor = md;
varProcessor = varProc;
} }
public boolean iterateGraph(StructMethod mt, RootStatement root, ControlFlowGraph graph) { public boolean iterateGraph(StructMethod mt, RootStatement root, ControlFlowGraph graph) {
// return processStatement(mt, root, graph, root);
return processStatementEx(mt, root, graph); return processStatementEx(mt, root, graph);
} }
private boolean processStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) { private boolean processStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) {
int bytecode_version = mt.getClassStruct().getBytecodeVersion(); int bytecode_version = mt.getClassStruct().getBytecodeVersion();
LinkedList<Statement> stack = new LinkedList<Statement>(); LinkedList<Statement> stack = new LinkedList<Statement>();
@ -87,7 +87,7 @@ public class FinallyProcessor {
fin.setFinally(true); fin.setFinally(true);
Integer var = finallyBlockIDs.get(handler.id); 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 { else {
@ -190,9 +190,7 @@ public class FinallyProcessor {
} }
} }
private Record getFinallyInformation(StructMethod mt, RootStatement root, CatchAllStatement fstat) {
private static Record getFinallyInformation(StructMethod mt, RootStatement root, CatchAllStatement fstat) {
Map<BasicBlock, Boolean> mapLast = new HashMap<BasicBlock, Boolean>(); Map<BasicBlock, Boolean> mapLast = new HashMap<BasicBlock, Boolean>();
BasicBlockStatement firstBlockStatement = fstat.getHandler().getBasichead(); BasicBlockStatement firstBlockStatement = fstat.getHandler().getBasichead();
@ -209,7 +207,7 @@ public class FinallyProcessor {
firstcode = 2; firstcode = 2;
} }
ExprProcessor proc = new ExprProcessor(); ExprProcessor proc = new ExprProcessor(methodDescriptor, varProcessor);
proc.processStatement(root, mt.getClassStruct()); proc.processStatement(root, mt.getClassStruct());
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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}); mapNumComparisons.put(FunctionExprent.FUNCTION_LE, new Integer[]{FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE, null});
} }
public static boolean identifySecondaryFunctions(Statement stat, VarProcessor varProc) {
public static boolean identifySecondaryFunctions(Statement stat) {
if (stat.getExprents() == null) { if (stat.getExprents() == null) {
// if(){;}else{...} -> if(!){...} // if(){;}else{...} -> if(!){...}
if (stat.type == Statement.TYPE_IF) { if (stat.type == Statement.TYPE_IF) {
@ -100,7 +98,6 @@ public class SecondaryFunctionsHelper {
} }
} }
boolean replaced = true; boolean replaced = true;
while (replaced) { while (replaced) {
replaced = false; replaced = false;
@ -111,13 +108,13 @@ public class SecondaryFunctionsHelper {
Object obj = lstObjects.get(i); Object obj = lstObjects.get(i);
if (obj instanceof Statement) { if (obj instanceof Statement) {
if (identifySecondaryFunctions((Statement)obj)) { if (identifySecondaryFunctions((Statement)obj, varProc)) {
replaced = true; replaced = true;
break; break;
} }
} }
else if (obj instanceof Exprent) { else if (obj instanceof Exprent) {
Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true); Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true, varProc);
if (retexpr != null) { if (retexpr != null) {
if (stat.getExprents() == null) { if (stat.getExprents() == null) {
// only head expressions can be replaced! // only head expressions can be replaced!
@ -136,9 +133,7 @@ public class SecondaryFunctionsHelper {
return false; return false;
} }
private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level, VarProcessor varProc) {
private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level) {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
@ -202,7 +197,7 @@ public class SecondaryFunctionsHelper {
replaced = false; replaced = false;
for (Exprent expr : exprent.getAllExprents()) { for (Exprent expr : exprent.getAllExprents()) {
Exprent retexpr = identifySecondaryFunctions(expr, false); Exprent retexpr = identifySecondaryFunctions(expr, false, varProc);
if (retexpr != null) { if (retexpr != null) {
exprent.replaceExprent(expr, retexpr); exprent.replaceExprent(expr, retexpr);
replaced = true; replaced = true;
@ -301,21 +296,20 @@ public class SecondaryFunctionsHelper {
case FunctionExprent.FUNCTION_DCMPG: case FunctionExprent.FUNCTION_DCMPG:
int var = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER); int var = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER);
VarType type = lstOperands.get(0).getExprType(); VarType type = lstOperands.get(0).getExprType();
VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList( 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), ConstExprent.getZeroConstant(type.type)), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(-1), null), new ConstExprent(VarType.VARTYPE_INT, new Integer(-1), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(1), null)), null); new ConstExprent(VarType.VARTYPE_INT, new Integer(1), null)), null);
FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList( FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(
new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB, new AssignmentExprent(new VarExprent(var, type, varProc),
Arrays.asList(lstOperands.get(0), new FunctionExprent(FunctionExprent.FUNCTION_SUB, Arrays.asList(lstOperands.get(0), lstOperands.get(1)), null),
lstOperands.get(1)), null), null), null),
ConstExprent.getZeroConstant(type.type)), 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( return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null), iff), fexpr.bytecode); 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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; 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.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.struct.StructMethod; 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.struct.gen.VarType;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class VarProcessor { public class VarProcessor {
private final StructMethod method;
private final MethodDescriptor methodDescriptor;
private Map<VarVersionPair, String> mapVarNames = new HashMap<VarVersionPair, String>(); private Map<VarVersionPair, String> mapVarNames = new HashMap<VarVersionPair, String>();
private VarVersionsProcessor varVersions; private VarVersionsProcessor varVersions;
private final Map<VarVersionPair, String> thisVars = new HashMap<VarVersionPair, String>(); private final Map<VarVersionPair, String> thisVars = new HashMap<VarVersionPair, String>();
private final Set<VarVersionPair> externalVars = new HashSet<VarVersionPair>(); private final Set<VarVersionPair> externalVars = new HashSet<VarVersionPair>();
public VarProcessor(StructMethod mt, MethodDescriptor md) {
method = mt;
methodDescriptor = md;
}
public void setVarVersions(RootStatement root) { public void setVarVersions(RootStatement root) {
varVersions = new VarVersionsProcessor(); varVersions = new VarVersionsProcessor(method, methodDescriptor);
varVersions.setVarVersions(root); varVersions.setVarVersions(root);
} }
public void setVarDefinitions(Statement root) { public void setVarDefinitions(Statement root) {
mapVarNames = new HashMap<VarVersionPair, String>(); mapVarNames = new HashMap<VarVersionPair, String>();
new VarDefinitionHelper(root, method, this).setVarDefinitions();
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
new VarDefinitionHelper(root, mt, this).setVarDefinitions();
} }
public void setDebugVarNames(Map<Integer, String> mapDebugVarNames) { public void setDebugVarNames(Map<Integer, String> mapDebugVarNames) {
@ -52,12 +56,7 @@ public class VarProcessor {
Map<Integer, Integer> mapOriginalVarIndices = varVersions.getMapOriginalVarIndices(); Map<Integer, Integer> mapOriginalVarIndices = varVersions.getMapOriginalVarIndices();
List<VarVersionPair> listVars = new ArrayList<VarVersionPair>(mapVarNames.keySet()); List<VarVersionPair> listVars = new ArrayList<VarVersionPair>(mapVarNames.keySet());
Collections.sort(listVars, new Comparator<VarVersionPair>() { Collections.sort(listVars, (o1, o2) -> o1.var - o2.var);
@Override
public int compare(VarVersionPair o1, VarVersionPair o2) {
return o1.var - o2.var;
}
});
Map<String, Integer> mapNames = new HashMap<String, Integer>(); 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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; import java.util.Map;
public class VarTypeProcessor { public class VarTypeProcessor {
public static final int VAR_NON_FINAL = 1; public static final int VAR_NON_FINAL = 1;
public static final int VAR_EXPLICIT_FINAL = 2; public static final int VAR_EXPLICIT_FINAL = 2;
public static final int VAR_FINAL = 3; 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> mapExprentMinTypes = new HashMap<VarVersionPair, VarType>();
private final Map<VarVersionPair, VarType> mapExprentMaxTypes = 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 final Map<VarVersionPair, Integer> mapFinalVars = new HashMap<VarVersionPair, Integer>();
private void setInitVars(RootStatement root) { public VarTypeProcessor(StructMethod mt, MethodDescriptor md) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD); 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) { if (thisVar) {
StructClass cl = (StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS); 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) { private static void resetExprentTypes(DirectGraph graph) {
graph.iterateExprents(new DirectGraph.ExprentIterator() { graph.iterateExprents(new DirectGraph.ExprentIterator() {
@Override @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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.sforms.SSAConstructorSparseEx;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.struct.StructMethod; 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.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet; import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet;
@ -33,25 +34,27 @@ import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class VarVersionsProcessor { public class VarVersionsProcessor {
private final StructMethod method;
private Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>(); private Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>();
private VarTypeProcessor typeProcessor; private VarTypeProcessor typeProcessor;
public void setVarVersions(RootStatement root) { public VarVersionsProcessor(StructMethod mt, MethodDescriptor md) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD); method = mt;
typeProcessor = new VarTypeProcessor(mt, md);
}
public void setVarVersions(RootStatement root) {
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, mt); ssa.splitVariables(root, method);
FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper(); FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper();
DirectGraph graph = flattenHelper.buildDirectGraph(root); DirectGraph graph = flattenHelper.buildDirectGraph(root);
mergePhiVersions(ssa, graph); mergePhiVersions(ssa, graph);
typeProcessor = new VarTypeProcessor();
typeProcessor.calculateVarTypes(root, graph); typeProcessor.calculateVarTypes(root, graph);
simpleMerge(typeProcessor, graph, mt); simpleMerge(typeProcessor, graph, method);
// FIXME: advanced merging // FIXME: advanced merging

Loading…
Cancel
Save