From 686b5abef9c269a726897c6992d0ea2abea79b04 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 4 Sep 2014 18:16:16 +0400 Subject: java-decompiler: optimization (empty lists allocation avoided) --- .../struct/attr/StructAnnotationAttribute.java | 260 +++++++++++---------- 1 file changed, 131 insertions(+), 129 deletions(-) (limited to 'src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java') diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java index 2a2c74c..d04cb04 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java @@ -22,160 +22,162 @@ import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; -import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class StructAnnotationAttribute extends StructGeneralAttribute { private List annotations; - public void initContent(ConstantPool pool) { - - super.initContent(pool); - - annotations = new ArrayList(); - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 2, info.length)); + @Override + public void initContent(ConstantPool pool) throws IOException { + annotations = parseAnnotations(pool, stream()); + } - int len = (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)); - for (int i = 0; i < len; i++) { - annotations.add(parseAnnotation(data, pool)); + public static List parseAnnotations(ConstantPool pool, DataInputStream data) throws IOException { + int len = data.readUnsignedShort(); + if (len > 0) { + List annotations = new ArrayList(len); + for (int i = 0; i < len; i++) { + annotations.add(parseAnnotation(data, pool)); + } + return annotations; + } + else { + return Collections.emptyList(); } } - public static AnnotationExprent parseAnnotation(DataInputStream data, ConstantPool pool) { - - try { - - String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - VarType cltype = new VarType(classname); - - int len = data.readUnsignedShort(); - - List parnames = new ArrayList(); - List parvalues = new ArrayList(); + public static AnnotationExprent parseAnnotation(DataInputStream data, ConstantPool pool) throws IOException { + String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + List names; + List values; + int len = data.readUnsignedShort(); + if (len > 0) { + names = new ArrayList(len); + values = new ArrayList(len); for (int i = 0; i < len; i++) { - parnames.add(pool.getPrimitiveConstant(data.readUnsignedShort()).getString()); - parvalues.add(parseAnnotationElement(data, pool)); + names.add(pool.getPrimitiveConstant(data.readUnsignedShort()).getString()); + values.add(parseAnnotationElement(data, pool)); } - - return new AnnotationExprent(cltype.value, parnames, parvalues); } - catch (IOException ex) { - throw new RuntimeException(ex); + else { + names = Collections.emptyList(); + values = Collections.emptyList(); } - } - public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) { - - try { - int tag = data.readUnsignedByte(); - - switch (tag) { - case 'e': // enum constant - String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - String constname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - - FieldDescriptor descr = FieldDescriptor.parseDescriptor(classname); - return new FieldExprent(constname, descr.type.value, true, null, descr); - case 'c': // class - String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - VarType type = FieldDescriptor.parseDescriptor(descriptor).type; - - String value; - switch (type.type) { - case CodeConstants.TYPE_OBJECT: - value = type.value; - break; - case CodeConstants.TYPE_BYTE: - value = byte.class.getName(); - break; - case CodeConstants.TYPE_CHAR: - value = char.class.getName(); - break; - case CodeConstants.TYPE_DOUBLE: - value = double.class.getName(); - break; - case CodeConstants.TYPE_FLOAT: - value = float.class.getName(); - break; - case CodeConstants.TYPE_INT: - value = int.class.getName(); - break; - case CodeConstants.TYPE_LONG: - value = long.class.getName(); - break; - case CodeConstants.TYPE_SHORT: - value = short.class.getName(); - break; - case CodeConstants.TYPE_BOOLEAN: - value = boolean.class.getName(); - break; - case CodeConstants.TYPE_VOID: - value = void.class.getName(); - break; - default: - throw new RuntimeException("invalid class type: " + type.type); - } - return new ConstExprent(VarType.VARTYPE_CLASS, value); - case '[': // array - int len = data.readUnsignedShort(); - List lst = new ArrayList(); + return new AnnotationExprent(new VarType(className).value, names, values); + } + public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) throws IOException { + int tag = data.readUnsignedByte(); + + switch (tag) { + case 'e': // enum constant + String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + String constName = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + FieldDescriptor descr = FieldDescriptor.parseDescriptor(className); + return new FieldExprent(constName, descr.type.value, true, null, descr); + + case 'c': // class + String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + VarType type = FieldDescriptor.parseDescriptor(descriptor).type; + + String value; + switch (type.type) { + case CodeConstants.TYPE_OBJECT: + value = type.value; + break; + case CodeConstants.TYPE_BYTE: + value = byte.class.getName(); + break; + case CodeConstants.TYPE_CHAR: + value = char.class.getName(); + break; + case CodeConstants.TYPE_DOUBLE: + value = double.class.getName(); + break; + case CodeConstants.TYPE_FLOAT: + value = float.class.getName(); + break; + case CodeConstants.TYPE_INT: + value = int.class.getName(); + break; + case CodeConstants.TYPE_LONG: + value = long.class.getName(); + break; + case CodeConstants.TYPE_SHORT: + value = short.class.getName(); + break; + case CodeConstants.TYPE_BOOLEAN: + value = boolean.class.getName(); + break; + case CodeConstants.TYPE_VOID: + value = void.class.getName(); + break; + default: + throw new RuntimeException("invalid class type: " + type.type); + } + return new ConstExprent(VarType.VARTYPE_CLASS, value); + + case '[': // array + List elements = Collections.emptyList(); + int len = data.readUnsignedShort(); + if (len > 0) { + elements = new ArrayList(len); for (int i = 0; i < len; i++) { - lst.add(parseAnnotationElement(data, pool)); - } - - VarType newtype; - if (lst.isEmpty()) { - newtype = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); - } - else { - VarType eltype = lst.get(0).getExprType(); - newtype = new VarType(eltype.type, 1, eltype.value); + elements.add(parseAnnotationElement(data, pool)); } - - NewExprent newexpr = new NewExprent(newtype, new ArrayList()); - newexpr.setDirectArrayInit(true); - newexpr.setLstArrayElements(lst); - return newexpr; - case '@': // annotation - return parseAnnotation(data, pool); - default: - PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); - switch (tag) { - case 'B': - return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); - case 'C': - return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); - case 'D': - return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); - case 'F': - return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); - case 'I': - return new ConstExprent(VarType.VARTYPE_INT, cn.value); - case 'J': - return new ConstExprent(VarType.VARTYPE_LONG, cn.value); - case 'S': - return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); - case 'Z': - return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); - case 's': - return new ConstExprent(VarType.VARTYPE_STRING, cn.value); - default: - throw new RuntimeException("invalid element type!"); - } - } - } - catch (IOException ex) { - throw new RuntimeException(ex); + } + + VarType newType; + if (elements.isEmpty()) { + newType = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); + } + else { + VarType elementType = elements.get(0).getExprType(); + newType = new VarType(elementType.type, 1, elementType.value); + } + + NewExprent newExpr = new NewExprent(newType, Collections.emptyList()); + newExpr.setDirectArrayInit(true); + newExpr.setLstArrayElements(elements); + return newExpr; + + case '@': // annotation + return parseAnnotation(data, pool); + + default: + PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); + switch (tag) { + case 'B': + return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); + case 'C': + return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); + case 'D': + return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); + case 'F': + return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); + case 'I': + return new ConstExprent(VarType.VARTYPE_INT, cn.value); + case 'J': + return new ConstExprent(VarType.VARTYPE_LONG, cn.value); + case 'S': + return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); + case 'Z': + return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); + case 's': + return new ConstExprent(VarType.VARTYPE_STRING, cn.value); + default: + throw new RuntimeException("invalid element type!"); + } } } - public List getAnnotations() { return annotations; } -- cgit v1.2.3