下面列出了org.objectweb.asm.Type#BOOLEAN 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static int getPrimitiveArrayOpcode(Type type) {
switch (type.getElementType().getSort()) {
case Type.BOOLEAN:
return Opcodes.T_BOOLEAN;
case Type.BYTE:
return Opcodes.T_BYTE;
case Type.SHORT:
return Opcodes.T_SHORT;
case Type.CHAR:
return Opcodes.T_CHAR;
case Type.INT:
return Opcodes.T_INT;
case Type.LONG:
return Opcodes.T_LONG;
case Type.FLOAT:
return Opcodes.T_FLOAT;
case Type.DOUBLE:
return Opcodes.T_DOUBLE;
default:
throw new RuntimeException("WT");
}
}
public static Type resolveBinOpType(Type type1, Type type2) {
if (isObjectRef(type1) || isObjectRef(type2)) {
if (isObjectRef(type1) != isObjectRef(type2)) {
throw new IllegalStateException("Illegal binop types: " + type1 + " " + type2);
}
return OBJECT_TYPE;
} else if (type1 == Type.DOUBLE_TYPE || type2 == Type.DOUBLE_TYPE) {
return Type.DOUBLE_TYPE;
} else if (type1 == Type.FLOAT_TYPE || type2 == Type.FLOAT_TYPE) {
return Type.FLOAT_TYPE;
} else if (type1 == Type.LONG_TYPE || type2 == Type.LONG_TYPE) {
return Type.LONG_TYPE;
} else if (type1.getSort() >= Type.BOOLEAN && type1.getSort() <= Type.INT && type2.getSort() >= Type.BOOLEAN && type2.getSort() <= Type.INT) {
return Type.INT_TYPE;
} else {
throw new UnsupportedOperationException("Unsupported binop types: " + type1 + " " + type2);
}
}
private static Type getBoxedType(final Type type) {
switch (type.getSort()) {
case Type.BYTE:
return BYTE_TYPE;
case Type.BOOLEAN:
return BOOLEAN_TYPE;
case Type.SHORT:
return SHORT_TYPE;
case Type.CHAR:
return CHARACTER_TYPE;
case Type.INT:
return INTEGER_TYPE;
case Type.FLOAT:
return FLOAT_TYPE;
case Type.LONG:
return LONG_TYPE;
case Type.DOUBLE:
return DOUBLE_TYPE;
default:
return type;
}
}
public static int NEWARRAY(Type type) {
switch (type.getSort()) {
case Type.BYTE:
return Constants.T_BYTE;
case Type.CHAR:
return Constants.T_CHAR;
case Type.DOUBLE:
return Constants.T_DOUBLE;
case Type.FLOAT:
return Constants.T_FLOAT;
case Type.INT:
return Constants.T_INT;
case Type.LONG:
return Constants.T_LONG;
case Type.SHORT:
return Constants.T_SHORT;
case Type.BOOLEAN:
return Constants.T_BOOLEAN;
default:
return -1; // error
}
}
/**
* Handle adding the variable to the maps.
*
* @param ast
* AST containing variable.
* @param root
* Root of AST.
* @param index
* Index to add variable to.
*
* @throws AssemblerException
* When fetching type information from the var-reference fails.
*/
private void addVariable(VariableReference ast, RootAST root, int index) throws AssemblerException {
String name = ast.getVariableName().getName();
// Fetch type information
int sort = -1;
if(ast instanceof Instruction)
sort = getType(((Instruction) ast).getOpcode().getOpcode());
else if(ast instanceof DefinitionArgAST) {
String desc = ((DefinitionArgAST) ast).getDesc().getDesc();
sort = Type.getType(desc).getSort();
}
if(sort == -1) {
int line = ((AST)ast).getLine();
throw new AssemblerException("Unknown variable type: " + ast, line);
}
// Update maps
int used = index + TypeUtil.sortToSize(sort);
if (used > maxIndex)
maxIndex = used;
nameToIndex.put(name, index);
indexToSort.put(index, sort);
if (sort >= Type.BOOLEAN && sort <= Type.DOUBLE)
nameToDesc.put(name, sortToDesc(sort));
}
/**
* Get the source code name for the specified type
*
* @param type Type to generate a friendly name for
* @param box True to return the equivalent boxing type for primitives
* @param fullyQualified fully-qualify class names
* @return String representation of the specified type, eg "int" for an
* integer primitive or "String" for java.lang.String
*/
public static String getTypeName(Type type, boolean box, boolean fullyQualified) {
if (type == null) {
return "{null?}";
}
switch (type.getSort()) {
case Type.VOID: return box ? "Void" : "void";
case Type.BOOLEAN: return box ? "Boolean" : "boolean";
case Type.CHAR: return box ? "Character" : "char";
case Type.BYTE: return box ? "Byte" : "byte";
case Type.SHORT: return box ? "Short" : "short";
case Type.INT: return box ? "Integer" : "int";
case Type.FLOAT: return box ? "Float" : "float";
case Type.LONG: return box ? "Long" : "long";
case Type.DOUBLE: return box ? "Double" : "double";
case Type.ARRAY: return SignaturePrinter.getTypeName(type.getElementType(), box, fullyQualified) + SignaturePrinter.arraySuffix(type);
case Type.OBJECT:
String typeName = type.getClassName();
if (!fullyQualified) {
typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
}
return typeName;
default:
return "Object";
}
}
private static void hash_primitive(CodeEmitter e, Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
// f ? 0 : 1
e.push(1);
e.math(e.XOR, Type.INT_TYPE);
break;
case Type.FLOAT:
// Float.floatToIntBits(f)
e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS);
break;
case Type.DOUBLE:
// Double.doubleToLongBits(f), hash_code(Long.TYPE)
e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS);
// fall through
case Type.LONG:
hash_long(e);
}
}
/**
* Append the call of proper autoboxing method for the given primitif type.
*/
protected static void autoBoxing(MethodVisitor mv, Type fieldType) {
switch (fieldType.getSort()) {
case Type.BOOLEAN:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
break;
case Type.BYTE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
break;
case Type.CHAR:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
break;
case Type.SHORT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
break;
case Type.INT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
break;
case Type.FLOAT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
break;
case Type.LONG:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
break;
case Type.DOUBLE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
break;
}
}
private static void loadType(MethodVisitor mv, Type type, Type ownerType) {
switch (type.getSort()) {
case Type.VOID:
mv.visitFieldInsn(GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
break;
case Type.BOOLEAN:
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
break;
case Type.CHAR:
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
break;
case Type.BYTE:
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
break;
case Type.SHORT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
break;
case Type.INT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
break;
case Type.FLOAT:
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
break;
case Type.LONG:
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
break;
case Type.DOUBLE:
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
break;
case Type.ARRAY:
loadArrayType(mv, type, ownerType);
break;
default:
loadObjectType(mv, type, ownerType);
}
}
@Override
public BasicValue newValue(final Type type) {
if (type == null) {
return BasicValue.UNINITIALIZED_VALUE;
}
boolean isArray = type.getSort() == Type.ARRAY;
if (isArray) {
switch (type.getElementType().getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
return new BasicValue(type);
default:
break;
}
}
BasicValue value = super.newValue(type);
if (BasicValue.REFERENCE_VALUE.equals(value)) {
if (isArray) {
value = newValue(type.getElementType());
StringBuilder descriptor = new StringBuilder();
for (int i = 0; i < type.getDimensions(); ++i) {
descriptor.append('[');
}
descriptor.append(value.getType().getDescriptor());
value = new BasicValue(Type.getType(descriptor.toString()));
} else {
value = new BasicValue(type);
}
}
return value;
}
@Override
public ComparisonAdapter getComparisionAdapter() {
return new ComparisonAdapter() {
@Override
public void coerceBoolean(CodeEmitter scope, Label isTrue, Label isFalse, Label isNull) {
MethodVisitor mv = scope.getMethodVisitor();
switch (getJVMType().getSort()) {
case Type.BOOLEAN:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
mv.visitJumpInsn(Opcodes.IFEQ, isFalse);
mv.visitJumpInsn(Opcodes.GOTO, isTrue);
break;
case Type.FLOAT:
mv.visitInsn(Opcodes.FCONST_0);
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFEQ, isTrue);
mv.visitJumpInsn(Opcodes.GOTO, isFalse);
break;
case Type.LONG:
mv.visitInsn(Opcodes.LCONST_0);
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFEQ, isTrue);
mv.visitJumpInsn(Opcodes.GOTO, isFalse);
break;
case Type.DOUBLE:
mv.visitInsn(Opcodes.DCONST_0);
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFEQ, isTrue);
mv.visitJumpInsn(Opcodes.GOTO, isFalse);
break;
default:
throw new UnsupportedOperationException("Unsupported JVM type: " + getJVMType());
}
}
};
}
/**
* Generates the instruction to push the given value on the stack.
*
* @param value the value to be pushed on the stack.
*/
public void push(final Type value) {
if (value == null) {
mv.visitInsn(Opcodes.ACONST_NULL);
} else {
switch (value.getSort()) {
case Type.BOOLEAN:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.CHAR:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.BYTE:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.SHORT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.INT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.FLOAT:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.LONG:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", CLASS_DESCRIPTOR);
break;
case Type.DOUBLE:
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", "TYPE", CLASS_DESCRIPTOR);
break;
default:
mv.visitLdcInsn(value);
break;
}
}
}
/**
* Constructs a new local variable of the given type.
*
* @param type the type of the local variable to be created.
* @return the identifier of the newly created local variable.
*/
public int newLocal(final Type type) {
Object localType;
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
localType = Opcodes.INTEGER;
break;
case Type.FLOAT:
localType = Opcodes.FLOAT;
break;
case Type.LONG:
localType = Opcodes.LONG;
break;
case Type.DOUBLE:
localType = Opcodes.DOUBLE;
break;
case Type.ARRAY:
localType = type.getDescriptor();
break;
case Type.OBJECT:
localType = type.getInternalName();
break;
default:
throw new AssertionError();
}
int local = newLocalMapping(type);
setLocalType(local, type);
setFrameLocal(local, localType);
return local;
}
public static Type resolveUnaryOpType(Type type) {
if (type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.INT) {
return Type.INT_TYPE;
} else if (type == Type.LONG_TYPE || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE) {
return type;
} else {
throw new UnsupportedOperationException("Unsupported binop types: " + type);
}
}
/**
* Generates instructions that returns a dummy value. Return values are as follows:
* <ul>
* <li>void -> no value</li>
* <li>boolean -> false</li>
* <li>byte/short/char/int -> 0</li>
* <li>long -> 0L</li>
* <li>float -> 0.0f</li>
* <li>double -> 0.0</li>
* <li>Object -> null</li>
* </ul>
*
* @param returnType return type of the method this generated bytecode is for
* @return instructions to return a dummy value
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if {@code returnType}'s sort is of {@link Type#METHOD}
*/
private static InsnList returnDummy(Type returnType) {
Validate.notNull(returnType);
Validate.isTrue(returnType.getSort() != Type.METHOD);
InsnList ret = new InsnList();
switch (returnType.getSort()) {
case Type.VOID:
ret.add(new InsnNode(Opcodes.RETURN));
break;
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
ret.add(new InsnNode(Opcodes.ICONST_0));
ret.add(new InsnNode(Opcodes.IRETURN));
break;
case Type.LONG:
ret.add(new InsnNode(Opcodes.LCONST_0));
ret.add(new InsnNode(Opcodes.LRETURN));
break;
case Type.FLOAT:
ret.add(new InsnNode(Opcodes.FCONST_0));
ret.add(new InsnNode(Opcodes.FRETURN));
break;
case Type.DOUBLE:
ret.add(new InsnNode(Opcodes.DCONST_0));
ret.add(new InsnNode(Opcodes.DRETURN));
break;
case Type.OBJECT:
case Type.ARRAY:
ret.add(new InsnNode(Opcodes.ACONST_NULL));
ret.add(new InsnNode(Opcodes.ARETURN));
break;
default:
throw new IllegalStateException();
}
return ret;
}
private MethodNode methodGen() {
String randDesc = descGen();
MethodNode method = new MethodNode(ACC_STATIC + ACC_PRIVATE, randomString(), randDesc, null, null);
int instructions = RandomUtils.getRandomInt(30) + 30;
InsnList insns = new InsnList();
for (int i = 0; i < instructions; ++i)
insns.add(junkInstructions());
Type returnType = Type.getReturnType(randDesc);
switch (returnType.getSort()) {
case Type.VOID:
insns.add(new InsnNode(RETURN));
break;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
if (RandomUtils.getRandomInt(10) % 2 == 1)
insns.add(new InsnNode(ICONST_0));
else
insns.add(new InsnNode(ICONST_1));
insns.add(new InsnNode(IRETURN));
break;
case Type.FLOAT:
insns.add(ASMUtils.getNumberInsn(RandomUtils.getRandomFloat()));
insns.add(new InsnNode(FRETURN));
break;
case Type.LONG:
insns.add(ASMUtils.getNumberInsn(RandomUtils.getRandomLong()));
insns.add(new InsnNode(LRETURN));
break;
case Type.DOUBLE:
insns.add(ASMUtils.getNumberInsn(RandomUtils.getRandomDouble()));
insns.add(new InsnNode(DRETURN));
break;
default:
insns.add(new VarInsnNode(ALOAD, RandomUtils.getRandomInt(30)));
insns.add(new InsnNode(ARETURN));
break;
}
method.instructions = insns;
return method;
}
protected void detectGoals(String className, String methodName, Class<?>[] argumentClasses ,Type[] argumentTypes, List<InputCoverageTestFitness> goals){
for (int i=0; i<argumentTypes.length;i++){
Type argType = argumentTypes[i];
int typeSort = argType.getSort();
if(typeSort == Type.OBJECT) {
Class<?> typeClass = argumentClasses[i];
if(ClassUtils.isPrimitiveWrapper(typeClass)) {
typeSort = Type.getType(ClassUtils.wrapperToPrimitive(typeClass)).getSort();
goals.add(createGoal(className, methodName, i, argType, REF_NULL));
}
}
switch (typeSort) {
case Type.BOOLEAN:
goals.add(createGoal(className, methodName, i, argType, BOOL_TRUE));
goals.add(createGoal(className, methodName, i, argType, BOOL_FALSE));
break;
case Type.CHAR:
goals.add(createGoal(className, methodName, i, argType, CHAR_ALPHA));
goals.add(createGoal(className, methodName, i, argType, CHAR_DIGIT));
goals.add(createGoal(className, methodName, i, argType, CHAR_OTHER));
break;
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
goals.add(createGoal(className, methodName, i, argType, NUM_NEGATIVE));
goals.add(createGoal(className, methodName, i, argType, NUM_ZERO));
goals.add(createGoal(className, methodName, i, argType, NUM_POSITIVE));
break;
case Type.ARRAY:
goals.add(createGoal(className, methodName, i, argType, REF_NULL));
goals.add(createGoal(className, methodName, i, argType, ARRAY_EMPTY));
goals.add(createGoal(className, methodName, i, argType, ARRAY_NONEMPTY));
break;
case Type.OBJECT:
goals.add(createGoal(className, methodName, i, argType, REF_NULL));
if (argType.getClassName().equals("java.lang.String")) {
goals.add(createGoal(className, methodName, i, argType, STRING_EMPTY));
goals.add(createGoal(className, methodName, i, argType, STRING_NONEMPTY));
} else if(List.class.isAssignableFrom(argumentClasses[i])) {
goals.add(createGoal(className, methodName, i, argType, LIST_EMPTY));
goals.add(createGoal(className, methodName, i, argType, LIST_NONEMPTY));
} else if(Set.class.isAssignableFrom(argumentClasses[i])) {
goals.add(createGoal(className, methodName, i, argType, SET_EMPTY));
goals.add(createGoal(className, methodName, i, argType, SET_NONEMPTY));
} else if(Map.class.isAssignableFrom(argumentClasses[i])) {
goals.add(createGoal(className, methodName, i, argType, MAP_EMPTY));
goals.add(createGoal(className, methodName, i, argType, MAP_NONEMPTY));
// TODO: Collection.class?
} else {
boolean observerGoalsAdded = false;
Class<?> paramClazz = argumentClasses[i];
for(Inspector inspector : InspectorManager.getInstance().getInspectors(paramClazz)) {
String insp = inspector.getMethodCall() + Type.getMethodDescriptor(inspector.getMethod());
Type t = Type.getReturnType(inspector.getMethod());
if (t.getSort() == Type.BOOLEAN) {
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL + ":" + argType.getClassName() + ":" + insp + ":" + BOOL_TRUE));
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL + ":" + argType.getClassName() + ":" + insp + ":" + BOOL_FALSE));
observerGoalsAdded = true;
} else if (Arrays.asList(new Integer[]{Type.BYTE, Type.SHORT, Type.INT, Type.FLOAT, Type.LONG, Type.DOUBLE}).contains(t.getSort())) {
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL + ":" + argType.getClassName() + ":" + insp + ":" + NUM_NEGATIVE));
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL + ":" + argType.getClassName() + ":" + insp + ":" + NUM_ZERO));
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL + ":" + argType.getClassName() + ":" + insp + ":" + NUM_POSITIVE));
observerGoalsAdded = true;
}
}
if (!observerGoalsAdded){
goals.add(createGoal(className, methodName, i, argType, REF_NONNULL)); goals.add(createGoal(className, methodName, i, argType, REF_NONNULL));
}
}
break;
default:
break;
}
}
}
private static void enhanceForGetValuePrimitive(ClassVisitor cw, String accessClassNm, String clazzNm, Field[] fields, Type type) {
String methodName;
final String typeNm = type.getDescriptor();
final int instruction;
switch (type.getSort()) {
case Type.BOOLEAN:
methodName = "getBooleanValue";
instruction = IRETURN;
break;
case Type.BYTE:
methodName = "getByteValue";
instruction = IRETURN;
break;
case Type.CHAR:
methodName = "getCharValue";
instruction = IRETURN;
break;
case Type.SHORT:
methodName = "getShortValue";
instruction = IRETURN;
break;
case Type.INT:
methodName = "getIntValue";
instruction = IRETURN;
break;
case Type.FLOAT:
methodName = "getFloatValue";
instruction = FRETURN;
break;
case Type.LONG:
methodName = "getLongValue";
instruction = LRETURN;
break;
case Type.DOUBLE:
methodName = "getDoubleValue";
instruction = DRETURN;
break;
default:
methodName = "getValue";
instruction = ARETURN;
break;
}
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(Ljava/lang/Object;Ljava/lang/String;)" + typeNm, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, accessClassNm, "fieldNames", "[Ljava/lang/String;");
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "binarySearch", "([Ljava/lang/Object;Ljava/lang/Object;)I");
mv.visitVarInsn(ISTORE, 3);
mv.visitVarInsn(ILOAD, 3);
final int maxStack;
if (fields.length > 0) {
maxStack = 5;
Label[] labels = constructLabels(fields);
Label defaultLabel = new Label();
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
for (int i = 0, n = labels.length; i < n; i++) {
Field field = fields[i];
mv.visitLabel(labels[i]);
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, clazzNm);
mv.visitFieldInsn(GETFIELD, clazzNm, field.getName(), typeNm);
mv.visitInsn(instruction);
}
mv.visitLabel(defaultLabel);
mv.visitFrame(F_SAME, 0, null, 0, null);
} else {
maxStack = 6;
}
enhanceForThrowingException(mv, IllegalArgumentException.class, "Field was not found", "Ljava/lang/Object;", ALOAD, 2);
mv.visitMaxs(maxStack, 4);
mv.visitEnd();
}
/**
* Compute sizes required for the storage arrays that will contain the local variables table at this frame.
* @param frame frame to compute for
* @return size required by each storage array
* @throws NullPointerException if any argument is {@code null}
*/
public static StorageSizes computeSizes(Frame<BasicValue> frame) {
Validate.notNull(frame);
// Count size required for each storage array
int intsSize = 0;
int longsSize = 0;
int floatsSize = 0;
int doublesSize = 0;
int objectsSize = 0;
for (int i = 0; i < frame.getLocals(); i++) {
BasicValue basicValue = frame.getLocal(i);
Type type = basicValue.getType();
// If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return '.'. This means that this
// slot contains nothing to save. So, skip this slot if we encounter it.
if (type == null) {
continue;
}
// If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
// the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
// point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot, thereby
// keeping the same 'Lnull;' type.
if ("Lnull;".equals(type.getDescriptor())) {
continue;
}
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
intsSize++;
break;
case Type.FLOAT:
floatsSize++;
break;
case Type.LONG:
longsSize++;
break;
case Type.DOUBLE:
doublesSize++;
break;
case Type.ARRAY:
case Type.OBJECT:
objectsSize++;
break;
case Type.METHOD:
case Type.VOID:
default:
throw new IllegalStateException();
}
}
return new StorageSizes(intsSize, longsSize, floatsSize, doublesSize, objectsSize);
}
public static boolean isPrimitive(Type type) {
return type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.DOUBLE;
}