From 2de38a9c0eb325b67bbad20aebc36c942ecf2ee2 Mon Sep 17 00:00:00 2001 From: Sylwester Lachiewicz Date: Mon, 27 Mar 2023 21:33:56 +0200 Subject: [PATCH] SM 9.5 Signed-off-by: Sylwester Lachiewicz --- .../org/eclipse/sisu/space/asm/ClassReader.java | 17 ++++++++++++++++- .../java/org/eclipse/sisu/space/asm/Frame.java | 5 +++-- .../java/org/eclipse/sisu/space/asm/Label.java | 14 +++++++++----- .../eclipse/sisu/space/asm/MethodVisitor.java | 2 +- .../org/eclipse/sisu/space/asm/Opcodes.java | 1 + .../sisu/space/asm/RecordComponentWriter.java | 2 +- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/ClassReader.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/ClassReader.java index 36546f64..69986a9b 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/ClassReader.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/ClassReader.java @@ -194,7 +194,7 @@ public ClassReader( this.b = classFileBuffer; // Check the class' major_version. This field is after the magic and minor_version fields, which // use 4 and 2 bytes respectively. - if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V20) { + if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V21) { throw new IllegalArgumentException( "Unsupported class file major version " + readShort(classFileOffset + 6)); } @@ -2050,6 +2050,7 @@ private void readCode( 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]; @@ -2665,6 +2666,20 @@ private void readCode( 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. diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Frame.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Frame.java index 4ef9023e..fb97309d 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Frame.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Frame.java @@ -367,11 +367,12 @@ private static int getAbstractTypeFromDescriptor( 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)); } } diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Label.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Label.java index 92b0d975..28b175b7 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Label.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Label.java @@ -81,6 +81,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,9 +148,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; @@ -332,7 +335,8 @@ final Label getCanonicalInstance() { * @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) { @@ -356,7 +360,7 @@ final void addLineNumber(final int lineNumber) { */ 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) { diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/MethodVisitor.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/MethodVisitor.java index dfa8a594..d9a3513e 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/MethodVisitor.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/MethodVisitor.java @@ -30,7 +30,7 @@ /** * 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 visitXInsn} | {@code visitLabel} | {@code visitInsnAnnotation} | {@code * visitTryCatchBlock} | {@code visitTryCatchAnnotation} | {@code visitLocalVariable} | {@code diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Opcodes.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Opcodes.java index 590475b6..824009b1 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Opcodes.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/Opcodes.java @@ -286,6 +286,7 @@ public interface Opcodes { int V18 = 0 << 16 | 62; int V19 = 0 << 16 | 63; int V20 = 0 << 16 | 64; + int V21 = 0 << 16 | 65; /** * Version flag indicating that the class is using 'preview' features. diff --git a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/RecordComponentWriter.java b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/RecordComponentWriter.java index 1c4361c4..16d0cc33 100644 --- a/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/RecordComponentWriter.java +++ b/org.eclipse.sisu.inject/src/main/java/org/eclipse/sisu/space/asm/RecordComponentWriter.java @@ -37,7 +37,7 @@ final class RecordComponentWriter extends RecordComponentVisitor { /** The name_index field of the Record attribute. */ private final int nameIndex; - /** The descriptor_index field of the the Record attribute. */ + /** The descriptor_index field of the Record attribute. */ private final int descriptorIndex; /**