Activated bytecode-to-source mapping for all instructions

master
Stiver 10 years ago
parent 46b494f26f
commit c975f11ecc
  1. 2
      src/org/jetbrains/java/decompiler/main/AssertProcessor.java
  2. 10
      src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
  3. 2
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  4. 2
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  5. 11
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java
  6. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java
  7. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java
  8. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java
  9. 113
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  10. 16
      src/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java
  11. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java
  12. 37
      src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java
  13. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java
  14. 9
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java
  15. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java
  16. 36
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
  17. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java
  18. 17
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java
  19. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java
  20. 22
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java
  21. 28
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java
  22. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  23. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java
  24. 18
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  25. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java
  26. 10
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java
  27. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
  28. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarTypeProcessor.java
  29. 24
      src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java

@ -174,7 +174,7 @@ public class AssertProcessor {
Exprent ascond = null, retcond = null; Exprent ascond = null, retcond = null;
if (exprres[0] != null) { if (exprres[0] != null) {
ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
Arrays.asList(new Exprent[]{(Exprent)exprres[0]})); Arrays.asList((Exprent)exprres[0]), throwError.bytecode);
retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond); retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond);
} }

@ -55,7 +55,7 @@ public class ClassReference14Processor {
bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN, bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN,
invfor, invfor,
VarType.VARTYPE_CLASS); VarType.VARTYPE_CLASS, null);
InvocationExprent constr = new InvocationExprent(); InvocationExprent constr = new InvocationExprent();
constr.setName("<init>"); constr.setName("<init>");
@ -65,7 +65,7 @@ public class ClassReference14Processor {
constr.setDescriptor(MethodDescriptor.parseDescriptor("()V")); constr.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
NewExprent newexpr = NewExprent newexpr =
new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<Exprent>()); new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<Exprent>(), null);
newexpr.setConstructor(constr); newexpr.setConstructor(constr);
InvocationExprent invcause = new InvocationExprent(); InvocationExprent invcause = new InvocationExprent();
@ -79,7 +79,7 @@ public class ClassReference14Processor {
handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW, handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW,
invcause, invcause,
null); null, null);
} }
@ -160,7 +160,7 @@ public class ClassReference14Processor {
String cl = isClass14Invocation(exprent, ent.getKey(), ent.getValue()); String cl = isClass14Invocation(exprent, ent.getKey(), ent.getValue());
if (cl != null) { if (cl != null) {
initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'))); initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'), exprent.bytecode));
setFound.add(ent.getKey()); setFound.add(ent.getKey());
} }
} }
@ -225,7 +225,7 @@ public class ClassReference14Processor {
for (Exprent expr : exprent.getAllExprents()) { for (Exprent expr : exprent.getAllExprents()) {
String cl = isClass14Invocation(expr, wrapper, meth); String cl = isClass14Invocation(expr, wrapper, meth);
if (cl != null) { if (cl != null) {
exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'))); exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'), expr.bytecode));
found = true; found = true;
res = true; res = true;
break; break;

@ -462,7 +462,7 @@ public class ClassWriter {
if (attr != null) { if (attr != null) {
PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex()); PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
buffer.append(" = "); buffer.append(" = ");
buffer.append(new ConstExprent(fieldType, constant.value).toJava(indent, tracer)); buffer.append(new ConstExprent(fieldType, constant.value, null).toJava(indent, tracer));
} }
} }

