Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
import org.jetbrains.java.decompiler.modules.decompiler.flow.FlattenStatementsHelper;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.*;
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.DoStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.*;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionNode;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionsGraph;
Expand All @@ -34,6 +31,7 @@

import java.util.*;
import java.util.Map.Entry;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class StackVarsProcessor {
Expand Down Expand Up @@ -123,21 +121,47 @@ private static boolean iterateStatements(RootStatement root, SSAUConstructorSpar
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root);

Map<VarVersionPair, LocalVariable> lvts = new HashMap<>();

boolean res = iterateStatementsNested(root, dgraph.first, ssa, options, dgraph, lvts, new HashSet<>(), new LinkedList<>(), new LinkedList<>(), null);

dgraph.iterateExprentsDeep(ex -> {
if (ex instanceof VarExprent var && lvts.containsKey(var.getVarVersionPair())) {
LocalVariable lvt = lvts.get(var.getVarVersionPair());
if (var.getLVT() == null) {
var.setLVT(lvt);
}
}

return 0;
});

return res;
}

private static boolean iterateStatementsNested(Statement root, DirectNode start, SSAUConstructorSparseEx ssa, StackSimplifyOptions options, DirectGraph dgraph, Map<VarVersionPair, LocalVariable> lvts, Set<DirectNode> setVisited, LinkedList<DirectNode> parentStack, LinkedList<Map<VarVersionPair, Exprent>> parentStackMaps, Map<VarVersionPair, Exprent> currentParentStackMap) {

This comment was marked as spam.

boolean res = false;

Set<DirectNode> setVisited = new HashSet<>();
LinkedList<DirectNode> stack = new LinkedList<>();
LinkedList<Map<VarVersionPair, Exprent>> stackMaps = new LinkedList<>();

stack.add(dgraph.first);
stack.add(start);
stackMaps.add(new HashMap<>());

Map<VarVersionPair, LocalVariable> lvts = new HashMap<>();

int[] ret = {0, 0};
while (!stack.isEmpty()) {
DirectNode nd = stack.removeFirst();
Map<VarVersionPair, Exprent> mapVarValues = stackMaps.removeFirst();

// Treat phantom switch statements as a sub method
if (nd.statement instanceof SwitchStatement switchSt && switchSt.isPhantom() && root != switchSt) {
res |= iterateStatementsNested(switchSt, nd, ssa, options, dgraph, lvts, setVisited, stack, stackMaps, mapVarValues);
continue;
} else if (!root.containsStatement(nd.statement) && !(root instanceof RootStatement)) {
parentStack.add(nd);
parentStackMaps.add(new HashMap<>(currentParentStackMap));
continue;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this case


if (setVisited.contains(nd)) {
continue;
Expand All @@ -156,8 +180,51 @@ private static boolean iterateStatements(RootStatement root, SSAUConstructorSpar
DirectNode ndsucc = succs.get(0).getDestination();

if (ndsucc.type == DirectNodeType.TAIL && !ndsucc.exprents.isEmpty()) {
lstLists.add(succs.get(0).getDestination().exprents);
nd = ndsucc;

// Skip over phantom switch statements
if (ndsucc.statement instanceof SwitchStatement switchSt && switchSt.isPhantom()) {

This comment was marked as spam.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what is going on here :[

Set<DirectNode> visited = new HashSet<>();
List<DirectNode> nodes = new ArrayList<>();
nodes.add(ndsucc);
boolean changed = false;
do {
changed = false;
List<DirectNode> newNodes = new ArrayList<>();
for (DirectNode node : nodes) {
if (switchSt.containsStatement(node.statement)) {
for (DirectEdge next : node.getSuccessors(DirectEdgeType.REGULAR)) {
if (!(next.getDestination().statement instanceof DummyExitStatement) && visited.add(next.getDestination())) {
newNodes.add(next.getDestination());
changed = true;
}
}
} else {
newNodes.add(node);
}
}
nodes = newNodes;
} while (changed);

if (nodes.size() == 1) {
ndsucc = nodes.get(0);
} else {
ndsucc = null;
}

while (ndsucc != null && ndsucc.exprents.isEmpty()) {

This comment was marked as spam.

List<DirectEdge> next = ndsucc.getSuccessors(DirectEdgeType.REGULAR);
if (next.size() == 1) {
ndsucc = next.get(0).getDestination();
} else {
ndsucc = null;
}
}
}

if (ndsucc != null) {
lstLists.add(ndsucc.exprents);
nd = ndsucc;
}
}
}

Expand Down Expand Up @@ -235,18 +302,6 @@ private static boolean iterateStatements(RootStatement root, SSAUConstructorSpar
}
}
}

dgraph.iterateExprentsDeep(ex -> {
if (ex instanceof VarExprent var && lvts.containsKey(var.getVarVersionPair())) {
LocalVariable lvt = lvts.get(var.getVarVersionPair());
if (var.getLVT() == null) {
var.setLVT(lvt);
}
}

return 0;
});

return res;
}

Expand Down Expand Up @@ -316,7 +371,11 @@ private static void iterateExprent(List<Exprent> lstExprents,
int changed = 0;

Object[] arr = {null, false, false};
for (Exprent expr : exprent.getAllExprents()) {
List<Exprent> containing = exprent.getAllExprents();
if (exprent instanceof SwitchExprent switchExp) {
containing = switchExp.getBacking().getHeadexprentList();
}
for (Exprent expr : containing) {
while (true) {
iterateChildExprent(expr, exprent, next, mapVarValues, ssau, arr, options);
Exprent retexpr = (Exprent)arr[0];
Expand Down Expand Up @@ -758,7 +817,11 @@ private static void iterateChildExprent(Exprent exprent,
boolean changed = false;

Object[] arr = {null, false, false};
for (Exprent expr : exprent.getAllExprents()) {
List<Exprent> containing = exprent.getAllExprents();
if (exprent instanceof SwitchExprent switchExp) {
containing = switchExp.getBacking().getHeadexprentList();
}
for (Exprent expr : containing) {
while (true) {
iterateChildExprent(expr, parent, next, mapVarValues, ssau, arr, options);
Exprent retexpr = (Exprent)arr[0];
Expand Down
2 changes: 2 additions & 0 deletions test/org/jetbrains/java/decompiler/SingleClassesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,8 @@ private void registerDefault() {
register(JAVA_17, "TestStringSwitchTypes");

register(JAVA_16, "TestSwitchExpressionIfBlocks");

register(JAVA_16, "TestSwitchExpressionMultiple");
}

private void registerEntireClassPath() {
Expand Down
171 changes: 171 additions & 0 deletions testData/results/pkg/TestSwitchExpressionMultiple.dec
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package pkg;

public class TestSwitchExpressionMultiple {
public int test(int i1, int i2) {
return switch (switch (i2) {// 5
case 0 -> 1;// 6
case 1 -> 0;// 7
default -> 0;// 8
}) {
case 0 -> 1;// 10
case 1 -> 0;// 11
default -> 0;// 12
} + switch (i1) {
case 0 -> {
switch (i2) {// 14
case 0:
yield 1;// 15
case 1:
yield 0;// 16
default:
yield 0;// 17
}
}
case 1 -> 0;// 19
default -> 0;// 20
};
}
}

class 'pkg/TestSwitchExpressionMultiple' {
method 'test (II)I' {
0 4
1 4
2 4
3 4
4 4
5 4
6 4
7 4
8 4
9 4
a 4
b 4
c 4
d 4
e 4
f 4
10 4
11 4
12 4
13 4
14 4
15 4
16 4
17 4
18 4
19 4
1a 4
1b 4
1c 5
20 6
24 7
25 4
26 4
27 4
28 4
29 4
2a 4
2b 4
2c 4
2d 4
2e 4
2f 4
30 4
31 4
32 4
33 4
34 4
35 4
36 4
37 4
38 4
39 4
3a 4
3b 4
3c 4
3d 4
3e 4
3f 4
40 9
44 10
48 11
49 12
4a 12
4b 12
4c 12
4d 12
4e 12
4f 12
50 12
51 12
52 12
53 12
54 12
55 12
56 12
57 12
58 12
59 12
5a 12
5b 12
5c 12
5d 12
5e 12
5f 12
60 12
61 12
62 12
63 12
64 14
65 14
66 14
67 14
68 14
69 14
6a 14
6b 14
6c 14
6d 14
6e 14
6f 14
70 14
71 14
72 14
73 14
74 14
75 14
76 14
77 14
78 14
79 14
7a 14
7b 14
7c 14
7d 14
7e 14
7f 14
80 16
84 18
88 20
8c 23
90 24
91 4
92 4
}
}

Lines mapping:
5 <-> 5
6 <-> 6
7 <-> 7
8 <-> 8
10 <-> 10
11 <-> 11
12 <-> 12
14 <-> 15
15 <-> 17
16 <-> 19
17 <-> 21
19 <-> 24
20 <-> 25
23 changes: 23 additions & 0 deletions testData/src/java16/pkg/TestSwitchExpressionMultiple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package pkg;

public class TestSwitchExpressionMultiple {

This comment was marked as spam.

public int test(int i1, int i2) {
return switch (switch (i2) {
case 0 -> 1;
case 1 -> 0;
default -> 0;
}) {
case 0 -> 1;
case 1 -> 0;
default -> 0;
} + switch (i1) {
case 0 -> switch (i2) {
case 0 -> 1;
case 1 -> 0;
default -> 0;
};
case 1 -> 0;
default -> 0;
};
}
}
Loading