Skip to content
Commits on Source (7)
......@@ -350,24 +350,9 @@ public class Frame<V extends Value> {
break;
case Opcodes.DUP_X2:
value1 = pop();
if (value1.getSize() == 1) {
value2 = pop();
if (value2.getSize() == 1) {
value3 = pop();
if (value3.getSize() == 1) {
push(interpreter.copyOperation(insn, value1));
push(value3);
push(value2);
push(value1);
break;
}
} else {
push(interpreter.copyOperation(insn, value1));
push(value2);
push(value1);
if (value1.getSize() == 1 && executeDupX2(insn, value1, interpreter)) {
break;
}
}
throw new AnalyzerException(insn, "Illegal use of DUP_X2");
case Opcodes.DUP2:
value1 = pop();
......@@ -437,24 +422,9 @@ public class Frame<V extends Value> {
break;
}
}
} else {
value2 = pop();
if (value2.getSize() == 1) {
value3 = pop();
if (value3.getSize() == 1) {
push(interpreter.copyOperation(insn, value1));
push(value3);
push(value2);
push(value1);
break;
}
} else {
push(interpreter.copyOperation(insn, value1));
push(value2);
push(value1);
} else if (executeDupX2(insn, value1, interpreter)) {
break;
}
}
throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
case Opcodes.SWAP:
value2 = pop();
......@@ -640,6 +610,28 @@ public class Frame<V extends Value> {
}
}
private boolean executeDupX2(
final AbstractInsnNode insn, final V value1, final Interpreter<V> interpreter)
throws AnalyzerException {
V value2 = pop();
if (value2.getSize() == 1) {
V value3 = pop();
if (value3.getSize() == 1) {
push(interpreter.copyOperation(insn, value1));
push(value3);
push(value2);
push(value1);
return true;
}
} else {
push(interpreter.copyOperation(insn, value1));
push(value2);
push(value1);
return true;
}
return false;
}
private void executeInvokeInsn(
final AbstractInsnNode insn, final String methodDescriptor, final Interpreter<V> interpreter)
throws AnalyzerException {
......
......@@ -254,7 +254,7 @@ public class SimpleVerifier extends BasicVerifier {
type1 = type1.getElementType();
type2 = type2.getElementType();
}
do {
while (true) {
if (type1 == null || isInterface(type1)) {
return newArrayValue(Type.getObjectType("java/lang/Object"), numDimensions);
}
......@@ -262,7 +262,7 @@ public class SimpleVerifier extends BasicVerifier {
if (isAssignableFrom(type1, type2)) {
return newArrayValue(type1, numDimensions);
}
} while (true);
}
}
return BasicValue.UNINITIALIZED_VALUE;
}
......
......@@ -72,9 +72,8 @@ final class Subroutine {
*/
Subroutine(final Subroutine subroutine) {
this.start = subroutine.start;
this.localsUsed = new boolean[subroutine.localsUsed.length];
this.localsUsed = subroutine.localsUsed.clone();
this.callers = new ArrayList<>(subroutine.callers);
System.arraycopy(subroutine.localsUsed, 0, this.localsUsed, 0, subroutine.localsUsed.length);
}
/**
......
......@@ -351,6 +351,8 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
popValue();
popValue();
break;
case RET:
break;
default:
throw new IllegalArgumentException(INVALID_OPCODE + opcode);
}
......
......@@ -41,6 +41,20 @@ import org.objectweb.asm.TypePath;
/**
* A {@link ClassVisitor} that remaps types with a {@link Remapper}.
*
* <p><i>This visitor has several limitations</i>. A non-exhaustive list is the following:
*
* <ul>
* <li>it cannot remap type names in dynamically computed strings (remapping of type names in
* static values is supported).
* <li>it cannot remap values derived from type names at compile time, such as
* <ul>
* <li>type name hashcodes used by some Java compilers to implement the string switch
* statement.
* <li>some compound strings used by some Java compilers to implement lambda
* deserialization.
* </ul>
* </ul>
*
* @author Eugene Kuleshov
*/
public class ClassRemapper extends ClassVisitor {
......
......@@ -758,48 +758,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
|| to.getSort() > Type.DOUBLE) {
throw new IllegalArgumentException("Cannot cast from " + from + " to " + to);
}
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
InstructionAdapter.cast(mv, from, to);
}
}
......@@ -1316,37 +1275,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
* @param type the type of the array elements.
*/
public void newArray(final Type type) {
int arrayType;
switch (type.getSort()) {
case Type.BOOLEAN:
arrayType = Opcodes.T_BOOLEAN;
break;
case Type.CHAR:
arrayType = Opcodes.T_CHAR;
break;
case Type.BYTE:
arrayType = Opcodes.T_BYTE;
break;
case Type.SHORT:
arrayType = Opcodes.T_SHORT;
break;
case Type.INT:
arrayType = Opcodes.T_INT;
break;
case Type.FLOAT:
arrayType = Opcodes.T_FLOAT;
break;
case Type.LONG:
arrayType = Opcodes.T_LONG;
break;
case Type.DOUBLE:
arrayType = Opcodes.T_DOUBLE;
break;
default:
typeInsn(Opcodes.ANEWARRAY, type);
return;
}
mv.visitIntInsn(Opcodes.NEWARRAY, arrayType);
InstructionAdapter.newarray(mv, type);
}
// -----------------------------------------------------------------------------------------------
......
......@@ -895,47 +895,58 @@ public class InstructionAdapter extends MethodVisitor {
* @param to a Type.
*/
public void cast(final Type from, final Type to) {
cast(mv, from, to);
}
/**
* Generates the instruction to cast from the first given type to the other.
*
* @param methodVisitor the method visitor to use to generate the instruction.
* @param from a Type.
* @param to a Type.
*/
static void cast(final MethodVisitor methodVisitor, final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
methodVisitor.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
methodVisitor.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
methodVisitor.visitInsn(Opcodes.D2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
methodVisitor.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
methodVisitor.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
methodVisitor.visitInsn(Opcodes.F2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
methodVisitor.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
methodVisitor.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
methodVisitor.visitInsn(Opcodes.L2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
methodVisitor.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
methodVisitor.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
methodVisitor.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
methodVisitor.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
methodVisitor.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
methodVisitor.visitInsn(Opcodes.I2S);
}
}
}
......@@ -1204,6 +1215,16 @@ public class InstructionAdapter extends MethodVisitor {
* @param type an array Type.
*/
public void newarray(final Type type) {
newarray(mv, type);
}
/**
* Generates the instruction to create and push on the stack an array of the given type.
*
* @param methodVisitor the method visitor to use to generate the instruction.
* @param type an array Type.
*/
static void newarray(final MethodVisitor methodVisitor, final Type type) {
int arrayType;
switch (type.getSort()) {
case Type.BOOLEAN:
......@@ -1231,10 +1252,10 @@ public class InstructionAdapter extends MethodVisitor {
arrayType = Opcodes.T_DOUBLE;
break;
default:
mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
return;
}
mv.visitIntInsn(Opcodes.NEWARRAY, arrayType);
methodVisitor.visitIntInsn(Opcodes.NEWARRAY, arrayType);
}
public void arraylength() {
......
......@@ -110,8 +110,7 @@ public abstract class Remapper {
String remappedInternalName = mapType(internalName);
if (remappedInternalName != null) {
if (remappedInternalNames == null) {
remappedInternalNames = new String[internalNames.length];
System.arraycopy(internalNames, 0, remappedInternalNames, 0, internalNames.length);
remappedInternalNames = internalNames.clone();
}
remappedInternalNames[i] = remappedInternalName;
}
......
......@@ -186,11 +186,10 @@ public class SerialVersionUIDAdder extends ClassVisitor {
if (computeSvuid) {
this.name = name;
this.access = access;
this.interfaces = new String[interfaces.length];
this.interfaces = interfaces.clone();
this.svuidFields = new ArrayList<>();
this.svuidConstructors = new ArrayList<>();
this.svuidMethods = new ArrayList<>();
System.arraycopy(interfaces, 0, this.interfaces, 0, interfaces.length);
}
super.visit(version, access, name, signature, superName, interfaces);
......
......@@ -405,6 +405,44 @@ public class AdviceAdapterTest extends AsmTest {
assertDoesNotThrow(() -> buildClassWithMethod(outputMethod).newInstance());
}
@Test
public void testAllMethods_constructorWithJsrRet() {
Label label0 = new Label();
Label label1 = new Label();
Label label2 = new Label();
Label label3 = new Label();
MethodNode inputMethod =
new MethodNodeBuilder("<init>", "(I)V", 3, 3)
.trycatch(label0, label1, label1)
.label(label0)
.aload(0)
.methodInsn(Opcodes.INVOKESPECIAL, "C", "<init>", "()V", false)
// After instrumentation, expect a before advice here, before instruction #3.
.go(label3)
.label(label1)
.jsr(label2)
// After instrumentation, expect an after advice here, before instruction #6.
.athrow()
.label(label2)
.astore(2)
.ret(2)
.label(label3)
// After instrumentation, expect an after advice here, before instruction #11.
.vreturn()
.build();
MethodNode outputMethod = new MethodNode(Opcodes.ACC_PUBLIC, "<init>", "(I)V", null, null);
inputMethod.accept(new BasicAdviceAdapter(outputMethod));
MethodNode expectedMethod =
new ExpectedMethodBuilder(inputMethod)
.withBeforeAdviceAt(3)
.withAfterAdviceAt(6, 11)
.build();
assertEquals(toText(expectedMethod), toText(outputMethod));
assertDoesNotThrow(() -> buildClassWithMethod(outputMethod).newInstance());
}
@Test
public void testAllMethods_constructorWithLongsAndArrays() {
MethodNode inputMethod =
......
......@@ -218,10 +218,14 @@ public class AnalyzerAdapterTest extends AsmTest {
*/
private ArrayList<Object> toFrameTypes(final List<Object> analyzerTypes) {
ArrayList<Object> frameTypes = new ArrayList<>();
for (int i = 0; i < analyzerTypes.size(); ) {
for (int i = 0; i < analyzerTypes.size(); ++i) {
if (i > 0
&& (analyzerTypes.get(i - 1) == Opcodes.LONG
|| analyzerTypes.get(i - 1) == Opcodes.DOUBLE)) {
continue;
}
Object value = analyzerTypes.get(i);
frameTypes.add(value);
i += (value == Opcodes.LONG || value == Opcodes.DOUBLE) ? 2 : 1;
}
return frameTypes;
}
......
This diff is collapsed.
......@@ -288,7 +288,7 @@ public class ClassFile {
builder.add("magic: ", parser.u4());
builder.add("minor_version: ", parser.u2());
int majorVersion = parser.u2();
if (majorVersion > /* V12 = */ 56) {
if (majorVersion > /* V14 = */ 58) {
throw new ClassFormatException("Unsupported class version");
}
builder.add("major_version: ", majorVersion);
......@@ -1747,6 +1747,8 @@ public class ClassFile {
}
/**
* Returns the constant pool item with the given index.
*
* @param <C> a CpInfo subclass.
* @param cpIndex a constant pool entry index.
* @param cpInfoType the expected type of the constant pool entry.
......@@ -2335,7 +2337,7 @@ public class ClassFile {
private abstract static class AbstractBuilder<T> implements ClassContext, MethodContext {
/** Flag used to distinguish CpInfo keys in {@link #context}. */
private static final int CP_INFO_KEY = 0xF0000000;
/** The parent node of this node. May be null. */
/** The parent node of this node. May be {@literal null}. */
private final AbstractBuilder<?> parent;
/** The children of this builder. */
final ArrayList<T> children;
......
......@@ -207,15 +207,9 @@ public class ClassNode extends ClassVisitor {
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
AnnotationNode annotation = new AnnotationNode(descriptor);
if (visible) {
if (visibleAnnotations == null) {
visibleAnnotations = new ArrayList<>(1);
}
visibleAnnotations.add(annotation);
visibleAnnotations = Util.add(visibleAnnotations, annotation);
} else {
if (invisibleAnnotations == null) {
invisibleAnnotations = new ArrayList<>(1);
}
invisibleAnnotations.add(annotation);
invisibleAnnotations = Util.add(invisibleAnnotations, annotation);
}
return annotation;
}
......@@ -225,33 +219,21 @@ public class ClassNode extends ClassVisitor {
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
if (visible) {
if (visibleTypeAnnotations == null) {
visibleTypeAnnotations = new ArrayList<>(1);
}
visibleTypeAnnotations.add(typeAnnotation);
visibleTypeAnnotations = Util.add(visibleTypeAnnotations, typeAnnotation);
} else {
if (invisibleTypeAnnotations == null) {
invisibleTypeAnnotations = new ArrayList<>(1);
}
invisibleTypeAnnotations.add(typeAnnotation);
invisibleTypeAnnotations = Util.add(invisibleTypeAnnotations, typeAnnotation);
}
return typeAnnotation;
}
@Override
public void visitAttribute(final Attribute attribute) {
if (attrs == null) {
attrs = new ArrayList<>(1);
}
attrs.add(attribute);
attrs = Util.add(attrs, attribute);
}
@Override
public void visitNestMember(final String nestMember) {
if (nestMembers == null) {
nestMembers = new ArrayList<>();
}
nestMembers.add(nestMember);
nestMembers = Util.add(nestMembers, nestMember);
}
@Override
......
......@@ -27,7 +27,6 @@
// THE POSSIBILITY OF SUCH DAMAGE.
package org.objectweb.asm.tree;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
......@@ -143,15 +142,9 @@ public class FieldNode extends FieldVisitor {
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
AnnotationNode annotation = new AnnotationNode(descriptor);
if (visible) {
if (visibleAnnotations == null) {
visibleAnnotations = new ArrayList<>(1);
}
visibleAnnotations.add(annotation);
visibleAnnotations = Util.add(visibleAnnotations, annotation);
} else {
if (invisibleAnnotations == null) {
invisibleAnnotations = new ArrayList<>(1);
}
invisibleAnnotations.add(annotation);
invisibleAnnotations = Util.add(invisibleAnnotations, annotation);
}
return annotation;
}
......@@ -161,25 +154,16 @@ public class FieldNode extends FieldVisitor {
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
if (visible) {
if (visibleTypeAnnotations == null) {
visibleTypeAnnotations = new ArrayList<>(1);
}
visibleTypeAnnotations.add(typeAnnotation);
visibleTypeAnnotations = Util.add(visibleTypeAnnotations, typeAnnotation);
} else {
if (invisibleTypeAnnotations == null) {
invisibleTypeAnnotations = new ArrayList<>(1);
}
invisibleTypeAnnotations.add(typeAnnotation);
invisibleTypeAnnotations = Util.add(invisibleTypeAnnotations, typeAnnotation);
}
return typeAnnotation;
}
@Override
public void visitAttribute(final Attribute attribute) {
if (attrs == null) {
attrs = new ArrayList<>(1);
}
attrs.add(attribute);
attrs = Util.add(attrs, attribute);
}
@Override
......
......@@ -35,7 +35,7 @@ import org.objectweb.asm.MethodVisitor;
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This implementation is not thread
* safe</i>.
*/
public class InsnList {
public class InsnList implements Iterable<AbstractInsnNode> {
/** The number of instructions in this list. */
private int size;
......@@ -151,6 +151,7 @@ public class InsnList {
*
* @return an iterator over the instructions in this list.
*/
@Override
public ListIterator<AbstractInsnNode> iterator() {
return iterator(0);
}
......
......@@ -259,15 +259,9 @@ public class MethodNode extends MethodVisitor {
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
AnnotationNode annotation = new AnnotationNode(descriptor);
if (visible) {
if (visibleAnnotations == null) {
visibleAnnotations = new ArrayList<>(1);
}
visibleAnnotations.add(annotation);
visibleAnnotations = Util.add(visibleAnnotations, annotation);
} else {
if (invisibleAnnotations == null) {
invisibleAnnotations = new ArrayList<>(1);
}
invisibleAnnotations.add(annotation);
invisibleAnnotations = Util.add(invisibleAnnotations, annotation);
}
return annotation;
}
......@@ -277,15 +271,9 @@ public class MethodNode extends MethodVisitor {
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
if (visible) {
if (visibleTypeAnnotations == null) {
visibleTypeAnnotations = new ArrayList<>(1);
}
visibleTypeAnnotations.add(typeAnnotation);
visibleTypeAnnotations = Util.add(visibleTypeAnnotations, typeAnnotation);
} else {
if (invisibleTypeAnnotations == null) {
invisibleTypeAnnotations = new ArrayList<>(1);
}
invisibleTypeAnnotations.add(typeAnnotation);
invisibleTypeAnnotations = Util.add(invisibleTypeAnnotations, typeAnnotation);
}
return typeAnnotation;
}
......@@ -309,29 +297,22 @@ public class MethodNode extends MethodVisitor {
int params = Type.getArgumentTypes(desc).length;
visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (visibleParameterAnnotations[parameter] == null) {
visibleParameterAnnotations[parameter] = new ArrayList<>(1);
}
visibleParameterAnnotations[parameter].add(annotation);
visibleParameterAnnotations[parameter] =
Util.add(visibleParameterAnnotations[parameter], annotation);
} else {
if (invisibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(desc).length;
invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (invisibleParameterAnnotations[parameter] == null) {
invisibleParameterAnnotations[parameter] = new ArrayList<>(1);
}
invisibleParameterAnnotations[parameter].add(annotation);
invisibleParameterAnnotations[parameter] =
Util.add(invisibleParameterAnnotations[parameter], annotation);
}
return annotation;
}
@Override
public void visitAttribute(final Attribute attribute) {
if (attrs == null) {
attrs = new ArrayList<>(1);
}
attrs.add(attribute);
attrs = Util.add(attrs, attribute);
}
@Override
......@@ -456,15 +437,11 @@ public class MethodNode extends MethodVisitor {
// Add the annotation to this instruction.
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
if (visible) {
if (currentInsn.visibleTypeAnnotations == null) {
currentInsn.visibleTypeAnnotations = new ArrayList<>(1);
}
currentInsn.visibleTypeAnnotations.add(typeAnnotation);
currentInsn.visibleTypeAnnotations =
Util.add(currentInsn.visibleTypeAnnotations, typeAnnotation);
} else {
if (currentInsn.invisibleTypeAnnotations == null) {
currentInsn.invisibleTypeAnnotations = new ArrayList<>(1);
}
currentInsn.invisibleTypeAnnotations.add(typeAnnotation);
currentInsn.invisibleTypeAnnotations =
Util.add(currentInsn.invisibleTypeAnnotations, typeAnnotation);
}
return typeAnnotation;
}
......@@ -472,11 +449,9 @@ public class MethodNode extends MethodVisitor {
@Override
public void visitTryCatchBlock(
final Label start, final Label end, final Label handler, final String type) {
if (tryCatchBlocks == null) {
tryCatchBlocks = new ArrayList<>(1);
}
tryCatchBlocks.add(
new TryCatchBlockNode(getLabelNode(start), getLabelNode(end), getLabelNode(handler), type));
TryCatchBlockNode tryCatchBlock =
new TryCatchBlockNode(getLabelNode(start), getLabelNode(end), getLabelNode(handler), type);
tryCatchBlocks = Util.add(tryCatchBlocks, tryCatchBlock);
}
@Override
......@@ -485,15 +460,11 @@ public class MethodNode extends MethodVisitor {
TryCatchBlockNode tryCatchBlock = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
if (visible) {
if (tryCatchBlock.visibleTypeAnnotations == null) {
tryCatchBlock.visibleTypeAnnotations = new ArrayList<>(1);
}
tryCatchBlock.visibleTypeAnnotations.add(typeAnnotation);
tryCatchBlock.visibleTypeAnnotations =
Util.add(tryCatchBlock.visibleTypeAnnotations, typeAnnotation);
} else {
if (tryCatchBlock.invisibleTypeAnnotations == null) {
tryCatchBlock.invisibleTypeAnnotations = new ArrayList<>(1);
}
tryCatchBlock.invisibleTypeAnnotations.add(typeAnnotation);
tryCatchBlock.invisibleTypeAnnotations =
Util.add(tryCatchBlock.invisibleTypeAnnotations, typeAnnotation);
}
return typeAnnotation;
}
......@@ -506,12 +477,10 @@ public class MethodNode extends MethodVisitor {
final Label start,
final Label end,
final int index) {
if (localVariables == null) {
localVariables = new ArrayList<>(1);
}
localVariables.add(
LocalVariableNode localVariable =
new LocalVariableNode(
name, descriptor, signature, getLabelNode(start), getLabelNode(end), index));
name, descriptor, signature, getLabelNode(start), getLabelNode(end), index);
localVariables = Util.add(localVariables, localVariable);
}
@Override
......@@ -527,15 +496,11 @@ public class MethodNode extends MethodVisitor {
new LocalVariableAnnotationNode(
typeRef, typePath, getLabelNodes(start), getLabelNodes(end), index, descriptor);
if (visible) {
if (visibleLocalVariableAnnotations == null) {
visibleLocalVariableAnnotations = new ArrayList<>(1);
}
visibleLocalVariableAnnotations.add(localVariableAnnotation);
visibleLocalVariableAnnotations =
Util.add(visibleLocalVariableAnnotations, localVariableAnnotation);
} else {
if (invisibleLocalVariableAnnotations == null) {
invisibleLocalVariableAnnotations = new ArrayList<>(1);
}
invisibleLocalVariableAnnotations.add(localVariableAnnotation);
invisibleLocalVariableAnnotations =
Util.add(invisibleLocalVariableAnnotations, localVariableAnnotation);
}
return localVariableAnnotation;
}
......
......@@ -40,6 +40,12 @@ final class Util {
private Util() {}
static <T> List<T> add(final List<T> list, final T element) {
List<T> newList = list == null ? new ArrayList<>(1) : list;
newList.add(element);
return newList;
}
static <T> List<T> asArrayList(final int length) {
List<T> list = new ArrayList<>(length);
for (int i = 0; i < length; ++i) {
......
This diff is collapsed.
/**
* ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA,
* France Telecom All rights reserved.
*
* <p>Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met: 1. Redistributions of source code must retain the
* above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions
* in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.objectweb.asm.util;
import java.util.Map;
import org.objectweb.asm.Label;
/**
* An {@link org.objectweb.asm.Attribute} that can generate the ASM code to create an equivalent
* attribute.
*
* @author Eugene Kuleshov
* @deprecated This interface is no longer supported (since ASM 7.1), because it uses a StringBuffer
* instead of a StringBuilder. Use {@link ASMifierSupport} instead.
*/
@Deprecated
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public interface ASMifiable {
/**
* Generates the ASM code to create an attribute equal to this attribute.
*
* @param outputBuffer where the generated code must be appended.
* @param visitorVariableName the name of the visitor variable in the produced code.
* @param labelNames the names of the labels in the generated code.
*/
void asmify(StringBuffer outputBuffer, String visitorVariableName, Map<Label, String> labelNames);
}