Browse Source

Checkstyle updates from ASM master

Issue: SPR-17267
pull/1942/merge
Juergen Hoeller 6 years ago
parent
commit
69e8bcdf40
  1. 13
      spring-core/src/main/java/org/springframework/asm/ByteVector.java
  2. 76
      spring-core/src/main/java/org/springframework/asm/ClassReader.java
  3. 12
      spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java
  4. 9
      spring-core/src/main/java/org/springframework/asm/ClassWriter.java
  5. 4
      spring-core/src/main/java/org/springframework/asm/Constants.java
  6. 127
      spring-core/src/main/java/org/springframework/asm/Frame.java
  7. 2
      spring-core/src/main/java/org/springframework/asm/Label.java
  8. 24
      spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java
  9. 18
      spring-core/src/main/java/org/springframework/asm/MethodVisitor.java
  10. 111
      spring-core/src/main/java/org/springframework/asm/MethodWriter.java
  11. 1
      spring-core/src/main/java/org/springframework/asm/Opcodes.java
  12. 2
      spring-core/src/main/java/org/springframework/asm/Symbol.java
  13. 165
      spring-core/src/main/java/org/springframework/asm/SymbolTable.java
  14. 411
      spring-core/src/main/java/org/springframework/asm/Type.java

13
spring-core/src/main/java/org/springframework/asm/ByteVector.java

