[java decompiler] cleanup (duplicates; dead code; typos; formatting)

master
Roman Shevchenko 7 years ago
parent acf6646941
commit b3171e60c9
  1. 21
      src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
  2. 17
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  3. 5
      src/org/jetbrains/java/decompiler/main/rels/MethodWrapper.java
  4. 60
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  5. 34
      src/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java
  6. 374
      src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java
  7. 119
      src/org/jetbrains/java/decompiler/modules/decompiler/StackVarsProcessor.java
  8. 35
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExprUtil.java
  9. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java
  10. 32
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  11. 82
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  12. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java
  13. 26
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsGraph.java
  14. 3
      src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java
  15. 5
      src/org/jetbrains/java/decompiler/struct/match/IMatchable.java
  16. 117
      src/org/jetbrains/java/decompiler/struct/match/MatchEngine.java
  17. 11
      src/org/jetbrains/java/decompiler/struct/match/MatchNode.java
  18. 2
      test/org/jetbrains/java/decompiler/DecompilerTestFixture.java

@ -42,10 +42,8 @@ public class ClassReference14Processor {
ctor.setStringDescriptor("()V");
ctor.setFunctype(InvocationExprent.TYP_INIT);
ctor.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
NewExprent newExpr = new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<>(), null);
newExpr.setConstructor(ctor);
InvocationExprent invCause = new InvocationExprent();
invCause.setName("initCause");
invCause.setClassname("java/lang/NoClassDefFoundError");
@ -54,18 +52,18 @@ public class ClassReference14Processor {
invCause.setInstance(newExpr);
invCause.setLstParameters(
Collections.singletonList(new VarExprent(2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null)));
HANDLER_EXPR = new ExitExprent(ExitExprent.EXIT_THROW, invCause, null, null);
}
public static void processClassReferences(ClassNode node) {
// find the synthetic method Class class$(String) if present
HashMap<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<>();
Map<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<>();
mapClassMethods(node, mapClassMeths);
if (mapClassMeths.isEmpty()) {
return;
}
HashSet<ClassWrapper> setFound = new HashSet<>();
Set<ClassWrapper> setFound = new HashSet<>();
processClassRec(node, mapClassMeths, setFound);
if (!setFound.isEmpty()) {
@ -76,15 +74,11 @@ public class ClassReference14Processor {
}
}
private static void processClassRec(ClassNode node,
final HashMap<ClassWrapper, MethodWrapper> mapClassMeths,
final HashSet<ClassWrapper> setFound) {
final ClassWrapper wrapper = node.getWrapper();
private static void processClassRec(ClassNode node, Map<ClassWrapper, MethodWrapper> mapClassMeths, Set<ClassWrapper> setFound) {
ClassWrapper wrapper = node.getWrapper();
// search code
for (MethodWrapper meth : wrapper.getMethods()) {
RootStatement root = meth.root;
if (root != null) {
DirectGraph graph = meth.getOrBuildGraph();
@ -166,13 +160,10 @@ public class ClassReference14Processor {
}
}
private static boolean replaceInvocations(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
boolean res = false;
while (true) {
boolean found = false;
for (Exprent expr : exprent.getAllExprents()) {
@ -195,9 +186,7 @@ public class ClassReference14Processor {
return res;
}
private static String isClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent;
if (fexpr.getFuncType() == FunctionExprent.FUNCTION_IIF) {

@ -647,11 +647,13 @@ public class ClassWriter {
descriptor = GenericMain.parseMethodSignature(attr.getSignature());
if (descriptor != null) {
long actualParams = md.params.length;
List<VarVersionPair> sigFields = methodWrapper.signatureFields;
if (sigFields != null) {
actualParams = sigFields.stream().filter(Objects::isNull).count();
List<VarVersionPair> mask = methodWrapper.synthParameters;
if (mask != null) {
actualParams = mask.stream().filter(Objects::isNull).count();
}
else if (isEnum && init) {
actualParams -= 2;
}
else if (isEnum && init) actualParams -= 2;
if (actualParams != descriptor.params.size()) {
String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor() + " in " + cl.qualifiedName;
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
@ -685,12 +687,11 @@ public class ClassWriter {
buffer.append(toValidJavaIdentifier(name));
buffer.append('(');
// parameters
List<VarVersionPair> signFields = methodWrapper.signatureFields;
List<VarVersionPair> mask = methodWrapper.synthParameters;
int lastVisibleParameterIndex = -1;
for (int i = 0; i < md.params.length; i++) {
if (signFields == null || signFields.get(i) == null) {
if (mask == null || mask.get(i) == null) {
lastVisibleParameterIndex = i;
}
}
@ -701,7 +702,7 @@ public class ClassWriter {
int start = isEnum && init && !hasDescriptor ? 2 : 0;
int params = hasDescriptor ? descriptor.params.size() : md.params.length;
for (int i = start; i < params; i++) {
if (hasDescriptor || (signFields == null || signFields.get(i) == null)) {
if (hasDescriptor || mask == null || mask.get(i) == null) {
if (!firstParameter) {
buffer.append(", ");
}

@ -11,16 +11,17 @@ import org.jetbrains.java.decompiler.struct.StructMethod;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MethodWrapper {
public final RootStatement root;
public final VarProcessor varproc;
public final StructMethod methodStruct;
public final CounterContainer counter;
public final HashSet<String> setOuterVarNames = new HashSet<>();
public final Set<String> setOuterVarNames = new HashSet<>();
public DirectGraph graph;
public List<VarVersionPair> signatureFields;
public List<VarVersionPair> synthParameters;
public boolean decompiledWithErrors;
public MethodWrapper(RootStatement root, VarProcessor varproc, StructMethod methodStruct, CounterContainer counter) {

@ -28,7 +28,6 @@ import java.util.*;
import java.util.Map.Entry;
public class NestedClassProcessor {
public void processClass(ClassNode root, ClassNode node) {
// hide synthetic lambda content methods
if (node.type == ClassNode.CLASS_LAMBDA && !node.lambdaInformation.is_method_reference) {
@ -93,22 +92,18 @@ public class NestedClassProcessor {
}
MethodWrapper method = parent.getWrapper().getMethods().getWithKey(child.lambdaInformation.content_method_key);
final MethodWrapper enclosingMethod = parent.getWrapper().getMethods().getWithKey(child.enclosingMethod);
MethodWrapper enclosingMethod = parent.getWrapper().getMethods().getWithKey(child.enclosingMethod);
MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(child.lambdaInformation.method_descriptor);
final MethodDescriptor md_content = MethodDescriptor.parseDescriptor(child.lambdaInformation.content_method_descriptor);
final int vars_count = md_content.params.length - md_lambda.params.length;
// if(vars_count < 0) { // should not happen, but just in case...
// vars_count = 0;
// }
MethodDescriptor md_content = MethodDescriptor.parseDescriptor(child.lambdaInformation.content_method_descriptor);
final boolean is_static_lambda_content = child.lambdaInformation.is_content_method_static;
int vars_count = md_content.params.length - md_lambda.params.length;
boolean is_static_lambda_content = child.lambdaInformation.is_content_method_static;
String parent_class_name = parent.getWrapper().getClassStruct().qualifiedName;
String lambda_class_name = child.simpleName;
final VarType lambda_class_type = new VarType(lambda_class_name, true);
VarType lambda_class_type = new VarType(lambda_class_name, true);
// this pointer
if (!is_static_lambda_content && DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS)) {
@ -116,7 +111,7 @@ public class NestedClassProcessor {
method.varproc.setVarName(new VarVersionPair(0, 0), parent.simpleName + ".this");
}
final Map<VarVersionPair, String> mapNewNames = new HashMap<>();
Map<VarVersionPair, String> mapNewNames = new HashMap<>();
enclosingMethod.getOrBuildGraph().iterateExprents(exprent -> {
List<Exprent> lst = exprent.getAllExprents(true);
@ -172,7 +167,7 @@ public class NestedClassProcessor {
List<ClassNode> copy = new ArrayList<>(node.nested);
for (ClassNode child : copy) {
if (child.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
if (child.classStruct.isSynthetic()) {
continue;
}
@ -234,19 +229,15 @@ public class NestedClassProcessor {
return false;
}
private static void computeLocalVarsAndDefinitions(final ClassNode node) {
// local var masks
// class name, constructor descriptor, field mask
final Map<String, Map<String, List<VarFieldPair>>> mapVarMasks = new HashMap<>();
private static void computeLocalVarsAndDefinitions(ClassNode node) {
// class name -> constructor descriptor -> var to field link
Map<String, Map<String, List<VarFieldPair>>> mapVarMasks = new HashMap<>();
int clTypes = 0;
for (ClassNode nd : node.nested) {
if (nd.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
continue;
}
if (nd.type != ClassNode.CLASS_LAMBDA &&
!nd.classStruct.isSynthetic() &&
(nd.access & CodeConstants.ACC_STATIC) == 0 &&
(nd.access & CodeConstants.ACC_INTERFACE) == 0) {
clTypes |= nd.type;
@ -263,11 +254,11 @@ public class NestedClassProcessor {
}
// local var masks
final Map<String, Map<String, List<VarFieldPair>>> mapVarFieldPairs = new HashMap<>();
Map<String, Map<String, List<VarFieldPair>>> mapVarFieldPairs = new HashMap<>();
if (clTypes != ClassNode.CLASS_MEMBER) {
// iterate enclosing class
for (final MethodWrapper method : node.getWrapper().getMethods()) {
for (MethodWrapper method : node.getWrapper().getMethods()) {
if (method.root != null) { // neither abstract, nor native
method.getOrBuildGraph().iterateExprents(exprent -> {
List<Exprent> lst = exprent.getAllExprents(true);
@ -388,34 +379,33 @@ public class NestedClassProcessor {
for (Entry<String, List<VarFieldPair>> entry : enclosing.getValue().entrySet()) {
mergeListSignatures(entry.getValue(), interPairMask, false);
MethodWrapper method = nestedNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, entry.getKey());
method.signatureFields = new ArrayList<>();
List<VarVersionPair> mask = new ArrayList<>(entry.getValue().size());
boolean firstSignField = nestedNode.type != ClassNode.CLASS_ANONYMOUS;
for (VarFieldPair pair : entry.getValue()) {
method.signatureFields.add(pair == null || (!firstSignField && pair.fieldKey.isEmpty()) ? null : pair.varPair);
mask.add(pair == null || (!firstSignField && pair.fieldKey.isEmpty()) ? null : pair.varPair);
firstSignField = false;
}
nestedNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, entry.getKey()).synthParameters = mask;
}
}
}
private static void insertLocalVars(ClassNode parent, final ClassNode child) {
private static void insertLocalVars(ClassNode parent, ClassNode child) {
// enclosing method, is null iff member class
MethodWrapper enclosingMethod = parent.getWrapper().getMethods().getWithKey(child.enclosingMethod);
// iterate all child methods
for (final MethodWrapper method : child.getWrapper().getMethods()) {
for (MethodWrapper method : child.getWrapper().getMethods()) {
if (method.root != null) { // neither abstract nor native
Map<VarVersionPair, String> mapNewNames = new HashMap<>(); // local var names
Map<VarVersionPair, VarType> mapNewTypes = new HashMap<>(); // local var types
final Map<Integer, VarVersionPair> mapParamsToNewVars = new HashMap<>();
if (method.signatureFields != null) {
Map<Integer, VarVersionPair> mapParamsToNewVars = new HashMap<>();
if (method.synthParameters != null) {
int index = 0, varIndex = 1;
MethodDescriptor md = MethodDescriptor.parseDescriptor(method.methodStruct.getDescriptor());
for (VarVersionPair pair : method.signatureFields) {
for (VarVersionPair pair : method.synthParameters) {
if (pair != null) {
VarVersionPair newVar = new VarVersionPair(method.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER), 0);
@ -450,7 +440,7 @@ public class NestedClassProcessor {
}
}
final Map<String, VarVersionPair> mapFieldsToNewVars = new HashMap<>();
Map<String, VarVersionPair> mapFieldsToNewVars = new HashMap<>();
for (ClassNode classNode = child; classNode != null; classNode = classNode.parent) {
for (Entry<String, VarVersionPair> entry : classNode.mapFieldsToVars.entrySet()) {
VarVersionPair newVar = new VarVersionPair(method.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER), 0);
@ -632,10 +622,10 @@ public class NestedClassProcessor {
assignExpr.getLeft().type == Exprent.EXPRENT_FIELD) {
FieldExprent left = (FieldExprent)assignExpr.getLeft();
StructField fd = cl.getField(left.getName(), left.getDescriptor().descriptorString);
if (fd != null && cl.qualifiedName.equals(left.getClassname()) &&
if (fd != null &&
cl.qualifiedName.equals(left.getClassname()) &&
fd.hasModifier(CodeConstants.ACC_FINAL) &&
(fd.isSynthetic() || (noSynthFlag && fd.hasModifier(CodeConstants.ACC_PRIVATE)))) {
(fd.isSynthetic() || noSynthFlag && fd.hasModifier(CodeConstants.ACC_PRIVATE))) {
// local (== not inherited) field
field = InterpreterUtil.makeUniqueKey(left.getName(), left.getDescriptor().descriptorString);
break;

@ -9,39 +9,25 @@ import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.SequenceStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.*;
public class IfHelper {
public static boolean mergeAllIfs(RootStatement root) {
boolean res = mergeAllIfsRec(root, new HashSet<>());
if (res) {
SequenceHelper.condenseSequences(root);
}
return res;
}
private static boolean mergeAllIfsRec(Statement stat, HashSet<Integer> setReorderedIfs) {
private static boolean mergeAllIfsRec(Statement stat, Set<Integer> setReorderedIfs) {
boolean res = false;
if (stat.getExprents() == null) {
while (true) {
boolean changed = false;
for (Statement st : stat.getStats()) {
res |= mergeAllIfsRec(st, setReorderedIfs);
// collapse composed if's
@ -61,7 +47,7 @@ public class IfHelper {
return res;
}
public static boolean mergeIfs(Statement statement, HashSet<Integer> setReorderedIfs) {
public static boolean mergeIfs(Statement statement, Set<Integer> setReorderedIfs) {
if (statement.type != Statement.TYPE_IF && statement.type != Statement.TYPE_SEQUENCE) {
return false;
}
@ -193,11 +179,9 @@ public class IfHelper {
}
private static boolean collapseIfElse(IfNode rtnode) {
if (rtnode.edgetypes.get(0) == 0) {
IfNode ifbranch = rtnode.succs.get(0);
if (ifbranch.succs.size() == 2) {
// if-else branch
if (ifbranch.succs.get(0).value == rtnode.succs.get(1).value) {
@ -245,9 +229,7 @@ public class IfHelper {
return false;
}
private static boolean collapseElse(IfNode rtnode) {
if (rtnode.edgetypes.get(1) == 0) {
IfNode elsebranch = rtnode.succs.get(1);
if (elsebranch.succs.size() == 2) {
@ -308,9 +290,7 @@ public class IfHelper {
}
}
else if (elsebranch.succs.size() == 1) {
if (elsebranch.succs.get(0).value == rtnode.succs.get(0).value) {
IfStatement firstif = (IfStatement)rtnode.value;
Statement second = elsebranch.value;
@ -349,9 +329,7 @@ public class IfHelper {
return false;
}
private static IfNode buildGraph(IfStatement stat, boolean stsingle) {
if (stat.iftype == IfStatement.IFTYPE_IFELSE) {
return null;
}
@ -664,9 +642,7 @@ public class IfHelper {
return false;
}
private static Statement getNextStatement(Statement stat) {
Statement parent = stat.getParent();
switch (parent.type) {
case Statement.TYPE_ROOT:
@ -688,7 +664,6 @@ public class IfHelper {
}
private static boolean existsPath(Statement from, Statement to) {
for (StatEdge edge : to.getAllPredecessorEdges()) {
if (from.containsStatementStrict(edge.getSource())) {
return true;
@ -700,7 +675,6 @@ public class IfHelper {
private static class IfNode {
public final Statement value;
public final List<IfNode> succs = new ArrayList<>();
public final List<Integer> edgetypes = new ArrayList<>();
@ -713,4 +687,4 @@ public class IfHelper {
edgetypes.add(type);
}
}
}
}

@ -21,7 +21,29 @@ import java.util.*;
import java.util.Map.Entry;
public class SimplifyExprentsHelper {
static final MatchEngine class14Builder = new MatchEngine();
@SuppressWarnings("SpellCheckingInspection") private static final MatchEngine class14Builder = new MatchEngine(
"statement type:if iftype:if exprsize:-1\n" +
" exprent position:head type:if\n" +
" exprent type:function functype:eq\n" +
" exprent type:field name:$fieldname$\n" +
" exprent type:constant consttype:null\n" +
" statement type:basicblock\n" +
" exprent position:-1 type:assignment ret:$assignfield$\n" +
" exprent type:var index:$var$\n" +
" exprent type:field name:$fieldname$\n" +
" statement type:sequence statsize:2\n" +
" statement type:trycatch\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:assignment\n" +
" exprent type:var index:$var$\n" +
" exprent type:invocation invclass:java/lang/Class signature:forName(Ljava/lang/String;)Ljava/lang/Class;\n" +
" exprent position:0 type:constant consttype:string constvalue:$classname$\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:exit exittype:throw\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:assignment\n" +
" exprent type:field name:$fieldname$ ret:$field$\n" +
" exprent type:var index:$var$");
private final boolean firstInvocation;
@ -29,10 +51,11 @@ public class SimplifyExprentsHelper {
this.firstInvocation = firstInvocation;
}
public boolean simplifyStackVarsStatement(Statement stat, HashSet<Integer> setReorderedIfs, SSAConstructorSparseEx ssa, StructClass cl) {
public boolean simplifyStackVarsStatement(Statement stat, Set<Integer> setReorderedIfs, SSAConstructorSparseEx ssa, StructClass cl) {
boolean res = false;
if (stat.getExprents() == null) {
List<Exprent> expressions = stat.getExprents();
if (expressions == null) {
boolean processClass14 = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4);
while (true) {
@ -65,7 +88,7 @@ public class SimplifyExprentsHelper {
}
}
else {
res = simplifyStackVarsExprents(stat.getExprents(), cl);
res = simplifyStackVarsExprents(expressions, cl);
}
return res;
@ -75,7 +98,6 @@ public class SimplifyExprentsHelper {
boolean res = false;
int index = 0;
while (index < list.size()) {
Exprent current = list.get(index);
@ -131,9 +153,9 @@ public class SimplifyExprentsHelper {
}
// direct initialization of an array
int arrcount = isArrayInitializer(list, index);
if (arrcount > 0) {
for (int i = 0; i < arrcount; i++) {
int arrCount = isArrayInitializer(list, index);
if (arrCount > 0) {
for (int i = 0; i < arrCount; i++) {
list.remove(index + 1);
}
res = true;
@ -163,13 +185,13 @@ public class SimplifyExprentsHelper {
}
// assignment on stack
if (isStackAssignement(current, next)) {
if (isStackAssignment(current, next)) {
list.remove(index + 1);
res = true;
continue;
}
if (!firstInvocation && isStackAssignement2(current, next)) {
if (!firstInvocation && isStackAssignment2(current, next)) {
list.remove(index + 1);
res = true;
continue;
@ -186,38 +208,38 @@ public class SimplifyExprentsHelper {
AssignmentExprent as = (AssignmentExprent)first;
if (as.getRight().type == Exprent.EXPRENT_NEW && as.getLeft().type == Exprent.EXPRENT_VAR) {
NewExprent newex = (NewExprent)as.getRight();
NewExprent newExpr = (NewExprent)as.getRight();
if (!newex.getLstArrayElements().isEmpty()) {
VarExprent arrvar = (VarExprent)as.getLeft();
if (!newExpr.getLstArrayElements().isEmpty()) {
VarExprent arrVar = (VarExprent)as.getLeft();
if (second.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent aas = (AssignmentExprent)second;
if (aas.getLeft().type == Exprent.EXPRENT_ARRAY) {
ArrayExprent arrex = (ArrayExprent)aas.getLeft();
if (arrex.getArray().type == Exprent.EXPRENT_VAR && arrvar.equals(arrex.getArray())
&& arrex.getIndex().type == Exprent.EXPRENT_CONST) {
int constvalue = ((ConstExprent)arrex.getIndex()).getIntValue();
if (constvalue < newex.getLstArrayElements().size()) {
Exprent init = newex.getLstArrayElements().get(constvalue);
ArrayExprent arrExpr = (ArrayExprent)aas.getLeft();
if (arrExpr.getArray().type == Exprent.EXPRENT_VAR &&
arrVar.equals(arrExpr.getArray()) &&
arrExpr.getIndex().type == Exprent.EXPRENT_CONST) {
int constValue = ((ConstExprent)arrExpr.getIndex()).getIntValue();
if (constValue < newExpr.getLstArrayElements().size()) {
Exprent init = newExpr.getLstArrayElements().get(constValue);
if (init.type == Exprent.EXPRENT_CONST) {
ConstExprent cinit = (ConstExprent)init;
VarType arrtype = newex.getNewType().decreaseArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
VarType arrType = newExpr.getNewType().decreaseArrayDim();
ConstExprent defaultVal = ExprProcessor.getDefaultArrayValue(arrType);
if (cinit.equals(defaultval)) {
Exprent tempexpr = aas.getRight();
if (cinit.equals(defaultVal)) {
Exprent tempExpr = aas.getRight();
if (!tempexpr.containsExprent(arrvar)) {
newex.getLstArrayElements().set(constvalue, tempexpr);
if (!tempExpr.containsExprent(arrVar)) {
newExpr.getLstArrayElements().set(constValue, tempExpr);
if (tempexpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempnewex = (NewExprent)tempexpr;
int dims = newex.getNewType().arrayDim;
if (dims > 1 && !tempnewex.getLstArrayElements().isEmpty()) {
tempnewex.setDirectArrayInit(true);
if (tempExpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempNewExpr = (NewExprent)tempExpr;
int dims = newExpr.getNewType().arrayDim;
if (dims > 1 && !tempNewExpr.getLstArrayElements().isEmpty()) {
tempNewExpr.setDirectArrayInit(true);
}
}
@ -242,19 +264,18 @@ public class SimplifyExprentsHelper {
AssignmentExprent as = (AssignmentExprent)current;
if (as.getRight().type == Exprent.EXPRENT_NEW && as.getLeft().type == Exprent.EXPRENT_VAR) {
NewExprent newex = (NewExprent)as.getRight();
NewExprent newExpr = (NewExprent)as.getRight();
if (newex.getExprType().arrayDim > 0 && newex.getLstDims().size() == 1 && newex.getLstArrayElements().isEmpty() &&
newex.getLstDims().get(0).type == Exprent.EXPRENT_CONST) {
if (newExpr.getExprType().arrayDim > 0 && newExpr.getLstDims().size() == 1 && newExpr.getLstArrayElements().isEmpty() &&
newExpr.getLstDims().get(0).type == Exprent.EXPRENT_CONST) {
int size = (Integer)((ConstExprent)newex.getLstDims().get(0)).getValue();
int size = (Integer)((ConstExprent)newExpr.getLstDims().get(0)).getValue();
if (size == 0) {
return 0;
}
VarExprent arrvar = (VarExprent)as.getLeft();
HashMap<Integer, Exprent> mapInit = new HashMap<>();
VarExprent arrVar = (VarExprent)as.getLeft();
Map<Integer, Exprent> mapInit = new HashMap<>();
int i = 1;
while (index + i < list.size() && i <= size) {
@ -264,17 +285,14 @@ public class SimplifyExprentsHelper {
if (expr.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent aas = (AssignmentExprent)expr;
if (aas.getLeft().type == Exprent.EXPRENT_ARRAY) {
ArrayExprent arrex = (ArrayExprent)aas.getLeft();
if (arrex.getArray().type == Exprent.EXPRENT_VAR && arrvar.equals(arrex.getArray())
&& arrex.getIndex().type == Exprent.EXPRENT_CONST) {
int constvalue = ((ConstExprent)arrex.getIndex())
.getIntValue(); // TODO: check for a number type. Failure extremely improbable, but nevertheless...
if (constvalue < size && !mapInit.containsKey(constvalue)) {
if (!aas.getRight().containsExprent(arrvar)) {
mapInit.put(constvalue, aas.getRight());
ArrayExprent arrExpr = (ArrayExprent)aas.getLeft();
if (arrExpr.getArray().type == Exprent.EXPRENT_VAR && arrVar.equals(arrExpr.getArray()) &&
arrExpr.getIndex().type == Exprent.EXPRENT_CONST) {
// TODO: check for a number type. Failure extremely improbable, but nevertheless...
int constValue = ((ConstExprent)arrExpr.getIndex()).getIntValue();
if (constValue < size && !mapInit.containsKey(constValue)) {
if (!aas.getRight().containsExprent(arrVar)) {
mapInit.put(constValue, aas.getRight());
found = true;
}
}
@ -291,33 +309,29 @@ public class SimplifyExprentsHelper {
double fraction = ((double)mapInit.size()) / size;
if ((arrvar.isStack() && fraction > 0) || (size <= 7 && fraction >= 0.3) ||
(size > 7 && fraction >= 0.7)) {
if ((arrVar.isStack() && fraction > 0) || (size <= 7 && fraction >= 0.3) || (size > 7 && fraction >= 0.7)) {
List<Exprent> lstRet = new ArrayList<>();
VarType arrtype = newex.getNewType().decreaseArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
VarType arrayType = newExpr.getNewType().decreaseArrayDim();
ConstExprent defaultVal = ExprProcessor.getDefaultArrayValue(arrayType);
for (int j = 0; j < size; j++) {
lstRet.add(defaultval.copy());
lstRet.add(defaultVal.copy());
}
int dims = newex.getNewType().arrayDim;
int dims = newExpr.getNewType().arrayDim;
for (Entry<Integer, Exprent> ent : mapInit.entrySet()) {
Exprent tempexpr = ent.getValue();
lstRet.set(ent.getKey(), tempexpr);
Exprent tempExpr = ent.getValue();
lstRet.set(ent.getKey(), tempExpr);
if (tempexpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempnewex = (NewExprent)tempexpr;
if (dims > 1 && !tempnewex.getLstArrayElements().isEmpty()) {
tempnewex.setDirectArrayInit(true);
if (tempExpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempNewExpr = (NewExprent)tempExpr;
if (dims > 1 && !tempNewExpr.getLstArrayElements().isEmpty()) {
tempNewExpr.setDirectArrayInit(true);
}
}
}
newex.setLstArrayElements(lstRet);
newExpr.setLstArrayElements(lstRet);
return mapInit.size();
}
@ -333,17 +347,16 @@ public class SimplifyExprentsHelper {
AssignmentExprent asf = (AssignmentExprent)first;
if (asf.getLeft().type == Exprent.EXPRENT_VAR && asf.getRight().type == Exprent.EXPRENT_VAR) {
VarExprent varleft = (VarExprent)asf.getLeft();
VarExprent varright = (VarExprent)asf.getRight();
return varleft.getIndex() == varright.getIndex() && varleft.isStack() && varright.isStack();
VarExprent left = (VarExprent)asf.getLeft();
VarExprent right = (VarExprent)asf.getRight();
return left.getIndex() == right.getIndex() && left.isStack() && right.isStack();
}
}
return false;
}
private static boolean isStackAssignement2(Exprent first, Exprent second) { // e.g. 1.4-style class invocation
private static boolean isStackAssignment2(Exprent first, Exprent second) { // e.g. 1.4-style class invocation
if (first.type == Exprent.EXPRENT_ASSIGNMENT && second.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent asf = (AssignmentExprent)first;
AssignmentExprent ass = (AssignmentExprent)second;
@ -360,7 +373,7 @@ public class SimplifyExprentsHelper {
return false;
}
private static boolean isStackAssignement(Exprent first, Exprent second) {
private static boolean isStackAssignment(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT && second.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent asf = (AssignmentExprent)first;
AssignmentExprent ass = (AssignmentExprent)second;
@ -395,8 +408,7 @@ public class SimplifyExprentsHelper {
if (as.getRight().type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent func = (FunctionExprent)as.getRight();
if (func.getFuncType() == FunctionExprent.FUNCTION_ADD ||
func.getFuncType() == FunctionExprent.FUNCTION_SUB) {
if (func.getFuncType() == FunctionExprent.FUNCTION_ADD || func.getFuncType() == FunctionExprent.FUNCTION_SUB) {
Exprent econd = func.getLstOperands().get(0);
Exprent econst = func.getLstOperands().get(1);
@ -410,9 +422,8 @@ public class SimplifyExprentsHelper {
Exprent left = as.getLeft();
if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) {
FunctionExprent ret = new FunctionExprent(
func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI,
econd, func.bytecode);
int type = func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI;
FunctionExprent ret = new FunctionExprent(type, econd, func.bytecode);
ret.setImplicitType(VarType.VARTYPE_INT);
return ret;
}
@ -449,10 +460,10 @@ public class SimplifyExprentsHelper {
private static boolean isMonitorExit(Exprent first) {
if (first.type == Exprent.EXPRENT_MONITOR) {
MonitorExprent monexpr = (MonitorExprent)first;
return monexpr.getMonType() == MonitorExprent.MONITOR_EXIT &&
monexpr.getValue().type == Exprent.EXPRENT_VAR &&
!((VarExprent)monexpr.getValue()).isStack();
MonitorExprent expr = (MonitorExprent)first;
return expr.getMonType() == MonitorExprent.MONITOR_EXIT &&
expr.getValue().type == Exprent.EXPRENT_VAR &&
!((VarExprent)expr.getValue()).isStack();
}
return false;
@ -460,21 +471,21 @@ public class SimplifyExprentsHelper {
private static boolean isQualifiedNewGetClass(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_INVOCATION) {
InvocationExprent invexpr = (InvocationExprent)first;
InvocationExprent invocation = (InvocationExprent)first;
if (!invexpr.isStatic() && invexpr.getInstance().type == Exprent.EXPRENT_VAR && invexpr.getName().equals("getClass") &&
invexpr.getStringDescriptor().equals("()Ljava/lang/Class;")) {
if (!invocation.isStatic() && invocation.getInstance().type == Exprent.EXPRENT_VAR && invocation.getName().equals("getClass") &&
invocation.getStringDescriptor().equals("()Ljava/lang/Class;")) {
List<Exprent> lstExprents = second.getAllExprents();
lstExprents.add(second);
for (Exprent expr : lstExprents) {
if (expr.type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)expr;
if (nexpr.getConstructor() != null && !nexpr.getConstructor().getLstParameters().isEmpty() &&
nexpr.getConstructor().getLstParameters().get(0).equals(invexpr.getInstance())) {
NewExprent newExpr = (NewExprent)expr;
if (newExpr.getConstructor() != null && !newExpr.getConstructor().getLstParameters().isEmpty() &&
newExpr.getConstructor().getLstParameters().get(0).equals(invocation.getInstance())) {
String classname = nexpr.getNewType().value;
String classname = newExpr.getNewType().value;
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
if (node != null && node.type != ClassNode.CLASS_ROOT) {
return true;
@ -488,7 +499,7 @@ public class SimplifyExprentsHelper {
return false;
}
// propagate (var = new X) forward to the <init> invokation
// propagate (var = new X) forward to the <init> invocation
private static boolean isConstructorInvocationRemote(List<Exprent> list, int index) {
Exprent current = list.get(index);
@ -497,12 +508,11 @@ public class SimplifyExprentsHelper {
if (as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
NewExprent newexpr = (NewExprent)as.getRight();
VarType newtype = newexpr.getNewType();
VarVersionPair leftPaar = new VarVersionPair((VarExprent)as.getLeft());
if (newtype.type == CodeConstants.TYPE_OBJECT && newtype.arrayDim == 0 && newexpr.getConstructor() == null) {
NewExprent newExpr = (NewExprent)as.getRight();
VarType newType = newExpr.getNewType();
VarVersionPair leftPair = new VarVersionPair((VarExprent)as.getLeft());
if (newType.type == CodeConstants.TYPE_OBJECT && newType.arrayDim == 0 && newExpr.getConstructor() == null) {
for (int i = index + 1; i < list.size(); i++) {
Exprent remote = list.get(i);
@ -513,8 +523,7 @@ public class SimplifyExprentsHelper {
if (in.getFunctype() == InvocationExprent.TYP_INIT &&
in.getInstance().type == Exprent.EXPRENT_VAR &&
as.getLeft().equals(in.getInstance())) {
newexpr.setConstructor(in);
newExpr.setConstructor(in);
in.setInstance(null);
list.set(i, as.copy());
@ -525,7 +534,7 @@ public class SimplifyExprentsHelper {
// check for variable in use
Set<VarVersionPair> setVars = remote.getAllVariables();
if (setVars.contains(leftPaar)) { // variable used somewhere in between -> exit, need a better reduced code
if (setVars.contains(leftPair)) { // variable used somewhere in between -> exit, need a better reduced code
return false;
}
}
@ -553,13 +562,13 @@ public class SimplifyExprentsHelper {
ClassNode lambda_class = DecompilerContext.getClassProcessor().getMapRootClasses().get(lambda_class_name);
if (lambda_class != null) { // real lambda class found, replace invocation with an anonymous class
NewExprent newexp = new NewExprent(new VarType(lambda_class_name, true), null, 0, in.bytecode);
newexp.setConstructor(in);
// note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invokation
NewExprent newExpr = new NewExprent(new VarType(lambda_class_name, true), null, 0, in.bytecode);
newExpr.setConstructor(in);
// note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invocation
// lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);)
// in this case instance will hold the corresponding object
return newexp;
return newExpr;
}
}
}
@ -579,10 +588,10 @@ public class SimplifyExprentsHelper {
if (exprent.type == Exprent.EXPRENT_INVOCATION) {
InvocationExprent in = (InvocationExprent)exprent;
if (in.getFunctype() == InvocationExprent.TYP_INIT && in.getInstance().type == Exprent.EXPRENT_NEW) {
NewExprent newexp = (NewExprent)in.getInstance();
newexp.setConstructor(in);
NewExprent newExpr = (NewExprent)in.getInstance();
newExpr.setConstructor(in);
in.setInstance(null);
return newexp;
return newExpr;
}
}
@ -591,37 +600,35 @@ public class SimplifyExprentsHelper {
private static boolean buildIff(Statement stat, SSAConstructorSparseEx ssa) {
if (stat.type == Statement.TYPE_IF && stat.getExprents() == null) {
IfStatement stif = (IfStatement)stat;
Exprent ifheadexpr = stif.getHeadexprent();
Set<Integer> ifheadexpr_bytecode = (ifheadexpr == null ? null : ifheadexpr.bytecode);
if (stif.iftype == IfStatement.IFTYPE_IFELSE) {
Statement ifstat = stif.getIfstat();
Statement elsestat = stif.getElsestat();
if (ifstat.getExprents() != null && ifstat.getExprents().size() == 1
&& elsestat.getExprents() != null && elsestat.getExprents().size() == 1
&& ifstat.getAllSuccessorEdges().size() == 1 && elsestat.getAllSuccessorEdges().size() == 1
&& ifstat.getAllSuccessorEdges().get(0).getDestination() == elsestat.getAllSuccessorEdges().get(0).getDestination()) {
Exprent ifexpr = ifstat.getExprents().get(0);
Exprent elseexpr = elsestat.getExprents().get(0);
if (ifexpr.type == Exprent.EXPRENT_ASSIGNMENT && elseexpr.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent ifas = (AssignmentExprent)ifexpr;
AssignmentExprent elseas = (AssignmentExprent)elseexpr;
if (ifas.getLeft().type == Exprent.EXPRENT_VAR && elseas.getLeft().type == Exprent.EXPRENT_VAR) {
VarExprent ifvar = (VarExprent)ifas.getLeft();
VarExprent elsevar = (VarExprent)elseas.getLeft();
if (ifvar.getIndex() == elsevar.getIndex() && ifvar.isStack()) { // ifvar.getIndex() >= VarExprent.STACK_BASE) {
IfStatement statement = (IfStatement)stat;
Exprent ifHeadExpr = statement.getHeadexprent();
Set<Integer> ifHeadExprBytecode = (ifHeadExpr == null ? null : ifHeadExpr.bytecode);
if (statement.iftype == IfStatement.IFTYPE_IFELSE) {
Statement ifStatement = statement.getIfstat();
Statement elseStatement = statement.getElsestat();
if (ifStatement.getExprents() != null && ifStatement.getExprents().size() == 1 &&
elseStatement.getExprents() != null && elseStatement.getExprents().size() == 1 &&
ifStatement.getAllSuccessorEdges().size() == 1 && elseStatement.getAllSuccessorEdges().size() == 1 &&
ifStatement.getAllSuccessorEdges().get(0).getDestination() == elseStatement.getAllSuccessorEdges().get(0).getDestination()) {
Exprent ifExpr = ifStatement.getExprents().get(0);
Exprent elseExpr = elseStatement.getExprents().get(0);
if (ifExpr.type == Exprent.EXPRENT_ASSIGNMENT && elseExpr.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent ifAssign = (AssignmentExprent)ifExpr;
AssignmentExprent elseAssign = (AssignmentExprent)elseExpr;
if (ifAssign.getLeft().type == Exprent.EXPRENT_VAR && elseAssign.getLeft().type == Exprent.EXPRENT_VAR) {
VarExprent ifVar = (VarExprent)ifAssign.getLeft();
VarExprent elseVar = (VarExprent)elseAssign.getLeft();
if (ifVar.getIndex() == elseVar.getIndex() && ifVar.isStack()) { // ifVar.getIndex() >= VarExprent.STACK_BASE) {
boolean found = false;
for (Entry<VarVersionPair, FastSparseSet<Integer>> ent : ssa.getPhi().entrySet()) {
if (ent.getKey().var == ifvar.getIndex()) {
if (ent.getValue().contains(ifvar.getVersion()) && ent.getValue().contains(elsevar.getVersion())) {
if (ent.getKey().var == ifVar.getIndex()) {
if (ent.getValue().contains(ifVar.getVersion()) && ent.getValue().contains(elseVar.getVersion())) {
found = true;
break;
}
@ -629,65 +636,61 @@ public class SimplifyExprentsHelper {
}
if (found) {
List<Exprent> data = new ArrayList<>(stif.getFirst().getExprents());
data.add(new AssignmentExprent(ifvar, new FunctionExprent(FunctionExprent.FUNCTION_IIF,
Arrays.asList(
stif.getHeadexprent().getCondition(),
ifas.getRight(),
elseas.getRight()), ifheadexpr_bytecode), ifheadexpr_bytecode));
stif.setExprents(data);
if (stif.getAllSuccessorEdges().isEmpty()) {
StatEdge ifedge = ifstat.getAllSuccessorEdges().get(0);
StatEdge edge = new StatEdge(ifedge.getType(), stif, ifedge.getDestination());
stif.addSuccessor(edge);
if (ifedge.closure != null) {
ifedge.closure.addLabeledEdge(edge);
List<Exprent> data = new ArrayList<>(statement.getFirst().getExprents());
List<Exprent> operands = Arrays.asList(statement.getHeadexprent().getCondition(), ifAssign.getRight(), elseAssign.getRight());
data.add(new AssignmentExprent(ifVar, new FunctionExprent(FunctionExprent.FUNCTION_IIF, operands, ifHeadExprBytecode), ifHeadExprBytecode));
statement.setExprents(data);
if (statement.getAllSuccessorEdges().isEmpty()) {
StatEdge ifEdge = ifStatement.getAllSuccessorEdges().get(0);
StatEdge edge = new StatEdge(ifEdge.getType(), statement, ifEdge.getDestination());
statement.addSuccessor(edge);
if (ifEdge.closure != null) {
ifEdge.closure.addLabeledEdge(edge);
}
}
SequenceHelper.destroyAndFlattenStatement(stif);
SequenceHelper.destroyAndFlattenStatement(statement);
return true;
}
}
}
}
else if (ifexpr.type == Exprent.EXPRENT_EXIT && elseexpr.type == Exprent.EXPRENT_EXIT) {
ExitExprent ifex = (ExitExprent)ifexpr;
ExitExprent elseex = (ExitExprent)elseexpr;
if (ifex.getExitType() == elseex.getExitType() && ifex.getValue() != null && elseex.getValue() != null &&
ifex.getExitType() == ExitExprent.EXIT_RETURN) {
else if (ifExpr.type == Exprent.EXPRENT_EXIT && elseExpr.type == Exprent.EXPRENT_EXIT) {
ExitExprent ifExit = (ExitExprent)ifExpr;
ExitExprent elseExit = (ExitExprent)elseExpr;
if (ifExit.getExitType() == elseExit.getExitType() && ifExit.getValue() != null && elseExit.getValue() != null &&
ifExit.getExitType() == ExitExprent.EXIT_RETURN) {
// throw is dangerous, because of implicit casting to a common superclass
// e.g. throws IOException and throw true?new RuntimeException():new IOException(); won't work
if (ifex.getExitType() == ExitExprent.EXIT_THROW &&
!ifex.getValue().getExprType().equals(elseex.getValue().getExprType())) { // note: getExprType unreliable at this point!
if (ifExit.getExitType() == ExitExprent.EXIT_THROW &&
!ifExit.getValue().getExprType().equals(elseExit.getValue().getExprType())) { // note: getExprType unreliable at this point!
return false;
}
// avoid flattening to 'iff' if any of the branches is an 'iff' already
if (isIff(ifex.getValue()) || isIff(elseex.getValue())) {
if (isIff(ifExit.getValue()) || isIff(elseExit.getValue())) {
return false;
}
List<Exprent> data = new ArrayList<>(stif.getFirst().getExprents());
List<Exprent> data = new ArrayList<>(statement.getFirst().getExprents());
data.add(new ExitExprent(ifex.getExitType(), new FunctionExprent(FunctionExprent.FUNCTION_IIF,
data.add(new ExitExprent(ifExit.getExitType(), new FunctionExprent(FunctionExprent.FUNCTION_IIF,
Arrays.asList(
stif.getHeadexprent().getCondition(),
ifex.getValue(),
elseex.getValue()), ifheadexpr_bytecode), ifex.getRetType(), ifheadexpr_bytecode));
stif.setExprents(data);
statement.getHeadexprent().getCondition(),
ifExit.getValue(),
elseExit.getValue()), ifHeadExprBytecode), ifExit.getRetType(), ifHeadExprBytecode));
statement.setExprents(data);
StatEdge retedge = ifstat.getAllSuccessorEdges().get(0);
stif.addSuccessor(new StatEdge(StatEdge.TYPE_BREAK, stif, retedge.getDestination(),
retedge.closure == stif ? stif.getParent() : retedge.closure));
StatEdge retEdge = ifStatement.getAllSuccessorEdges().get(0);
Statement closure = retEdge.closure == statement ? statement.getParent() : retEdge.closure;
statement.addSuccessor(new StatEdge(StatEdge.TYPE_BREAK, statement, retEdge.getDestination(), closure));
SequenceHelper.destroyAndFlattenStatement(stif);
SequenceHelper.destroyAndFlattenStatement(statement);
return true;
}
@ -703,41 +706,14 @@ public class SimplifyExprentsHelper {
return exp.type == Exprent.EXPRENT_FUNCTION && ((FunctionExprent) exp).getFuncType() == FunctionExprent.FUNCTION_IIF;
}
static {
class14Builder.parse(
"statement type:if iftype:if exprsize:-1\n" +
" exprent position:head type:if\n" +
" exprent type:function functype:eq\n" +
" exprent type:field name:$fieldname$\n" +
" exprent type:constant consttype:null\n" +
" statement type:basicblock\n" +
" exprent position:-1 type:assignment ret:$assignfield$\n" +
" exprent type:var index:$var$\n" +
" exprent type:field name:$fieldname$\n" +
" statement type:sequence statsize:2\n" +
" statement type:trycatch\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:assignment\n" +
" exprent type:var index:$var$\n" +
" exprent type:invocation invclass:java/lang/Class signature:forName(Ljava/lang/String;)Ljava/lang/Class;\n" +
" exprent position:0 type:constant consttype:string constvalue:$classname$\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:exit exittype:throw\n" +
" statement type:basicblock exprsize:1\n" +
" exprent type:assignment\n" +
" exprent type:field name:$fieldname$ ret:$field$\n" +
" exprent type:var index:$var$"
);
}
private static boolean collapseInlinedClass14(Statement stat) {
boolean ret = class14Builder.match(stat);
if (ret) {
String class_name = (String)class14Builder.getVariableValue("$classname$");
AssignmentExprent assfirst = (AssignmentExprent)class14Builder.getVariableValue("$assignfield$");
FieldExprent fieldexpr = (FieldExprent)class14Builder.getVariableValue("$field$");
AssignmentExprent assignment = (AssignmentExprent)class14Builder.getVariableValue("$assignfield$");
FieldExprent fieldExpr = (FieldExprent)class14Builder.getVariableValue("$field$");
assfirst.replaceExprent(assfirst.getRight(), new ConstExprent(VarType.VARTYPE_CLASS, class_name, null));
assignment.replaceExprent(assignment.getRight(), new ConstExprent(VarType.VARTYPE_CLASS, class_name, null));
List<Exprent> data = new ArrayList<>(stat.getFirst().getExprents());
@ -747,7 +723,7 @@ public class SimplifyExprentsHelper {
ClassWrapper wrapper = (ClassWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_WRAPPER);
if (wrapper != null) {
wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fieldexpr.getName(), fieldexpr.getDescriptor().descriptorString));
wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fieldExpr.getName(), fieldExpr.getDescriptor().descriptorString));
}
}

@ -20,36 +20,22 @@ import org.jetbrains.java.decompiler.util.SFormsFastMapDirect;
import java.util.*;
import java.util.Map.Entry;
public class StackVarsProcessor {
public void simplifyStackVars(RootStatement root, StructMethod mt, StructClass cl) {
HashSet<Integer> setReorderedIfs = new HashSet<>();
Set<Integer> setReorderedIfs = new HashSet<>();
SSAUConstructorSparseEx ssau = null;
while (true) {
boolean found = false;
// System.out.println("--------------- \r\n"+root.toJava());
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, mt);
// System.out.println("--------------- \r\n"+root.toJava());
SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(ssau == null);
while (sehelper.simplifyStackVarsStatement(root, setReorderedIfs, ssa, cl)) {
// System.out.println("--------------- \r\n"+root.toJava());
found = true;
}
// System.out.println("=============== \r\n"+root.toJava());
setVersionsToNull(root);
SequenceHelper.condenseSequences(root);
@ -57,21 +43,10 @@ public class StackVarsProcessor {
ssau = new SSAUConstructorSparseEx();
ssau.splitVariables(root, mt);
// try {
// DotExporter.toDotFile(ssau.getSsuversions(), new File("c:\\Temp\\gr12_my.dot"));
// } catch(Exception ex) {
// ex.printStackTrace();
// }
// System.out.println("++++++++++++++++ \r\n"+root.toJava());
if (iterateStatements(root, ssau)) {
found = true;
}
// System.out.println("***************** \r\n"+root.toJava());
setVersionsToNull(root);
if (!found) {
@ -83,21 +58,12 @@ public class StackVarsProcessor {
ssau = new SSAUConstructorSparseEx();
ssau.splitVariables(root, mt);
// try {
// DotExporter.toDotFile(ssau.getSsuversions(), new File("c:\\Temp\\gr12_my.dot"));
// } catch(Exception ex) {
// ex.printStackTrace();
// }
iterateStatements(root, ssau);
// System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
setVersionsToNull(root);
}
private static void setVersionsToNull(Statement stat) {
if (stat.getExprents() == null) {
for (Object obj : stat.getSequentialObjects()) {
if (obj instanceof Statement) {
@ -116,7 +82,6 @@ public class StackVarsProcessor {
}
private static void setExprentVersionsToNull(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
@ -127,25 +92,22 @@ public class StackVarsProcessor {
}
}
private boolean iterateStatements(RootStatement root, SSAUConstructorSparseEx ssa) {
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root);
boolean res = false;
HashSet<DirectNode> setVisited = new HashSet<>();
Set<DirectNode> setVisited = new HashSet<>();
LinkedList<DirectNode> stack = new LinkedList<>();
LinkedList<HashMap<VarVersionPair, Exprent>> stackMaps = new LinkedList<>();
LinkedList<Map<VarVersionPair, Exprent>> stackMaps = new LinkedList<>();
stack.add(dgraph.first);
stackMaps.add(new HashMap<>());
while (!stack.isEmpty()) {
DirectNode nd = stack.removeFirst();
HashMap<VarVersionPair, Exprent> mapVarValues = stackMaps.removeFirst();
Map<VarVersionPair, Exprent> mapVarValues = stackMaps.removeFirst();
if (setVisited.contains(nd)) {
continue;
@ -182,9 +144,6 @@ public class StackVarsProcessor {
}
int[] ret = iterateExprent(lst, index, next, mapVarValues, ssa);
//System.out.println("***************** \r\n"+root.toJava());
if (ret[0] >= 0) {
index = ret[0];
}
@ -221,26 +180,21 @@ public class StackVarsProcessor {
return res;
}
private static Exprent isReplaceableVar(Exprent exprent, HashMap<VarVersionPair, Exprent> mapVarValues) {
private static Exprent isReplaceableVar(Exprent exprent, Map<VarVersionPair, Exprent> mapVarValues) {
Exprent dest = null;
if (exprent.type == Exprent.EXPRENT_VAR) {
VarExprent var = (VarExprent)exprent;
dest = mapVarValues.get(new VarVersionPair(var));
}
return dest;
}
private static void replaceSingleVar(Exprent parent, VarExprent var, Exprent dest, SSAUConstructorSparseEx ssau) {
parent.replaceExprent(var, dest);
// live sets
SFormsFastMapDirect livemap = ssau.getLiveVarVersionsMap(new VarVersionPair(var));
HashSet<VarVersionPair> setVars = getAllVersions(dest);
Set<VarVersionPair> setVars = getAllVersions(dest);
for (VarVersionPair varpaar : setVars) {
VarVersionNode node = ssau.getSsuversions().nodes.getWithKey(varpaar);
@ -265,9 +219,11 @@ public class StackVarsProcessor {
}
}
private int[] iterateExprent(List<Exprent> lstExprents, int index, Exprent next, HashMap<VarVersionPair,
Exprent> mapVarValues, SSAUConstructorSparseEx ssau) {
private int[] iterateExprent(List<Exprent> lstExprents,
int index,
Exprent next,
Map<VarVersionPair, Exprent> mapVarValues,
SSAUConstructorSparseEx ssau) {
Exprent exprent = lstExprents.get(index);
int changed = 0;
@ -354,14 +310,14 @@ public class StackVarsProcessor {
return new int[]{-1, changed};
}
HashMap<Integer, HashSet<VarVersionPair>> mapVars = getAllVarVersions(leftpaar, right, ssau);
Map<Integer, Set<VarVersionPair>> mapVars = getAllVarVersions(leftpaar, right, ssau);
boolean isSelfReference = mapVars.containsKey(leftpaar.var);
if (isSelfReference && notdom) {
return new int[]{-1, changed};
}
HashSet<VarVersionPair> setNextVars = next == null ? null : getAllVersions(next);
Set<VarVersionPair> setNextVars = next == null ? null : getAllVersions(next);
// FIXME: fix the entire method!
if (right.type != Exprent.EXPRENT_CONST &&
@ -380,8 +336,7 @@ public class StackVarsProcessor {
boolean vernotreplaced = false;
boolean verreplaced = false;
HashSet<VarVersionPair> setTempUsedVers = new HashSet<>();
Set<VarVersionPair> setTempUsedVers = new HashSet<>();
for (VarVersionNode usedvar : usedVers) {
VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version);
@ -424,9 +379,8 @@ public class StackVarsProcessor {
}
}
private static HashSet<VarVersionPair> getAllVersions(Exprent exprent) {
HashSet<VarVersionPair> res = new HashSet<>();
private static Set<VarVersionPair> getAllVersions(Exprent exprent) {
Set<VarVersionPair> res = new HashSet<>();
List<Exprent> listTemp = new ArrayList<>(exprent.getAllExprents(true));
listTemp.add(exprent);
@ -444,9 +398,8 @@ public class StackVarsProcessor {
private static Object[] iterateChildExprent(Exprent exprent,
Exprent parent,
Exprent next,
HashMap<VarVersionPair, Exprent> mapVarValues,
Map<VarVersionPair, Exprent> mapVarValues,
SSAUConstructorSparseEx ssau) {
boolean changed = false;
for (Exprent expr : exprent.getAllExprents()) {
@ -527,23 +480,21 @@ public class StackVarsProcessor {
return new Object[]{null, changed, false};
}
HashMap<Integer, HashSet<VarVersionPair>> mapVars = getAllVarVersions(leftpaar, right, ssau);
Map<Integer, Set<VarVersionPair>> mapVars = getAllVarVersions(leftpaar, right, ssau);
if (mapVars.containsKey(leftpaar.var) && notdom) {
return new Object[]{null, changed, false};
}
mapVars.remove(leftpaar.var);
HashSet<VarVersionPair> setAllowedVars = getAllVersions(parent);
Set<VarVersionPair> setAllowedVars = getAllVersions(parent);
if (next != null) {
setAllowedVars.addAll(getAllVersions(next));
}
boolean vernotreplaced = false;
HashSet<VarVersionPair> setTempUsedVers = new HashSet<>();
Set<VarVersionPair> setTempUsedVers = new HashSet<>();
for (VarVersionNode usedvar : usedVers) {
VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version);
@ -558,7 +509,6 @@ public class StackVarsProcessor {
}
if (!notdom && !vernotreplaced) {
for (VarVersionPair usedver : setTempUsedVers) {
Exprent copy = right.copy();
if (right.type == Exprent.EXPRENT_FIELD && ssau.getMapFieldVars().containsKey(right.id)) {
@ -576,19 +526,16 @@ public class StackVarsProcessor {
}
private static boolean getUsedVersions(SSAUConstructorSparseEx ssa, VarVersionPair var, List<VarVersionNode> res) {
VarVersionsGraph ssuversions = ssa.getSsuversions();
VarVersionNode varnode = ssuversions.nodes.getWithKey(var);
HashSet<VarVersionNode> setVisited = new HashSet<>();
HashSet<VarVersionNode> setNotDoms = new HashSet<>();
Set<VarVersionNode> setVisited = new HashSet<>();
Set<VarVersionNode> setNotDoms = new HashSet<>();
LinkedList<VarVersionNode> stack = new LinkedList<>();
stack.add(varnode);
while (!stack.isEmpty()) {
VarVersionNode nd = stack.remove(0);
setVisited.add(nd);
@ -625,10 +572,9 @@ public class StackVarsProcessor {
}
private static boolean isVersionToBeReplaced(VarVersionPair usedvar,
HashMap<Integer, HashSet<VarVersionPair>> mapVars,
Map<Integer, Set<VarVersionPair>> mapVars,
SSAUConstructorSparseEx ssau,
VarVersionPair leftpaar) {
VarVersionsGraph ssuversions = ssau.getSsuversions();
SFormsFastMapDirect mapLiveVars = ssau.getLiveVarVersionsMap(usedvar);
@ -643,13 +589,13 @@ public class StackVarsProcessor {
return false;
}
for (Entry<Integer, HashSet<VarVersionPair>> ent : mapVars.entrySet()) {
for (Entry<Integer, Set<VarVersionPair>> ent : mapVars.entrySet()) {
FastSparseSet<Integer> liveverset = mapLiveVars.get(ent.getKey());
if (liveverset == null) {
return false;
}
HashSet<VarVersionNode> domset = new HashSet<>();
Set<VarVersionNode> domset = new HashSet<>();
for (VarVersionPair verpaar : ent.getValue()) {
domset.add(ssuversions.nodes.getWithKey(verpaar));
}
@ -673,11 +619,10 @@ public class StackVarsProcessor {
return true;
}
private static HashMap<Integer, HashSet<VarVersionPair>> getAllVarVersions(VarVersionPair leftvar,
Exprent exprent,
SSAUConstructorSparseEx ssau) {
HashMap<Integer, HashSet<VarVersionPair>> map = new HashMap<>();
private static Map<Integer, Set<VarVersionPair>> getAllVarVersions(VarVersionPair leftvar,
Exprent exprent,
SSAUConstructorSparseEx ssau) {
Map<Integer, Set<VarVersionPair>> map = new HashMap<>();
SFormsFastMapDirect mapLiveVars = ssau.getLiveVarVersionsMap(leftvar);
List<Exprent> lst = exprent.getAllExprents(true);
@ -688,7 +633,7 @@ public class StackVarsProcessor {
int varindex = ((VarExprent)expr).getIndex();
if (leftvar.var != varindex) {
if (mapLiveVars.containsKey(varindex)) {
HashSet<VarVersionPair> verset = new HashSet<>();
Set<VarVersionPair> verset = new HashSet<>();
for (Integer vers : mapLiveVars.get(varindex)) {
verset.add(new VarVersionPair(varindex, vers.intValue()));
}
@ -706,7 +651,7 @@ public class StackVarsProcessor {
if (ssau.getMapFieldVars().containsKey(expr.id)) {
int varindex = ssau.getMapFieldVars().get(expr.id);
if (mapLiveVars.containsKey(varindex)) {
HashSet<VarVersionPair> verset = new HashSet<>();
Set<VarVersionPair> verset = new HashSet<>();
for (Integer vers : mapLiveVars.get(varindex)) {
verset.add(new VarVersionPair(varindex, vers.intValue()));
}
@ -718,4 +663,4 @@ public class StackVarsProcessor {
return map;
}
}
}

@ -0,0 +1,35 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExprUtil {
public static List<VarVersionPair> getSyntheticParametersMask(String className, String descriptor, int parameters) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(className);
return node != null ? getSyntheticParametersMask(node, descriptor, parameters) : null;
}
public static List<VarVersionPair> getSyntheticParametersMask(ClassNode node, String descriptor, int parameters) {
List<VarVersionPair> mask = null;
ClassWrapper wrapper = node.getWrapper();
if (wrapper != null) {
// own class
mask = wrapper.getMethodWrapper(CodeConstants.INIT_NAME, descriptor).synthParameters;
}
else if (parameters > 0 && node.type == ClassNode.CLASS_MEMBER && node.classStruct.hasModifier(CodeConstants.ACC_STATIC)) {
// non-static member class
mask = new ArrayList<>(Collections.nCopies(parameters, null));
mask.set(0, new VarVersionPair(-1, 0));
}
return mask;
}
}

@ -217,9 +217,7 @@ public class FunctionExprent extends Exprent {
public VarType getExprType() {
VarType exprType = null;
if (funcType <= FUNCTION_NEG || funcType == FUNCTION_IPP || funcType == FUNCTION_PPI
|| funcType == FUNCTION_IMM || funcType == FUNCTION_MMI) {
if (funcType <= FUNCTION_NEG || funcType == FUNCTION_IPP || funcType == FUNCTION_PPI || funcType == FUNCTION_IMM || funcType == FUNCTION_MMI) {
VarType type1 = lstOperands.get(0).getExprType();
VarType type2 = null;
if (lstOperands.size() > 1) {
@ -268,7 +266,6 @@ public class FunctionExprent extends Exprent {
Exprent param1 = lstOperands.get(1);
Exprent param2 = lstOperands.get(2);
VarType supertype = VarType.getCommonSupertype(param1.getExprType(), param2.getExprType());
if (param1.type == Exprent.EXPRENT_CONST && param2.type == Exprent.EXPRENT_CONST &&
supertype.type != CodeConstants.TYPE_BOOLEAN && VarType.VARTYPE_INT.isSuperset(supertype)) {
exprType = VarType.VARTYPE_INT;
@ -324,9 +321,6 @@ public class FunctionExprent extends Exprent {
switch (funcType) {
case FUNCTION_IIF:
VarType supertype = getExprType();
if (supertype == null) {
supertype = getExprType();
}
result.addMinTypeExprent(param1, VarType.VARTYPE_BOOLEAN);
result.addMinTypeExprent(param2, VarType.getMinTypeInFamily(supertype.typeFamily));
result.addMinTypeExprent(lstOperands.get(2), VarType.getMinTypeInFamily(supertype.typeFamily));

@ -300,10 +300,11 @@ public class InvocationExprent extends Exprent {
buf.append("<invokedynamic>");
}
buf.append("(");
break;
case TYP_CLINIT:
throw new RuntimeException("Explicit invocation of " + CodeConstants.CLINIT_NAME);
case TYP_INIT:
if (super_qualifier != null) {
buf.append("super(");
@ -311,31 +312,20 @@ public class InvocationExprent extends Exprent {
else if (isInstanceThis) {
buf.append("this(");
}
else if (instance != null) {
buf.append(instance.toJava(indent, tracer)).append(".<init>(");
}
else {
if (instance != null) {
buf.append(instance.toJava(indent, tracer)).append(".<init>(");
}
else {
throw new RuntimeException("Unrecognized invocation of " + CodeConstants.INIT_NAME);
}
throw new RuntimeException("Unrecognized invocation of " + CodeConstants.INIT_NAME);
}
}
List<VarVersionPair> sigFields = null;
List<VarVersionPair> mask = null;
boolean isEnum = false;
if (functype == TYP_INIT) {
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
if (newNode != null) { // own class
if (newNode.getWrapper() != null) {
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, stringDescriptor).signatureFields;
}
else {
if (newNode.type == ClassNode.CLASS_MEMBER && (newNode.access & CodeConstants.ACC_STATIC) == 0) { // non-static member class
sigFields = new ArrayList<>(Collections.nCopies(lstParameters.size(), (VarVersionPair)null));
sigFields.set(0, new VarVersionPair(-1, 0));
}
}
if (newNode != null) {
mask = ExprUtil.getSyntheticParametersMask(newNode, stringDescriptor, lstParameters.size());
isEnum = newNode.classStruct.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
}
}
@ -353,7 +343,7 @@ public class InvocationExprent extends Exprent {
boolean firstParameter = true;
int start = isEnum ? 2 : 0;
for (int i = start; i < lstParameters.size(); i++) {
if (sigFields == null || sigFields.get(i) == null) {
if (mask == null || mask.get(i) == null) {
TextBuffer buff = new TextBuffer();
boolean ambiguous = setAmbiguousParameters.get(i);
@ -373,7 +363,7 @@ public class InvocationExprent extends Exprent {
}
}
buf.append(")");
buf.append(')');
return buf;
}

@ -20,7 +20,6 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@ -90,10 +89,8 @@ public class NewExprent extends Exprent {
}
}
}
else {
if (constructor != null) {
return constructor.checkExprTypeBounds();
}
else if (constructor != null) {
return constructor.checkExprTypeBounds();
}
return result;
@ -102,21 +99,18 @@ public class NewExprent extends Exprent {
@Override
public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<>();
if (newType.arrayDim == 0) {
if (constructor != null) {
Exprent constructor_instance = constructor.getInstance();
if (constructor_instance != null) { // should be true only for a lambda expression with a virtual content method
lst.add(constructor_instance);
}
lst.addAll(constructor.getLstParameters());
}
}
else {
if (newType.arrayDim != 0) {
lst.addAll(lstDims);
lst.addAll(lstArrayElements);
}
else if (constructor != null) {
Exprent constructor = this.constructor.getInstance();
if (constructor != null) { // should be true only for a lambda expression with a virtual content method
lst.add(constructor);
}
lst.addAll(this.constructor.getLstParameters());
}
return lst;
}
@ -193,35 +187,22 @@ public class NewExprent extends Exprent {
buf.append('(');
if (!lambda && constructor != null) {
InvocationExprent invSuper = child.superInvocation;
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(invSuper.getClassname());
List<VarVersionPair> sigFields = child.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, constructor.getStringDescriptor()).signatureFields;
if (sigFields == null && newNode != null) { // own class
if (newNode.getWrapper() != null) {
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, invSuper.getStringDescriptor()).signatureFields;
}
else {
if (newNode.type == ClassNode.CLASS_MEMBER && (newNode.access & CodeConstants.ACC_STATIC) == 0 &&
!constructor.getLstParameters().isEmpty()) { // member non-static class invoked with enclosing class instance
sigFields = new ArrayList<>(Collections.nCopies(constructor.getLstParameters().size(), (VarVersionPair)null));
sigFields.set(0, new VarVersionPair(-1, 0));
}
}
List<Exprent> parameters = constructor.getLstParameters();
List<VarVersionPair> mask = child.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, constructor.getStringDescriptor()).synthParameters;
if (mask == null) {
InvocationExprent superCall = child.superInvocation;
mask = ExprUtil.getSyntheticParametersMask(superCall.getClassname(), superCall.getStringDescriptor(), parameters.size());
}
List<Exprent> lstParameters = constructor.getLstParameters();
int start = enumConst ? 2 : 0;
boolean firstParam = true;
for (int i = start; i < lstParameters.size(); i++) {
if (sigFields == null || sigFields.get(i) == null) {
for (int i = start; i < parameters.size(); i++) {
if (mask == null || mask.get(i) == null) {
if (!firstParam) {
buf.append(", ");
}
ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buf, indent, true, tracer);
ExprProcessor.getCastedExprent(parameters.get(i), constructor.getDescriptor().params[i], buf, indent, true, tracer);
firstParam = false;
}
@ -289,33 +270,20 @@ public class NewExprent extends Exprent {
}
if (constructor != null) {
List<Exprent> lstParameters = constructor.getLstParameters();
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(constructor.getClassname());
List<VarVersionPair> sigFields = null;
if (newNode != null) { // own class
if (newNode.getWrapper() != null) {
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, constructor.getStringDescriptor()).signatureFields;
}
else if (newNode.type == ClassNode.CLASS_MEMBER && (newNode.access & CodeConstants.ACC_STATIC) == 0 && !constructor.getLstParameters().isEmpty()) {
// member non-static class invoked with enclosing class instance
sigFields = new ArrayList<>(Collections.nCopies(lstParameters.size(), (VarVersionPair)null));
sigFields.set(0, new VarVersionPair(-1, 0));
}
}
List<Exprent> parameters = constructor.getLstParameters();
List<VarVersionPair> mask = ExprUtil.getSyntheticParametersMask(constructor.getClassname(), constructor.getStringDescriptor(), parameters.size());
int start = enumConst ? 2 : 0;
if (!enumConst || start < lstParameters.size()) {
if (!enumConst || start < parameters.size()) {
buf.append('(');
boolean firstParam = true;
for (int i = start; i < lstParameters.size(); i++) {
if (sigFields == null || sigFields.get(i) == null) {
Exprent expr = InvocationExprent.unboxIfNeeded(lstParameters.get(i));
for (int i = start; i < parameters.size(); i++) {
if (mask == null || mask.get(i) == null) {
Exprent expr = InvocationExprent.unboxIfNeeded(parameters.get(i));
VarType leftType = constructor.getDescriptor().params[i];
if (i == lstParameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) {
if (i == parameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(leftType.value);
if (node != null && node.namelessConstructorStub) {
break; // skip last parameter of synthetic constructor call

@ -158,7 +158,7 @@ public class VarDefinitionHelper {
boolean defset = false;
// search for the first assignement to var [index]
// search for the first assignment to var [index]
int addindex = 0;
for (Exprent expr : lst) {
if (setDefinition(expr, index)) {

@ -23,24 +23,21 @@ public class VarVersionsGraph {
nodes.addAllWithKey(colnodes, colpaars);
}
public boolean isDominatorSet(VarVersionNode node, HashSet<VarVersionNode> domnodes) {
public boolean isDominatorSet(VarVersionNode node, Set<VarVersionNode> domnodes) {
if (domnodes.size() == 1) {
return engine.isDominator(node, domnodes.iterator().next());
}
else {
HashSet<VarVersionNode> marked = new HashSet<>();
Set<VarVersionNode> marked = new HashSet<>();
if (domnodes.contains(node)) {
return true;
}
LinkedList<VarVersionNode> lstNodes = new LinkedList<>();
List<VarVersionNode> lstNodes = new LinkedList<>();
lstNodes.add(node);
while (!lstNodes.isEmpty()) {
VarVersionNode nd = lstNodes.remove(0);
if (marked.contains(nd)) {
continue;
@ -66,8 +63,7 @@ public class VarVersionsGraph {
}
public void initDominators() {
final HashSet<VarVersionNode> roots = new HashSet<>();
Set<VarVersionNode> roots = new HashSet<>();
for (VarVersionNode node : nodes) {
if (node.preds.isEmpty()) {
@ -88,23 +84,20 @@ public class VarVersionsGraph {
engine.initialize();
}
private static LinkedList<VarVersionNode> getReversedPostOrder(Collection<VarVersionNode> roots) {
LinkedList<VarVersionNode> lst = new LinkedList<>();
HashSet<VarVersionNode> setVisited = new HashSet<>();
private static List<VarVersionNode> getReversedPostOrder(Collection<VarVersionNode> roots) {
List<VarVersionNode> lst = new LinkedList<>();
Set<VarVersionNode> setVisited = new HashSet<>();
for (VarVersionNode root : roots) {
LinkedList<VarVersionNode> lstTemp = new LinkedList<>();
List<VarVersionNode> lstTemp = new LinkedList<>();
addToReversePostOrderListIterative(root, lstTemp, setVisited);
lst.addAll(lstTemp);
}
return lst;
}
private static void addToReversePostOrderListIterative(VarVersionNode root, List<VarVersionNode> lst, HashSet<VarVersionNode> setVisited) {
private static void addToReversePostOrderListIterative(VarVersionNode root, List<VarVersionNode> lst, Set<VarVersionNode> setVisited) {
Map<VarVersionNode, List<VarVersionEdge>> mapNodeSuccs = new HashMap<>();
LinkedList<VarVersionNode> stackNode = new LinkedList<>();
LinkedList<Integer> stackIndex = new LinkedList<>();
@ -113,7 +106,6 @@ public class VarVersionsGraph {
stackIndex.add(0);
while (!stackNode.isEmpty()) {
VarVersionNode node = stackNode.getLast();
int index = stackIndex.removeLast();

@ -8,7 +8,6 @@ import java.util.Arrays;
import java.util.List;
public class MethodDescriptor {
public final VarType[] params;
public final VarType ret;
@ -127,4 +126,4 @@ public class MethodDescriptor {
result = 31 * result + params.length;
return result;
}
}
}

@ -1,9 +1,7 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.struct.match;
public interface IMatchable {
enum MatchProperties {
STATEMENT_TYPE,
STATEMENT_RET,
@ -29,5 +27,4 @@ public interface IMatchable {
IMatchable findObject(MatchNode matchNode, int index);
boolean match(MatchNode matchNode, MatchEngine engine);
}
}

@ -12,13 +12,7 @@ import org.jetbrains.java.decompiler.struct.match.MatchNode.RuleValue;
import java.util.*;
public class MatchEngine {
private MatchNode rootNode = null;
private final Map<String, Object> variables = new HashMap<>();
private static final Map<String, MatchProperties> stat_properties = new HashMap<>();
private static final Map<String, MatchProperties> expr_properties = new HashMap<>();
private static final Map<String, Integer> stat_type = new HashMap<>();
@ -83,19 +77,19 @@ public class MatchEngine {
expr_const_type.put("string", VarType.VARTYPE_STRING);
}
private final MatchNode rootNode;
private final Map<String, Object> variables = new HashMap<>();
public void parse(String description) {
public MatchEngine(String description) {
// each line is a separate statement/exprent
String[] lines = description.split("\n");
int depth = 0;
LinkedList<MatchNode> stack = new LinkedList<>();
for(String line : lines) {
for (String line : lines) {
List<String> properties = new ArrayList<>(Arrays.asList(line.split("\\s+"))); // split on any number of whitespaces
if(properties.get(0).isEmpty()) {
if (properties.get(0).isEmpty()) {
properties.remove(0);
}
@ -103,11 +97,11 @@ public class MatchEngine {
// create new node
MatchNode matchNode = new MatchNode(node_type);
for(int i = 1; i < properties.size(); ++i) {
for (int i = 1; i < properties.size(); ++i) {
String[] values = properties.get(i).split(":");
MatchProperties property = (node_type == MatchNode.MATCHNODE_STATEMENT ? stat_properties : expr_properties).get(values[0]);
if(property == null) { // unknown property defined
if (property == null) { // unknown property defined
throw new RuntimeException("Unknown matching property");
}
else {
@ -115,61 +109,61 @@ public class MatchEngine {
int parameter = 0;
String strValue = values[1];
if(values.length == 3) {
if (values.length == 3) {
parameter = Integer.parseInt(values[1]);
strValue = values[2];
}
switch(property) {
case STATEMENT_TYPE:
value = stat_type.get(strValue);
break;
case STATEMENT_STATSIZE:
case STATEMENT_EXPRSIZE:
value = Integer.valueOf(strValue);
break;
case STATEMENT_POSITION:
case EXPRENT_POSITION:
case EXPRENT_INVOCATION_CLASS:
case EXPRENT_INVOCATION_SIGNATURE:
case EXPRENT_INVOCATION_PARAMETER:
case EXPRENT_VAR_INDEX:
case EXPRENT_FIELD_NAME:
case EXPRENT_CONSTVALUE:
case STATEMENT_RET:
case EXPRENT_RET:
value = strValue;
break;
case STATEMENT_IFTYPE:
value = stat_if_type.get(strValue);
break;
case EXPRENT_FUNCTYPE:
value = expr_func_type.get(strValue);
break;
case EXPRENT_EXITTYPE:
value = expr_exit_type.get(strValue);
break;
case EXPRENT_CONSTTYPE:
value = expr_const_type.get(strValue);
break;
case EXPRENT_TYPE:
value = expr_type.get(strValue);
break;
default:
throw new RuntimeException("Unhandled matching property");
switch (property) {
case STATEMENT_TYPE:
value = stat_type.get(strValue);
break;
case STATEMENT_STATSIZE:
case STATEMENT_EXPRSIZE:
value = Integer.valueOf(strValue);
break;
case STATEMENT_POSITION:
case EXPRENT_POSITION:
case EXPRENT_INVOCATION_CLASS:
case EXPRENT_INVOCATION_SIGNATURE:
case EXPRENT_INVOCATION_PARAMETER:
case EXPRENT_VAR_INDEX:
case EXPRENT_FIELD_NAME:
case EXPRENT_CONSTVALUE:
case STATEMENT_RET:
case EXPRENT_RET:
value = strValue;
break;
case STATEMENT_IFTYPE:
value = stat_if_type.get(strValue);
break;
case EXPRENT_FUNCTYPE:
value = expr_func_type.get(strValue);
break;
case EXPRENT_EXITTYPE:
value = expr_exit_type.get(strValue);
break;
case EXPRENT_CONSTTYPE:
value = expr_const_type.get(strValue);
break;
case EXPRENT_TYPE:
value = expr_type.get(strValue);
break;
default:
throw new RuntimeException("Unhandled matching property");
}
matchNode.addRule(property, new RuleValue(parameter, value));
}
}
if(stack.isEmpty()) { // first line, root node
if (stack.isEmpty()) { // first line, root node
stack.push(matchNode);
} else {
}
else {
// return to the correct parent on the stack
int new_depth = line.lastIndexOf(' ', depth) + 1;
for(int i = new_depth; i <= depth; ++i) {
for (int i = new_depth; i <= depth; ++i) {
stack.pop();
}
@ -190,25 +184,24 @@ public class MatchEngine {
}
private boolean match(MatchNode matchNode, IMatchable object) {
if(!object.match(matchNode, this)) {
if (!object.match(matchNode, this)) {
return false;
}
int expr_index = 0;
int stat_index = 0;
for(MatchNode childNode : matchNode.getChildren()) {
for (MatchNode childNode : matchNode.getChildren()) {
boolean isStatement = childNode.getType() == MatchNode.MATCHNODE_STATEMENT;
IMatchable childObject = object.findObject(childNode, isStatement ? stat_index : expr_index);
if(childObject == null || !match(childNode, childObject)) {
if (childObject == null || !match(childNode, childObject)) {
return false;
}
if(isStatement) {
if (isStatement) {
stat_index++;
} else {
}
else {
expr_index++;
}
}

@ -1,15 +1,14 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.struct.match;
import org.jetbrains.java.decompiler.struct.match.IMatchable.MatchProperties;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.java.decompiler.struct.match.IMatchable.MatchProperties;
public class MatchNode {
public static class RuleValue {
public final int parameter;
public final Object value;
@ -33,12 +32,9 @@ public class MatchNode {
public static final int MATCHNODE_EXPRENT = 1;
private final int type;
private final Map<MatchProperties, RuleValue> rules = new HashMap<>();
private final List<MatchNode> children = new ArrayList<>();
public MatchNode(int type) {
this.type = type;
}
@ -67,5 +63,4 @@ public class MatchNode {
RuleValue rule = rules.get(property);
return rule == null ? null : rule.value;
}
}
}

@ -14,7 +14,7 @@ import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
public class DecompilerTestFixture {

Loading…
Cancel
Save