[java decompiler] cleanup (dead code; optimizations; warnings)

master
Roman Shevchenko 7 years ago
parent 71d8f4d689
commit 29de7ad72e
  1. 31
      src/org/jetbrains/java/decompiler/code/CodeConstants.java
  2. 468
      src/org/jetbrains/java/decompiler/code/ConstantsUtil.java
  3. 26
      src/org/jetbrains/java/decompiler/code/ExceptionHandler.java
  4. 32
      src/org/jetbrains/java/decompiler/code/ExceptionTable.java
  5. 22
      src/org/jetbrains/java/decompiler/code/IfInstruction.java
  6. 135
      src/org/jetbrains/java/decompiler/code/Instruction.java
  7. 87
      src/org/jetbrains/java/decompiler/code/InstructionSequence.java
  8. 24
      src/org/jetbrains/java/decompiler/code/JumpInstruction.java
  9. 66
      src/org/jetbrains/java/decompiler/code/SwitchInstruction.java
  10. 85
      src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java
  11. 73
      src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java
  12. 48
      src/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java
  13. 31
      src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java
  14. 272
      src/org/jetbrains/java/decompiler/code/interpreter/Util.java
  15. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/ALOAD.java
  16. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/ANEWARRAY.java
  17. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/ASTORE.java
  18. 34
      src/org/jetbrains/java/decompiler/code/optinstructions/BIPUSH.java
  19. 20
      src/org/jetbrains/java/decompiler/code/optinstructions/CHECKCAST.java
  20. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/DLOAD.java
  21. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/DSTORE.java
  22. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/FLOAD.java
  23. 46
      src/org/jetbrains/java/decompiler/code/optinstructions/FSTORE.java
  24. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/GETFIELD.java
  25. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/GETSTATIC.java
  26. 32
      src/org/jetbrains/java/decompiler/code/optinstructions/GOTO.java
  27. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/GOTO_W.java
  28. 29
      src/org/jetbrains/java/decompiler/code/optinstructions/IINC.java
  29. 41
      src/org/jetbrains/java/decompiler/code/optinstructions/ILOAD.java
  30. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/INSTANCEOF.java
  31. 21
      src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEDYNAMIC.java
  32. 21
      src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEINTERFACE.java
  33. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESPECIAL.java
  34. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESTATIC.java
  35. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEVIRTUAL.java
  36. 41
      src/org/jetbrains/java/decompiler/code/optinstructions/ISTORE.java
  37. 32
      src/org/jetbrains/java/decompiler/code/optinstructions/JSR.java
  38. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/JSR_W.java
  39. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/LDC.java
  40. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/LDC2_W.java
  41. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/LDC_W.java
  42. 41
      src/org/jetbrains/java/decompiler/code/optinstructions/LLOAD.java
  43. 28
      src/org/jetbrains/java/decompiler/code/optinstructions/LOOKUPSWITCH.java
  44. 41
      src/org/jetbrains/java/decompiler/code/optinstructions/LSTORE.java
  45. 20
      src/org/jetbrains/java/decompiler/code/optinstructions/MULTIANEWARRAY.java
  46. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/NEW.java
  47. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/NEWARRAY.java
  48. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/PUTFIELD.java
  49. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/PUTSTATIC.java
  50. 27
      src/org/jetbrains/java/decompiler/code/optinstructions/RET.java
  51. 19
      src/org/jetbrains/java/decompiler/code/optinstructions/SIPUSH.java
  52. 28
      src/org/jetbrains/java/decompiler/code/optinstructions/TABLESWITCH.java
  53. 12
      src/org/jetbrains/java/decompiler/main/AssertProcessor.java
  54. 14
      src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
  55. 16
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  56. 34
      src/org/jetbrains/java/decompiler/main/TextBuffer.java
  57. 22
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java
  58. 10
      src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java
  59. 5
      src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java
  60. 3
      src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
  61. 16
      src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
  62. 140
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  63. 4
      src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
  64. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java
  65. 16
      src/org/jetbrains/java/decompiler/modules/decompiler/DecHelper.java
  66. 24
      src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java
  67. 197
      src/org/jetbrains/java/decompiler/modules/decompiler/EliminateLoopsHelper.java
  68. 7
      src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java
  69. 65
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  70. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprentStack.java
  71. 150
      src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java
  72. 16
      src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java
  73. 48
      src/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java
  74. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/InlineSingleBlockHelper.java
  75. 36
      src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java
  76. 9
      src/org/jetbrains/java/decompiler/modules/decompiler/LoopExtractHelper.java
  77. 194
      src/org/jetbrains/java/decompiler/modules/decompiler/LowBreakHelper.java
  78. 41
      src/org/jetbrains/java/decompiler/modules/decompiler/MergeHelper.java
  79. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java
  80. 175
      src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java
  81. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/StackVarsProcessor.java
  82. 3
      src/org/jetbrains/java/decompiler/modules/decompiler/StatEdge.java
  83. 136
      src/org/jetbrains/java/decompiler/modules/decompiler/StrongConnectivityHelper.java
  84. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/SwitchHelper.java
  85. 21
      src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java
  86. 129
      src/org/jetbrains/java/decompiler/modules/decompiler/decompose/FastExtendedPostdominanceHelper.java
  87. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/decompose/GenericDominatorEngine.java
  88. 12
      src/org/jetbrains/java/decompiler/modules/decompiler/deobfuscator/ExceptionDeobfuscator.java
  89. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java
  90. 26
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
  91. 15
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java
  92. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java
  93. 19
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java
  94. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java
  95. 9
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java
  96. 28
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java
  97. 22
      src/org/jetbrains/java/decompiler/modules/decompiler/sforms/FlattenStatementsHelper.java
  98. 13
      src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAConstructorSparseEx.java
  99. 20
      src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java
  100. 20
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,8 +1,8 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
@SuppressWarnings({"unused", "SpellCheckingInspection"})
public interface CodeConstants {
// ----------------------------------------------------------------------
// BYTECODE VERSIONS
// ----------------------------------------------------------------------
@ -50,20 +50,6 @@ public interface CodeConstants {
int TYPE_FAMILY_DOUBLE = 5;
int TYPE_FAMILY_OBJECT = 6;
// ----------------------------------------------------------------------
// MODULE CONSTANTS
// ----------------------------------------------------------------------
int STACKSIZE_SIMPLE = 1;
int STACKSIZE_DOUBLE = 2;
int VAR_LOCAL = 0;
int VAR_STACK = 1;
int VAR_WRITE = 0;
int VAR_READ = 1;
// ----------------------------------------------------------------------
// ACCESS FLAGS
// ----------------------------------------------------------------------
@ -92,17 +78,6 @@ public interface CodeConstants {
int ACC_SUPER = 0x0020;
int ACC_INTERFACE = 0x0200;
// ----------------------------------------------------------------------
// DEPENDENCY CONSTANTS
// ----------------------------------------------------------------------
int DEP_CONSTANT = 0;
int DEP_UNKNOWN = 1;
int DEP_GENERAL = 2;
int DEP_PARAMS = 4;
int DEP_STATIC = 8;
// ----------------------------------------------------------------------
// INSTRUCTION GROUPS
// ----------------------------------------------------------------------
@ -338,7 +313,6 @@ public interface CodeConstants {
int opc_invokestatic = 184;
int opc_invokeinterface = 185;
int opc_invokedynamic = 186;
int opc_xxxunusedxxx = 186;
int opc_new = 187;
int opc_newarray = 188;
int opc_anewarray = 189;
@ -355,7 +329,6 @@ public interface CodeConstants {
int opc_goto_w = 200;
int opc_jsr_w = 201;
@SuppressWarnings("SpellCheckingInspection")
String CLINIT_NAME = "<clinit>";
String INIT_NAME = "<init>";
}
}

@ -1,468 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.code.optinstructions.*;
public class ConstantsUtil {
public static String getName(int opcode) {
return opcodeNames[opcode];
}
public static Instruction getInstructionInstance(int opcode, boolean wide, int group, int bytecode_version, int[] operands) {
Instruction instr = getInstructionInstance(opcode, bytecode_version);
instr.wide = wide;
instr.group = group;
instr.bytecode_version = bytecode_version;
instr.setOperands(operands);
return instr;
}
private static Instruction getInstructionInstance(int opcode, int bytecode_version) {
try {
Instruction instr;
if ((opcode >= CodeConstants.opc_ifeq &&
opcode <= CodeConstants.opc_if_acmpne) ||
opcode == CodeConstants.opc_ifnull ||
opcode == CodeConstants.opc_ifnonnull) {
instr = new IfInstruction();
}
else {
Class cl = opcodeClasses[opcode];
if (opcode == CodeConstants.opc_invokedynamic && bytecode_version < CodeConstants.BYTECODE_JAVA_7) {
cl = null; // instruction unused in Java 6 and before
}
if (cl == null) {
instr = new Instruction();
}
else {
instr = (Instruction)cl.newInstance();
}
}
instr.opcode = opcode;
return instr;
}
catch (Exception ex) {
return null;
}
}
private static final String[] opcodeNames = {
"nop", // "nop",
"aconst_null", // "aconst_null",
"iconst_m1", // "iconst_m1",
"iconst_0", // "iconst_0",
"iconst_1", // "iconst_1",
"iconst_2", // "iconst_2",
"iconst_3", // "iconst_3",
"iconst_4", // "iconst_4",
"iconst_5", // "iconst_5",
"lconst_0", // "lconst_0",
"lconst_1", // "lconst_1",
"fconst_0", // "fconst_0",
"fconst_1", // "fconst_1",
"fconst_2", // "fconst_2",
"dconst_0", // "dconst_0",
"dconst_1", // "dconst_1",
"bipush", // "bipush",
"sipush", // "sipush",
"ldc", // "ldc",
"ldc_w", // "ldc_w",
"ldc2_w", // "ldc2_w",
"iload", // "iload",
"lload", // "lload",
"fload", // "fload",
"dload", // "dload",
"aload", // "aload",
"iload_0", // "iload_0",
"iload_1", // "iload_1",
"iload_2", // "iload_2",
"iload_3", // "iload_3",
"lload_0", // "lload_0",
"lload_1", // "lload_1",
"lload_2", // "lload_2",
"lload_3", // "lload_3",
"fload_0", // "fload_0",
"fload_1", // "fload_1",
"fload_2", // "fload_2",
"fload_3", // "fload_3",
"dload_0", // "dload_0",
"dload_1", // "dload_1",
"dload_2", // "dload_2",
"dload_3", // "dload_3",
"aload_0", // "aload_0",
"aload_1", // "aload_1",
"aload_2", // "aload_2",
"aload_3", // "aload_3",
"iaload", // "iaload",
"laload", // "laload",
"faload", // "faload",
"daload", // "daload",
"aaload", // "aaload",
"baload", // "baload",
"caload", // "caload",
"saload", // "saload",
"istore", // "istore",
"lstore", // "lstore",
"fstore", // "fstore",
"dstore", // "dstore",
"astore", // "astore",
"istore_0", // "istore_0",
"istore_1", // "istore_1",
"istore_2", // "istore_2",
"istore_3", // "istore_3",
"lstore_0", // "lstore_0",
"lstore_1", // "lstore_1",
"lstore_2", // "lstore_2",
"lstore_3", // "lstore_3",
"fstore_0", // "fstore_0",
"fstore_1", // "fstore_1",
"fstore_2", // "fstore_2",
"fstore_3", // "fstore_3",
"dstore_0", // "dstore_0",
"dstore_1", // "dstore_1",
"dstore_2", // "dstore_2",
"dstore_3", // "dstore_3",
"astore_0", // "astore_0",
"astore_1", // "astore_1",
"astore_2", // "astore_2",
"astore_3", // "astore_3",
"iastore", // "iastore",
"lastore", // "lastore",
"fastore", // "fastore",
"dastore", // "dastore",
"aastore", // "aastore",
"bastore", // "bastore",
"castore", // "castore",
"sastore", // "sastore",
"pop", // "pop",
"pop2", // "pop2",
"dup", // "dup",
"dup_x1", // "dup_x1",
"dup_x2", // "dup_x2",
"dup2", // "dup2",
"dup2_x1", // "dup2_x1",
"dup2_x2", // "dup2_x2",
"swap", // "swap",
"iadd", // "iadd",
"ladd", // "ladd",
"fadd", // "fadd",
"dadd", // "dadd",
"isub", // "isub",
"lsub", // "lsub",
"fsub", // "fsub",
"dsub", // "dsub",
"imul", // "imul",
"lmul", // "lmul",
"fmul", // "fmul",
"dmul", // "dmul",
"idiv", // "idiv",
"ldiv", // "ldiv",
"fdiv", // "fdiv",
"ddiv", // "ddiv",
"irem", // "irem",
"lrem", // "lrem",
"frem", // "frem",
"drem", // "drem",
"ineg", // "ineg",
"lneg", // "lneg",
"fneg", // "fneg",
"dneg", // "dneg",
"ishl", // "ishl",
"lshl", // "lshl",
"ishr", // "ishr",
"lshr", // "lshr",
"iushr", // "iushr",
"lushr", // "lushr",
"iand", // "iand",
"land", // "land",
"ior", // "ior",
"lor", // "lor",
"ixor", // "ixor",
"lxor", // "lxor",
"iinc", // "iinc",
"i2l", // "i2l",
"i2f", // "i2f",
"i2d", // "i2d",
"l2i", // "l2i",
"l2f", // "l2f",
"l2d", // "l2d",
"f2i", // "f2i",
"f2l", // "f2l",
"f2d", // "f2d",
"d2i", // "d2i",
"d2l", // "d2l",
"d2f", // "d2f",
"i2b", // "i2b",
"i2c", // "i2c",
"i2s", // "i2s",
"lcmp", // "lcmp",
"fcmpl", // "fcmpl",
"fcmpg", // "fcmpg",
"dcmpl", // "dcmpl",
"dcmpg", // "dcmpg",
"ifeq", // "ifeq",
"ifne", // "ifne",
"iflt", // "iflt",
"ifge", // "ifge",
"ifgt", // "ifgt",
"ifle", // "ifle",
"if_icmpeq", // "if_icmpeq",
"if_icmpne", // "if_icmpne",
"if_icmplt", // "if_icmplt",
"if_icmpge", // "if_icmpge",
"if_icmpgt", // "if_icmpgt",
"if_icmple", // "if_icmple",
"if_acmpeq", // "if_acmpeq",
"if_acmpne", // "if_acmpne",
"goto", // "goto",
"jsr", // "jsr",
"ret", // "ret",
"tableswitch", // "tableswitch",
"lookupswitch", // "lookupswitch",
"ireturn", // "ireturn",
"lreturn", // "lreturn",
"freturn", // "freturn",
"dreturn", // "dreturn",
"areturn", // "areturn",
"return", // "return",
"getstatic", // "getstatic",
"putstatic", // "putstatic",
"getfield", // "getfield",
"putfield", // "putfield",
"invokevirtual", // "invokevirtual",
"invokespecial", // "invokespecial",
"invokestatic", // "invokestatic",
"invokeinterface", // "invokeinterface",
//"xxxunusedxxx", // "xxxunusedxxx", Java 6 and before
"invokedynamic", // "invokedynamic", Java 7 and later
"new", // "new",
"newarray", // "newarray",
"anewarray", // "anewarray",
"arraylength", // "arraylength",
"athrow", // "athrow",
"checkcast", // "checkcast",
"instanceof", // "instanceof",
"monitorenter", // "monitorenter",
"monitorexit", // "monitorexit",
"wide", // "wide",
"multianewarray", // "multianewarray",
"ifnull", // "ifnull",
"ifnonnull", // "ifnonnull",
"goto_w", // "goto_w",
"jsr_w" // "jsr_w"
};
private static final Class[] opcodeClasses = {
null, // "nop",
null, // "aconst_null",
null, // "iconst_m1",
null, // "iconst_0",
null, // "iconst_1",
null, // "iconst_2",
null, // "iconst_3",
null, // "iconst_4",
null, // "iconst_5",
null, // "lconst_0",
null, // "lconst_1",
null, // "fconst_0",
null, // "fconst_1",
null, // "fconst_2",
null, // "dconst_0",
null, // "dconst_1",
BIPUSH.class, // "bipush",
SIPUSH.class, // "sipush",
LDC.class, // "ldc",
LDC_W.class, // "ldc_w",
LDC2_W.class, // "ldc2_w",
ILOAD.class, // "iload",
LLOAD.class, // "lload",
FLOAD.class, // "fload",
DLOAD.class, // "dload",
ALOAD.class, // "aload",
null, // "iload_0",
null, // "iload_1",
null, // "iload_2",
null, // "iload_3",
null, // "lload_0",
null, // "lload_1",
null, // "lload_2",
null, // "lload_3",
null, // "fload_0",
null, // "fload_1",
null, // "fload_2",
null, // "fload_3",
null, // "dload_0",
null, // "dload_1",
null, // "dload_2",
null, // "dload_3",
null, // "aload_0",
null, // "aload_1",
null, // "aload_2",
null, // "aload_3",
null, // "iaload",
null, // "laload",
null, // "faload",
null, // "daload",
null, // "aaload",
null, // "baload",
null, // "caload",
null, // "saload",
ISTORE.class, // "istore",
LSTORE.class, // "lstore",
FSTORE.class, // "fstore",
DSTORE.class, // "dstore",
ASTORE.class, // "astore",
null, // "istore_0",
null, // "istore_1",
null, // "istore_2",
null, // "istore_3",
null, // "lstore_0",
null, // "lstore_1",
null, // "lstore_2",
null, // "lstore_3",
null, // "fstore_0",
null, // "fstore_1",
null, // "fstore_2",
null, // "fstore_3",
null, // "dstore_0",
null, // "dstore_1",
null, // "dstore_2",
null, // "dstore_3",
null, // "astore_0",
null, // "astore_1",
null, // "astore_2",
null, // "astore_3",
null, // "iastore",
null, // "lastore",
null, // "fastore",
null, // "dastore",
null, // "aastore",
null, // "bastore",
null, // "castore",
null, // "sastore",
null, // "pop",
null, // "pop2",
null, // "dup",
null, // "dup_x1",
null, // "dup_x2",
null, // "dup2",
null, // "dup2_x1",
null, // "dup2_x2",
null, // "swap",
null, // "iadd",
null, // "ladd",
null, // "fadd",
null, // "dadd",
null, // "isub",
null, // "lsub",
null, // "fsub",
null, // "dsub",
null, // "imul",
null, // "lmul",
null, // "fmul",
null, // "dmul",
null, // "idiv",
null, // "ldiv",
null, // "fdiv",
null, // "ddiv",
null, // "irem",
null, // "lrem",
null, // "frem",
null, // "drem",
null, // "ineg",
null, // "lneg",
null, // "fneg",
null, // "dneg",
null, // "ishl",
null, // "lshl",
null, // "ishr",
null, // "lshr",
null, // "iushr",
null, // "lushr",
null, // "iand",
null, // "land",
null, // "ior",
null, // "lor",
null, // "ixor",
null, // "lxor",
IINC.class, // "iinc",
null, // "i2l",
null, // "i2f",
null, // "i2d",
null, // "l2i",
null, // "l2f",
null, // "l2d",
null, // "f2i",
null, // "f2l",
null, // "f2d",
null, // "d2i",
null, // "d2l",
null, // "d2f",
null, // "i2b",
null, // "i2c",
null, // "i2s",
null, // "lcmp",
null, // "fcmpl",
null, // "fcmpg",
null, // "dcmpl",
null, // "dcmpg",
null, // "ifeq",
null, // "ifne",
null, // "iflt",
null, // "ifge",
null, // "ifgt",
null, // "ifle",
null, // "if_icmpeq",
null, // "if_icmpne",
null, // "if_icmplt",
null, // "if_icmpge",
null, // "if_icmpgt",
null, // "if_icmple",
null, // "if_acmpeq",
null, // "if_acmpne",
GOTO.class, // "goto",
JSR.class, // "jsr",
RET.class, // "ret",
TABLESWITCH.class, // "tableswitch",
LOOKUPSWITCH.class, // "lookupswitch",
null, // "ireturn",
null, // "lreturn",
null, // "freturn",
null, // "dreturn",
null, // "areturn",
null, // "return",
GETSTATIC.class, // "getstatic",
PUTSTATIC.class, // "putstatic",
GETFIELD.class, // "getfield",
PUTFIELD.class, // "putfield",
INVOKEVIRTUAL.class, // "invokevirtual",
INVOKESPECIAL.class, // "invokespecial",
INVOKESTATIC.class, // "invokestatic",
INVOKEINTERFACE.class, // "invokeinterface",
INVOKEDYNAMIC.class, // "xxxunusedxxx" Java 6 and before, "invokedynamic" Java 7 and later
NEW.class, // "new",
NEWARRAY.class, // "newarray",
ANEWARRAY.class, // "anewarray",
null, // "arraylength",
null, // "athrow",
CHECKCAST.class, // "checkcast",
INSTANCEOF.class, // "instanceof",
null, // "monitorenter",
null, // "monitorexit",
null, // "wide",
MULTIANEWARRAY.class, // "multianewarray",
null, // "ifnull",
null, // "ifnonnull",
GOTO_W.class, // "goto_w",
JSR_W.class // "jsr_w"
};
}

@ -3,11 +3,7 @@ package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import java.io.DataOutputStream;
import java.io.IOException;
public class ExceptionHandler {
public int from = 0;
public int to = 0;
public int handler = 0;
@ -16,32 +12,12 @@ public class ExceptionHandler {
public int to_instr = 0;
public int handler_instr = 0;
public int class_index = 0;
public String exceptionClass = null;
public ExceptionHandler() {
}
public ExceptionHandler(int from_raw, int to_raw, int handler_raw, String exceptionClass) {
this.from = from_raw;
this.to = to_raw;
this.handler = handler_raw;
this.exceptionClass = exceptionClass;
}
public void writeToStream(DataOutputStream out) throws IOException {
out.writeShort(from);
out.writeShort(to);
out.writeShort(handler);
out.writeShort(class_index);
}
public String toString() {
String new_line_separator = DecompilerContext.getNewLineSeparator();
return "from: " + from + " to: " + to + " handler: " + handler + new_line_separator +
"from_instr: " + from_instr + " to_instr: " + to_instr + " handler_instr: " + handler_instr + new_line_separator +
"exceptionClass: " + exceptionClass + new_line_separator;
}
}
}

@ -1,19 +1,11 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.code.interpreter.Util;
import org.jetbrains.java.decompiler.struct.StructContext;
import java.util.Collections;
import java.util.List;
public class ExceptionTable {
public static final ExceptionTable EMPTY = new ExceptionTable(null) {
@Override
public List<ExceptionHandler> getHandlers() {
return Collections.emptyList();
}
};
public static final ExceptionTable EMPTY = new ExceptionTable(Collections.emptyList());
private final List<ExceptionHandler> handlers;
@ -21,27 +13,7 @@ public class ExceptionTable {
this.handlers = handlers;
}
public ExceptionHandler getHandlerByClass(StructContext context, int line, String valclass, boolean withany) {
ExceptionHandler res = null; // no handler found
for (ExceptionHandler handler : handlers) {
if (handler.from <= line && handler.to > line) {
String name = handler.exceptionClass;
if ((withany && name == null) || // any -> finally or synchronized handler
(name != null && Util.instanceOf(context, valclass, name))) {
res = handler;
break;
}
}
}
return res;
}
public List<ExceptionHandler> getHandlers() {
return handlers;
}
}
}

@ -1,22 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
import java.io.DataOutputStream;
import java.io.IOException;
/*
* opc_ifeq, opc_ifne, opc_iflt, opc_ifge, opc_ifgt, opc_ifle, opc_if_icmpeq, opc_if_icmpne, opc_if_icmplt,
* opc_if_icmpge, opc_if_icmpgt, opc_if_icmple, opc_if_acmpeq, opc_if_acmpne, opc_ifnull, opc_ifnonnull
*/
public class IfInstruction extends JumpInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opcode);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,112 +1,65 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
import java.io.DataOutputStream;
import java.io.IOException;
public class Instruction implements CodeConstants {
public static Instruction create(int opcode, boolean wide, int group, int bytecodeVersion, int[] operands) {
if (opcode >= opc_ifeq && opcode <= opc_if_acmpne ||
opcode == opc_ifnull || opcode == opc_ifnonnull ||
opcode == opc_jsr || opcode == opc_jsr_w ||
opcode == opc_goto || opcode == opc_goto_w) {
return new JumpInstruction(opcode, group, wide, bytecodeVersion, operands);
}
else if (opcode == opc_tableswitch || opcode == opc_lookupswitch) {
return new SwitchInstruction(opcode, group, wide, bytecodeVersion, operands);
}
else {
return new Instruction(opcode, group, wide, bytecodeVersion, operands);
}
}
// *****************************************************************************
// public fields
// *****************************************************************************
public int opcode;
public int group = CodeConstants.GROUP_GENERAL;
public boolean wide = false;
public int bytecode_version = BYTECODE_JAVA_LE_4;
// *****************************************************************************
// private fields
// *****************************************************************************
public static boolean equals(Instruction i1, Instruction i2) {
return i1 != null && i2 != null &&
(i1 == i2 ||
i1.opcode == i2.opcode &&
i1.wide == i2.wide &&
i1.operandsCount() == i2.operandsCount());
}
private int[] operands = null;
public final int opcode;
public final int group;
public final boolean wide;
public final int bytecodeVersion;
// *****************************************************************************
// public methods
// *****************************************************************************
protected final int[] operands;
public Instruction() {
public Instruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
this.opcode = opcode;
this.group = group;
this.wide = wide;
this.bytecodeVersion = bytecodeVersion;
this.operands = operands;
}
public int length() {
return 1;
}
public void initInstruction(InstructionSequence seq) { }
public int operandsCount() {
return (operands == null) ? 0 : operands.length;
return operands == null ? 0 : operands.length;
}
public int getOperand(int index) {
public int operand(int index) {
return operands[index];
}
public Instruction clone() {
return ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, operands == null ? null : operands.clone());
}
public String toString() {
String res = wide ? "@wide " : "";
res += "@" + ConstantsUtil.getName(opcode);
int len = operandsCount();
for (int i = 0; i < len; i++) {
int op = operands[i];
if (op < 0) {
res += " -" + Integer.toHexString(-op);
}
else {
res += " " + Integer.toHexString(op);
}
}
return res;
}
public boolean canFallthrough() {
public boolean canFallThrough() {
return opcode != opc_goto && opcode != opc_goto_w && opcode != opc_ret &&
!(opcode >= opc_ireturn && opcode <= opc_return) && opcode != opc_athrow
&& opcode != opc_jsr && opcode != opc_tableswitch && opcode != opc_lookupswitch;
}
public boolean equalsInstruction(Instruction instr) {
if (opcode != instr.opcode || wide != instr.wide
|| operandsCount() != instr.operandsCount()) {
return false;
}
if (operands != null) {
for (int i = 0; i < operands.length; i++) {
if (operands[i] != instr.getOperand(i)) {
return false;
}
}
}
return true;
!(opcode >= opc_ireturn && opcode <= opc_return) &&
opcode != opc_athrow &&
opcode != opc_jsr && opcode != opc_tableswitch && opcode != opc_lookupswitch;
}
// should be overwritten by subclasses
public void initInstruction(InstructionSequence seq) {
}
// should be overwritten by subclasses
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opcode);
}
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
public int[] getOperands() {
return operands;
}
public void setOperands(int[] operands) {
this.operands = operands;
@Override
@SuppressWarnings("MethodDoesntCallSuperMethod")
public Instruction clone() {
return create(opcode, wide, group, bytecodeVersion, operands == null ? null : operands.clone());
}
}
}