@ -239,6 +239,7 @@ public class ByteVector { @@ -239,6 +239,7 @@ public class ByteVector {
* @param stringValue a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public ByteVector putUTF8(final String stringValue) {
int charLength = stringValue.length();
if (charLength > 65535) {
@ -261,7 +262,7 @@ public class ByteVector { @@ -261,7 +262,7 @@ public class ByteVector {
currentData[currentLength++] = (byte) charValue;
} else {
length = currentLength;
return encodeUTF8(stringValue, i, 65535);
return encodeUtf8(stringValue, i, 65535);
}
}
length = currentLength;
@ -280,14 +281,14 @@ public class ByteVector { @@ -280,14 +281,14 @@ public class ByteVector {
* encoded characters.
* @return this byte vector.
*/
final ByteVector encodeUTF8(final String stringValue, final int offset, final int maxByteLength) {
final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) {
int charLength = stringValue.length();
int byteLength = offset;
for (int i = offset; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= '\u0001' && charValue <= '\u007F') {
if (charValue >= 0x0001 && charValue <= 0x007F) {
byteLength++;
} else if (charValue <= '\u07FF') {
} else if (charValue <= 0x07FF) {
byteLength += 2;
} else {
byteLength += 3;
@ -308,9 +309,9 @@ public class ByteVector { @@ -308,9 +309,9 @@ public class ByteVector {
int currentLength = length;
for (int i = offset; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= '\u0001' && charValue <= '\u007F') {
if (charValue >= 0x0001 && charValue <= 0x007F) {
data[currentLength++] = (byte) charValue;
} else if (charValue <= '\u07FF') {
} else if (charValue <= 0x07FF) {
data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F);
data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
} else {

76
spring-core/src/main/java/org/springframework/asm/ClassReader.java

@ -99,6 +99,7 @@ public class ClassReader { @@ -99,6 +99,7 @@ public class ClassReader {
* necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct
* ClassFile element offsets within this byte array.
*/
// DontCheck(MemberName): can't be renamed (for backward binary compatibility).
public final byte[] b;
/**
@ -488,7 +489,7 @@ public class ClassReader { @@ -488,7 +489,7 @@ public class ClassReader {
accessFlags |= Opcodes.ACC_SYNTHETIC;
} else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
sourceDebugExtension =
readUTF(currentAttributeOffset, attributeLength, new char[attributeLength]);
readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]);
} else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
} else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
@ -530,7 +531,8 @@ public class ClassReader { @@ -530,7 +531,8 @@ public class ClassReader {
// Visit the Module, ModulePackages and ModuleMainClass attributes.
if (moduleOffset != 0) {
readModule(classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
readModuleAttributes(
classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
}
// Visit the NestHost attribute.
@ -685,7 +687,7 @@ public class ClassReader { @@ -685,7 +687,7 @@ public class ClassReader {
// ----------------------------------------------------------------------------------------------
/**
* Reads the module attribute and visit it.
* Reads the Module, ModulePackages and ModuleMainClass attributes and visit them.
*
* @param classVisitor the current class visitor
* @param context information about the class being parsed.
@ -695,7 +697,7 @@ public class ClassReader { @@ -695,7 +697,7 @@ public class ClassReader {
* attribute_info's attribute_name_index and attribute_length fields), or 0.
* @param moduleMainClass the string corresponding to the ModuleMainClass attribute, or null.
*/
private void readModule(
private void readModuleAttributes(
final ClassVisitor classVisitor,
final Context context,
final int moduleOffset,
@ -1111,7 +1113,7 @@ public class ClassReader { @@ -1111,7 +1113,7 @@ public class ClassReader {
context.currentMethodAccessFlags,
context.currentMethodName,
context.currentMethodDescriptor,
signatureIndex == 0 ? null : readUTF(signatureIndex, charBuffer),
signatureIndex == 0 ? null : readUtf(signatureIndex, charBuffer),
exceptions);
if (methodVisitor == null) {
return currentOffset;
@ -1601,18 +1603,15 @@ public class ClassReader { @@ -1601,18 +1603,15 @@ public class ClassReader {
// Read the 'exception_table_length' and 'exception_table' field to create a label for each
// referenced instruction, and to make methodVisitor visit the corresponding try catch blocks.
{
int exceptionTableLength = readUnsignedShort(currentOffset);
currentOffset += 2;
while (exceptionTableLength-- > 0) {
Label start = createLabel(readUnsignedShort(currentOffset), labels);
Label end = createLabel(readUnsignedShort(currentOffset + 2), labels);
Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels);
String catchType =
readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer);
currentOffset += 8;
methodVisitor.visitTryCatchBlock(start, end, handler, catchType);
}
int exceptionTableLength = readUnsignedShort(currentOffset);
currentOffset += 2;
while (exceptionTableLength-- > 0) {
Label start = createLabel(readUnsignedShort(currentOffset), labels);
Label end = createLabel(readUnsignedShort(currentOffset + 2), labels);
Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels);
String catchType = readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer);
currentOffset += 8;
methodVisitor.visitTryCatchBlock(start, end, handler, catchType);
}
// Read the Code attributes to create a label for each referenced instruction (the variables
@ -2142,11 +2141,11 @@ public class ClassReader { @@ -2142,11 +2141,11 @@ public class ClassReader {
currentOffset += 4 - (currentBytecodeOffset & 3);
// Read the instruction.
Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
int nPairs = readInt(currentOffset + 4);
int numPairs = readInt(currentOffset + 4);
currentOffset += 8;
int[] keys = new int[nPairs];
Label[] values = new Label[nPairs];
for (int i = 0; i < nPairs; ++i) {
int[] keys = new int[numPairs];
Label[] values = new Label[numPairs];
for (int i = 0; i < numPairs; ++i) {
keys[i] = readInt(currentOffset);
values[i] = labels[currentBytecodeOffset + readInt(currentOffset + 4)];
currentOffset += 8;
@ -2958,12 +2957,12 @@ public class ClassReader { @@ -2958,12 +2957,12 @@ public class ClassReader {
private void computeImplicitFrame(final Context context) {
String methodDescriptor = context.currentMethodDescriptor;
Object[] locals = context.currentFrameLocalTypes;
int nLocal = 0;
int numLocal = 0;
if ((context.currentMethodAccessFlags & Opcodes.ACC_STATIC) == 0) {
if ("<init>".equals(context.currentMethodName)) {
locals[nLocal++] = Opcodes.UNINITIALIZED_THIS;
locals[numLocal++] = Opcodes.UNINITIALIZED_THIS;
} else {
locals[nLocal++] = readClass(header + 2, context.charBuffer);
locals[numLocal++] = readClass(header + 2, context.charBuffer);
}
}
// Parse the method descriptor, one argument type descriptor at each iteration. Start by
@ -2977,16 +2976,16 @@ public class ClassReader { @@ -2977,16 +2976,16 @@ public class ClassReader {
case 'B':
case 'S':
case 'I':
locals[nLocal++] = Opcodes.INTEGER;
locals[numLocal++] = Opcodes.INTEGER;
break;
case 'F':
locals[nLocal++] = Opcodes.FLOAT;
locals[numLocal++] = Opcodes.FLOAT;
break;
case 'J':
locals[nLocal++] = Opcodes.LONG;
locals[numLocal++] = Opcodes.LONG;
break;
case 'D':
locals[nLocal++] = Opcodes.DOUBLE;
locals[numLocal++] = Opcodes.DOUBLE;
break;
case '[':
while (methodDescriptor.charAt(currentMethodDescritorOffset) == '[') {
@ -2998,7 +2997,7 @@ public class ClassReader { @@ -2998,7 +2997,7 @@ public class ClassReader {
++currentMethodDescritorOffset;
}
}
locals[nLocal++] =
locals[numLocal++] =
methodDescriptor.substring(
currentArgumentDescriptorStartOffset, ++currentMethodDescritorOffset);
break;
@ -3006,12 +3005,12 @@ public class ClassReader { @@ -3006,12 +3005,12 @@ public class ClassReader {
while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
++currentMethodDescritorOffset;
}
locals[nLocal++] =
locals[numLocal++] =
methodDescriptor.substring(
currentArgumentDescriptorStartOffset + 1, currentMethodDescritorOffset++);
break;
default:
context.currentFrameLocalCount = nLocal;
context.currentFrameLocalCount = numLocal;
return;
}
}
@ -3178,7 +3177,11 @@ public class ClassReader { @@ -3178,7 +3177,11 @@ public class ClassReader {
// Methods to parse attributes
// ----------------------------------------------------------------------------------------------
/** @return the offset in {@link #b} of the first ClassFile's 'attributes' array field entry. */
/**
* Returns the offset in {@link #b} of the first ClassFile's 'attributes' array field entry.
*
* @return the offset in {@link #b} of the first ClassFile's 'attributes' array field entry.
*/
final int getFirstAttributeOffset() {
// Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes
// each), as well as the interfaces array field (2 bytes per interface).
@ -3399,12 +3402,13 @@ public class ClassReader { @@ -3399,12 +3402,13 @@ public class ClassReader {
* large. It is not automatically resized.
* @return the String corresponding to the specified CONSTANT_Utf8 entry.
*/
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public String readUTF8(final int offset, final char[] charBuffer) {
int constantPoolEntryIndex = readUnsignedShort(offset);
if (offset == 0 || constantPoolEntryIndex == 0) {
return null;
}
return readUTF(constantPoolEntryIndex, charBuffer);
return readUtf(constantPoolEntryIndex, charBuffer);
}
/**
@ -3416,14 +3420,14 @@ public class ClassReader { @@ -3416,14 +3420,14 @@ public class ClassReader {
* large. It is not automatically resized.
* @return the String corresponding to the specified CONSTANT_Utf8 entry.
*/
final String readUTF(final int constantPoolEntryIndex, final char[] charBuffer) {
final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) {
String value = constantUtf8Values[constantPoolEntryIndex];
if (value != null) {
return value;
}
int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
return constantUtf8Values[constantPoolEntryIndex] =
readUTF(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);
readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);
}
/**
@ -3435,7 +3439,7 @@ public class ClassReader { @@ -3435,7 +3439,7 @@ public class ClassReader {
* large. It is not automatically resized.
* @return the String corresponding to the specified UTF8 string.
*/
private String readUTF(final int utfOffset, final int utfLength, final char[] charBuffer) {
private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) {
int currentOffset = utfOffset;
int endOffset = currentOffset + utfLength;
int strLength = 0;

12
spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java

@ -51,12 +51,20 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException { @@ -51,12 +51,20 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException {
this.constantPoolCount = constantPoolCount;
}
/** @return the internal name of the class. */
/**
* Returns the internal name of the class.
*
* @return the internal name of the class.
*/
public String getClassName() {
return className;
}
/** @return the number of constant pool items of the class. */
/**
* Returns the number of constant pool items of the class.
*
* @return the number of constant pool items of the class.
*/
public int getConstantPoolCount() {
return constantPoolCount;
}

9
spring-core/src/main/java/org/springframework/asm/ClassWriter.java

@ -282,7 +282,7 @@ public class ClassWriter extends ClassVisitor { @@ -282,7 +282,7 @@ public class ClassWriter extends ClassVisitor {
sourceFileIndex = symbolTable.addConstantUtf8(file);
}
if (debug != null) {
debugExtension = new ByteVector().encodeUTF8(debug, 0, Integer.MAX_VALUE);
debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE);
}
}
@ -674,7 +674,7 @@ public class ClassWriter extends ClassVisitor { @@ -674,7 +674,7 @@ public class ClassWriter extends ClassVisitor {
* ones.
*/
private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) {
Attribute[] attributes = getAttributePrototypes();
final Attribute[] attributes = getAttributePrototypes();
firstField = null;
lastField = null;
firstMethod = null;
@ -743,6 +743,7 @@ public class ClassWriter extends ClassVisitor { @@ -743,6 +743,7 @@ public class ClassWriter extends ClassVisitor {
* @param value the String value.
* @return the index of a new or already existing UTF8 item.
*/
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
public int newUTF8(final String value) {
return symbolTable.addConstantUtf8(value);
}
@ -947,13 +948,13 @@ public class ClassWriter extends ClassVisitor { @@ -947,13 +948,13 @@ public class ClassWriter extends ClassVisitor {
Class<?> class1;
try {
class1 = Class.forName(type1.replace('/', '.'), false, classLoader);
} catch (Exception e) {
} catch (ClassNotFoundException e) {
throw new TypeNotPresentException(type1, e);
}
Class<?> class2;
try {
class2 = Class.forName(type2.replace('/', '.'), false, classLoader);
} catch (Exception e) {
} catch (ClassNotFoundException e) {
throw new TypeNotPresentException(type2, e);
}
if (class1.isAssignableFrom(class2)) {

4
spring-core/src/main/java/org/springframework/asm/Constants.java

@ -36,8 +36,6 @@ package org.springframework.asm; @@ -36,8 +36,6 @@ package org.springframework.asm;
*/
final class Constants implements Opcodes {
private Constants() {}
// The ClassFile attribute names, in the order they are defined in
// https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
@ -173,4 +171,6 @@ final class Constants implements Opcodes { @@ -173,4 +171,6 @@ final class Constants implements Opcodes {
static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA;
static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
static final int ASM_GOTO_W = 220;
private Constants() {}
}

127
spring-core/src/main/java/org/springframework/asm/Frame.java

@ -223,6 +223,38 @@ class Frame { @@ -223,6 +223,38 @@ class Frame {
*/
private int[] initializations;
// -----------------------------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------------------------
/**
* Constructs a new Frame.
*
* @param owner the basic block to which these input and output stack map frames correspond.
*/
Frame(final Label owner) {
this.owner = owner;
}
/**
* Sets this frame to the value of the given frame.
*
* <p>WARNING: after this method is called the two frames share the same data structures. It is
* recommended to discard the given frame to avoid unexpected side effects.
*
* @param frame The new frame value.
*/
final void copyFrom(final Frame frame) {
inputLocals = frame.inputLocals;
inputStack = frame.inputStack;
outputStackStart = 0;
outputLocals = frame.outputLocals;
outputStack = frame.outputStack;
outputStackTop = frame.outputStackTop;
initializationCount = frame.initializationCount;
initializations = frame.initializations;
}
// -----------------------------------------------------------------------------------------------
// Static methods to get abstract types from other type formats
// -----------------------------------------------------------------------------------------------
@ -336,38 +368,6 @@ class Frame { @@ -336,38 +368,6 @@ class Frame {
}
}
// -----------------------------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------------------------
/**
* Constructs a new Frame.
*
* @param owner the basic block to which these input and output stack map frames correspond.
*/
Frame(final Label owner) {
this.owner = owner;
}
/**
* Sets this frame to the value of the given frame.
*
* <p>WARNING: after this method is called the two frames share the same data structures. It is
* recommended to discard the given frame to avoid unexpected side effects.
*
* @param frame The new frame value.
*/
final void copyFrom(final Frame frame) {
inputLocals = frame.inputLocals;
inputStack = frame.inputStack;
outputStackStart = 0;
outputLocals = frame.outputLocals;
outputStack = frame.outputStack;
outputStackTop = frame.outputStackTop;
initializationCount = frame.initializationCount;
initializations = frame.initializations;
}
// -----------------------------------------------------------------------------------------------
// Methods related to the input frame
// -----------------------------------------------------------------------------------------------
@ -415,21 +415,21 @@ class Frame { @@ -415,21 +415,21 @@ class Frame {
* Sets the input frame from the given public API frame description.
*
* @param symbolTable the type table to use to lookup and store type {@link Symbol}.
* @param nLocal the number of local variables.
* @param numLocal the number of local variables.
* @param local the local variable types, described using the same format as in {@link
* MethodVisitor#visitFrame}.
* @param nStack the number of operand stack elements.
* @param numStack the number of operand stack elements.
* @param stack the operand stack types, described using the same format as in {@link
* MethodVisitor#visitFrame}.
*/
final void setInputFrameFromApiFormat(
final SymbolTable symbolTable,
final int nLocal,
final int numLocal,
final Object[] local,
final int nStack,
final int numStack,
final Object[] stack) {
int inputLocalIndex = 0;
for (int i = 0; i < nLocal; ++i) {
for (int i = 0; i < numLocal; ++i) {
inputLocals[inputLocalIndex++] = getAbstractTypeFromApiFormat(symbolTable, local[i]);
if (local[i] == Opcodes.LONG || local[i] == Opcodes.DOUBLE) {
inputLocals[inputLocalIndex++] = TOP;
@ -438,15 +438,15 @@ class Frame { @@ -438,15 +438,15 @@ class Frame {
while (inputLocalIndex < inputLocals.length) {
inputLocals[inputLocalIndex++] = TOP;
}
int nStackTop = 0;
for (int i = 0; i < nStack; ++i) {
int numStackTop = 0;
for (int i = 0; i < numStack; ++i) {
if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
++nStackTop;
++numStackTop;
}
}
inputStack = new int[nStack + nStackTop];
inputStack = new int[numStack + numStackTop];
int inputStackIndex = 0;
for (int i = 0; i < nStack; ++i) {
for (int i = 0; i < numStack; ++i) {
inputStack[inputStackIndex++] = getAbstractTypeFromApiFormat(symbolTable, stack[i]);
if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
inputStack[inputStackIndex++] = TOP;
@ -1122,13 +1122,13 @@ class Frame { @@ -1122,13 +1122,13 @@ class Frame {
// Compute the concrete types of the local variables at the end of the basic block corresponding
// to this frame, by resolving its abstract output types, and merge these concrete types with
// those of the local variables in the input frame of dstFrame.
int nLocal = inputLocals.length;
int nStack = inputStack.length;
int numLocal = inputLocals.length;
int numStack = inputStack.length;
if (dstFrame.inputLocals == null) {
dstFrame.inputLocals = new int[nLocal];
dstFrame.inputLocals = new int[numLocal];
frameChanged = true;
}
for (int i = 0; i < nLocal; ++i) {
for (int i = 0; i < numLocal; ++i) {
int concreteOutputType;
if (outputLocals != null && i < outputLocals.length) {
int abstractOutputType = outputLocals[i];
@ -1152,7 +1152,7 @@ class Frame { @@ -1152,7 +1152,7 @@ class Frame {
// By definition, a STACK_KIND type designates the concrete type of a local variable at
// the beginning of the basic block corresponding to this frame (which is known when
// this method is called, but was not when the abstract type was computed).
concreteOutputType = dim + inputStack[nStack - (abstractOutputType & VALUE_MASK)];
concreteOutputType = dim + inputStack[numStack - (abstractOutputType & VALUE_MASK)];
if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0
&& (concreteOutputType == LONG || concreteOutputType == DOUBLE)) {
concreteOutputType = TOP;
@ -1181,7 +1181,7 @@ class Frame { @@ -1181,7 +1181,7 @@ class Frame {
// frame (and the input stack of dstFrame should be compatible, i.e. merged, with a one
// element stack containing the caught exception type).
if (catchTypeIndex > 0) {
for (int i = 0; i < nLocal; ++i) {
for (int i = 0; i < numLocal; ++i) {
frameChanged |= merge(symbolTable, inputLocals[i], dstFrame.inputLocals, i);
}
if (dstFrame.inputStack == null) {
@ -1195,15 +1195,15 @@ class Frame { @@ -1195,15 +1195,15 @@ class Frame {
// Compute the concrete types of the stack operands at the end of the basic block corresponding
// to this frame, by resolving its abstract output types, and merge these concrete types with
// those of the stack operands in the input frame of dstFrame.
int nInputStack = inputStack.length + outputStackStart;
int numInputStack = inputStack.length + outputStackStart;
if (dstFrame.inputStack == null) {
dstFrame.inputStack = new int[nInputStack + outputStackTop];
dstFrame.inputStack = new int[numInputStack + outputStackTop];
frameChanged = true;
}
// First, do this for the stack operands that have not been popped in the basic block
// corresponding to this frame, and which are therefore equal to their value in the input
// frame (except for uninitialized types, which may have been initialized).
for (int i = 0; i < nInputStack; ++i) {
for (int i = 0; i < numInputStack; ++i) {
int concreteOutputType = inputStack[i];
if (initializations != null) {
concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
@ -1224,7 +1224,7 @@ class Frame { @@ -1224,7 +1224,7 @@ class Frame {
concreteOutputType = TOP;
}
} else if (kind == STACK_KIND) {
concreteOutputType = dim + inputStack[nStack - (abstractOutputType & VALUE_MASK)];
concreteOutputType = dim + inputStack[numStack - (abstractOutputType & VALUE_MASK)];
if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0
&& (concreteOutputType == LONG || concreteOutputType == DOUBLE)) {
concreteOutputType = TOP;
@ -1235,7 +1235,8 @@ class Frame { @@ -1235,7 +1235,8 @@ class Frame {
if (initializations != null) {
concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
}
frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputStack, nInputStack + i);
frameChanged |=
merge(symbolTable, concreteOutputType, dstFrame.inputStack, numInputStack + i);
}
return frameChanged;
}
@ -1348,38 +1349,38 @@ class Frame { @@ -1348,38 +1349,38 @@ class Frame {
// Compute the number of locals, ignoring TOP types that are just after a LONG or a DOUBLE, and
// all trailing TOP types.
int[] localTypes = inputLocals;
int nLocal = 0;
int nTrailingTop = 0;
int numLocal = 0;
int numTrailingTop = 0;
int i = 0;
while (i < localTypes.length) {
int localType = localTypes[i];
i += (localType == LONG || localType == DOUBLE) ? 2 : 1;
if (localType == TOP) {
nTrailingTop++;
numTrailingTop++;
} else {
nLocal += nTrailingTop + 1;
nTrailingTop = 0;
numLocal += numTrailingTop + 1;
numTrailingTop = 0;
}
}
// Compute the stack size, ignoring TOP types that are just after a LONG or a DOUBLE.
int[] stackTypes = inputStack;
int nStack = 0;
int numStack = 0;
i = 0;
while (i < stackTypes.length) {
int stackType = stackTypes[i];
i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1;
nStack++;
numStack++;
}
// Visit the frame and its content.
int frameIndex = methodWriter.visitFrameStart(owner.bytecodeOffset, nLocal, nStack);
int frameIndex = methodWriter.visitFrameStart(owner.bytecodeOffset, numLocal, numStack);
i = 0;
while (nLocal-- > 0) {
while (numLocal-- > 0) {
int localType = localTypes[i];
i += (localType == LONG || localType == DOUBLE) ? 2 : 1;
methodWriter.visitAbstractType(frameIndex++, localType);
}
i = 0;
while (nStack-- > 0) {
while (numStack-- > 0) {
int stackType = stackTypes[i];
i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1;
methodWriter.visitAbstractType(frameIndex++, stackType);

2
spring-core/src/main/java/org/springframework/asm/Label.java

@ -178,7 +178,7 @@ public class Label { @@ -178,7 +178,7 @@ public class Label {
* and {@link #FORWARD_REFERENCE_HANDLE_MASK}.
* </ul>
*
* For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is
* <p>For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is
* equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1
* (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after
* the start of the instruction itself). For the default case of a lookupswitch instruction at

24
spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java

@ -61,22 +61,38 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException { @@ -61,22 +61,38 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException {
this.codeSize = codeSize;
}
/** @return the internal name of the owner class. */
/**
* Returns the internal name of the owner class.
*
* @return the internal name of the owner class.
*/
public String getClassName() {
return className;
}
/** @return the name of the method. */
/**
* Returns the name of the method.
*
* @return the name of the method.
*/
public String getMethodName() {
return methodName;
}
/** @return the descriptor of the method. */
/**
* Returns the descriptor of the method.
*
* @return the descriptor of the method.
*/
public String getDescriptor() {
return descriptor;
}
/** @return the size of the method's Code attribute, in bytes. */
/**
* Returns the size of the method's Code attribute, in bytes.
*
* @return the size of the method's Code attribute, in bytes.
*/
public int getCodeSize() {
return codeSize;
}

18
spring-core/src/main/java/org/springframework/asm/MethodVisitor.java

@ -243,15 +243,15 @@ public abstract class MethodVisitor { @@ -243,15 +243,15 @@ public abstract class MethodVisitor {
* <li>{@link Opcodes#F_SAME} representing frame with exactly the same locals as the
* previous frame and with the empty stack.
* <li>{@link Opcodes#F_SAME1} representing frame with exactly the same locals as the
* previous frame and with single value on the stack ( <code>nStack</code> is 1 and
* previous frame and with single value on the stack ( <code>numStack</code> is 1 and
* <code>stack[0]</code> contains value for the type of the stack item).
* <li>{@link Opcodes#F_APPEND} representing frame with current locals are the same as the
* locals in the previous frame, except that additional locals are defined (<code>
* nLocal</code> is 1, 2 or 3 and <code>local</code> elements contains values
* numLocal</code> is 1, 2 or 3 and <code>local</code> elements contains values
* representing added types).
* <li>{@link Opcodes#F_CHOP} representing frame with current locals are the same as the
* locals in the previous frame, except that the last 1-3 locals are absent and with
* the empty stack (<code>nLocals</code> is 1, 2 or 3).
* the empty stack (<code>numLocal</code> is 1, 2 or 3).
* <li>{@link Opcodes#F_FULL} representing complete frame data.
* </ul>
* </ul>
@ -264,7 +264,7 @@ public abstract class MethodVisitor { @@ -264,7 +264,7 @@ 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 nLocal the number of local variables in the visited frame.
* @param numLocal the number of local variables in the visited frame.
* @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
@ -272,7 +272,7 @@ public abstract class MethodVisitor { @@ -272,7 +272,7 @@ public abstract class MethodVisitor {
* 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 nStack the number of operand stack elements in the visited frame.
* @param numStack the number of operand stack elements in the visited frame.
* @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
@ -281,12 +281,12 @@ public abstract class MethodVisitor { @@ -281,12 +281,12 @@ public abstract class MethodVisitor {
*/
public void visitFrame(
final int type,
final int nLocal,
final int numLocal,
final Object[] local,
final int nStack,
final int numStack,
final Object[] stack) {
if (mv != null) {
mv.visitFrame(type, nLocal, local, nStack, stack);
mv.visitFrame(type, numLocal, local, numStack, stack);
}
}
@ -390,7 +390,7 @@ public abstract class MethodVisitor { @@ -390,7 +390,7 @@ public abstract class MethodVisitor {
* Type#getInternalName()}).
* @param name the method's name.
* @param descriptor the method's descriptor (see {@link Type}).
* @deprecated
* @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
*/
@Deprecated
public void visitMethodInsn(

111
spring-core/src/main/java/org/springframework/asm/MethodWriter.java

@ -531,11 +531,10 @@ final class MethodWriter extends MethodVisitor { @@ -531,11 +531,10 @@ final class MethodWriter extends MethodVisitor {
* The current stack map frame. The first element contains the bytecode offset of the instruction
* to which the frame corresponds, the second element is the number of locals and the third one is
* 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] = nLocal, frame[2] = nStack,
* frame[3] = nLocal. 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.
* 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.
*/
private int[] currentFrame;
@ -745,9 +744,9 @@ final class MethodWriter extends MethodVisitor { @@ -745,9 +744,9 @@ final class MethodWriter extends MethodVisitor {
@Override
public void visitFrame(
final int type,
final int nLocal,
final int numLocal,
final Object[] local,
final int nStack,
final int numStack,
final Object[] stack) {
if (compute == COMPUTE_ALL_FRAMES) {
return;
@ -760,12 +759,12 @@ final class MethodWriter extends MethodVisitor { @@ -760,12 +759,12 @@ final class MethodWriter extends MethodVisitor {
// can't be set if EXPAND_ASM_INSNS is not used).
currentBasicBlock.frame = new CurrentFrame(currentBasicBlock);
currentBasicBlock.frame.setInputFrameFromDescriptor(
symbolTable, accessFlags, descriptor, nLocal);
symbolTable, accessFlags, descriptor, numLocal);
currentBasicBlock.frame.accept(this);
} else {
if (type == Opcodes.F_NEW) {
currentBasicBlock.frame.setInputFrameFromApiFormat(
symbolTable, nLocal, local, nStack, stack);
symbolTable, numLocal, local, numStack, stack);
} else {
// In this case type is equal to F_INSERT by hypothesis, and currentBlock.frame contains
// the stack map frame at the current instruction, computed from the last F_NEW frame
@ -781,12 +780,12 @@ final class MethodWriter extends MethodVisitor { @@ -781,12 +780,12 @@ final class MethodWriter extends MethodVisitor {
symbolTable, accessFlags, descriptor, argumentsSize);
implicitFirstFrame.accept(this);
}
currentLocals = nLocal;
int frameIndex = visitFrameStart(code.length, nLocal, nStack);
for (int i = 0; i < nLocal; ++i) {
currentLocals = numLocal;
int frameIndex = visitFrameStart(code.length, numLocal, numStack);
for (int i = 0; i < numLocal; ++i) {
currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, local[i]);
}
for (int i = 0; i < nStack; ++i) {
for (int i = 0; i < numStack; ++i) {
currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, stack[i]);
}
visitFrameEnd();
@ -808,26 +807,26 @@ final class MethodWriter extends MethodVisitor { @@ -808,26 +807,26 @@ final class MethodWriter extends MethodVisitor {
switch (type) {
case Opcodes.F_FULL:
currentLocals = nLocal;
stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(nLocal);
for (int i = 0; i < nLocal; ++i) {
currentLocals = numLocal;
stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
for (int i = 0; i < numLocal; ++i) {
putFrameType(local[i]);
}
stackMapTableEntries.putShort(nStack);
for (int i = 0; i < nStack; ++i) {
stackMapTableEntries.putShort(numStack);
for (int i = 0; i < numStack; ++i) {
putFrameType(stack[i]);
}
break;
case Opcodes.F_APPEND:
currentLocals += nLocal;
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocal).putShort(offsetDelta);
for (int i = 0; i < nLocal; ++i) {
currentLocals += numLocal;
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + numLocal).putShort(offsetDelta);
for (int i = 0; i < numLocal; ++i) {
putFrameType(local[i]);
}
break;
case Opcodes.F_CHOP:
currentLocals -= nLocal;
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - nLocal).putShort(offsetDelta);
currentLocals -= numLocal;
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - numLocal).putShort(offsetDelta);
break;
case Opcodes.F_SAME:
if (offsetDelta < 64) {
@ -855,8 +854,8 @@ final class MethodWriter extends MethodVisitor { @@ -855,8 +854,8 @@ final class MethodWriter extends MethodVisitor {
}
if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) {
relativeStackSize = nStack;
for (int i = 0; i < nStack; ++i) {
relativeStackSize = numStack;
for (int i = 0; i < numStack; ++i) {
if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
relativeStackSize++;
}
@ -866,7 +865,7 @@ final class MethodWriter extends MethodVisitor { @@ -866,7 +865,7 @@ final class MethodWriter extends MethodVisitor {
}
}
maxStack = Math.max(maxStack, nStack);
maxStack = Math.max(maxStack, numStack);
maxLocals = Math.max(maxLocals, currentLocals);
}
@ -1649,7 +1648,7 @@ final class MethodWriter extends MethodVisitor { @@ -1649,7 +1648,7 @@ final class MethodWriter extends MethodVisitor {
code.data[endOffset] = (byte) Opcodes.ATHROW;
// Emit a frame for this unreachable block, with no local and a Throwable on the stack
// (so that the ATHROW could consume this Throwable if it were reachable).
int frameIndex = visitFrameStart(startOffset, /* nLocal = */ 0, /* nStack = */ 1);
int frameIndex = visitFrameStart(startOffset, /* numLocal = */ 0, /* numStack = */ 1);
currentFrame[frameIndex] =
Frame.getAbstractTypeFromInternalName(symbolTable, "java/lang/Throwable");
visitFrameEnd();
@ -1821,18 +1820,18 @@ final class MethodWriter extends MethodVisitor { @@ -1821,18 +1820,18 @@ final class MethodWriter extends MethodVisitor {
* Starts the visit of a new stack map frame, stored in {@link #currentFrame}.
*
* @param offset the bytecode offset of the instruction to which the frame corresponds.
* @param nLocal the number of local variables in the frame.
* @param nStack the number of stack elements in the frame.
* @param numLocal the number of local variables in the frame.
* @param numStack the number of stack elements in the frame.
* @return the index of the next element to be written in this frame.
*/
int visitFrameStart(final int offset, final int nLocal, final int nStack) {
int frameLength = 3 + nLocal + nStack;
int visitFrameStart(final int offset, final int numLocal, final int numStack) {
int frameLength = 3 + numLocal + numStack;
if (currentFrame == null || currentFrame.length < frameLength) {
currentFrame = new int[frameLength];
}
currentFrame[0] = offset;
currentFrame[1] = nLocal;
currentFrame[2] = nStack;
currentFrame[1] = numLocal;
currentFrame[2] = numStack;
return 3;
}
@ -1865,25 +1864,25 @@ final class MethodWriter extends MethodVisitor { @@ -1865,25 +1864,25 @@ final class MethodWriter extends MethodVisitor {
/** Compresses and writes {@link #currentFrame} in a new StackMapTable entry. */
private void putFrame() {
final int nLocal = currentFrame[1];
final int nStack = currentFrame[2];
final int numLocal = currentFrame[1];
final int numStack = currentFrame[2];
if (symbolTable.getMajorVersion() < Opcodes.V1_6) {
// Generate a StackMap attribute entry, which are always uncompressed.
stackMapTableEntries.putShort(currentFrame[0]).putShort(nLocal);
putAbstractTypes(3, 3 + nLocal);
stackMapTableEntries.putShort(nStack);
putAbstractTypes(3 + nLocal, 3 + nLocal + nStack);
stackMapTableEntries.putShort(currentFrame[0]).putShort(numLocal);
putAbstractTypes(3, 3 + numLocal);
stackMapTableEntries.putShort(numStack);
putAbstractTypes(3 + numLocal, 3 + numLocal + numStack);
return;
}
final int offsetDelta =
stackMapTableNumberOfEntries == 0
? currentFrame[0]
: currentFrame[0] - previousFrame[0] - 1;
final int previousNlocal = previousFrame[1];
final int nLocalDelta = nLocal - previousNlocal;
final int previousNumlocal = previousFrame[1];
final int numLocalDelta = numLocal - previousNumlocal;
int type = Frame.FULL_FRAME;
if (nStack == 0) {
switch (nLocalDelta) {
if (numStack == 0) {
switch (numLocalDelta) {
case -3:
case -2:
case -1:
@ -1901,7 +1900,7 @@ final class MethodWriter extends MethodVisitor { @@ -1901,7 +1900,7 @@ final class MethodWriter extends MethodVisitor {
// Keep the FULL_FRAME type.
break;
}
} else if (nLocalDelta == 0 && nStack == 1) {
} else if (numLocalDelta == 0 && numStack == 1) {
type =
offsetDelta < 63
? Frame.SAME_LOCALS_1_STACK_ITEM_FRAME
@ -1910,7 +1909,7 @@ final class MethodWriter extends MethodVisitor { @@ -1910,7 +1909,7 @@ final class MethodWriter extends MethodVisitor {
if (type != Frame.FULL_FRAME) {
// Verify if locals are the same as in the previous frame.
int frameIndex = 3;
for (int i = 0; i < previousNlocal && i < nLocal; i++) {
for (int i = 0; i < previousNumlocal && i < numLocal; i++) {
if (currentFrame[frameIndex] != previousFrame[frameIndex]) {
type = Frame.FULL_FRAME;
break;
@ -1924,30 +1923,34 @@ final class MethodWriter extends MethodVisitor { @@ -1924,30 +1923,34 @@ final class MethodWriter extends MethodVisitor {
break;
case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME:
stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta);
putAbstractTypes(3 + nLocal, 4 + nLocal);
putAbstractTypes(3 + numLocal, 4 + numLocal);
break;
case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
stackMapTableEntries
.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
.putShort(offsetDelta);
putAbstractTypes(3 + nLocal, 4 + nLocal);
putAbstractTypes(3 + numLocal, 4 + numLocal);
break;
case Frame.SAME_FRAME_EXTENDED:
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta);
break;
case Frame.CHOP_FRAME:
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocalDelta).putShort(offsetDelta);
stackMapTableEntries
.putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta)
.putShort(offsetDelta);
break;
case Frame.APPEND_FRAME:
stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocalDelta).putShort(offsetDelta);
putAbstractTypes(3 + previousNlocal, 3 + nLocal);
stackMapTableEntries
.putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta)
.putShort(offsetDelta);
putAbstractTypes(3 + previousNumlocal, 3 + numLocal);
break;
case Frame.FULL_FRAME:
default:
stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(nLocal);
putAbstractTypes(3, 3 + nLocal);
stackMapTableEntries.putShort(nStack);
putAbstractTypes(3 + nLocal, 3 + nLocal + nStack);
stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
putAbstractTypes(3, 3 + numLocal);
stackMapTableEntries.putShort(numStack);
putAbstractTypes(3 + numLocal, 3 + numLocal + numStack);
}
}

1
spring-core/src/main/java/org/springframework/asm/Opcodes.java

@ -38,6 +38,7 @@ package org.springframework.asm; @@ -38,6 +38,7 @@ package org.springframework.asm;
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
// DontCheck(InterfaceIsType): can't be fixed (for backward binary compatibility).
public interface Opcodes {
// ASM API versions.

2
spring-core/src/main/java/org/springframework/asm/Symbol.java

@ -227,6 +227,8 @@ abstract class Symbol { @@ -227,6 +227,8 @@ abstract class Symbol {
}
/**
* Returns the result {@link Type#getArgumentsAndReturnSizes} on {@link #value}.
*
* @return the result {@link Type#getArgumentsAndReturnSizes} on {@link #value} (memoized in
* {@link #info} for efficiency). This should only be used for {@link
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link

165
spring-core/src/main/java/org/springframework/asm/SymbolTable.java

@ -39,58 +39,6 @@ package org.springframework.asm; @@ -39,58 +39,6 @@ package org.springframework.asm;
*/
final class SymbolTable {
/**
* An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields
* which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid
* duplicate symbols). See {@link #entries}.
*
* @author Eric Bruneton
*/
private static class Entry extends Symbol {
/** The hash code of this entry. */
final int hashCode;
/**
* Another entry (and so on recursively) having the same hash code (modulo the size of {@link
* #entries}) as this one.
*/
Entry next;
Entry(
final int index,
final int tag,
final String owner,
final String name,
final String value,
final long data,
final int hashCode) {
super(index, tag, owner, name, value, data);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final String value, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final String value, final long data, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, value, data);
this.hashCode = hashCode;
}
Entry(
final int index, final int tag, final String name, final String value, final int hashCode) {
super(index, tag, /* owner = */ null, name, value, /* data = */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final long data, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data);
this.hashCode = hashCode;
}
}
/**
* The ClassWriter to which this SymbolTable belongs. This is only used to get access to {@link
* ClassWriter#getCommonSuperClass} and to serialize custom attributes with {@link
@ -224,7 +172,7 @@ final class SymbolTable { @@ -224,7 +172,7 @@ final class SymbolTable {
break;
case Symbol.CONSTANT_INTEGER_TAG:
case Symbol.CONSTANT_FLOAT_TAG:
addConstantInteger(itemIndex, itemTag, classReader.readInt(itemOffset));
addConstantIntegerOrFloat(itemIndex, itemTag, classReader.readInt(itemOffset));
break;
case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
addConstantNameAndType(
@ -234,10 +182,10 @@ final class SymbolTable { @@ -234,10 +182,10 @@ final class SymbolTable {
break;
case Symbol.CONSTANT_LONG_TAG:
case Symbol.CONSTANT_DOUBLE_TAG:
addConstantLong(itemIndex, itemTag, classReader.readLong(itemOffset));
addConstantLongOrDouble(itemIndex, itemTag, classReader.readLong(itemOffset));
break;
case Symbol.CONSTANT_UTF8_TAG:
addConstantUtf8(itemIndex, classReader.readUTF(itemIndex, charBuffer));
addConstantUtf8(itemIndex, classReader.readUtf(itemIndex, charBuffer));
break;
case Symbol.CONSTANT_METHOD_HANDLE_TAG:
int memberRefItemOffset =
@ -331,6 +279,8 @@ final class SymbolTable { @@ -331,6 +279,8 @@ final class SymbolTable {
}
/**
* Returns the ClassReader from which this SymbolTable was constructed.
*
* @return the ClassReader from which this SymbolTable was constructed, or {@literal null} if it
* was constructed from scratch.
*/
@ -338,12 +288,20 @@ final class SymbolTable { @@ -338,12 +288,20 @@ final class SymbolTable {
return sourceClassReader;
}
/** @return the major version of the class to which this symbol table belongs. */
/**
* Returns the major version of the class to which this symbol table belongs.
*
* @return the major version of the class to which this symbol table belongs.
*/
int getMajorVersion() {
return majorVersion;
}
/** @return the internal name of the class to which this symbol table belongs. */
/**
* Returns the internal name of the class to which this symbol table belongs.
*
* @return the internal name of the class to which this symbol table belongs.
*/
String getClassName() {
return className;
}
@ -362,12 +320,20 @@ final class SymbolTable { @@ -362,12 +320,20 @@ final class SymbolTable {
return addConstantClass(className).index;
}
/** @return the number of items in this symbol table's constant_pool array (plus 1). */
/**
* Returns the number of items in this symbol table's constant_pool array (plus 1).
*
* @return the number of items in this symbol table's constant_pool array (plus 1).
*/
int getConstantPoolCount() {
return constantPoolCount;
}
/** @return the length in bytes of this symbol table's constant_pool array. */
/**
* Returns the length in bytes of this symbol table's constant_pool array.
*
* @return the length in bytes of this symbol table's constant_pool array.
*/
int getConstantPoolLength() {
return constantPool.length;
}
@ -418,6 +384,8 @@ final class SymbolTable { @@ -418,6 +384,8 @@ final class SymbolTable {
// -----------------------------------------------------------------------------------------------
/**
* Returns the list of entries which can potentially have the given hash code.
*
* @param hashCode a {@link Entry#hashCode} value.
* @return the list of entries which can potentially have the given hash code. The list is stored
* via the {@link Entry#next} field.
@ -644,7 +612,7 @@ final class SymbolTable { @@ -644,7 +612,7 @@ final class SymbolTable {
* @return a new or already existing Symbol with the given value.
*/
Symbol addConstantInteger(final int value) {
return addConstantInteger(Symbol.CONSTANT_INTEGER_TAG, value);
return addConstantIntegerOrFloat(Symbol.CONSTANT_INTEGER_TAG, value);
}
/**
@ -655,7 +623,7 @@ final class SymbolTable { @@ -655,7 +623,7 @@ final class SymbolTable {
* @return a new or already existing Symbol with the given value.
*/
Symbol addConstantFloat(final float value) {
return addConstantInteger(Symbol.CONSTANT_FLOAT_TAG, Float.floatToRawIntBits(value));
return addConstantIntegerOrFloat(Symbol.CONSTANT_FLOAT_TAG, Float.floatToRawIntBits(value));
}
/**
@ -666,7 +634,7 @@ final class SymbolTable { @@ -666,7 +634,7 @@ final class SymbolTable {
* @param value an int or float.
* @return a constant pool constant with the given tag and primitive values.
*/
private Symbol addConstantInteger(final int tag, final int value) {
private Symbol addConstantIntegerOrFloat(final int tag, final int value) {
int hashCode = hash(tag, value);
Entry entry = get(hashCode);
while (entry != null) {
@ -687,7 +655,7 @@ final class SymbolTable { @@ -687,7 +655,7 @@ final class SymbolTable {
* @param tag one of {@link Symbol#CONSTANT_INTEGER_TAG} or {@link Symbol#CONSTANT_FLOAT_TAG}.
* @param value an int or float.
*/
private void addConstantInteger(final int index, final int tag, final int value) {
private void addConstantIntegerOrFloat(final int index, final int tag, final int value) {
add(new Entry(index, tag, value, hash(tag, value)));
}
@ -699,7 +667,7 @@ final class SymbolTable { @@ -699,7 +667,7 @@ final class SymbolTable {
* @return a new or already existing Symbol with the given value.
*/
Symbol addConstantLong(final long value) {
return addConstantLong(Symbol.CONSTANT_LONG_TAG, value);
return addConstantLongOrDouble(Symbol.CONSTANT_LONG_TAG, value);
}
/**
@ -710,7 +678,7 @@ final class SymbolTable { @@ -710,7 +678,7 @@ final class SymbolTable {
* @return a new or already existing Symbol with the given value.
*/
Symbol addConstantDouble(final double value) {
return addConstantLong(Symbol.CONSTANT_DOUBLE_TAG, Double.doubleToRawLongBits(value));
return addConstantLongOrDouble(Symbol.CONSTANT_DOUBLE_TAG, Double.doubleToRawLongBits(value));
}
/**
@ -721,7 +689,7 @@ final class SymbolTable { @@ -721,7 +689,7 @@ final class SymbolTable {
* @param value a long or double.
* @return a constant pool constant with the given tag and primitive values.
*/
private Symbol addConstantLong(final int tag, final long value) {
private Symbol addConstantLongOrDouble(final int tag, final long value) {
int hashCode = hash(tag, value);
Entry entry = get(hashCode);
while (entry != null) {
@ -737,13 +705,14 @@ final class SymbolTable { @@ -737,13 +705,14 @@ final class SymbolTable {
}
/**
* Adds a new CONSTANT_Double_info to the constant pool of this symbol table.
* Adds a new CONSTANT_Long_info or CONSTANT_Double_info to the constant pool of this symbol
* table.
*
* @param index the constant pool index of the new Symbol.
* @param tag one of {@link Symbol#CONSTANT_LONG_TAG} or {@link Symbol#CONSTANT_DOUBLE_TAG}.
* @param value a long or double.
*/
private void addConstantLong(final int index, final int tag, final long value) {
private void addConstantLongOrDouble(final int index, final int tag, final long value) {
add(new Entry(index, tag, value, hash(tag, value)));
}
@ -1149,6 +1118,8 @@ final class SymbolTable { @@ -1149,6 +1118,8 @@ final class SymbolTable {
// -----------------------------------------------------------------------------------------------
/**
* Returns the type table element whose index is given.
*
* @param typeIndex a type table index.
* @return the type table element whose index is given.
*/
@ -1172,7 +1143,7 @@ final class SymbolTable { @@ -1172,7 +1143,7 @@ final class SymbolTable {
}
entry = entry.next;
}
return addType(new Entry(typeCount, Symbol.TYPE_TAG, value, hashCode));
return addTypeInternal(new Entry(typeCount, Symbol.TYPE_TAG, value, hashCode));
}
/**
@ -1196,7 +1167,7 @@ final class SymbolTable { @@ -1196,7 +1167,7 @@ final class SymbolTable {
}
entry = entry.next;
}
return addType(
return addTypeInternal(
new Entry(typeCount, Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset, hashCode));
}
@ -1237,7 +1208,7 @@ final class SymbolTable { @@ -1237,7 +1208,7 @@ final class SymbolTable {
* @return the index in {@link #typeTable} where the given type was added, which is also equal to
* entry's index by hypothesis.
*/
private int addType(final Entry entry) {
private int addTypeInternal(final Entry entry) {
if (typeTable == null) {
typeTable = new Entry[16];
}
@ -1292,4 +1263,56 @@ final class SymbolTable { @@ -1292,4 +1263,56 @@ final class SymbolTable {
final int value4) {
return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode() * value3.hashCode() * value4);
}
/**
* An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields
* which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid
* duplicate symbols). See {@link #entries}.
*
* @author Eric Bruneton
*/
private static class Entry extends Symbol {
/** The hash code of this entry. */
final int hashCode;
/**
* Another entry (and so on recursively) having the same hash code (modulo the size of {@link
* #entries}) as this one.
*/
Entry next;
Entry(
final int index,
final int tag,
final String owner,
final String name,
final String value,
final long data,
final int hashCode) {
super(index, tag, owner, name, value, data);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final String value, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final String value, final long data, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, value, data);
this.hashCode = hashCode;
}
Entry(
final int index, final int tag, final String name, final String value, final int hashCode) {
super(index, tag, /* owner = */ null, name, value, /* data = */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final long data, final int hashCode) {
super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data);
this.hashCode = hashCode;
}
}
}

411
spring-core/src/main/java/org/springframework/asm/Type.java

@ -146,10 +146,6 @@ public class Type { @@ -146,10 +146,6 @@ public class Type {
*/
private final int valueEnd;
// -----------------------------------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------------------------------
/**
* Constructs a reference type.
*
@ -167,6 +163,10 @@ public class Type { @@ -167,6 +163,10 @@ public class Type {
this.valueEnd = valueEnd;
}
// -----------------------------------------------------------------------------------------------
// Methods to get Type(s) from a descriptor, a reflected Method or Constructor, other types, etc.
// -----------------------------------------------------------------------------------------------
/**
* Returns the {@link Type} corresponding to the given type descriptor.
*
@ -174,40 +174,7 @@ public class Type { @@ -174,40 +174,7 @@ public class Type {
* @return the {@link Type} corresponding to the given type descriptor.
*/
public static Type getType(final String typeDescriptor) {
return getType(typeDescriptor, 0, typeDescriptor.length());
}
/**
* Returns the {@link Type} corresponding to the given internal name.
*
* @param internalName an internal name.
* @return the {@link Type} corresponding to the given internal name.
*/
public static Type getObjectType(final String internalName) {
return new Type(
internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length());
}
/**
* Returns the {@link Type} corresponding to the given method descriptor. Equivalent to <code>
* Type.getType(methodDescriptor)</code>.
*
* @param methodDescriptor a method descriptor.
* @return the {@link Type} corresponding to the given method descriptor.
*/
public static Type getMethodType(final String methodDescriptor) {
return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length());
}
/**
* Returns the method {@link Type} corresponding to the given argument and return types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the method {@link Type} corresponding to the given argument and return types.
*/
public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
return getType(getMethodDescriptor(returnType, argumentTypes));
return getTypeInternal(typeDescriptor, 0, typeDescriptor.length());
}
/**
@ -264,6 +231,60 @@ public class Type { @@ -264,6 +231,60 @@ public class Type {
return getType(getMethodDescriptor(method));
}
/**
* Returns the type of the elements of this array type. This method should only be used for an
* array type.
*
* @return Returns the type of the elements of this array type.
*/
public Type getElementType() {
final int numDimensions = getDimensions();
return getTypeInternal(valueBuffer, valueBegin + numDimensions, valueEnd);
}
/**
* Returns the {@link Type} corresponding to the given internal name.
*
* @param internalName an internal name.
* @return the {@link Type} corresponding to the given internal name.
*/
public static Type getObjectType(final String internalName) {
return new Type(
internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length());
}
/**
* Returns the {@link Type} corresponding to the given method descriptor. Equivalent to <code>
* Type.getType(methodDescriptor)</code>.
*
* @param methodDescriptor a method descriptor.
* @return the {@link Type} corresponding to the given method descriptor.
*/
public static Type getMethodType(final String methodDescriptor) {
return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length());
}
/**
* Returns the method {@link Type} corresponding to the given argument and return types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the method {@link Type} corresponding to the given argument and return types.
*/
public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
return getType(getMethodDescriptor(returnType, argumentTypes));
}
/**
* Returns the argument types of methods of this type. This method should only be used for method
* types.
*
* @return the argument types of methods of this type.
*/
public Type[] getArgumentTypes() {
return getArgumentTypes(getDescriptor());
}
/**
* Returns the {@link Type} values corresponding to the argument types of the given method
* descriptor.
@ -307,7 +328,7 @@ public class Type { @@ -307,7 +328,7 @@ public class Type {
}
}
argumentTypes[currentArgumentTypeIndex++] =
getType(methodDescriptor, currentArgumentTypeOffset, currentOffset);
getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset);
}
return argumentTypes;
}
@ -327,6 +348,16 @@ public class Type { @@ -327,6 +348,16 @@ public class Type {
return types;
}
/**
* Returns the return type of methods of this type. This method should only be used for method
* types.
*
* @return the return type of methods of this type.
*/
public Type getReturnType() {
return getReturnType(getDescriptor());
}
/**
* Returns the {@link Type} corresponding to the return type of the given method descriptor.
*
@ -347,7 +378,7 @@ public class Type { @@ -347,7 +378,7 @@ public class Type {
}
}
}
return getType(methodDescriptor, currentOffset + 1, methodDescriptor.length());
return getTypeInternal(methodDescriptor, currentOffset + 1, methodDescriptor.length());
}
/**
@ -360,47 +391,6 @@ public class Type { @@ -360,47 +391,6 @@ public class Type {
return getType(method.getReturnType());
}
/**
* Computes the size of the arguments and of the return value of a method.
*
* @param methodDescriptor a method descriptor.
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
*/
public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
int argumentsSize = 1;
// Skip the first character, which is always a '('.
int currentOffset = 1;
int currentChar = methodDescriptor.charAt(currentOffset);
// Parse the argument types and compute their size, one at a each loop iteration.
while (currentChar != ')') {
if (currentChar == 'J' || currentChar == 'D') {
currentOffset++;
argumentsSize += 2;
} else {
while (methodDescriptor.charAt(currentOffset) == '[') {
currentOffset++;
}
if (methodDescriptor.charAt(currentOffset++) == 'L') {
while (methodDescriptor.charAt(currentOffset++) != ';') {
// Skip the argument descriptor content.
}
}
argumentsSize += 1;
}
currentChar = methodDescriptor.charAt(currentOffset);
}
currentChar = methodDescriptor.charAt(currentOffset + 1);
if (currentChar == 'V') {
return argumentsSize << 2;
} else {
int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1;
return argumentsSize << 2 | returnSize;
}
}
/**
* Returns the {@link Type} corresponding to the given field or method descriptor.
*
@ -411,7 +401,7 @@ public class Type { @@ -411,7 +401,7 @@ public class Type {
* descriptorBuffer.
* @return the {@link Type} corresponding to the given type descriptor.
*/
private static Type getType(
private static Type getTypeInternal(
final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) {
switch (descriptorBuffer.charAt(descriptorBegin)) {
case 'V':
@ -444,45 +434,9 @@ public class Type { @@ -444,45 +434,9 @@ public class Type {
}
// -----------------------------------------------------------------------------------------------
// Accessors
// Methods to get class names, internal names or descriptors.
// -----------------------------------------------------------------------------------------------
/**
* Returns the sort of this type.
*
* @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link
* #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or
* {@link #METHOD}.
*/
public int getSort() {
return sort == INTERNAL ? OBJECT : sort;
}
/**
* Returns the number of dimensions of this array type. This method should only be used for an
* array type.
*
* @return the number of dimensions of this array type.
*/
public int getDimensions() {
int numDimensions = 1;
while (valueBuffer.charAt(valueBegin + numDimensions) == '[') {
numDimensions++;
}
return numDimensions;
}
/**
* Returns the type of the elements of this array type. This method should only be used for an
* array type.
*
* @return Returns the type of the elements of this array type.
*/
public Type getElementType() {
final int numDimensions = getDimensions();
return getType(valueBuffer, valueBegin + numDimensions, valueEnd);
}
/**
* Returns the binary name of the class corresponding to this type. This method must not be used
* on method types.
@ -535,42 +489,16 @@ public class Type { @@ -535,42 +489,16 @@ public class Type {
}
/**
* Returns the argument types of methods of this type. This method should only be used for method
* types.
*
* @return the argument types of methods of this type.
*/
public Type[] getArgumentTypes() {
return getArgumentTypes(getDescriptor());
}
/**
* Returns the return type of methods of this type. This method should only be used for method
* types.
*
* @return the return type of methods of this type.
*/
public Type getReturnType() {
return getReturnType(getDescriptor());
}
/**
* 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.
* Returns the internal name of the given class. The internal name of a class is its fully
* qualified name, as returned by Class.getName(), where '.' are replaced by '/'.
*
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
* @param clazz an object or array class.
* @return the internal name of the given class.
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
public static String getInternalName(final Class<?> clazz) {
return clazz.getName().replace('.', '/');
}
// -----------------------------------------------------------------------------------------------
// Conversion to type descriptors
// -----------------------------------------------------------------------------------------------
/**
* Returns the descriptor corresponding to this type.
*
@ -590,57 +518,6 @@ public class Type { @@ -590,57 +518,6 @@ public class Type {
}
}
/**
* Returns the descriptor corresponding to the given argument and return types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the descriptor corresponding to the given argument and return types.
*/
public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].appendDescriptor(stringBuilder);
}
stringBuilder.append(')');
returnType.appendDescriptor(stringBuilder);
return stringBuilder.toString();
}
/**
* Appends the descriptor corresponding to this type to the given string buffer.
*
* @param stringBuilder the string builder to which the descriptor must be appended.
*/
private void appendDescriptor(final StringBuilder stringBuilder) {
if (sort == OBJECT) {
stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1);
} else if (sort == INTERNAL) {
stringBuilder.append('L');
stringBuilder.append(valueBuffer, valueBegin, valueEnd);
stringBuilder.append(';');
} else {
stringBuilder.append(valueBuffer, valueBegin, valueEnd);
}
}
// -----------------------------------------------------------------------------------------------
// Direct conversion from classes to type descriptors,
// without intermediate Type objects
// -----------------------------------------------------------------------------------------------
/**
* Returns the internal name of the given class. The internal name of a class is its fully
* qualified name, as returned by Class.getName(), where '.' are replaced by '/'.
*
* @param clazz an object or array class.
* @return the internal name of the given class.
*/
public static String getInternalName(final Class<?> clazz) {
return clazz.getName().replace('.', '/');
}
/**
* Returns the descriptor corresponding to the given class.
*
@ -649,7 +526,7 @@ public class Type { @@ -649,7 +526,7 @@ public class Type {
*/
public static String getDescriptor(final Class<?> clazz) {
StringBuilder stringBuilder = new StringBuilder();
appendDescriptor(stringBuilder, clazz);
appendDescriptor(clazz, stringBuilder);
return stringBuilder.toString();
}
@ -664,11 +541,29 @@ public class Type { @@ -664,11 +541,29 @@ public class Type {
stringBuilder.append('(');
Class<?>[] parameters = constructor.getParameterTypes();
for (int i = 0; i < parameters.length; ++i) {
appendDescriptor(stringBuilder, parameters[i]);
appendDescriptor(parameters[i], stringBuilder);
}
return stringBuilder.append(")V").toString();
}
/**
* Returns the descriptor corresponding to the given argument and return types.
*
* @param returnType the return type of the method.
* @param argumentTypes the argument types of the method.
* @return the descriptor corresponding to the given argument and return types.
*/
public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].appendDescriptor(stringBuilder);
}
stringBuilder.append(')');
returnType.appendDescriptor(stringBuilder);
return stringBuilder.toString();
}
/**
* Returns the descriptor corresponding to the given method.
*
@ -680,20 +575,37 @@ public class Type { @@ -680,20 +575,37 @@ public class Type {
stringBuilder.append('(');
Class<?>[] parameters = method.getParameterTypes();
for (int i = 0; i < parameters.length; ++i) {
appendDescriptor(stringBuilder, parameters[i]);
appendDescriptor(parameters[i], stringBuilder);
}
stringBuilder.append(')');
appendDescriptor(stringBuilder, method.getReturnType());
appendDescriptor(method.getReturnType(), stringBuilder);
return stringBuilder.toString();
}
/**
* Appends the descriptor of the given class to the given string builder.
* Appends the descriptor corresponding to this type to the given string buffer.
*
* @param stringBuilder the string builder to which the descriptor must be appended.
*/
private void appendDescriptor(final StringBuilder stringBuilder) {
if (sort == OBJECT) {
stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1);
} else if (sort == INTERNAL) {
stringBuilder.append('L');
stringBuilder.append(valueBuffer, valueBegin, valueEnd);
stringBuilder.append(';');
} else {
stringBuilder.append(valueBuffer, valueBegin, valueEnd);
}
}
/**
* Appends the descriptor of the given class to the given string builder.
*
* @param clazz the class whose descriptor must be computed.
* @param stringBuilder the string builder to which the descriptor must be appended.
*/
private static void appendDescriptor(final StringBuilder stringBuilder, final Class<?> clazz) {
private static void appendDescriptor(final Class<?> clazz, final StringBuilder stringBuilder) {
Class<?> currentClass = clazz;
while (currentClass.isArray()) {
stringBuilder.append('[');
@ -736,9 +648,34 @@ public class Type { @@ -736,9 +648,34 @@ public class Type {
}
// -----------------------------------------------------------------------------------------------
// Corresponding size and opcodes
// Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor.
// -----------------------------------------------------------------------------------------------
/**
* Returns the sort of this type.
*
* @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link
* #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or
* {@link #METHOD}.
*/
public int getSort() {
return sort == INTERNAL ? OBJECT : sort;
}
/**
* Returns the number of dimensions of this array type. This method should only be used for an
* array type.
*
* @return the number of dimensions of this array type.
*/
public int getDimensions() {
int numDimensions = 1;
while (valueBuffer.charAt(valueBegin + numDimensions) == '[') {
numDimensions++;
}
return numDimensions;
}
/**
* Returns the size of values of this type. This method must not be used for method types.
*
@ -767,6 +704,60 @@ public class Type { @@ -767,6 +704,60 @@ public class Type {
}
}
/**
* 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.
*
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
}
/**
* Computes the size of the arguments and of the return value of a method.
*
* @param methodDescriptor a method descriptor.
* @return the size of the arguments of the method (plus one for the implicit this argument),
* argumentsSize, and the size of its return value, returnSize, packed into a single int i =
* {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
* i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
*/
public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
int argumentsSize = 1;
// Skip the first character, which is always a '('.
int currentOffset = 1;
int currentChar = methodDescriptor.charAt(currentOffset);
// Parse the argument types and compute their size, one at a each loop iteration.
while (currentChar != ')') {
if (currentChar == 'J' || currentChar == 'D') {
currentOffset++;
argumentsSize += 2;
} else {
while (methodDescriptor.charAt(currentOffset) == '[') {
currentOffset++;
}
if (methodDescriptor.charAt(currentOffset++) == 'L') {
while (methodDescriptor.charAt(currentOffset++) != ';') {
// Skip the argument descriptor content.
}
}
argumentsSize += 1;
}
currentChar = methodDescriptor.charAt(currentOffset);
}
currentChar = methodDescriptor.charAt(currentOffset + 1);
if (currentChar == 'V') {
return argumentsSize << 2;
} else {
int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1;
return argumentsSize << 2 | returnSize;
}
}
/**
* Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for
* method types.
@ -841,7 +832,7 @@ public class Type { @@ -841,7 +832,7 @@ public class Type {
}
// -----------------------------------------------------------------------------------------------
// Equals, hashCode and toString
// Equals, hashCode and toString.
// -----------------------------------------------------------------------------------------------
/**

Loading…
Cancel
Save