This commit is contained in:
Roman Shevchenko
2016-03-16 17:23:47 +01:00
5 changed files with 61 additions and 53 deletions
@@ -118,7 +118,7 @@ public class BasicBlock implements IGraphNode {
block.removePredecessor(this);
}
// FIXME: unify block comparisons: id or direkt equality
// FIXME: unify block comparisons: id or direct equality
public void replaceSuccessor(BasicBlock oldBlock, BasicBlock newBlock) {
for (int i = 0; i < succs.size(); i++) {
if (succs.get(i).id == oldBlock.id) {
@@ -38,12 +38,11 @@ import java.util.Map.Entry;
public class ClassReference14Processor {
public final ExitExprent bodyexprent;
public static final ExitExprent bodyexprent;
public final ExitExprent handlerexprent;
public static final ExitExprent handlerexprent;
public ClassReference14Processor() {
static {
InvocationExprent invfor = new InvocationExprent();
invfor.setName("forName");
@@ -65,7 +64,7 @@ public class ClassReference14Processor {
constr.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
NewExprent newexpr =
new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<Exprent>(), null);
new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<>(), null);
newexpr.setConstructor(constr);
InvocationExprent invcause = new InvocationExprent();
@@ -82,32 +81,13 @@ public class ClassReference14Processor {
null, null);
}
public void processClassReferences(ClassNode node) {
ClassWrapper wrapper = node.getWrapper();
// int major_version = wrapper.getClassStruct().major_version;
// int minor_version = wrapper.getClassStruct().minor_version;
//
// if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
// // version 1.5 or above
// return;
// }
if (wrapper.getClassStruct().isVersionGE_1_5()) {
// version 1.5 or above
return;
}
public static void processClassReferences(ClassNode node) {
// find the synthetic method Class class$(String) if present
HashMap<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<ClassWrapper, MethodWrapper>();
mapClassMethods(node, mapClassMeths);
if (mapClassMeths.isEmpty()) {
return;
}
HashSet<ClassWrapper> setFound = new HashSet<ClassWrapper>();
processClassRec(node, mapClassMeths, setFound);
@@ -173,7 +153,7 @@ public class ClassReference14Processor {
}
}
private void mapClassMethods(ClassNode node, Map<ClassWrapper, MethodWrapper> map) {
private static void mapClassMethods(ClassNode node, Map<ClassWrapper, MethodWrapper> map) {
boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
ClassWrapper wrapper = node.getWrapper();
@@ -43,25 +43,27 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.struct.gen.generics.*;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ClassWriter {
private final ClassReference14Processor ref14processor;
private final PoolInterceptor interceptor;
public ClassWriter() {
ref14processor = new ClassReference14Processor();
interceptor = DecompilerContext.getPoolInterceptor();
}
private void invokeProcessors(ClassNode node) {
private static void invokeProcessors(ClassNode node) {
ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
InitializerProcessor.extractInitializers(wrapper);
if (node.type == ClassNode.CLASS_ROOT && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4)) {
ref14processor.processClassReferences(node);
if (node.type == ClassNode.CLASS_ROOT &&
!cl.isVersionGE_1_5() &&
DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4)) {
ClassReference14Processor.processClassReferences(node);
}
if (cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM)) {
@@ -273,7 +275,8 @@ public class ClassWriter {
}
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
StructLineNumberTableAttribute table = (StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
StructLineNumberTableAttribute table =
(StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
tracer.setLineNumberTable(table);
String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor());
DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer);
@@ -385,7 +388,12 @@ public class ClassWriter {
buffer.append('{').appendLineSeparator();
}
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
private void fieldToJava(ClassWrapper wrapper,
StructClass cl,
StructField fd,
TextBuffer buffer,
int indent,
BytecodeMappingTracer tracer) {
int start = buffer.length();
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
boolean isDeprecated = fd.getAttributes().containsKey("Deprecated");
@@ -571,7 +579,9 @@ public class ClassWriter {
changed = true;
res.append("_");
}
else res.append(c);
else {
res.append(c);
}
}
if (!changed) {
return name;
@@ -661,7 +671,7 @@ public class ClassWriter {
int actualParams = md.params.length;
List<VarVersionPair> sigFields = methodWrapper.signatureFields;
if (sigFields != null) {
actualParams = 0;
actualParams = 0;
for (VarVersionPair field : methodWrapper.signatureFields) {
if (field == null) {
actualParams++;
@@ -670,7 +680,8 @@ public class ClassWriter {
}
else if (isEnum && init) actualParams -= 2;
if (actualParams != descriptor.params.size()) {
String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor() + " in " + cl.qualifiedName;
String message =
"Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor() + " in " + cl.qualifiedName;
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
descriptor = null;
}
@@ -732,7 +743,8 @@ public class ClassWriter {
if (descriptor != null) {
GenericType parameterType = descriptor.params.get(i);
boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
boolean isVarArg =
(i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
if (isVarArg) {
parameterType = parameterType.decreaseArrayDim();
}
@@ -752,7 +764,8 @@ public class ClassWriter {
else {
VarType parameterType = md.params[i];
boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
boolean isVarArg =
(i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
if (isVarArg) {
parameterType = parameterType.decreaseArrayDim();
}
@@ -961,7 +974,8 @@ public class ClassWriter {
}
private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = {
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) {
@@ -981,6 +995,7 @@ public class ClassWriter {
}
private static final Map<Integer, String> MODIFIERS;
static {
MODIFIERS = new LinkedHashMap<>();
MODIFIERS.put(CodeConstants.ACC_PUBLIC, "public");
@@ -1003,8 +1018,15 @@ public class ClassWriter {
CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE | CodeConstants.ACC_STATIC |
CodeConstants.ACC_FINAL | CodeConstants.ACC_TRANSIENT | CodeConstants.ACC_VOLATILE;
private static final int METHOD_ALLOWED =
CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE | CodeConstants.ACC_ABSTRACT |
CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL | CodeConstants.ACC_SYNCHRONIZED | CodeConstants.ACC_NATIVE | CodeConstants.ACC_STRICT;
CodeConstants.ACC_PUBLIC |
CodeConstants.ACC_PROTECTED |
CodeConstants.ACC_PRIVATE |
CodeConstants.ACC_ABSTRACT |
CodeConstants.ACC_STATIC |
CodeConstants.ACC_FINAL |
CodeConstants.ACC_SYNCHRONIZED |
CodeConstants.ACC_NATIVE |
CodeConstants.ACC_STRICT;
private static final int CLASS_EXCLUDED = CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_STATIC;
private static final int FIELD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL;
@@ -368,7 +368,7 @@ public class ExprProcessor implements CodeConstants {
}
else if (cn instanceof LinkConstant) {
//TODO: for now treat Links as Strings
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_STRING, ((LinkConstant)cn).elementname , bytecode_offsets));
pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_STRING, ((LinkConstant)cn).elementname, bytecode_offsets));
}
break;
case opc_iload:
@@ -422,7 +422,8 @@ public class ExprProcessor implements CodeConstants {
Exprent index_store = stack.pop();
Exprent arr_store = stack.pop();
AssignmentExprent arrassign =
new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore], bytecode_offsets), value, bytecode_offsets);
new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore], bytecode_offsets), value,
bytecode_offsets);
exprlist.add(arrassign);
break;
case opc_iadd:
@@ -523,7 +524,7 @@ public class ExprProcessor implements CodeConstants {
case opc_tableswitch:
case opc_lookupswitch:
exprlist.add(new SwitchExprent(stack.pop(), bytecode_offsets));
break;
break;
case opc_ireturn:
case opc_lreturn:
case opc_freturn:
@@ -538,7 +539,7 @@ public class ExprProcessor implements CodeConstants {
: ((MethodDescriptor)DecompilerContext
.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret,
bytecode_offsets));
break;
break;
case opc_monitorenter:
case opc_monitorexit:
exprlist.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop(), bytecode_offsets));
@@ -552,13 +553,15 @@ public class ExprProcessor implements CodeConstants {
case opc_getstatic:
case opc_getfield:
pushEx(stack, exprlist,
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop(), bytecode_offsets));
new FieldExprent(pool.getLinkConstant(instr.getOperand(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(), bytecode_offsets);
new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop(),
bytecode_offsets);
exprlist.add(new AssignmentExprent(exprfield, valfield, bytecode_offsets));
break;
case opc_invokevirtual:
@@ -755,7 +758,7 @@ public class ExprProcessor implements CodeConstants {
return prlst;
}
public static boolean endsWithSemikolon(Exprent expr) {
public static boolean endsWithSemicolon(Exprent expr) {
int type = expr.type;
return !(type == Exprent.EXPRENT_SWITCH ||
type == Exprent.EXPRENT_MONITOR ||
@@ -768,7 +771,8 @@ public class ExprProcessor implements CodeConstants {
if (stat instanceof BasicBlockStatement) {
BasicBlock block = ((BasicBlockStatement)stat).getBlock();
List<Integer> offsets = block.getInstrOldOffsets();
if (!offsets.isEmpty() && offsets.size() > block.getSeq().length()) { // some instructions have been deleted, but we still have offsets
if (!offsets.isEmpty() &&
offsets.size() > block.getSeq().length()) { // some instructions have been deleted, but we still have offsets
tracer.addMapping(offsets.get(offsets.size() - 1)); // add the last offset
}
}
@@ -840,7 +844,7 @@ public class ExprProcessor implements CodeConstants {
if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMonType() == MonitorExprent.MONITOR_ENTER) {
buf.append("{}"); // empty synchronized block
}
if (endsWithSemikolon(expr)) {
if (endsWithSemicolon(expr)) {
buf.append(";");
}
buf.appendLineSeparator();
@@ -68,7 +68,9 @@ public class BasicBlockStatement extends Statement {
// *****************************************************************************
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
return ExprProcessor.listToJava(varDefinitions, indent, tracer).append(ExprProcessor.listToJava(exprents, indent, tracer));
TextBuffer tb = ExprProcessor.listToJava(varDefinitions, indent, tracer);
tb.append(ExprProcessor.listToJava(exprents, indent, tracer));
return tb;
}
public Statement getSimpleCopy() {