8323835: Updating ASM to 9.6 for JDK 23
Reviewed-by: mchung
This commit is contained in:
parent
a65a89522d
commit
91d8ea79d9
@ -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.
|
||||
*
|
||||
|
@ -403,4 +403,3 @@ public class ByteVector {
|
||||
data = newData;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,4 +208,3 @@ public final class ConstantDynamic {
|
||||
+ Arrays.toString(bootstrapMethodArguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,4 +251,3 @@ final class Constants {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,4 +166,3 @@ final class Context {
|
||||
*/
|
||||
Object[] currentFrameStackTypes;
|
||||
}
|
||||
|
||||
|
@ -85,4 +85,3 @@ final class CurrentFrame extends Frame {
|
||||
copyFrom(successor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,4 +121,3 @@ final class Edge {
|
||||
this.nextEdge = nextEdge;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,4 +314,3 @@ final class FieldWriter extends FieldVisitor {
|
||||
attributePrototypes.addAttributes(firstAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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" : "") + ')';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,4 +228,3 @@ final class Handler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 <init> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,4 +283,3 @@ final class ModuleWriter extends ModuleVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,4 +588,3 @@ public interface Opcodes {
|
||||
int IFNULL = 198; // visitJumpInsn
|
||||
int IFNONNULL = 199; // -
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,4 +255,3 @@ final class RecordComponentWriter extends RecordComponentVisitor {
|
||||
attributePrototypes.addAttributes(firstAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 <init> 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 <init> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 <init> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 << 2) | returnSize} (argumentsSize is therefore equal to {@code
|
||||
* i >> 2}, and returnSize to {@code i & 0x03}).
|
||||
* i >> 2}, and returnSize to {@code i & 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 << 2) | returnSize} (argumentsSize is therefore equal to {@code
|
||||
* i >> 2}, and returnSize to {@code i & 0x03}).
|
||||
* i >> 2}, and returnSize to {@code i & 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,4 +230,3 @@ public final class TypePath {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,4 +465,3 @@ public class TypeReference {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -700,4 +700,3 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
|
||||
*/
|
||||
protected void onMethodExit(final int opcode) {}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,4 +329,3 @@ public class ClassRemapper extends ClassVisitor {
|
||||
return new RecordComponentRemapper(api, recordComponentVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,4 +237,3 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
||||
super.visitMultiANewArrayInsn(descriptor, numDimensions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,4 +144,3 @@ public class FieldRemapper extends FieldVisitor {
|
||||
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,4 +381,3 @@ public class LocalVariablesSorter extends MethodVisitor {
|
||||
return local;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,4 +292,3 @@ public class Method {
|
||||
return name.hashCode() ^ descriptor.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,4 +319,3 @@ public class MethodRemapper extends MethodVisitor {
|
||||
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,4 +168,3 @@ public final class ModuleHashesAttribute extends Attribute {
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,4 +150,3 @@ public class ModuleRemapper extends ModuleVisitor {
|
||||
super.visitProvide(remapper.mapType(service), remappedProviders);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,4 +142,3 @@ public final class ModuleResolutionAttribute extends Attribute {
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,4 +116,3 @@ public final class ModuleTargetAttribute extends Attribute {
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,4 +147,3 @@ public class RecordComponentRemapper extends RecordComponentVisitor {
|
||||
.orDeprecatedValue(createAnnotationRemapper(annotationVisitor));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,4 +522,3 @@ public class SerialVersionUIDAdder extends ClassVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,4 +202,3 @@ public class SignatureRemapper extends SignatureVisitor {
|
||||
classNames.remove(classNames.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ public class SimpleRemapper extends Remapper {
|
||||
* attribute (in the form <owner>.<name>), 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,4 +154,3 @@ public class StaticInitMerger extends ClassVisitor {
|
||||
super.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,4 +81,3 @@ public interface TableSwitchGenerator {
|
||||
/** Generates the code for the default switch case. */
|
||||
void generateDefault();
|
||||
}
|
||||
|
||||
|
@ -155,4 +155,3 @@ public class TryCatchBlockSorter extends MethodNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,4 +282,3 @@ public class SignatureReader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
}
|
||||
|
||||
|
@ -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 '<' and '>' 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,4 +260,3 @@ public class AnnotationNode extends AnnotationVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,4 +274,3 @@ public class FieldNode extends FieldVisitor {
|
||||
fieldVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,4 +104,3 @@ public class IincInsnNode extends AbstractInsnNode {
|
||||
return new IincInsnNode(var, incr).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,4 +634,3 @@ public class InsnList implements Iterable<AbstractInsnNode> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,3 @@ public class InsnNode extends AbstractInsnNode {
|
||||
return new InsnNode(opcode).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,4 +109,3 @@ public class IntInsnNode extends AbstractInsnNode {
|
||||
return new IntInsnNode(opcode, operand).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,4 +117,3 @@ public class JumpInsnNode extends AbstractInsnNode {
|
||||
return new JumpInsnNode(opcode, clone(label, clonedLabels)).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,4 +109,3 @@ public class LabelNode extends AbstractInsnNode {
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,4 +113,3 @@ public class LdcInsnNode extends AbstractInsnNode {
|
||||
return new LdcInsnNode(cst).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,4 +104,3 @@ public class LineNumberNode extends AbstractInsnNode {
|
||||
return new LineNumberNode(line, clone(start, clonedLabels));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,4 +169,3 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
|
||||
typeRef, typePath, startLabels, endLabels, indices, desc, visible));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,4 +122,3 @@ public class LocalVariableNode {
|
||||
name, desc, signature, start.getLabel(), end.getLabel(), index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,4 +123,3 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
|
||||
return clone.cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,4 +153,3 @@ public class MethodInsnNode extends AbstractInsnNode {
|
||||
return new MethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,4 +103,3 @@ public class ModuleRequireNode {
|
||||
moduleVisitor.visitRequire(module, access, version);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,4 +104,3 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
|
||||
return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,4 +98,3 @@ public class ParameterNode {
|
||||
methodVisitor.visitParameter(name, access);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,4 +234,3 @@ public class RecordComponentNode extends RecordComponentVisitor {
|
||||
recordComponentVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,4 +123,3 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
|
||||
.cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,4 +115,3 @@ public class TypeAnnotationNode extends AnnotationNode {
|
||||
this.typePath = typePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,4 +70,3 @@ public class UnsupportedClassVersionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -3502347765891805831L;
|
||||
}
|
||||
|
||||
|
@ -193,4 +193,3 @@ final class Util {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,4 +112,3 @@ public class VarInsnNode extends AbstractInsnNode {
|
||||
return new VarInsnNode(opcode, var).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,4 +119,3 @@ public class AnalyzerException extends Exception {
|
||||
this.node = insn;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,4 +405,3 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements Opcodes
|
||||
return value1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,4 +159,3 @@ public class BasicValue implements Value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,4 +480,3 @@ public class BasicVerifier extends BasicInterpreter {
|
||||
return value.equals(expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user