Merge branch '6.2.x'
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
Deploy Docs / Dispatch docs deployment (push) Waiting to run Details

# Conflicts:
#	spring-core/src/main/java/org/springframework/cglib/core/CodeEmitter.java
This commit is contained in:
Juergen Hoeller 2025-10-02 21:56:12 +02:00
commit 37319fc367
2 changed files with 959 additions and 835 deletions

View File

@ -27,34 +27,38 @@ import org.springframework.asm.Type;
*/ */
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
public class CodeEmitter extends LocalVariablesSorter { public class CodeEmitter extends LocalVariablesSorter {
private static final Signature BOOLEAN_VALUE =
TypeUtils.parseSignature("boolean booleanValue()"); // SPRING PATCH BEGIN
private static final Signature BOOLEAN_VALUE_OF = private static final Signature BOOLEAN_VALUE_OF =
TypeUtils.parseSignature("Boolean valueOf(boolean)"); TypeUtils.parseSignature("Boolean valueOf(boolean)");
private static final Signature INTEGER_VALUE_OF =
TypeUtils.parseSignature("Integer valueOf(int)");
private static final Signature BYTE_VALUE_OF = private static final Signature BYTE_VALUE_OF =
TypeUtils.parseSignature("Byte valueOf(byte)"); TypeUtils.parseSignature("Byte valueOf(byte)");
private static final Signature SHORT_VALUE_OF =
TypeUtils.parseSignature("Short valueOf(short)");
private static final Signature LONG_VALUE_OF =
TypeUtils.parseSignature("Long valueOf(long)");
private static final Signature FLOAT_VALUE_OF =
TypeUtils.parseSignature("Float valueOf(float)");
private static final Signature DOUBLE_VALUE_OF =
TypeUtils.parseSignature("Double valueOf(double)");
private static final Signature CHARACTER_VALUE_OF = private static final Signature CHARACTER_VALUE_OF =
TypeUtils.parseSignature("Character valueOf(char)"); TypeUtils.parseSignature("Character valueOf(char)");
private static final Signature DOUBLE_VALUE_OF =
TypeUtils.parseSignature("Double valueOf(double)");
private static final Signature FLOAT_VALUE_OF =
TypeUtils.parseSignature("Float valueOf(float)");
private static final Signature INTEGER_VALUE_OF =
TypeUtils.parseSignature("Integer valueOf(int)");
private static final Signature LONG_VALUE_OF =
TypeUtils.parseSignature("Long valueOf(long)");
private static final Signature SHORT_VALUE_OF =
TypeUtils.parseSignature("Short valueOf(short)");
// SPRING PATCH END
private static final Signature BOOLEAN_VALUE =
TypeUtils.parseSignature("boolean booleanValue()");
private static final Signature CHAR_VALUE = private static final Signature CHAR_VALUE =
TypeUtils.parseSignature("char charValue()"); TypeUtils.parseSignature("char charValue()");
private static final Signature LONG_VALUE =
TypeUtils.parseSignature("long longValue()");
private static final Signature DOUBLE_VALUE = private static final Signature DOUBLE_VALUE =
TypeUtils.parseSignature("double doubleValue()"); TypeUtils.parseSignature("double doubleValue()");
private static final Signature FLOAT_VALUE = private static final Signature FLOAT_VALUE =
TypeUtils.parseSignature("float floatValue()"); TypeUtils.parseSignature("float floatValue()");
private static final Signature INT_VALUE = private static final Signature INT_VALUE =
TypeUtils.parseSignature("int intValue()"); TypeUtils.parseSignature("int intValue()");
private static final Signature LONG_VALUE =
TypeUtils.parseSignature("long longValue()");
private static final Signature CSTRUCT_NULL = private static final Signature CSTRUCT_NULL =
TypeUtils.parseConstructor(""); TypeUtils.parseConstructor("");
private static final Signature CSTRUCT_STRING = private static final Signature CSTRUCT_STRING =
@ -70,7 +74,6 @@ public class CodeEmitter extends LocalVariablesSorter {
public static final int REM = Constants.IREM; public static final int REM = Constants.IREM;
public static final int AND = Constants.IAND; public static final int AND = Constants.IAND;
public static final int OR = Constants.IOR; public static final int OR = Constants.IOR;
public static final int GT = Constants.IFGT; public static final int GT = Constants.IFGT;
public static final int LT = Constants.IFLT; public static final int LT = Constants.IFLT;
public static final int GE = Constants.IFGE; public static final int GE = Constants.IFGE;
@ -79,48 +82,9 @@ public class CodeEmitter extends LocalVariablesSorter {
public static final int EQ = Constants.IFEQ; public static final int EQ = Constants.IFEQ;
private ClassEmitter ce; private ClassEmitter ce;
private State state; private State state;
private static class State
extends MethodInfo
{
ClassInfo classInfo;
int access;
Signature sig;
Type[] argumentTypes;
int localOffset;
Type[] exceptionTypes;
State(ClassInfo classInfo, int access, Signature sig, Type[] exceptionTypes) {
this.classInfo = classInfo;
this.access = access;
this.sig = sig;
this.exceptionTypes = exceptionTypes;
localOffset = TypeUtils.isStatic(access) ? 0 : 1;
argumentTypes = sig.getArgumentTypes();
}
@Override
public ClassInfo getClassInfo() {
return classInfo;
}
@Override
public int getModifiers() {
return access;
}
@Override
public Signature getSignature() {
return sig;
}
@Override
public Type[] getExceptionTypes() {
return exceptionTypes;
}
}
CodeEmitter(ClassEmitter ce, MethodVisitor mv, int access, Signature sig, Type[] exceptionTypes) { CodeEmitter(ClassEmitter ce, MethodVisitor mv, int access, Signature sig, Type[] exceptionTypes) {
super(access, sig.getDescriptor(), mv); super(access, sig.getDescriptor(), mv);
@ -134,6 +98,7 @@ public class CodeEmitter extends LocalVariablesSorter {
this.state = wrap.state; this.state = wrap.state;
} }
public boolean isStaticHook() { public boolean isStaticHook() {
return false; return false;
} }
@ -172,9 +137,17 @@ public class CodeEmitter extends LocalVariablesSorter {
exception.getInternalName()); exception.getInternalName());
} }
public void goTo(Label label) { mv.visitJumpInsn(Constants.GOTO, label); } public void goTo(Label label) {
public void ifnull(Label label) { mv.visitJumpInsn(Constants.IFNULL, label); } mv.visitJumpInsn(Constants.GOTO, label);
public void ifnonnull(Label label) { mv.visitJumpInsn(Constants.IFNONNULL, label); } }
public void ifnull(Label label) {
mv.visitJumpInsn(Constants.IFNULL, label);
}
public void ifnonnull(Label label) {
mv.visitJumpInsn(Constants.IFNONNULL, label);
}
public void if_jump(int mode, Label label) { public void if_jump(int mode, Label label) {
mv.visitJumpInsn(mode, label); mv.visitJumpInsn(mode, label);
@ -188,8 +161,12 @@ public class CodeEmitter extends LocalVariablesSorter {
int intOp = -1; int intOp = -1;
int jumpmode = mode; int jumpmode = mode;
switch (mode) { switch (mode) {
case GE: jumpmode = LT; break; case GE:
case LE: jumpmode = GT; break; jumpmode = LT;
break;
case LE:
jumpmode = GT;
break;
} }
switch (type.getSort()) { switch (type.getSort()) {
case Type.LONG: case Type.LONG:
@ -214,12 +191,22 @@ public class CodeEmitter extends LocalVariablesSorter {
throw new IllegalArgumentException("Bad comparison for type " + type); throw new IllegalArgumentException("Bad comparison for type " + type);
default: default:
switch (mode) { switch (mode) {
case EQ: intOp = Constants.IF_ICMPEQ; break; case EQ:
case NE: intOp = Constants.IF_ICMPNE; break; intOp = Constants.IF_ICMPEQ;
case GE: swap(); /* fall through */ break;
case LT: intOp = Constants.IF_ICMPLT; break; case NE:
case LE: swap(); /* fall through */ intOp = Constants.IF_ICMPNE;
case GT: intOp = Constants.IF_ICMPGT; break; break;
case GE:
swap(); /* fall through */
case LT:
intOp = Constants.IF_ICMPLT;
break;
case LE:
swap(); /* fall through */
case GT:
intOp = Constants.IF_ICMPGT;
break;
} }
mv.visitJumpInsn(intOp, label); mv.visitJumpInsn(intOp, label);
return; return;
@ -227,43 +214,87 @@ public class CodeEmitter extends LocalVariablesSorter {
if_jump(jumpmode, label); if_jump(jumpmode, label);
} }
public void pop() { mv.visitInsn(Constants.POP); } public void pop() {
public void pop2() { mv.visitInsn(Constants.POP2); } mv.visitInsn(Constants.POP);
public void dup() { mv.visitInsn(Constants.DUP); } }
public void dup2() { mv.visitInsn(Constants.DUP2); }
public void dup_x1() { mv.visitInsn(Constants.DUP_X1); } public void pop2() {
public void dup_x2() { mv.visitInsn(Constants.DUP_X2); } mv.visitInsn(Constants.POP2);
public void dup2_x1() { mv.visitInsn(Constants.DUP2_X1); } }
public void dup2_x2() { mv.visitInsn(Constants.DUP2_X2); }
public void swap() { mv.visitInsn(Constants.SWAP); } public void dup() {
public void aconst_null() { mv.visitInsn(Constants.ACONST_NULL); } mv.visitInsn(Constants.DUP);
}
public void dup2() {
mv.visitInsn(Constants.DUP2);
}
public void dup_x1() {
mv.visitInsn(Constants.DUP_X1);
}
public void dup_x2() {
mv.visitInsn(Constants.DUP_X2);
}
public void dup2_x1() {
mv.visitInsn(Constants.DUP2_X1);
}
public void dup2_x2() {
mv.visitInsn(Constants.DUP2_X2);
}
public void swap() {
mv.visitInsn(Constants.SWAP);
}
public void aconst_null() {
mv.visitInsn(Constants.ACONST_NULL);
}
public void swap(Type prev, Type type) { public void swap(Type prev, Type type) {
if (type.getSize() == 1) { if (type.getSize() == 1) {
if (prev.getSize() == 1) { if (prev.getSize() == 1) {
swap(); // same as dup_x1(), pop(); swap(); // same as dup_x1(), pop();
} else { }
else {
dup_x2(); dup_x2();
pop(); pop();
} }
} else { }
else {
if (prev.getSize() == 1) { if (prev.getSize() == 1) {
dup2_x1(); dup2_x1();
pop2(); pop2();
} else { }
else {
dup2_x2(); dup2_x2();
pop2(); pop2();
} }
} }
} }
public void monitorenter() { mv.visitInsn(Constants.MONITORENTER); } public void monitorenter() {
public void monitorexit() { mv.visitInsn(Constants.MONITOREXIT); } mv.visitInsn(Constants.MONITORENTER);
}
public void math(int op, Type type) { mv.visitInsn(type.getOpcode(op)); } public void monitorexit() {
mv.visitInsn(Constants.MONITOREXIT);
}
public void array_load(Type type) { mv.visitInsn(type.getOpcode(Constants.IALOAD)); } public void math(int op, Type type) {
public void array_store(Type type) { mv.visitInsn(type.getOpcode(Constants.IASTORE)); } mv.visitInsn(type.getOpcode(op));
}
public void array_load(Type type) {
mv.visitInsn(type.getOpcode(Constants.IALOAD));
}
public void array_store(Type type) {
mv.visitInsn(type.getOpcode(Constants.IASTORE));
}
/** /**
* Casts from one primitive numeric type to another * Casts from one primitive numeric type to another
@ -273,42 +304,56 @@ public class CodeEmitter extends LocalVariablesSorter {
if (from == Type.DOUBLE_TYPE) { if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) { if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Constants.D2F); mv.visitInsn(Constants.D2F);
} else if (to == Type.LONG_TYPE) { }
else if (to == Type.LONG_TYPE) {
mv.visitInsn(Constants.D2L); mv.visitInsn(Constants.D2L);
} else { }
else {
mv.visitInsn(Constants.D2I); mv.visitInsn(Constants.D2I);
cast_numeric(Type.INT_TYPE, to); cast_numeric(Type.INT_TYPE, to);
} }
} else if (from == Type.FLOAT_TYPE) { }
else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) { if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Constants.F2D); mv.visitInsn(Constants.F2D);
} else if (to == Type.LONG_TYPE) { }
else if (to == Type.LONG_TYPE) {
mv.visitInsn(Constants.F2L); mv.visitInsn(Constants.F2L);
} else { }
else {
mv.visitInsn(Constants.F2I); mv.visitInsn(Constants.F2I);
cast_numeric(Type.INT_TYPE, to); cast_numeric(Type.INT_TYPE, to);
} }
} else if (from == Type.LONG_TYPE) { }
else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) { if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Constants.L2D); mv.visitInsn(Constants.L2D);
} else if (to == Type.FLOAT_TYPE) { }
else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Constants.L2F); mv.visitInsn(Constants.L2F);
} else { }
else {
mv.visitInsn(Constants.L2I); mv.visitInsn(Constants.L2I);
cast_numeric(Type.INT_TYPE, to); cast_numeric(Type.INT_TYPE, to);
} }
} else { }
else {
if (to == Type.BYTE_TYPE) { if (to == Type.BYTE_TYPE) {
mv.visitInsn(Constants.I2B); mv.visitInsn(Constants.I2B);
} else if (to == Type.CHAR_TYPE) { }
else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Constants.I2C); mv.visitInsn(Constants.I2C);
} else if (to == Type.DOUBLE_TYPE) { }
else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Constants.I2D); mv.visitInsn(Constants.I2D);
} else if (to == Type.FLOAT_TYPE) { }
else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Constants.I2F); mv.visitInsn(Constants.I2F);
} else if (to == Type.LONG_TYPE) { }
else if (to == Type.LONG_TYPE) {
mv.visitInsn(Constants.I2L); mv.visitInsn(Constants.I2L);
} else if (to == Type.SHORT_TYPE) { }
else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Constants.I2S); mv.visitInsn(Constants.I2S);
} }
} }
@ -318,13 +363,17 @@ public class CodeEmitter extends LocalVariablesSorter {
public void push(int i) { public void push(int i) {
if (i < -1) { if (i < -1) {
mv.visitLdcInsn(i); mv.visitLdcInsn(i);
} else if (i <= 5) { }
else if (i <= 5) {
mv.visitInsn(TypeUtils.ICONST(i)); mv.visitInsn(TypeUtils.ICONST(i));
} else if (i <= Byte.MAX_VALUE) { }
else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(Constants.BIPUSH, i); mv.visitIntInsn(Constants.BIPUSH, i);
} else if (i <= Short.MAX_VALUE) { }
else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(Constants.SIPUSH, i); mv.visitIntInsn(Constants.SIPUSH, i);
} else { }
else {
mv.visitLdcInsn(i); mv.visitLdcInsn(i);
} }
} }
@ -332,7 +381,8 @@ public class CodeEmitter extends LocalVariablesSorter {
public void push(long value) { public void push(long value) {
if (value == 0L || value == 1L) { if (value == 0L || value == 1L) {
mv.visitInsn(TypeUtils.LCONST(value)); mv.visitInsn(TypeUtils.LCONST(value));
} else { }
else {
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }
} }
@ -340,14 +390,17 @@ public class CodeEmitter extends LocalVariablesSorter {
public void push(float value) { public void push(float value) {
if (value == 0f || value == 1f || value == 2f) { if (value == 0f || value == 1f || value == 2f) {
mv.visitInsn(TypeUtils.FCONST(value)); mv.visitInsn(TypeUtils.FCONST(value));
} else { }
else {
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }
} }
public void push(double value) { public void push(double value) {
if (value == 0d || value == 1d) { if (value == 0d || value == 1d) {
mv.visitInsn(TypeUtils.DCONST(value)); mv.visitInsn(TypeUtils.DCONST(value));
} else { }
else {
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }
} }
@ -363,7 +416,8 @@ public class CodeEmitter extends LocalVariablesSorter {
public void newarray(Type type) { public void newarray(Type type) {
if (TypeUtils.isPrimitive(type)) { if (TypeUtils.isPrimitive(type)) {
mv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type)); mv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type));
} else { }
else {
emit_type(Constants.ANEWARRAY, type); emit_type(Constants.ANEWARRAY, type);
} }
} }
@ -388,6 +442,7 @@ public class CodeEmitter extends LocalVariablesSorter {
/** /**
* Pushes the specified argument of the current method onto the stack. * Pushes the specified argument of the current method onto the stack.
*
* @param index the zero-based index into the argument list * @param index the zero-based index into the argument list
*/ */
public void load_arg(int index) { public void load_arg(int index) {
@ -573,7 +628,8 @@ public class CodeEmitter extends LocalVariablesSorter {
String desc; String desc;
if (TypeUtils.isArray(type)) { if (TypeUtils.isArray(type)) {
desc = type.getDescriptor(); desc = type.getDescriptor();
} else { }
else {
desc = type.getInternalName(); desc = type.getInternalName();
} }
mv.visitTypeInsn(opcode, desc); mv.visitTypeInsn(opcode, desc);
@ -584,9 +640,17 @@ public class CodeEmitter extends LocalVariablesSorter {
aaload(); aaload();
} }
public void aaload() { mv.visitInsn(Constants.AALOAD); } public void aaload() {
public void aastore() { mv.visitInsn(Constants.AASTORE); } mv.visitInsn(Constants.AALOAD);
public void athrow() { mv.visitInsn(Constants.ATHROW); } }
public void aastore() {
mv.visitInsn(Constants.AASTORE);
}
public void athrow() {
mv.visitInsn(Constants.ATHROW);
}
public Label make_label() { public Label make_label() {
return new Label(); return new Label();
@ -622,8 +686,9 @@ public class CodeEmitter extends LocalVariablesSorter {
float density; float density;
if (keys.length == 0) { if (keys.length == 0) {
density = 0; density = 0;
} else { }
density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1); else {
density = (float) keys.length / (keys[keys.length - 1] - keys[0] + 1);
} }
process_switch(keys, callback, density >= 0.5f); process_switch(keys, callback, density >= 0.5f);
} }
@ -656,7 +721,8 @@ public class CodeEmitter extends LocalVariablesSorter {
callback.processCase(i + min, end); callback.processCase(i + min, end);
} }
} }
} else { }
else {
Label[] labels = new Label[len]; Label[] labels = new Label[len];
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
labels[i] = make_label(); labels[i] = make_label();
@ -673,9 +739,11 @@ public class CodeEmitter extends LocalVariablesSorter {
callback.processDefault(); callback.processDefault();
mark(end); mark(end);
} catch (RuntimeException | Error e) { }
catch (RuntimeException | Error e) {
throw e; throw e;
} catch (Exception e) { }
catch (Exception e) {
throw new CodeGenerationException(e); throw new CodeGenerationException(e);
} }
} }
@ -724,6 +792,7 @@ public class CodeEmitter extends LocalVariablesSorter {
* on the top of the stack with the wrapped (Object) equivalent using valueOf() methods. * on the top of the stack with the wrapped (Object) equivalent using valueOf() methods.
* For example, char -> Character. * For example, char -> Character.
* If the class is Void, a null is pushed onto the stack instead. * If the class is Void, a null is pushed onto the stack instead.
*
* @param type the class indicating the current type of the top stack value * @param type the class indicating the current type of the top stack value
*/ */
public void box(Type type) { public void box(Type type) {
@ -732,31 +801,32 @@ public class CodeEmitter extends LocalVariablesSorter {
case Type.VOID: case Type.VOID:
aconst_null(); aconst_null();
break; break;
// SPRING PATCH BEGIN
case Type.CHAR:
invoke_static(Constants.TYPE_CHARACTER, CHARACTER_VALUE_OF);
break;
case Type.BOOLEAN: case Type.BOOLEAN:
invoke_static(Constants.TYPE_BOOLEAN, BOOLEAN_VALUE_OF); invoke_static(Constants.TYPE_BOOLEAN, BOOLEAN_VALUE_OF);
break; break;
case Type.INT:
invoke_static(Constants.TYPE_INTEGER, INTEGER_VALUE_OF);
break;
case Type.BYTE:
invoke_static(Constants.TYPE_BYTE, BYTE_VALUE_OF);
break;
case Type.SHORT:
invoke_static(Constants.TYPE_SHORT, SHORT_VALUE_OF);
break;
case Type.LONG:
invoke_static(Constants.TYPE_LONG, LONG_VALUE_OF);
break;
case Type.FLOAT:
invoke_static(Constants.TYPE_FLOAT, FLOAT_VALUE_OF);
break;
case Type.DOUBLE: case Type.DOUBLE:
invoke_static(Constants.TYPE_DOUBLE, DOUBLE_VALUE_OF); invoke_static(Constants.TYPE_DOUBLE, DOUBLE_VALUE_OF);
break; break;
case Type.CHAR: case Type.FLOAT:
invoke_static(Constants.TYPE_CHARACTER, CHARACTER_VALUE_OF); invoke_static(Constants.TYPE_FLOAT, FLOAT_VALUE_OF);
break; break;
case Type.LONG:
invoke_static(Constants.TYPE_LONG, LONG_VALUE_OF);
break;
case Type.INT:
invoke_static(Constants.TYPE_INTEGER, INTEGER_VALUE_OF);
break;
case Type.SHORT:
invoke_static(Constants.TYPE_SHORT, SHORT_VALUE_OF);
break;
case Type.BYTE:
invoke_static(Constants.TYPE_BYTE, BYTE_VALUE_OF);
break;
// SPRING PATCH END
default: default:
Type boxed = TypeUtils.getBoxedType(type); Type boxed = TypeUtils.getBoxedType(type);
new_instance(boxed); new_instance(boxed);
@ -765,12 +835,13 @@ public class CodeEmitter extends LocalVariablesSorter {
dup_x2(); dup_x2();
dup_x2(); dup_x2();
pop(); pop();
} else { }
else {
// p -> po -> opo -> oop -> o // p -> po -> opo -> oop -> o
dup_x1(); dup_x1();
swap(); swap();
} }
invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type })); invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{type}));
} }
} }
} }
@ -779,6 +850,7 @@ public class CodeEmitter extends LocalVariablesSorter {
* If the argument is a primitive class, replaces the object * If the argument is a primitive class, replaces the object
* on the top of the stack with the unwrapped (primitive) * on the top of the stack with the unwrapped (primitive)
* equivalent. For example, Character -> char. * equivalent. For example, Character -> char.
*
* @param type the class indicating the desired type of the top stack value * @param type the class indicating the desired type of the top stack value
*/ */
public void unbox(Type type) { public void unbox(Type type) {
@ -812,7 +884,8 @@ public class CodeEmitter extends LocalVariablesSorter {
if (sig == null) { if (sig == null) {
checkcast(type); checkcast(type);
} else { }
else {
checkcast(t); checkcast(t);
invoke_virtual(t, sig); invoke_virtual(t, sig);
} }
@ -860,7 +933,8 @@ public class CodeEmitter extends LocalVariablesSorter {
default: default:
push(0); push(0);
} }
} else { }
else {
aconst_null(); aconst_null();
} }
} }
@ -883,7 +957,8 @@ public class CodeEmitter extends LocalVariablesSorter {
unbox(type); unbox(type);
mark(end); mark(end);
} }
} else { }
else {
checkcast(type); checkcast(type);
} }
} }
@ -901,11 +976,14 @@ public class CodeEmitter extends LocalVariablesSorter {
Signature sig = method.getSignature(); Signature sig = method.getSignature();
if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) { if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
invoke_constructor(type, sig); invoke_constructor(type, sig);
} else if (TypeUtils.isStatic(method.getModifiers())) { }
else if (TypeUtils.isStatic(method.getModifiers())) {
invoke_static(type, sig, TypeUtils.isInterface(classInfo.getModifiers())); invoke_static(type, sig, TypeUtils.isInterface(classInfo.getModifiers()));
} else if (TypeUtils.isInterface(classInfo.getModifiers())) { }
else if (TypeUtils.isInterface(classInfo.getModifiers())) {
invoke_interface(type, sig); invoke_interface(type, sig);
} else { }
else {
invoke_virtual(virtualType, sig); invoke_virtual(virtualType, sig);
} }
} }
@ -913,4 +991,50 @@ public class CodeEmitter extends LocalVariablesSorter {
public void invoke(MethodInfo method) { public void invoke(MethodInfo method) {
invoke(method, method.getClassInfo().getType()); invoke(method, method.getClassInfo().getType());
} }
private static class State extends MethodInfo {
ClassInfo classInfo;
int access;
Signature sig;
Type[] argumentTypes;
int localOffset;
Type[] exceptionTypes;
State(ClassInfo classInfo, int access, Signature sig, Type[] exceptionTypes) {
this.classInfo = classInfo;
this.access = access;
this.sig = sig;
this.exceptionTypes = exceptionTypes;
localOffset = TypeUtils.isStatic(access) ? 0 : 1;
argumentTypes = sig.getArgumentTypes();
}
@Override
public ClassInfo getClassInfo() {
return classInfo;
}
@Override
public int getModifiers() {
return access;
}
@Override
public Signature getSignature() {
return sig;
}
@Override
public Type[] getExceptionTypes() {
return exceptionTypes;
}
}
} }

View File

@ -392,7 +392,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
} }
else { else {
// a single resource with the given name // a single resource with the given name
return new Resource[] {getResourceLoader().getResource(locationPattern)}; return new Resource[] {getResource(locationPattern)};
} }
} }
} }