Skip to content

Commit 9280ca7

Browse files
committed
Upgraded to ASM 5.0.1
Issue: SPR-11239
1 parent 1c1e114 commit 9280ca7

File tree

2 files changed

+73
-54
lines changed

2 files changed

+73
-54
lines changed

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,29 @@ public final void visitInnerClass(final String name,
756756
if (innerClasses == null) {
757757
innerClasses = new ByteVector();
758758
}
759-
++innerClassesCount;
760-
innerClasses.putShort(name == null ? 0 : newClass(name));
761-
innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
762-
innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
763-
innerClasses.putShort(access);
759+
// §4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
760+
// constant_pool table which represents a class or interface C that is
761+
// not a package member must have exactly one corresponding entry in the
762+
// classes array". To avoid duplicates we keep track in the intVal field
763+
// of the Item of each CONSTANT_Class_info entry C whether an inner
764+
// class entry has already been added for C (this field is unused for
765+
// class entries, and changing its value does not change the hashcode
766+
// and equality tests). If so we store the index of this inner class
767+
// entry (plus one) in intVal. This hack allows duplicate detection in
768+
// O(1) time.
769+
Item nameItem = newClassItem(name);
770+
if (nameItem.intVal == 0) {
771+
++innerClassesCount;
772+
innerClasses.putShort(nameItem.index);
773+
innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
774+
innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
775+
innerClasses.putShort(access);
776+
nameItem.intVal = innerClassesCount;
777+
} else {
778+
// Compare the inner classes entry nameItem.intVal - 1 with the
779+
// arguments of this method and throw an exception if there is a
780+
// difference?
781+
}
764782
}
765783

766784
@Override

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

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class MethodWriter extends MethodVisitor {
4343
* Pseudo access flag used to denote constructors.
4444
*/
4545
static final int ACC_CONSTRUCTOR = 0x80000;
46-
46+
4747
/**
4848
* Frame has exactly the same locals as the previous stack map frame and
4949
* number of stack items is zero.
@@ -1401,6 +1401,14 @@ public void visitLineNumber(final int line, final Label start) {
14011401

14021402
@Override
14031403
public void visitMaxs(final int maxStack, final int maxLocals) {
1404+
if (resize) {
1405+
// replaces the temporary jump opcodes introduced by Label.resolve.
1406+
if (ClassReader.RESIZE) {
1407+
resizeInstructions();
1408+
} else {
1409+
throw new RuntimeException("Method code too large!");
1410+
}
1411+
}
14041412
if (ClassReader.FRAMES && compute == FRAMES) {
14051413
// completes the control flow graph with exception handler blocks
14061414
Handler handler = firstHandler;
@@ -2022,14 +2030,6 @@ final int getSize() {
20222030
if (classReaderOffset != 0) {
20232031
return 6 + classReaderLength;
20242032
}
2025-
if (resize) {
2026-
// replaces the temporary jump opcodes introduced by Label.resolve.
2027-
if (ClassReader.RESIZE) {
2028-
resizeInstructions();
2029-
} else {
2030-
throw new RuntimeException("Method code too large!");
2031-
}
2032-
}
20332033
int size = 8;
20342034
if (code.length > 0) {
20352035
if (code.length > 65536) {
@@ -2686,49 +2686,50 @@ private void resizeInstructions() {
26862686
}
26872687
}
26882688

2689-
// recomputes the stack map frames
2690-
if (frameCount > 0) {
2691-
if (compute == FRAMES) {
2692-
frameCount = 0;
2693-
stackMap = null;
2694-
previousFrame = null;
2695-
frame = null;
2696-
Frame f = new Frame();
2697-
f.owner = labels;
2698-
Type[] args = Type.getArgumentTypes(descriptor);
2699-
f.initInputFrame(cw, access, args, maxLocals);
2700-
visitFrame(f);
2701-
Label l = labels;
2702-
while (l != null) {
2703-
/*
2704-
* here we need the original label position. getNewOffset
2705-
* must therefore never have been called for this label.
2706-
*/
2707-
u = l.position - 3;
2708-
if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) {
2709-
getNewOffset(allIndexes, allSizes, l);
2710-
// TODO update offsets in UNINITIALIZED values
2711-
visitFrame(l.frame);
2712-
}
2713-
l = l.successor;
2714-
}
2715-
} else {
2689+
// updates the stack map frame labels
2690+
if (compute == FRAMES) {
2691+
Label l = labels;
2692+
while (l != null) {
27162693
/*
2717-
* Resizing an existing stack map frame table is really hard.
2718-
* Not only the table must be parsed to update the offets, but
2719-
* new frames may be needed for jump instructions that were
2720-
* inserted by this method. And updating the offsets or
2721-
* inserting frames can change the format of the following
2722-
* frames, in case of packed frames. In practice the whole table
2723-
* must be recomputed. For this the frames are marked as
2724-
* potentially invalid. This will cause the whole class to be
2725-
* reread and rewritten with the COMPUTE_FRAMES option (see the
2726-
* ClassWriter.toByteArray method). This is not very efficient
2727-
* but is much easier and requires much less code than any other
2728-
* method I can think of.
2694+
* Detects the labels that are just after an IF instruction that
2695+
* has been resized with the IFNOT GOTO_W pattern. These labels
2696+
* are now the target of a jump instruction (the IFNOT
2697+
* instruction). Note that we need the original label position
2698+
* here. getNewOffset must therefore never have been called for
2699+
* this label.
27292700
*/
2730-
cw.invalidFrames = true;
2701+
u = l.position - 3;
2702+
if (u >= 0 && resize[u]) {
2703+
l.status |= Label.TARGET;
2704+
}
2705+
getNewOffset(allIndexes, allSizes, l);
2706+
l = l.successor;
27312707
}
2708+
// Update the offsets in the uninitialized types
2709+
for (i = 0; i < cw.typeTable.length; ++i) {
2710+
Item item = cw.typeTable[i];
2711+
if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
2712+
item.intVal = getNewOffset(allIndexes, allSizes, 0,
2713+
item.intVal);
2714+
}
2715+
}
2716+
// The stack map frames are not serialized yet, so we don't need
2717+
// to update them. They will be serialized in visitMaxs.
2718+
} else if (frameCount > 0) {
2719+
/*
2720+
* Resizing an existing stack map frame table is really hard. Not
2721+
* only the table must be parsed to update the offets, but new
2722+
* frames may be needed for jump instructions that were inserted by
2723+
* this method. And updating the offsets or inserting frames can
2724+
* change the format of the following frames, in case of packed
2725+
* frames. In practice the whole table must be recomputed. For this
2726+
* the frames are marked as potentially invalid. This will cause the
2727+
* whole class to be reread and rewritten with the COMPUTE_FRAMES
2728+
* option (see the ClassWriter.toByteArray method). This is not very
2729+
* efficient but is much easier and requires much less code than any
2730+
* other method I can think of.
2731+
*/
2732+
cw.invalidFrames = true;
27322733
}
27332734
// updates the exception handler block labels
27342735
Handler h = firstHandler;

0 commit comments

Comments
 (0)