Skip to content

Commit d294487

Browse files
committed
SSAU-lite
1 parent 2a87a7e commit d294487

File tree

4 files changed

+112
-3
lines changed

4 files changed

+112
-3
lines changed

src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler;
33

4-
import org.jetbrains.java.decompiler.code.CodeConstants;
54
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
65
import org.jetbrains.java.decompiler.main.DecompilerContext;
76
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
87
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
98
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
109
import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType;
1110
import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAConstructorSparseEx;
11+
import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAUConstructorSparseEx;
1212
import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement;
1313
import org.jetbrains.java.decompiler.modules.decompiler.stats.IfStatement;
1414
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
15+
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionNode;
1516
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
1617
import org.jetbrains.java.decompiler.struct.StructClass;
1718
import org.jetbrains.java.decompiler.struct.gen.CodeType;
@@ -1175,4 +1176,84 @@ private static boolean collapseInlinedClass14(Statement stat) {
11751176

11761177
return ret;
11771178
}
1179+
1180+
public static boolean simplifySimple(Statement stat, SSAUConstructorSparseEx ssu) {
1181+
if (stat instanceof BasicBlockStatement bbStat) {
1182+
return simplifySimpleBlock(bbStat, ssu);
1183+
}
1184+
boolean simplified = false;
1185+
for(var subStat : stat.getStats()) {
1186+
simplified |= simplifySimple(subStat, ssu);
1187+
}
1188+
return simplified;
1189+
}
1190+
1191+
private static boolean simplifySimpleBlock(BasicBlockStatement bbStat, SSAUConstructorSparseEx ssu) {
1192+
var statExprents = bbStat.getExprents();
1193+
if (statExprents == null) {
1194+
return false;
1195+
}
1196+
1197+
boolean simplified = false;
1198+
1199+
for (int i = statExprents.size() - 1; i > 0; i--) {
1200+
var prevExprent = statExprents.get(i - 1);
1201+
if (prevExprent instanceof AssignmentExprent ass &&
1202+
ass.getCondType() == null &&
1203+
ass.getLeft() instanceof VarExprent varExprent &&
1204+
varExprent.isStack()
1205+
){
1206+
VarVersionNode node = ssu.getNode(varExprent);
1207+
if (node.hasSingleSuccessor()) {
1208+
VarVersionNode targetNode = node.getSingleSuccessor();
1209+
if (targetNode.hasSinglePredecessor() && !targetNode.hasAnySuccessors()) {
1210+
// inlining in next exprent if the use is in the next exprent
1211+
1212+
if (inlineExprent(statExprents.get(i), targetNode.asPair(), ass.getRight()) == 1){
1213+
simplified = true;
1214+
statExprents.remove(i - 1);
1215+
}
1216+
}
1217+
}
1218+
}
1219+
}
1220+
return simplified;
1221+
}
1222+
1223+
// 0 => fail; 1 => success; 2 => fail, stop looking (impure)
1224+
private static int inlineExprent(
1225+
Exprent targetExprent,
1226+
VarVersionPair replaceablePair,
1227+
Exprent replaceExprent
1228+
) {
1229+
// step 1: find exprent
1230+
for (var subExprent : targetExprent.getAllExprents()) {
1231+
if (subExprent instanceof VarExprent varExprent) {
1232+
if (varExprent.getIndex() == replaceablePair.var &&
1233+
varExprent.getVersion() == replaceablePair.version) {
1234+
1235+
targetExprent.replaceExprent(varExprent, replaceExprent);
1236+
return 1;
1237+
}
1238+
}
1239+
1240+
if ((subExprent.getExprentUse() & Exprent.SIDE_EFFECTS_FREE) != 0) {
1241+
int sub = inlineExprent(subExprent, replaceablePair, replaceExprent);
1242+
if( sub > 0 ) {
1243+
return sub;
1244+
}
1245+
} else if(subExprent instanceof InvocationExprent) {
1246+
int sub = inlineExprent(subExprent, replaceablePair, replaceExprent);
1247+
if( sub > 0 ) {
1248+
return sub;
1249+
}
1250+
return 2;
1251+
} else {
1252+
return 2; // safety
1253+
}
1254+
}
1255+
1256+
// exprent use is not here
1257+
return 0;
1258+
}
11781259
}

src/org/jetbrains/java/decompiler/modules/decompiler/StackVarsProcessor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ public static void simplifyStackVars(RootStatement root, StructMethod mt, Struct
6464
SequenceHelper.condenseSequences(root);
6565
ValidationHelper.validateStatement(root);
6666

67+
if (first) {
68+
ssau = new SSAUConstructorSparseEx(false);
69+
ssau.splitVariables(root, mt);
70+
71+
found |= SimplifyExprentsHelper.simplifySimple(root, ssau);
72+
73+
setVersionsToNull(root);
74+
}
75+
6776
ssau = new SSAUConstructorSparseEx();
6877
ssau.splitVariables(root, mt);
6978

src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,28 @@ public class SSAUConstructorSparseEx extends SFormsConstructor {
3131
// field access counter
3232
private int fieldVarCounter = -1;
3333

34-
public SSAUConstructorSparseEx() {
34+
final private boolean trackLiveVars;
35+
36+
public SSAUConstructorSparseEx(boolean trackLiveVars) {
3537
super(
3638
true,
3739
true
3840
);
41+
42+
this.trackLiveVars = trackLiveVars;
43+
}
44+
45+
public SSAUConstructorSparseEx() {
46+
this(true);
3947
}
4048

4149
@Override
4250
public void splitVariables(RootStatement root, StructMethod mt) {
4351
super.splitVariables(root, mt);
4452

45-
this.ssaStatements(this.dgraph, new HashSet<>(), true, mt, 999_999);
53+
if (this.trackLiveVars) {
54+
this.ssaStatements(this.dgraph, new HashSet<>(), true, mt, 999_999);
55+
}
4656

4757
// this.ssuVersions.initDominators();
4858

src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionNode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ public boolean hasSinglePredecessor() {
4949
return this.predecessors.size() == 1;
5050
}
5151

52+
public boolean hasSingleSuccessor() {
53+
return this.successors.size() == 1;
54+
}
55+
5256
public boolean hasAnySuccessors() {
5357
return !this.successors.isEmpty();
5458
}
@@ -58,6 +62,11 @@ public VarVersionNode getSinglePredecessor() {
5862
return this.predecessors.iterator().next();
5963
}
6064

65+
public VarVersionNode getSingleSuccessor() {
66+
ValidationHelper.validateTrue(this.hasSingleSuccessor(), "Expected only a single successor");
67+
return this.successors.iterator().next();
68+
}
69+
6170
@Override
6271
public String toString() {
6372
return "(" + this.var + "_" + this.version + ")";

0 commit comments

Comments
 (0)