@ -1,19 +1,10 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.code.interpreter.Util;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.struct.StructContext;
import org.jetbrains.java.decompiler.util.TextUtil;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public abstract class InstructionSequence {
// *****************************************************************************
@ -73,10 +64,6 @@ public abstract class InstructionSequence {
}
}
public Instruction getCurrentInstr() {
return collinstr.get(pointer);
}
public Instruction getInstr(int index) {
return collinstr.get(index);
}
@ -85,16 +72,12 @@ public abstract class InstructionSequence {
return collinstr.getLast();
}
public int getCurrentOffset() {
return collinstr.getKey(pointer).intValue();
}
public int getOffset(int index) {
return collinstr.getKey(index).intValue();
public int getOffset(int index) {
return collinstr.getKey(index);
}
public int getPointerByAbsOffset(int offset) {
Integer absoffset = new Integer(offset);
Integer absoffset = offset;
if (collinstr.containsKey(absoffset)) {
return collinstr.getIndexByKey(absoffset);
}
@ -104,7 +87,7 @@ public int getOffset(int index) {
}
public int getPointerByRelOffset(int offset) {
Integer absoffset = new Integer(collinstr.getKey(pointer).intValue() + offset);
Integer absoffset = collinstr.getKey(pointer) + offset;
if (collinstr.containsKey(absoffset)) {
return collinstr.getIndexByKey(absoffset);
}
@ -113,13 +96,6 @@ public int getOffset(int index) {
}
}
public void setPointerByAbsOffset(int offset) {
Integer absoffset = new Integer(collinstr.getKey(pointer).intValue() + offset);
if (collinstr.containsKey(absoffset)) {
pointer = collinstr.getIndexByKey(absoffset);
}
}
public int length() {
return collinstr.size();
}
@ -153,55 +129,6 @@ public int getOffset(int index) {
return buf.toString();
}
public void writeCodeToStream(DataOutputStream out) throws IOException {
for (int i = 0; i < collinstr.size(); i++) {
collinstr.get(i).writeToStream(out, collinstr.getKey(i).intValue());
}
}
public void writeExceptionsToStream(DataOutputStream out) throws IOException {
List<ExceptionHandler> handlers = exceptionTable.getHandlers();
out.writeShort(handlers.size());
for (int i = 0; i < handlers.size(); i++) {
handlers.get(i).writeToStream(out);
}
}
public void sortHandlers(final StructContext context) {
Collections.sort(exceptionTable.getHandlers(), (handler0, handler1) -> {
if (handler0.to == handler1.to) {
if (handler0.exceptionClass == null) {
return 1;
}
else {
if (handler1.exceptionClass == null) {
return -1;
}
else if (handler0.exceptionClass.equals(handler1.exceptionClass)) {
return (handler0.from > handler1.from) ? -1 : 1; // invalid code
}
else {
if (Util.instanceOf(context, handler0.exceptionClass, handler1.exceptionClass)) {
return -1;
}
else {
return 1;
}
}
}
}
else {
return (handler0.to > handler1.to) ? 1 : -1;
}
});
}
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
@ -217,8 +144,4 @@ public int getOffset(int index) {
public ExceptionTable getExceptionTable() {
return exceptionTable;
}
public void setExceptionTable(ExceptionTable exceptionTable) {
this.exceptionTable = exceptionTable;
}
}
}

@ -1,28 +1,22 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
/*
* opc_ifeq, opc_ifne, opc_iflt, opc_ifge, opc_ifgt, opc_ifle, opc_if_icmpeq, opc_if_icmpne, opc_if_icmplt,
* opc_if_icmpge, opc_if_icmpgt, opc_if_icmple, opc_if_acmpeq, opc_if_acmpne, opc_ifnull, opc_ifnonnull
* opc_goto, opc_jsr, opc_goto_w, opc_jsr_w
*/
public class JumpInstruction extends Instruction {
public int destination;
public JumpInstruction() {
public JumpInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
super(opcode, group, wide, bytecodeVersion, operands);
}
@Override
public void initInstruction(InstructionSequence seq) {
destination = seq.getPointerByRelOffset(this.getOperand(0));
destination = seq.getPointerByRelOffset(this.operand(0));
}
@Override
public JumpInstruction clone() {
JumpInstruction newinstr = (JumpInstruction)super.clone();
newinstr.destination = destination;
return newinstr;
JumpInstruction copy = (JumpInstruction)super.clone();
copy.destination = destination;
return copy;
}
}
}

@ -1,83 +1,61 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code;
/*
* opc_tableswitch, lookupswitch
*/
public class SwitchInstruction extends Instruction {
private int[] destinations;
private int[] values;
private int defaultDestination;
private int defaultdest;
public SwitchInstruction() {
public SwitchInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
super(opcode, group, wide, bytecodeVersion, operands);
}
@Override
public void initInstruction(InstructionSequence seq) {
defaultDestination = seq.getPointerByRelOffset(operands[0]);
int pref = (opcode == CodeConstants.opc_tableswitch ? 3 : 2);
int len = this.getOperands().length - pref;
defaultdest = seq.getPointerByRelOffset(this.getOperand(0));
int prefix = opcode == CodeConstants.opc_tableswitch ? 3 : 2;
int len = operands.length - prefix;
int low = 0;
if (opcode == CodeConstants.opc_lookupswitch) {
len /= 2;
}
else {
low = this.getOperand(1);
low = operands[1];
}
destinations = new int[len];
values = new int[len];
for (int i = 0, k = 0; i < len; i++, k++) {
if (opcode == CodeConstants.opc_lookupswitch) {
values[i] = this.getOperand(pref + k);
values[i] = operands[prefix + k];
k++;
}
else {
values[i] = low + k;
}
destinations[i] = seq.getPointerByRelOffset(this.getOperand(pref + k));
destinations[i] = seq.getPointerByRelOffset(operands[prefix + k]);
}
}
public SwitchInstruction clone() {
SwitchInstruction newinstr = (SwitchInstruction)super.clone();
newinstr.defaultdest = defaultdest;
newinstr.destinations = destinations.clone();
newinstr.values = values.clone();
return newinstr;
}
public int[] getDestinations() {
return destinations;
}
public void setDestinations(int[] destinations) {
this.destinations = destinations;
}
public int getDefaultdest() {
return defaultdest;
}
public void setDefaultdest(int defaultdest) {
this.defaultdest = defaultdest;
}
public int[] getValues() {
return values;
}
public void setValues(int[] values) {
this.values = values;
public int getDefaultDestination() {
return defaultDestination;
}
@Override
public SwitchInstruction clone() {
SwitchInstruction copy = (SwitchInstruction)super.clone();
copy.defaultDestination = defaultDestination;
copy.destinations = destinations.clone();
copy.values = values.clone();
return copy;
}
}
}

