mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-03-23 16:20:26 +08:00
consider return type when calculating stack change
This commit is contained in:
parent
43cd4aeeec
commit
7d2dd83410
@ -122,21 +122,17 @@ public class SourceClassHandler extends BaseClassHandler {
|
|||||||
for (int i = rangeEnd - 1; i >= 0; i--) {
|
for (int i = rangeEnd - 1; i >= 0; i--) {
|
||||||
switch (instructions[i].getOpcode()) {
|
switch (instructions[i].getOpcode()) {
|
||||||
case Opcodes.INVOKESPECIAL:
|
case Opcodes.INVOKESPECIAL:
|
||||||
stackLevel += ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size();
|
case Opcodes.INVOKEVIRTUAL:
|
||||||
|
case Opcodes.INVOKEINTERFACE:
|
||||||
|
stackLevel += stackEffectOfInvocation(instructions[i]) + 1;
|
||||||
if (((MethodInsnNode)instructions[i]).name.equals(ConstPool.CONSTRUCTOR)) {
|
if (((MethodInsnNode)instructions[i]).name.equals(ConstPool.CONSTRUCTOR)) {
|
||||||
// constructor implicitly eat 2 more stack and return 1 value
|
// constructor must be INVOKESPECIAL and implicitly pop 1 more stack
|
||||||
stackLevel++;
|
stackLevel++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opcodes.INVOKESTATIC:
|
case Opcodes.INVOKESTATIC:
|
||||||
case Opcodes.INVOKEDYNAMIC:
|
case Opcodes.INVOKEDYNAMIC:
|
||||||
// static and dynamic invoke implicitly return 1 value
|
stackLevel += stackEffectOfInvocation(instructions[i]);
|
||||||
stackLevel += (ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size() - 1);
|
|
||||||
break;
|
|
||||||
case Opcodes.INVOKEVIRTUAL:
|
|
||||||
case Opcodes.INVOKEINTERFACE:
|
|
||||||
// virtual and interface invoke implicitly eat 1 more stack and return 1 value, deuce
|
|
||||||
stackLevel += ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size();
|
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
// reach LineNumberNode or LabelNode
|
// reach LineNumberNode or LabelNode
|
||||||
@ -151,6 +147,11 @@ public class SourceClassHandler extends BaseClassHandler {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int stackEffectOfInvocation(AbstractInsnNode instruction) {
|
||||||
|
String desc = ((MethodInsnNode)instruction).desc;
|
||||||
|
return ClassUtil.getParameterTypes(desc).size() - (ClassUtil.getReturnType(desc).isEmpty() ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
private AbstractInsnNode[] replaceNewOps(ClassNode cn, MethodNode mn, String newOperatorInjectMethodName,
|
private AbstractInsnNode[] replaceNewOps(ClassNode cn, MethodNode mn, String newOperatorInjectMethodName,
|
||||||
AbstractInsnNode[] instructions, int start, int end) {
|
AbstractInsnNode[] instructions, int start, int end) {
|
||||||
LogUtil.debug(" Using %s mock new operation in %s", newOperatorInjectMethodName, mn.name);
|
LogUtil.debug(" Using %s mock new operation in %s", newOperatorInjectMethodName, mn.name);
|
||||||
|
@ -26,6 +26,7 @@ public class ClassUtil {
|
|||||||
public static final byte TYPE_CLASS = 'L';
|
public static final byte TYPE_CLASS = 'L';
|
||||||
public static final byte TYPE_SHORT = 'S';
|
public static final byte TYPE_SHORT = 'S';
|
||||||
public static final byte TYPE_BOOL = 'Z';
|
public static final byte TYPE_BOOL = 'Z';
|
||||||
|
public static final byte TYPE_VOID = 'V';
|
||||||
private static final byte PARAM_END = ')';
|
private static final byte PARAM_END = ')';
|
||||||
private static final byte CLASS_END = ';';
|
private static final byte CLASS_END = ';';
|
||||||
private static final byte TYPE_ARRAY = '[';
|
private static final byte TYPE_ARRAY = '[';
|
||||||
@ -39,6 +40,7 @@ public class ClassUtil {
|
|||||||
private static final String CLASS_LONG = "java/lang/Long";
|
private static final String CLASS_LONG = "java/lang/Long";
|
||||||
private static final String CLASS_SHORT = "java/lang/Short";
|
private static final String CLASS_SHORT = "java/lang/Short";
|
||||||
private static final String CLASS_BOOLEAN = "java/lang/Boolean";
|
private static final String CLASS_BOOLEAN = "java/lang/Boolean";
|
||||||
|
private static final String EMPTY = "";
|
||||||
private static final String METHOD_VALUE_OF = "valueOf";
|
private static final String METHOD_VALUE_OF = "valueOf";
|
||||||
|
|
||||||
private final static String JOINER = "::";
|
private final static String JOINER = "::";
|
||||||
@ -56,6 +58,7 @@ public class ClassUtil {
|
|||||||
TYPE_MAPPING.put(TYPE_LONG, CLASS_LONG);
|
TYPE_MAPPING.put(TYPE_LONG, CLASS_LONG);
|
||||||
TYPE_MAPPING.put(TYPE_SHORT, CLASS_SHORT);
|
TYPE_MAPPING.put(TYPE_SHORT, CLASS_SHORT);
|
||||||
TYPE_MAPPING.put(TYPE_BOOL, CLASS_BOOLEAN);
|
TYPE_MAPPING.put(TYPE_BOOL, CLASS_BOOLEAN);
|
||||||
|
TYPE_MAPPING.put(TYPE_VOID, EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,7 +162,7 @@ public class ClassUtil {
|
|||||||
} else if (TYPE_MAPPING.containsKey((byte)typeChar)) {
|
} else if (TYPE_MAPPING.containsKey((byte)typeChar)) {
|
||||||
return TYPE_MAPPING.get((byte)typeChar);
|
return TYPE_MAPPING.get((byte)typeChar);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user