@ -287,7 +287,7 @@ public class ClassesProcessor {
mapper.addTotalOffset(total_offset_lines); mapper.addTotalOffset(total_offset_lines);
buffer.append(lineSeparator); buffer.append(lineSeparator);
mapper.dumpMapping(buffer); mapper.dumpMapping(buffer, true);
} }
} }
finally { finally {

@ -1,11 +1,11 @@
package org.jetbrains.java.decompiler.main.collectors; package org.jetbrains.java.decompiler.main.collectors;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
public class BytecodeSourceMapper { public class BytecodeSourceMapper {
private int offset_total; private int offset_total;
@ -37,7 +37,7 @@ public class BytecodeSourceMapper {
} }
} }
public void dumpMapping(TextBuffer buffer) { public void dumpMapping(TextBuffer buffer, boolean offsetsToHex) {
String lineSeparator = DecompilerContext.getNewLineSeparator(); String lineSeparator = DecompilerContext.getNewLineSeparator();
@ -56,7 +56,8 @@ public class BytecodeSourceMapper {
buffer.appendIndent(1).append("method " + method_entry.getKey() + "{" + lineSeparator); buffer.appendIndent(1).append("method " + method_entry.getKey() + "{" + lineSeparator);
for(Entry<Integer, Integer> line : method_mapping.entrySet()) { for(Entry<Integer, Integer> line : method_mapping.entrySet()) {
buffer.appendIndent(2).append(line.getKey().toString()).appendIndent(2).append((line.getValue() + offset_total) + lineSeparator); String strOffset = offsetsToHex ? Integer.toHexString(line.getKey()): line.getKey().toString();
buffer.appendIndent(2).append(strOffset).appendIndent(2).append((line.getValue() + offset_total) + lineSeparator);
} }
buffer.appendIndent(1).append("}").appendLineSeparator(); buffer.appendIndent(1).append("}").appendLineSeparator();
is_first_method = false; is_first_method = false;

@ -104,7 +104,7 @@ public class ConcatenationHelper {
} }
if (first2str == 0) { if (first2str == 0) {
lstOperands.add(0, new ConstExprent(VarType.VARTYPE_STRING, "")); lstOperands.add(0, new ConstExprent(VarType.VARTYPE_STRING, "", expr.bytecode));
} }
// remove redundant String.valueOf // remove redundant String.valueOf
@ -133,7 +133,7 @@ public class ConcatenationHelper {
List<Exprent> lstTmp = new ArrayList<Exprent>(); List<Exprent> lstTmp = new ArrayList<Exprent>();
lstTmp.add(func); lstTmp.add(func);
lstTmp.add(lstOperands.get(i)); lstTmp.add(lstOperands.get(i));
func = new FunctionExprent(FunctionExprent.FUNCTION_STRCONCAT, lstTmp); func = new FunctionExprent(FunctionExprent.FUNCTION_STRCONCAT, lstTmp, expr.bytecode);
} }
return func; return func;

@ -213,6 +213,12 @@ public class DomHelper {
RootStatement root = graphToStatement(graph); RootStatement root = graphToStatement(graph);
if (!processStatement(root, new HashMap<Integer, Set<Integer>>())) { if (!processStatement(root, new HashMap<Integer, Set<Integer>>())) {
// try {
// DotExporter.toDotFile(root.getFirst().getStats().get(13), new File("c:\\Temp\\stat1.dot"));
// } catch (Exception ex) {
// ex.printStackTrace();
// }
throw new RuntimeException("parsing failure!"); throw new RuntimeException("parsing failure!");
} }

@ -319,7 +319,7 @@ public class ExitHelper {
ExitExprent retexpr = new ExitExprent(ExitExprent.EXIT_RETURN, null, ExitExprent retexpr = new ExitExprent(ExitExprent.EXIT_RETURN, null,
((MethodDescriptor)DecompilerContext ((MethodDescriptor)DecompilerContext
.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret); .getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret, null);
// a changeable list needed // a changeable list needed
bstat.setExprents(new ArrayList<Exprent>(Arrays.asList(new Exprent[]{retexpr}))); bstat.setExprents(new ArrayList<Exprent>(Arrays.asList(new Exprent[]{retexpr})));

@ -15,6 +15,14 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler; package org.jetbrains.java.decompiler.modules.decompiler;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.Instruction; import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.code.InstructionSequence;
@ -22,12 +30,28 @@ import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.exps.ArrayExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.ExitExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.MonitorExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchExprent;
import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph; import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode; import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper; import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper; import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.stats.*; import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchAllStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.attr.StructBootstrapMethodsAttribute; import org.jetbrains.java.decompiler.struct.attr.StructBootstrapMethodsAttribute;
@ -40,8 +64,6 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
public class ExprProcessor implements CodeConstants { public class ExprProcessor implements CodeConstants {
public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>"; public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>";
@ -333,33 +355,34 @@ public class ExprProcessor implements CodeConstants {
Instruction instr = seq.getInstr(i); Instruction instr = seq.getInstr(i);
Integer bytecode_offset = block.getOldOffset(i); Integer bytecode_offset = block.getOldOffset(i);
Set<Integer> bytecode_offsets = bytecode_offset >= 0 ? new HashSet<Integer>(Arrays.asList(bytecode_offset)) : null;
switch (instr.opcode) { switch (instr.opcode) {
case opc_aconst_null: case opc_aconst_null:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_NULL, null)); pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_NULL, null, bytecode_offsets));
break; break;
case opc_bipush: case opc_bipush:
case opc_sipush: case opc_sipush:
pushEx(stack, exprlist, new ConstExprent(instr.getOperand(0), true)); pushEx(stack, exprlist, new ConstExprent(instr.getOperand(0), true, bytecode_offsets));
break; break;
case opc_lconst_0: case opc_lconst_0:
case opc_lconst_1: case opc_lconst_1:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, new Long(instr.opcode - opc_lconst_0))); pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, new Long(instr.opcode - opc_lconst_0), bytecode_offsets));
break; break;
case opc_fconst_0: case opc_fconst_0:
case opc_fconst_1: case opc_fconst_1:
case opc_fconst_2: case opc_fconst_2:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, new Float(instr.opcode - opc_fconst_0))); pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, new Float(instr.opcode - opc_fconst_0), bytecode_offsets));
break; break;
case opc_dconst_0: case opc_dconst_0:
case opc_dconst_1: case opc_dconst_1:
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(instr.opcode - opc_dconst_0))); pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(instr.opcode - opc_dconst_0), bytecode_offsets));
break; break;
case opc_ldc: case opc_ldc:
case opc_ldc_w: case opc_ldc_w:
case opc_ldc2_w: case opc_ldc2_w:
PrimitiveConstant cn = pool.getPrimitiveConstant(instr.getOperand(0)); PrimitiveConstant cn = pool.getPrimitiveConstant(instr.getOperand(0));
pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], cn.value)); pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], cn.value, bytecode_offsets));
break; break;
case opc_iload: case opc_iload:
case opc_lload: case opc_lload:
@ -387,7 +410,7 @@ public class ExprProcessor implements CodeConstants {
case opc_daload: case opc_daload:
vartype = VarType.VARTYPE_DOUBLE; vartype = VarType.VARTYPE_DOUBLE;
} }
pushEx(stack, exprlist, new ArrayExprent(arr, index, arrtypes[instr.opcode - opc_iaload]), vartype); pushEx(stack, exprlist, new ArrayExprent(arr, index, arrtypes[instr.opcode - opc_iaload], bytecode_offsets), vartype);
break; break;
case opc_istore: case opc_istore:
case opc_lstore: case opc_lstore:
@ -397,7 +420,7 @@ public class ExprProcessor implements CodeConstants {
Exprent top = stack.pop(); Exprent top = stack.pop();
int varindex = instr.getOperand(0); int varindex = instr.getOperand(0);
AssignmentExprent assign = AssignmentExprent assign =
new AssignmentExprent(new VarExprent(varindex, vartypes[instr.opcode - opc_istore], varProcessor), top); new AssignmentExprent(new VarExprent(varindex, vartypes[instr.opcode - opc_istore], varProcessor), top, bytecode_offsets);
exprlist.add(assign); exprlist.add(assign);
break; break;
case opc_iastore: case opc_iastore:
@ -412,7 +435,7 @@ public class ExprProcessor implements CodeConstants {
Exprent index_store = stack.pop(); Exprent index_store = stack.pop();
Exprent arr_store = stack.pop(); Exprent arr_store = stack.pop();
AssignmentExprent arrassign = AssignmentExprent arrassign =
new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore]), value); new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore], bytecode_offsets), value, bytecode_offsets);
exprlist.add(arrassign); exprlist.add(arrassign);
break; break;
case opc_iadd: case opc_iadd:
@ -435,7 +458,7 @@ public class ExprProcessor implements CodeConstants {
case opc_lrem: case opc_lrem:
case opc_frem: case opc_frem:
case opc_drem: case opc_drem:
pushEx(stack, exprlist, new FunctionExprent(func1[(instr.opcode - opc_iadd) / 4], stack)); pushEx(stack, exprlist, new FunctionExprent(func1[(instr.opcode - opc_iadd) / 4], stack, bytecode_offsets));
break; break;
case opc_ishl: case opc_ishl:
case opc_lshl: case opc_lshl:
@ -449,19 +472,20 @@ public class ExprProcessor implements CodeConstants {
case opc_lor: case opc_lor:
case opc_ixor: case opc_ixor:
case opc_lxor: case opc_lxor:
pushEx(stack, exprlist, new FunctionExprent(func2[(instr.opcode - opc_ishl) / 2], stack)); pushEx(stack, exprlist, new FunctionExprent(func2[(instr.opcode - opc_ishl) / 2], stack, bytecode_offsets));
break; break;
case opc_ineg: case opc_ineg:
case opc_lneg: case opc_lneg:
case opc_fneg: case opc_fneg:
case opc_dneg: case opc_dneg:
pushEx(stack, exprlist, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack)); pushEx(stack, exprlist, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack, bytecode_offsets));
break; break;
case opc_iinc: case opc_iinc:
VarExprent vevar = new VarExprent(instr.getOperand(0), VarType.VARTYPE_INT, varProcessor); VarExprent vevar = new VarExprent(instr.getOperand(0), VarType.VARTYPE_INT, varProcessor);
exprlist.add(new AssignmentExprent(vevar, new FunctionExprent( exprlist.add(new AssignmentExprent(vevar, new FunctionExprent(
instr.getOperand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays instr.getOperand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays
.asList(new Exprent[]{vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, new Integer(Math.abs(instr.getOperand(1))))})))); .asList(vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, Math.abs(instr.getOperand(1)), null)),
bytecode_offsets), bytecode_offsets));
break; break;
case opc_i2l: case opc_i2l:
case opc_i2f: case opc_i2f:
@ -478,14 +502,14 @@ public class ExprProcessor implements CodeConstants {
case opc_i2b: case opc_i2b:
case opc_i2c: case opc_i2c:
case opc_i2s: case opc_i2s:
pushEx(stack, exprlist, new FunctionExprent(func3[instr.opcode - opc_i2l], stack)); pushEx(stack, exprlist, new FunctionExprent(func3[instr.opcode - opc_i2l], stack, bytecode_offsets));
break; break;
case opc_lcmp: case opc_lcmp:
case opc_fcmpl: case opc_fcmpl:
case opc_fcmpg: case opc_fcmpg:
case opc_dcmpl: case opc_dcmpl:
case opc_dcmpg: case opc_dcmpg:
pushEx(stack, exprlist, new FunctionExprent(func4[instr.opcode - opc_lcmp], stack)); pushEx(stack, exprlist, new FunctionExprent(func4[instr.opcode - opc_lcmp], stack, bytecode_offsets));
break; break;
case opc_ifeq: case opc_ifeq:
case opc_ifne: case opc_ifne:
@ -493,7 +517,7 @@ public class ExprProcessor implements CodeConstants {
case opc_ifge: case opc_ifge:
case opc_ifgt: case opc_ifgt:
case opc_ifle: case opc_ifle:
exprlist.add(new IfExprent(negifs[func5[instr.opcode - opc_ifeq]], stack)); exprlist.add(new IfExprent(negifs[func5[instr.opcode - opc_ifeq]], stack, bytecode_offsets));
break; break;
case opc_if_icmpeq: case opc_if_icmpeq:
case opc_if_icmpne: case opc_if_icmpne:
@ -503,16 +527,16 @@ public class ExprProcessor implements CodeConstants {
case opc_if_icmple: case opc_if_icmple:
case opc_if_acmpeq: case opc_if_acmpeq:
case opc_if_acmpne: case opc_if_acmpne:
exprlist.add(new IfExprent(negifs[func6[instr.opcode - opc_if_icmpeq]], stack)); exprlist.add(new IfExprent(negifs[func6[instr.opcode - opc_if_icmpeq]], stack, bytecode_offsets));
break; break;
case opc_ifnull: case opc_ifnull:
case opc_ifnonnull: case opc_ifnonnull:
exprlist.add(new IfExprent(negifs[func7[instr.opcode - opc_ifnull]], stack)); exprlist.add(new IfExprent(negifs[func7[instr.opcode - opc_ifnull]], stack, bytecode_offsets));
break; break;
case opc_tableswitch: case opc_tableswitch:
case opc_lookupswitch: case opc_lookupswitch:
exprlist.add(new SwitchExprent(stack.pop())); exprlist.add(new SwitchExprent(stack.pop(), bytecode_offsets));
break; break;
case opc_ireturn: case opc_ireturn:
case opc_lreturn: case opc_lreturn:
case opc_freturn: case opc_freturn:
@ -525,29 +549,30 @@ public class ExprProcessor implements CodeConstants {
instr.opcode == opc_athrow instr.opcode == opc_athrow
? null ? null
: ((MethodDescriptor)DecompilerContext : ((MethodDescriptor)DecompilerContext
.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret)); .getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret,
break; bytecode_offsets));
break;
case opc_monitorenter: case opc_monitorenter:
case opc_monitorexit: case opc_monitorexit:
exprlist.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop())); exprlist.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop(), bytecode_offsets));
break; break;
case opc_checkcast: case opc_checkcast:
case opc_instanceof: case opc_instanceof:
stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true), null)); stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true), null, null));
case opc_arraylength: case opc_arraylength:
pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode).intValue(), stack)); pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode).intValue(), stack, bytecode_offsets));
break; break;
case opc_getstatic: case opc_getstatic:
case opc_getfield: case opc_getfield:
pushEx(stack, exprlist, pushEx(stack, exprlist,
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop())); new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop(), bytecode_offsets));
break; break;
case opc_putstatic: case opc_putstatic:
case opc_putfield: case opc_putfield:
Exprent valfield = stack.pop(); Exprent valfield = stack.pop();
Exprent exprfield = Exprent exprfield =
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop()); new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop(), bytecode_offsets);
exprlist.add(new AssignmentExprent(exprfield, valfield)); exprlist.add(new AssignmentExprent(exprfield, valfield, bytecode_offsets));
break; break;
case opc_invokevirtual: case opc_invokevirtual:
case opc_invokespecial: case opc_invokespecial:
@ -566,7 +591,7 @@ public class ExprProcessor implements CodeConstants {
dynamic_invokation_type = content_method_handle.index1; dynamic_invokation_type = content_method_handle.index1;
} }
InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type); InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type, bytecode_offsets);
if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) { if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) {
exprlist.add(exprinv); exprlist.add(exprinv);
} }
@ -583,10 +608,10 @@ public class ExprProcessor implements CodeConstants {
if (instr.opcode != opc_multianewarray) { if (instr.opcode != opc_multianewarray) {
arrtype.arraydim += arrdims; arrtype.arraydim += arrdims;
} }
pushEx(stack, exprlist, new NewExprent(arrtype, stack, arrdims)); pushEx(stack, exprlist, new NewExprent(arrtype, stack, arrdims, bytecode_offsets));
break; break;
case opc_newarray: case opc_newarray:
pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1)); pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1, bytecode_offsets));
break; break;
case opc_dup: case opc_dup:
pushEx(stack, exprlist, stack.getByOffset(-1).copy()); pushEx(stack, exprlist, stack.getByOffset(-1).copy());
@ -660,7 +685,7 @@ public class ExprProcessor implements CodeConstants {
VarExprent var = new VarExprent(varindex, vartype == null ? exprent.getExprType() : vartype, varProcessor); VarExprent var = new VarExprent(varindex, vartype == null ? exprent.getExprType() : vartype, varProcessor);
var.setStack(true); var.setStack(true);
exprlist.add(new AssignmentExprent(var, exprent)); exprlist.add(new AssignmentExprent(var, exprent, null));
stack.push(var.copy()); stack.push(var.copy());
} }
@ -674,14 +699,14 @@ public class ExprProcessor implements CodeConstants {
Exprent varex = stack.pop(); Exprent varex = stack.pop();
VarExprent varnew = new VarExprent(base + i + 1, varex.getExprType(), varProcessor); VarExprent varnew = new VarExprent(base + i + 1, varex.getExprType(), varProcessor);
varnew.setStack(true); varnew.setStack(true);
exprlist.add(new AssignmentExprent(varnew, varex)); exprlist.add(new AssignmentExprent(varnew, varex, null));
lst.add(0, (VarExprent)varnew.copy()); lst.add(0, (VarExprent)varnew.copy());
} }
Exprent exprent = lst.get(lst.size() + copyoffset).copy(); Exprent exprent = lst.get(lst.size() + copyoffset).copy();
VarExprent var = new VarExprent(base + offset, exprent.getExprType(), varProcessor); VarExprent var = new VarExprent(base + offset, exprent.getExprType(), varProcessor);
var.setStack(true); var.setStack(true);
exprlist.add(new AssignmentExprent(var, exprent)); exprlist.add(new AssignmentExprent(var, exprent, null));
lst.add(0, (VarExprent)var.copy()); lst.add(0, (VarExprent)var.copy());
for (VarExprent expr : lst) { for (VarExprent expr : lst) {
@ -742,7 +767,7 @@ public class ExprProcessor implements CodeConstants {
VarExprent vartmp = new VarExprent(VarExprent.STACK_BASE, var.getExprType(), var.getProcessor()); VarExprent vartmp = new VarExprent(VarExprent.STACK_BASE, var.getExprType(), var.getProcessor());
vartmp.setStack(true); vartmp.setStack(true);
prlst.getLstExprents().add(new AssignmentExprent(vartmp, var.copy())); prlst.getLstExprents().add(new AssignmentExprent(vartmp, var.copy(), null));
prlst.getStack().push(vartmp.copy()); prlst.getStack().push(vartmp.copy());
return prlst; return prlst;
} }
@ -840,19 +865,19 @@ public class ExprProcessor implements CodeConstants {
ConstExprent defaultval; ConstExprent defaultval;
if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arraydim > 0) { if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arraydim > 0) {
defaultval = new ConstExprent(VarType.VARTYPE_NULL, null); defaultval = new ConstExprent(VarType.VARTYPE_NULL, null, null);
} }
else if (arrtype.type == CodeConstants.TYPE_FLOAT) { else if (arrtype.type == CodeConstants.TYPE_FLOAT) {
defaultval = new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0)); defaultval = new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0), null);
} }
else if (arrtype.type == CodeConstants.TYPE_LONG) { else if (arrtype.type == CodeConstants.TYPE_LONG) {
defaultval = new ConstExprent(VarType.VARTYPE_LONG, new Long(0)); defaultval = new ConstExprent(VarType.VARTYPE_LONG, new Long(0), null);
} }
else if (arrtype.type == CodeConstants.TYPE_DOUBLE) { else if (arrtype.type == CodeConstants.TYPE_DOUBLE) {
defaultval = new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0)); defaultval = new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0), null);
} }
else { // integer types else { // integer types
defaultval = new ConstExprent(0, true); defaultval = new ConstExprent(0, true, null);
} }
return defaultval; return defaultval;

