Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix variable used in switch head not being inlined #399

Merged
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 @@ -5,6 +5,7 @@
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType;
import org.jetbrains.java.decompiler.modules.decompiler.stats.*;
import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
Expand All @@ -15,6 +16,7 @@
import org.jetbrains.java.decompiler.util.Pair;

import java.util.*;
import java.util.stream.Stream;

public final class SwitchPatternMatchProcessor {
public static boolean processPatternMatching(Statement root) {
Expand Down Expand Up @@ -66,6 +68,7 @@ private static boolean processStatement(SwitchStatement stat, Statement root) {
Exprent realSelector = origParams.get(0);
boolean guarded = true;
boolean isEnumSwitch = value.getName().equals("enumSwitch");
boolean nullCase = false;
List<Pair<Statement, Exprent>> references = new ArrayList<>();
if (origParams.get(1) instanceof VarExprent) {
VarExprent var = (VarExprent) origParams.get(1);
Expand Down Expand Up @@ -134,6 +137,7 @@ private static boolean processStatement(SwitchStatement stat, Statement root) {

// -1 always means null
if (caseValue == -1) {
nullCase = true;
allCases.remove(caseExpr);
ConstExprent nullConst = new ConstExprent(VarType.VARTYPE_NULL, null, null);
// null can be shared with a pattern or default; put it at the end, but before default, to make sure it doesn't get
Expand Down Expand Up @@ -262,6 +266,41 @@ private static boolean processStatement(SwitchStatement stat, Statement root) {
}
}

Exprent oldSelector = realSelector;
jaskarth marked this conversation as resolved.
Show resolved Hide resolved
// inline head
List<Exprent> basicHead = stat.getBasichead().getExprents();
if (realSelector instanceof VarExprent var && basicHead != null && basicHead.size() >= 1) {
if (basicHead.get(basicHead.size() - 1) instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned) {
if (var.equals(assigned) && !var.isVarReferenced(root, Stream.concat(Stream.of(assigned), stat.getCaseValues().stream().flatMap(List::stream).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0) instanceof VarExprent checked && checked.equals(var)).map(exp -> (VarExprent) ((FunctionExprent) exp).getLstOperands().get(0))).toArray(VarExprent[]::new))) {
jaskarth marked this conversation as resolved.
Show resolved Hide resolved
realSelector = assignment.getRight();
basicHead.remove(basicHead.size() - 1);
}
}
}

// Check for non null
if (basicHead != null && basicHead.size() >= 1 && realSelector instanceof VarExprent var && !nullCase) {
Exprent last = basicHead.get(basicHead.size() - 1);
if (last instanceof InvocationExprent inv && inv.isStatic() && inv.getClassname().equals("java/util/Objects") && inv.getName().equals("requireNonNull") && inv.getStringDescriptor().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && var.equals(inv.getLstParameters().get(0))) {
basicHead.remove(basicHead.size() - 1);
// Check for other assignment
if (basicHead.size() >= 1 && var.isStack() && !nullCase) {
last = basicHead.get(basicHead.size() - 1);
if (last instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned && var.equals(assigned)) {
if (!var.isVarReferenced(root, assigned)) {
realSelector = assignment.getRight();
basicHead.remove(basicHead.size() - 1);
}
}
}
}
}

if (oldSelector != realSelector) {
Exprent finalSelector = realSelector;
stat.getCaseValues().stream().flatMap(List::stream).filter(Objects::nonNull).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0).equals(oldSelector)).forEach(exp -> ((FunctionExprent) exp).getLstOperands().set(0, finalSelector));
jaskarth marked this conversation as resolved.
Show resolved Hide resolved
}

head.setValue(realSelector); // SwitchBootstraps.typeSwitch(o, var1) -> o

if (guarded && stat.getParent() instanceof DoStatement) {
Expand Down
140 changes: 67 additions & 73 deletions testData/results/pkg/TestSwitchPatternMatching1.dec
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package pkg;

import java.util.Objects;

public class TestSwitchPatternMatching1 {
public void test(Object o) {
Objects.requireNonNull(o);// 5
switch (o) {
switch (o) {// 5
case Integer i:// 6
System.out.println(i);
break;
Expand All @@ -20,76 +17,73 @@ public class TestSwitchPatternMatching1 {

class 'pkg/TestSwitchPatternMatching1' {
method 'test (Ljava/lang/Object;)V' {
0 6
2 6
3 6
4 6
9 7
10 7
11 7
12 7
13 7
14 7
15 7
16 7
17 7
18 7
19 7
1a 7
1b 7
1c 7
1d 7
1e 7
1f 7
20 7
21 7
22 7
23 7
24 7
25 7
26 7
27 7
28 7
29 7
2a 7
2b 7
30 8
31 8
32 9
33 9
34 9
35 9
36 9
37 9
38 9
39 9
3a 10
41 11
42 11
43 12
44 12
45 12
46 12
47 12
48 12
49 12
4a 12
4b 13
4e 15
4f 15
50 15
51 15
52 15
53 15
54 15
55 15
56 17
0 4
9 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 4
1d 4
1e 4
1f 4
20 4
21 4
22 4
23 4
24 4
25 4
26 4
27 4
28 4
29 4
2a 4
2b 4
30 5
31 5
32 6
33 6
34 6
35 6
36 6
37 6
38 6
39 6
3a 7
41 8
42 8
43 9
44 9
45 9
46 9
47 9
48 9
49 9
4a 9
4b 10
4e 12
4f 12
50 12
51 12
52 12
53 12
54 12
55 12
56 14
}
}

Lines mapping:
5 <-> 7
6 <-> 9
7 <-> 12
8 <-> 16
10 <-> 18
5 <-> 5
6 <-> 6
7 <-> 9
8 <-> 13
10 <-> 15
Loading
Loading