mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-25 18:56:48 +00:00
new for loop continues detection
This commit is contained in:
@@ -391,69 +391,6 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Set<GraphPart>> reachable = new ArrayList<>();
|
||||
for (GraphPart p : parts) {
|
||||
LinkedHashSet<GraphPart> r1 = new LinkedHashSet<>();
|
||||
getReachableParts(localData, p, r1, loops, gotoParts);
|
||||
Set<GraphPart> r2 = new LinkedHashSet<>();
|
||||
r2.add(p);
|
||||
r2.addAll(r1);
|
||||
reachable.add(r2);
|
||||
}
|
||||
///List<GraphPart> first = reachable.get(0);
|
||||
int commonLevel;
|
||||
Map<GraphPart, Integer> levelMap = new HashMap<>();
|
||||
for (Set<GraphPart> first : reachable) {
|
||||
int maxclevel = 0;
|
||||
Set<GraphPart> visited = new HashSet<>();
|
||||
for (GraphPart p : first) {
|
||||
if (loopContinues.contains(p)) {
|
||||
break;
|
||||
}
|
||||
if (visited.contains(p)) {
|
||||
continue;
|
||||
}
|
||||
visited.add(p);
|
||||
boolean common = true;
|
||||
commonLevel = 1;
|
||||
for (Set<GraphPart> r : reachable) {
|
||||
if (r == first) {
|
||||
continue;
|
||||
}
|
||||
if (r.contains(p)) {
|
||||
commonLevel++;
|
||||
}
|
||||
}
|
||||
if (commonLevel <= maxclevel) {
|
||||
continue;
|
||||
}
|
||||
maxclevel = commonLevel;
|
||||
if (levelMap.containsKey(p)) {
|
||||
if (levelMap.get(p) > commonLevel) {
|
||||
commonLevel = levelMap.get(p);
|
||||
}
|
||||
}
|
||||
levelMap.put(p, commonLevel);
|
||||
if (common) {
|
||||
//return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = reachable.size() - 1; i >= 2; i--) {
|
||||
for (GraphPart p : levelMap.keySet()) {
|
||||
if (levelMap.get(p) == i) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (GraphPart p : levelMap.keySet()) {
|
||||
if (levelMap.get(p) == parts.size()) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
/*
|
||||
s
|
||||
List<Set<GraphPart>> reachable = new ArrayList<>();
|
||||
Set<GraphPart> allReachable = new LinkedHashSet<>();
|
||||
for (GraphPart p : parts) {
|
||||
@@ -494,7 +431,6 @@ public class Graph {
|
||||
//System.err.println("maxclevelpart = " + maxCommonLevelPart);
|
||||
|
||||
return maxCommonLevelPart;
|
||||
*/
|
||||
}
|
||||
|
||||
public GraphPart getNextNoJump(GraphPart part, BaseLocalData localData) {
|
||||
@@ -1449,6 +1385,19 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
if (i < list.size() - 1) {
|
||||
if (list.get(i + 1) instanceof ContinueItem) {
|
||||
if ((!onTrue.isEmpty()) && (onFalse.isEmpty())) {
|
||||
if (onTrue.get(onTrue.size() - 1) instanceof ContinueItem) {
|
||||
if (((ContinueItem) onTrue.get(onTrue.size() - 1)).loopId == ((ContinueItem) list.get(i + 1)).loopId) {
|
||||
onTrue.remove(onTrue.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) {
|
||||
GraphTargetItem last = onTrue.get(onTrue.size() - 1);
|
||||
if ((last instanceof ExitItem) || (last instanceof ContinueItem) || (last instanceof BreakItem)) {
|
||||
@@ -2163,6 +2112,23 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private void getContinuesCommands(List<GraphTargetItem> commands, List<List<GraphTargetItem>> result, long loopId) {
|
||||
for (GraphTargetItem ti : commands) {
|
||||
if (ti instanceof ContinueItem) {
|
||||
ContinueItem ci = (ContinueItem) ti;
|
||||
if (ci.loopId == loopId) {
|
||||
result.add(commands);
|
||||
}
|
||||
}
|
||||
if (ti instanceof Block) {
|
||||
Block bl = (Block) ti;
|
||||
for (List<GraphTargetItem> subCommands : bl.getSubs()) {
|
||||
getContinuesCommands(subCommands, result, loopId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, List<GraphPartEdge> gotoTargets, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -2715,6 +2681,7 @@ public class Graph {
|
||||
GraphPart precoBackup = currentLoop.loopPreContinue;
|
||||
currentLoop.loopPreContinue = null;
|
||||
loopItem.commands.addAll(printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1));
|
||||
checkContinueAtTheEnd(loopItem.commands, currentLoop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2778,9 +2745,26 @@ public class Graph {
|
||||
currentLoop.loopPreContinue = null;
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
stopPart2.add(currentLoop.loopContinue);
|
||||
finalComm = printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
List<GraphTargetItem> precoCommands = printGraph(foundGotos, gotoTargets, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
currentLoop.loopPreContinue = backup;
|
||||
checkContinueAtTheEnd(finalComm, currentLoop);
|
||||
checkContinueAtTheEnd(precoCommands, currentLoop);
|
||||
|
||||
List<List<GraphTargetItem>> continueCommands = new ArrayList<>();
|
||||
getContinuesCommands(commands, continueCommands, currentLoop.id);
|
||||
|
||||
if (continueCommands.isEmpty()) {
|
||||
commands.addAll(precoCommands);
|
||||
precoCommands = new ArrayList<>();
|
||||
} //Single continue and there is break/continue/return/throw at end of the commands
|
||||
else if (!commands.isEmpty() && continueCommands.size() == 1) {
|
||||
GraphTargetItem lastItem = commands.get(commands.size() - 1);
|
||||
if ((lastItem instanceof BreakItem) || (lastItem instanceof ContinueItem) || (lastItem instanceof ExitItem)) {
|
||||
continueCommands.get(0).addAll(continueCommands.get(0).size() - 1, precoCommands);
|
||||
precoCommands = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
finalComm.addAll(precoCommands);
|
||||
}
|
||||
if (currentLoop.precontinueCommands != null) {
|
||||
finalComm.addAll(currentLoop.precontinueCommands);
|
||||
|
||||
@@ -28,10 +28,18 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Detects "precontinues" in Graph. A precontinue is target of continue
|
||||
* statement in a for loop. For loop in this case has single backedge.
|
||||
* Precontinue is predeccessor of loops backedge. Precontinue can have branches
|
||||
* in it (and in some special cases like xml .() operator a while too). This
|
||||
* class tries to simplify graph up to the level that precontinue is a single
|
||||
* node.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPrecontinueDetector {
|
||||
|
||||
public void detectPrecontinues(List<GraphPart> heads, Set<GraphPart> allParts, List<Loop> loops) {
|
||||
boolean isSomethingTodo = false;
|
||||
for (Loop el : loops) {
|
||||
@@ -106,7 +114,12 @@ public class GraphPrecontinueDetector {
|
||||
//printGraph(headNodes);
|
||||
}
|
||||
|
||||
private void printGraph(List<Node> headNodes) {
|
||||
/**
|
||||
* Converts node graph to graphviz for easily display.
|
||||
*
|
||||
* @param headNodes
|
||||
*/
|
||||
public void printGraph(List<Node> headNodes) {
|
||||
Set<Node> allNodes = new LinkedHashSet<>();
|
||||
for (Node headNode : headNodes) {
|
||||
populateNodes(headNode, allNodes);
|
||||
@@ -196,7 +209,7 @@ public class GraphPrecontinueDetector {
|
||||
whileNode.graphPart = node.graphPart;
|
||||
whileNode.body = bodyNode;
|
||||
whileNode.body.removeFromGraph();
|
||||
whileNode.prev = new NonNullList<>(node.prev);
|
||||
whileNode.prev = new ArrayList<>(node.prev);
|
||||
node.replacePrevs(whileNode);
|
||||
node.replaceNexts(whileNode);
|
||||
whileNode.next.add(breakNode);
|
||||
@@ -204,7 +217,8 @@ public class GraphPrecontinueDetector {
|
||||
numWhile.setVal(numWhile.getVal() + 1);
|
||||
}
|
||||
|
||||
for (Node n : result.next) {
|
||||
List<Node> nexts = new ArrayList<>(result.next);
|
||||
for (Node n : nexts) {
|
||||
handleWhile(n, visited, numWhile);
|
||||
}
|
||||
return result;
|
||||
@@ -231,8 +245,8 @@ public class GraphPrecontinueDetector {
|
||||
JoinedNode joinedNode = new JoinedNode();
|
||||
joinedNode.graphPart = node.graphPart;
|
||||
joinedNode.nodes = nodeList;
|
||||
joinedNode.next = new NonNullList<>(currentNode.next);
|
||||
joinedNode.prev = new NonNullList<>(node.prev);
|
||||
joinedNode.next = new ArrayList<>(currentNode.next);
|
||||
joinedNode.prev = new ArrayList<>(node.prev);
|
||||
node.replacePrevs(joinedNode);
|
||||
currentNode.replaceNexts(joinedNode);
|
||||
for (Node n : nodeList) {
|
||||
@@ -243,7 +257,8 @@ public class GraphPrecontinueDetector {
|
||||
numJoined.setVal(numJoined.getVal() + 1);
|
||||
}
|
||||
|
||||
for (Node n : result.next) {
|
||||
List<Node> nexts = new ArrayList<>(result.next);
|
||||
for (Node n : nexts) {
|
||||
joinNodes(n, visited, numJoined);
|
||||
}
|
||||
|
||||
@@ -270,7 +285,7 @@ public class GraphPrecontinueDetector {
|
||||
ifNode.onTrue.removeFromGraph();
|
||||
ifNode.onFalse = null;
|
||||
ifNode.graphPart = node.graphPart;
|
||||
ifNode.prev = new NonNullList<>(node.prev);
|
||||
ifNode.prev = new ArrayList<>(node.prev);
|
||||
node.replacePrevs(ifNode);
|
||||
Node after = node.next.get(1);
|
||||
node.removeFromGraph();
|
||||
@@ -300,7 +315,7 @@ public class GraphPrecontinueDetector {
|
||||
ifNode.onFalse.parentNode = ifNode;
|
||||
ifNode.onFalse.removeFromGraph();
|
||||
ifNode.graphPart = node.graphPart;
|
||||
ifNode.prev = new NonNullList<>(node.prev);
|
||||
ifNode.prev = new ArrayList<>(node.prev);
|
||||
node.replacePrevs(ifNode);
|
||||
Node after = node.next.get(0);
|
||||
node.removeFromGraph();
|
||||
@@ -331,7 +346,7 @@ public class GraphPrecontinueDetector {
|
||||
ifNode.onFalse.parentNode = ifNode;
|
||||
ifNode.onFalse.removeFromGraph();
|
||||
ifNode.graphPart = node.graphPart;
|
||||
ifNode.prev = new NonNullList<>(node.prev);
|
||||
ifNode.prev = new ArrayList<>(node.prev);
|
||||
node.replacePrevs(ifNode);
|
||||
Node after = node.next.get(0).next.get(0);
|
||||
node.removeFromGraph();
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2018 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph.precontinues;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2018 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph.precontinues;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.util.List;
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Node {
|
||||
public List<Node> next = new NonNullList<>();
|
||||
public List<Node> prev = new NonNullList<Node>();
|
||||
public List<Node> next = new ArrayList<>();
|
||||
public List<Node> prev = new ArrayList<Node>();
|
||||
public GraphPart graphPart;
|
||||
private static int CURRENT_ID = 0;
|
||||
private int id;
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.jpexs.decompiler.graph.precontinues;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
class NonNullList<T> extends ArrayList<T> {
|
||||
|
||||
public NonNullList(Collection<? extends T> col) {
|
||||
super(col);
|
||||
}
|
||||
|
||||
public NonNullList() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean add(T item) {
|
||||
if (item == null) {
|
||||
throw new NullPointerException("The collection does not support null values");
|
||||
} else {
|
||||
return super.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> items) {
|
||||
if (items.contains(null)) {
|
||||
throw new NullPointerException("The collection does not support null values");
|
||||
} else {
|
||||
return super.addAll(items);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user