8323835: Updating ASM to 9.6 for JDK 23

Reviewed-by: mchung
This commit is contained in:
Vicente Romero 2024-01-26 18:34:56 +00:00
parent a65a89522d
commit 91d8ea79d9
127 changed files with 1355 additions and 503 deletions

View File

@ -112,6 +112,17 @@ public abstract class AnnotationVisitor {
this.av = annotationVisitor;
}
/**
* The annotation visitor to which this visitor must delegate method calls. May be {@literal
* null}.
*
* @return the annotation visitor to which this visitor must delegate method calls, or {@literal
* null}.
*/
public AnnotationVisitor getDelegate() {
return av;
}
/**
* Visits a primitive value of the annotation.
*

View File

@ -403,4 +403,3 @@ public class ByteVector {
data = newData;
}
}

View File

@ -407,7 +407,7 @@ public class ClassReader {
}
/**
* Returns the internal of name of the super class (see {@link Type#getInternalName()}). For
* Returns the internal name of the super class (see {@link Type#getInternalName()}). For
* interfaces, the super class is {@link Object}.
*
* @return the internal name of the super class, or {@literal null} for {@link Object} class.
@ -2082,6 +2082,7 @@ public class ClassReader {
currentOffset = bytecodeStartOffset;
while (currentOffset < bytecodeEndOffset) {
final int currentBytecodeOffset = currentOffset - bytecodeStartOffset;
readBytecodeInstructionOffset(currentBytecodeOffset);
// Visit the label and the line number(s) for this bytecode offset, if any.
Label currentLabel = labels[currentBytecodeOffset];
@ -2697,6 +2698,20 @@ public class ClassReader {
methodVisitor.visitMaxs(maxStack, maxLocals);
}
/**
* Handles the bytecode offset of the next instruction to be visited in {@link
* #accept(ClassVisitor,int)}. This method is called just before the instruction and before its
* associated label and stack map frame, if any. The default implementation of this method does
* nothing. Subclasses can override this method to store the argument in a mutable field, for
* instance, so that {@link MethodVisitor} instances can get the bytecode offset of each visited
* instruction (if so, the usual concurrency issues related to mutable data should be addressed).
*
* @param bytecodeOffset the bytecode offset of the next instruction to be visited.
*/
protected void readBytecodeInstructionOffset(final int bytecodeOffset) {
// Do nothing by default.
}
/**
* Returns the label corresponding to the given bytecode offset. The default implementation of
* this method creates a label for the given offset if it has not been already created.
@ -3882,4 +3897,3 @@ public class ClassReader {
}
}
}

View File

@ -74,7 +74,8 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException {
/**
* Constructs a new {@link ClassTooLargeException}.
*
* @param className the internal name of the class.
* @param className the internal name of the class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param constantPoolCount the number of constant pool items of the class.
*/
public ClassTooLargeException(final String className, final int constantPoolCount) {
@ -84,7 +85,7 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException {
}
/**
* Returns the internal name of the class.
* Returns the internal name of the class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*
* @return the internal name of the class.
*/
@ -101,4 +102,3 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException {
return constantPoolCount;
}
}

View File

