Skip to content

Commit 185c2bf

Browse files
committed
Upgrade to ASM 6.0
Issue: SPR-14514
1 parent ac9cfef commit 185c2bf

14 files changed

+847
-105
lines changed

spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
4141

4242
/**
4343
* The ASM API version implemented by this visitor. The value of this field
44-
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
44+
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
4545
*/
4646
protected final int api;
4747

@@ -56,7 +56,7 @@ public abstract class AnnotationVisitor {
5656
*
5757
* @param api
5858
* the ASM API version implemented by this visitor. Must be one
59-
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
59+
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
6060
*/
6161
public AnnotationVisitor(final int api) {
6262
this(api, null);
@@ -67,13 +67,13 @@ public AnnotationVisitor(final int api) {
6767
*
6868
* @param api
6969
* the ASM API version implemented by this visitor. Must be one
70-
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
70+
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
7171
* @param av
7272
* the annotation visitor to which this visitor must delegate
7373
* method calls. May be null.
7474
*/
7575
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
76-
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
76+
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
7777
throw new IllegalArgumentException();
7878
}
7979
this.api = api;

spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ final class AnnotationWriter extends AnnotationVisitor {
104104
*/
105105
AnnotationWriter(final ClassWriter cw, final boolean named,
106106
final ByteVector bv, final ByteVector parent, final int offset) {
107-
super(Opcodes.ASM5);
107+
super(Opcodes.ASM6);
108108
this.cw = cw;
109109
this.named = named;
110110
this.bv = bv;

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

Lines changed: 214 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ public ClassReader(final byte[] b, final int off, final int len) {
222222
// case ClassWriter.CLASS:
223223
// case ClassWriter.STR:
224224
// case ClassWriter.MTYPE
225+
// case ClassWriter.PACKAGE:
226+
// case ClassWriter.MODULE:
225227
default:
226228
size = 3;
227229
break;
@@ -365,7 +367,9 @@ void copyPool(final ClassWriter classWriter) {
365367
break;
366368
// case ClassWriter.STR:
367369
// case ClassWriter.CLASS:
368-
// case ClassWriter.MTYPE
370+
// case ClassWriter.MTYPE:
371+
// case ClassWriter.MODULE:
372+
// case ClassWriter.PACKAGE:
369373
default:
370374
item.set(tag, readUTF8(index, buf), null, null);
371375
break;
@@ -572,11 +576,14 @@ public void accept(final ClassVisitor classVisitor,
572576
String enclosingOwner = null;
573577
String enclosingName = null;
574578
String enclosingDesc = null;
579+
String moduleMainClass = null;
575580
int anns = 0;
576581
int ianns = 0;
577582
int tanns = 0;
578583
int itanns = 0;
579584
int innerClasses = 0;
585+
int module = 0;
586+
int packages = 0;
580587
Attribute attributes = null;
581588

582589
u = getAttributes();
@@ -617,6 +624,12 @@ public void accept(final ClassVisitor classVisitor,
617624
} else if (ANNOTATIONS
618625
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
619626
itanns = u + 8;
627+
} else if ("Module".equals(attrName)) {
628+
module = u + 8;
629+
} else if ("ModuleMainClass".equals(attrName)) {
630+
moduleMainClass = readClass(u + 8, c);
631+
} else if ("ModulePackages".equals(attrName)) {
632+
packages = u + 10;
620633
} else if ("BootstrapMethods".equals(attrName)) {
621634
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
622635
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
@@ -645,6 +658,12 @@ public void accept(final ClassVisitor classVisitor,
645658
classVisitor.visitSource(sourceFile, sourceDebug);
646659
}
647660

661+
// visits the module info and associated attributes
662+
if (module != 0) {
663+
readModule(classVisitor, context, module,
664+
moduleMainClass, packages);
665+
}
666+
648667
// visits the outer class
649668
if (enclosingOwner != null) {
650669
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
@@ -714,6 +733,120 @@ public void accept(final ClassVisitor classVisitor,
714733
classVisitor.visitEnd();
715734
}
716735

736+
/**
737+
* Reads the module attribute and visit it.
738+
*
739+
* @param classVisitor
740+
* the current class visitor
741+
* @param context
742+
* information about the class being parsed.
743+
* @param u
744+
* start offset of the module attribute in the class file.
745+
* @param mainClass
746+
* name of the main class of a module or null.
747+
* @param packages
748+
* start offset of the concealed package attribute.
749+
*/
750+
private void readModule(final ClassVisitor classVisitor,
751+
final Context context, int u,
752+
final String mainClass, int packages) {
753+
754+
char[] buffer = context.buffer;
755+
756+
// reads module name, flags and version
757+
String name = readModule(u, buffer);
758+
int flags = readUnsignedShort(u + 2);
759+
String version = readUTF8(u + 4, buffer);
760+
u += 6;
761+
762+
ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
763+
if (mv == null) {
764+
return;
765+
}
766+
767+
// module attributes (main class, packages)
768+
if (mainClass != null) {
769+
mv.visitMainClass(mainClass);
770+
}
771+
772+
if (packages != 0) {
773+
for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
774+
String packaze = readPackage(packages, buffer);
775+
mv.visitPackage(packaze);
776+
packages += 2;
777+
}
778+
}
779+
780+
// reads requires
781+
u += 2;
782+
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
783+
String module = readModule(u, buffer);
784+
int access = readUnsignedShort(u + 2);
785+
String requireVersion = readUTF8(u + 4, buffer);
786+
mv.visitRequire(module, access, requireVersion);
787+
u += 6;
788+
}
789+
790+
// reads exports
791+
u += 2;
792+
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
793+
String export = readPackage(u, buffer);
794+
int access = readUnsignedShort(u + 2);
795+
int exportToCount = readUnsignedShort(u + 4);
796+
u += 6;
797+
String[] tos = null;
798+
if (exportToCount != 0) {
799+
tos = new String[exportToCount];
800+
for (int j = 0; j < tos.length; ++j) {
801+
tos[j] = readModule(u, buffer);
802+
u += 2;
803+
}
804+
}
805+
mv.visitExport(export, access, tos);
806+
}
807+
808+
// reads opens
809+
u += 2;
810+
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
811+
String open = readPackage(u, buffer);
812+
int access = readUnsignedShort(u + 2);
813+
int openToCount = readUnsignedShort(u + 4);
814+
u += 6;
815+
String[] tos = null;
816+
if (openToCount != 0) {
817+
tos = new String[openToCount];
818+
for (int j = 0; j < tos.length; ++j) {
819+
tos[j] = readModule(u, buffer);
820+
u += 2;
821+
}
822+
}
823+
mv.visitOpen(open, access, tos);
824+
}
825+
826+
// read uses
827+
u += 2;
828+
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
829+
mv.visitUse(readClass(u, buffer));
830+
u += 2;
831+
}
832+
833+
// read provides
834+
u += 2;
835+
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
836+
String service = readClass(u, buffer);
837+
int provideWithCount = readUnsignedShort(u + 2);
838+
u += 4;
839+
String[] withs = new String[provideWithCount];
840+
for (int j = 0; j < withs.length; ++j) {
841+
withs[j] = readClass(u, buffer);
842+
u += 2;
843+
}
844+
mv.visitProvide(service, withs);
845+
}
846+
847+
mv.visitEnd();
848+
}
849+
717850
/**
718851
* Reads a field and makes the given visitor visit it.
719852
*
@@ -1082,6 +1215,7 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
10821215
u += 3;
10831216
break;
10841217
case ClassWriter.LABELW_INSN:
1218+
case ClassWriter.ASM_LABELW_INSN:
10851219
readLabel(offset + readInt(u + 1), labels);
10861220
u += 5;
10871221
break;
@@ -1305,7 +1439,8 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
13051439
}
13061440
}
13071441
}
1308-
if ((context.flags & EXPAND_ASM_INSNS) != 0) {
1442+
if ((context.flags & EXPAND_ASM_INSNS) != 0
1443+
&& (context.flags & EXPAND_FRAMES) != 0) {
13091444
// Expanding the ASM pseudo instructions can introduce F_INSERT
13101445
// frames, even if the method does not currently have any frame.
13111446
// Also these inserted frames must be computed by simulating the
@@ -1322,6 +1457,7 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
13221457

13231458
// visits the instructions
13241459
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
1460+
boolean insertFrame = false;
13251461
u = codeStart;
13261462
while (u < codeEnd) {
13271463
int offset = u - codeStart;
@@ -1354,6 +1490,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
13541490
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
13551491
frame.stackCount, frame.stack);
13561492
}
1493+
// if there is already a frame for this offset, there is no
1494+
// need to insert a new one.
1495+
insertFrame = false;
13571496
}
13581497
if (frameCount > 0) {
13591498
stackMap = readFrame(stackMap, zip, unzip, frame);
@@ -1362,6 +1501,13 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
13621501
frame = null;
13631502
}
13641503
}
1504+
// inserts a frame for this offset, if requested by setting
1505+
// insertFrame to true during the previous iteration. The actual
1506+
// frame content will be computed in MethodWriter.
1507+
if (FRAMES && insertFrame) {
1508+
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
1509+
insertFrame = false;
1510+
}
13651511

13661512
// visits the instruction at this offset
13671513
int opcode = b[u] & 0xFF;
@@ -1397,31 +1543,36 @@ private void readCode(final MethodVisitor mv, final Context context, int u) {
13971543
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
13981544
Label target = labels[offset + readUnsignedShort(u + 1)];
13991545
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
1400-
// <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
1546+
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
14011547
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
1402-
// and where <l'> designates the instruction just after
1548+
// and where <L> designates the instruction just after
14031549
// the GOTO_W.
14041550
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
14051551
mv.visitJumpInsn(opcode + 33, target);
14061552
} else {
14071553
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
14081554
: opcode ^ 1;
1409-
Label endif = new Label();
1555+
Label endif = readLabel(offset + 3, labels);
14101556
mv.visitJumpInsn(opcode, endif);
14111557
mv.visitJumpInsn(200, target); // GOTO_W
1412-
mv.visitLabel(endif);
1413-
// since we introduced an unconditional jump instruction we
1414-
// also need to insert a stack map frame here, unless there
1415-
// is already one. The actual frame content will be computed
1416-
// in MethodWriter.
1417-
if (FRAMES && stackMap != 0
1418-
&& (frame == null || frame.offset != offset + 3)) {
1419-
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
1420-
}
1558+
// endif designates the instruction just after GOTO_W,
1559+
// and is visited as part of the next instruction. Since
1560+
// it is a jump target, we need to insert a frame here.
1561+
insertFrame = true;
14211562
}
14221563
u += 3;
14231564
break;
14241565
}
1566+
case ClassWriter.ASM_LABELW_INSN: {
1567+
// replaces the pseudo GOTO_W instruction with a real one.
1568+
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
1569+
// The instruction just after is a jump target (because pseudo
1570+
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
1571+
// see MethodWriter), so we need to insert a frame here.
1572+
insertFrame = true;
1573+
u += 5;
1574+
break;
1575+
}
14251576
case ClassWriter.WIDE_INSN:
14261577
opcode = b[u + 1] & 0xFF;
14271578
if (opcode == Opcodes.IINC) {
@@ -2516,6 +2667,20 @@ private String readUTF(int index, final int utfLen, final char[] buf) {
25162667
return new String(buf, 0, strLen);
25172668
}
25182669

2670+
/**
2671+
* Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
2672+
* CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
2673+
* @param index
2674+
* @param buf
2675+
* @return
2676+
*/
2677+
private String readStringish(final int index, final char[] buf) {
2678+
// computes the start index of the item in b
2679+
// and reads the CONSTANT_Utf8 item designated by
2680+
// the first two bytes of this item
2681+
return readUTF8(items[readUnsignedShort(index)], buf);
2682+
}
2683+
25192684
/**
25202685
* Reads a class constant pool item in {@link #b b}. <i>This method is
25212686
* intended for {@link Attribute} sub classes, and is normally not needed by
@@ -2530,11 +2695,41 @@ private String readUTF(int index, final int utfLen, final char[] buf) {
25302695
* @return the String corresponding to the specified class item.
25312696
*/
25322697
public String readClass(final int index, final char[] buf) {
2533-
// computes the start index of the CONSTANT_Class item in b
2534-
// and reads the CONSTANT_Utf8 item designated by
2535-
// the first two bytes of this CONSTANT_Class item
2536-
String name = readUTF8(items[readUnsignedShort(index)], buf);
2537-
return (name != null ? name.intern() : null);
2698+
return readStringish(index, buf);
2699+
}
2700+
2701+
/**
2702+
* Reads a module constant pool item in {@link #b b}. <i>This method is
2703+
* intended for {@link Attribute} sub classes, and is normally not needed by
2704+
* class generators or adapters.</i>
2705+
*
2706+
* @param index
2707+
* the start index of an unsigned short value in {@link #b b},
2708+
* whose value is the index of a module constant pool item.
2709+
* @param buf
2710+
* buffer to be used to read the item. This buffer must be
2711+
* sufficiently large. It is not automatically resized.
2712+
* @return the String corresponding to the specified module item.
2713+
*/
2714+
public String readModule(final int index, final char[] buf) {
2715+
return readStringish(index, buf);
2716+
}
2717+
2718+
/**
2719+
* Reads a module constant pool item in {@link #b b}. <i>This method is
2720+
* intended for {@link Attribute} sub classes, and is normally not needed by
2721+
* class generators or adapters.</i>
2722+
*
2723+
* @param index
2724+
* the start index of an unsigned short value in {@link #b b},
2725+
* whose value is the index of a module constant pool item.
2726+
* @param buf
2727+
* buffer to be used to read the item. This buffer must be
2728+
* sufficiently large. It is not automatically resized.
2729+
* @return the String corresponding to the specified module item.
2730+
*/
2731+
public String readPackage(final int index, final char[] buf) {
2732+
return readStringish(index, buf);
25382733
}
25392734

25402735
/**

0 commit comments

Comments
 (0)