下面列出了org.objectweb.asm.Opcodes# CHECKCAST 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visitTypeInsn(final int opcode, final String type) {
Type objectType = Type.getObjectType(type);
switch (opcode) {
case Opcodes.NEW:
anew(objectType);
break;
case Opcodes.ANEWARRAY:
newarray(objectType);
break;
case Opcodes.CHECKCAST:
checkcast(objectType);
break;
case Opcodes.INSTANCEOF:
instanceOf(objectType);
break;
default:
throw new IllegalArgumentException();
}
}
public InsnValue casting(TypeInsnNode tin, InsnValue value) {
switch (tin.getOpcode()) {
case Opcodes.CHECKCAST:
return value;
case Opcodes.INSTANCEOF:
if (value.getValue() == null) {
return InsnValue.intValue(0);
}
Class<?> clazz = value.getValue().getClass();
try {
Class<?> compared = Class.forName(Type.getType(tin.desc).getClassName());
return InsnValue.intValue(clazz.isAssignableFrom(compared));
} catch (ClassNotFoundException e) {
}
return InsnValue.intValue(0);
}
return null;
}
@Override
public void visitTypeInsn(final int opcode, final String type) {
Type objectType = Type.getObjectType(type);
switch (opcode) {
case Opcodes.NEW:
anew(objectType);
break;
case Opcodes.ANEWARRAY:
newarray(objectType);
break;
case Opcodes.CHECKCAST:
checkcast(objectType);
break;
case Opcodes.INSTANCEOF:
instanceOf(objectType);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitTypeInsn(final int opcode, final String type) {
Type objectType = Type.getObjectType(type);
switch (opcode) {
case Opcodes.NEW:
anew(objectType);
break;
case Opcodes.ANEWARRAY:
newarray(objectType);
break;
case Opcodes.CHECKCAST:
checkcast(objectType);
break;
case Opcodes.INSTANCEOF:
instanceOf(objectType);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitTypeInsn(final int opcode, final String type) {
Type objectType = Type.getObjectType(type);
switch (opcode) {
case Opcodes.NEW:
anew(objectType);
break;
case Opcodes.ANEWARRAY:
newarray(objectType);
break;
case Opcodes.CHECKCAST:
checkcast(objectType);
break;
case Opcodes.INSTANCEOF:
instanceOf(objectType);
break;
default:
throw new IllegalArgumentException();
}
}
/**
* If the supplied instruction is a constant, returns the constant value
* from the instruction
*
* @param insn constant instruction to process
* @return the constant value or <tt>null</tt> if the value cannot be parsed
* (<tt>null</tt> constant is returned as <tt>Type.VOID_TYPE</tt>)
*/
public static Object getConstant(AbstractInsnNode insn) {
if (insn == null) {
return null;
} else if (insn instanceof LdcInsnNode) {
return ((LdcInsnNode)insn).cst;
} else if (insn instanceof IntInsnNode) {
int value = ((IntInsnNode)insn).operand;
if (insn.getOpcode() == Opcodes.BIPUSH || insn.getOpcode() == Opcodes.SIPUSH) {
return Integer.valueOf(value);
}
throw new IllegalArgumentException("IntInsnNode with invalid opcode " + insn.getOpcode() + " in getConstant");
} else if (insn instanceof TypeInsnNode) {
if (insn.getOpcode() < Opcodes.CHECKCAST) {
return null; // Don't treat NEW and ANEWARRAY as constants
}
return Type.getObjectType(((TypeInsnNode)insn).desc);
}
int index = Ints.indexOf(Bytecode.CONSTANTS_ALL, insn.getOpcode());
return index < 0 ? null : Bytecode.CONSTANTS_VALUES[index];
}
/**
* Transforms type operations (eg. cast, instanceof) in the method being
* processed. Changes references to mixin classes to that of the appropriate
* class for this context.
*
* @param method Method being processed
* @param iter Insn interator
* @param typeInsn Insn to transform
* @param lastNode Last insn in the method
*/
private void transformTypeNode(MethodNode method, Iterator<AbstractInsnNode> iter, TypeInsnNode typeInsn, AbstractInsnNode lastNode) {
if (typeInsn.getOpcode() == Opcodes.CHECKCAST
&& typeInsn.desc.equals(this.getTarget().getClassRef())
&& lastNode.getOpcode() == Opcodes.ALOAD
&& ((VarInsnNode)lastNode).var == 0) {
iter.remove();
return;
}
if (typeInsn.desc.equals(this.getClassRef())) {
typeInsn.desc = this.getTarget().getClassRef();
} else {
String newName = this.innerClasses.get(typeInsn.desc);
if (newName != null) {
typeInsn.desc = newName;
}
}
this.transformDescriptor(typeInsn);
}
@Override
public void visitMethodInsn(
int opcode, String owner, String name, String descriptor, boolean isInterface) {
MethodKey methodKey = MethodKey.create(ClassName.create(owner), name, descriptor);
if (methodInvocationMappings.containsKey(methodKey)) {
MethodKey mappedMethodKey = methodInvocationMappings.get(methodKey);
super.visitMethodInsn(
opcode,
mappedMethodKey.ownerName(),
mappedMethodKey.name(),
mappedMethodKey.descriptor(),
isInterface);
super.visitTypeInsn(Opcodes.CHECKCAST, owner);
return;
}
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
@Override
public void visitTypeInsn(int opcode, String type) {
String descriptor = convertToDescriptor(type);
switch (opcode) {
case Opcodes.NEW:
// This should be UNINITIALIZED(label). Okay for type inference.
pushDescriptor(descriptor);
break;
case Opcodes.ANEWARRAY:
pop();
pushDescriptor('[' + descriptor);
break;
case Opcodes.CHECKCAST:
pop();
pushDescriptor(descriptor);
break;
case Opcodes.INSTANCEOF:
pop();
push(InferredType.INT);
break;
default:
throw new RuntimeException("Unhandled opcode " + opcode);
}
super.visitTypeInsn(opcode, type);
}
/**
* @param opcode
* @param type
* @param s
*/
static void handleJVMTypeInsn ( int opcode, String type, JVMStackState s ) {
BaseType o;
switch ( opcode ) {
case Opcodes.NEW:
s.push(new ObjectReferenceConstant(false, Type.getObjectType(type), type.replace('/', '.')));
break;
case Opcodes.ANEWARRAY:
s.pop();
if ( type.charAt(0) == '[' ) {
s.push(new BasicVariable(Type.getObjectType("[" + type), "array", false)); //$NON-NLS-1$//$NON-NLS-2$
}
else {
s.push(new BasicVariable(Type.getObjectType("[L" + type + ";"), "array", false)); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
}
break;
case Opcodes.CHECKCAST:
if ( log.isDebugEnabled() ) {
log.debug("Checkcast " + type); //$NON-NLS-1$
}
o = s.pop();
if ( o != null ) {
o.addAlternativeType(Type.getObjectType(type));
s.push(o);
}
else {
s.clear();
}
break;
case Opcodes.INSTANCEOF:
o = s.pop();
if ( o != null ) {
o.addAlternativeType(Type.getObjectType(type));
}
s.push(new BasicConstant(Type.BOOLEAN_TYPE, "typeof " + o + " = " + type, ! ( o != null ) || o.isTainted())); //$NON-NLS-1$ //$NON-NLS-2$
break;
}
}
/**
* Returns the {@link Type} of a particular constant instruction's payload
*
* @param insn constant instruction
* @return type of constant or <tt>null</tt> if it cannot be parsed (<tt>
* null</tt> constant is returned as <tt>Type.VOID_TYPE</tt>)
*/
public static Type getConstantType(AbstractInsnNode insn) {
if (insn == null) {
return null;
} else if (insn instanceof LdcInsnNode) {
Object cst = ((LdcInsnNode)insn).cst;
if (cst instanceof Integer) {
return Type.getType("I");
} else if (cst instanceof Float) {
return Type.getType("F");
} else if (cst instanceof Long) {
return Type.getType("J");
} else if (cst instanceof Double) {
return Type.getType("D");
} else if (cst instanceof String) {
return Type.getType(Constants.STRING_DESC);
} else if (cst instanceof Type) {
return Type.getType(Constants.CLASS_DESC);
}
throw new IllegalArgumentException("LdcInsnNode with invalid payload type " + cst.getClass() + " in getConstant");
} else if (insn instanceof TypeInsnNode) {
if (insn.getOpcode() < Opcodes.CHECKCAST) {
return null; // Don't treat NEW and ANEWARRAY as constants
}
return Type.getType(Constants.CLASS_DESC);
}
int index = Ints.indexOf(Bytecode.CONSTANTS_ALL, insn.getOpcode());
return index < 0 ? null : Type.getType(Bytecode.CONSTANTS_TYPES[index]);
}
private void mutateObjectReferenceReturn() {
if (shouldMutate("object reference", "[see docs for details]")) {
final Type returnType = this.methodInfo.getReturnType();
super.visitLdcInsn(returnType);
super.visitMethodInsn(Opcodes.INVOKESTATIC,
OBJECT_MUTATION_METHOD.getClassName(),
OBJECT_MUTATION_METHOD.getMethodName(),
OBJECT_MUTATION_METHOD.getMethodDescriptor(), false);
super.visitTypeInsn(Opcodes.CHECKCAST, returnType.getInternalName());
}
super.visitInsn(Opcodes.ARETURN);
}
public CheckCastFrame(Frame check) {
super(Opcodes.CHECKCAST);
this.check = check;
this.check.children.add(this);
this.parents.add(this.check);
}
@Override
public void appendInstruction(StringBuilder b, List<Instruction> l) {
type = type.replace('.', '_').replace('/', '_').replace('$', '_');
b.append(" ");
switch(opcode) {
case Opcodes.NEW:
b.append("PUSH_POINTER(__NEW_");
b.append(type);
b.append("(threadStateData)); /* NEW */\n");
break;
case Opcodes.ANEWARRAY:
if(type.startsWith("[")) {
int dim = 2;
String t = type.substring(1);
while(t.startsWith("[")) {
t = t.substring(1);
dim++;
}
b.append(" SP--;\n PUSH_POINTER(allocArray(threadStateData, (*SP).data.i, &class_array");
b.append(dim);
b.append("__");
b.append(actualType);
b.append(", sizeof(JAVA_OBJECT), ");
b.append(dim);
b.append("));\n SP[-1].data.o->__codenameOneParentClsReference = &class_array");
b.append(dim);
b.append("__");
b.append(actualType);
b.append("; /* ANEWARRAY multi */\n");
break;
}
b.append("SP--;\n PUSH_POINTER(__NEW_ARRAY_");
b.append(actualType);
b.append("(threadStateData, SP[0].data.i));\n");
break;
case Opcodes.CHECKCAST:
b.append("BC_CHECKCAST(");
b.append(type);
b.append(");\n");
break;
case Opcodes.INSTANCEOF:
int pos = type.indexOf('[');
if(pos > -1) {
int count = 1;
while(type.charAt(pos + 1) == '[') {
count++;
pos++;
}
b.append("BC_INSTANCEOF(cn1_array_");
b.append(count);
b.append("_id_");
b.append(actualType);
} else {
b.append("BC_INSTANCEOF(cn1_class_id_");
b.append(actualType);
}
b.append(");\n");
break;
}
}
/**
* Compares two synthetic bridge methods and throws an exception if they are
* not compatible.
*
* @param a Incumbent method
* @param b Incoming method
*/
public static void compareBridgeMethods(MethodNode a, MethodNode b) {
ListIterator<AbstractInsnNode> ia = a.instructions.iterator();
ListIterator<AbstractInsnNode> ib = b.instructions.iterator();
int index = 0;
for (; ia.hasNext() && ib.hasNext(); index++) {
AbstractInsnNode na = ia.next();
AbstractInsnNode nb = ib.next();
if (na instanceof LabelNode) {
continue;
}
if (na instanceof MethodInsnNode) {
MethodInsnNode ma = (MethodInsnNode)na;
MethodInsnNode mb = (MethodInsnNode)nb;
if (!ma.name.equals(mb.name)) {
throw new SyntheticBridgeException(Problem.BAD_INVOKE_NAME, a.name, a.desc, index, na, nb);
} else if (!ma.desc.equals(mb.desc)) {
throw new SyntheticBridgeException(Problem.BAD_INVOKE_DESC, a.name, a.desc, index, na, nb);
}
} else if (na.getOpcode() != nb.getOpcode()) {
throw new SyntheticBridgeException(Problem.BAD_INSN, a.name, a.desc, index, na, nb);
} else if (na instanceof VarInsnNode) {
VarInsnNode va = (VarInsnNode)na;
VarInsnNode vb = (VarInsnNode)nb;
if (va.var != vb.var) {
throw new SyntheticBridgeException(Problem.BAD_LOAD, a.name, a.desc, index, na, nb);
}
} else if (na instanceof TypeInsnNode) {
TypeInsnNode ta = (TypeInsnNode)na;
TypeInsnNode tb = (TypeInsnNode)nb;
if (ta.getOpcode() == Opcodes.CHECKCAST && !ta.desc.equals(tb.desc)) {
throw new SyntheticBridgeException(Problem.BAD_CAST, a.name, a.desc, index, na, nb);
}
}
}
if (ia.hasNext() || ib.hasNext()) {
throw new SyntheticBridgeException(Problem.BAD_LENGTH, a.name, a.desc, index, null, null);
}
}