Skip to content

Commit 6019a90

Browse files
author
emmanue1
committed
Improve loop reconstruction
1 parent b3ccba8 commit 6019a90

File tree

9 files changed

+436
-373
lines changed

9 files changed

+436
-373
lines changed

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/util/ControlFlowGraphReducer.java

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package org.jd.core.v1.service.converter.classfiletojavasyntax.util;
99

1010
import org.jd.core.v1.model.classfile.attribute.AttributeCode;
11+
import org.jd.core.v1.model.javasyntax.expression.Expression;
1112
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.cfg.BasicBlock;
1213
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.cfg.ControlFlowGraph;
1314

@@ -1260,31 +1261,41 @@ protected static void createContinueLoop(BitSet visited, BasicBlock basicBlock)
12601261

12611262
protected static void createContinueLoop(BitSet visited, BasicBlock basicBlock, BasicBlock subBasicBlock) {
12621263
if (subBasicBlock != null) {
1263-
if ((subBasicBlock.getPredecessors().size() > 1) && (basicBlock.getFromOffset() < subBasicBlock.getFromOffset()) && (basicBlock.getFirstLineNumber() > subBasicBlock.getFirstLineNumber())) {
1264-
Set<BasicBlock> predecessors = subBasicBlock.getPredecessors();
1265-
Iterator<BasicBlock> iterator = predecessors.iterator();
1266-
BasicBlock lastPredecessor = iterator.next();
1267-
1268-
if (lastPredecessor.getType() != TYPE_GOTO_IN_TERNARY_OPERATOR) {
1269-
while (iterator.hasNext()) {
1270-
BasicBlock predecessor = iterator.next();
1271-
if (predecessor.getType() == TYPE_GOTO_IN_TERNARY_OPERATOR) {
1272-
lastPredecessor = null;
1273-
break;
1274-
}
1275-
if (lastPredecessor.getFromOffset() < predecessor.getFromOffset()) {
1276-
lastPredecessor = predecessor;
1277-
}
1278-
}
1264+
if ((subBasicBlock.getPredecessors().size() > 1) && (basicBlock.getFromOffset() < subBasicBlock.getFromOffset())) {
1265+
boolean condition;
1266+
1267+
if (basicBlock.getFirstLineNumber() == Expression.UNKNOWN_LINE_NUMBER) {
1268+
condition = subBasicBlock.matchType(GROUP_SINGLE_SUCCESSOR) && (subBasicBlock.getNext().getType() == TYPE_LOOP_START);
1269+
} else {
1270+
condition = (basicBlock.getFirstLineNumber() > subBasicBlock.getFirstLineNumber());
1271+
}
12791272

1280-
if (lastPredecessor != null) {
1281-
iterator = predecessors.iterator();
1273+
if (condition) {
1274+
Set<BasicBlock> predecessors = subBasicBlock.getPredecessors();
1275+
Iterator<BasicBlock> iterator = predecessors.iterator();
1276+
BasicBlock lastPredecessor = iterator.next();
12821277

1278+
if (lastPredecessor.getType() != TYPE_GOTO_IN_TERNARY_OPERATOR) {
12831279
while (iterator.hasNext()) {
12841280
BasicBlock predecessor = iterator.next();
1285-
if (predecessor != lastPredecessor) {
1286-
iterator.remove();
1287-
predecessor.replace(subBasicBlock, LOOP_CONTINUE);
1281+
if (predecessor.getType() == TYPE_GOTO_IN_TERNARY_OPERATOR) {
1282+
lastPredecessor = null;
1283+
break;
1284+
}
1285+
if (lastPredecessor.getFromOffset() < predecessor.getFromOffset()) {
1286+
lastPredecessor = predecessor;
1287+
}
1288+
}
1289+
1290+
if (lastPredecessor != null) {
1291+
iterator = predecessors.iterator();
1292+
1293+
while (iterator.hasNext()) {
1294+
BasicBlock predecessor = iterator.next();
1295+
if (predecessor != lastPredecessor) {
1296+
iterator.remove();
1297+
predecessor.replace(subBasicBlock, LOOP_CONTINUE);
1298+
}
12881299
}
12891300
}
12901301
}

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/util/LoopStatementMaker.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.statement.ClassFileForStatement;
1818
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.localvariable.AbstractLocalVariable;
1919
import org.jd.core.v1.service.converter.classfiletojavasyntax.visitor.SearchFirstLineNumberVisitor;
20+
import org.jd.core.v1.service.converter.classfiletojavasyntax.visitor.SearchLocalVariableReferenceVisitor;
2021

2122
import java.util.Collections;
2223
import java.util.Iterator;
@@ -567,7 +568,7 @@ protected static Statement makeForEachList(LocalVariableMaker localVariableMaker
567568

568569
boe = (BinaryOperatorExpression)es.getExpression();
569570

570-
if ((boe == null) || (boe.getLeftExpression().getClass() != ClassFileLocalVariableReferenceExpression.class)) {
571+
if (boe.getLeftExpression().getClass() != ClassFileLocalVariableReferenceExpression.class) {
571572
return null;
572573
}
573574

@@ -589,15 +590,23 @@ protected static Statement makeForEachList(LocalVariableMaker localVariableMaker
589590
return null;
590591
}
591592

593+
// Check if 'i$' is not used in sub-statements
594+
SearchLocalVariableReferenceVisitor visitor = new SearchLocalVariableReferenceVisitor(syntheticIterator);
595+
596+
for (int i=1, len=subStatements.size(); i<len; i++) {
597+
subStatements.get(i).accept(visitor);
598+
}
599+
600+
if (visitor.containsReference()) {
601+
return null;
602+
}
603+
592604
// Found
593605
AbstractLocalVariable item = ((ClassFileLocalVariableReferenceExpression)boe.getLeftExpression()).getLocalVariable();
594606

595607
statements.removeLast();
596-
597608
subStatements.remove(0);
598-
599609
item.setDeclared(true);
600-
601610
localVariableMaker.removeLocalVariable(syntheticIterator);
602611

603612
return new ClassFileForEachStatement(item, list, subStatements);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2008-2019 Emmanuel Dupuy.
3+
* This project is distributed under the GPLv3 license.
4+
* This is a Copyleft license that gives the user the right to use,
5+
* copy and modify the code freely for non-commercial purposes.
6+
*/
7+
8+
package org.jd.core.v1.service.converter.classfiletojavasyntax.visitor;
9+
10+
import org.jd.core.v1.model.javasyntax.AbstractJavaSyntaxVisitor;
11+
import org.jd.core.v1.model.javasyntax.expression.LocalVariableReferenceExpression;
12+
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.expression.ClassFileLocalVariableReferenceExpression;
13+
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.localvariable.AbstractLocalVariable;
14+
15+
public class SearchLocalVariableReferenceVisitor extends AbstractJavaSyntaxVisitor {
16+
protected int index;
17+
protected boolean found;
18+
19+
public SearchLocalVariableReferenceVisitor(AbstractLocalVariable alv) {
20+
this.index = alv.getIndex();
21+
this.found = false;
22+
}
23+
24+
public boolean containsReference() {
25+
return found;
26+
}
27+
28+
@Override
29+
public void visit(LocalVariableReferenceExpression expression) {
30+
ClassFileLocalVariableReferenceExpression referenceExpression = (ClassFileLocalVariableReferenceExpression)expression;
31+
found |= referenceExpression.getLocalVariable().getIndex() == index;
32+
}
33+
}

0 commit comments

Comments
 (0)