@ -16,8 +16,7 @@ public class BasicBlock implements IGraphNode {
// public fields
// *****************************************************************************
public int id = 0;
public int id;
public int mark = 0;
// *****************************************************************************
@ -26,15 +25,11 @@ public class BasicBlock implements IGraphNode {
private InstructionSequence seq = new SimpleInstructionSequence();
private List<BasicBlock> preds = new ArrayList<>();
private List<BasicBlock> succs = new ArrayList<>();
private final List<BasicBlock> preds = new ArrayList<>();
private final List<BasicBlock> succs = new ArrayList<>();
private final List<Integer> instrOldOffsets = new ArrayList<>();
private List<BasicBlock> predExceptions = new ArrayList<>();
private List<BasicBlock> succExceptions = new ArrayList<>();
private final List<BasicBlock> predExceptions = new ArrayList<>();
private final List<BasicBlock> succExceptions = new ArrayList<>();
public BasicBlock(int id) {
this.id = id;
@ -44,7 +39,9 @@ public class BasicBlock implements IGraphNode {
// public methods
// *****************************************************************************
public Object clone() {
@Override
@SuppressWarnings("MethodDoesntCallSuperMethod")
public BasicBlock clone() {
BasicBlock block = new BasicBlock(id);
block.setSeq(seq.clone());
@ -53,14 +50,6 @@ public class BasicBlock implements IGraphNode {
return block;
}
public void free() {
preds.clear();
succs.clear();
instrOldOffsets.clear();
succExceptions.clear();
seq = new SimpleInstructionSequence();
}
public Instruction getInstruction(int index) {
return seq.getInstr(index);
}
@ -91,7 +80,7 @@ public class BasicBlock implements IGraphNode {
}
public void removePredecessor(BasicBlock block) {
while (preds.remove(block)) ;
while (preds.remove(block)) /**/;
}
public void addSuccessor(BasicBlock block) {
@ -100,7 +89,7 @@ public class BasicBlock implements IGraphNode {
}
public void removeSuccessor(BasicBlock block) {
while (succs.remove(block)) ;
while (succs.remove(block)) /**/;
block.removePredecessor(this);
}
@ -128,7 +117,7 @@ public class BasicBlock implements IGraphNode {
}
public void removePredecessorException(BasicBlock block) {
while (predExceptions.remove(block)) ;
while (predExceptions.remove(block)) /**/;
}
public void addSuccessorException(BasicBlock block) {
@ -139,7 +128,7 @@ public class BasicBlock implements IGraphNode {
}
public void removeSuccessorException(BasicBlock block) {
while (succExceptions.remove(block)) ;
while (succExceptions.remove(block)) /**/;
block.removePredecessorException(this);
}
@ -154,27 +143,6 @@ public class BasicBlock implements IGraphNode {
return id + ":" + new_line_separator + seq.toString(indent);
}
public String toStringOldIndices() {
String new_line_separator = DecompilerContext.getNewLineSeparator();
StringBuilder buf = new StringBuilder();
for (int i = 0; i < seq.length(); i++) {
if (i < instrOldOffsets.size()) {
buf.append(instrOldOffsets.get(i));
}
else {
buf.append("-1");
}
buf.append(": ");
buf.append(seq.getInstr(i).toString());
buf.append(new_line_separator);
}
return buf.toString();
}
public boolean isSuccessor(BasicBlock block) {
for (BasicBlock succ : succs) {
if (succ.id == block.id) {
@ -184,15 +152,6 @@ public class BasicBlock implements IGraphNode {
return false;
}
public boolean isPredecessor(BasicBlock block) {
for (int i = 0; i < preds.size(); i++) {
if (preds.get(i).id == block.id) {
return true;
}
}
return false;
}
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
@ -211,10 +170,6 @@ public class BasicBlock implements IGraphNode {
return preds;
}
public void setPreds(List<BasicBlock> preds) {
this.preds = preds;
}
public InstructionSequence getSeq() {
return seq;
}
@ -227,25 +182,11 @@ public class BasicBlock implements IGraphNode {
return succs;
}
public void setSuccs(List<BasicBlock> succs) {
this.succs = succs;
}
public List<BasicBlock> getSuccExceptions() {
return succExceptions;
}
public void setSuccExceptions(List<BasicBlock> succExceptions) {
this.succExceptions = succExceptions;
}
public List<BasicBlock> getPredExceptions() {
return predExceptions;
}
public void setPredExceptions(List<BasicBlock> predExceptions) {
this.predExceptions = predExceptions;
}
}
}

@ -33,7 +33,7 @@ public class ControlFlowGraph implements CodeConstants {
private Map<BasicBlock, BasicBlock> subroutines;
private Set<BasicBlock> finallyExits = new HashSet<>();
private final Set<BasicBlock> finallyExits = new HashSet<>();
// *****************************************************************************
// constructors
@ -48,19 +48,6 @@ public class ControlFlowGraph implements CodeConstants {
// public methods
// *****************************************************************************
public void free() {
for (BasicBlock block : blocks) {
block.free();
}
blocks.clear();
first = null;
last = null;
exceptions.clear();
finallyExits.clear();
}
public void removeMarkers() {
for (BasicBlock block : blocks) {
block.mark = 0;
@ -80,12 +67,11 @@ public class ControlFlowGraph implements CodeConstants {
buf.append("----- Edges -----").append(new_line_separator);
List<BasicBlock> suc = block.getSuccs();
for (int j = 0; j < suc.size(); j++) {
buf.append(">>>>>>>>(regular) Block ").append(suc.get(j).id).append(new_line_separator);
for (BasicBlock aSuc : suc) {
buf.append(">>>>>>>>(regular) Block ").append(aSuc.id).append(new_line_separator);
}
suc = block.getSuccExceptions();
for (int j = 0; j < suc.size(); j++) {
BasicBlock handler = suc.get(j);
for (BasicBlock handler : suc) {
ExceptionRangeCFG range = getExceptionRange(handler, block);
if (range == null) {
@ -156,13 +142,7 @@ public class ControlFlowGraph implements CodeConstants {
}
}
Iterator<Entry<BasicBlock, BasicBlock>> it = subroutines.entrySet().iterator();
while (it.hasNext()) {
Entry<BasicBlock, BasicBlock> ent = it.next();
if (ent.getKey() == block || ent.getValue() == block) {
it.remove();
}
}
subroutines.entrySet().removeIf(ent -> ent.getKey() == block || ent.getValue() == block);
}
public ExceptionRangeCFG getExceptionRange(BasicBlock handler, BasicBlock block) {
@ -261,7 +241,7 @@ public class ControlFlowGraph implements CodeConstants {
for (int j = dests.length - 1; j >= 0; j--) {
inststates[dests[j]] = 1;
}
inststates[swinstr.getDefaultdest()] = 1;
inststates[swinstr.getDefaultDestination()] = 1;
if (i + 1 < len) {
inststates[i + 1] = 1;
}
@ -322,7 +302,7 @@ public class ControlFlowGraph implements CodeConstants {
BasicBlock block = lstbb.get(i);
Instruction instr = block.getLastInstruction();
boolean fallthrough = instr.canFallthrough();
boolean fallthrough = instr.canFallThrough();
BasicBlock bTemp;
switch (instr.group) {
@ -336,10 +316,10 @@ public class ControlFlowGraph implements CodeConstants {
SwitchInstruction sinstr = (SwitchInstruction)instr;
int[] dests = sinstr.getDestinations();
bTemp = mapInstrBlocks.get(((SwitchInstruction)instr).getDefaultdest());
bTemp = mapInstrBlocks.get(((SwitchInstruction)instr).getDefaultDestination());
block.addSuccessor(bTemp);
for (int j = 0; j < dests.length; j++) {
bTemp = mapInstrBlocks.get(dests[j]);
for (int dest1 : dests) {
bTemp = mapInstrBlocks.get(dest1);
block.addSuccessor(bTemp);
}
}
@ -617,9 +597,8 @@ public class ControlFlowGraph implements CodeConstants {
node.replaceSuccessor(child, mapNewNodes.get(childid));
}
else if (common_blocks.contains(child)) {
// make a copy of the current block
BasicBlock copy = (BasicBlock)child.clone();
BasicBlock copy = child.clone();
copy.id = ++last_id;
// copy all successors
if (copy.getLastInstruction().opcode == CodeConstants.opc_ret &&
@ -816,10 +795,6 @@ public class ControlFlowGraph implements CodeConstants {
return blocks;
}
public void setBlocks(VBStyleCollection<BasicBlock, Integer> blocks) {
this.blocks = blocks;
}
public BasicBlock getFirst() {
return first;
}
@ -828,39 +803,15 @@ public class ControlFlowGraph implements CodeConstants {
this.first = first;
}
public List<BasicBlock> getEndBlocks() {
return last.getPreds();
}
public List<ExceptionRangeCFG> getExceptions() {
return exceptions;
}
public void setExceptions(List<ExceptionRangeCFG> exceptions) {
this.exceptions = exceptions;
}
public BasicBlock getLast() {
return last;
}
public void setLast(BasicBlock last) {
this.last = last;
}
public Map<BasicBlock, BasicBlock> getSubroutines() {
return subroutines;
}
public void setSubroutines(Map<BasicBlock, BasicBlock> subroutines) {
this.subroutines = subroutines;
}
public Set<BasicBlock> getFinallyExits() {
return finallyExits;
}
public void setFinallyExits(HashSet<BasicBlock> finallyExits) {
this.finallyExits = finallyExits;
}
}
}

@ -1,18 +1,13 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.cfg;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ExceptionRangeCFG {
private List<BasicBlock> protectedRange = new ArrayList<>(); // FIXME: replace with set
private final List<BasicBlock> protectedRange; // FIXME: replace with set
private BasicBlock handler;
private List<String> exceptionTypes;
public ExceptionRangeCFG(List<BasicBlock> protectedRange, BasicBlock handler, List<String> exceptionType) {
@ -28,28 +23,6 @@ public class ExceptionRangeCFG {
return protectedRange.contains(handler);
}
public String toString() {
String new_line_separator = DecompilerContext.getNewLineSeparator();
StringBuilder buf = new StringBuilder();
buf.append("exceptionType:");
for (String exception_type : exceptionTypes) {
buf.append(" ").append(exception_type);
}
buf.append(new_line_separator);
buf.append("handler: ").append(handler.id).append(new_line_separator);
buf.append("range: ");
for (int i = 0; i < protectedRange.size(); i++) {
buf.append(protectedRange.get(i).id).append(" ");
}
buf.append(new_line_separator);
return buf.toString();
}
public BasicBlock getHandler() {
return handler;
}
@ -62,16 +35,11 @@ public class ExceptionRangeCFG {
return protectedRange;
}
public void setProtectedRange(List<BasicBlock> protectedRange) {
this.protectedRange = protectedRange;
}
public List<String> getExceptionTypes() {
return this.exceptionTypes;
}
public void addExceptionType(String exceptionType) {
if (this.exceptionTypes == null) {
return;
}
@ -85,16 +53,6 @@ public class ExceptionRangeCFG {
}
public String getUniqueExceptionsString() {
if (exceptionTypes == null) {
return null;
}
return exceptionTypes.stream().distinct().collect(Collectors.joining(":"));
return exceptionTypes != null ? exceptionTypes.stream().distinct().collect(Collectors.joining(":")) : null;
}
// public void setExceptionType(String exceptionType) {
// this.exceptionType = exceptionType;
// }
}
}

@ -325,7 +325,6 @@ public class InstructionImpact {
public static void stepTypes(DataPoint data, Instruction instr, ConstantPool pool) {
ListStack<VarType> stack = data.getStack();
int[][] arr = stack_impact[instr.opcode];
@ -337,8 +336,7 @@ public class InstructionImpact {
if (read != null) {
int depth = 0;
for (int i = 0; i < read.length; i++) {
int type = read[i];
for (int type : read) {
depth++;
if (type == CodeConstants.TYPE_LONG ||
type == CodeConstants.TYPE_DOUBLE) {
@ -350,8 +348,7 @@ public class InstructionImpact {
}
if (write != null) {
for (int i = 0; i < write.length; i++) {
int type = write[i];
for (int type : write) {
stack.push(new VarType(type));
if (type == CodeConstants.TYPE_LONG ||
type == CodeConstants.TYPE_DOUBLE) {
@ -381,7 +378,7 @@ public class InstructionImpact {
case CodeConstants.opc_ldc:
case CodeConstants.opc_ldc_w:
case CodeConstants.opc_ldc2_w:
PooledConstant constant = pool.getConstant(instr.getOperand(0));
PooledConstant constant = pool.getConstant(instr.operand(0));
switch (constant.type) {
case CodeConstants.CONSTANT_Integer:
stack.push(new VarType(CodeConstants.TYPE_INT));
@ -409,7 +406,7 @@ public class InstructionImpact {
}
break;
case CodeConstants.opc_aload:
var1 = data.getVariable(instr.getOperand(0));
var1 = data.getVariable(instr.operand(0));
if (var1 != null) {
stack.push(var1);
}
@ -422,7 +419,7 @@ public class InstructionImpact {
stack.push(new VarType(var1.type, var1.arrayDim - 1, var1.value));
break;
case CodeConstants.opc_astore:
data.setVariable(instr.getOperand(0), stack.pop());
data.setVariable(instr.operand(0), stack.pop());
break;
case CodeConstants.opc_dup:
case CodeConstants.opc_dup_x1:
@ -444,7 +441,7 @@ public class InstructionImpact {
case CodeConstants.opc_getfield:
stack.pop();
case CodeConstants.opc_getstatic:
ck = pool.getLinkConstant(instr.getOperand(0));
ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
stack.push(var1);
if (var1.stackSize == 2) {
@ -454,7 +451,7 @@ public class InstructionImpact {
case CodeConstants.opc_putfield:
stack.pop();
case CodeConstants.opc_putstatic:
ck = pool.getLinkConstant(instr.getOperand(0));
ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
stack.pop(var1.stackSize);
break;
@ -464,8 +461,8 @@ public class InstructionImpact {
stack.pop();
case CodeConstants.opc_invokestatic:
case CodeConstants.opc_invokedynamic:
if (instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
ck = pool.getLinkConstant(instr.getOperand(0));
if (instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecodeVersion >= CodeConstants.BYTECODE_JAVA_7) {
ck = pool.getLinkConstant(instr.operand(0));
MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor);
for (int i = 0; i < md.params.length; i++) {
stack.pop(md.params[i].stackSize);
@ -479,12 +476,12 @@ public class InstructionImpact {
}
break;
case CodeConstants.opc_new:
cn = pool.getPrimitiveConstant(instr.getOperand(0));
cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_newarray:
stack.pop();
stack.push(new VarType(arr_type[instr.getOperand(0) - 4], 1).resizeArrayDim(1));
stack.push(new VarType(arr_type[instr.operand(0) - 4], 1).resizeArrayDim(1));
break;
case CodeConstants.opc_athrow:
var1 = stack.pop();
@ -494,14 +491,14 @@ public class InstructionImpact {
case CodeConstants.opc_checkcast:
case CodeConstants.opc_instanceof:
stack.pop();
cn = pool.getPrimitiveConstant(instr.getOperand(0));
cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_anewarray:
case CodeConstants.opc_multianewarray:
int dimensions = (instr.opcode == CodeConstants.opc_anewarray) ? 1 : instr.getOperand(1);
int dimensions = (instr.opcode == CodeConstants.opc_anewarray) ? 1 : instr.operand(1);
stack.pop(dimensions);
cn = pool.getPrimitiveConstant(instr.getOperand(0));
cn = pool.getPrimitiveConstant(instr.operand(0));
if (cn.isArray) {
var1 = new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString());
var1 = var1.resizeArrayDim(var1.arrayDim + dimensions);

@ -1,272 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.interpreter;
import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructContext;
// FIXME: move to StructContext
public class Util {
private static final String[][] runtime_exceptions = {
null, // public final static int opc_nop = 0;
null, // public final static int opc_aconst_null = 1;
null, // public final static int opc_iconst_m1 = 2;
null, // public final static int opc_iconst_0 = 3;
null, // public final static int opc_iconst_1 = 4;
null, // public final static int opc_iconst_2 = 5;
null, // public final static int opc_iconst_3 = 6;
null, // public final static int opc_iconst_4 = 7;
null, // public final static int opc_iconst_5 = 8;
null, // public final static int opc_lconst_0 = 9;
null, // public final static int opc_lconst_1 = 10;
null, // public final static int opc_fconst_0 = 11;
null, // public final static int opc_fconst_1 = 12;
null, // public final static int opc_fconst_2 = 13;
null, // public final static int opc_dconst_0 = 14;
null, // public final static int opc_dconst_1 = 15;
null, // public final static int opc_bipush = 16;
null, // public final static int opc_sipush = 17;
null, // public final static int opc_ldc = 18;
null, // public final static int opc_ldc_w = 19;
null, // public final static int opc_ldc2_w = 20;
null, // public final static int opc_iload = 21;
null, // public final static int opc_lload = 22;
null, // public final static int opc_fload = 23;
null, // public final static int opc_dload = 24;
null, // public final static int opc_aload = 25;
null, // public final static int opc_iload_0 = 26;
null, // public final static int opc_iload_1 = 27;
null, // public final static int opc_iload_2 = 28;
null, // public final static int opc_iload_3 = 29;
null, // public final static int opc_lload_0 = 30;
null, // public final static int opc_lload_1 = 31;
null, // public final static int opc_lload_2 = 32;
null, // public final static int opc_lload_3 = 33;
null, // public final static int opc_fload_0 = 34;
null, // public final static int opc_fload_1 = 35;
null, // public final static int opc_fload_2 = 36;
null, // public final static int opc_fload_3 = 37;
null, // public final static int opc_dload_0 = 38;
null, // public final static int opc_dload_1 = 39;
null, // public final static int opc_dload_2 = 40;
null, // public final static int opc_dload_3 = 41;
null, // public final static int opc_aload_0 = 42;
null, // public final static int opc_aload_1 = 43;
null, // public final static int opc_aload_2 = 44;
null, // public final static int opc_aload_3 = 45;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_iaload = 46;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_laload = 47;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_faload = 48;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_daload = 49;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_aaload = 50;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_baload = 51;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_caload = 52;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_saload = 53;
null, // public final static int opc_istore = 54;
null, // public final static int opc_lstore = 55;
null, // public final static int opc_fstore = 56;
null, // public final static int opc_dstore = 57;
null, // public final static int opc_astore = 58;
null, // public final static int opc_istore_0 = 59;
null, // public final static int opc_istore_1 = 60;
null, // public final static int opc_istore_2 = 61;
null, // public final static int opc_istore_3 = 62;
null, // public final static int opc_lstore_0 = 63;
null, // public final static int opc_lstore_1 = 64;
null, // public final static int opc_lstore_2 = 65;
null, // public final static int opc_lstore_3 = 66;
null, // public final static int opc_fstore_0 = 67;
null, // public final static int opc_fstore_1 = 68;
null, // public final static int opc_fstore_2 = 69;
null, // public final static int opc_fstore_3 = 70;
null, // public final static int opc_dstore_0 = 71;
null, // public final static int opc_dstore_1 = 72;
null, // public final static int opc_dstore_2 = 73;
null, // public final static int opc_dstore_3 = 74;
null, // public final static int opc_astore_0 = 75;
null, // public final static int opc_astore_1 = 76;
null, // public final static int opc_astore_2 = 77;
null, // public final static int opc_astore_3 = 78;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_iastore = 79;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_lastore = 80;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_fastore = 81;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_dastore = 82;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException", "java/lang/ArrayStoreException"},
// public final static int opc_aastore = 83;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_bastore = 84;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_castore = 85;
{"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
// public final static int opc_sastore = 86;
null, // public final static int opc_pop = 87;
null, // public final static int opc_pop2 = 88;
null, // public final static int opc_dup = 89;
null, // public final static int opc_dup_x1 = 90;
null, // public final static int opc_dup_x2 = 91;
null, // public final static int opc_dup2 = 92;
null, // public final static int opc_dup2_x1 = 93;
null, // public final static int opc_dup2_x2 = 94;
null, // public final static int opc_swap = 95;
null, // public final static int opc_iadd = 96;
null, // public final static int opc_ladd = 97;
null, // public final static int opc_fadd = 98;
null, // public final static int opc_dadd = 99;
null, // public final static int opc_isub = 100;
null, // public final static int opc_lsub = 101;
null, // public final static int opc_fsub = 102;
null, // public final static int opc_dsub = 103;
null, // public final static int opc_imul = 104;
null, // public final static int opc_lmul = 105;
null, // public final static int opc_fmul = 106;
null, // public final static int opc_dmul = 107;
{"java/lang/ArithmeticException"}, // public final static int opc_idiv = 108;
{"java/lang/ArithmeticException"}, // public final static int opc_ldiv = 109;
null, // public final static int opc_fdiv = 110;
null, // public final static int opc_ddiv = 111;
{"java/lang/ArithmeticException"}, // public final static int opc_irem = 112;
{"java/lang/ArithmeticException"}, // public final static int opc_lrem = 113;
null, // public final static int opc_frem = 114;
null, // public final static int opc_drem = 115;
null, // public final static int opc_ineg = 116;
null, // public final static int opc_lneg = 117;
null, // public final static int opc_fneg = 118;
null, // public final static int opc_dneg = 119;
null, // public final static int opc_ishl = 120;
null, // public final static int opc_lshl = 121;
null, // public final static int opc_ishr = 122;
null, // public final static int opc_lshr = 123;
null, // public final static int opc_iushr = 124;
null, // public final static int opc_lushr = 125;
null, // public final static int opc_iand = 126;
null, // public final static int opc_land = 127;
null, // public final static int opc_ior = 128;
null, // public final static int opc_lor = 129;
null, // public final static int opc_ixor = 130;
null, // public final static int opc_lxor = 131;
null, // public final static int opc_iinc = 132;
null, // public final static int opc_i2l = 133;
null, // public final static int opc_i2f = 134;
null, // public final static int opc_i2d = 135;
null, // public final static int opc_l2i = 136;
null, // public final static int opc_l2f = 137;
null, // public final static int opc_l2d = 138;
null, // public final static int opc_f2i = 139;
null, // public final static int opc_f2l = 140;
null, // public final static int opc_f2d = 141;
null, // public final static int opc_d2i = 142;
null, // public final static int opc_d2l = 143;
null, // public final static int opc_d2f = 144;
null, // public final static int opc_i2b = 145;
null, // public final static int opc_i2c = 146;
null, // public final static int opc_i2s = 147;
null, // public final static int opc_lcmp = 148;
null, // public final static int opc_fcmpl = 149;
null, // public final static int opc_fcmpg = 150;
null, // public final static int opc_dcmpl = 151;
null, // public final static int opc_dcmpg = 152;
null, // public final static int opc_ifeq = 153;
null, // public final static int opc_ifne = 154;
null, // public final static int opc_iflt = 155;
null, // public final static int opc_ifge = 156;
null, // public final static int opc_ifgt = 157;
null, // public final static int opc_ifle = 158;
null, // public final static int opc_if_icmpeq = 159;
null, // public final static int opc_if_icmpne = 160;
null, // public final static int opc_if_icmplt = 161;
null, // public final static int opc_if_icmpge = 162;
null, // public final static int opc_if_icmpgt = 163;
null, // public final static int opc_if_icmple = 164;
null, // public final static int opc_if_acmpeq = 165;
null, // public final static int opc_if_acmpne = 166;
null, // public final static int opc_goto = 167;
null, // public final static int opc_jsr = 168;
null, // public final static int opc_ret = 169;
null, // public final static int opc_tableswitch = 170;
null, // public final static int opc_lookupswitch = 171;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_ireturn = 172;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_lreturn = 173;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_freturn = 174;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_dreturn = 175;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_areturn = 176;
{"java/lang/IllegalMonitorStateException"}, // public final static int opc_return = 177;
null, // public final static int opc_getstatic = 178;
null, // public final static int opc_putstatic = 179;
{"java/lang/NullPointerException"}, // public final static int opc_getfield = 180;
{"java/lang/NullPointerException"}, // public final static int opc_putfield = 181;
{"java/lang/NullPointerException", "java/lang/AbstractMethodError", "java/lang/UnsatisfiedLinkError"},
// public final static int opc_invokevirtual = 182;
{"java/lang/NullPointerException", "java/lang/UnsatisfiedLinkError"},
// public final static int opc_invokespecial = 183;
{"java/lang/UnsatisfiedLinkError"}, // public final static int opc_invokestatic = 184;
{"java/lang/NullPointerException", "java/lang/IncompatibleClassChangeError", "java/lang/IllegalAccessError",
"java/lang/java/lang/AbstractMethodError", "java/lang/UnsatisfiedLinkError"},
// public final static int opc_invokeinterface = 185;
null, // public final static int opc_xxxunusedxxx = 186;
null, // public final static int opc_new = 187;
{"java/lang/NegativeArraySizeException"}, // public final static int opc_newarray = 188;
{"java/lang/NegativeArraySizeException"}, // public final static int opc_anewarray = 189;
{"java/lang/NullPointerException"}, // public final static int opc_arraylength = 190;
{"java/lang/NullPointerException", "java/lang/IllegalMonitorStateException"},
// public final static int opc_athrow = 191;
{"java/lang/ClassCastException"}, // public final static int opc_checkcast = 192;
null, // public final static int opc_instanceof = 193;
{"java/lang/NullPointerException"}, // public final static int opc_monitorenter = 194;
{"java/lang/NullPointerException", "java/lang/IllegalMonitorStateException"},
// public final static int opc_monitorexit = 195;
null, // public final static int opc_wide = 196;
{"java/lang/NegativeArraySizeException"}, // public final static int opc_multianewarray = 197;
null, // public final static int opc_ifnull = 198;
null, // public final static int opc_ifnonnull = 199;
null, // public final static int opc_goto_w = 200;
null, // public final static int opc_jsr_w = 201;
};
public static boolean instanceOf(StructContext context, String valclass, String refclass) {
if (valclass.equals(refclass)) {
return true;
}
StructClass cl = context.getClass(valclass);
if (cl == null) {
return false;
}
if (cl.superClass != null && instanceOf(context, cl.superClass.getString(), refclass)) {
return true;
}
int[] interfaces = cl.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
String intfc = cl.getPool().getPrimitiveConstant(interfaces[i]).getString();
if (instanceOf(context, intfc, refclass)) {
return true;
}
}
return false;
}
public static String[] getRuntimeExceptions(Instruction instr) {
return runtime_exceptions[instr.opcode];
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class ALOAD extends Instruction {
private static final int[] opcodes = new int[]{opc_aload_0, opc_aload_1, opc_aload_2, opc_aload_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_aload);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class ANEWARRAY extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_anewarray);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class ASTORE extends Instruction {
private static final int[] opcodes = new int[]{opc_astore_0, opc_astore_1, opc_astore_2, opc_astore_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_astore);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,34 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class BIPUSH extends Instruction {
private static final int[] opcodes =
new int[]{opc_iconst_m1, opc_iconst_0, opc_iconst_1, opc_iconst_2, opc_iconst_3, opc_iconst_4, opc_iconst_5};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int value = getOperand(0);
if (value < -1 || value > 5) {
out.writeByte(opc_bipush);
out.writeByte(value);
}
else {
out.writeByte(opcodes[value + 1]);
}
}
public int length() {
int value = getOperand(0);
if (value < -1 || value > 5) {
return 2;
}
else {
return 1;
}
}
}

@ -1,20 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class CHECKCAST extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_checkcast);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class DLOAD extends Instruction {
private static final int[] opcodes = new int[]{opc_dload_0, opc_dload_1, opc_dload_2, opc_dload_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_dload);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class DSTORE extends Instruction {
private static final int[] opcodes = new int[]{opc_dstore_0, opc_dstore_1, opc_dstore_2, opc_dstore_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_dstore);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class FLOAD extends Instruction {
private static final int[] opcodes = new int[]{opc_fload_0, opc_fload_1, opc_fload_2, opc_fload_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_fload);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,46 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class FSTORE extends Instruction {
private static final int[] opcodes = new int[]{opc_fstore_0, opc_fstore_1, opc_fstore_2, opc_fstore_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_fstore);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
if (wide) {
return 4;
}
else {
return 2;
}
}
else {
return 1;
}
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class GETFIELD extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_getfield);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class GETSTATIC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_getstatic);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,32 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.JumpInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class GOTO extends JumpInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int operand = getOperand(0);
if (operand < -32768 || operand > 32767) {
out.writeByte(opc_goto_w);
out.writeInt(operand);
}
else {
out.writeByte(opc_goto);
out.writeShort(operand);
}
}
public int length() {
int operand = getOperand(0);
if (operand < -32768 || operand > 32767) {
return 5;
}
else {
return 3;
}
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.JumpInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class GOTO_W extends JumpInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_goto_w);
out.writeInt(getOperand(0));
}
public int length() {
return 5;
}
}

@ -1,29 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class IINC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_iinc);
if (wide) {
out.writeShort(getOperand(0));
out.writeShort(getOperand(1));
}
else {
out.writeByte(getOperand(0));
out.writeByte(getOperand(1));
}
}
public int length() {
return wide ? 6 : 3;
}
}

@ -1,41 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class ILOAD extends Instruction {
private static final int[] opcodes = new int[]{opc_iload_0, opc_iload_1, opc_iload_2, opc_iload_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_iload);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
return wide ? 4 : 2;
}
else {
return 1;
}
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INSTANCEOF extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_instanceof);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,21 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INVOKEDYNAMIC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokedynamic);
out.writeShort(getOperand(0));
out.writeByte(0);
out.writeByte(0);
}
public int length() {
return 5;
}
}

@ -1,21 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INVOKEINTERFACE extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokeinterface);
out.writeShort(getOperand(0));
out.writeByte(getOperand(1));
out.writeByte(0);
}
public int length() {
return 5;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INVOKESPECIAL extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokespecial);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INVOKESTATIC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokestatic);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class INVOKEVIRTUAL extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_invokevirtual);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,41 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class ISTORE extends Instruction {
private static final int[] opcodes = new int[]{opc_istore_0, opc_istore_1, opc_istore_2, opc_istore_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_istore);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
return wide ? 4 : 2;
}
else {
return 1;
}
}
}

@ -1,32 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.JumpInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class JSR extends JumpInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int operand = getOperand(0);
if (operand < -32768 || operand > 32767) {
out.writeByte(opc_jsr_w);
out.writeInt(operand);
}
else {
out.writeByte(opc_jsr);
out.writeShort(operand);
}
}
public int length() {
int operand = getOperand(0);
if (operand < -32768 || operand > 32767) {
return 5;
}
else {
return 3;
}
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.JumpInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class JSR_W extends JumpInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_jsr_w);
out.writeInt(getOperand(0));
}
public int length() {
return 5;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LDC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_ldc);
out.writeByte(getOperand(0));
}
public int length() {
return 2;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LDC2_W extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_ldc2_w);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LDC_W extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_ldc_w);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,41 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LLOAD extends Instruction {
private static final int[] opcodes = new int[]{opc_lload_0, opc_lload_1, opc_lload_2, opc_lload_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_lload);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
return wide ? 4 : 2;
}
else {
return 1;
}
}
}

@ -1,28 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.SwitchInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LOOKUPSWITCH extends SwitchInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_lookupswitch);
int padding = 3 - (offset % 4);
for (int i = 0; i < padding; i++) {
out.writeByte(0);
}
for (int i = 0; i < operandsCount(); i++) {
out.writeInt(getOperand(i));
}
}
public int length() {
return 1 + operandsCount() * 4;
}
}

@ -1,41 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class LSTORE extends Instruction {
private static final int[] opcodes = new int[]{opc_lstore_0, opc_lstore_1, opc_lstore_2, opc_lstore_3};
public void writeToStream(DataOutputStream out, int offset) throws IOException {
int index = getOperand(0);
if (index > 3) {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_lstore);
if (wide) {
out.writeShort(index);
}
else {
out.writeByte(index);
}
}
else {
out.writeByte(opcodes[index]);
}
}
public int length() {
int index = getOperand(0);
if (index > 3) {
return wide ? 4 : 2;
}
else {
return 1;
}
}
}

@ -1,20 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class MULTIANEWARRAY extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_multianewarray);
out.writeShort(getOperand(0));
out.writeByte(getOperand(1));
}
public int length() {
return 4;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class NEW extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_new);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class NEWARRAY extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_newarray);
out.writeByte(getOperand(0));
}
public int length() {
return 2;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class PUTFIELD extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_putfield);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class PUTSTATIC extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_putstatic);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,27 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class RET extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
if (wide) {
out.writeByte(opc_wide);
}
out.writeByte(opc_ret);
if (wide) {
out.writeShort(getOperand(0));
}
else {
out.writeByte(getOperand(0));
}
}
public int length() {
return wide ? 4 : 2;
}
}

@ -1,19 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.Instruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class SIPUSH extends Instruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_sipush);
out.writeShort(getOperand(0));
}
public int length() {
return 3;
}
}

@ -1,28 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.code.optinstructions;
import org.jetbrains.java.decompiler.code.SwitchInstruction;
import java.io.DataOutputStream;
import java.io.IOException;
public class TABLESWITCH extends SwitchInstruction {
public void writeToStream(DataOutputStream out, int offset) throws IOException {
out.writeByte(opc_tableswitch);
int padding = 3 - (offset % 4);
for (int i = 0; i < padding; i++) {
out.writeByte(0);
}
for (int i = 0; i < operandsCount(); i++) {
out.writeInt(getOperand(i));
}
}
public int length() {
return 1 + operandsCount() * 4;
}
}

@ -316,10 +316,8 @@ public class AssertProcessor {
if (fparam.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
fparam.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0);
if (classname.equals(fdparam.getClassname())
&& key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString))) {
return true;
}
return classname.equals(fdparam.getClassname()) &&
key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString));
}
}
return false;
@ -327,10 +325,8 @@ public class AssertProcessor {
else {
if (exprent.type == Exprent.EXPRENT_FIELD) {
FieldExprent fdparam = (FieldExprent) exprent;
if (classname.equals(fdparam.getClassname())
&& key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString))) {
return true;
}
return classname.equals(fdparam.getClassname()) &&
key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString));
}
return false;
}

@ -87,18 +87,14 @@ public class ClassReference14Processor {
RootStatement root = meth.root;
if (root != null) {
DirectGraph graph = meth.getOrBuildGraph();
graph.iterateExprents(new DirectGraph.ExprentIterator() {
public int processExprent(Exprent exprent) {
for (Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
setFound.add(ent.getKey());
}
graph.iterateExprents(exprent -> {
for (Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
setFound.add(ent.getKey());
}
return 0;
}
return 0;
});
}
}

@ -103,18 +103,10 @@ public class ClassesProcessor {
}
// reference to the nested class
Set<String> set = mapNestedClassReferences.get(enclClassName);
if (set == null) {
mapNestedClassReferences.put(enclClassName, set = new HashSet<>());
}
set.add(innerName);
mapNestedClassReferences.computeIfAbsent(enclClassName, k1 -> new HashSet<>()).add(innerName);
// reference to the enclosing class
set = mapEnclosingClassReferences.get(innerName);
if (set == null) {
mapEnclosingClassReferences.put(innerName, set = new HashSet<>());
}
set.add(enclClassName);
mapEnclosingClassReferences.computeIfAbsent(innerName, k -> new HashSet<>()).add(enclClassName);
}
}
}
@ -281,7 +273,7 @@ public class ClassesProcessor {
}
}
private static void initWrappers(ClassNode node) throws IOException {
private static void initWrappers(ClassNode node) {
if (node.type == ClassNode.CLASS_LAMBDA) {
return;
}
@ -355,7 +347,6 @@ public class ClassesProcessor {
lambdaInformation = new LambdaInformation();
lambdaInformation.class_name = lambda_class_name;
lambdaInformation.method_name = lambda_method_name;
lambdaInformation.method_descriptor = lambda_method_descriptor;
@ -405,7 +396,6 @@ public class ClassesProcessor {
}
public static class LambdaInformation {
public String class_name;
public String method_name;
public String method_descriptor;

@ -56,7 +56,8 @@ public class TextBuffer {
}
public TextBuffer prepend(String s) {
insert(0, s);
myStringBuilder.insert(0, s);
shiftMapping(s.length());
return this;
}
@ -167,20 +168,15 @@ public class TextBuffer {
return myStringBuilder.length();
}
public String substring(int start) {
return myStringBuilder.substring(start);
}
public TextBuffer setStart(int position) {
public void setStart(int position) {
myStringBuilder.delete(0, position);
shiftMapping(0, -position);
return this;
shiftMapping(-position);
}
public void setLength(int position) {
myStringBuilder.setLength(position);
if (myLineToOffsetMapping != null) {
HashMap<Integer, Integer> newMap = new HashMap<>();
Map<Integer, Integer> newMap = new HashMap<>();
for (Map.Entry<Integer, Integer> entry : myLineToOffsetMapping.entrySet()) {
if (entry.getValue() <= position) {
newMap.put(entry.getKey(), entry.getValue());
@ -201,12 +197,12 @@ public class TextBuffer {
return this;
}
private void shiftMapping(int startOffset, int shiftOffset) {
private void shiftMapping(int shiftOffset) {
if (myLineToOffsetMapping != null) {
HashMap<Integer, Integer> newMap = new HashMap<>();
Map<Integer, Integer> newMap = new HashMap<>();
for (Map.Entry<Integer, Integer> entry : myLineToOffsetMapping.entrySet()) {
int newValue = entry.getValue();
if (newValue >= startOffset) {
if (newValue >= 0) {
newValue += shiftOffset;
}
if (newValue >= 0) {
@ -223,12 +219,6 @@ public class TextBuffer {
}
}
public TextBuffer insert(int offset, String s) {
myStringBuilder.insert(offset, s);
shiftMapping(offset, s.length());
return this;
}
public int countLines() {
return countLines(0);
}
@ -283,13 +273,9 @@ public class TextBuffer {
myLineMapping = new HashMap<>();
for (int i = 0; i < lineMapping.length; i += 2) {
int key = lineMapping[i + 1];
Set<Integer> existing = myLineMapping.get(key);
if (existing == null) {
existing = new TreeSet<>();
myLineMapping.put(key, existing);
}
Set<Integer> existing = myLineMapping.computeIfAbsent(key, k -> new TreeSet<>());
existing.add(lineMapping[i]);
}
}
}
}
}

@ -8,7 +8,6 @@ import java.util.*;
import java.util.Map.Entry;
public class BytecodeSourceMapper {
private int offset_total;
// class, method, bytecode offset, source line
@ -19,15 +18,8 @@ public class BytecodeSourceMapper {
private final Set<Integer> unmappedLines = new TreeSet<>();
public void addMapping(String className, String methodName, int bytecodeOffset, int sourceLine) {
Map<String, Map<Integer, Integer>> class_mapping = mapping.get(className);
if (class_mapping == null) {
mapping.put(className, class_mapping = new LinkedHashMap<>()); // need to preserve order
}
Map<Integer, Integer> method_mapping = class_mapping.get(methodName);
if (method_mapping == null) {
class_mapping.put(methodName, method_mapping = new HashMap<>());
}
Map<String, Map<Integer, Integer>> class_mapping = mapping.computeIfAbsent(className, k -> new LinkedHashMap<>()); // need to preserve order
Map<Integer, Integer> method_mapping = class_mapping.computeIfAbsent(methodName, k -> new HashMap<>());
// don't overwrite
if (!method_mapping.containsKey(bytecodeOffset)) {
@ -98,14 +90,6 @@ public class BytecodeSourceMapper {
}
}
public int getTotalOffset() {
return offset_total;
}
public void setTotalOffset(int offset_total) {
this.offset_total = offset_total;
}
public void addTotalOffset(int offset_total) {
this.offset_total += offset_total;
}
@ -124,4 +108,4 @@ public class BytecodeSourceMapper {
}
return res;
}
}
}

@ -70,12 +70,12 @@ public class ImportCollector {
public String getShortName(String fullName, boolean imported) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(fullName.replace('.', '/'));
String result = null;
StringBuilder result = null;
if (node != null && node.classStruct.isOwn()) {
result = node.simpleName;
result = new StringBuilder(node.simpleName);
while (node.parent != null && node.type == ClassNode.CLASS_MEMBER) {
result = node.parent.simpleName + '.' + result;
result.insert(0, node.parent.simpleName + '.');
node = node.parent;
}
@ -84,7 +84,7 @@ public class ImportCollector {
fullName = fullName.replace('/', '.');
}
else {
return result;
return result.toString();
}
}
else {
@ -121,7 +121,7 @@ public class ImportCollector {
}
}
return result == null ? shortName : result;
return result == null ? shortName : result.toString();
}
public int writeImports(TextBuffer buffer) {

@ -244,10 +244,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
}
private boolean checkEntry(String entryName, String file) {
Set<String> set = mapArchiveEntries.get(file);
if (set == null) {
mapArchiveEntries.put(file, set = new HashSet<>());
}
Set<String> set = mapArchiveEntries.computeIfAbsent(file, k -> new HashSet<>());
boolean added = set.add(entryName);
if (!added) {

@ -19,7 +19,6 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -35,7 +34,7 @@ public class ClassWrapper {
this.classStruct = classStruct;
}
public void init() throws IOException {
public void init() {
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS, classStruct);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_WRAPPER, this);
DecompilerContext.getLogger().startClass(classStruct.qualifiedName);

@ -30,21 +30,17 @@ public class LambdaProcessor {
processClass(child);
}
hasLambda(node);
}
public boolean hasLambda(ClassNode node) throws IOException {
ClassesProcessor clProcessor = DecompilerContext.getClassProcessor();
StructClass cl = node.classStruct;
if (cl.getBytecodeVersion() < CodeConstants.BYTECODE_JAVA_8) { // lambda beginning with Java 8
return false;
return;
}
StructBootstrapMethodsAttribute bootstrap =
(StructBootstrapMethodsAttribute)cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
if (bootstrap == null || bootstrap.getMethodsNumber() == 0) {
return false; // no bootstrap constants in pool
return; // no bootstrap constants in pool
}
BitSet lambda_methods = new BitSet();
@ -61,7 +57,7 @@ public class LambdaProcessor {
}
if (lambda_methods.isEmpty()) {
return false; // no lambda bootstrap constant found
return; // no lambda bootstrap constant found
}
Map<String, String> mapMethodsLambda = new HashMap<>();
@ -78,7 +74,7 @@ public class LambdaProcessor {
Instruction instr = seq.getInstr(i);
if (instr.opcode == CodeConstants.opc_invokedynamic) {
LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));
LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.operand(0));
if (lambda_methods.get(invoke_dynamic.index1)) { // lambda invocation found
@ -126,7 +122,5 @@ public class LambdaProcessor {
}
// FIXME: mixed hierarchy?
return false;
}
}
}

@ -118,45 +118,42 @@ public class NestedClassProcessor {
final Map<VarVersionPair, String> mapNewNames = new HashMap<>();
enclosingMethod.getOrBuildGraph().iterateExprents(new DirectGraph.ExprentIterator() {
@Override
public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
enclosingMethod.getOrBuildGraph().iterateExprents(exprent -> {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_NEW) {
NewExprent new_expr = (NewExprent)expr;
for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_NEW) {
NewExprent new_expr = (NewExprent)expr;
VarNamesCollector enclosingCollector = new VarNamesCollector(enclosingMethod.varproc.getVarNames());
VarNamesCollector enclosingCollector = new VarNamesCollector(enclosingMethod.varproc.getVarNames());
if (new_expr.isLambda() && lambda_class_type.equals(new_expr.getNewType())) {
InvocationExprent inv_dynamic = new_expr.getConstructor();
if (new_expr.isLambda() && lambda_class_type.equals(new_expr.getNewType())) {
InvocationExprent inv_dynamic = new_expr.getConstructor();
int param_index = is_static_lambda_content ? 0 : 1;
int varIndex = is_static_lambda_content ? 0 : 1;
int param_index = is_static_lambda_content ? 0 : 1;
int varIndex = is_static_lambda_content ? 0 : 1;
for (int i = 0; i < md_content.params.length; ++i) {
VarVersionPair varVersion = new VarVersionPair(varIndex, 0);
if (i < vars_count) {
Exprent param = inv_dynamic.getLstParameters().get(param_index + i);
for (int i = 0; i < md_content.params.length; ++i) {
VarVersionPair varVersion = new VarVersionPair(varIndex, 0);
if (i < vars_count) {
Exprent param = inv_dynamic.getLstParameters().get(param_index + i);
if (param.type == Exprent.EXPRENT_VAR) {
mapNewNames.put(varVersion, enclosingMethod.varproc.getVarName(new VarVersionPair((VarExprent)param)));
}
}
else {
mapNewNames.put(varVersion, enclosingCollector.getFreeName(method.varproc.getVarName(varVersion)));
if (param.type == Exprent.EXPRENT_VAR) {
mapNewNames.put(varVersion, enclosingMethod.varproc.getVarName(new VarVersionPair((VarExprent)param)));
}
varIndex += md_content.params[i].stackSize;
}
else {
mapNewNames.put(varVersion, enclosingCollector.getFreeName(method.varproc.getVarName(varVersion)));
}
varIndex += md_content.params[i].stackSize;
}
}
}
return 0;
}
return 0;
});
// update names of local variables
@ -272,67 +269,64 @@ public class NestedClassProcessor {
// iterate enclosing class
for (final MethodWrapper method : node.getWrapper().getMethods()) {
if (method.root != null) { // neither abstract, nor native
method.getOrBuildGraph().iterateExprents(new DirectGraph.ExprentIterator() {
@Override
public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
method.getOrBuildGraph().iterateExprents(exprent -> {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_NEW) {
InvocationExprent constructor = ((NewExprent)expr).getConstructor();
for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_NEW) {
InvocationExprent constructor = ((NewExprent)expr).getConstructor();
if (constructor != null && mapVarMasks.containsKey(constructor.getClassname())) { // non-static inner class constructor
String refClassName = constructor.getClassname();
ClassNode nestedClassNode = node.getClassNode(refClassName);
if (constructor != null && mapVarMasks.containsKey(constructor.getClassname())) { // non-static inner class constructor
String refClassName = constructor.getClassname();
ClassNode nestedClassNode = node.getClassNode(refClassName);
if (nestedClassNode.type != ClassNode.CLASS_MEMBER) {
List<VarFieldPair> mask = mapVarMasks.get(refClassName).get(constructor.getStringDescriptor());
if (!mapVarFieldPairs.containsKey(refClassName)) {
mapVarFieldPairs.put(refClassName, new HashMap<>());
}
if (nestedClassNode.type != ClassNode.CLASS_MEMBER) {
List<VarFieldPair> mask = mapVarMasks.get(refClassName).get(constructor.getStringDescriptor());
List<VarFieldPair> lstTemp = new ArrayList<>();
if (!mapVarFieldPairs.containsKey(refClassName)) {
mapVarFieldPairs.put(refClassName, new HashMap<>());
}
for (int i = 0; i < mask.size(); i++) {
Exprent param = constructor.getLstParameters().get(i);
VarFieldPair pair = null;
List<VarFieldPair> lstTemp = new ArrayList<>();
if (param.type == Exprent.EXPRENT_VAR && mask.get(i) != null) {
VarVersionPair varPair = new VarVersionPair((VarExprent)param);
for (int i = 0; i < mask.size(); i++) {
Exprent param = constructor.getLstParameters().get(i);
VarFieldPair pair = null;
// FIXME: flags of variables are wrong! Correct the entire functionality.
// if(method.varproc.getVarFinal(varPair) != VarTypeProcessor.VAR_NON_FINAL) {
pair = new VarFieldPair(mask.get(i).fieldKey, varPair);
// }
}
if (param.type == Exprent.EXPRENT_VAR && mask.get(i) != null) {
VarVersionPair varPair = new VarVersionPair((VarExprent)param);
lstTemp.add(pair);
// FIXME: flags of variables are wrong! Correct the entire functionality.
// if(method.varproc.getVarFinal(varPair) != VarTypeProcessor.VAR_NON_FINAL) {
pair = new VarFieldPair(mask.get(i).fieldKey, varPair);
// }
}
List<VarFieldPair> pairMask = mapVarFieldPairs.get(refClassName).get(constructor.getStringDescriptor());
if (pairMask == null) {
pairMask = lstTemp;
}
else {
for (int i = 0; i < pairMask.size(); i++) {
if (!InterpreterUtil.equalObjects(pairMask.get(i), lstTemp.get(i))) {
pairMask.set(i, null);
}
lstTemp.add(pair);
}
List<VarFieldPair> pairMask = mapVarFieldPairs.get(refClassName).get(constructor.getStringDescriptor());
if (pairMask == null) {
pairMask = lstTemp;
}
else {
for (int i = 0; i < pairMask.size(); i++) {
if (!InterpreterUtil.equalObjects(pairMask.get(i), lstTemp.get(i))) {
pairMask.set(i, null);
}
}
mapVarFieldPairs.get(refClassName).put(constructor.getStringDescriptor(), pairMask);
nestedClassNode.enclosingMethod =
InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor());
}
mapVarFieldPairs.get(refClassName).put(constructor.getStringDescriptor(), pairMask);
nestedClassNode.enclosingMethod =
InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor());
}
}
}
return 0;
}
return 0;
});
}
}
@ -918,7 +912,7 @@ public class NestedClassProcessor {
}
private static class VarFieldPair {
public String fieldKey = "";
public String fieldKey;
public VarVersionPair varPair;
public VarFieldPair(String field, VarVersionPair varPair) {
@ -940,4 +934,4 @@ public class NestedClassProcessor {
return fieldKey.hashCode() + varPair.hashCode();
}
}
}
}

@ -247,9 +247,7 @@ public class NestedMemberAccess {
}
}
for (DirectNode ndx : nd.succs) {
stack.add(ndx);
}
stack.addAll(nd.succs);
}
if (replaced) {

@ -212,13 +212,9 @@ public class ConcatenationHelper {
}
private static boolean isNewConcat(NewExprent expr, VarType cltype) {
if (expr.getNewType().equals(cltype)) {
VarType[] params = expr.getConstructor().getDescriptor().params;
if (params.length == 0 || (params.length == 1 &&
params[0].equals(VarType.VARTYPE_STRING))) {
return true;
}
return params.length == 0 || params.length == 1 && params[0].equals(VarType.VARTYPE_STRING);
}
return false;

@ -180,17 +180,9 @@ public class DecHelper {
return true;
}
public static HashSet<Statement> getUniquePredExceptions(Statement head) {
HashSet<Statement> setHandlers = new HashSet<>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_FORWARD));
Iterator<Statement> it = setHandlers.iterator();
while (it.hasNext()) {
if (it.next().getPredecessorEdges(StatEdge.TYPE_EXCEPTION).size() > 1) {
it.remove();
}
}
public static Set<Statement> getUniquePredExceptions(Statement head) {
Set<Statement> setHandlers = new HashSet<>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_FORWARD));
setHandlers.removeIf(statement -> statement.getPredecessorEdges(StatEdge.TYPE_EXCEPTION).size() > 1);
return setHandlers;
}
@ -201,4 +193,4 @@ public class DecHelper {
}
return ret;
}
}
}

@ -177,7 +177,7 @@ public class DomHelper {
lstPosts.add(stt.id);
}
Collections.sort(lstPosts, Comparator.comparing(mapSortOrder::get));
lstPosts.sort(Comparator.comparing(mapSortOrder::get));
if (lstPosts.size() > 1 && lstPosts.get(0).intValue() == st.id) {
lstPosts.add(lstPosts.remove(0));
@ -453,14 +453,12 @@ public class DomHelper {
Set<Integer> setExtPosts = mapExtPost.get(headid);
for (int i = 0; i < posts.size(); i++) {
Integer postid = posts.get(i);
if (!postid.equals(headid) && !setExtPosts.contains(postid)) {
for (Integer postId : posts) {
if (!postId.equals(headid) && !setExtPosts.contains(postId)) {
continue;
}
Statement post = stats.getWithKey(postid);
Statement post = stats.getWithKey(postId);
if (post == null) { // possible in case of an inherited postdominance set
continue;
@ -539,14 +537,14 @@ public class DomHelper {
// build statement and return
if (excok) {
Statement res = null;
Statement res;
setPreds.removeAll(setNodes);
if (setPreds.size() == 0) {
if ((setNodes.size() > 1 ||
head.getNeighbours(StatEdge.TYPE_REGULAR, Statement.DIRECTION_BACKWARD).contains(head))
&& setNodes.size() < stats.size()) {
if (checkSynchronizedCompleteness(head, setNodes)) {
if (checkSynchronizedCompleteness(setNodes)) {
res = new GeneralStatement(head, setNodes, same ? null : post);
stat.collapseNodesToStatement(res);
@ -561,8 +559,7 @@ public class DomHelper {
return null;
}
private static boolean checkSynchronizedCompleteness(Statement head, HashSet<Statement> setNodes) {
private static boolean checkSynchronizedCompleteness(Set<Statement> setNodes) {
// check exit nodes
for (Statement stat : setNodes) {
if (stat.isMonitorEnter()) {
@ -618,12 +615,7 @@ public class DomHelper {
set.removeAll(setOldNodes);
if (setOldNodes.contains(key)) {
Set<Integer> setNew = mapExtPost.get(newid);
if (setNew == null) {
mapExtPost.put(newid, setNew = new HashSet<>());
}
setNew.addAll(set);
mapExtPost.computeIfAbsent(newid, k -> new HashSet<>()).addAll(set);
mapExtPost.remove(key);
}
else {

@ -1,197 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.modules.decompiler;
import org.jetbrains.java.decompiler.modules.decompiler.stats.DoStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class EliminateLoopsHelper {
// public static boolean eliminateLoops(Statement root) {
//
// boolean ret = eliminateLoopsRec(root);
//
// if(ret) {
// SequenceHelper.condenseSequences(root);
//
// HashSet<Integer> setReorderedIfs = new HashSet<Integer>();
//
// SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(false);
// while(sehelper.simplifyStackVarsStatement(root, setReorderedIfs, null)) {
// SequenceHelper.condenseSequences(root);
// }
// }
//
// return ret;
// }
private static boolean eliminateLoopsRec(Statement stat) {
for (Statement st : stat.getStats()) {
if (eliminateLoopsRec(st)) {
return true;
}
}
if (stat.type == Statement.TYPE_DO && isLoopRedundant((DoStatement)stat)) {
return true;
}
return false;
}
private static boolean isLoopRedundant(DoStatement loop) {
if (loop.getLooptype() != DoStatement.LOOP_DO) {
return false;
}
// get parent loop if exists
Statement parentloop = loop.getParent();
while (parentloop != null && parentloop.type != Statement.TYPE_DO) {
parentloop = parentloop.getParent();
}
if (parentloop == null || parentloop.getBasichead() != loop.getBasichead()) {
return false;
}
// collect relevant break edges
List<StatEdge> lstBreakEdges = new ArrayList<>();
for (StatEdge edge : loop.getLabelEdges()) {
if (edge.getType() == StatEdge.TYPE_BREAK) { // all break edges are explicit because of LOOP_DO type
lstBreakEdges.add(edge);
}
}
Statement loopcontent = loop.getFirst();
boolean firstok = loopcontent.getAllSuccessorEdges().isEmpty();
if (!firstok) {
StatEdge edge = loopcontent.getAllSuccessorEdges().get(0);
firstok = (edge.closure == loop && edge.getType() == StatEdge.TYPE_BREAK);
if (firstok) {
lstBreakEdges.remove(edge);
}
}
if (!lstBreakEdges.isEmpty()) {
if (firstok) {
HashMap<Integer, Boolean> statLabeled = new HashMap<>();
List<Statement> lstEdgeClosures = new ArrayList<>();
for (StatEdge edge : lstBreakEdges) {
Statement minclosure = LowBreakHelper.getMinClosure(loopcontent, edge.getSource());
lstEdgeClosures.add(minclosure);
}
int precount = loop.isLabeled() ? 1 : 0;
for (Statement st : lstEdgeClosures) {
if (!statLabeled.containsKey(st.id)) {
boolean btemp = st.isLabeled();
precount += btemp ? 1 : 0;
statLabeled.put(st.id, btemp);
}
}
for (int i = 0; i < lstBreakEdges.size(); i++) {
Statement st = lstEdgeClosures.get(i);
statLabeled.put(st.id, LowBreakHelper.isBreakEdgeLabeled(lstBreakEdges.get(i).getSource(), st) | statLabeled.get(st.id));
}
for (int i = 0; i < lstBreakEdges.size(); i++) {
lstEdgeClosures.set(i, getMaxBreakLift(lstEdgeClosures.get(i), lstBreakEdges.get(i), statLabeled, loop));
}
statLabeled.clear();
for (Statement st : lstEdgeClosures) {
statLabeled.put(st.id, st.isLabeled());
}
for (int i = 0; i < lstBreakEdges.size(); i++) {
Statement st = lstEdgeClosures.get(i);
statLabeled.put(st.id, LowBreakHelper.isBreakEdgeLabeled(lstBreakEdges.get(i).getSource(), st) | statLabeled.get(st.id));
}
long postcount = statLabeled.values().stream().filter(Boolean::booleanValue).count();
if (precount <= postcount) {
return false;
}
else {
for (int i = 0; i < lstBreakEdges.size(); i++) {
lstEdgeClosures.get(i).addLabeledEdge(lstBreakEdges.get(i));
}
}
}
else {
return false;
}
}
eliminateLoop(loop, parentloop);
return true;
}
private static Statement getMaxBreakLift(Statement stat, StatEdge edge, HashMap<Integer, Boolean> statLabeled, Statement max) {
Statement closure = stat;
Statement newclosure = stat;
while ((newclosure = getNextBreakLift(newclosure, edge, statLabeled, max)) != null) {
closure = newclosure;
}
return closure;
}
private static Statement getNextBreakLift(Statement stat, StatEdge edge, HashMap<Integer, Boolean> statLabeled, Statement max) {
Statement closure = stat.getParent();
while (closure != null && closure != max && !closure.containsStatementStrict(edge.getDestination())) {
boolean edge_labeled = LowBreakHelper.isBreakEdgeLabeled(edge.getSource(), closure);
boolean stat_labeled = statLabeled.containsKey(closure.id) ? statLabeled.get(closure.id) : closure.isLabeled();
if (stat_labeled || !edge_labeled) {
return closure;
}
closure = closure.getParent();
}
return null;
}
private static void eliminateLoop(Statement loop, Statement parentloop) {
// move continue edges to the parent loop
List<StatEdge> lst = new ArrayList<>(loop.getLabelEdges());
for (StatEdge edge : lst) {
loop.removePredecessor(edge);
edge.getSource().changeEdgeNode(Statement.DIRECTION_FORWARD, edge, parentloop);
parentloop.addPredecessor(edge);
parentloop.addLabeledEdge(edge);
}
// remove the last break edge, if exists
Statement loopcontent = loop.getFirst();
if (!loopcontent.getAllSuccessorEdges().isEmpty()) {
loopcontent.removeSuccessor(loopcontent.getAllSuccessorEdges().get(0));
}
// replace loop with its content
loop.getParent().replaceStatement(loop, loopcontent);
}
}

@ -208,9 +208,7 @@ public class ExitHelper {
return true;
}
public static boolean removeRedundantReturns(RootStatement root) {
boolean res = false;
public static void removeRedundantReturns(RootStatement root) {
DummyExitStatement dummyExit = root.getDummyExit();
for (StatEdge edge : dummyExit.getAllPredecessorEdges()) {
@ -225,13 +223,10 @@ public class ExitHelper {
// remove redundant return
dummyExit.addBytecodeOffsets(ex.bytecode);
lstExpr.remove(lstExpr.size() - 1);
res = true;
}
}
}
}
}
return res;
}
}

@ -24,6 +24,7 @@ import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.TextUtil;
import java.util.*;
@ -170,12 +171,7 @@ public class ExprProcessor implements CodeConstants {
}
if (isSuccessor) {
Map<String, PrimitiveExprsList> mapSucc = mapData.get(nd);
if (mapSucc == null) {
mapData.put(nd, mapSucc = new HashMap<>());
}
Map<String, PrimitiveExprsList> mapSucc = mapData.computeIfAbsent(nd, k -> new HashMap<>());
LinkedList<String> ndentrypoints = new LinkedList<>(entrypoints);
if (setFinallyLongRangeEntryPaths.contains(node.id + "##" + nd.id)) {
@ -295,25 +291,25 @@ public class ExprProcessor implements CodeConstants {
break;
case opc_bipush:
case opc_sipush:
pushEx(stack, exprlist, new ConstExprent(instr.getOperand(0), true, bytecode_offsets));
pushEx(stack, exprlist, new ConstExprent(instr.operand(0), true, bytecode_offsets));
break;
case opc_lconst_0:
case opc_lconst_1:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, Long.valueOf(instr.opcode - opc_lconst_0), bytecode_offsets));
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, (long)(instr.opcode - opc_lconst_0), bytecode_offsets));
break;
case opc_fconst_0:
case opc_fconst_1:
case opc_fconst_2:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, Float.valueOf(instr.opcode - opc_fconst_0), bytecode_offsets));
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, (float)(instr.opcode - opc_fconst_0), bytecode_offsets));
break;
case opc_dconst_0:
case opc_dconst_1:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, Double.valueOf(instr.opcode - opc_dconst_0), bytecode_offsets));
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, (double)(instr.opcode - opc_dconst_0), bytecode_offsets));
break;
case opc_ldc:
case opc_ldc_w:
case opc_ldc2_w:
PooledConstant cn = pool.getConstant(instr.getOperand(0));
PooledConstant cn = pool.getConstant(instr.operand(0));
if (cn instanceof PrimitiveConstant) {
pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], ((PrimitiveConstant)cn).value, bytecode_offsets));
}
@ -327,7 +323,7 @@ public class ExprProcessor implements CodeConstants {
case opc_fload:
case opc_dload:
case opc_aload:
pushEx(stack, exprlist, new VarExprent(instr.getOperand(0), varTypes[instr.opcode - opc_iload], varProcessor, bytecode_offset));
pushEx(stack, exprlist, new VarExprent(instr.operand(0), varTypes[instr.opcode - opc_iload], varProcessor, bytecode_offset));
break;
case opc_iaload:
case opc_laload:
@ -355,10 +351,10 @@ public class ExprProcessor implements CodeConstants {
case opc_fstore:
case opc_dstore:
case opc_astore:
Exprent top = stack.pop();
int varindex = instr.getOperand(0);
Exprent expr = stack.pop();
int varindex = instr.operand(0);
AssignmentExprent assign = new AssignmentExprent(
new VarExprent(varindex, varTypes[instr.opcode - opc_istore], varProcessor, nextMeaningfulOffset(block, i)), top, bytecode_offsets);
new VarExprent(varindex, varTypes[instr.opcode - opc_istore], varProcessor, nextMeaningfulOffset(block, i)), expr, bytecode_offsets);
exprlist.add(assign);
break;
case opc_iastore:
@ -420,10 +416,10 @@ public class ExprProcessor implements CodeConstants {
pushEx(stack, exprlist, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack, bytecode_offsets));
break;
case opc_iinc:
VarExprent vevar = new VarExprent(instr.getOperand(0), VarType.VARTYPE_INT, varProcessor);
VarExprent vevar = new VarExprent(instr.operand(0), VarType.VARTYPE_INT, varProcessor);
exprlist.add(new AssignmentExprent(vevar, new FunctionExprent(
instr.getOperand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays
.asList(vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, Math.abs(instr.getOperand(1)), null)),
instr.operand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays
.asList(vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, Math.abs(instr.operand(1)), null)),
bytecode_offsets), bytecode_offsets));
break;
case opc_i2l:
@ -494,21 +490,21 @@ public class ExprProcessor implements CodeConstants {
break;
case opc_checkcast:
case opc_instanceof:
stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true), null, null));
stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.operand(0)).getString(), true), null, null));
case opc_arraylength:
pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode).intValue(), stack, bytecode_offsets));
pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode), stack, bytecode_offsets));
break;
case opc_getstatic:
case opc_getfield:
pushEx(stack, exprlist,
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop(),
new FieldExprent(pool.getLinkConstant(instr.operand(0)), instr.opcode == opc_getstatic ? null : stack.pop(),
bytecode_offsets));
break;
case opc_putstatic:
case opc_putfield:
Exprent valfield = stack.pop();
Exprent exprfield =
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop(),
new FieldExprent(pool.getLinkConstant(instr.operand(0)), instr.opcode == opc_putstatic ? null : stack.pop(),
bytecode_offsets);
exprlist.add(new AssignmentExprent(exprfield, valfield, bytecode_offsets));
break;
@ -517,8 +513,8 @@ public class ExprProcessor implements CodeConstants {
case opc_invokestatic:
case opc_invokeinterface:
case opc_invokedynamic:
if (instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
LinkConstant invoke_constant = pool.getLinkConstant(instr.getOperand(0));
if (instr.opcode != opc_invokedynamic || instr.bytecodeVersion >= CodeConstants.BYTECODE_JAVA_7) {
LinkConstant invoke_constant = pool.getLinkConstant(instr.operand(0));
List<PooledConstant> bootstrap_arguments = null;
if (instr.opcode == opc_invokedynamic && bootstrap != null) {
@ -537,15 +533,15 @@ public class ExprProcessor implements CodeConstants {
case opc_new:
case opc_anewarray:
case opc_multianewarray:
int dimensions = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1);
VarType arrType = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true);
int dimensions = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.operand(1);
VarType arrType = new VarType(pool.getPrimitiveConstant(instr.operand(0)).getString(), true);
if (instr.opcode != opc_multianewarray) {
arrType = arrType.resizeArrayDim(arrType.arrayDim + dimensions);
}
pushEx(stack, exprlist, new NewExprent(arrType, stack, dimensions, bytecode_offsets));
break;
case opc_newarray:
pushEx(stack, exprlist, new NewExprent(new VarType(arrTypeIds[instr.getOperand(0) - 4], 1), stack, 1, bytecode_offsets));
pushEx(stack, exprlist, new NewExprent(new VarType(arrTypeIds[instr.operand(0) - 4], 1), stack, 1, bytecode_offsets));
break;
case opc_dup:
pushEx(stack, exprlist, stack.getByOffset(-1).copy());
@ -714,12 +710,9 @@ public class ExprProcessor implements CodeConstants {
}
public static String getCastTypeName(VarType type, boolean getShort) {
String s = getTypeName(type, getShort);
int dim = type.arrayDim;
while (dim-- > 0) {
s += "[]";
}
return s;
StringBuilder s = new StringBuilder(getTypeName(type, getShort));
TextUtil.append(s, "[]", type.arrayDim);
return s.toString();
}
public static PrimitiveExprsList getExpressionData(VarExprent var) {
@ -835,13 +828,13 @@ public class ExprProcessor implements CodeConstants {
defaultVal = new ConstExprent(VarType.VARTYPE_NULL, null, null);
}
else if (arrType.type == CodeConstants.TYPE_FLOAT) {
defaultVal = new ConstExprent(VarType.VARTYPE_FLOAT, Float.valueOf(0), null);
defaultVal = new ConstExprent(VarType.VARTYPE_FLOAT, 0f, null);
}
else if (arrType.type == CodeConstants.TYPE_LONG) {
defaultVal = new ConstExprent(VarType.VARTYPE_LONG, Long.valueOf(0), null);
defaultVal = new ConstExprent(VarType.VARTYPE_LONG, 0L, null);
}
else if (arrType.type == CodeConstants.TYPE_DOUBLE) {
defaultVal = new ConstExprent(VarType.VARTYPE_DOUBLE, Double.valueOf(0), null);
defaultVal = new ConstExprent(VarType.VARTYPE_DOUBLE, 0d, null);
}
else { // integer types
defaultVal = new ConstExprent(0, true, null);

@ -14,10 +14,8 @@ public class ExprentStack extends ListStack<Exprent> {
pointer = list.getPointer();
}
public Exprent push(Exprent item) {
public void push(Exprent item) {
super.push(item);
return item;
}
public Exprent pop() {

@ -54,7 +54,6 @@ public class FinallyProcessor {
stack.add(root);
while (!stack.isEmpty()) {
Statement stat = stack.removeLast();
Statement parent = stat.getParent();
@ -69,14 +68,12 @@ public class FinallyProcessor {
// do nothing
}
else if (finallyBlockIDs.containsKey(handler.id)) {
fin.setFinally(true);
Integer var = finallyBlockIDs.get(handler.id);
fin.setMonitor(var == null ? null : new VarExprent(var.intValue(), VarType.VARTYPE_INT, varProcessor));
fin.setMonitor(var == null ? null : new VarExprent(var, VarType.VARTYPE_INT, varProcessor));
}
else {
Record inf = getFinallyInformation(mt, root, fin);
if (inf == null) { // inconsistent finally
@ -110,62 +107,6 @@ public class FinallyProcessor {
return false;
}
// private boolean processStatement(StructMethod mt, RootStatement root, ControlFlowGraph graph, Statement stat) {
//
// boolean res = false;
//
// for(int i=stat.getStats().size()-1;i>=0;i--) {
// if(processStatement(mt, root, graph, stat.getStats().get(i))) {
// return true;
// }
// }
//
//
// if(stat.type == Statement.TYPE_CATCHALL && !stat.isCopied()) {
//
// CatchAllStatement fin = (CatchAllStatement)stat;
// BasicBlock head = fin.getBasichead().getBlock();
// BasicBlock handler = fin.getHandler().getBasichead().getBlock();
//
// if(catchallBlockIDs.containsKey(handler.id)) {
// ; // do nothing
// }else if(finallyBlockIDs.containsKey(handler.id)) {
//
// fin.setFinally(true);
//
// Integer var = finallyBlockIDs.get(handler.id);
// fin.setMonitor(var==null?null:new VarExprent(var.intValue(), VarType.VARTYPE_INT, varprocessor));
//
// } else {
//
// Object[] inf = getFinallyInformation(mt, root, fin);
//
// if(inf == null) { // inconsistent finally
// catchallBlockIDs.put(handler.id, null);
// } else {
//
// if(DecompilerContext.getOption(IFernflowerPreferences.FINALLY_DEINLINE) && verifyFinallyEx(graph, fin, inf)) {
// finallyBlockIDs.put(handler.id, null);
// } else {
//
// int varindex = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER);
// insertSemaphore(graph, getAllBasicBlocks(fin.getFirst()), head, handler, varindex, inf);
//
// finallyBlockIDs.put(handler.id, varindex);
// }
//
// DeadCodeHelper.removeEmptyBlocks(graph);
// DeadCodeHelper.mergeBasicBlocks(graph);
// }
//
// res = true;
// }
// }
//
// return res;
// }
private static class Record {
private final int firstCode;
private final Map<BasicBlock, Boolean> mapLast;
@ -212,7 +153,6 @@ public class FinallyProcessor {
Set<DirectNode> setVisited = new HashSet<>();
while (!stack.isEmpty()) {
DirectNode node = stack.removeFirst();
if (setVisited.contains(node)) {
@ -359,7 +299,6 @@ public class FinallyProcessor {
int var,
Record information,
int bytecode_version) {
Set<BasicBlock> setCopy = new HashSet<>(setTry);
int finallytype = information.firstCode;
@ -378,21 +317,15 @@ public class FinallyProcessor {
// disable semaphore at statement exit points
for (BasicBlock block : setTry) {
List<BasicBlock> lstSucc = block.getSuccs();
for (BasicBlock dest : lstSucc) {
for (BasicBlock dest : lstSucc) {
// break out
if (!setCopy.contains(dest) && dest != graph.getLast()) {
// disable semaphore
SimpleInstructionSequence seq = new SimpleInstructionSequence();
seq.addInstruction(ConstantsUtil
.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version,
new int[]{0}), -1);
seq.addInstruction(ConstantsUtil
.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version,
new int[]{var}), -1);
seq.addInstruction(Instruction.create(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}), -1);
seq.addInstruction(Instruction.create(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}), -1);
// build a separate block
BasicBlock newblock = new BasicBlock(++graph.last_id);
@ -419,14 +352,10 @@ public class FinallyProcessor {
}
}
// enable semaphor at the statement entrance
// enable semaphore at the statement entrance
SimpleInstructionSequence seq = new SimpleInstructionSequence();
seq.addInstruction(
ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{1}),
-1);
seq.addInstruction(
ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}),
-1);
seq.addInstruction(Instruction.create(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{1}), -1);
seq.addInstruction(Instruction.create(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}), -1);
BasicBlock newhead = new BasicBlock(++graph.last_id);
newhead.setSeq(seq);
@ -435,12 +364,8 @@ public class FinallyProcessor {
// initialize semaphor with false
seq = new SimpleInstructionSequence();
seq.addInstruction(
ConstantsUtil.getInstructionInstance(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}),
-1);
seq.addInstruction(
ConstantsUtil.getInstructionInstance(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}),
-1);
seq.addInstruction(Instruction.create(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}), -1);
seq.addInstruction(Instruction.create(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{var}), -1);
BasicBlock newheadinit = new BasicBlock(++graph.last_id);
newheadinit.setSeq(seq);
@ -460,9 +385,7 @@ public class FinallyProcessor {
}
}
private static void insertBlockBefore(ControlFlowGraph graph, BasicBlock oldblock, BasicBlock newblock) {
List<BasicBlock> lstTemp = new ArrayList<>();
lstTemp.addAll(oldblock.getPreds());
lstTemp.addAll(oldblock.getPredExceptions());
@ -494,8 +417,7 @@ public class FinallyProcessor {
}
}
private static HashSet<BasicBlock> getAllBasicBlocks(Statement stat) {
private static Set<BasicBlock> getAllBasicBlocks(Statement stat) {
List<Statement> lst = new LinkedList<>();
lst.add(stat);
@ -513,7 +435,7 @@ public class FinallyProcessor {
}
while (index < lst.size());
HashSet<BasicBlock> res = new HashSet<>();
Set<BasicBlock> res = new HashSet<>();
for (Statement st : lst) {
res.add(((BasicBlockStatement)st).getBlock());
@ -522,11 +444,9 @@ public class FinallyProcessor {
return res;
}
private boolean verifyFinallyEx(ControlFlowGraph graph, CatchAllStatement fstat, Record information) {
HashSet<BasicBlock> tryBlocks = getAllBasicBlocks(fstat.getFirst());
HashSet<BasicBlock> catchBlocks = getAllBasicBlocks(fstat.getHandler());
Set<BasicBlock> tryBlocks = getAllBasicBlocks(fstat.getFirst());
Set<BasicBlock> catchBlocks = getAllBasicBlocks(fstat.getHandler());
int finallytype = information.firstCode;
Map<BasicBlock, Boolean> mapLast = information.mapLast;
@ -555,7 +475,7 @@ public class FinallyProcessor {
}
// identify start blocks
HashSet<BasicBlock> startBlocks = new HashSet<>();
Set<BasicBlock> startBlocks = new HashSet<>();
for (BasicBlock block : tryBlocks) {
startBlocks.addAll(block.getSuccs());
}
@ -618,12 +538,11 @@ public class FinallyProcessor {
private Area compareSubgraphsEx(ControlFlowGraph graph,
BasicBlock startSample,
HashSet<BasicBlock> catchBlocks,
Set<BasicBlock> catchBlocks,
BasicBlock startCatch,
int finallytype,
Map<BasicBlock, Boolean> mapLast,
boolean skippedFirst) {
class BlockStackEntry {
public BasicBlock blockCatch;
public BasicBlock blockSample;
@ -677,7 +596,6 @@ public class FinallyProcessor {
}
}
// exception successors
if (isLastBlock && blockSample.getSeq().isEmpty()) {
// do nothing, blockSample will be removed anyway
@ -706,7 +624,7 @@ public class FinallyProcessor {
if (instrCatch.opcode == CodeConstants.opc_astore &&
instrSample.opcode == CodeConstants.opc_astore) {
lst = new ArrayList<>(lst);
lst.add(new int[]{instrCatch.getOperand(0), instrSample.getOperand(0)});
lst.add(new int[]{instrCatch.operand(0), instrSample.operand(0)});
}
}
@ -743,7 +661,6 @@ public class FinallyProcessor {
}
private static BasicBlock getUniqueNext(ControlFlowGraph graph, Set<BasicBlock[]> setNext) {
// precondition: there is at most one true exit path in a finally statement
BasicBlock next = null;
@ -784,13 +701,11 @@ public class FinallyProcessor {
Instruction instrNext = seqNext.getInstr(i);
Instruction instrBlock = seqBlock.getInstr(i);
if (instrNext.opcode != instrBlock.opcode || instrNext.wide != instrBlock.wide
|| instrNext.operandsCount() != instrBlock.operandsCount()) {
if (!Instruction.equals(instrNext, instrBlock)) {
return null;
}
for (int j = 0; j < instrNext.getOperands().length; j++) {
if (instrNext.getOperand(j) != instrBlock.getOperand(j)) {
for (int j = 0; j < instrNext.operandsCount(); j++) {
if (instrNext.operand(j) != instrBlock.operand(j)) {
return null;
}
}
@ -832,7 +747,6 @@ public class FinallyProcessor {
int type,
int finallytype,
List<int[]> lstStoreVars) {
InstructionSequence seqPattern = pattern.getSeq();
InstructionSequence seqSample = sample.getSeq();
@ -871,7 +785,6 @@ public class FinallyProcessor {
}
if (seqPattern.length() < seqSample.length()) { // split in two blocks
SimpleInstructionSequence seq = new SimpleInstructionSequence();
LinkedList<Integer> oldOffsets = new LinkedList<>();
for (int i = seqSample.length() - 1; i >= seqPattern.length(); i--) {
@ -916,19 +829,15 @@ public class FinallyProcessor {
}
public boolean equalInstructions(Instruction first, Instruction second, List<int[]> lstStoreVars) {
if (first.opcode != second.opcode || first.wide != second.wide
|| first.operandsCount() != second.operandsCount()) {
if (!Instruction.equals(first, second)) {
return false;
}
if (first.group != CodeConstants.GROUP_JUMP && first.getOperands() != null) { // FIXME: switch comparison
for (int i = 0; i < first.getOperands().length; i++) {
int firstOp = first.getOperand(i);
int secondOp = second.getOperand(i);
if (first.group != CodeConstants.GROUP_JUMP) { // FIXME: switch comparison
for (int i = 0; i < first.operandsCount(); i++) {
int firstOp = first.operand(i);
int secondOp = second.operand(i);
if (firstOp != secondOp) {
// a-load/store instructions
if (first.opcode == CodeConstants.opc_aload || first.opcode == CodeConstants.opc_astore) {
for (int[] arr : lstStoreVars) {
@ -947,7 +856,6 @@ public class FinallyProcessor {
}
private static void deleteArea(ControlFlowGraph graph, Area area) {
BasicBlock start = area.start;
BasicBlock next = area.next;
@ -1021,18 +929,15 @@ public class FinallyProcessor {
}
if (is_outside_range) {
// new empty block
BasicBlock emptyblock = new BasicBlock(++graph.last_id);
graph.getBlocks().addWithKey(emptyblock, emptyblock.id);
// add to ranges if necessary
if (setCommonRemovedExceptionRanges != null) {
for (ExceptionRangeCFG range : setCommonRemovedExceptionRanges) {
emptyblock.addSuccessorException(range.getHandler());
range.getProtectedRange().add(emptyblock);
}
for (ExceptionRangeCFG range : setCommonRemovedExceptionRanges) {
emptyblock.addSuccessorException(range.getHandler());
range.getProtectedRange().add(emptyblock);
}
// insert between predecessors and next
@ -1044,7 +949,6 @@ public class FinallyProcessor {
}
private static void removeExceptionInstructionsEx(BasicBlock block, int blocktype, int finallytype) {
InstructionSequence seq = block.getSeq();
if (finallytype == 3) { // empty finally handler

@ -111,7 +111,7 @@ public class IdeaNotNullHelper {
return false;
}
removeParameterCheck(stat, mt);
removeParameterCheck(stat);
return true;
}
@ -119,7 +119,7 @@ public class IdeaNotNullHelper {
return false;
}
private static void removeParameterCheck(Statement stat, StructMethod mt) {
private static void removeParameterCheck(Statement stat) {
Statement st = stat.getFirst();
while (st.type == Statement.TYPE_SEQUENCE) {
@ -128,11 +128,7 @@ public class IdeaNotNullHelper {
IfStatement ifstat = (IfStatement)st;
if (ifstat.getElsestat() == null) { // if
// TODO:
}
else { // if - else
if (ifstat.getElsestat() != null) { // if - else
StatEdge ifedge = ifstat.getIfEdge();
StatEdge elseedge = ifstat.getElseEdge();
@ -171,11 +167,7 @@ public class IdeaNotNullHelper {
}
}
if (is_notnull_check) {
return removeReturnCheck(stat, mt);
}
return false;
return is_notnull_check && removeReturnCheck(stat, mt);
}

@ -61,9 +61,7 @@ public class IfHelper {
return res;
}
public static boolean mergeIfs(Statement statement, HashSet<Integer> setReorderedIfs) {
if (statement.type != Statement.TYPE_IF && statement.type != Statement.TYPE_SEQUENCE) {
return false;
}
@ -71,7 +69,6 @@ public class IfHelper {
boolean res = false;
while (true) {
boolean updated = false;
List<Statement> lst = new ArrayList<>();
@ -85,7 +82,6 @@ public class IfHelper {
boolean stsingle = (lst.size() == 1);
for (Statement stat : lst) {
if (stat.type == Statement.TYPE_IF) {
IfNode rtnode = buildGraph((IfStatement)stat, stsingle);
@ -98,7 +94,6 @@ public class IfHelper {
}
if (!setReorderedIfs.contains(stat.id)) {
if (updated = collapseIfElse(rtnode)) {
break;
}
@ -119,14 +114,13 @@ public class IfHelper {
break;
}
res |= updated;
res |= true;
}
return res;
}
private static boolean collapseIfIf(IfNode rtnode) {
if (rtnode.edgetypes.get(0) == 0) {
IfNode ifbranch = rtnode.succs.get(0);
if (ifbranch.succs.size() == 2) {
@ -144,7 +138,7 @@ public class IfHelper {
ifchild.removeSuccessor(ifchild.getAllSuccessorEdges().get(0));
ifparent.getStats().removeWithKey(ifchild.id);
if (ifbranch.edgetypes.get(0).intValue() == 1) { // target null
if (ifbranch.edgetypes.get(0) == 1) { // target null
ifparent.setIfstat(null);
@ -200,7 +194,7 @@ public class IfHelper {
private static boolean collapseIfElse(IfNode rtnode) {
if (rtnode.edgetypes.get(0).intValue() == 0) {
if (rtnode.edgetypes.get(0) == 0) {
IfNode ifbranch = rtnode.succs.get(0);
if (ifbranch.succs.size() == 2) {
@ -216,8 +210,8 @@ public class IfHelper {
ifchild.getFirst().removeSuccessor(ifchild.getIfEdge());
ifparent.getStats().removeWithKey(ifchild.id);
if (ifbranch.edgetypes.get(1).intValue() == 1 &&
ifbranch.edgetypes.get(0).intValue() == 1) { // target null
if (ifbranch.edgetypes.get(1) == 1 &&
ifbranch.edgetypes.get(0) == 1) { // target null
ifparent.setIfstat(null);
@ -254,7 +248,7 @@ public class IfHelper {
private static boolean collapseElse(IfNode rtnode) {
if (rtnode.edgetypes.get(1).intValue() == 0) {
if (rtnode.edgetypes.get(1) == 0) {
IfNode elsebranch = rtnode.succs.get(1);
if (elsebranch.succs.size() == 2) {
@ -419,16 +413,14 @@ public class IfHelper {
return res;
}
// FIXME: rewrite the entire method!!! keep in mind finally exits!!
private static boolean reorderIf(IfStatement ifstat) {
if (ifstat.iftype == IfStatement.IFTYPE_IFELSE) {
return false;
}
boolean ifdirect = false, elsedirect = false;
boolean noifstat = false, noelsestat = false;
boolean ifdirect, elsedirect;
boolean noifstat = false, noelsestat;
boolean ifdirectpath = false, elsedirectpath = false;
Statement parent = ifstat.getParent();
@ -439,32 +431,20 @@ public class IfHelper {
if (ifstat.getIfstat() == null) {
noifstat = true;
if (ifstat.getIfEdge().getType() == StatEdge.TYPE_FINALLYEXIT) {
ifdirect = true;
}
else {
ifdirect = MergeHelper.isDirectPath(from, ifstat.getIfEdge().getDestination());
}
ifdirect = ifstat.getIfEdge().getType() == StatEdge.TYPE_FINALLYEXIT ||
MergeHelper.isDirectPath(from, ifstat.getIfEdge().getDestination());
}
else {
List<StatEdge> lstSuccs = ifstat.getIfstat().getAllSuccessorEdges();
if (!lstSuccs.isEmpty() && lstSuccs.get(0).getType() == StatEdge.TYPE_FINALLYEXIT) {
ifdirect = true;
}
else {
ifdirect = hasDirectEndEdge(ifstat.getIfstat(), from);
}
ifdirect = !lstSuccs.isEmpty() && lstSuccs.get(0).getType() == StatEdge.TYPE_FINALLYEXIT ||
hasDirectEndEdge(ifstat.getIfstat(), from);
}
Statement last = parent.type == Statement.TYPE_SEQUENCE ? parent.getStats().getLast() : ifstat;
noelsestat = (last == ifstat);
if (!last.getAllSuccessorEdges().isEmpty() && last.getAllSuccessorEdges().get(0).getType() == StatEdge.TYPE_FINALLYEXIT) {
elsedirect = true;
}
else {
elsedirect = hasDirectEndEdge(last, from);
}
elsedirect = !last.getAllSuccessorEdges().isEmpty() && last.getAllSuccessorEdges().get(0).getType() == StatEdge.TYPE_FINALLYEXIT ||
hasDirectEndEdge(last, from);
if (!noelsestat && existsPath(ifstat, ifstat.getAllSuccessorEdges().get(0).getDestination())) {
return false;

@ -186,21 +186,13 @@ public class InlineSingleBlockHelper {
}
public static boolean isBreakEdgeLabeled(Statement source, Statement closure) {
if (closure.type == Statement.TYPE_DO || closure.type == Statement.TYPE_SWITCH) {
Statement parent = source.getParent();
if (parent == closure) {
return false;
}
else {
return parent.type == Statement.TYPE_DO || parent.type == Statement.TYPE_SWITCH ||
isBreakEdgeLabeled(parent, closure);
}
return parent != closure &&
(parent.type == Statement.TYPE_DO || parent.type == Statement.TYPE_SWITCH || isBreakEdgeLabeled(parent, closure));
}
else {
return true;
}
}
}
}

@ -265,7 +265,7 @@ public class LabelHelper {
Statement stlast = swst.getCaseStatements().get(last);
if (stlast.getExprents() != null && stlast.getExprents().isEmpty()) {
StatEdge edge = stlast.getAllSuccessorEdges().get(0);
mapEdges.put(edge.getDestination(), new ArrayList<>(Arrays.asList(new StatEdge[]{edge})));
mapEdges.put(edge.getDestination(), new ArrayList<>(Collections.singletonList(edge)));
}
else {
mapEdges = setExplicitEdges(stlast);
@ -326,7 +326,7 @@ public class LabelHelper {
edge.explicit = false;
}
mapEdges.put(newedge.getDestination(), new ArrayList<>(Arrays.asList(new StatEdge[]{newedge})));
mapEdges.put(newedge.getDestination(), new ArrayList<>(Collections.singletonList(newedge)));
}
}
}
@ -374,7 +374,7 @@ public class LabelHelper {
}
if (statedge != null) {
mapEdges.put(statedge.getDestination(), new ArrayList<>(Arrays.asList(new StatEdge[]{statedge})));
mapEdges.put(statedge.getDestination(), new ArrayList<>(Collections.singletonList(statedge)));
}
}
@ -406,24 +406,26 @@ public class LabelHelper {
}
}
private static HashSet<Statement>[] processStatementLabel(Statement stat) {
private static class LabelSets {
private final Set<Statement> breaks = new HashSet<>();
private final Set<Statement> continues = new HashSet<>();
}
HashSet<Statement> setBreak = new HashSet<>();
HashSet<Statement> setContinue = new HashSet<>();
private static LabelSets processStatementLabel(Statement stat) {
LabelSets sets = new LabelSets();
if (stat.getExprents() == null) {
for (Statement st : stat.getStats()) {
HashSet<Statement>[] arr = processStatementLabel(st);
setBreak.addAll(arr[0]);
setContinue.addAll(arr[1]);
LabelSets nested = processStatementLabel(st);
sets.breaks.addAll(nested.breaks);
sets.continues.addAll(nested.continues);
}
boolean shieldType = (stat.type == Statement.TYPE_DO || stat.type == Statement.TYPE_SWITCH);
if (shieldType) {
for (StatEdge edge : stat.getLabelEdges()) {
if (edge.explicit && ((edge.getType() == StatEdge.TYPE_BREAK && setBreak.contains(edge.getSource())) ||
(edge.getType() == StatEdge.TYPE_CONTINUE && setContinue.contains(edge.getSource())))) {
if (edge.explicit && ((edge.getType() == StatEdge.TYPE_BREAK && sets.breaks.contains(edge.getSource())) ||
(edge.getType() == StatEdge.TYPE_CONTINUE && sets.continues.contains(edge.getSource())))) {
edge.labeled = false;
}
}
@ -431,16 +433,16 @@ public class LabelHelper {
switch (stat.type) {
case Statement.TYPE_DO:
setContinue.clear();
sets.continues.clear();
case Statement.TYPE_SWITCH:
setBreak.clear();
sets.breaks.clear();
}
}
setBreak.add(stat);
setContinue.add(stat);
sets.breaks.add(stat);
sets.continues.add(stat);
return new HashSet[] { setBreak, setContinue };
return sets;
}
public static void replaceContinueWithBreak(Statement stat) {

@ -58,9 +58,7 @@ public class LoopExtractHelper {
return res ? 1 : 0;
}
private static boolean extractLoop(DoStatement stat) {
if (stat.getLooptype() != DoStatement.LOOP_DO) {
return false;
}
@ -71,12 +69,7 @@ public class LoopExtractHelper {
}
}
if (!extractLastIf(stat)) {
return extractFirstIf(stat);
}
else {
return true;
}
return extractLastIf(stat) || extractFirstIf(stat);
}
private static boolean extractLastIf(DoStatement stat) {

@ -1,194 +0,0 @@
// Copyright 2000-2017 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.
package org.jetbrains.java.decompiler.modules.decompiler;
import org.jetbrains.java.decompiler.modules.decompiler.stats.IfStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.SynchronizedStatement;
import java.util.List;
public class LowBreakHelper {
public static void lowBreakLabels(Statement root) {
lowBreakLabelsRec(root);
liftBreakLabels(root);
}
private static void lowBreakLabelsRec(Statement stat) {
while (true) {
boolean found = false;
for (StatEdge edge : stat.getLabelEdges()) {
if (edge.getType() == StatEdge.TYPE_BREAK) {
Statement minclosure = getMinClosure(stat, edge.getSource());
if (minclosure != stat) {
minclosure.addLabeledEdge(edge);
edge.labeled = isBreakEdgeLabeled(edge.getSource(), minclosure);
found = true;
break;
}
}
}
if (!found) {
break;
}
}
for (Statement st : stat.getStats()) {
lowBreakLabelsRec(st);
}
}
public static boolean isBreakEdgeLabeled(Statement source, Statement closure) {
if (closure.type == Statement.TYPE_DO || closure.type == Statement.TYPE_SWITCH) {
Statement parent = source.getParent();
if (parent == closure) {
return false;
}
else {
return isBreakEdgeLabeled(parent, closure) ||
(parent.type == Statement.TYPE_DO || parent.type == Statement.TYPE_SWITCH);
}
}
else {
return true;
}
}
public static Statement getMinClosure(Statement closure, Statement source) {
while (true) {
Statement newclosure = null;
switch (closure.type) {
case Statement.TYPE_SEQUENCE:
Statement last = closure.getStats().getLast();
if (isOkClosure(closure, source, last)) {
newclosure = last;
}
break;
case Statement.TYPE_IF:
IfStatement ifclosure = (IfStatement)closure;
if (isOkClosure(closure, source, ifclosure.getIfstat())) {
newclosure = ifclosure.getIfstat();
}
else if (isOkClosure(closure, source, ifclosure.getElsestat())) {
newclosure = ifclosure.getElsestat();
}
break;
case Statement.TYPE_TRYCATCH:
for (Statement st : closure.getStats()) {
if (isOkClosure(closure, source, st)) {
newclosure = st;
break;
}
}
break;
case Statement.TYPE_SYNCRONIZED:
Statement body = ((SynchronizedStatement)closure).getBody();
if (isOkClosure(closure, source, body)) {
newclosure = body;
}
}
if (newclosure == null) {
break;
}
closure = newclosure;
}
return closure;
}
private static boolean isOkClosure(Statement closure, Statement source, Statement stat) {
boolean ok = false;
if (stat != null && stat.containsStatementStrict(source)) {
List<StatEdge> lst = stat.getAllSuccessorEdges();
ok = lst.isEmpty();
if (!ok) {
StatEdge edge = lst.get(0);
ok = (edge.closure == closure && edge.getType() == StatEdge.TYPE_BREAK);
}
}
return ok;
}
private static void liftBreakLabels(Statement stat) {
for (Statement st : stat.getStats()) {
liftBreakLabels(st);
}
while (true) {
boolean found = false;
for (StatEdge edge : stat.getLabelEdges()) {
if (edge.explicit && edge.labeled && edge.getType() == StatEdge.TYPE_BREAK) {
Statement newclosure = getMaxBreakLift(stat, edge);
if (newclosure != null) {
newclosure.addLabeledEdge(edge);
edge.labeled = isBreakEdgeLabeled(edge.getSource(), newclosure);
found = true;
break;
}
}
}
if (!found) {
break;
}
}
}
private static Statement getMaxBreakLift(Statement stat, StatEdge edge) {
Statement closure = null;
Statement newclosure = stat;
while ((newclosure = getNextBreakLift(newclosure, edge)) != null) {
closure = newclosure;
}
return closure;
}
private static Statement getNextBreakLift(Statement stat, StatEdge edge) {
Statement closure = stat.getParent();
while (closure != null && !closure.containsStatementStrict(edge.getDestination())) {
boolean labeled = isBreakEdgeLabeled(edge.getSource(), closure);
if (closure.isLabeled() || !labeled) {
return closure;
}
closure = closure.getParent();
}
return null;
}
}

@ -13,16 +13,12 @@ import java.util.List;
import java.util.Set;
public class MergeHelper {
public static void enhanceLoops(Statement root) {
while (enhanceLoopsRec(root)) ;
while (enhanceLoopsRec(root)) /**/;
SequenceHelper.condenseSequences(root);
}
private static boolean enhanceLoopsRec(Statement stat) {
boolean res = false;
for (Statement st : stat.getStats()) {
@ -39,7 +35,6 @@ public class MergeHelper {
}
private static boolean enhanceLoop(DoStatement stat) {
int oldloop = stat.getLooptype();
switch (oldloop) {
@ -63,8 +58,7 @@ public class MergeHelper {
return (stat.getLooptype() != oldloop);
}
private static boolean matchDoWhile(DoStatement stat) {
private static void matchDoWhile(DoStatement stat) {
// search for an if condition at the end of the loop
Statement last = stat.getFirst();
while (last.type == Statement.TYPE_SEQUENCE) {
@ -86,10 +80,9 @@ public class MergeHelper {
set.remove(last);
if (!set.isEmpty()) {
return false;
return;
}
stat.setLooptype(DoStatement.LOOP_DOWHILE);
IfExprent ifexpr = (IfExprent)lastif.getHeadexprent().copy();
@ -121,12 +114,9 @@ public class MergeHelper {
}
stat.addSuccessor(edge);
}
return true;
}
}
}
return false;
}
private static boolean matchWhile(DoStatement stat) {
@ -277,15 +267,14 @@ public class MergeHelper {
}
}
private static boolean matchFor(DoStatement stat) {
Exprent lastDoExprent = null, initDoExprent = null;
Statement lastData = null, preData = null;
private static void matchFor(DoStatement stat) {
Exprent lastDoExprent, initDoExprent;
Statement lastData, preData = null;
// get last exprent
lastData = getLastDirectData(stat.getFirst());
if (lastData == null || lastData.getExprents().isEmpty()) {
return false;
return;
}
List<Exprent> lstExpr = lastData.getExprents();
@ -298,11 +287,9 @@ public class MergeHelper {
}
}
boolean haslast = issingle || (lastDoExprent.type == Exprent.EXPRENT_ASSIGNMENT ||
lastDoExprent.type == Exprent.EXPRENT_FUNCTION);
boolean haslast = issingle || lastDoExprent.type == Exprent.EXPRENT_ASSIGNMENT || lastDoExprent.type == Exprent.EXPRENT_FUNCTION;
if (!haslast) {
return false;
return;
}
boolean hasinit = false;
@ -336,13 +323,12 @@ public class MergeHelper {
}
}
if ((hasinit && haslast) || issingle) { // FIXME: issingle sufficient?
if (hasinit || issingle) { // FIXME: issingle sufficient?
Set<Statement> set = stat.getNeighboursSet(StatEdge.TYPE_CONTINUE, Statement.DIRECTION_BACKWARD);
set.remove(lastData);
if (!set.isEmpty()) {
return false;
return;
}
stat.setLooptype(DoStatement.LOOP_FOR);
@ -359,8 +345,6 @@ public class MergeHelper {
}
removeLastEmptyStatement(stat, lastData);
}
return true;
}
private static void removeLastEmptyStatement(DoStatement dostat, Statement stat) {
@ -388,7 +372,6 @@ public class MergeHelper {
}
private static Statement getLastDirectData(Statement stat) {
if (stat.getExprents() != null) {
return stat;
}
@ -404,4 +387,4 @@ public class MergeHelper {
}
return null;
}
}
}

@ -164,7 +164,7 @@ public class SecondaryFunctionsHelper {
if (index >= 0 && index <= 2) {
Integer destcon = destcons[index];
if (destcon != null) {
desttype = destcon.intValue();
desttype = destcon;
}
}
}
@ -208,10 +208,10 @@ public class SecondaryFunctionsHelper {
ConstExprent cexpr = (ConstExprent)operand;
long val;
if (operandtype.type == CodeConstants.TYPE_LONG) {
val = ((Long)cexpr.getValue()).longValue();
val = (Long)cexpr.getValue();
}
else {
val = ((Integer)cexpr.getValue()).intValue();
val = (Integer)cexpr.getValue();
}
if (val == -1) {
@ -229,7 +229,7 @@ public class SecondaryFunctionsHelper {
for (int i = 0; i < 2; i++) {
if (lstOperands.get(i).type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)lstOperands.get(i);
int val = ((Integer)cexpr.getValue()).intValue();
int val = (Integer)cexpr.getValue();
if ((fexpr.getFuncType() == FunctionExprent.FUNCTION_EQ && val == 1) ||
(fexpr.getFuncType() == FunctionExprent.FUNCTION_NE && val == 0)) {
@ -248,10 +248,10 @@ public class SecondaryFunctionsHelper {
if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) {
int val = ((ConstExprent)lstOperands.get(0)).getIntValue();
if (val == 0) {
return new ConstExprent(VarType.VARTYPE_BOOLEAN, Integer.valueOf(1), fexpr.bytecode);
return new ConstExprent(VarType.VARTYPE_BOOLEAN, 1, fexpr.bytecode);
}
else {
return new ConstExprent(VarType.VARTYPE_BOOLEAN, Integer.valueOf(0), fexpr.bytecode);
return new ConstExprent(VarType.VARTYPE_BOOLEAN, 0, fexpr.bytecode);
}
}
break;
@ -286,8 +286,8 @@ public class SecondaryFunctionsHelper {
FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new VarExprent(var, type, varProc),
ConstExprent.getZeroConstant(type.type)), null),
new ConstExprent(VarType.VARTYPE_INT, Integer.valueOf(-1), null),
new ConstExprent(VarType.VARTYPE_INT, Integer.valueOf(1), null)), null);
new ConstExprent(VarType.VARTYPE_INT, -1, null),
new ConstExprent(VarType.VARTYPE_INT, 1, null)), null);
FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(
new AssignmentExprent(new VarExprent(var, type, varProc),
@ -298,7 +298,7 @@ public class SecondaryFunctionsHelper {
varProc.setVarType(new VarVersionPair(var, 0), type);
return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
head, new ConstExprent(VarType.VARTYPE_INT, Integer.valueOf(0), null), iff), fexpr.bytecode);
head, new ConstExprent(VarType.VARTYPE_INT, 0, null), iff), fexpr.bytecode);
}
break;
case Exprent.EXPRENT_ASSIGNMENT: // check for conditional assignment

@ -21,7 +21,6 @@ import java.util.*;
import java.util.Map.Entry;
public class SimplifyExprentsHelper {
static final MatchEngine class14Builder = new MatchEngine();
private final boolean firstInvocation;
@ -31,15 +30,12 @@ public class SimplifyExprentsHelper {
}
public boolean simplifyStackVarsStatement(Statement stat, HashSet<Integer> setReorderedIfs, SSAConstructorSparseEx ssa, StructClass cl) {
boolean res = false;
if (stat.getExprents() == null) {
boolean processClass14 = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4);
while (true) {
boolean changed = false;
for (Statement st : stat.getStats()) {
@ -69,27 +65,24 @@ public class SimplifyExprentsHelper {
}
}
else {
res |= simplifyStackVarsExprents(stat.getExprents(), cl);
res = simplifyStackVarsExprents(stat.getExprents(), cl);
}
return res;
}
private boolean simplifyStackVarsExprents(List<Exprent> list, StructClass cl) {
boolean res = false;
int index = 0;
while (index < list.size()) {
Exprent current = list.get(index);
Exprent ret = isSimpleConstructorInvocation(current);
if (ret != null) {
list.set(index, ret);
res = true;
continue;
}
@ -98,7 +91,6 @@ public class SimplifyExprentsHelper {
if (ret != null) {
list.set(index, ret);
res = true;
continue;
}
@ -106,7 +98,6 @@ public class SimplifyExprentsHelper {
if (isMonitorExit(current)) {
list.remove(index);
res = true;
continue;
}
@ -114,7 +105,6 @@ public class SimplifyExprentsHelper {
if (isTrivialStackAssignment(current)) {
list.remove(index);
res = true;
continue;
}
@ -122,15 +112,12 @@ public class SimplifyExprentsHelper {
break;
}
Exprent next = list.get(index + 1);
// constructor invocation
if (isConstructorInvocationRemote(list, index)) {
list.remove(index);
res = true;
continue;
}
@ -139,7 +126,6 @@ public class SimplifyExprentsHelper {
if (isQualifiedNewGetClass(current, next)) {
list.remove(index);
res = true;
continue;
}
}
@ -151,7 +137,6 @@ public class SimplifyExprentsHelper {
list.remove(index + 1);
}
res = true;
continue;
}
@ -159,7 +144,6 @@ public class SimplifyExprentsHelper {
if (addArrayInitializer(current, next)) {
list.remove(index + 1);
res = true;
continue;
}
@ -168,7 +152,6 @@ public class SimplifyExprentsHelper {
if (func != null) {
list.set(index, func);
res = true;
continue;
}
@ -176,7 +159,6 @@ public class SimplifyExprentsHelper {
if (isIPPorIMM(current, next)) {
list.remove(index + 1);
res = true;
continue;
}
@ -184,14 +166,12 @@ public class SimplifyExprentsHelper {
if (isStackAssignement(current, next)) {
list.remove(index + 1);
res = true;
continue;
}
if (!firstInvocation && isStackAssignement2(current, next)) {
list.remove(index + 1);
res = true;
continue;
}
@ -202,7 +182,6 @@ public class SimplifyExprentsHelper {
}
private static boolean addArrayInitializer(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent as = (AssignmentExprent)first;
@ -210,7 +189,6 @@ public class SimplifyExprentsHelper {
NewExprent newex = (NewExprent)as.getRight();
if (!newex.getLstArrayElements().isEmpty()) {
VarExprent arrvar = (VarExprent)as.getLeft();
if (second.type == Exprent.EXPRENT_ASSIGNMENT) {
@ -226,13 +204,10 @@ public class SimplifyExprentsHelper {
Exprent init = newex.getLstArrayElements().get(constvalue);
if (init.type == Exprent.EXPRENT_CONST) {
ConstExprent cinit = (ConstExprent)init;
VarType arrtype = newex.getNewType().decreaseArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
if (cinit.equals(defaultval)) {
Exprent tempexpr = aas.getRight();
if (!tempexpr.containsExprent(arrvar)) {
@ -261,9 +236,7 @@ public class SimplifyExprentsHelper {
return false;
}
private static int isArrayInitializer(List<Exprent> list, int index) {
Exprent current = list.get(index);
if (current.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent as = (AssignmentExprent)current;
@ -274,7 +247,7 @@ public class SimplifyExprentsHelper {
if (newex.getExprType().arrayDim > 0 && newex.getLstDims().size() == 1 && newex.getLstArrayElements().isEmpty() &&
newex.getLstDims().get(0).type == Exprent.EXPRENT_CONST) {
int size = ((Integer)((ConstExprent)newex.getLstDims().get(0)).getValue()).intValue();
int size = (Integer)((ConstExprent)newex.getLstDims().get(0)).getValue();
if (size == 0) {
return 0;
}
@ -356,7 +329,6 @@ public class SimplifyExprentsHelper {
}
private static boolean isTrivialStackAssignment(Exprent first) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent asf = (AssignmentExprent)first;
@ -364,10 +336,7 @@ public class SimplifyExprentsHelper {
VarExprent varleft = (VarExprent)asf.getLeft();
VarExprent varright = (VarExprent)asf.getRight();
if (varleft.getIndex() == varright.getIndex() && varleft.isStack() &&
varright.isStack()) {
return true;
}
return varleft.getIndex() == varright.getIndex() && varleft.isStack() && varright.isStack();
}
}
@ -375,7 +344,6 @@ public class SimplifyExprentsHelper {
}
private static boolean isStackAssignement2(Exprent first, Exprent second) { // e.g. 1.4-style class invocation
if (first.type == Exprent.EXPRENT_ASSIGNMENT && second.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent asf = (AssignmentExprent)first;
AssignmentExprent ass = (AssignmentExprent)second;
@ -393,7 +361,6 @@ public class SimplifyExprentsHelper {
}
private static boolean isStackAssignement(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT && second.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent asf = (AssignmentExprent)first;
AssignmentExprent ass = (AssignmentExprent)second;
@ -422,7 +389,6 @@ public class SimplifyExprentsHelper {
}
private static Exprent isPPIorMMI(Exprent first) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent as = (AssignmentExprent)first;
@ -459,7 +425,6 @@ public class SimplifyExprentsHelper {
}
private static boolean isIPPorIMM(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_ASSIGNMENT && second.type == Exprent.EXPRENT_FUNCTION) {
AssignmentExprent as = (AssignmentExprent)first;
FunctionExprent in = (FunctionExprent)second;
@ -485,17 +450,15 @@ public class SimplifyExprentsHelper {
private static boolean isMonitorExit(Exprent first) {
if (first.type == Exprent.EXPRENT_MONITOR) {
MonitorExprent monexpr = (MonitorExprent)first;
if (monexpr.getMonType() == MonitorExprent.MONITOR_EXIT && monexpr.getValue().type == Exprent.EXPRENT_VAR
&& !((VarExprent)monexpr.getValue()).isStack()) {
return true;
}
return monexpr.getMonType() == MonitorExprent.MONITOR_EXIT &&
monexpr.getValue().type == Exprent.EXPRENT_VAR &&
!((VarExprent)monexpr.getValue()).isStack();
}
return false;
}
private static boolean isQualifiedNewGetClass(Exprent first, Exprent second) {
if (first.type == Exprent.EXPRENT_INVOCATION) {
InvocationExprent invexpr = (InvocationExprent)first;
@ -525,118 +488,8 @@ public class SimplifyExprentsHelper {
return false;
}
// private static boolean isConstructorInvocationRemote(List<Exprent> list, int index) {
//
// Exprent current = list.get(index);
//
// if(current.type == Exprent.EXPRENT_ASSIGNMENT) {
// AssignmentExprent as = (AssignmentExprent)current;
//
// if(as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
//
// NewExprent newexpr = (NewExprent)as.getRight();
// VarType newtype = newexpr.getNewType();
// VarVersionPair leftPaar = new VarVersionPair((VarExprent)as.getLeft());
//
// if(newtype.type == CodeConstants.TYPE_OBJECT && newtype.arrayDim == 0 &&
// newexpr.getConstructor() == null) {
//
// Set<VarVersionPair> setChangedVars = new HashSet<VarVersionPair>();
//
// for(int i = index + 1; i < list.size(); i++) {
// Exprent remote = list.get(i);
//
// if(remote.type == Exprent.EXPRENT_INVOCATION) {
// InvocationExprent in = (InvocationExprent)remote;
//
// if(in.getFuncType() == InvocationExprent.TYP_INIT && in.getInstance().type == Exprent.EXPRENT_VAR
// && as.getLeft().equals(in.getInstance())) {
//
// Set<VarVersionPair> setVars = remote.getAllVariables();
// setVars.remove(leftPaar);
// setVars.retainAll(setChangedVars);
//
// if(setVars.isEmpty()) {
//
// newexpr.setConstructor(in);
// in.setInstance(null);
//
// if(!setChangedVars.isEmpty()) { // some exprents inbetween
// list.add(index+1, as.copy());
// list.remove(i+1);
// } else {
// list.set(i, as.copy());
// }
//
// return true;
// }
// }
// }
//
// boolean isTempAssignment = false;
//
// if(remote.type == Exprent.EXPRENT_ASSIGNMENT) { // ugly solution
// AssignmentExprent asremote = (AssignmentExprent)remote;
// if(asremote.getLeft().type == Exprent.EXPRENT_VAR &&
// asremote.getRight().type == Exprent.EXPRENT_VAR) {
// setChangedVars.add(new VarVersionPair((VarExprent)asremote.getLeft()));
// isTempAssignment = true;
// }
//
// // FIXME: needs to be rewritten
// // propagate (var = new X) forward to the <init> invokation and then reduce
//
//// if(asremote.getLeft().type == Exprent.EXPRENT_VAR) {
//// List<Exprent> lstRightExprents = asremote.getRight().getAllExprents(true);
//// lstRightExprents.add(asremote.getRight());
////
//// Set<VarVersionPair> setTempChangedVars = new HashSet<VarVersionPair>();
//// boolean isTemp = true;
////
//// for(Exprent expr : lstRightExprents) {
//// if(expr.type != Exprent.EXPRENT_VAR && expr.type != Exprent.EXPRENT_FIELD) {
//// isTemp = false;
//// break;
//// } else if(expr.type == Exprent.EXPRENT_VAR) {
//// setTempChangedVars.add(new VarVersionPair((VarExprent)expr));
//// }
//// }
////
//// if(isTemp) {
//// setChangedVars.addAll(setTempChangedVars);
//// isTempAssignment = true;
//// }
//// }
//// } else if(remote.type == Exprent.EXPRENT_FUNCTION) {
//// FunctionExprent fexpr = (FunctionExprent)remote;
//// if(fexpr.getFuncType() == FunctionExprent.FUNCTION_IPP || fexpr.getFuncType() == FunctionExprent.FUNCTION_IMM
//// || fexpr.getFuncType() == FunctionExprent.FUNCTION_PPI || fexpr.getFuncType() == FunctionExprent.FUNCTION_MMI) {
//// if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) {
//// setChangedVars.add(new VarVersionPair((VarExprent)fexpr.getLstOperands().get(0)));
//// isTempAssignment = true;
//// }
//// }
// }
//
// if(!isTempAssignment) {
// Set<VarVersionPair> setVars = remote.getAllVariables();
// if(setVars.contains(leftPaar)) {
// return false;
// } else {
// setChangedVars.addAll(setVars);
// }
// }
// }
// }
// }
// }
//
// return false;
// }
// propagate (var = new X) forward to the <init> invokation
private static boolean isConstructorInvocationRemote(List<Exprent> list, int index) {
Exprent current = list.get(index);
if (current.type == Exprent.EXPRENT_ASSIGNMENT) {
@ -684,7 +537,6 @@ public class SimplifyExprentsHelper {
}
private static Exprent isLambda(Exprent exprent, StructClass cl) {
List<Exprent> lst = exprent.getAllExprents();
for (Exprent expr : lst) {
Exprent ret = isLambda(expr, cl);
@ -697,12 +549,10 @@ public class SimplifyExprentsHelper {
InvocationExprent in = (InvocationExprent)exprent;
if (in.getInvocationTyp() == InvocationExprent.INVOKE_DYNAMIC) {
String lambda_class_name = cl.qualifiedName + in.getInvokeDynamicClassSuffix();
ClassNode lambda_class = DecompilerContext.getClassProcessor().getMapRootClasses().get(lambda_class_name);
if (lambda_class != null) { // real lambda class found, replace invocation with an anonymous class
NewExprent newexp = new NewExprent(new VarType(lambda_class_name, true), null, 0, in.bytecode);
newexp.setConstructor(in);
// note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invokation
@ -717,9 +567,7 @@ public class SimplifyExprentsHelper {
return null;
}
private static Exprent isSimpleConstructorInvocation(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents();
for (Exprent expr : lst) {
Exprent ret = isSimpleConstructorInvocation(expr);
@ -741,9 +589,7 @@ public class SimplifyExprentsHelper {
return null;
}
private static boolean buildIff(Statement stat, SSAConstructorSparseEx ssa) {
if (stat.type == Statement.TYPE_IF && stat.getExprents() == null) {
IfStatement stif = (IfStatement)stat;
@ -771,7 +617,6 @@ public class SimplifyExprentsHelper {
VarExprent elsevar = (VarExprent)elseas.getLeft();
if (ifvar.getIndex() == elsevar.getIndex() && ifvar.isStack()) { // ifvar.getIndex() >= VarExprent.STACK_BASE) {
boolean found = false;
for (Entry<VarVersionPair, FastSparseSet<Integer>> ent : ssa.getPhi().entrySet()) {
@ -886,10 +731,8 @@ public class SimplifyExprentsHelper {
}
private static boolean collapseInlinedClass14(Statement stat) {
boolean ret = class14Builder.match(stat);
if(ret) {
if (ret) {
String class_name = (String)class14Builder.getVariableValue("$classname$");
AssignmentExprent assfirst = (AssignmentExprent)class14Builder.getVariableValue("$assignfield$");
FieldExprent fieldexpr = (FieldExprent)class14Builder.getVariableValue("$field$");
@ -906,10 +749,8 @@ public class SimplifyExprentsHelper {
if (wrapper != null) {
wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fieldexpr.getName(), fieldexpr.getDescriptor().descriptorString));
}
}
return ret;
}
}
}

@ -222,7 +222,7 @@ public class StackVarsProcessor {
}
private static Exprent isReplaceableVar(Exprent exprent, HashMap<VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) {
private static Exprent isReplaceableVar(Exprent exprent, HashMap<VarVersionPair, Exprent> mapVarValues) {
Exprent dest = null;
@ -473,7 +473,7 @@ public class StackVarsProcessor {
}
}
Exprent dest = isReplaceableVar(exprent, mapVarValues, ssau);
Exprent dest = isReplaceableVar(exprent, mapVarValues);
if (dest != null) {
return new Object[]{dest, true, true};
}

@ -7,9 +7,6 @@ import java.util.ArrayList;
import java.util.List;
public class StatEdge {
public static final int TYPE_ALL = 0xFF;
public static final int TYPE_REGULAR = 1;
public static final int TYPE_EXCEPTION = 2;
public static final int TYPE_BREAK = 4;

@ -4,80 +4,19 @@ package org.jetbrains.java.decompiler.modules.decompiler;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
// --------------------------------------------------------------------
// Algorithm
// --------------------------------------------------------------------
// DFS(G)
// {
// make a new vertex x with edges x->v for all v
// initialize a counter N to zero
// initialize list L to empty
// build directed tree T, initially a single vertex {x}
// visit(x)
// }
//
// visit(p)
// {
// add p to L
// dfsnum(p) = N
// increment N
// low(p) = dfsnum(p)
// for each edge p->q
// if q is not already in T
// {
// add p->q to T
// visit(q)
// low(p) = min(low(p), low(q))
// } else low(p) = min(low(p), dfsnum(q))
//
// if low(p)=dfsnum(p)
// {
// output "component:"
// repeat
// remove last element v from L
// output v
// remove v from G
// until v=p
// }
// }
// --------------------------------------------------------------------
import java.util.*;
public class StrongConnectivityHelper {
private final List<List<Statement>> components;
private final Set<Statement> setProcessed;
private ListStack<Statement> lstack;
private int ncounter;
private HashSet<Statement> tset;
private HashMap<Statement, Integer> dfsnummap;
private HashMap<Statement, Integer> lowmap;
private List<List<Statement>> components;
private HashSet<Statement> setProcessed;
// *****************************************************************************
// constructors
// *****************************************************************************
public StrongConnectivityHelper() {
}
private Set<Statement> tset;
private Map<Statement, Integer> dfsnummap;
private Map<Statement, Integer> lowmap;
public StrongConnectivityHelper(Statement stat) {
findComponents(stat);
}
// *****************************************************************************
// public methods
// *****************************************************************************
public List<List<Statement>> findComponents(Statement stat) {
components = new ArrayList<>();
setProcessed = new HashSet<>();
@ -95,38 +34,8 @@ public class StrongConnectivityHelper {
visitTree(st);
}
}
return components;
}
public static boolean isExitComponent(List<Statement> lst) {
HashSet<Statement> set = new HashSet<>();
for (Statement stat : lst) {
set.addAll(stat.getNeighbours(StatEdge.TYPE_REGULAR, Statement.DIRECTION_FORWARD));
}
set.removeAll(lst);
return (set.size() == 0);
}
public static List<Statement> getExitReps(List<List<Statement>> lst) {
List<Statement> res = new ArrayList<>();
for (List<Statement> comp : lst) {
if (isExitComponent(comp)) {
res.add(comp.get(0));
}
}
return res;
}
// *****************************************************************************
// private methods
// *****************************************************************************
private void visitTree(Statement stat) {
lstack = new ListStack<>();
ncounter = 0;
@ -141,7 +50,6 @@ public class StrongConnectivityHelper {
}
private void visit(Statement stat) {
lstack.push(stat);
dfsnummap.put(stat, ncounter);
lowmap.put(stat, ncounter);
@ -150,8 +58,7 @@ public class StrongConnectivityHelper {
List<Statement> lstSuccs = stat.getNeighbours(StatEdge.TYPE_REGULAR, Statement.DIRECTION_FORWARD); // TODO: set?
lstSuccs.removeAll(setProcessed);
for (int i = 0; i < lstSuccs.size(); i++) {
Statement succ = lstSuccs.get(i);
for (Statement succ : lstSuccs) {
int secvalue;
if (tset.contains(succ)) {
@ -178,16 +85,29 @@ public class StrongConnectivityHelper {
}
}
public static boolean isExitComponent(List<Statement> lst) {
Set<Statement> set = new HashSet<>();
for (Statement stat : lst) {
set.addAll(stat.getNeighbours(StatEdge.TYPE_REGULAR, Statement.DIRECTION_FORWARD));
}
set.removeAll(lst);
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
return (set.size() == 0);
}
public List<List<Statement>> getComponents() {
return components;
public static List<Statement> getExitReps(List<List<Statement>> lst) {
List<Statement> res = new ArrayList<>();
for (List<Statement> comp : lst) {
if (isExitComponent(comp)) {
res.add(comp.get(0));
}
}
return res;
}
public void setComponents(List<List<Statement>> components) {
this.components = components;
public List<List<Statement>> getComponents() {
return components;
}
}
}

@ -7,7 +7,6 @@ import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.stats.SwitchStatement;
import java.util.ArrayList;
@ -29,18 +28,15 @@ public class SwitchHelper {
if (classNode != null) {
MethodWrapper wrapper = classNode.getWrapper().getMethodWrapper(CodeConstants.CLINIT_NAME, "()V");
if (wrapper != null && wrapper.root != null) {
wrapper.getOrBuildGraph().iterateExprents(new DirectGraph.ExprentIterator() {
@Override
public int processExprent(Exprent exprent) {
if (exprent instanceof AssignmentExprent) {
AssignmentExprent assignment = (AssignmentExprent)exprent;
Exprent left = assignment.getLeft();
if (left.type == Exprent.EXPRENT_ARRAY && ((ArrayExprent)left).getArray().equals(arrayField)) {
mapping.put(assignment.getRight(), ((InvocationExprent)((ArrayExprent)left).getIndex()).getInstance());
}
wrapper.getOrBuildGraph().iterateExprents(exprent -> {
if (exprent instanceof AssignmentExprent) {
AssignmentExprent assignment = (AssignmentExprent)exprent;
Exprent left = assignment.getLeft();
if (left.type == Exprent.EXPRENT_ARRAY && ((ArrayExprent)left).getArray().equals(arrayField)) {
mapping.put(assignment.getRight(), ((InvocationExprent)((ArrayExprent)left).getIndex()).getInstance());
}
return 0;
}
return 0;
});
}
}

@ -31,7 +31,6 @@ public class DominatorTreeExceptionFilter {
}
public void initialize() {
domEngine = new DominatorEngine(statement);
domEngine.initialize();
@ -47,12 +46,11 @@ public class DominatorTreeExceptionFilter {
}
public boolean acceptStatementPair(Integer head, Integer exit) {
Map<Integer, Integer> filter = mapExceptionRangeUniqueExit.get(head);
for (Entry<Integer, Integer> entry : filter.entrySet()) {
if (!head.equals(mapExceptionDoms.get(entry.getKey()))) {
Integer filterExit = entry.getValue();
if (filterExit.intValue() == -1 || !filterExit.equals(exit)) {
if (filterExit == -1 || !filterExit.equals(exit)) {
return false;
}
}
@ -62,19 +60,13 @@ public class DominatorTreeExceptionFilter {
}
private void buildDominatorTree() {
VBStyleCollection<Integer, Integer> orderedIDoms = domEngine.getOrderedIDoms();
List<Integer> lstKeys = orderedIDoms.getLstKeys();
for (int index = lstKeys.size() - 1; index >= 0; index--) {
Integer key = lstKeys.get(index);
Integer idom = orderedIDoms.get(index);
Set<Integer> set = mapTreeBranches.get(idom);
if (set == null) {
mapTreeBranches.put(idom, set = new HashSet<>());
}
set.add(key);
mapTreeBranches.computeIfAbsent(idom, k -> new HashSet<>()).add(key);
}
Integer firstid = statement.getFirst().id;
@ -82,7 +74,6 @@ public class DominatorTreeExceptionFilter {
}
private void buildExceptionRanges() {
for (Statement stat : statement.getStats()) {
List<Statement> lstPreds = stat.getNeighbours(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_BACKWARD);
if (!lstPreds.isEmpty()) {
@ -101,7 +92,6 @@ public class DominatorTreeExceptionFilter {
}
private Map<Integer, Integer> buildExceptionDoms(Integer id) {
Map<Integer, Integer> map = new HashMap<>();
Set<Integer> children = mapTreeBranches.get(id);
@ -123,21 +113,16 @@ public class DominatorTreeExceptionFilter {
return map;
}
private void buildFilter(Integer id) {
Map<Integer, Integer> map = new HashMap<>();
Set<Integer> children = mapTreeBranches.get(id);
if (children != null) {
for (Integer childid : children) {
buildFilter(childid);
Map<Integer, Integer> mapChild = mapExceptionRangeUniqueExit.get(childid);
for (Entry<Integer, Set<Integer>> entry : mapExceptionRanges.entrySet()) {
Integer handler = entry.getKey();
Set<Integer> range = entry.getValue();
@ -167,4 +152,4 @@ public class DominatorTreeExceptionFilter {
public DominatorEngine getDomEngine() {
return domEngine;
}
}
}

@ -117,12 +117,8 @@ public class FastExtendedPostdominanceHelper {
}
}
private void filterOnExceptionRanges(DominatorTreeExceptionFilter filter) {
for (Integer head : new HashSet<>(mapExtPostdominators.keySet())) {
FastFixedSet<Integer> set = mapExtPostdominators.get(head);
for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) {
if (!filter.acceptStatementPair(head, it.next())) {
@ -135,64 +131,59 @@ public class FastExtendedPostdominanceHelper {
}
}
private void removeErroneousNodes() {
mapSupportPoints = new HashMap<>();
calcReachabilitySuppPoints(StatEdge.TYPE_REGULAR);
iterateReachability(new IReachabilityAction() {
public boolean action(Statement node, HashMap<Integer, FastFixedSet<Integer>> mapSets) {
Integer nodeid = node.id;
iterateReachability((node, mapSets) -> {
Integer nodeid = node.id;
FastFixedSet<Integer> setReachability = mapSets.get(nodeid);
List<FastFixedSet<Integer>> lstPredSets = new ArrayList<>();
FastFixedSet<Integer> setReachability = mapSets.get(nodeid);
List<FastFixedSet<Integer>> lstPredSets = new ArrayList<>();
for (StatEdge prededge : node.getPredecessorEdges(StatEdge.TYPE_REGULAR)) {
FastFixedSet<Integer> setPred = mapSets.get(prededge.getSource().id);
if (setPred == null) {
setPred = mapSupportPoints.get(prededge.getSource().id);
}
// setPred cannot be empty as it is a reachability set
lstPredSets.add(setPred);
for (StatEdge prededge : node.getPredecessorEdges(StatEdge.TYPE_REGULAR)) {
FastFixedSet<Integer> setPred = mapSets.get(prededge.getSource().id);
if (setPred == null) {
setPred = mapSupportPoints.get(prededge.getSource().id);
}
for (Integer id : setReachability) {
// setPred cannot be empty as it is a reachability set
lstPredSets.add(setPred);
}
FastFixedSet<Integer> setReachabilityCopy = setReachability.getCopy();
for (Integer id : setReachability) {
FastFixedSet<Integer> setIntersection = factory.spawnEmptySet();
boolean isIntersectionInitialized = false;
FastFixedSet<Integer> setReachabilityCopy = setReachability.getCopy();
for (FastFixedSet<Integer> predset : lstPredSets) {
if (predset.contains(id)) {
if (!isIntersectionInitialized) {
setIntersection.union(predset);
isIntersectionInitialized = true;
}
else {
setIntersection.intersection(predset);
}
}
}
FastFixedSet<Integer> setIntersection = factory.spawnEmptySet();
boolean isIntersectionInitialized = false;
if (nodeid != id.intValue()) {
setIntersection.add(nodeid);
}
else {
setIntersection.remove(nodeid);
for (FastFixedSet<Integer> predset : lstPredSets) {
if (predset.contains(id)) {
if (!isIntersectionInitialized) {
setIntersection.union(predset);
isIntersectionInitialized = true;
}
else {
setIntersection.intersection(predset);
}
}
}
setReachabilityCopy.complement(setIntersection);
mapExtPostdominators.get(id).complement(setReachabilityCopy);
if (nodeid != id.intValue()) {
setIntersection.add(nodeid);
}
else {
setIntersection.remove(nodeid);
}
setReachabilityCopy.complement(setIntersection);
return false;
mapExtPostdominators.get(id).complement(setReachabilityCopy);
}
return false;
}, StatEdge.TYPE_REGULAR);
// exception handlers cannot be postdominator nodes
@ -215,9 +206,7 @@ public class FastExtendedPostdominanceHelper {
}
}
private void calcDefaultReachableSets() {
int edgetype = StatEdge.TYPE_REGULAR | StatEdge.TYPE_EXCEPTION;
calcReachabilitySuppPoints(edgetype);
@ -226,50 +215,40 @@ public class FastExtendedPostdominanceHelper {
mapExtPostdominators.put(stat.id, factory.spawnEmptySet());
}
iterateReachability(new IReachabilityAction() {
public boolean action(Statement node, HashMap<Integer, FastFixedSet<Integer>> mapSets) {
iterateReachability((node, mapSets) -> {
Integer nodeid = node.id;
FastFixedSet<Integer> setReachability = mapSets.get(nodeid);
Integer nodeid = node.id;
FastFixedSet<Integer> setReachability = mapSets.get(nodeid);
for (Integer id : setReachability) {
mapExtPostdominators.get(id).add(nodeid);
}
return false;
for (Integer id : setReachability) {
mapExtPostdominators.get(id).add(nodeid);
}
return false;
}, edgetype);
}
private void calcReachabilitySuppPoints(final int edgetype) {
iterateReachability(new IReachabilityAction() {
public boolean action(Statement node, HashMap<Integer, FastFixedSet<Integer>> mapSets) {
// consider to be a support point
for (StatEdge sucedge : node.getAllSuccessorEdges()) {
if ((sucedge.getType() & edgetype) != 0) {
if (mapSets.containsKey(sucedge.getDestination().id)) {
FastFixedSet<Integer> setReachability = mapSets.get(node.id);
if (!InterpreterUtil.equalObjects(setReachability, mapSupportPoints.get(node.id))) {
mapSupportPoints.put(node.id, setReachability);
return true;
}
iterateReachability((node, mapSets) -> {
// consider to be a support point
for (StatEdge sucedge : node.getAllSuccessorEdges()) {
if ((sucedge.getType() & edgetype) != 0) {
if (mapSets.containsKey(sucedge.getDestination().id)) {
FastFixedSet<Integer> setReachability = mapSets.get(node.id);
if (!InterpreterUtil.equalObjects(setReachability, mapSupportPoints.get(node.id))) {
mapSupportPoints.put(node.id, setReachability);
return true;
}
}
}
return false;
}
return false;
}, edgetype);
}
private void iterateReachability(IReachabilityAction action, int edgetype) {
while (true) {
boolean iterate = false;
HashMap<Integer, FastFixedSet<Integer>> mapSets = new HashMap<>();

@ -112,10 +112,6 @@ public class GenericDominatorEngine {
}
}
public VBStyleCollection<IGraphNode, IGraphNode> getOrderedIDoms() {
return colOrderedIDoms;
}
public boolean isDominator(IGraphNode node, IGraphNode dom) {
while (!node.equals(dom)) {

@ -216,7 +216,7 @@ public class ExceptionDeobfuscator {
}
public Set<? extends IGraphNode> getRoots() {
return new HashSet<>(Arrays.asList(new IGraphNode[]{graph.getFirst()}));
return new HashSet<>(Collections.singletonList(graph.getFirst()));
}
});
@ -279,16 +279,10 @@ public class ExceptionDeobfuscator {
return lstRes;
}
public static boolean hasObfuscatedExceptions(ControlFlowGraph graph) {
Map<BasicBlock, Set<BasicBlock>> mapRanges = new HashMap<>();
for (ExceptionRangeCFG range : graph.getExceptions()) {
Set<BasicBlock> set = mapRanges.get(range.getHandler());
if (set == null) {
mapRanges.put(range.getHandler(), set = new HashSet<>());
}
set.addAll(range.getProtectedRange());
mapRanges.computeIfAbsent(range.getHandler(), k -> new HashSet<>()).addAll(range.getProtectedRange());
}
for (Entry<BasicBlock, Set<BasicBlock>> ent : mapRanges.entrySet()) {
@ -312,4 +306,4 @@ public class ExceptionDeobfuscator {
return false;
}
}
}

@ -176,10 +176,6 @@ public class AssignmentExprent extends Exprent {
return left;
}
public void setLeft(Exprent left) {
this.left = left;
}
public Exprent getRight() {
return right;
}

@ -37,7 +37,7 @@ public class ConstExprent extends Exprent {
private final boolean boolPermitted;
public ConstExprent(int val, boolean boolPermitted, Set<Integer> bytecodeOffsets) {
this(guessType(val, boolPermitted), Integer.valueOf(val), boolPermitted, bytecodeOffsets);
this(guessType(val, boolPermitted), val, boolPermitted, bytecodeOffsets);
}
public ConstExprent(VarType constType, Object value, Set<Integer> bytecodeOffsets) {
@ -112,7 +112,7 @@ public class ConstExprent extends Exprent {
switch (constType.type) {
case CodeConstants.TYPE_BOOLEAN:
return new TextBuffer(Boolean.toString(((Integer)value).intValue() != 0));
return new TextBuffer(Boolean.toString((Integer)value != 0));
case CodeConstants.TYPE_CHAR:
Integer val = (Integer)value;
@ -133,7 +133,7 @@ public class ConstExprent extends Exprent {
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_SHORTCHAR:
case CodeConstants.TYPE_INT:
int intVal = ((Integer)value).intValue();
int intVal = (Integer)value;
if (!literal) {
if (intVal == Integer.MAX_VALUE) {
return new FieldExprent("MAX_VALUE", "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
@ -145,7 +145,7 @@ public class ConstExprent extends Exprent {
return new TextBuffer(value.toString());
case CodeConstants.TYPE_LONG:
long longVal = ((Long)value).longValue();
long longVal = (Long)value;
if (!literal) {
if (longVal == Long.MAX_VALUE) {
return new FieldExprent("MAX_VALUE", "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
@ -157,7 +157,7 @@ public class ConstExprent extends Exprent {
return new TextBuffer(value.toString()).append('L');
case CodeConstants.TYPE_FLOAT:
float floatVal = ((Float)value).floatValue();
float floatVal = (Float)value;
if (!literal) {
if (Float.isNaN(floatVal)) {
return new FieldExprent("NaN", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
@ -187,7 +187,7 @@ public class ConstExprent extends Exprent {
return new TextBuffer(value.toString()).append('F');
case CodeConstants.TYPE_DOUBLE:
double doubleVal = ((Double)value).doubleValue();
double doubleVal = (Double)value;
if (!literal) {
if (Double.isNaN(doubleVal)) {
return new FieldExprent("NaN", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
@ -306,7 +306,7 @@ public class ConstExprent extends Exprent {
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_SHORTCHAR:
case CodeConstants.TYPE_INT:
int value = ((Integer)this.value).intValue();
int value = (Integer)this.value;
return value == 0 || (DecompilerContext.getOption(IFernflowerPreferences.BOOLEAN_TRUE_ONE) && value == 1);
}
@ -322,7 +322,7 @@ public class ConstExprent extends Exprent {
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_SHORTCHAR:
case CodeConstants.TYPE_INT:
return ((Integer)value).intValue() == 1;
return (Integer)value == 1;
case CodeConstants.TYPE_LONG:
return ((Long)value).intValue() == 1;
case CodeConstants.TYPE_DOUBLE:
@ -337,13 +337,13 @@ public class ConstExprent extends Exprent {
public static ConstExprent getZeroConstant(int type) {
switch (type) {
case CodeConstants.TYPE_INT:
return new ConstExprent(VarType.VARTYPE_INT, Integer.valueOf(0), null);
return new ConstExprent(VarType.VARTYPE_INT, 0, null);
case CodeConstants.TYPE_LONG:
return new ConstExprent(VarType.VARTYPE_LONG, Long.valueOf(0), null);
return new ConstExprent(VarType.VARTYPE_LONG, 0L, null);
case CodeConstants.TYPE_DOUBLE:
return new ConstExprent(VarType.VARTYPE_DOUBLE, Double.valueOf(0), null);
return new ConstExprent(VarType.VARTYPE_DOUBLE, 0d, null);
case CodeConstants.TYPE_FLOAT:
return new ConstExprent(VarType.VARTYPE_FLOAT, Float.valueOf(0), null);
return new ConstExprent(VarType.VARTYPE_FLOAT, 0f, null);
}
throw new RuntimeException("Invalid argument: " + type);
@ -383,7 +383,7 @@ public class ConstExprent extends Exprent {
}
public int getIntValue() {
return ((Integer)value).intValue();
return (Integer)value;
}
public boolean isBoolPermitted() {

@ -144,20 +144,13 @@ public class ExitExprent extends Exprent {
// IMatchable implementation
// *****************************************************************************
@Override
public boolean match(MatchNode matchNode, MatchEngine engine) {
if(!super.match(matchNode, engine)) {
if (!super.match(matchNode, engine)) {
return false;
}
Integer type = (Integer)matchNode.getRuleValue(MatchProperties.EXPRENT_EXITTYPE);
if(type != null) {
if(this.exitType != type.intValue()) {
return false;
}
}
return true;
return type == null || this.exitType == type;
}
}
}

@ -143,8 +143,7 @@ public class Exprent implements IMatchable {
String position = (String)matchNode.getRuleValue(MatchProperties.EXPRENT_POSITION);
if (position != null) {
if (position.matches("-?\\d+")) {
return lstAllExprents
.get((lstAllExprents.size() + Integer.parseInt(position)) % lstAllExprents.size()); // care for negative positions
return lstAllExprents.get((lstAllExprents.size() + Integer.parseInt(position)) % lstAllExprents.size()); // care for negative positions
}
}
else if (index < lstAllExprents.size()) { // use 'index' parameter
@ -162,7 +161,7 @@ public class Exprent implements IMatchable {
for (Entry<MatchProperties, RuleValue> rule : matchNode.getRules().entrySet()) {
MatchProperties key = rule.getKey();
if (key == MatchProperties.EXPRENT_TYPE && this.type != ((Integer)rule.getValue().value).intValue()) {
if (key == MatchProperties.EXPRENT_TYPE && this.type != (Integer)rule.getValue().value) {
return false;
}
if (key == MatchProperties.EXPRENT_RET && !engine.checkAndSetVariableValue((String)rule.getValue().value, this)) {

@ -187,22 +187,19 @@ public class FieldExprent extends Exprent {
// IMatchable implementation
// *****************************************************************************
@Override
public boolean match(MatchNode matchNode, MatchEngine engine) {
if(!super.match(matchNode, engine)) {
if (!super.match(matchNode, engine)) {
return false;
}
RuleValue rule = matchNode.getRules().get(MatchProperties.EXPRENT_FIELD_NAME);
if(rule != null) {
if(rule.isVariable()) {
if(!engine.checkAndSetVariableValue((String)rule.value, this.name)) {
return false;
}
} else {
if(!rule.value.equals(this.name)) {
return false;
}
if (rule != null) {
if (rule.isVariable()) {
return engine.checkAndSetVariableValue((String)rule.value, this.name);
}
else {
return rule.value.equals(this.name);
}
}

@ -399,8 +399,7 @@ public class FunctionExprent extends Exprent {
@Override
public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<>(lstOperands);
return lst;
return new ArrayList<>(lstOperands);
}
@Override
@ -609,20 +608,13 @@ public class FunctionExprent extends Exprent {
// IMatchable implementation
// *****************************************************************************
@Override
public boolean match(MatchNode matchNode, MatchEngine engine) {
if(!super.match(matchNode, engine)) {
if (!super.match(matchNode, engine)) {
return false;
}
Integer type = (Integer)matchNode.getRuleValue(MatchProperties.EXPRENT_FUNCTYPE);
if(type != null) {
if(this.funcType != type.intValue()) {
return false;
}
}
return true;
return type == null || this.funcType == type;
}
}
}

@ -30,10 +30,9 @@ public class IfExprent extends Exprent {
public static final int IF_ACMPEQ = 14;
public static final int IF_ACMPNE = 15;
public static final int IF_CAND = 16;
public static final int IF_COR = 17;
public static final int IF_NOT = 18;
//public static final int IF_CAND = 16;
//public static final int IF_COR = 17;
//public static final int IF_NOT = 18;
public static final int IF_VALUE = 19;
private static final int[] FUNC_TYPES = {
@ -132,4 +131,4 @@ public class IfExprent extends Exprent {
public void setCondition(Exprent condition) {
this.condition = condition;
}
}
}

@ -37,7 +37,7 @@ public class VarExprent extends Exprent {
private int index;
private VarType varType;
private boolean definition = false;
private VarProcessor processor;
private final VarProcessor processor;
private final int visibleOffset;
private int version = 0;
private boolean classDef = false;
@ -219,10 +219,6 @@ public class VarExprent extends Exprent {
return processor;
}
public void setProcessor(VarProcessor processor) {
this.processor = processor;
}
public int getVersion() {
return version;
}
@ -251,26 +247,22 @@ public class VarExprent extends Exprent {
// IMatchable implementation
// *****************************************************************************
@Override
public boolean match(MatchNode matchNode, MatchEngine engine) {
if(!super.match(matchNode, engine)) {
if (!super.match(matchNode, engine)) {
return false;
}
RuleValue rule = matchNode.getRules().get(MatchProperties.EXPRENT_VAR_INDEX);
if(rule != null) {
if(rule.isVariable()) {
if(!engine.checkAndSetVariableValue((String)rule.value, this.index)) {
return false;
}
} else {
if(this.index != Integer.valueOf((String)rule.value).intValue()) {
return false;
}
if (rule != null) {
if (rule.isVariable()) {
return engine.checkAndSetVariableValue((String)rule.value, this.index);
}
else {
return this.index == Integer.valueOf((String)rule.value);
}
}
return true;
}
}
}

@ -398,21 +398,19 @@ public class FlattenStatementsHelper {
}
if (finallyShortRangeSource != null) {
boolean isContinueEdge = (edgetype == StatEdge.TYPE_CONTINUE);
List<String[]> lst = mapShortRangeFinallyPathIds.get(sourcenode.id);
if (lst == null) {
mapShortRangeFinallyPathIds.put(sourcenode.id, lst = new ArrayList<>());
}
lst.add(new String[]{finallyShortRangeSource.id, destination.id.toString(), finallyShortRangeEntry.id.toString(),
isFinallyMonitorExceptionPath ? "1" : null, isContinueEdge ? "1" : null});
mapShortRangeFinallyPathIds.computeIfAbsent(sourcenode.id, k -> new ArrayList<>()).add(new String[]{
finallyShortRangeSource.id,
destination.id.toString(),
finallyShortRangeEntry.id.toString(),
isFinallyMonitorExceptionPath ? "1" : null,
isContinueEdge ? "1" : null});
lst = mapLongRangeFinallyPathIds.get(sourcenode.id);
if (lst == null) {
mapLongRangeFinallyPathIds.put(sourcenode.id, lst = new ArrayList<>());
}
lst.add(new String[]{finallyLongRangeSource.id, destination.id.toString(), finallyLongRangeEntry.id.toString(),
mapLongRangeFinallyPathIds.computeIfAbsent(sourcenode.id, k -> new ArrayList<>()).add(new String[]{
finallyLongRangeSource.id,
destination.id.toString(),
finallyLongRangeEntry.id.toString(),
isContinueEdge ? "1" : null});
}
}

@ -19,7 +19,6 @@ import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.SFormsFastMapDirect;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -45,8 +44,6 @@ public class SSAConstructorSparseEx {
// var, version
private final HashMap<Integer, Integer> lastversion = new HashMap<>();
private final List<VarVersionPair> startVars = new ArrayList<>();
// set factory
private FastSparseSetFactory<Integer> factory;
@ -246,7 +243,7 @@ public class SSAConstructorSparseEx {
if (cardinality == 1) { // == 1
// set version
Integer it = vers.iterator().next();
vardest.setVersion(it.intValue());
vardest.setVersion(it);
}
else if (cardinality == 2) { // size > 1
Integer current_vers = vardest.getVersion();
@ -358,7 +355,7 @@ public class SSAConstructorSparseEx {
}
// false path?
boolean isFalsePath = true;
boolean isFalsePath;
if (recFinally) {
isFalsePath = !finwrap.destination.equals(nodeid);
@ -463,7 +460,6 @@ public class SSAConstructorSparseEx {
setCurrentVar(map, varindex, version);
extraVarVersions.put(dgraph.nodes.getWithKey(flatthelper.getMapDestinationNodes().get(stat.getStats().get(i).id)[0]).id, map);
startVars.add(new VarVersionPair(varindex, version));
}
}
@ -487,7 +483,6 @@ public class SSAConstructorSparseEx {
FastSparseSet<Integer> set = factory.spawnEmptySet();
set.add(version);
map.put(varindex, set);
startVars.add(new VarVersionPair(varindex, version));
if (thisvar) {
if (i == 0) {
@ -508,8 +503,4 @@ public class SSAConstructorSparseEx {
public HashMap<VarVersionPair, FastSparseSet<Integer>> getPhi() {
return phi;
}
public List<VarVersionPair> getStartVars() {
return startVars;
}
}

@ -41,9 +41,6 @@ public class SSAUConstructorSparseEx {
private final HashMap<String, SFormsFastMapDirect> extraVarVersions = new HashMap<>();
//private HashMap<String, HashMap<Integer, FastSet<Integer>>> extraVarVersions = new HashMap<String, HashMap<Integer, FastSet<Integer>>>();
// (var, version), version
private final HashMap<VarVersionPair, HashSet<Integer>> phi = new HashMap<>();
// var, version
private final HashMap<Integer, Integer> lastversion = new HashMap<>();
@ -344,7 +341,7 @@ public class SSAUConstructorSparseEx {
if (calcLiveVars) {
varMapToGraph(varpaar, varmap);
}
setCurrentVar(varmap, varindex.intValue(), var.getVersion());
setCurrentVar(varmap, varindex, var.getVersion());
}
}
}
@ -359,7 +356,7 @@ public class SSAUConstructorSparseEx {
int cardinality = vers.getCardinality();
if (cardinality == 1) { // size == 1
if (current_vers.intValue() != 0) {
if (current_vers != 0) {
if (calcLiveVars) {
varMapToGraph(new VarVersionPair(varindex, current_vers), varmap);
}
@ -384,7 +381,7 @@ public class SSAUConstructorSparseEx {
}
else if (cardinality == 2) { // size > 1
if (current_vers.intValue() != 0) {
if (current_vers != 0) {
if (calcLiveVars) {
varMapToGraph(new VarVersionPair(varindex, current_vers), varmap);
}
@ -449,7 +446,7 @@ public class SSAUConstructorSparseEx {
Integer tempver = getNextFreeVersion(phivar.var, stat);
VarVersionNode tempnode = new VarVersionNode(phivar.var, tempver.intValue());
VarVersionNode tempnode = new VarVersionNode(phivar.var, tempver);
colnodes.add(tempnode);
colpaars.add(new VarVersionPair(phivar.var, tempver.intValue()));
@ -468,9 +465,6 @@ public class SSAUConstructorSparseEx {
}
ssuversions.addNodes(colnodes, colpaars);
// update phi node
phi.put(phivar, phiVers);
}
private void varMapToGraph(VarVersionPair varpaar, SFormsFastMapDirect varmap) {
@ -583,7 +577,7 @@ public class SSAUConstructorSparseEx {
}
// false path?
boolean isFalsePath = true;
boolean isFalsePath;
if (recFinally) {
isFalsePath = !finwrap.destination.equals(nodeid);
@ -801,10 +795,6 @@ public class SSAUConstructorSparseEx {
return null;
}
public HashMap<VarVersionPair, HashSet<Integer>> getPhi() {
return phi;
}
public VarVersionsGraph getSsuversions() {
return ssuversions;
}

@ -12,10 +12,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.*;
public class CatchAllStatement extends Statement {
@ -64,13 +61,11 @@ public class CatchAllStatement extends Statement {
// *****************************************************************************
public static Statement isHead(Statement head) {
if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
return null;
}
HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
Set<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
if (setHandlers.size() != 1) {
return null;
}
@ -190,27 +185,18 @@ public class CatchAllStatement extends Statement {
return handler;
}
public void setHandler(Statement handler) {
this.handler = handler;
}
public boolean isFinally() {
return isFinally;
}
public void setFinally(boolean isFinally) {
this.isFinally = isFinally;
}
public VarExprent getMonitor() {
return monitor;
}
public void setMonitor(VarExprent monitor) {
this.monitor = monitor;
}
@ -218,4 +204,4 @@ public class CatchAllStatement extends Statement {
public List<VarExprent> getVars() {
return vars;
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save