@ -200,7 +200,8 @@ public class IfHelper {
lstOperands.add(statexpr.getCondition()); lstOperands.add(statexpr.getCondition());
lstOperands.add(ifchild.getHeadexprent().getCondition()); lstOperands.add(ifchild.getHeadexprent().getCondition());
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands)); statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands, null));
statexpr.addBytecodeOffsets(ifchild.getHeadexprent().bytecode);
return true; return true;
} }
@ -252,8 +253,9 @@ public class IfHelper {
List<Exprent> lstOperands = new ArrayList<Exprent>(); List<Exprent> lstOperands = new ArrayList<Exprent>();
lstOperands.add(statexpr.getCondition()); lstOperands.add(statexpr.getCondition());
lstOperands.add(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstOperands.add(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
Arrays.asList(new Exprent[]{ifchild.getHeadexprent().getCondition()}))); Arrays.asList(ifchild.getHeadexprent().getCondition()), null));
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands)); statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands, null));
statexpr.addBytecodeOffsets(ifchild.getHeadexprent().bytecode);
return true; return true;
} }
@ -309,13 +311,13 @@ public class IfHelper {
if (path == 2) { if (path == 2) {
lstOperands.set(0, new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstOperands.set(0, new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
Arrays.asList(new Exprent[]{lstOperands.get(0)}))); Arrays.asList(lstOperands.get(0)), null));
} }
lstOperands.add(statexpr.getCondition()); lstOperands.add(statexpr.getCondition());
statexpr statexpr
.setCondition(new FunctionExprent(path == 1 ? FunctionExprent.FUNCTION_COR : FunctionExprent.FUNCTION_CADD, lstOperands)); .setCondition(new FunctionExprent(path == 1 ? FunctionExprent.FUNCTION_COR : FunctionExprent.FUNCTION_CADD, lstOperands, null));
if (secondif.getFirst().getExprents().isEmpty() && if (secondif.getFirst().getExprents().isEmpty() &&
!firstif.getFirst().getExprents().isEmpty()) { !firstif.getFirst().getExprents().isEmpty()) {
@ -359,7 +361,7 @@ public class IfHelper {
// negate the if condition // negate the if condition
IfExprent statexpr = firstif.getHeadexprent(); IfExprent statexpr = firstif.getHeadexprent();
statexpr statexpr
.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(new Exprent[]{statexpr.getCondition()}))); .setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(statexpr.getCondition()), null));
return true; return true;
} }
@ -554,7 +556,7 @@ public class IfHelper {
// negate the if condition // negate the if condition
IfExprent statexpr = ifstat.getHeadexprent(); IfExprent statexpr = ifstat.getHeadexprent();
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(new Exprent[]{statexpr.getCondition()}))); statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(statexpr.getCondition()), null));
if (noelsestat) { if (noelsestat) {
StatEdge ifedge = ifstat.getIfEdge(); StatEdge ifedge = ifstat.getIfEdge();

@ -138,7 +138,7 @@ public class PPandMMHelper {
if (left.equals(econd) && (midlayer == null || midlayer.equals(condtype))) { if (left.equals(econd) && (midlayer == null || midlayer.equals(condtype))) {
FunctionExprent ret = new FunctionExprent( FunctionExprent ret = new FunctionExprent(
func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI, func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI,
Arrays.asList(new Exprent[]{econd})); Arrays.asList(econd), func.bytecode);
ret.setImplicitType(condtype); ret.setImplicitType(condtype);
exprentReplaced = true; exprentReplaced = true;

@ -189,7 +189,7 @@ public class SecondaryFunctionsHelper {
} }
if (desttype >= 0) { if (desttype >= 0) {
return new FunctionExprent(desttype, funcexpr.getLstOperands()); return new FunctionExprent(desttype, funcexpr.getLstOperands(), funcexpr.bytecode);
} }
} }
} }
@ -236,7 +236,7 @@ public class SecondaryFunctionsHelper {
if (val == -1) { if (val == -1) {
List<Exprent> lstBitNotOperand = new ArrayList<Exprent>(); List<Exprent> lstBitNotOperand = new ArrayList<Exprent>();
lstBitNotOperand.add(lstOperands.get(1 - i)); lstBitNotOperand.add(lstOperands.get(1 - i));
return new FunctionExprent(FunctionExprent.FUNCTION_BITNOT, lstBitNotOperand); return new FunctionExprent(FunctionExprent.FUNCTION_BITNOT, lstBitNotOperand, fexpr.bytecode);
} }
} }
} }
@ -257,7 +257,7 @@ public class SecondaryFunctionsHelper {
else { else {
List<Exprent> lstNotOperand = new ArrayList<Exprent>(); List<Exprent> lstNotOperand = new ArrayList<Exprent>();
lstNotOperand.add(lstOperands.get(1 - i)); lstNotOperand.add(lstOperands.get(1 - i));
return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstNotOperand); return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstNotOperand, fexpr.bytecode);
} }
} }
} }
@ -267,10 +267,10 @@ public class SecondaryFunctionsHelper {
if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) { if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) {
int val = ((ConstExprent)lstOperands.get(0)).getIntValue(); int val = ((ConstExprent)lstOperands.get(0)).getIntValue();
if (val == 0) { if (val == 0) {
return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(1)); return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(1), fexpr.bytecode);
} }
else { else {
return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(0)); return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(0), fexpr.bytecode);
} }
} }
break; break;
@ -286,7 +286,7 @@ public class SecondaryFunctionsHelper {
cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) { cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) {
if (cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) { if (cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) {
return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(new Exprent[]{lstOperands.get(0)})); return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(lstOperands.get(0)), fexpr.bytecode);
} }
else if (cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) { else if (cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) {
return lstOperands.get(0); return lstOperands.get(0);
@ -303,23 +303,22 @@ public class SecondaryFunctionsHelper {
VarType type = lstOperands.get(0).getExprType(); VarType type = lstOperands.get(0).getExprType();
VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR); VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[]{ FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new Exprent[]{new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new VarExprent(var, type, processor),
ConstExprent.getZeroConstant(type.type)})), ConstExprent.getZeroConstant(type.type)), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(-1)), new ConstExprent(VarType.VARTYPE_INT, new Integer(-1), null),
new ConstExprent(VarType.VARTYPE_INT, new Integer(1))})); new ConstExprent(VarType.VARTYPE_INT, new Integer(1), null)), null);
FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(new Exprent[]{ FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(
new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB, new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB,
Arrays.asList( Arrays.asList(lstOperands.get(0),
new Exprent[]{lstOperands.get(0), lstOperands.get(1)), null), null),
lstOperands.get(1)}))), ConstExprent.getZeroConstant(type.type)), null);
ConstExprent.getZeroConstant(type.type)}));
processor.setVarType(new VarVersionPaar(var, 0), type); processor.setVarType(new VarVersionPaar(var, 0), type);
return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[]{ return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(
head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0)), iff})); head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null), iff), fexpr.bytecode);
} }
break; break;
case Exprent.EXPRENT_ASSIGNMENT: // check for conditional assignment case Exprent.EXPRENT_ASSIGNMENT: // check for conditional assignment
@ -409,7 +408,7 @@ public class SecondaryFunctionsHelper {
List<Exprent> operands = fparam.getLstOperands(); List<Exprent> operands = fparam.getLstOperands();
for (int i = 0; i < operands.size(); i++) { for (int i = 0; i < operands.size(); i++) {
Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
Arrays.asList(new Exprent[]{operands.get(i)})); Arrays.asList(operands.get(i)), operands.get(i).bytecode);
Exprent retparam = propagateBoolNot(newparam); Exprent retparam = propagateBoolNot(newparam);
operands.set(i, retparam == null ? newparam : retparam); operands.set(i, retparam == null ? newparam : retparam);

@ -387,7 +387,7 @@ public class SimplifyExprentsHelper {
if (asf.getLeft().type == Exprent.EXPRENT_VAR && ass.getRight().type == Exprent.EXPRENT_VAR && if (asf.getLeft().type == Exprent.EXPRENT_VAR && ass.getRight().type == Exprent.EXPRENT_VAR &&
asf.getLeft().equals(ass.getRight()) && ((VarExprent)asf.getLeft()).isStack()) { asf.getLeft().equals(ass.getRight()) && ((VarExprent)asf.getLeft()).isStack()) {
if (ass.getLeft().type != Exprent.EXPRENT_VAR || !((VarExprent)ass.getLeft()).isStack()) { if (ass.getLeft().type != Exprent.EXPRENT_VAR || !((VarExprent)ass.getLeft()).isStack()) {
asf.setRight(new AssignmentExprent(ass.getLeft(), asf.getRight())); asf.setRight(new AssignmentExprent(ass.getLeft(), asf.getRight(), ass.bytecode));
return true; return true;
} }
} }
@ -450,7 +450,7 @@ public class SimplifyExprentsHelper {
if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) { if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) {
FunctionExprent ret = new FunctionExprent( FunctionExprent ret = new FunctionExprent(
func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI, func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI,
Arrays.asList(new Exprent[]{econd})); Arrays.asList(econd), func.bytecode);
ret.setImplicitType(VarType.VARTYPE_INT); ret.setImplicitType(VarType.VARTYPE_INT);
return ret; return ret;
} }
@ -707,7 +707,7 @@ public class SimplifyExprentsHelper {
if (lambda_class != null) { // real lambda class found, replace invocation with an anonymous class 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); NewExprent newexp = new NewExprent(new VarType(lambda_class_name, true), null, 0, in.bytecode);
newexp.setConstructor(in); 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 // note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invokation
// lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);) // lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);)
@ -750,6 +750,10 @@ public class SimplifyExprentsHelper {
if (stat.type == Statement.TYPE_IF && stat.getExprents() == null) { if (stat.type == Statement.TYPE_IF && stat.getExprents() == null) {
IfStatement stif = (IfStatement)stat; IfStatement stif = (IfStatement)stat;
Exprent ifheadexpr = stif.getHeadexprent();
Set<Integer> ifheadexpr_bytecode = (ifheadexpr == null ? null : ifheadexpr.bytecode);
if (stif.iftype == IfStatement.IFTYPE_IFELSE) { if (stif.iftype == IfStatement.IFTYPE_IFELSE) {
Statement ifstat = stif.getIfstat(); Statement ifstat = stif.getIfstat();
Statement elsestat = stif.getElsestat(); Statement elsestat = stif.getElsestat();
@ -788,10 +792,10 @@ public class SimplifyExprentsHelper {
data.addAll(stif.getFirst().getExprents()); data.addAll(stif.getFirst().getExprents());
data.add(new AssignmentExprent(ifvar, new FunctionExprent(FunctionExprent.FUNCTION_IIF, data.add(new AssignmentExprent(ifvar, new FunctionExprent(FunctionExprent.FUNCTION_IIF,
Arrays.asList(new Exprent[]{ Arrays.asList(
stif.getHeadexprent().getCondition(), stif.getHeadexprent().getCondition(),
ifas.getRight(), ifas.getRight(),
elseas.getRight()})))); elseas.getRight()), ifheadexpr_bytecode), ifheadexpr_bytecode));
stif.setExprents(data); stif.setExprents(data);
if (stif.getAllSuccessorEdges().isEmpty()) { if (stif.getAllSuccessorEdges().isEmpty()) {
@ -829,10 +833,10 @@ public class SimplifyExprentsHelper {
data.addAll(stif.getFirst().getExprents()); data.addAll(stif.getFirst().getExprents());
data.add(new ExitExprent(ifex.getExittype(), new FunctionExprent(FunctionExprent.FUNCTION_IIF, data.add(new ExitExprent(ifex.getExittype(), new FunctionExprent(FunctionExprent.FUNCTION_IIF,
Arrays.asList(new Exprent[]{ Arrays.asList(
stif.getHeadexprent().getCondition(), stif.getHeadexprent().getCondition(),
ifex.getValue(), ifex.getValue(),
elseex.getValue()})), ifex.getRettype())); elseex.getValue()), ifheadexpr_bytecode), ifex.getRettype(), ifheadexpr_bytecode));
stif.setExprents(data); stif.setExprents(data);
StatEdge retedge = ifstat.getAllSuccessorEdges().get(0); StatEdge retedge = ifstat.getAllSuccessorEdges().get(0);

@ -16,6 +16,8 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
@ -38,14 +40,17 @@ public class ArrayExprent extends Exprent {
this.type = EXPRENT_ARRAY; this.type = EXPRENT_ARRAY;
} }
public ArrayExprent(Exprent array, Exprent index, VarType hardtype) { public ArrayExprent(Exprent array, Exprent index, VarType hardtype, Set<Integer> bytecode_offsets) {
this.array = array; this.array = array;
this.index = index; this.index = index;
this.hardtype = hardtype; this.hardtype = hardtype;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
return new ArrayExprent(array.copy(), index.copy(), hardtype); return new ArrayExprent(array.copy(), index.copy(), hardtype, bytecode);
} }
public VarType getExprType() { public VarType getExprType() {

@ -15,6 +15,10 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
@ -26,9 +30,6 @@ import org.jetbrains.java.decompiler.struct.StructField;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class AssignmentExprent extends Exprent { public class AssignmentExprent extends Exprent {
@ -60,9 +61,11 @@ public class AssignmentExprent extends Exprent {
} }
public AssignmentExprent(Exprent left, Exprent right) { public AssignmentExprent(Exprent left, Exprent right, Set<Integer> bytecode_offsets) {
this.left = left; this.left = left;
this.right = right; this.right = right;
addBytecodeOffsets(bytecode_offsets);
} }
@ -97,8 +100,9 @@ public class AssignmentExprent extends Exprent {
return lst; return lst;
} }
@Override
public Exprent copy() { public Exprent copy() {
return new AssignmentExprent(left.copy(), right.copy()); return new AssignmentExprent(left.copy(), right.copy(), bytecode);
} }
public int getPrecedence() { public int getPrecedence() {

@ -15,6 +15,11 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
@ -25,10 +30,6 @@ import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ConstExprent extends Exprent { public class ConstExprent extends Exprent {
private static final HashMap<Integer, String> escapes = new HashMap<Integer, String>(); private static final HashMap<Integer, String> escapes = new HashMap<Integer, String>();
@ -54,7 +55,7 @@ public class ConstExprent extends Exprent {
this.type = EXPRENT_CONST; this.type = EXPRENT_CONST;
} }
public ConstExprent(int val, boolean boolPermitted) { public ConstExprent(int val, boolean boolPermitted, Set<Integer> bytecode_offsets) {
this.boolPermitted = boolPermitted; this.boolPermitted = boolPermitted;
if (boolPermitted) { if (boolPermitted) {
@ -85,15 +86,20 @@ public class ConstExprent extends Exprent {
} }
} }
value = new Integer(val); value = new Integer(val);
addBytecodeOffsets(bytecode_offsets);
} }
public ConstExprent(VarType consttype, Object value) { public ConstExprent(VarType consttype, Object value, Set<Integer> bytecode_offsets) {
this.consttype = consttype; this.consttype = consttype;
this.value = value; this.value = value;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
return new ConstExprent(consttype, value); return new ConstExprent(consttype, value, bytecode);
} }
public VarType getExprType() { public VarType getExprType() {
@ -155,7 +161,7 @@ public class ConstExprent extends Exprent {
else { else {
return new TextBuffer(value.toString()); return new TextBuffer(value.toString());
} }
return new FieldExprent(intfield, "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR).toJava(0, tracer); return new FieldExprent(intfield, "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
case CodeConstants.TYPE_LONG: case CodeConstants.TYPE_LONG:
long lval = ((Long)value).longValue(); long lval = ((Long)value).longValue();
@ -172,7 +178,7 @@ public class ConstExprent extends Exprent {
else { else {
return new TextBuffer(value.toString()).append("L"); return new TextBuffer(value.toString()).append("L");
} }
return new FieldExprent(longfield, "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR).toJava(0, tracer); return new FieldExprent(longfield, "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
case CodeConstants.TYPE_DOUBLE: case CodeConstants.TYPE_DOUBLE:
double dval = ((Double)value).doubleValue(); double dval = ((Double)value).doubleValue();
@ -209,7 +215,7 @@ public class ConstExprent extends Exprent {
else { else {
return new TextBuffer(value.toString()).append("D"); return new TextBuffer(value.toString()).append("D");
} }
return new FieldExprent(doublefield, "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR).toJava(0, tracer); return new FieldExprent(doublefield, "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
case CodeConstants.TYPE_FLOAT: case CodeConstants.TYPE_FLOAT:
float fval = ((Float)value).floatValue(); float fval = ((Float)value).floatValue();
@ -246,7 +252,7 @@ public class ConstExprent extends Exprent {
else { else {
return new TextBuffer(value.toString()).append("F"); return new TextBuffer(value.toString()).append("F");
} }
return new FieldExprent(floatfield, "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR).toJava(0, tracer); return new FieldExprent(floatfield, "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
case CodeConstants.TYPE_NULL: case CodeConstants.TYPE_NULL:
return new TextBuffer("null"); return new TextBuffer("null");
case CodeConstants.TYPE_OBJECT: case CodeConstants.TYPE_OBJECT:
@ -369,13 +375,13 @@ public class ConstExprent extends Exprent {
switch (type) { switch (type) {
case CodeConstants.TYPE_INT: case CodeConstants.TYPE_INT:
return new ConstExprent(VarType.VARTYPE_INT, new Integer(0)); return new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null);
case CodeConstants.TYPE_LONG: case CodeConstants.TYPE_LONG:
return new ConstExprent(VarType.VARTYPE_LONG, new Long(0)); return new ConstExprent(VarType.VARTYPE_LONG, new Long(0), null);
case CodeConstants.TYPE_DOUBLE: case CodeConstants.TYPE_DOUBLE:
return new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0)); return new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0), null);
case CodeConstants.TYPE_FLOAT: case CodeConstants.TYPE_FLOAT:
return new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0)); return new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0), null);
} }
throw new RuntimeException("Invalid argument!"); throw new RuntimeException("Invalid argument!");

@ -15,6 +15,10 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
@ -27,9 +31,6 @@ import org.jetbrains.java.decompiler.struct.attr.StructExceptionsAttribute;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class ExitExprent extends Exprent { public class ExitExprent extends Exprent {
@ -47,14 +48,17 @@ public class ExitExprent extends Exprent {
this.type = EXPRENT_EXIT; this.type = EXPRENT_EXIT;
} }
public ExitExprent(int exittype, Exprent value, VarType rettype) { public ExitExprent(int exittype, Exprent value, VarType rettype, Set<Integer> bytecode_offsets) {
this.exittype = exittype; this.exittype = exittype;
this.value = value; this.value = value;
this.rettype = rettype; this.rettype = rettype;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
return new ExitExprent(exittype, value == null ? null : value.copy(), rettype); return new ExitExprent(exittype, value == null ? null : value.copy(), rettype, bytecode);
} }
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {

@ -15,6 +15,12 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
@ -23,11 +29,6 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Exprent { public class Exprent {
@ -135,4 +136,10 @@ public class Exprent {
public void replaceExprent(Exprent oldexpr, Exprent newexpr) { public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
} }
public void addBytecodeOffsets(Collection<Integer> bytecode_offsets) {
if(bytecode_offsets != null) {
bytecode.addAll(bytecode_offsets);
}
}
} }

@ -15,6 +15,10 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
@ -29,9 +33,6 @@ import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class FieldExprent extends Exprent { public class FieldExprent extends Exprent {
@ -49,7 +50,7 @@ public class FieldExprent extends Exprent {
this.type = EXPRENT_FIELD; this.type = EXPRENT_FIELD;
} }
public FieldExprent(LinkConstant cn, Exprent instance) { public FieldExprent(LinkConstant cn, Exprent instance, Set<Integer> bytecode_offsets) {
this.instance = instance; this.instance = instance;
@ -60,14 +61,18 @@ public class FieldExprent extends Exprent {
classname = cn.classname; classname = cn.classname;
name = cn.elementname; name = cn.elementname;
descriptor = FieldDescriptor.parseDescriptor(cn.descriptor); descriptor = FieldDescriptor.parseDescriptor(cn.descriptor);
addBytecodeOffsets(bytecode_offsets);
} }
public FieldExprent(String name, String classname, boolean isStatic, Exprent instance, FieldDescriptor descriptor) { public FieldExprent(String name, String classname, boolean isStatic, Exprent instance, FieldDescriptor descriptor, Set<Integer> bytecode_offsets) {
this.name = name; this.name = name;
this.classname = classname; this.classname = classname;
this.isStatic = isStatic; this.isStatic = isStatic;
this.instance = instance; this.instance = instance;
this.descriptor = descriptor; this.descriptor = descriptor;
addBytecodeOffsets(bytecode_offsets);
} }
public VarType getExprType() { public VarType getExprType() {
@ -91,8 +96,9 @@ public class FieldExprent extends Exprent {
return lst; return lst;
} }
@Override
public Exprent copy() { public Exprent copy() {
return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor); return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor, bytecode);
} }
@Override @Override

@ -15,6 +15,12 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
@ -24,11 +30,6 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
public class FunctionExprent extends Exprent { public class FunctionExprent extends Exprent {
@ -207,7 +208,7 @@ public class FunctionExprent extends Exprent {
this.type = EXPRENT_FUNCTION; this.type = EXPRENT_FUNCTION;
} }
public FunctionExprent(int functype, ListStack<Exprent> stack) { public FunctionExprent(int functype, ListStack<Exprent> stack, Set<Integer> bytecode_offsets) {
this.functype = functype; this.functype = functype;
if (functype >= FUNCTION_BITNOT && functype <= FUNCTION_PPI && functype != FUNCTION_CAST if (functype >= FUNCTION_BITNOT && functype <= FUNCTION_PPI && functype != FUNCTION_CAST
&& functype != FUNCTION_INSTANCEOF) { && functype != FUNCTION_INSTANCEOF) {
@ -221,11 +222,15 @@ public class FunctionExprent extends Exprent {
lstOperands.add(stack.pop()); lstOperands.add(stack.pop());
lstOperands.add(expr); lstOperands.add(expr);
} }
addBytecodeOffsets(bytecode_offsets);
} }
public FunctionExprent(int functype, List<Exprent> operands) { public FunctionExprent(int functype, List<Exprent> operands, Set<Integer> bytecode_offsets) {
this.functype = functype; this.functype = functype;
this.lstOperands = operands; this.lstOperands = operands;
addBytecodeOffsets(bytecode_offsets);
} }
public VarType getExprType() { public VarType getExprType() {
@ -420,12 +425,13 @@ public class FunctionExprent extends Exprent {
return lst; return lst;
} }
@Override
public Exprent copy() { public Exprent copy() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
for (Exprent expr : lstOperands) { for (Exprent expr : lstOperands) {
lst.add(expr.copy()); lst.add(expr.copy());
} }
FunctionExprent func = new FunctionExprent(functype, lst); FunctionExprent func = new FunctionExprent(functype, lst, bytecode);
func.setImplicitType(implicitType); func.setImplicitType(implicitType);
return func; return func;

@ -16,15 +16,16 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class IfExprent extends Exprent { public class IfExprent extends Exprent {
@ -82,29 +83,34 @@ public class IfExprent extends Exprent {
this.type = EXPRENT_IF; this.type = EXPRENT_IF;
} }
public IfExprent(int iftype, ListStack<Exprent> stack) { public IfExprent(int iftype, ListStack<Exprent> stack, Set<Integer> bytecode_offsets) {
if (iftype <= IF_LE) { if (iftype <= IF_LE) {
stack.push(new ConstExprent(0, true)); stack.push(new ConstExprent(0, true, null));
} }
else if (iftype <= IF_NONNULL) { else if (iftype <= IF_NONNULL) {
stack.push(new ConstExprent(VarType.VARTYPE_NULL, null)); stack.push(new ConstExprent(VarType.VARTYPE_NULL, null, null));
} }
if (iftype == IF_VALUE) { if (iftype == IF_VALUE) {
condition = stack.pop(); condition = stack.pop();
} }
else { else {
condition = new FunctionExprent(functypes[iftype], stack); condition = new FunctionExprent(functypes[iftype], stack, null);
} }
addBytecodeOffsets(bytecode_offsets);
} }
private IfExprent(Exprent condition) { private IfExprent(Exprent condition, Set<Integer> bytecode_offsets) {
this.condition = condition; this.condition = condition;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
return new IfExprent(condition.copy()); return new IfExprent(condition.copy(), bytecode);
} }
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
@ -135,7 +141,7 @@ public class IfExprent extends Exprent {
public IfExprent negateIf() { public IfExprent negateIf() {
condition = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, condition = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
Arrays.asList(new Exprent[]{condition})); Arrays.asList(condition), condition.bytecode);
return this; return this;
} }

@ -80,7 +80,7 @@ public class InvocationExprent extends Exprent {
public InvocationExprent() { public InvocationExprent() {
} }
public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack, int dynamic_invokation_type) { public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack, int dynamic_invokation_type, Set<Integer> bytecode_offsets) {
name = cn.elementname; name = cn.elementname;
classname = cn.classname; classname = cn.classname;
@ -134,6 +134,8 @@ public class InvocationExprent extends Exprent {
else { else {
instance = stack.pop(); instance = stack.pop();
} }
addBytecodeOffsets(bytecode_offsets);
} }
private InvocationExprent(InvocationExprent expr) { private InvocationExprent(InvocationExprent expr) {
@ -152,6 +154,7 @@ public class InvocationExprent extends Exprent {
for (int i = 0; i < lstParameters.size(); i++) { for (int i = 0; i < lstParameters.size(); i++) {
lstParameters.set(i, lstParameters.get(i).copy()); lstParameters.set(i, lstParameters.get(i).copy());
} }
bytecode.addAll(expr.bytecode);
} }
@ -184,6 +187,7 @@ public class InvocationExprent extends Exprent {
} }
@Override
public Exprent copy() { public Exprent copy() {
return new InvocationExprent(this); return new InvocationExprent(this);
} }

@ -16,11 +16,12 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class MonitorExprent extends Exprent { public class MonitorExprent extends Exprent {
@ -36,13 +37,16 @@ public class MonitorExprent extends Exprent {
this.type = EXPRENT_MONITOR; this.type = EXPRENT_MONITOR;
} }
public MonitorExprent(int montype, Exprent value) { public MonitorExprent(int montype, Exprent value, Set<Integer> bytecode_offsets) {
this.montype = montype; this.montype = montype;
this.value = value; this.value = value;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
return new MonitorExprent(montype, value.copy()); return new MonitorExprent(montype, value.copy(), bytecode);
} }
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {

@ -15,6 +15,11 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
@ -30,10 +35,6 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class NewExprent extends Exprent { public class NewExprent extends Exprent {
private InvocationExprent constructor; private InvocationExprent constructor;
@ -56,19 +57,21 @@ public class NewExprent extends Exprent {
this.type = EXPRENT_NEW; this.type = EXPRENT_NEW;
} }
public NewExprent(VarType newtype, ListStack<Exprent> stack, int arraydim) { public NewExprent(VarType newtype, ListStack<Exprent> stack, int arraydim, Set<Integer> bytecode_offsets) {
this.newtype = newtype; this.newtype = newtype;
for (int i = 0; i < arraydim; i++) { for (int i = 0; i < arraydim; i++) {
lstDims.add(0, stack.pop()); lstDims.add(0, stack.pop());
} }
addBytecodeOffsets(bytecode_offsets);
setAnonymous(); setAnonymous();
} }
public NewExprent(VarType newtype, List<Exprent> lstDims) { public NewExprent(VarType newtype, List<Exprent> lstDims, Set<Integer> bytecode_offsets) {
this.newtype = newtype; this.newtype = newtype;
this.lstDims = lstDims; this.lstDims = lstDims;
addBytecodeOffsets(bytecode_offsets);
setAnonymous(); setAnonymous();
} }
@ -152,13 +155,14 @@ public class NewExprent extends Exprent {
return lst; return lst;
} }
@Override
public Exprent copy() { public Exprent copy() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
for (Exprent expr : lstDims) { for (Exprent expr : lstDims) {
lst.add(expr.copy()); lst.add(expr.copy());
} }
NewExprent ret = new NewExprent(newtype, lst); NewExprent ret = new NewExprent(newtype, lst, bytecode);
ret.setConstructor(constructor == null ? null : (InvocationExprent)constructor.copy()); ret.setConstructor(constructor == null ? null : (InvocationExprent)constructor.copy());
ret.setLstArrayElements(lstArrayElements); ret.setLstArrayElements(lstArrayElements);
ret.setDirectArrayInit(directArrayInit); ret.setDirectArrayInit(directArrayInit);

@ -16,14 +16,15 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class SwitchExprent extends Exprent { public class SwitchExprent extends Exprent {
@ -35,12 +36,15 @@ public class SwitchExprent extends Exprent {
this.type = EXPRENT_SWITCH; this.type = EXPRENT_SWITCH;
} }
public SwitchExprent(Exprent value) { public SwitchExprent(Exprent value, Set<Integer> bytecode_offsets) {
this.value = value; this.value = value;
addBytecodeOffsets(bytecode_offsets);
} }
@Override
public Exprent copy() { public Exprent copy() {
SwitchExprent swexpr = new SwitchExprent(value.copy()); SwitchExprent swexpr = new SwitchExprent(value.copy(), bytecode);
List<List<ConstExprent>> lstCaseValues = new ArrayList<List<ConstExprent>>(); List<List<ConstExprent>> lstCaseValues = new ArrayList<List<ConstExprent>>();
for (List<ConstExprent> lst : caseValues) { for (List<ConstExprent> lst : caseValues) {

@ -15,12 +15,16 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
@ -28,9 +32,6 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class VarExprent extends Exprent { public class VarExprent extends Exprent {
public static final int STACK_BASE = 10000; public static final int STACK_BASE = 10000;
@ -73,6 +74,7 @@ public class VarExprent extends Exprent {
return new ArrayList<Exprent>(); return new ArrayList<Exprent>();
} }
@Override
public Exprent copy() { public Exprent copy() {
VarExprent var = new VarExprent(index, getVartype(), processor); VarExprent var = new VarExprent(index, getVartype(), processor);
var.setDefinition(definition); var.setDefinition(definition);

@ -311,7 +311,7 @@ public class SwitchStatement extends Statement {
int index = in == lstSuccs.size() ? 0 : in; int index = in == lstSuccs.size() ? 0 : in;
lste.add(lstSuccs.get(index)); lste.add(lstSuccs.get(index));
lstv.add(index == 0 ? null : new ConstExprent(values[index - 1], false)); lstv.add(index == 0 ? null : new ConstExprent(values[index - 1], false, null));
} }
lstEdges.add(lste); lstEdges.add(lste);
lstValues.add(lstv); lstValues.add(lstv);

@ -116,7 +116,7 @@ public class VarTypeProcessor {
else if (expr.type == Exprent.EXPRENT_CONST) { else if (expr.type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)expr; ConstExprent cexpr = (ConstExprent)expr;
if (cexpr.getConsttype().type_family == CodeConstants.TYPE_FAMILY_INTEGER) { if (cexpr.getConsttype().type_family == CodeConstants.TYPE_FAMILY_INTEGER) {
cexpr.setConsttype(new ConstExprent(cexpr.getIntValue(), cexpr.isBoolPermitted()).getConsttype()); cexpr.setConsttype(new ConstExprent(cexpr.getIntValue(), cexpr.isBoolPermitted(), null).getConsttype());
} }
} }
} }
@ -183,7 +183,7 @@ public class VarTypeProcessor {
return true; return true;
} }
else if (newtype.type_family == CodeConstants.TYPE_FAMILY_INTEGER) { else if (newtype.type_family == CodeConstants.TYPE_FAMILY_INTEGER) {
VarType mininteger = new ConstExprent((Integer)((ConstExprent)exprent).getValue(), false).getConsttype(); VarType mininteger = new ConstExprent((Integer)((ConstExprent)exprent).getValue(), false, null).getConsttype();
if (mininteger.isStrictSuperset(newtype)) { if (mininteger.isStrictSuperset(newtype)) {
newtype = mininteger; newtype = mininteger;
} }

@ -81,7 +81,7 @@ public class StructAnnotationAttribute extends StructGeneralAttribute {
String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString();
String constName = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); String constName = pool.getPrimitiveConstant(data.readUnsignedShort()).getString();
FieldDescriptor descr = FieldDescriptor.parseDescriptor(className); FieldDescriptor descr = FieldDescriptor.parseDescriptor(className);
return new FieldExprent(constName, descr.type.value, true, null, descr); return new FieldExprent(constName, descr.type.value, true, null, descr, null);
case 'c': // class case 'c': // class
String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString();
@ -122,7 +122,7 @@ public class StructAnnotationAttribute extends StructGeneralAttribute {
default: default:
throw new RuntimeException("invalid class type: " + type.type); throw new RuntimeException("invalid class type: " + type.type);
} }
return new ConstExprent(VarType.VARTYPE_CLASS, value); return new ConstExprent(VarType.VARTYPE_CLASS, value, null);
case '[': // array case '[': // array
List<Exprent> elements = Collections.emptyList(); List<Exprent> elements = Collections.emptyList();
@ -143,7 +143,7 @@ public class StructAnnotationAttribute extends StructGeneralAttribute {
newType = new VarType(elementType.type, 1, elementType.value); newType = new VarType(elementType.type, 1, elementType.value);
} }
NewExprent newExpr = new NewExprent(newType, Collections.<Exprent>emptyList()); NewExprent newExpr = new NewExprent(newType, Collections.<Exprent>emptyList(), null);
newExpr.setDirectArrayInit(true); newExpr.setDirectArrayInit(true);
newExpr.setLstArrayElements(elements); newExpr.setLstArrayElements(elements);
return newExpr; return newExpr;
@ -155,23 +155,23 @@ public class StructAnnotationAttribute extends StructGeneralAttribute {
PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort());
switch (tag) { switch (tag) {
case 'B': case 'B':
return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); return new ConstExprent(VarType.VARTYPE_BYTE, cn.value, null);
case 'C': case 'C':
return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); return new ConstExprent(VarType.VARTYPE_CHAR, cn.value, null);
case 'D': case 'D':
return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value, null);
case 'F': case 'F':
return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value, null);
case 'I': case 'I':
return new ConstExprent(VarType.VARTYPE_INT, cn.value); return new ConstExprent(VarType.VARTYPE_INT, cn.value, null);
case 'J': case 'J':
return new ConstExprent(VarType.VARTYPE_LONG, cn.value); return new ConstExprent(VarType.VARTYPE_LONG, cn.value, null);
case 'S': case 'S':
return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); return new ConstExprent(VarType.VARTYPE_SHORT, cn.value, null);
case 'Z': case 'Z':
return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value, null);
case 's': case 's':
return new ConstExprent(VarType.VARTYPE_STRING, cn.value); return new ConstExprent(VarType.VARTYPE_STRING, cn.value, null);
default: default:
throw new RuntimeException("invalid element type!"); throw new RuntimeException("invalid element type!");
} }

Loading…
Cancel
Save