mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-24 22:04:54 +00:00
try..catch vs loops
This commit is contained in:
@@ -89,6 +89,8 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
*/
|
||||
public Map<Integer, GraphPart> finallyThrowParts = new HashMap<>();
|
||||
|
||||
public Map<Integer, GraphPart> finallyTargetParts = new HashMap<>();
|
||||
|
||||
//switchedPart -> index of nextpart
|
||||
public Map<GraphPart, Integer> defaultWays = new HashMap<>();
|
||||
|
||||
@@ -156,6 +158,7 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
finallyThrowParts = localData.finallyThrowParts;
|
||||
inGetLoops = localData.inGetLoops;
|
||||
parsedExceptionIds = localData.parsedExceptionIds;
|
||||
finallyTargetParts = localData.finallyTargetParts;
|
||||
}
|
||||
|
||||
public AVM2ConstantPool getConstants() {
|
||||
|
||||
@@ -160,9 +160,27 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
if (aLocalData.finallyTargetParts.containsValue(part)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts, List<ThrowState> throwStates) throws InterruptedException {
|
||||
AVM2LocalData avm2LocalData = ((AVM2LocalData) localData);
|
||||
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
ABCException ex = body.exceptions[e];
|
||||
if (ex.isFinally()) {
|
||||
avm2LocalData.finallyTargetParts.put(e, searchPart(code.adr2pos(ex.target), allParts));
|
||||
}
|
||||
}
|
||||
|
||||
avm2LocalData.codeStats = avm2LocalData.code.getStats(avm2LocalData.abc, avm2LocalData.methodBody, avm2LocalData.methodBody.init_scope_depth, false);
|
||||
getIgnoredSwitches((AVM2LocalData) localData, allParts);
|
||||
Set<Integer> integerSwitchesIps = new HashSet<>();
|
||||
|
||||
@@ -143,7 +143,7 @@ public class ActionGraph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeBreakCandidate(GraphPart part) {
|
||||
protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) {
|
||||
if (part.refs.size() <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -517,7 +517,6 @@ public class Graph {
|
||||
beforeGetLoops(localData, path, allParts, throwStates);
|
||||
List<Loop> loops = new ArrayList<>();
|
||||
|
||||
|
||||
getLoops(localData, heads.get(0), loops, throwStates, null);
|
||||
|
||||
afterGetLoops(localData, path, allParts);
|
||||
@@ -532,7 +531,7 @@ public class Graph {
|
||||
//TODO: Make getPrecontinues faster
|
||||
getBackEdges(localData, loops, throwStates);
|
||||
|
||||
new GraphPrecontinueDetector().detectPrecontinues(heads, allParts, loops);
|
||||
new GraphPrecontinueDetector().detectPrecontinues(heads, allParts, loops, throwStates);
|
||||
|
||||
/*System.err.println("<loopspre>");
|
||||
for (Loop el : loops) {
|
||||
@@ -1155,13 +1154,21 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart) throws InterruptedException {
|
||||
clearLoops(loops);
|
||||
getLoops(localData, part, loops, throwStates, stopPart, true, 1, new ArrayList<>());
|
||||
clearLoops(loops);
|
||||
private void clearThrowStates(List<ThrowState> throwStates) {
|
||||
for (ThrowState ts : throwStates) {
|
||||
ts.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean canBeBreakCandidate(GraphPart part) {
|
||||
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart) throws InterruptedException {
|
||||
clearLoops(loops);
|
||||
clearThrowStates(throwStates);
|
||||
getLoopsWalk(localData, part, loops, throwStates, stopPart, true, new ArrayList<>(), 0);
|
||||
clearLoops(loops);
|
||||
clearThrowStates(throwStates);
|
||||
}
|
||||
|
||||
protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1176,21 @@ public class Graph {
|
||||
|
||||
}
|
||||
|
||||
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart, boolean first, int level, List<GraphPart> visited) throws InterruptedException {
|
||||
private void findPartsOutsideTry(ThrowState ts, GraphPart part, List<GraphPart> ret, Set<GraphPart> visited) {
|
||||
if (visited.contains(part)) {
|
||||
return;
|
||||
}
|
||||
visited.add(part);
|
||||
if (!ts.throwingParts.contains(part)) {
|
||||
ret.add(part);
|
||||
return;
|
||||
}
|
||||
for (GraphPart n : part.nextParts) {
|
||||
findPartsOutsideTry(ts, n, ret, visited);
|
||||
}
|
||||
}
|
||||
|
||||
private void getLoopsWalk(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart, boolean first, List<GraphPart> visited, int level) throws InterruptedException {
|
||||
|
||||
if (part == null) {
|
||||
return;
|
||||
@@ -1184,6 +1205,15 @@ public class Graph {
|
||||
}
|
||||
checkGetLoopsPart(part);
|
||||
|
||||
List<ThrowState> currentThrowStates = new ArrayList<>();
|
||||
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.throwingParts.contains(part) && ts.state != 1) {
|
||||
currentThrowStates.add(ts);
|
||||
ts.state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (debugGetLoops) {
|
||||
System.err.println("getloops: " + part);
|
||||
}
|
||||
@@ -1200,8 +1230,11 @@ public class Graph {
|
||||
|
||||
}
|
||||
}
|
||||
if (lastP1 != null && canBeBreakCandidate(part)) {
|
||||
if (lastP1 != null && canBeBreakCandidate(localData, part)) {
|
||||
if (lastP1.breakCandidates.contains(part)) {
|
||||
if (part.start == 54) {
|
||||
System.err.println("xxx");
|
||||
}
|
||||
lastP1.breakCandidates.add(part);
|
||||
lastP1.breakCandidatesLevels.add(level);
|
||||
return;
|
||||
@@ -1259,16 +1292,16 @@ public class Graph {
|
||||
stopPart2.add(next);
|
||||
}
|
||||
if (next != nps.get(0)) {
|
||||
getLoops(localData, nps.get(0), loops, throwStates, stopPart2, false, level + 1, visited);
|
||||
getLoopsWalk(localData, nps.get(0), loops, throwStates, stopPart2, false, visited, level + 1);
|
||||
}
|
||||
if (next != nps.get(1)) {
|
||||
getLoops(localData, nps.get(1), loops, throwStates, stopPart2, false, level + 1, visited);
|
||||
getLoopsWalk(localData, nps.get(1), loops, throwStates, stopPart2, false, visited, level + 1);
|
||||
}
|
||||
if (next != null) {
|
||||
getLoops(localData, next, loops, throwStates, stopPart, false, level, visited);
|
||||
getLoopsWalk(localData, next, loops, throwStates, stopPart, false, visited, level);
|
||||
}
|
||||
} else if (part.nextParts.size() > 2 || partIsSwitch(part)) {
|
||||
GraphPart next = getNextCommonPart(localData, part, loops, throwStates);
|
||||
GraphPart next = getMostCommonPart(localData, part.nextParts, loops, throwStates);
|
||||
|
||||
for (GraphPart p : part.nextParts) {
|
||||
List<GraphPart> stopPart2 = stopPart == null ? new ArrayList<>() : new ArrayList<>(stopPart);
|
||||
@@ -1284,45 +1317,107 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
if (next != p) {
|
||||
getLoops(localData, p, loops, throwStates, stopPart2, false, level + 1, visited);
|
||||
getLoopsWalk(localData, p, loops, throwStates, stopPart2, false, visited, level + 1);
|
||||
}
|
||||
}
|
||||
if (next != null) {
|
||||
getLoops(localData, next, loops, throwStates, stopPart, false, level, visited);
|
||||
getLoopsWalk(localData, next, loops, throwStates, stopPart, false, visited, level);
|
||||
}
|
||||
} else if (part.nextParts.size() == 1) {
|
||||
getLoops(localData, part.nextParts.get(0), loops, throwStates, stopPart, false, level, visited);
|
||||
getLoopsWalk(localData, part.nextParts.get(0), loops, throwStates, stopPart, false, visited, level);
|
||||
}
|
||||
|
||||
List<Loop> loops2 = new ArrayList<>(loops);
|
||||
for (Loop l : loops2) {
|
||||
/*for (Loop l : loops2) {
|
||||
l.breakCandidatesLocked++;
|
||||
}
|
||||
}*/
|
||||
for (ThrowState ts : throwStates) {
|
||||
//check state?
|
||||
if (ts.throwingParts.contains(part)) {
|
||||
if (ts.throwingParts.contains(part) && (currentThrowStates.contains(ts) || ts.state != 1)) {
|
||||
GraphPart t = ts.targetPart;
|
||||
if (!visited.contains(t)) {
|
||||
getLoops(localData, t, loops, throwStates, stopPart, false, level, visited);
|
||||
getLoopsWalk(localData, t, loops, throwStates, stopPart, false, visited, level + 1 /*???*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Loop l : loops2) {
|
||||
/*for (Loop l : loops2) {
|
||||
l.breakCandidatesLocked--;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (isLoop && currentLoop != null) {
|
||||
GraphPart found;
|
||||
|
||||
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
|
||||
GraphPart ch = checkPart(null, localData, null, currentLoop.breakCandidates.get(i), null);
|
||||
if (ch == null) {
|
||||
currentLoop.breakCandidates.remove(i);
|
||||
currentLoop.breakCandidatesLevels.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (debugGetLoops) {
|
||||
System.err.println("loop " + currentLoop + " break candidates:");
|
||||
for (GraphPart cand : currentLoop.breakCandidates) {
|
||||
System.err.println("- " + cand);
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> contThrowStates = new ArrayList<>();
|
||||
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.throwingParts.contains(currentLoop.loopContinue)) {
|
||||
contThrowStates.add(ts.exceptionId);
|
||||
}
|
||||
}
|
||||
|
||||
Map<GraphPart, Integer> removed = new HashMap<>();
|
||||
do {
|
||||
found = null;
|
||||
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
|
||||
GraphPart ch = checkPart(null, localData, null, currentLoop.breakCandidates.get(i), null);
|
||||
if (ch == null) {
|
||||
currentLoop.breakCandidates.remove(i);
|
||||
i--;
|
||||
|
||||
loopcand:
|
||||
for (int c = 0; c < currentLoop.breakCandidates.size(); c++) {
|
||||
GraphPart cand = currentLoop.breakCandidates.get(c);
|
||||
List<Integer> candThrowStates = new ArrayList<>();
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.throwingParts.contains(cand)) {
|
||||
if (contThrowStates.equals(candThrowStates)) {
|
||||
//adding new ts
|
||||
//this means breakcandidate is in nested try
|
||||
if (debugGetLoops) {
|
||||
System.err.println("candidate " + cand + " is in inner try, getting outside parts");
|
||||
}
|
||||
List<GraphPart> outsideTry = new ArrayList<>();
|
||||
findPartsOutsideTry(ts, cand, outsideTry, new HashSet<>());
|
||||
|
||||
for (int j = outsideTry.size() - 1; j >= 0; j--) {
|
||||
if (!canBeBreakCandidate(localData, outsideTry.get(j))) {
|
||||
outsideTry.remove(j);
|
||||
}
|
||||
}
|
||||
if (debugGetLoops) {
|
||||
for (GraphPart op : outsideTry) {
|
||||
System.err.println("- outsidepart " + op);
|
||||
}
|
||||
}
|
||||
int bcLevel = currentLoop.breakCandidatesLevels.get(c);
|
||||
currentLoop.breakCandidates.remove(c);
|
||||
|
||||
currentLoop.breakCandidates.addAll(c, outsideTry);
|
||||
currentLoop.breakCandidatesLevels.remove(c);
|
||||
|
||||
removed.put(cand, bcLevel);
|
||||
for (int j = 0; j < outsideTry.size(); j++) {
|
||||
currentLoop.breakCandidatesLevels.add(c, bcLevel);
|
||||
}
|
||||
|
||||
c--;
|
||||
continue loopcand;
|
||||
}
|
||||
candThrowStates.add(ts.exceptionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
found = null;
|
||||
|
||||
loopcand:
|
||||
for (GraphPart cand : currentLoop.breakCandidates) {
|
||||
for (GraphPart cand2 : currentLoop.breakCandidates) {
|
||||
@@ -1372,7 +1467,7 @@ public class Graph {
|
||||
removed.put(found, maxlevel);
|
||||
}
|
||||
} while ((found != null) && (currentLoop.breakCandidates.size() > 1));
|
||||
|
||||
|
||||
Map<GraphPart, Integer> count = new HashMap<>();
|
||||
GraphPart winner = null;
|
||||
int winnerCount = 0;
|
||||
@@ -1431,7 +1526,7 @@ public class Graph {
|
||||
if (removedVisited.contains(r)) {
|
||||
continue;
|
||||
}
|
||||
getLoops(localData, r, loops, throwStates, stopPart, false, removed.get(r), visited);
|
||||
getLoopsWalk(localData, r, loops, throwStates, stopPart, false, visited, removed.get(r));
|
||||
removedVisited.add(r);
|
||||
}
|
||||
start = false;
|
||||
@@ -1444,7 +1539,7 @@ public class Graph {
|
||||
el.phase = 2;
|
||||
}
|
||||
}
|
||||
getLoops(localData, currentLoop.loopBreak, loops, throwStates, stopPart, false, level, visited);
|
||||
getLoopsWalk(localData, currentLoop.loopBreak, loops, throwStates, stopPart, false, visited, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1638,9 +1733,7 @@ public class Graph {
|
||||
|
||||
boolean vCanHandleVisited = canHandleVisited(localData, part);
|
||||
|
||||
/*if (part.start == 31) {
|
||||
|
||||
FIXME
|
||||
/*if (part.start == 25) {
|
||||
new RuntimeException().printStackTrace();
|
||||
}*/
|
||||
if (vCanHandleVisited) {
|
||||
|
||||
@@ -175,7 +175,6 @@ public class GraphPart implements Serializable {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (useThrow)
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.state != 1) {
|
||||
if (ts.throwingParts.contains(this)) {
|
||||
@@ -188,15 +187,6 @@ public class GraphPart implements Serializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if (useThrow) {
|
||||
for (GraphPart p : throwParts) {
|
||||
if (p == part) {
|
||||
return true;
|
||||
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -13,4 +13,29 @@ public class ThrowState {
|
||||
|
||||
public Set<GraphPart> throwingParts = new HashSet<>();
|
||||
public GraphPart targetPart;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 97 * hash + this.exceptionId;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ThrowState other = (ThrowState) obj;
|
||||
if (this.exceptionId != other.exceptionId) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph.precontinues;
|
||||
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import com.jpexs.decompiler.graph.ThrowState;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -40,7 +41,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class GraphPrecontinueDetector {
|
||||
|
||||
public void detectPrecontinues(List<GraphPart> heads, Set<GraphPart> allParts, List<Loop> loops) {
|
||||
public void detectPrecontinues(List<GraphPart> heads, Set<GraphPart> allParts, List<Loop> loops, List<ThrowState> throwStates) {
|
||||
boolean isSomethingTodo = false;
|
||||
for (Loop el : loops) {
|
||||
if (el.backEdges.size() == 1) {
|
||||
@@ -60,6 +61,12 @@ public class GraphPrecontinueDetector {
|
||||
for (GraphPart part : allParts) {
|
||||
Node node = partToNode.get(part);
|
||||
for (GraphPart prev : part.refs) {
|
||||
/*if (prev.start < 0 && !partToNode.containsKey(prev)) {
|
||||
Node minusNode = new Node();
|
||||
minusNode.graphPart = prev;
|
||||
partToNode.put(prev, node);
|
||||
continue;
|
||||
}*/
|
||||
if (prev.start < 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -90,6 +97,12 @@ public class GraphPrecontinueDetector {
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphPart> targetParts = new ArrayList<>();
|
||||
|
||||
for (ThrowState ts : throwStates) {
|
||||
targetParts.add(ts.targetPart);
|
||||
}
|
||||
|
||||
for (Loop el : loops) {
|
||||
if (el.backEdges.size() == 1) {
|
||||
//System.err.println("loop " + el.loopContinue);
|
||||
@@ -97,15 +110,26 @@ public class GraphPrecontinueDetector {
|
||||
Node node = partToNode.get(backEdgePart);
|
||||
//System.err.println("backedge:" + backEdgePart);
|
||||
boolean wholeLoop = false;
|
||||
while (node.parentNode != null) {
|
||||
node = node.parentNode;
|
||||
//System.err.println("- parent " + node.graphPart);
|
||||
if (node.graphPart.equals(el.loopContinue)) {
|
||||
wholeLoop = true;
|
||||
break;
|
||||
boolean inTryTarget = false;
|
||||
|
||||
if (targetParts.contains(node.graphPart)) {
|
||||
inTryTarget = true;
|
||||
}
|
||||
if (!inTryTarget) {
|
||||
while (node.parentNode != null) {
|
||||
node = node.parentNode;
|
||||
//System.err.println("- parent " + node.graphPart);
|
||||
if (node.graphPart.equals(el.loopContinue)) {
|
||||
wholeLoop = true;
|
||||
break;
|
||||
}
|
||||
if (targetParts.contains(node.graphPart)) {
|
||||
inTryTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wholeLoop) {
|
||||
if (!wholeLoop && !inTryTarget) {
|
||||
el.loopPreContinue = node.graphPart;
|
||||
//System.err.println("found precontinue:" + node.graphPart);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user