|
1 | 1 | // 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. |
2 | 2 | package org.jetbrains.java.decompiler.modules.decompiler; |
3 | 3 |
|
4 | | -import org.jetbrains.java.decompiler.code.CodeConstants; |
5 | 4 | import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; |
6 | 5 | import org.jetbrains.java.decompiler.main.DecompilerContext; |
7 | 6 | import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; |
8 | 7 | import org.jetbrains.java.decompiler.main.rels.ClassWrapper; |
9 | 8 | import org.jetbrains.java.decompiler.modules.decompiler.exps.*; |
10 | 9 | import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType; |
11 | 10 | import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAConstructorSparseEx; |
| 11 | +import org.jetbrains.java.decompiler.modules.decompiler.sforms.SSAUConstructorSparseEx; |
12 | 12 | import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement; |
13 | 13 | import org.jetbrains.java.decompiler.modules.decompiler.stats.IfStatement; |
14 | 14 | import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; |
| 15 | +import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionNode; |
15 | 16 | import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair; |
16 | 17 | import org.jetbrains.java.decompiler.struct.StructClass; |
17 | 18 | import org.jetbrains.java.decompiler.struct.gen.CodeType; |
@@ -1175,4 +1176,84 @@ private static boolean collapseInlinedClass14(Statement stat) { |
1175 | 1176 |
|
1176 | 1177 | return ret; |
1177 | 1178 | } |
| 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 | + } |
1178 | 1259 | } |
0 commit comments