@ -111,6 +111,15 @@ public abstract class ClassVisitor {
this.cv = classVisitor;
}
/**
* The class visitor to which this visitor must delegate method calls. May be {@literal null}.
*
* @return the class visitor to which this visitor must delegate method calls, or {@literal null}.
*/
public ClassVisitor getDelegate() {
return cv;
}
/**
* Visits the header of the class.
*
@ -185,7 +194,8 @@ public abstract class ClassVisitor {
* implicitly its own nest, so it's invalid to call this method with the visited class name as
* argument.
*
* @param nestHost the internal name of the host class of the nest.
* @param nestHost the internal name of the host class of the nest (see {@link
* Type#getInternalName()}).
*/
public void visitNestHost(final String nestHost) {
if (api < Opcodes.ASM7) {
@ -197,14 +207,19 @@ public abstract class ClassVisitor {
}
/**
* Visits the enclosing class of the class. This method must be called only if the class has an
* enclosing class.
* Visits the enclosing class of the class. This method must be called only if this class is a
* local or anonymous class. See the JVMS 4.7.7 section for more details.
*
* @param owner internal name of the enclosing class of the class.
* @param owner internal name of the enclosing class of the class (see {@link
* Type#getInternalName()}).
* @param name the name of the method that contains the class, or {@literal null} if the class is
* not enclosed in a method of its enclosing class.
* not enclosed in a method or constructor of its enclosing class (e.g. if it is enclosed in
* an instance initializer, static initializer, instance variable initializer, or class
* variable initializer).
* @param descriptor the descriptor of the method that contains the class, or {@literal null} if
* the class is not enclosed in a method of its enclosing class.
* the class is not enclosed in a method or constructor of its enclosing class (e.g. if it is
* enclosed in an instance initializer, static initializer, instance variable initializer, or
* class variable initializer).
*/
public void visitOuterClass(final String owner, final String name, final String descriptor) {
if (cv != null) {
@ -271,7 +286,7 @@ public abstract class ClassVisitor {
* the visited class is the host of a nest. A nest host is implicitly a member of its own nest, so
* it's invalid to call this method with the visited class name as argument.
*
* @param nestMember the internal name of a nest member.
* @param nestMember the internal name of a nest member (see {@link Type#getInternalName()}).
*/
public void visitNestMember(final String nestMember) {
if (api < Opcodes.ASM7) {
@ -286,7 +301,8 @@ public abstract class ClassVisitor {
* Visits a permitted subclasses. A permitted subclass is one of the allowed subclasses of the
* current class.
*
* @param permittedSubclass the internal name of a permitted subclass.
* @param permittedSubclass the internal name of a permitted subclass (see {@link
* Type#getInternalName()}).
*/
public void visitPermittedSubclass(final String permittedSubclass) {
if (api < Opcodes.ASM9) {
@ -299,15 +315,18 @@ public abstract class ClassVisitor {
/**
* Visits information about an inner class. This inner class is not necessarily a member of the
* class being visited.
* class being visited. More precisely, every class or interface C which is referenced by this
* class and which is not a package member must be visited with this method. This class must
* reference its nested class or interface members, and its enclosing class, if any. See the JVMS
* 4.7.6 section for more details.
*
* @param name the internal name of an inner class (see {@link Type#getInternalName()}).
* @param outerName the internal name of the class to which the inner class belongs (see {@link
* Type#getInternalName()}). May be {@literal null} for not member classes.
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
* {@literal null} for anonymous inner classes.
* @param access the access flags of the inner class as originally declared in the enclosing
* class.
* @param name the internal name of C (see {@link Type#getInternalName()}).
* @param outerName the internal name of the class or interface C is a member of (see {@link
* Type#getInternalName()}). Must be {@literal null} if C is not the member of a class or
* interface (e.g. for local or anonymous classes).
* @param innerName the (simple) name of C. Must be {@literal null} for anonymous inner classes.
* @param access the access flags of C originally declared in the source code from which this
* class was compiled.
*/
public void visitInnerClass(
final String name, final String outerName, final String innerName, final int access) {
@ -405,4 +424,3 @@ public abstract class ClassVisitor {
}
}
}

View File

@ -249,6 +249,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Indicates what must be automatically computed in {@link MethodWriter}. Must be one of {@link
* MethodWriter#COMPUTE_NOTHING}, {@link MethodWriter#COMPUTE_MAX_STACK_AND_LOCAL}, {@link
* MethodWriter#COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link
* MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}.
*/
private int compute;
@ -874,7 +875,7 @@ public class ClassWriter extends ClassVisitor {
* constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
* sub classes, and is normally not needed by class generators or adapters.</i>
*
* @param value the internal name of the class.
* @param value the internal name of the class (see {@link Type#getInternalName()}).
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
@ -926,7 +927,8 @@ public class ClassWriter extends ClassVisitor {
* Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
* Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the field or method owner class.
* @param owner the internal name of the field or method owner class (see {@link
* Type#getInternalName()}).
* @param name the name of the field or method.
* @param descriptor the descriptor of the field or method.
* @return the index of a new or already existing method type reference item.
@ -948,7 +950,8 @@ public class ClassWriter extends ClassVisitor {
* Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
* Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the field or method owner class.
* @param owner the internal name of the field or method owner class (see {@link
* Type#getInternalName()}).
* @param name the name of the field or method.
* @param descriptor the descriptor of the field or method.
* @param isInterface true if the owner is an interface.
@ -1010,7 +1013,7 @@ public class ClassWriter extends ClassVisitor {
* constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
* sub classes, and is normally not needed by class generators or adapters.</i>
*
* @param owner the internal name of the field's owner class.
* @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}).
* @param name the field's name.
* @param descriptor the field's descriptor.
* @return the index of a new or already existing field reference item.
@ -1024,7 +1027,8 @@ public class ClassWriter extends ClassVisitor {
* constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
* sub classes, and is normally not needed by class generators or adapters.</i>
*
* @param owner the internal name of the method's owner class.
* @param owner the internal name of the method's owner class (see {@link
* Type#getInternalName()}).
* @param name the method's name.
* @param descriptor the method's descriptor.
* @param isInterface {@literal true} if {@code owner} is an interface.
@ -1060,9 +1064,10 @@ public class ClassWriter extends ClassVisitor {
* currently being generated by this ClassWriter, which can of course not be loaded since it is
* under construction.
*
* @param type1 the internal name of a class.
* @param type2 the internal name of another class.
* @return the internal name of the common super class of the two given classes.
* @param type1 the internal name of a class (see {@link Type#getInternalName()}).
* @param type2 the internal name of another class (see {@link Type#getInternalName()}).
* @return the internal name of the common super class of the two given classes (see {@link
* Type#getInternalName()}).
*/
protected String getCommonSuperClass(final String type1, final String type2) {
ClassLoader classLoader = getClassLoader();
@ -1105,4 +1110,3 @@ public class ClassWriter extends ClassVisitor {
return getClass().getClassLoader();
}
}

View File

@ -208,4 +208,3 @@ public final class ConstantDynamic {
+ Arrays.toString(bootstrapMethodArguments);
}
}

View File

@ -251,4 +251,3 @@ final class Constants {
}
}
}

View File

@ -166,4 +166,3 @@ final class Context {
*/
Object[] currentFrameStackTypes;
}

View File

@ -85,4 +85,3 @@ final class CurrentFrame extends Frame {
copyFrom(successor);
}
}

View File

@ -121,4 +121,3 @@ final class Edge {
this.nextEdge = nextEdge;
}
}

View File

@ -108,6 +108,15 @@ public abstract class FieldVisitor {
this.fv = fieldVisitor;
}
/**
* The field visitor to which this visitor must delegate method calls. May be {@literal null}.
*
* @return the field visitor to which this visitor must delegate method calls, or {@literal null}.
*/
public FieldVisitor getDelegate() {
return fv;
}
/**
* Visits an annotation of the field.
*
@ -168,4 +177,3 @@ public abstract class FieldVisitor {
}
}
}

View File

@ -314,4 +314,3 @@ final class FieldWriter extends FieldVisitor {
attributePrototypes.addAttributes(firstAttribute);
}
}

View File

@ -96,8 +96,8 @@ package jdk.internal.org.objectweb.asm;
* right shift of {@link #DIM_SHIFT}.
* <li>the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be
* retrieved with {@link #KIND_MASK} and, without any shift, must be equal to {@link
* #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link #LOCAL_KIND}
* or {@link #STACK_KIND}.
* #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link
* #FORWARD_UNINITIALIZED_KIND},{@link #LOCAL_KIND} or {@link #STACK_KIND}.
* <li>the FLAGS field, stored in 2 bits, contains up to 2 boolean flags. Currently only one flag
* is defined, namely {@link #TOP_IF_LONG_OR_DOUBLE_FLAG}.
* <li>the VALUE field, stored in the remaining 20 bits, contains either
@ -110,7 +110,10 @@ package jdk.internal.org.objectweb.asm;
* <li>the index of a {@link Symbol#TYPE_TAG} {@link Symbol} in the type table of a {@link
* SymbolTable}, if KIND is equal to {@link #REFERENCE_KIND}.
* <li>the index of an {@link Symbol#UNINITIALIZED_TYPE_TAG} {@link Symbol} in the type
* table of a SymbolTable, if KIND is equal to {@link #UNINITIALIZED_KIND}.
* table of a {@link SymbolTable}, if KIND is equal to {@link #UNINITIALIZED_KIND}.
* <li>the index of a {@link Symbol#FORWARD_UNINITIALIZED_TYPE_TAG} {@link Symbol} in the
* type table of a {@link SymbolTable}, if KIND is equal to {@link
* #FORWARD_UNINITIALIZED_KIND}.
* <li>the index of a local variable in the input stack frame, if KIND is equal to {@link
* #LOCAL_KIND}.
* <li>a position relatively to the top of the stack of the input stack frame, if KIND is
@ -120,10 +123,10 @@ package jdk.internal.org.objectweb.asm;
*
* <p>Output frames can contain abstract types of any kind and with a positive or negative array
* dimension (and even unassigned types, represented by 0 - which does not correspond to any valid
* abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND or
* UNINITIALIZED_KIND abstract types of positive or {@literal null} array dimension. In all cases
* the type table contains only internal type names (array type descriptors are forbidden - array
* dimensions must be represented through the DIM field).
* abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND,
* UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract types of positive or {@literal null}
* array dimension. In all cases the type table contains only internal type names (array type
* descriptors are forbidden - array dimensions must be represented through the DIM field).
*
* <p>The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE +
* TOP), for local variables as well as in the operand stack. This is necessary to be able to
@ -191,8 +194,9 @@ class Frame {
private static final int CONSTANT_KIND = 1 << KIND_SHIFT;
private static final int REFERENCE_KIND = 2 << KIND_SHIFT;
private static final int UNINITIALIZED_KIND = 3 << KIND_SHIFT;
private static final int LOCAL_KIND = 4 << KIND_SHIFT;
private static final int STACK_KIND = 5 << KIND_SHIFT;
private static final int FORWARD_UNINITIALIZED_KIND = 4 << KIND_SHIFT;
private static final int LOCAL_KIND = 5 << KIND_SHIFT;
private static final int STACK_KIND = 6 << KIND_SHIFT;
// Possible flags for the FLAGS field of an abstract type.
@ -252,13 +256,13 @@ class Frame {
/**
* The abstract types that are initialized in the basic block. A constructor invocation on an
* UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every occurrence</i> of this
* type in the local variables and in the operand stack. This cannot be done during the first step
* of the algorithm since, during this step, the local variables and the operand stack types are
* still abstract. It is therefore necessary to store the abstract types of the constructors which
* are invoked in the basic block, in order to do this replacement during the second step of the
* algorithm, where the frames are fully computed. Note that this array can contain abstract types
* that are relative to the input locals or to the input stack.
* UNINITIALIZED, FORWARD_UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every
* occurrence</i> of this type in the local variables and in the operand stack. This cannot be
* done during the first step of the algorithm since, during this step, the local variables and
* the operand stack types are still abstract. It is therefore necessary to store the abstract
* types of the constructors which are invoked in the basic block, in order to do this replacement
* during the second step of the algorithm, where the frames are fully computed. Note that this
* array can contain abstract types that are relative to the input locals or to the input stack.
*/
private int[] initializations;
@ -316,8 +320,12 @@ class Frame {
String descriptor = Type.getObjectType((String) type).getDescriptor();
return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0);
} else {
return UNINITIALIZED_KIND
| symbolTable.addUninitializedType("", ((Label) type).bytecodeOffset);
Label label = (Label) type;
if ((label.flags & Label.FLAG_RESOLVED) != 0) {
return UNINITIALIZED_KIND | symbolTable.addUninitializedType("", label.bytecodeOffset);
} else {
return FORWARD_UNINITIALIZED_KIND | symbolTable.addForwardUninitializedType("", label);
}
}
}
@ -399,11 +407,12 @@ class Frame {
typeValue = REFERENCE_KIND | symbolTable.addType(internalName);
break;
default:
throw new IllegalArgumentException();
throw new IllegalArgumentException(
"Invalid descriptor fragment: " + buffer.substring(elementDescriptorOffset));
}
return ((elementDescriptorOffset - offset) << DIM_SHIFT) | typeValue;
default:
throw new IllegalArgumentException();
throw new IllegalArgumentException("Invalid descriptor: " + buffer.substring(offset));
}
}
@ -611,7 +620,7 @@ class Frame {
*/
private void pop(final int elements) {
if (outputStackTop >= elements) {
outputStackTop -= (short) elements;
outputStackTop -= (short)elements;
} else {
// If the number of elements to be popped is greater than the number of elements in the output
// stack, clear it, and pop the remaining elements from the input stack.
@ -668,12 +677,14 @@ class Frame {
* @param symbolTable the type table to use to lookup and store type {@link Symbol}.
* @param abstractType an abstract type.
* @return the REFERENCE_KIND abstract type corresponding to abstractType if it is
* UNINITIALIZED_THIS or an UNINITIALIZED_KIND abstract type for one of the types on which a
* constructor is invoked in the basic block. Otherwise returns abstractType.
* UNINITIALIZED_THIS or an UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract type for
* one of the types on which a constructor is invoked in the basic block. Otherwise returns
* abstractType.
*/
private int getInitializedType(final SymbolTable symbolTable, final int abstractType) {
if (abstractType == UNINITIALIZED_THIS
|| (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND) {
|| (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND
|| (abstractType & (DIM_MASK | KIND_MASK)) == FORWARD_UNINITIALIZED_KIND) {
for (int i = 0; i < initializationCount; ++i) {
int initializedType = initializations[i];
int dim = initializedType & DIM_MASK;
@ -1284,11 +1295,12 @@ class Frame {
*
* @param symbolTable the type table to use to lookup and store type {@link Symbol}.
* @param sourceType the abstract type with which the abstract type array element must be merged.
* This type should be of {@link #CONSTANT_KIND}, {@link #REFERENCE_KIND} or {@link
* #UNINITIALIZED_KIND} kind, with positive or {@literal null} array dimensions.
* This type should be of {@link #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link
* #UNINITIALIZED_KIND} or {@link #FORWARD_UNINITIALIZED_KIND} kind, with positive or
* {@literal null} array dimensions.
* @param dstTypes an array of abstract types. These types should be of {@link #CONSTANT_KIND},
* {@link #REFERENCE_KIND} or {@link #UNINITIALIZED_KIND} kind, with positive or {@literal
* null} array dimensions.
* {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND} or {@link #FORWARD_UNINITIALIZED_KIND}
* kind, with positive or {@literal null} array dimensions.
* @param dstIndex the index of the type that must be merged in dstTypes.
* @return {@literal true} if the type array has been modified by this operation.
*/
@ -1431,7 +1443,8 @@ class Frame {
*
* @param symbolTable the type table to use to lookup and store type {@link Symbol}.
* @param abstractType an abstract type, restricted to {@link Frame#CONSTANT_KIND}, {@link
* Frame#REFERENCE_KIND} or {@link Frame#UNINITIALIZED_KIND} types.
* Frame#REFERENCE_KIND}, {@link Frame#UNINITIALIZED_KIND} or {@link
* Frame#FORWARD_UNINITIALIZED_KIND} types.
* @param output where the abstract type must be put.
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4">JVMS
* 4.7.4</a>
@ -1453,6 +1466,10 @@ class Frame {
case UNINITIALIZED_KIND:
output.putByte(ITEM_UNINITIALIZED).putShort((int) symbolTable.getType(typeValue).data);
break;
case FORWARD_UNINITIALIZED_KIND:
output.putByte(ITEM_UNINITIALIZED);
symbolTable.getForwardUninitializedLabel(typeValue).put(output);
break;
default:
throw new AssertionError();
}

View File

@ -96,7 +96,7 @@ public final class Handle {
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
* Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the class that owns the field or method designated by this
* handle.
* handle (see {@link Type#getInternalName()}).
* @param name the name of the field or method designated by this handle.
* @param descriptor the descriptor of the field or method designated by this handle.
* @deprecated this constructor has been superseded by {@link #Handle(int, String, String, String,
@ -116,7 +116,7 @@ public final class Handle {
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
* Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the class that owns the field or method designated by this
* handle.
* handle (see {@link Type#getInternalName()}).
* @param name the name of the field or method designated by this handle.
* @param descriptor the descriptor of the field or method designated by this handle.
* @param isInterface whether the owner is an interface or not.
@ -149,7 +149,8 @@ public final class Handle {
/**
* Returns the internal name of the class that owns the field or method designated by this handle.
*
* @return the internal name of the class that owns the field or method designated by this handle.
* @return the internal name of the class that owns the field or method designated by this handle
* (see {@link Type#getInternalName()}).
*/
public String getOwner() {
return owner;
@ -218,4 +219,3 @@ public final class Handle {
return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
}
}

View File

@ -228,4 +228,3 @@ final class Handler {
}
}
}

View File

@ -113,6 +113,9 @@ public class Label {
/** A flag indicating that the basic block corresponding to a label is the end of a subroutine. */
static final int FLAG_SUBROUTINE_END = 64;
/** A flag indicating that this label has at least one associated line number. */
static final int FLAG_LINE_NUMBER = 128;
/**
* The number of elements to add to the {@link #otherLineNumbers} array when it needs to be
* resized to store a new source line number.
@ -145,6 +148,13 @@ public class Label {
*/
static final int FORWARD_REFERENCE_TYPE_WIDE = 0x20000000;
/**
* The type of forward references stored in two bytes in the <i>stack map table</i>. This is the
* case of the labels of {@link Frame#ITEM_UNINITIALIZED} stack map frame elements, when the NEW
* instruction is after the &lt;init&gt; constructor call (in bytecode offset order).
*/
static final int FORWARD_REFERENCE_TYPE_STACK_MAP = 0x30000000;
/**
* The bit mask to extract the 'handle' of a forward reference to this label. The extracted handle
* is the bytecode offset where the forward reference value is stored (using either 2 or 4 bytes,
@ -177,9 +187,9 @@ public class Label {
short flags;
/**
* The source line number corresponding to this label, or 0. If there are several source line
* numbers corresponding to this label, the first one is stored in this field, and the remaining
* ones are stored in {@link #otherLineNumbers}.
* The source line number corresponding to this label, if {@link #FLAG_LINE_NUMBER} is set. If
* there are several source line numbers corresponding to this label, the first one is stored in
* this field, and the remaining ones are stored in {@link #otherLineNumbers}.
*/
private short lineNumber;
@ -364,7 +374,8 @@ public class Label {
* @param lineNumber a source line number (which should be strictly positive).
*/
final void addLineNumber(final int lineNumber) {
if (this.lineNumber == 0) {
if ((flags & FLAG_LINE_NUMBER) == 0) {
flags |= FLAG_LINE_NUMBER;
this.lineNumber = (short) lineNumber;
} else {
if (otherLineNumbers == null) {
@ -388,7 +399,7 @@ public class Label {
*/
final void accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers) {
methodVisitor.visitLabel(this);
if (visitLineNumbers && lineNumber != 0) {
if (visitLineNumbers && (flags & FLAG_LINE_NUMBER) != 0) {
methodVisitor.visitLineNumber(lineNumber & 0xFFFF, this);
if (otherLineNumbers != null) {
for (int i = 1; i <= otherLineNumbers[0]; ++i) {
@ -432,6 +443,20 @@ public class Label {
}
}
/**
* Puts a reference to this label in the <i>stack map table</i> of a method. If the bytecode
* offset of the label is known, it is written directly. Otherwise, a null relative offset is
* written and a new forward reference is declared for this label.
*
* @param stackMapTableEntries the stack map table where the label offset must be added.
*/
final void put(final ByteVector stackMapTableEntries) {
if ((flags & FLAG_RESOLVED) == 0) {
addForwardReference(0, FORWARD_REFERENCE_TYPE_STACK_MAP, stackMapTableEntries.length);
}
stackMapTableEntries.putShort(bytecodeOffset);
}
/**
* Adds a forward reference to this label. This method must be called only for a true forward
* reference, i.e. only if this label is not resolved yet. For backward references, the relative
@ -464,9 +489,12 @@ public class Label {
* Sets the bytecode offset of this label to the given value and resolves the forward references
* to this label, if any. This method must be called when this label is added to the bytecode of
* the method, i.e. when its bytecode offset becomes known. This method fills in the blanks that
* where left in the bytecode by each forward reference previously added to this label.
* where left in the bytecode (and optionally in the stack map table) by each forward reference
* previously added to this label.
*
* @param code the bytecode of the method.
* @param stackMapTableEntries the 'entries' array of the StackMapTable code attribute of the
* method. Maybe {@literal null}.
* @param bytecodeOffset the bytecode offset of this label.
* @return {@literal true} if a blank that was left for this label was too small to store the
* offset. In such a case the corresponding jump instruction is replaced with an equivalent
@ -474,7 +502,8 @@ public class Label {
* instructions are later replaced with standard bytecode instructions with wider offsets (4
* bytes instead of 2), in ClassReader.
*/
final boolean resolve(final byte[] code, final int bytecodeOffset) {
final boolean resolve(
final byte[] code, final ByteVector stackMapTableEntries, final int bytecodeOffset) {
this.flags |= FLAG_RESOLVED;
this.bytecodeOffset = bytecodeOffset;
if (forwardReferences == null) {
@ -504,11 +533,14 @@ public class Label {
}
code[handle++] = (byte) (relativeOffset >>> 8);
code[handle] = (byte) relativeOffset;
} else {
} else if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_WIDE) {
code[handle++] = (byte) (relativeOffset >>> 24);
code[handle++] = (byte) (relativeOffset >>> 16);
code[handle++] = (byte) (relativeOffset >>> 8);
code[handle] = (byte) relativeOffset;
} else {
stackMapTableEntries.data[handle++] = (byte) (bytecodeOffset >>> 8);
stackMapTableEntries.data[handle] = (byte) bytecodeOffset;
}
}
return hasAsmInstructions;
@ -652,4 +684,3 @@ public class Label {
return "L" + System.identityHashCode(this);
}
}

View File

@ -76,7 +76,7 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException {
/**
* Constructs a new {@link MethodTooLargeException}.
*
* @param className the internal name of the owner class.
* @param className the internal name of the owner class (see {@link Type#getInternalName()}).
* @param methodName the name of the method.
* @param descriptor the descriptor of the method.
* @param codeSize the size of the method's Code attribute, in bytes.
@ -96,7 +96,7 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException {
/**
* Returns the internal name of the owner class.
*
* @return the internal name of the owner class.
* @return the internal name of the owner class (see {@link Type#getInternalName()}).
*/
public String getClassName() {
return className;
@ -129,4 +129,3 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException {
return codeSize;
}
}

View File

@ -62,7 +62,7 @@ package jdk.internal.org.objectweb.asm;
/**
* A visitor to visit a Java method. The methods of this class must be called in the following
* order: ( {@code visitParameter} )* [ {@code visitAnnotationDefault} ] ( {@code visitAnnotation} |
* {@code visitAnnotableParameterCount} | {@code visitParameterAnnotation} {@code
* {@code visitAnnotableParameterCount} | {@code visitParameterAnnotation} | {@code
* visitTypeAnnotation} | {@code visitAttribute} )* [ {@code visitCode} ( {@code visitFrame} |
* {@code visit<i>X</i>Insn} | {@code visitLabel} | {@code visitInsnAnnotation} | {@code
* visitTryCatchBlock} | {@code visitTryCatchAnnotation} | {@code visitLocalVariable} | {@code
@ -124,6 +124,16 @@ public abstract class MethodVisitor {
this.mv = methodVisitor;
}
/**
* The method visitor to which this visitor must delegate method calls. May be {@literal null}.
*
* @return the method visitor to which this visitor must delegate method calls, or {@literal
* null}.
*/
public MethodVisitor getDelegate() {
return mv;
}
// -----------------------------------------------------------------------------------------------
// Parameters, annotations and non standard attributes
// -----------------------------------------------------------------------------------------------
@ -150,7 +160,7 @@ public abstract class MethodVisitor {
* @return a visitor to the visit the actual default value of this annotation interface method, or
* {@literal null} if this visitor is not interested in visiting this default value. The
* 'name' parameters passed to the methods of this annotation visitor are ignored. Moreover,
* exacly one visit method must be called on this annotation visitor, followed by visitEnd.
* exactly one visit method must be called on this annotation visitor, followed by visitEnd.
*/
public AnnotationVisitor visitAnnotationDefault() {
if (mv != null) {
@ -303,15 +313,17 @@ public abstract class MethodVisitor {
* @param type the type of this stack map frame. Must be {@link Opcodes#F_NEW} for expanded
* frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
* Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
* @param numLocal the number of local variables in the visited frame.
* @param numLocal the number of local variables in the visited frame. Long and double values
* count for one variable.
* @param local the local variable types in this frame. This array must not be modified. Primitive
* types are represented by {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
* Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL} or
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a single element).
* Reference types are represented by String objects (representing internal names), and
* uninitialized types by Label objects (this label designates the NEW instruction that
* created this uninitialized value).
* @param numStack the number of operand stack elements in the visited frame.
* Reference types are represented by String objects (representing internal names, see {@link
* Type#getInternalName()}), and uninitialized types by Label objects (this label designates
* the NEW instruction that created this uninitialized value).
* @param numStack the number of operand stack elements in the visited frame. Long and double
* values count for one stack element.
* @param stack the operand stack types in this frame. This array must not be modified. Its
* content has the same format as the "local" array.
* @throws IllegalStateException if a frame is visited just after another one, without any
@ -390,7 +402,7 @@ public abstract class MethodVisitor {
/**
* Visits a type instruction. A type instruction is an instruction that takes the internal name of
* a class as parameter.
* a class as parameter (see {@link Type#getInternalName()}).
*
* @param opcode the opcode of the type instruction to be visited. This opcode is either NEW,
* ANEWARRAY, CHECKCAST or INSTANCEOF.
@ -673,8 +685,9 @@ public abstract class MethodVisitor {
* @param start the beginning of the exception handler's scope (inclusive).
* @param end the end of the exception handler's scope (exclusive).
* @param handler the beginning of the exception handler's code.
* @param type the internal name of the type of exceptions handled by the handler, or {@literal
* null} to catch any exceptions (for "finally" blocks).
* @param type the internal name of the type of exceptions handled by the handler (see {@link
* Type#getInternalName()}), or {@literal null} to catch any exceptions (for "finally"
* blocks).
* @throws IllegalArgumentException if one of the labels has already been visited by this visitor
* (by the {@link #visitLabel} method).
*/
@ -812,4 +825,3 @@ public abstract class MethodVisitor {
}
}
}

View File

@ -566,8 +566,9 @@ final class MethodWriter extends MethodVisitor {
* the number of stack elements. The local variables start at index 3 and are followed by the
* operand stack elements. In summary frame[0] = offset, frame[1] = numLocal, frame[2] = numStack.
* Local variables and operand stack entries contain abstract types, as defined in {@link Frame},
* but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND} or {@link
* Frame#UNINITIALIZED_KIND} abstract types. Long and double types use only one array entry.
* but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND}, {@link
* Frame#UNINITIALIZED_KIND} or {@link Frame#FORWARD_UNINITIALIZED_KIND} abstract types. Long and
* double types use only one array entry.
*/
private int[] currentFrame;
@ -725,7 +726,7 @@ final class MethodWriter extends MethodVisitor {
if (visible) {
if (lastRuntimeVisibleParameterAnnotations == null) {
lastRuntimeVisibleParameterAnnotations =
new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
new AnnotationWriter[Type.getArgumentCount(descriptor)];
}
return lastRuntimeVisibleParameterAnnotations[parameter] =
AnnotationWriter.create(
@ -733,7 +734,7 @@ final class MethodWriter extends MethodVisitor {
} else {
if (lastRuntimeInvisibleParameterAnnotations == null) {
lastRuntimeInvisibleParameterAnnotations =
new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
new AnnotationWriter[Type.getArgumentCount(descriptor)];
}
return lastRuntimeInvisibleParameterAnnotations[parameter] =
AnnotationWriter.create(
@ -1231,7 +1232,7 @@ final class MethodWriter extends MethodVisitor {
@Override
public void visitLabel(final Label label) {
// Resolve the forward references to this label, if any.
hasAsmInstructions |= label.resolve(code.data, code.length);
hasAsmInstructions |= label.resolve(code.data, stackMapTableEntries, code.length);
// visitLabel starts a new basic block (except for debug only labels), so we need to update the
// previous and current block references and list of successors.
if ((label.flags & Label.FLAG_DEBUG_ONLY) != 0) {
@ -1244,7 +1245,7 @@ final class MethodWriter extends MethodVisitor {
// one place, but this does not work for labels which have not been visited yet.
// Therefore, when we detect here two labels having the same bytecode offset, we need to
// - consolidate the state scattered in these two instances into the canonical instance:
currentBasicBlock.flags |= (short) (label.flags & Label.FLAG_JUMP_TARGET);
currentBasicBlock.flags |= (short)(label.flags & Label.FLAG_JUMP_TARGET);
// - make sure the two instances share the same Frame instance (the implementation of
// {@link Label#getCanonicalInstance} relies on this property; here label.frame should be
// null):
@ -1260,7 +1261,7 @@ final class MethodWriter extends MethodVisitor {
if (lastBasicBlock != null) {
if (label.bytecodeOffset == lastBasicBlock.bytecodeOffset) {
// Same comment as above.
lastBasicBlock.flags |= (short) (label.flags & Label.FLAG_JUMP_TARGET);
lastBasicBlock.flags |= (short)(label.flags & Label.FLAG_JUMP_TARGET);
// Here label.frame should be null.
label.frame = lastBasicBlock.frame;
currentBasicBlock = lastBasicBlock;
@ -1827,7 +1828,7 @@ final class MethodWriter extends MethodVisitor {
if (compute == COMPUTE_ALL_FRAMES) {
Label nextBasicBlock = new Label();
nextBasicBlock.frame = new Frame(nextBasicBlock);
nextBasicBlock.resolve(code.data, code.length);
nextBasicBlock.resolve(code.data, stackMapTableEntries, code.length);
lastBasicBlock.nextBasicBlock = nextBasicBlock;
lastBasicBlock = nextBasicBlock;
currentBasicBlock = null;
@ -2011,9 +2012,8 @@ final class MethodWriter extends MethodVisitor {
.putByte(Frame.ITEM_OBJECT)
.putShort(symbolTable.addConstantClass((String) type).index);
} else {
stackMapTableEntries
.putByte(Frame.ITEM_UNINITIALIZED)
.putShort(((Label) type).bytecodeOffset);
stackMapTableEntries.putByte(Frame.ITEM_UNINITIALIZED);
((Label) type).put(stackMapTableEntries);
}
}

View File

@ -110,10 +110,21 @@ public abstract class ModuleVisitor {
this.mv = moduleVisitor;
}
/**
* The module visitor to which this visitor must delegate method calls. May be {@literal null}.
*
* @return the module visitor to which this visitor must delegate method calls, or {@literal
* null}.
*/
public ModuleVisitor getDelegate() {
return mv;
}
/**
* Visit the main class of the current module.
*
* @param mainClass the internal name of the main class of the current module.
* @param mainClass the internal name of the main class of the current module (see {@link
* Type#getInternalName()}).
*/
public void visitMainClass(final String mainClass) {
if (mv != null) {
@ -124,7 +135,7 @@ public abstract class ModuleVisitor {
/**
* Visit a package of the current module.
*
* @param packaze the internal name of a package.
* @param packaze the internal name of a package (see {@link Type#getInternalName()}).
*/
public void visitPackage(final String packaze) {
if (mv != null) {
@ -149,7 +160,7 @@ public abstract class ModuleVisitor {
/**
* Visit an exported package of the current module.
*
* @param packaze the internal name of the exported package.
* @param packaze the internal name of the exported package (see {@link Type#getInternalName()}).
* @param access the access flag of the exported package, valid values are among {@code
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* @param modules the fully qualified names (using dots) of the modules that can access the public
@ -164,7 +175,7 @@ public abstract class ModuleVisitor {
/**
* Visit an open package of the current module.
*
* @param packaze the internal name of the opened package.
* @param packaze the internal name of the opened package (see {@link Type#getInternalName()}).
* @param access the access flag of the opened package, valid values are among {@code
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* @param modules the fully qualified names (using dots) of the modules that can use deep
@ -180,7 +191,7 @@ public abstract class ModuleVisitor {
* Visit a service used by the current module. The name must be the internal name of an interface
* or a class.
*
* @param service the internal name of the service.
* @param service the internal name of the service (see {@link Type#getInternalName()}).
*/
public void visitUse(final String service) {
if (mv != null) {
@ -191,9 +202,9 @@ public abstract class ModuleVisitor {
/**
* Visit an implementation of a service.
*
* @param service the internal name of the service.
* @param providers the internal names of the implementations of the service (there is at least
* one provider).
* @param service the internal name of the service (see {@link Type#getInternalName()}).
* @param providers the internal names (see {@link Type#getInternalName()}) of the implementations
* of the service (there is at least one provider).
*/
public void visitProvide(final String service, final String... providers) {
if (mv != null) {
@ -211,4 +222,3 @@ public abstract class ModuleVisitor {
}
}
}

View File

@ -283,4 +283,3 @@ final class ModuleWriter extends ModuleVisitor {
}
}
}

View File

@ -588,4 +588,3 @@ public interface Opcodes {
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
}

View File

@ -77,7 +77,7 @@ public abstract class RecordComponentVisitor {
/**
* The record visitor to which this visitor must delegate method calls. May be {@literal null}.
*/
/*package-private*/ RecordComponentVisitor delegate;
protected RecordComponentVisitor delegate;
/**
* Constructs a new {@link RecordComponentVisitor}.
@ -113,7 +113,8 @@ public abstract class RecordComponentVisitor {
/**
* The record visitor to which this visitor must delegate method calls. May be {@literal null}.
*
* @return the record visitor to which this visitor must delegate method calls or {@literal null}.
* @return the record visitor to which this visitor must delegate method calls, or {@literal
* null}.
*/
public RecordComponentVisitor getDelegate() {
return delegate;
@ -178,4 +179,3 @@ public abstract class RecordComponentVisitor {
}
}
}

View File

@ -255,4 +255,3 @@ final class RecordComponentWriter extends RecordComponentVisitor {
attributePrototypes.addAttributes(firstAttribute);
}
}

View File

@ -135,12 +135,25 @@ abstract class Symbol {
static final int TYPE_TAG = 128;
/**
* The tag value of an {@link Frame#ITEM_UNINITIALIZED} type entry in the type table of a class.
* The tag value of an uninitialized type entry in the type table of a class. This type is used
* for the normal case where the NEW instruction is before the &lt;init&gt; constructor call (in
* bytecode offset order), i.e. when the label of the NEW instruction is resolved when the
* constructor call is visited. If the NEW instruction is after the constructor call, use the
* {@link #FORWARD_UNINITIALIZED_TYPE_TAG} tag value instead.
*/
static final int UNINITIALIZED_TYPE_TAG = 129;
/**
* The tag value of an uninitialized type entry in the type table of a class. This type is used
* for the unusual case where the NEW instruction is after the &lt;init&gt; constructor call (in
* bytecode offset order), i.e. when the label of the NEW instruction is not resolved when the
* constructor call is visited. If the NEW instruction is before the constructor call, use the
* {@link #UNINITIALIZED_TYPE_TAG} tag value instead.
*/
static final int FORWARD_UNINITIALIZED_TYPE_TAG = 130;
/** The tag value of a merged type entry in the (ASM specific) type table of a class. */
static final int MERGED_TYPE_TAG = 130;
static final int MERGED_TYPE_TAG = 131;
// Instance fields.
@ -183,8 +196,8 @@ abstract class Symbol {
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
* <li>an arbitrary string for {@link #CONSTANT_UTF8_TAG} and {@link #CONSTANT_STRING_TAG}
* symbols,
* <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG} and {@link
* #UNINITIALIZED_TYPE_TAG} symbols,
* <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG}, {@link
* #UNINITIALIZED_TYPE_TAG} and {@link #FORWARD_UNINITIALIZED_TYPE_TAG} symbols,
* <li>{@literal null} for the other types of symbol.
* </ul>
*/
@ -204,6 +217,9 @@ abstract class Symbol {
* {@link #CONSTANT_DYNAMIC_TAG} or {@link #BOOTSTRAP_METHOD_TAG} symbols,
* <li>the bytecode offset of the NEW instruction that created an {@link
* Frame#ITEM_UNINITIALIZED} type for {@link #UNINITIALIZED_TYPE_TAG} symbols,
* <li>the index of the {@link Label} (in the {@link SymbolTable#labelTable} table) of the NEW
* instruction that created an {@link Frame#ITEM_UNINITIALIZED} type for {@link
* #FORWARD_UNINITIALIZED_TYPE_TAG} symbols,
* <li>the indices (in the class' type table) of two {@link #TYPE_TAG} source types for {@link
* #MERGED_TYPE_TAG} symbols,
* <li>0 for the other types of symbol.
@ -273,4 +289,3 @@ abstract class Symbol {
return info;
}
}

View File

@ -140,11 +140,35 @@ final class SymbolTable {
* An ASM specific type table used to temporarily store internal names that will not necessarily
* be stored in the constant pool. This type table is used by the control flow and data flow
* analysis algorithm used to compute stack map frames from scratch. This array stores {@link
* Symbol#TYPE_TAG} and {@link Symbol#UNINITIALIZED_TYPE_TAG}) Symbol. The type symbol at index
* {@code i} has its {@link Symbol#index} equal to {@code i} (and vice versa).
* Symbol#TYPE_TAG}, {@link Symbol#UNINITIALIZED_TYPE_TAG},{@link
* Symbol#FORWARD_UNINITIALIZED_TYPE_TAG} and {@link Symbol#MERGED_TYPE_TAG} entries. The type
* symbol at index {@code i} has its {@link Symbol#index} equal to {@code i} (and vice versa).
*/
private Entry[] typeTable;
/**
* The actual number of {@link LabelEntry} in {@link #labelTable}. These elements are stored from
* index 0 to labelCount (excluded). The other array entries are empty. These label entries are
* also stored in the {@link #labelEntries} hash set.
*/
private int labelCount;
/**
* The labels corresponding to the "forward uninitialized" types in the ASM specific {@link
* typeTable} (see {@link Symbol#FORWARD_UNINITIALIZED_TYPE_TAG}). The label entry at index {@code
* i} has its {@link LabelEntry#index} equal to {@code i} (and vice versa).
*/
private LabelEntry[] labelTable;
/**
* A hash set of all the {@link LabelEntry} elements in the {@link #labelTable}. Each {@link
* LabelEntry} instance is stored at the array index given by its hash code modulo the array size.
* If several entries must be stored at the same array index, they are linked together via their
* {@link LabelEntry#next} field. The {@link #getOrAddLabelEntry(Label)} method ensures that this
* table does not contain duplicated entries.
*/
private LabelEntry[] labelEntries;
/**
* Constructs a new, empty SymbolTable for the given ClassWriter.
*
@ -1161,6 +1185,18 @@ final class SymbolTable {
return typeTable[typeIndex];
}
/**
* Returns the label corresponding to the "forward uninitialized" type table element whose index
* is given.
*
* @param typeIndex the type table index of a "forward uninitialized" type table element.
* @return the label corresponding of the NEW instruction which created this "forward
* uninitialized" type.
*/
Label getForwardUninitializedLabel(final int typeIndex) {
return labelTable[(int) typeTable[typeIndex].data].label;
}
/**
* Adds a type in the type table of this symbol table. Does nothing if the type table already
* contains a similar type.
@ -1181,13 +1217,13 @@ final class SymbolTable {
}
/**
* Adds an {@link Frame#ITEM_UNINITIALIZED} type in the type table of this symbol table. Does
* nothing if the type table already contains a similar type.
* Adds an uninitialized type in the type table of this symbol table. Does nothing if the type
* table already contains a similar type.
*
* @param value an internal class name.
* @param bytecodeOffset the bytecode offset of the NEW instruction that created this {@link
* Frame#ITEM_UNINITIALIZED} type value.
* @return the index of a new or already existing type Symbol with the given value.
* @param bytecodeOffset the bytecode offset of the NEW instruction that created this
* uninitialized type value.
* @return the index of a new or already existing type #@link Symbol} with the given value.
*/
int addUninitializedType(final String value, final int bytecodeOffset) {
int hashCode = hash(Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset);
@ -1205,6 +1241,32 @@ final class SymbolTable {
new Entry(typeCount, Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset, hashCode));
}
/**
* Adds a "forward uninitialized" type in the type table of this symbol table. Does nothing if the
* type table already contains a similar type.
*
* @param value an internal class name.
* @param label the label of the NEW instruction that created this uninitialized type value. If
* the label is resolved, use the {@link #addUninitializedType} method instead.
* @return the index of a new or already existing type {@link Symbol} with the given value.
*/
int addForwardUninitializedType(final String value, final Label label) {
int labelIndex = getOrAddLabelEntry(label).index;
int hashCode = hash(Symbol.FORWARD_UNINITIALIZED_TYPE_TAG, value, labelIndex);
Entry entry = get(hashCode);
while (entry != null) {
if (entry.tag == Symbol.FORWARD_UNINITIALIZED_TYPE_TAG
&& entry.hashCode == hashCode
&& entry.data == labelIndex
&& entry.value.equals(value)) {
return entry.index;
}
entry = entry.next;
}
return addTypeInternal(
new Entry(typeCount, Symbol.FORWARD_UNINITIALIZED_TYPE_TAG, value, labelIndex, hashCode));
}
/**
* Adds a merged type in the type table of this symbol table. Does nothing if the type table
* already contains a similar type.
@ -1257,6 +1319,59 @@ final class SymbolTable {
return put(entry).index;
}
/**
* Returns the {@link LabelEntry} corresponding to the given label. Creates a new one if there is
* no such entry.
*
* @param label the {@link Label} of a NEW instruction which created an uninitialized type, in the
* case where this NEW instruction is after the &lt;init&gt; constructor call (in bytecode
* offset order). See {@link Symbol#FORWARD_UNINITIALIZED_TYPE_TAG}.
* @return the {@link LabelEntry} corresponding to {@code label}.
*/
private LabelEntry getOrAddLabelEntry(final Label label) {
if (labelEntries == null) {
labelEntries = new LabelEntry[16];
labelTable = new LabelEntry[16];
}
int hashCode = System.identityHashCode(label);
LabelEntry labelEntry = labelEntries[hashCode % labelEntries.length];
while (labelEntry != null && labelEntry.label != label) {
labelEntry = labelEntry.next;
}
if (labelEntry != null) {
return labelEntry;
}
if (labelCount > (labelEntries.length * 3) / 4) {
int currentCapacity = labelEntries.length;
int newCapacity = currentCapacity * 2 + 1;
LabelEntry[] newLabelEntries = new LabelEntry[newCapacity];
for (int i = currentCapacity - 1; i >= 0; --i) {
LabelEntry currentEntry = labelEntries[i];
while (currentEntry != null) {
int newCurrentEntryIndex = System.identityHashCode(currentEntry.label) % newCapacity;
LabelEntry nextEntry = currentEntry.next;
currentEntry.next = newLabelEntries[newCurrentEntryIndex];
newLabelEntries[newCurrentEntryIndex] = currentEntry;
currentEntry = nextEntry;
}
}
labelEntries = newLabelEntries;
}
if (labelCount == labelTable.length) {
LabelEntry[] newLabelTable = new LabelEntry[2 * labelTable.length];
System.arraycopy(labelTable, 0, newLabelTable, 0, labelTable.length);
labelTable = newLabelTable;
}
labelEntry = new LabelEntry(labelCount, label);
int index = hashCode % labelEntries.length;
labelEntry.next = labelEntries[index];
labelEntries[index] = labelEntry;
labelTable[labelCount++] = labelEntry;
return labelEntry;
}
// -----------------------------------------------------------------------------------------------
// Static helper methods to compute hash codes.
// -----------------------------------------------------------------------------------------------
@ -1307,7 +1422,7 @@ final class SymbolTable {
*
* @author Eric Bruneton
*/
private static class Entry extends Symbol {
private static final class Entry extends Symbol {
/** The hash code of this entry. */
final int hashCode;
@ -1351,5 +1466,30 @@ final class SymbolTable {
this.hashCode = hashCode;
}
}
}
/**
* A label corresponding to a "forward uninitialized" type in the ASM specific {@link
* SymbolTable#typeTable} (see {@link Symbol#FORWARD_UNINITIALIZED_TYPE_TAG}).
*
* @author Eric Bruneton
*/
private static final class LabelEntry {
/** The index of this label entry in the {@link SymbolTable#labelTable} array. */
final int index;
/** The value of this label entry. */
final Label label;
/**
* Another entry (and so on recursively) having the same hash code (modulo the size of {@link
* SymbolTable#labelEntries}}) as this one.
*/
LabelEntry next;
LabelEntry(final int index, final Label label) {
this.index = index;
this.label = label;
}
}
}

View File

@ -277,7 +277,7 @@ public final class Type {
/**
* Returns the {@link Type} corresponding to the given internal name.
*
* @param internalName an internal name.
* @param internalName an internal name (see {@link Type#getInternalName()}).
* @return the {@link Type} corresponding to the given internal name.
*/
public static Type getObjectType(final String internalName) {
@ -327,26 +327,12 @@ public final class Type {
*/
public static Type[] getArgumentTypes(final String methodDescriptor) {
// First step: compute the number of argument types in methodDescriptor.
int numArgumentTypes = 0;
// Skip the first character, which is always a '('.
int currentOffset = 1;
// Parse the argument types, one at a each loop iteration.
while (methodDescriptor.charAt(currentOffset) != ')') {
while (methodDescriptor.charAt(currentOffset) == '[') {
currentOffset++;
}
if (methodDescriptor.charAt(currentOffset++) == 'L') {
// Skip the argument descriptor content.
int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
}
++numArgumentTypes;
}
int numArgumentTypes = getArgumentCount(methodDescriptor);
// Second step: create a Type instance for each argument type.
Type[] argumentTypes = new Type[numArgumentTypes];
// Skip the first character, which is always a '('.
currentOffset = 1;
int currentOffset = 1;
// Parse and create the argument types, one at each loop iteration.
int currentArgumentTypeIndex = 0;
while (methodDescriptor.charAt(currentOffset) != ')') {
@ -734,6 +720,43 @@ public final class Type {
}
}
/**
* Returns the number of arguments of this method type. This method should only be used for method
* types.
*
* @return the number of arguments of this method type. Each argument counts for 1, even long and
* double ones. The implicit @literal{this} argument is not counted.
*/
public int getArgumentCount() {
return getArgumentCount(getDescriptor());
}
/**
* Returns the number of arguments in the given method descriptor.
*
* @param methodDescriptor a method descriptor.
* @return the number of arguments in the given method descriptor. Each argument counts for 1,
* even long and double ones. The implicit @literal{this} argument is not counted.
*/
public static int getArgumentCount(final String methodDescriptor) {
int argumentCount = 0;
// Skip the first character, which is always a '('.
int currentOffset = 1;
// Parse the argument types, one at a each loop iteration.
while (methodDescriptor.charAt(currentOffset) != ')') {
while (methodDescriptor.charAt(currentOffset) == '[') {
currentOffset++;
}
if (methodDescriptor.charAt(currentOffset++) == 'L') {
// Skip the argument descriptor content.
int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
}
++argumentCount;
}
return argumentCount;
}
/**
* Returns the size of the arguments and of the return value of methods of this type. This method
* should only be used for method types.
@ -741,7 +764,8 @@ public final class Type {
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}). Long and double values have size 2,
* the others have size 1.
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@ -754,7 +778,8 @@ public final class Type {
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}). Long and double values have size 2,
* the others have size 1.
*/
public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
int argumentsSize = 1;
@ -925,4 +950,3 @@ public final class Type {
return getDescriptor();
}
}

View File

@ -230,4 +230,3 @@ public final class TypePath {
}
}
}

View File

@ -465,4 +465,3 @@ public class TypeReference {
}
}
}

View File

@ -700,4 +700,3 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
*/
protected void onMethodExit(final int opcode) {}
}

View File

@ -92,9 +92,10 @@ public class AnalyzerAdapter extends MethodVisitor {
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
* double are represented by two elements, the second one being TOP). Reference types are
* represented by String objects (representing internal names), and uninitialized types by Label
* objects (this label designates the NEW instruction that created this uninitialized value). This
* field is {@literal null} for unreachable instructions.
* represented by String objects (representing internal names, see {@link
* Type#getInternalName()}), and uninitialized types by Label objects (this label designates the
* NEW instruction that created this uninitialized value). This field is {@literal null} for
* unreachable instructions.
*/
public List<Object> locals;
@ -103,9 +104,10 @@ public class AnalyzerAdapter extends MethodVisitor {
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and
* double are represented by two elements, the second one being TOP). Reference types are
* represented by String objects (representing internal names), and uninitialized types by Label
* objects (this label designates the NEW instruction that created this uninitialized value). This
* field is {@literal null} for unreachable instructions.
* represented by String objects (representing internal names, see {@link
* Type#getInternalName()}), and uninitialized types by Label objects (this label designates the
* NEW instruction that created this uninitialized value). This field is {@literal null} for
* unreachable instructions.
*/
public List<Object> stack;
@ -114,9 +116,9 @@ public class AnalyzerAdapter extends MethodVisitor {
/**
* The uninitialized types in the current execution frame. This map associates internal names to
* Label objects. Each label designates a NEW instruction that created the currently uninitialized
* types, and the associated internal name represents the NEW operand, i.e. the final, initialized
* type value.
* Label objects (see {@link Type#getInternalName()}). Each label designates a NEW instruction
* that created the currently uninitialized types, and the associated internal name represents the
* NEW operand, i.e. the final, initialized type value.
*/
public Map<Object, Object> uninitializedTypes;
@ -338,7 +340,7 @@ public class AnalyzerAdapter extends MethodVisitor {
if (value == Opcodes.UNINITIALIZED_THIS) {
initializedValue = this.owner;
} else {
initializedValue = uninitializedTypes.get(value);
initializedValue = owner;
}
for (int i = 0; i < locals.size(); ++i) {
if (locals.get(i) == value) {
@ -938,4 +940,3 @@ public class AnalyzerAdapter extends MethodVisitor {
labels = null;
}
}

View File

@ -227,7 +227,7 @@ public class AnnotationRemapper extends AnnotationVisitor {
/**
* Maps an annotation attribute name with the remapper. Returns the original name unchanged if the
* internal name of the annotation is {@literal null}.
* descriptor of the annotation is {@literal null}.
*
* @param name the name of the annotation attribute.
* @return the new name of the annotation attribute.
@ -239,4 +239,3 @@ public class AnnotationRemapper extends AnnotationVisitor {
return remapper.mapAnnotationAttributeName(descriptor, name);
}
}

View File

@ -329,4 +329,3 @@ public class ClassRemapper extends ClassVisitor {
return new RecordComponentRemapper(api, recordComponentVisitor, remapper);
}
}

View File

@ -237,4 +237,3 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
super.visitMultiANewArrayInsn(descriptor, numDimensions);
}
}

View File

@ -144,4 +144,3 @@ public class FieldRemapper extends FieldVisitor {
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
}
}

View File

@ -308,7 +308,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
* Returns the internal names of the given types.
*
* @param types a set of types.
* @return the internal names of the given types.
* @return the internal names of the given types (see {@link Type#getInternalName()}).
*/
private static String[] getInternalNames(final Type[] types) {
String[] names = new String[types.length];
@ -1386,7 +1386,8 @@ public class GeneratorAdapter extends LocalVariablesSorter {
*
* @param start beginning of the exception handler's scope (inclusive).
* @param end end of the exception handler's scope (exclusive).
* @param exception internal name of the type of exceptions handled by the handler.
* @param exception internal name of the type of exceptions handled by the handler (see {@link
* Type#getInternalName()}).
*/
public void catchException(final Label start, final Label end, final Type exception) {
Label catchLabel = new Label();
@ -1398,4 +1399,3 @@ public class GeneratorAdapter extends LocalVariablesSorter {
mark(catchLabel);
}
}

View File

@ -1094,7 +1094,8 @@ public class InstructionAdapter extends MethodVisitor {
/**
* Deprecated.
*
* @param owner the internal name of the method's owner class.
* @param owner the internal name of the method's owner class (see {@link
* Type#getInternalName()}).
* @param name the method's name.
* @param descriptor the method's descriptor (see {@link Type}).
* @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead.
@ -1132,7 +1133,8 @@ public class InstructionAdapter extends MethodVisitor {
/**
* Deprecated.
*
* @param owner the internal name of the method's owner class.
* @param owner the internal name of the method's owner class (see {@link
* Type#getInternalName()}).
* @param name the method's name.
* @param descriptor the method's descriptor (see {@link Type}).
* @deprecated use {@link #invokespecial(String, String, String, boolean)} instead.
@ -1170,7 +1172,8 @@ public class InstructionAdapter extends MethodVisitor {
/**
* Deprecated.
*
* @param owner the internal name of the method's owner class.
* @param owner the internal name of the method's owner class (see {@link
* Type#getInternalName()}).
* @param name the method's name.
* @param descriptor the method's descriptor (see {@link Type}).
* @deprecated use {@link #invokestatic(String, String, String, boolean)} instead.
@ -1329,4 +1332,3 @@ public class InstructionAdapter extends MethodVisitor {
mv.visitLabel(label);
}
}

View File

@ -120,7 +120,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
* @param name the method's name.
* @param descriptor the method's descriptor.
* @param signature the method's signature. May be {@literal null}.
* @param exceptions the internal names of the method's exception classes. May be {@literal null}.
* @param exceptions the internal names of the method's exception classes (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
* @throws IllegalStateException if a subclass calls this constructor.
*/
public JSRInlinerAdapter(
@ -155,7 +156,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
* @param name the method's name.
* @param descriptor the method's descriptor.
* @param signature the method's signature. May be {@literal null}.
* @param exceptions the internal names of the method's exception classes. May be {@literal null}.
* @param exceptions the internal names of the method's exception classes (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
protected JSRInlinerAdapter(
final int api,
@ -455,7 +457,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
}
/** An instantiation of a subroutine. */
private class Instantiation extends AbstractMap<LabelNode, LabelNode> {
private final class Instantiation extends AbstractMap<LabelNode, LabelNode> {
/**
* The instantiation from which this one was created (or {@literal null} for the instantiation
@ -600,4 +602,3 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
}
}
}

View File

@ -381,4 +381,3 @@ public class LocalVariablesSorter extends MethodVisitor {
return local;
}
}

View File

@ -292,4 +292,3 @@ public class Method {
return name.hashCode() ^ descriptor.hashCode();
}
}

View File

@ -319,4 +319,3 @@ public class MethodRemapper extends MethodVisitor {
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
}
}

View File

@ -168,4 +168,3 @@ public final class ModuleHashesAttribute extends Attribute {
return byteVector;
}
}

View File

@ -150,4 +150,3 @@ public class ModuleRemapper extends ModuleVisitor {
super.visitProvide(remapper.mapType(service), remappedProviders);
}
}

View File

@ -142,4 +142,3 @@ public final class ModuleResolutionAttribute extends Attribute {
return byteVector;
}
}

View File

@ -116,4 +116,3 @@ public final class ModuleTargetAttribute extends Attribute {
return byteVector;
}
}

View File

@ -147,4 +147,3 @@ public class RecordComponentRemapper extends RecordComponentVisitor {
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
}
}

View File

@ -80,7 +80,7 @@ public abstract class Remapper {
* @param descriptor a type descriptor.
* @return the given descriptor, with its [array element type] internal name remapped with {@link
* #map(String)} (if the descriptor corresponds to an array or object type, otherwise the
* descriptor is returned as is).
* descriptor is returned as is). See {@link Type#getInternalName()}.
*/
public String mapDesc(final String descriptor) {
return mapType(Type.getType(descriptor)).getDescriptor();
@ -94,7 +94,7 @@ public abstract class Remapper {
* @return the given type, with its [array element type] internal name remapped with {@link
* #map(String)} (if the type is an array or object type, otherwise the type is returned as
* is) or, of the type is a method type, with its descriptor remapped with {@link
* #mapMethodDesc(String)}.
* #mapMethodDesc(String)}. See {@link Type#getInternalName()}.
*/
private Type mapType(final Type type) {
switch (type.getSort()) {
@ -118,8 +118,10 @@ public abstract class Remapper {
/**
* Returns the given internal name, remapped with {@link #map(String)}.
*
* @param internalName the internal name (or array type descriptor) of some (array) class.
* @return the given internal name, remapped with {@link #map(String)}.
* @param internalName the internal name (or array type descriptor) of some (array) class (see
* {@link Type#getInternalName()}).
* @return the given internal name, remapped with {@link #map(String)} (see {@link
* Type#getInternalName()}).
*/
public String mapType(final String internalName) {
if (internalName == null) {
@ -131,8 +133,10 @@ public abstract class Remapper {
/**
* Returns the given internal names, remapped with {@link #map(String)}.
*
* @param internalNames the internal names (or array type descriptors) of some (array) classes.
* @return the given internal name, remapped with {@link #map(String)}.
* @param internalNames the internal names (or array type descriptors) of some (array) classes
* (see {@link Type#getInternalName()}).
* @return the given internal name, remapped with {@link #map(String)} (see {@link
* Type#getInternalName()}).
*/
public String[] mapTypes(final String[] internalNames) {
String[] remappedInternalNames = null;
@ -286,14 +290,30 @@ public abstract class Remapper {
* strategy that will work for inner classes produced by Java, but not necessarily other
* languages. Subclasses can override.
*
* @param name the fully-qualified internal name of the inner class.
* @param ownerName the internal name of the owner class of the inner class.
* @param innerName the internal name of the inner class.
* @param name the fully-qualified internal name of the inner class (see {@link
* Type#getInternalName()}).
* @param ownerName the internal name of the owner class of the inner class (see {@link
* Type#getInternalName()}).
* @param innerName the internal name of the inner class (see {@link Type#getInternalName()}).
* @return the new inner name of the inner class.
*/
public String mapInnerClassName(
final String name, final String ownerName, final String innerName) {
final String remappedInnerName = this.mapType(name);
if (remappedInnerName.equals(name)) {
return innerName;
} else {
int originSplit = name.lastIndexOf('/');
int remappedSplit = remappedInnerName.lastIndexOf('/');
if (originSplit != -1 && remappedSplit != -1) {
if (name.substring(originSplit).equals(remappedInnerName.substring(remappedSplit))) {
// class name not changed
return innerName;
}
}
}
if (remappedInnerName.contains("$")) {
int index = remappedInnerName.lastIndexOf('$') + 1;
while (index < remappedInnerName.length()
@ -310,7 +330,8 @@ public abstract class Remapper {
* Maps a method name to its new name. The default implementation of this method returns the given
* name, unchanged. Subclasses can override.
*
* @param owner the internal name of the owner class of the method.
* @param owner the internal name of the owner class of the method (see {@link
* Type#getInternalName()}).
* @param name the name of the method.
* @param descriptor the descriptor of the method.
* @return the new name of the method.
@ -335,7 +356,8 @@ public abstract class Remapper {
* Maps a record component name to its new name. The default implementation of this method returns
* the given name, unchanged. Subclasses can override.
*
* @param owner the internal name of the owner class of the field.
* @param owner the internal name of the owner class of the field (see {@link
* Type#getInternalName()}).
* @param name the name of the field.
* @param descriptor the descriptor of the field.
* @return the new name of the field.
@ -349,7 +371,8 @@ public abstract class Remapper {
* Maps a field name to its new name. The default implementation of this method returns the given
* name, unchanged. Subclasses can override.
*
* @param owner the internal name of the owner class of the field.
* @param owner the internal name of the owner class of the field (see {@link
* Type#getInternalName()}).
* @param name the name of the field.
* @param descriptor the descriptor of the field.
* @return the new name of the field.
@ -384,11 +407,10 @@ public abstract class Remapper {
* Maps the internal name of a class to its new name. The default implementation of this method
* returns the given name, unchanged. Subclasses can override.
*
* @param internalName the internal name of a class.
* @return the new internal name.
* @param internalName the internal name of a class (see {@link Type#getInternalName()}).
* @return the new internal name (see {@link Type#getInternalName()}).
*/
public String map(final String internalName) {
return internalName;
}
}

View File

@ -522,4 +522,3 @@ public class SerialVersionUIDAdder extends ClassVisitor {
}
}
}

View File

@ -202,4 +202,3 @@ public class SignatureRemapper extends SignatureVisitor {
classNames.remove(classNames.size() - 1);
}
}

View File

@ -85,7 +85,7 @@ public class SimpleRemapper extends Remapper {
* attribute (in the form &lt;owner&gt;.&lt;name&gt;), and the value is the new field
* name.
* <li>for internal names, the key is the old internal name, and the value is the new
* internal name.
* internal name (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* </ul>
*/
public SimpleRemapper(final Map<String, String> mapping) {
@ -97,7 +97,8 @@ public class SimpleRemapper extends Remapper {
*
* @param oldName the key corresponding to a method, field or internal name (see {@link
* #SimpleRemapper(Map)} for the format of these keys).
* @param newName the new method, field or internal name.
* @param newName the new method, field or internal name (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public SimpleRemapper(final String oldName, final String newName) {
this.mapping = Collections.singletonMap(oldName, newName);
@ -132,4 +133,3 @@ public class SimpleRemapper extends Remapper {
return mapping.get(key);
}
}

View File

@ -154,4 +154,3 @@ public class StaticInitMerger extends ClassVisitor {
super.visitEnd();
}
}

View File

@ -81,4 +81,3 @@ public interface TableSwitchGenerator {
/** Generates the code for the default switch case. */
void generateDefault();
}

View File

@ -155,4 +155,3 @@ public class TryCatchBlockSorter extends MethodNode {
}
}
}

View File

@ -282,4 +282,3 @@ public class SignatureReader {
}
}
}

View File

@ -211,7 +211,8 @@ public abstract class SignatureVisitor {
/**
* Starts the visit of a signature corresponding to a class or interface type.
*
* @param name the internal name of the class or interface.
* @param name the internal name of the class or interface (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public void visitClassType(final String name) {}
@ -238,4 +239,3 @@ public abstract class SignatureVisitor {
/** Ends the visit of a signature corresponding to a class or interface type. */
public void visitEnd() {}
}

View File

@ -73,7 +73,7 @@ import jdk.internal.org.objectweb.asm.Opcodes;
public class SignatureWriter extends SignatureVisitor {
/** The builder used to construct the visited signature. */
private final StringBuilder stringBuilder = new StringBuilder();
private final StringBuilder stringBuilder;
/** Whether the visited signature contains formal type parameters. */
private boolean hasFormals;
@ -83,8 +83,9 @@ public class SignatureWriter extends SignatureVisitor {
/**
* The stack used to keep track of class types that have arguments. Each element of this stack is
* a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false
* = *2, pushing true = *2+1, popping = /2.
* a boolean encoded in one bit. The top of the stack is the least significant bit. The bottom of
* the stack is a sentinel element always equal to 1 (used to detect when the stack is full).
* Pushing false = {@code <<= 1}, pushing true = {@code ( <<= 1) | 1}, popping = {@code >>>= 1}.
*
* <p>Class type arguments must be surrounded with '&lt;' and '&gt;' and, because
*
@ -94,15 +95,20 @@ public class SignatureWriter extends SignatureVisitor {
* SignatureWriter instances),
* </ol>
*
* <p>we need a stack to properly balance these 'parentheses'. A new element is pushed on this
* stack for each new visited type, and popped when the visit of this type ends (either is
* <p>we need a stack to properly balance these angle brackets. A new element is pushed on this
* stack for each new visited type, and popped when the visit of this type ends (either in
* visitEnd, or because visitInnerClassType is called).
*/
private int argumentStack;
private int argumentStack = 1;
/** Constructs a new {@link SignatureWriter}. */
public SignatureWriter() {
this(new StringBuilder());
}
private SignatureWriter(final StringBuilder stringBuilder) {
super(/* latest api =*/ Opcodes.ASM9);
this.stringBuilder = stringBuilder;
}
// -----------------------------------------------------------------------------------------------
@ -191,7 +197,7 @@ public class SignatureWriter extends SignatureVisitor {
stringBuilder.append(name);
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
// we can tell at this point).
argumentStack *= 2;
argumentStack <<= 1;
}
@Override
@ -201,7 +207,7 @@ public class SignatureWriter extends SignatureVisitor {
stringBuilder.append(name);
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
// we can tell at this point).
argumentStack *= 2;
argumentStack <<= 1;
}
@Override
@ -209,7 +215,7 @@ public class SignatureWriter extends SignatureVisitor {
// If the top of the stack is 'false', this means we are visiting the first type argument of the
// currently visited type. We therefore need to append a '<', and to replace the top stack
// element with 'true' (meaning that the current type does have type arguments).
if (argumentStack % 2 == 0) {
if ((argumentStack & 1) == 0) {
argumentStack |= 1;
stringBuilder.append('<');
}
@ -221,14 +227,15 @@ public class SignatureWriter extends SignatureVisitor {
// If the top of the stack is 'false', this means we are visiting the first type argument of the
// currently visited type. We therefore need to append a '<', and to replace the top stack
// element with 'true' (meaning that the current type does have type arguments).
if (argumentStack % 2 == 0) {
if ((argumentStack & 1) == 0) {
argumentStack |= 1;
stringBuilder.append('<');
}
if (wildcard != '=') {
stringBuilder.append(wildcard);
}
return this;
// If the stack is full, start a nested one by returning a new SignatureWriter.
return (argumentStack & (1 << 31)) == 0 ? this : new SignatureWriter(stringBuilder);
}
@Override
@ -264,10 +271,9 @@ public class SignatureWriter extends SignatureVisitor {
// If the top of the stack is 'true', this means that some type arguments have been visited for
// the type whose visit is now ending. We therefore need to append a '>', and to pop one element
// from the stack.
if (argumentStack % 2 == 1) {
if ((argumentStack & 1) == 1) {
stringBuilder.append('>');
}
argumentStack /= 2;
argumentStack >>>= 1;
}
}

View File

@ -120,7 +120,10 @@ public abstract class AbstractInsnNode {
/** The type of {@link LineNumberNode} "instructions". */
public static final int LINE = 15;
/** The opcode of this instruction. */
/**
* The opcode of this instruction, or -1 if this is not a JVM instruction (e.g. a label or a line
* number).
*/
protected int opcode;
/**
@ -163,7 +166,8 @@ public abstract class AbstractInsnNode {
/**
* Returns the opcode of this instruction.
*
* @return the opcode of this instruction.
* @return the opcode of this instruction, or -1 if this is not a JVM instruction (e.g. a label or
* a line number).
*/
public int getOpcode() {
return opcode;
@ -295,4 +299,3 @@ public abstract class AbstractInsnNode {
return this;
}
}

View File

@ -260,4 +260,3 @@ public class AnnotationNode extends AnnotationVisitor {
}
}
}

View File

@ -90,14 +90,14 @@ public class ClassNode extends ClassVisitor {
*/
public int access;
/** The internal name of this class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName}). */
/** The internal name of this class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}). */
public String name;
/** The signature of this class. May be {@literal null}. */
public String signature;
/**
* The internal of name of the super class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName}).
* The internal of name of the super class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
* {@link Object} class.
*/
@ -105,7 +105,7 @@ public class ClassNode extends ClassVisitor {
/**
* The internal names of the interfaces directly implemented by this class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public List<String> interfaces;
@ -120,18 +120,26 @@ public class ClassNode extends ClassVisitor {
/** The module stored in this class. May be {@literal null}. */
public ModuleNode module;
/** The internal name of the enclosing class of this class. May be {@literal null}. */
/**
* The internal name of the enclosing class of this class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). Must be {@literal null} if this class has no
* enclosing class, or if it is a local or anonymous class.
*/
public String outerClass;
/**
* The name of the method that contains this class, or {@literal null} if this class is not
* enclosed in a method.
* The name of the method that contains the class, or {@literal null} if the class has no
* enclosing class, or is not enclosed in a method or constructor of its enclosing class (e.g. if
* it is enclosed in an instance initializer, static initializer, instance variable initializer,
* or class variable initializer).
*/
public String outerMethod;
/**
* The descriptor of the method that contains this class, or {@literal null} if this class is not
* enclosed in a method.
* The descriptor of the method that contains the class, or {@literal null} if the class has no
* enclosing class, or is not enclosed in a method or constructor of its enclosing class (e.g. if
* it is enclosed in an instance initializer, static initializer, instance variable initializer,
* or class variable initializer).
*/
public String outerMethodDesc;
@ -153,13 +161,22 @@ public class ClassNode extends ClassVisitor {
/** The inner classes of this class. */
public List<InnerClassNode> innerClasses;
/** The internal name of the nest host class of this class. May be {@literal null}. */
/**
* The internal name of the nest host class of this class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public String nestHostClass;
/** The internal names of the nest members of this class. May be {@literal null}. */
/**
* The internal names of the nest members of this class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public List<String> nestMembers;
/** The internal names of the permitted subclasses of this class. May be {@literal null}. */
/**
* The internal names of the permitted subclasses of this class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public List<String> permittedSubclasses;
/** The record components of this class. May be {@literal null}. */
@ -485,4 +502,3 @@ public class ClassNode extends ClassVisitor {
classVisitor.visitEnd();
}
}

View File

@ -72,7 +72,7 @@ public class FieldInsnNode extends AbstractInsnNode {
/**
* The internal name of the field's owner class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public String owner;
@ -88,7 +88,7 @@ public class FieldInsnNode extends AbstractInsnNode {
* @param opcode the opcode of the type instruction to be constructed. This opcode must be
* GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
* @param owner the internal name of the field's owner class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param name the field's name.
* @param descriptor the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
*/
@ -126,4 +126,3 @@ public class FieldInsnNode extends AbstractInsnNode {
return new FieldInsnNode(opcode, owner, name, desc).cloneAnnotations(this);
}
}

View File

@ -274,4 +274,3 @@ public class FieldNode extends FieldVisitor {
fieldVisitor.visitEnd();
}
}

View File

@ -111,14 +111,18 @@ public class FrameNode extends AbstractInsnNode {
* @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
* {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
* Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
* @param numLocal number of local variables of this stack map frame.
* @param numLocal number of local variables of this stack map frame. Long and double values count
* for one variable.
* @param local the types of the local variables of this stack map frame. Elements of this list
* can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
* types respectively - see {@link MethodVisitor}).
* @param numStack number of operand stack elements of this stack map frame.
* types respectively - see {@link MethodVisitor}). Long and double values are represented by
* a single element.
* @param numStack number of operand stack elements of this stack map frame. Long and double
* values count for one stack element.
* @param stack the types of the operand stack elements of this stack map frame. Elements of this
* list can be Integer, String or LabelNode objects (for primitive, reference and
* uninitialized types respectively - see {@link MethodVisitor}).
* uninitialized types respectively - see {@link MethodVisitor}). Long and double values are
* represented by a single element.
*/
public FrameNode(
final int type,
@ -218,4 +222,3 @@ public class FrameNode extends AbstractInsnNode {
return array;
}
}

View File

@ -104,4 +104,3 @@ public class IincInsnNode extends AbstractInsnNode {
return new IincInsnNode(var, incr).cloneAnnotations(this);
}
}

View File

@ -62,7 +62,11 @@ package jdk.internal.org.objectweb.asm.tree;
import jdk.internal.org.objectweb.asm.ClassVisitor;
/**
* A node that represents an inner class.
* A node that represents an inner class. This inner class is not necessarily a member of the {@link
* ClassNode} containing this object. More precisely, every class or interface C which is referenced
* by a {@link ClassNode} and which is not a package member must be represented with an {@link
* InnerClassNode}. The {@link ClassNode} must reference its nested class or interface members, and
* its enclosing class, if any. See the JVMS 4.7.6 section for more details.
*
* @author Eric Bruneton
*/
@ -78,25 +82,27 @@ public class InnerClassNode {
public String outerName;
/**
* The (simple) name of the inner class inside its enclosing class. May be {@literal null} for
* anonymous inner classes.
* The (simple) name of the inner class inside its enclosing class. Must be {@literal null} if the
* inner class is not the member of a class or interface (e.g. for local or anonymous classes).
*/
public String innerName;
/** The access flags of the inner class as originally declared in the enclosing class. */
/**
* The access flags of the inner class as originally declared in the source code from which the
* class was compiled.
*/
public int access;
/**
* Constructs a new {@link InnerClassNode}.
* Constructs a new {@link InnerClassNode} for an inner class C.
*
* @param name the internal name of an inner class (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param outerName the internal name of the class to which the inner class belongs (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
* {@literal null} for anonymous inner classes.
* @param access the access flags of the inner class as originally declared in the enclosing
* class.
* @param name the internal name of C (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param outerName the internal name of the class or interface C is a member of (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). Must be {@literal null} if C is not the member
* of a class or interface (e.g. for local or anonymous classes).
* @param innerName the (simple) name of C. Must be {@literal null} for anonymous inner classes.
* @param access the access flags of C originally declared in the source code from which this
* class was compiled.
*/
public InnerClassNode(
final String name, final String outerName, final String innerName, final int access) {
@ -115,4 +121,3 @@ public class InnerClassNode {
classVisitor.visitInnerClass(name, outerName, innerName, access);
}
}

View File

@ -634,4 +634,3 @@ public class InsnList implements Iterable<AbstractInsnNode> {
}
}
}

View File

@ -103,4 +103,3 @@ public class InsnNode extends AbstractInsnNode {
return new InsnNode(opcode).cloneAnnotations(this);
}
}

View File

@ -109,4 +109,3 @@ public class IntInsnNode extends AbstractInsnNode {
return new IntInsnNode(opcode, operand).cloneAnnotations(this);
}
}

View File

@ -98,12 +98,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) { // NOPMD(ArrayIsStoredDirectly): public field.
final Object... bootstrapMethodArguments) {
super(Opcodes.INVOKEDYNAMIC);
this.name = name;
this.desc = descriptor;
this.bsm = bootstrapMethodHandle;
this.bsmArgs = bootstrapMethodArguments;
this.bsmArgs = bootstrapMethodArguments; // NOPMD(ArrayIsStoredDirectly): public field.
}
@Override
@ -122,4 +122,3 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs).cloneAnnotations(this);
}
}

View File

@ -117,4 +117,3 @@ public class JumpInsnNode extends AbstractInsnNode {
return new JumpInsnNode(opcode, clone(label, clonedLabels)).cloneAnnotations(this);
}
}

View File

@ -109,4 +109,3 @@ public class LabelNode extends AbstractInsnNode {
value = null;
}
}

View File

@ -113,4 +113,3 @@ public class LdcInsnNode extends AbstractInsnNode {
return new LdcInsnNode(cst).cloneAnnotations(this);
}
}

View File

@ -104,4 +104,3 @@ public class LineNumberNode extends AbstractInsnNode {
return new LineNumberNode(line, clone(start, clonedLabels));
}
}

View File

@ -169,4 +169,3 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
typeRef, typePath, startLabels, endLabels, indices, desc, visible));
}
}

View File

@ -122,4 +122,3 @@ public class LocalVariableNode {
name, desc, signature, start.getLabel(), end.getLabel(), index);
}
}

View File

@ -123,4 +123,3 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
return clone.cloneAnnotations(this);
}
}

View File

@ -153,4 +153,3 @@ public class MethodInsnNode extends AbstractInsnNode {
return new MethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this);
}
}

View File

@ -326,14 +326,14 @@ public class MethodNode extends MethodVisitor {
AnnotationNode annotation = new AnnotationNode(descriptor);
if (visible) {
if (visibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(desc).length;
int params = Type.getArgumentCount(desc);
visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
visibleParameterAnnotations[parameter] =
Util.add(visibleParameterAnnotations[parameter], annotation);
} else {
if (invisibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(desc).length;
int params = Type.getArgumentCount(desc);
invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
invisibleParameterAnnotations[parameter] =
@ -802,4 +802,3 @@ public class MethodNode extends MethodVisitor {
methodVisitor.visitEnd();
}
}

View File

@ -69,7 +69,10 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
*/
public class ModuleExportNode {
/** The internal name of the exported package. */
/**
* The internal name of the exported package (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public String packaze;
/**
@ -87,7 +90,8 @@ public class ModuleExportNode {
/**
* Constructs a new {@link ModuleExportNode}.
*
* @param packaze the internal name of the exported package.
* @param packaze the internal name of the exported package (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param access the package access flags, one or more of {@code ACC_SYNTHETIC} and {@code
* ACC_MANDATED}.
* @param modules a list of modules that can access this exported package, specified with fully
@ -109,4 +113,3 @@ public class ModuleExportNode {
packaze, access, modules == null ? null : modules.toArray(new String[0]));
}
}

View File

@ -84,10 +84,16 @@ public class ModuleNode extends ModuleVisitor {
/** The version of this module. May be {@literal null}. */
public String version;
/** The internal name of the main class of this module. May be {@literal null}. */
/**
* The internal name of the main class of this module (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public String mainClass;
/** The internal name of the packages declared by this module. May be {@literal null}. */
/**
* The internal name of the packages declared by this module (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public List<String> packages;
/** The dependencies of this module. May be {@literal null}. */
@ -99,7 +105,10 @@ public class ModuleNode extends ModuleVisitor {
/** The packages opened by this module. May be {@literal null}. */
public List<ModuleOpenNode> opens;
/** The internal names of the services used by this module. May be {@literal null}. */
/**
* The internal names of the services used by this module (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
*/
public List<String> uses;
/** The services provided by this module. May be {@literal null}. */
@ -138,7 +147,8 @@ public class ModuleNode extends ModuleVisitor {
* @param requires The dependencies of this module. May be {@literal null}.
* @param exports The packages exported by this module. May be {@literal null}.
* @param opens The packages opened by this module. May be {@literal null}.
* @param uses The internal names of the services used by this module. May be {@literal null}.
* @param uses The internal names of the services used by this module (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
* @param provides The services provided by this module. May be {@literal null}.
*/
public ModuleNode(
@ -265,4 +275,3 @@ public class ModuleNode extends ModuleVisitor {
}
}
}

View File

@ -69,7 +69,9 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
*/
public class ModuleOpenNode {
/** The internal name of the opened package. */
/**
* The internal name of the opened package (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public String packaze;
/**
@ -87,7 +89,8 @@ public class ModuleOpenNode {
/**
* Constructs a new {@link ModuleOpenNode}.
*
* @param packaze the internal name of the opened package.
* @param packaze the internal name of the opened package (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
* @param access the access flag of the opened package, valid values are among {@code
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* @param modules the fully qualified names (using dots) of the modules that can use deep
@ -109,4 +112,3 @@ public class ModuleOpenNode {
packaze, access, modules == null ? null : modules.toArray(new String[0]));
}
}

View File

@ -69,10 +69,13 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
*/
public class ModuleProvideNode {
/** The internal name of the service. */
/** The internal name of the service (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}). */
public String service;
/** The internal names of the implementations of the service (there is at least one provider). */
/**
* The internal names of the implementations of the service (there is at least one provider). See
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}.
*/
public List<String> providers;
/**
@ -80,7 +83,7 @@ public class ModuleProvideNode {
*
* @param service the internal name of the service.
* @param providers the internal names of the implementations of the service (there is at least
* one provider).
* one provider). See {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}.
*/
public ModuleProvideNode(final String service, final List<String> providers) {
this.service = service;
@ -96,4 +99,3 @@ public class ModuleProvideNode {
moduleVisitor.visitProvide(service, providers.toArray(new String[0]));
}
}

View File

@ -103,4 +103,3 @@ public class ModuleRequireNode {
moduleVisitor.visitRequire(module, access, version);
}
}

View File

@ -104,4 +104,3 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
}
}

View File

@ -98,4 +98,3 @@ public class ParameterNode {
methodVisitor.visitParameter(name, access);
}
}

View File

@ -234,4 +234,3 @@ public class RecordComponentNode extends RecordComponentVisitor {
recordComponentVisitor.visitEnd();
}
}

View File

@ -123,4 +123,3 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
.cloneAnnotations(this);
}
}

View File

@ -98,8 +98,9 @@ public class TryCatchBlockNode {
* @param start the beginning of the exception handler's scope (inclusive).
* @param end the end of the exception handler's scope (exclusive).
* @param handler the beginning of the exception handler's code.
* @param type the internal name of the type of exceptions handled by the handler, or {@literal
* null} to catch any exceptions (for "finally" blocks).
* @param type the internal name of the type of exceptions handled by the handler (see {@link
* jdk.internal.org.objectweb.asm.Type#getInternalName()}), or {@literal null} to catch any exceptions (for
* "finally" blocks).
*/
public TryCatchBlockNode(
final LabelNode start, final LabelNode end, final LabelNode handler, final String type) {
@ -156,4 +157,3 @@ public class TryCatchBlockNode {
}
}
}

View File

@ -115,4 +115,3 @@ public class TypeAnnotationNode extends AnnotationNode {
this.typePath = typePath;
}
}

View File

@ -63,16 +63,16 @@ import java.util.Map;
import jdk.internal.org.objectweb.asm.MethodVisitor;
/**
* A node that represents a type instruction. A type instruction is an instruction that takes a type
* descriptor as parameter.
* A node that represents a type instruction. A type instruction is an instruction which takes an
* internal name as parameter (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*
* @author Eric Bruneton
*/
public class TypeInsnNode extends AbstractInsnNode {
/**
* The operand of this instruction. This operand is an internal name (see {@link
* jdk.internal.org.objectweb.asm.Type}).
* The operand of this instruction. Despite its name (due to historical reasons), this operand is
* an internal name (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public String desc;
@ -81,12 +81,12 @@ public class TypeInsnNode extends AbstractInsnNode {
*
* @param opcode the opcode of the type instruction to be constructed. This opcode must be NEW,
* ANEWARRAY, CHECKCAST or INSTANCEOF.
* @param descriptor the operand of the instruction to be constructed. This operand is an internal
* name (see {@link jdk.internal.org.objectweb.asm.Type}).
* @param type the operand of the instruction to be constructed. This operand is an internal name
* (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}).
*/
public TypeInsnNode(final int opcode, final String descriptor) {
public TypeInsnNode(final int opcode, final String type) {
super(opcode);
this.desc = descriptor;
this.desc = type;
}
/**
@ -115,4 +115,3 @@ public class TypeInsnNode extends AbstractInsnNode {
return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
}
}

View File

@ -70,4 +70,3 @@ public class UnsupportedClassVersionException extends RuntimeException {
private static final long serialVersionUID = -3502347765891805831L;
}

View File

@ -193,4 +193,3 @@ final class Util {
return list;
}
}

View File

@ -112,4 +112,3 @@ public class VarInsnNode extends AbstractInsnNode {
return new VarInsnNode(opcode, var).cloneAnnotations(this);
}
}

View File

@ -80,7 +80,7 @@ import jdk.internal.org.objectweb.asm.tree.VarInsnNode;
* A semantic bytecode analyzer. <i>This class does not fully check that JSR and RET instructions
* are valid.</i>
*
* @param <V> type of the Value used for the analysis.
* @param <V> type of the {@link Value} used for the analysis.
* @author Eric Bruneton
*/
public class Analyzer<V extends Value> implements Opcodes {
@ -124,7 +124,8 @@ public class Analyzer<V extends Value> implements Opcodes {
/**
* Analyzes the given method.
*
* @param owner the internal name of the class to which 'method' belongs.
* @param owner the internal name of the class to which 'method' belongs (see {@link
* Type#getInternalName()}).
* @param method the method to be analyzed. The maxStack and maxLocals fields must have correct
* values.
* @return the symbolic state of the execution stack frame at each bytecode instruction of the
@ -154,7 +155,7 @@ public class Analyzer<V extends Value> implements Opcodes {
TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i);
int startIndex = insnList.indexOf(tryCatchBlock.start);
int endIndex = insnList.indexOf(tryCatchBlock.end);
for (int j = startIndex; j < endIndex; ++j) {
for (int j = startIndex; j <= endIndex; ++j) {
List<TryCatchBlockNode> insnHandlers = handlers[j];
if (insnHandlers == null) {
insnHandlers = new ArrayList<>();
@ -164,37 +165,19 @@ public class Analyzer<V extends Value> implements Opcodes {
}
}
// For each instruction, compute the subroutine to which it belongs.
// Follow the main 'subroutine', and collect the jsr instructions to nested subroutines.
Subroutine main = new Subroutine(null, method.maxLocals, null);
List<AbstractInsnNode> jsrInsns = new ArrayList<>();
findSubroutine(0, main, jsrInsns);
// Follow the nested subroutines, and collect their own nested subroutines, until all
// subroutines are found.
Map<LabelNode, Subroutine> jsrSubroutines = new HashMap<>();
while (!jsrInsns.isEmpty()) {
JumpInsnNode jsrInsn = (JumpInsnNode) jsrInsns.remove(0);
Subroutine subroutine = jsrSubroutines.get(jsrInsn.label);
if (subroutine == null) {
subroutine = new Subroutine(jsrInsn.label, method.maxLocals, jsrInsn);
jsrSubroutines.put(jsrInsn.label, subroutine);
findSubroutine(insnList.indexOf(jsrInsn.label), subroutine, jsrInsns);
} else {
subroutine.callers.add(jsrInsn);
}
}
// Clear the main 'subroutine', which is not a real subroutine (and was used only as an
// intermediate step above to find the real ones).
for (int i = 0; i < insnListSize; ++i) {
if (subroutines[i] != null && subroutines[i].start == null) {
subroutines[i] = null;
}
}
// Finds the method's subroutines.
findSubroutines(method.maxLocals);
// Initializes the data structures for the control flow analysis.
Frame<V> currentFrame = computeInitialFrame(owner, method);
merge(0, currentFrame, null);
init(owner, method);
Frame<V> currentFrame;
try {
currentFrame = computeInitialFrame(owner, method);
merge(0, currentFrame, null);
init(owner, method);
} catch (RuntimeException e) {
// DontCheck(IllegalCatch): can't be fixed, for backward compatibility.
throw new AnalyzerException(insnList.get(0), "Error at instruction 0: " + e.getMessage(), e);
}
// Control flow analysis.
while (numInstructionsToProcess > 0) {
@ -336,7 +319,8 @@ public class Analyzer<V extends Value> implements Opcodes {
* Analyzes the given method and computes and sets its maximum stack size and maximum number of
* local variables.
*
* @param owner the internal name of the class to which 'method' belongs.
* @param owner the internal name of the class to which 'method' belongs (see {@link
* Type#getInternalName()}).
* @param method the method to be analyzed.
* @return the symbolic state of the execution stack frame at each bytecode instruction of the
* method. The size of the returned array is equal to the number of instructions (and labels)
@ -361,6 +345,9 @@ public class Analyzer<V extends Value> implements Opcodes {
*/
private static int computeMaxLocals(final MethodNode method) {
int maxLocals = Type.getArgumentsAndReturnSizes(method.desc) >> 2;
if ((method.access & Opcodes.ACC_STATIC) != 0) {
maxLocals -= 1;
}
for (AbstractInsnNode insnNode : method.instructions) {
if (insnNode instanceof VarInsnNode) {
int local = ((VarInsnNode) insnNode).var;
@ -400,6 +387,42 @@ public class Analyzer<V extends Value> implements Opcodes {
return maxStack;
}
/**
* Finds the subroutines of the currently analyzed method and stores them in {@link #subroutines}.
*
* @param maxLocals the maximum number of local variables of the currently analyzed method (long
* and double values count for two variables).
* @throws AnalyzerException if the control flow graph can fall off the end of the code.
*/
private void findSubroutines(final int maxLocals) throws AnalyzerException {
// For each instruction, compute the subroutine to which it belongs.
// Follow the main 'subroutine', and collect the jsr instructions to nested subroutines.
Subroutine main = new Subroutine(null, maxLocals, null);
List<AbstractInsnNode> jsrInsns = new ArrayList<>();
findSubroutine(0, main, jsrInsns);
// Follow the nested subroutines, and collect their own nested subroutines, until all
// subroutines are found.
Map<LabelNode, Subroutine> jsrSubroutines = new HashMap<>();
while (!jsrInsns.isEmpty()) {
JumpInsnNode jsrInsn = (JumpInsnNode) jsrInsns.remove(0);
Subroutine subroutine = jsrSubroutines.get(jsrInsn.label);
if (subroutine == null) {
subroutine = new Subroutine(jsrInsn.label, maxLocals, jsrInsn);
jsrSubroutines.put(jsrInsn.label, subroutine);
findSubroutine(insnList.indexOf(jsrInsn.label), subroutine, jsrInsns);
} else {
subroutine.callers.add(jsrInsn);
}
}
// Clear the main 'subroutine', which is not a real subroutine (and was used only as an
// intermediate step above to find the real ones).
for (int i = 0; i < insnListSize; ++i) {
if (subroutines[i] != null && subroutines[i].start == null) {
subroutines[i] = null;
}
}
}
/**
* Follows the control flow graph of the currently analyzed method, starting at the given
* instruction index, and stores a copy of the given subroutine in {@link #subroutines} for each
@ -485,7 +508,8 @@ public class Analyzer<V extends Value> implements Opcodes {
/**
* Computes the initial execution stack frame of the given method.
*
* @param owner the internal name of the class to which 'method' belongs.
* @param owner the internal name of the class to which 'method' belongs (see {@link
* Type#getInternalName()}).
* @param method the method to be analyzed.
* @return the initial execution stack frame of the 'method'.
*/
@ -542,9 +566,10 @@ public class Analyzer<V extends Value> implements Opcodes {
/**
* Initializes this analyzer. This method is called just before the execution of control flow
* analysis loop in #analyze. The default implementation of this method does nothing.
* analysis loop in {@link #analyze}. The default implementation of this method does nothing.
*
* @param owner the internal name of the class to which the method belongs.
* @param owner the internal name of the class to which the method belongs (see {@link
* Type#getInternalName()}).
* @param method the method to be analyzed.
* @throws AnalyzerException if a problem occurs.
*/
@ -702,4 +727,3 @@ public class Analyzer<V extends Value> implements Opcodes {
}
}
}

View File

@ -119,4 +119,3 @@ public class AnalyzerException extends Exception {
this.node = insn;
}
}

View File

@ -405,4 +405,3 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements Opcodes
return value1;
}
}

View File

@ -159,4 +159,3 @@ public class BasicValue implements Value {
}
}
}

View File

@ -480,4 +480,3 @@ public class BasicVerifier extends BasicInterpreter {
return value.equals(expected);
}
}

View File

@ -704,7 +704,7 @@ public class Frame<V extends Value> {
final AbstractInsnNode insn, final String methodDescriptor, final Interpreter<V> interpreter)
throws AnalyzerException {
ArrayList<V> valueList = new ArrayList<>();
for (int i = Type.getArgumentTypes(methodDescriptor).length; i > 0; --i) {
for (int i = Type.getArgumentCount(methodDescriptor); i > 0; --i) {
valueList.add(0, pop());
}
if (insn.getOpcode() != Opcodes.INVOKESTATIC && insn.getOpcode() != Opcodes.INVOKEDYNAMIC) {
@ -782,4 +782,3 @@ public class Frame<V extends Value> {
return stringBuilder.toString();
}
}

View File

@ -297,4 +297,3 @@ public abstract class Interpreter<V extends Value> {
*/
public abstract V merge(V value1, V value2);
}

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