下面列出了org.objectweb.asm.Type#INT 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Insert the necessary methods to box a primitive type (if the given type
* is a primitive object).
*
* @param mv The method visitor
* @param type The type to unbox
*/
public static void visitBoxingMethod(MethodVisitor mv, Type type) {
if (type.getSort() == Type.BOOLEAN) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
} else if (type.getSort() == Type.INT) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
} else if (type.getSort() == Type.BYTE) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
} else if (type.getSort() == Type.SHORT) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
} else if (type.getSort() == Type.LONG) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
} else if (type.getSort() == Type.FLOAT) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
} else if (type.getSort() == Type.DOUBLE) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
} else if (type.getSort() == Type.CHAR) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
}
}
public static int getVariableStoreOpcode(Type type) {
if (type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.INT) {
return Opcodes.ISTORE;
} else if (type == Type.LONG_TYPE) {
return Opcodes.LSTORE;
} else if (type == Type.FLOAT_TYPE) {
return Opcodes.FSTORE;
} else if (type == Type.DOUBLE_TYPE) {
return Opcodes.DSTORE;
} else if (type.getSort() >= Type.ARRAY && type.getSort() <= Type.OBJECT) {
return Opcodes.ASTORE;
} else {
return getVariableStoreOpcode(asSimpleType(type));
// throw new IllegalArgumentException(type.toString());
}
}
private void boxingIfShould(final String desc) {
switch (Type.getType(desc).getSort()) {
case Type.BOOLEAN:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
break;
case Type.BYTE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case Type.CHAR:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
break;
case Type.SHORT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
break;
case Type.INT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
break;
case Type.FLOAT:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
break;
case Type.LONG:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
break;
case Type.DOUBLE:
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
break;
}
}
private static void initType(int offset, Type t, DirectSorter v) {
switch(t.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
v.visitInsn(Opcodes.ICONST_0);
v.directVarInsn(Opcodes.ISTORE, offset);
break;
case Type.LONG:
v.visitInsn(Opcodes.LCONST_0);
v.directVarInsn(Opcodes.LSTORE, offset);
break;
case Type.FLOAT:
v.visitInsn(Opcodes.FCONST_0);
v.directVarInsn(Opcodes.FSTORE, offset);
break;
case Type.DOUBLE:
v.visitInsn(Opcodes.DCONST_0);
v.directVarInsn(Opcodes.DSTORE, offset);
break;
case Type.OBJECT:
v.visitInsn(Opcodes.ACONST_NULL);
v.directVarInsn(Opcodes.ASTORE, offset);
break;
default:
throw new UnsupportedOperationException();
}
}
/**
* 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 int getReturnOpcode(Type type) {
if (type.getSort() >= Type.BOOLEAN && type.getSort() <= Type.INT) {
return Opcodes.IRETURN;
} else if (type == Type.LONG_TYPE) {
return Opcodes.LRETURN;
} else if (type == Type.FLOAT_TYPE) {
return Opcodes.FRETURN;
} else if (type == Type.DOUBLE_TYPE) {
return Opcodes.DRETURN;
} else if (type.getSort() >= Type.ARRAY && type.getSort() <= Type.OBJECT) {
return Opcodes.ARETURN;
} else {
throw new IllegalArgumentException(type.toString());
}
}
@Override
public BasicValue newValue(final Type type)
{
if(type == null)
return new BasicValue(Type.getType("java/lang/Object"));
switch(type.getSort())
{
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return BasicValue.INT_VALUE;
case Type.FLOAT:
return BasicValue.FLOAT_VALUE;
case Type.LONG:
return BasicValue.LONG_VALUE;
case Type.DOUBLE:
return BasicValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return new BasicValue(type);
default:
throw new Error("Internal error");
}
}
/**
* 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;
}
}
}
private void checkType(Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
case Type.LONG:
case Type.FLOAT:
case Type.DOUBLE:
case Type.VOID:
return; // Ignore primitive types.
case Type.ARRAY:
checkType(type.getElementType());
return;
case Type.METHOD:
for (Type argumentType : type.getArgumentTypes()) {
checkType(argumentType);
}
checkType(type.getReturnType());
return;
case Type.OBJECT:
checkInternalName(type.getInternalName());
return;
default:
throw new UnsupportedOperationException("Unhandled type: " + type);
}
}
@Override
public Type getType() {
Type t = expression.getType();
if (t.getSort() >= Type.BOOLEAN && t.getSort() <= Type.INT) {
return Type.INT_TYPE;
} else if (t == Type.LONG_TYPE || t == Type.FLOAT_TYPE || t == Type.DOUBLE_TYPE) {
return t;
} else {
throw new IllegalArgumentException(t.toString());
}
}
/**
* Copies a local variable on to the stack.
* @param variable variable within the local variable table to load from
* @return instructions to load a local variable on to the stack
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if {@code variable} has been released
*/
public static InsnList loadVar(Variable variable) {
Validate.notNull(variable);
InsnList ret = new InsnList();
switch (variable.getType().getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
ret.add(new VarInsnNode(Opcodes.ILOAD, variable.getIndex()));
break;
case Type.LONG:
ret.add(new VarInsnNode(Opcodes.LLOAD, variable.getIndex()));
break;
case Type.FLOAT:
ret.add(new VarInsnNode(Opcodes.FLOAD, variable.getIndex()));
break;
case Type.DOUBLE:
ret.add(new VarInsnNode(Opcodes.DLOAD, variable.getIndex()));
break;
case Type.OBJECT:
case Type.ARRAY:
ret.add(new VarInsnNode(Opcodes.ALOAD, variable.getIndex()));
// If required, do it outside this method
// ret.add(new TypeInsnNode(Opcodes.CHECKCAST, variable.getType().getInternalName()));
break;
default:
throw new IllegalStateException(); // should never happen, there is code in Variable/VariableTable to make sure invalid
// types aren't set
}
return ret;
}
@Override
public BasicValue newValue(final Type type) {
if (type == null) {
return BasicValue.UNINITIALIZED_VALUE;
}
switch (type.getSort()) {
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return BasicValue.INT_VALUE;
case Type.FLOAT:
return BasicValue.FLOAT_VALUE;
case Type.LONG:
return BasicValue.LONG_VALUE;
case Type.DOUBLE:
return BasicValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return BasicValue.REFERENCE_VALUE;
default:
throw new AssertionError();
}
}
/**
* Generates the instructions to unbox the top stack value. This value is replaced by its unboxed
* equivalent on top of the stack.
*
* @param type the type of the top stack value.
*/
public void unbox(final Type type) {
Type boxedType = NUMBER_TYPE;
Method unboxMethod;
switch (type.getSort()) {
case Type.VOID:
return;
case Type.CHAR:
boxedType = CHARACTER_TYPE;
unboxMethod = CHAR_VALUE;
break;
case Type.BOOLEAN:
boxedType = BOOLEAN_TYPE;
unboxMethod = BOOLEAN_VALUE;
break;
case Type.DOUBLE:
unboxMethod = DOUBLE_VALUE;
break;
case Type.FLOAT:
unboxMethod = FLOAT_VALUE;
break;
case Type.LONG:
unboxMethod = LONG_VALUE;
break;
case Type.INT:
case Type.SHORT:
case Type.BYTE:
unboxMethod = INT_VALUE;
break;
default:
unboxMethod = null;
break;
}
if (unboxMethod == null) {
checkCast(type);
} else {
checkCast(boxedType);
invokeVirtual(boxedType, unboxMethod);
}
}
/**
* Creates an array of {@link Class} objects with the same size of the array of the passed
* parameter types. For each parameter type, stores its {@link Class} object into the result
* array. For intrinsic types which are not present in the class constant pool, just push
* the actual {@link Type} object on the stack and let ASM do the rest. For non intrinsic
* type use a {@link MethodVisitor#visitLdcInsn(Object)} to ensure the referenced class's
* presence in this class constant pool.
*
* <p>Stack Before : nothing of interest Stack After : /array of {@link Class}/
*
* @param parameterTypes a method list of parameters.
*/
private void pushParameterTypesOnStack(Type[] parameterTypes) {
push(parameterTypes.length);
newArray(Type.getType(Class.class));
for (int i = 0; i < parameterTypes.length; i++) {
dup();
push(i);
switch(parameterTypes[i].getSort()) {
case Type.OBJECT:
case Type.ARRAY:
visitLdcInsn(parameterTypes[i]);
break;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.LONG:
case Type.FLOAT:
case Type.DOUBLE:
push(parameterTypes[i]);
break;
default:
throw new RuntimeException(
"Unexpected parameter type " + parameterTypes[i]);
}
arrayStore(Type.getType(Class.class));
}
}
@Override
public BasicValue newValue(final Type type) {
if (type == null) {
return BasicValue.UNINITIALIZED_VALUE;
}
switch (type.getSort()) {
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return BasicValue.INT_VALUE;
case Type.FLOAT:
return BasicValue.FLOAT_VALUE;
case Type.LONG:
return BasicValue.LONG_VALUE;
case Type.DOUBLE:
return BasicValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return BasicValue.REFERENCE_VALUE;
default:
throw new AssertionError();
}
}
/**
* 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);
}
}
}
public void emitNewArray(TypeWidget elementType, BytecodeExpression e) {
MethodVisitor mv = getMethodVisitor();
exec(e);
cast(BaseTypeAdapter.INT32, e.getType());
switch (elementType.getJVMType().getSort()) {
case Type.BYTE:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE);
break;
case Type.BOOLEAN:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
break;
case Type.SHORT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_SHORT);
break;
case Type.INT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT);
break;
case Type.CHAR:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_CHAR);
break;
case Type.FLOAT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_FLOAT);
break;
case Type.LONG:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_LONG);
break;
case Type.DOUBLE:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_DOUBLE);
break;
case Type.OBJECT:
mv.visitTypeInsn(Opcodes.ANEWARRAY, elementType.getJVMType().getInternalName());
break;
default:
throw new UnsupportedOperationException("unknown sort for newArray" + elementType.getJVMType());
}
}
private void detailLocals(ContinuationPoint cp, MethodNode methodNode, StringBuilder output) {
int intIdx = 0;
int floatIdx = 0;
int doubleIdx = 0;
int longIdx = 0;
int objectIdx = 0;
for (int j = 0; j < cp.getFrame().getLocals(); j++) {
BasicValue local = cp.getFrame().getLocal(j);
if (local.getType() == null) {
// unused in frame, so skip over it
continue;
}
LocalVariableNode lvn = findLocalVariableNodeForInstruction(
methodNode.localVariables,
methodNode.instructions,
cp.getInvokeInstruction(),
j);
String name;
if (lvn == null || lvn.name == null) {
name = "???????";
} else {
name = lvn.name;
}
String accessor;
String type = null;
switch (local.getType().getSort()) {
case Type.INT:
accessor = "varInts[" + intIdx + "]";
type = "int";
intIdx++;
break;
case Type.FLOAT:
accessor = "varFloats[" + floatIdx + "]";
type = "float";
floatIdx++;
break;
case Type.LONG:
accessor = "varLongs[" + longIdx + "]";
type = "long";
longIdx++;
break;
case Type.DOUBLE:
accessor = "varDoubles[" + doubleIdx + "]";
type = "double";
doubleIdx++;
break;
case Type.ARRAY:
case Type.OBJECT:
accessor = "varObjects[" + objectIdx + "]";
type = local.getType().toString();
objectIdx++;
break;
default:
throw new IllegalStateException(local.getType().toString()); // should never happen
}
String line = String.format(Locale.ENGLISH, " %-20s // LVT index is %d / name is %s / type is %s",
accessor,
j,
name,
type);
output.append(line).append('\n');
}
}
final protected void checkCastReturn(Type returnType) {
final int sort = returnType.getSort();
switch (sort) {
case Type.VOID: {
pop();
mv.visitInsn(Opcodes.RETURN);
break;
}
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT: {
unbox(returnType);
returnValue();
break;
}
case Type.FLOAT: {
unbox(returnType);
mv.visitInsn(Opcodes.FRETURN);
break;
}
case Type.LONG: {
unbox(returnType);
mv.visitInsn(Opcodes.LRETURN);
break;
}
case Type.DOUBLE: {
unbox(returnType);
mv.visitInsn(Opcodes.DRETURN);
break;
}
case Type.ARRAY:
case Type.OBJECT:
case Type.METHOD:
default: {
// checkCast(returnType);
unbox(returnType);
mv.visitInsn(ARETURN);
break;
}
}
}
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;
}