/** * Returns the number of dimensions of arrays to be created. * If the opcode is multianewarray, this method returns the second * operand. Otherwise, it returns 1. */ public int getCreatedDimensions() { if (opcode == Opcode.MULTIANEWARRAY) return iterator.byteAt(currentPos + 3); else return 1; }
private int canReplace() throws CannotCompileException { int op = iterator.byteAt(newPos + 3); if (op == Opcode.DUP) // Typical single DUP or Javaflow DUP DUP2_X2 POP2 return ((iterator.byteAt(newPos + 4) == Opcode.DUP2_X2 && iterator.byteAt(newPos + 5) == Opcode.POP2)) ? 6 : 4; else if (op == Opcode.DUP_X1 && iterator.byteAt(newPos + 4) == Opcode.SWAP) return 5; else return 3; // for Eclipse. The generated code may include no DUP. // throw new CannotCompileException( // "sorry, cannot edit NEW followed by no DUP"); }
/** * Returns the number of dimensions of arrays to be created. * If the opcode is multianewarray, this method returns the second * operand. Otherwise, it returns 1. */ public int getCreatedDimensions() { if (opcode == Opcode.MULTIANEWARRAY) return iterator.byteAt(currentPos + 3); return 1; }
private int canReplace() throws CannotCompileException { int op = iterator.byteAt(newPos + 3); if (op == Opcode.DUP) // Typical single DUP or Javaflow DUP DUP2_X2 POP2 return ((iterator.byteAt(newPos + 4) == Opcode.DUP2_X2 && iterator.byteAt(newPos + 5) == Opcode.POP2)) ? 6 : 4; else if (op == Opcode.DUP_X1 && iterator.byteAt(newPos + 4) == Opcode.SWAP) return 5; else return 3; // for Eclipse. The generated code may include no DUP. // throw new CannotCompileException( // "sorry, cannot edit NEW followed by no DUP"); }
private static String wide(CodeIterator iter, int pos) { int opcode = iter.byteAt(pos + 1); int index = iter.u16bitAt(pos + 2); switch (opcode) { case ILOAD: case LLOAD: case FLOAD: case DLOAD: case ALOAD: case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: case IINC: case RET: return opcodes[opcode] + " " + index; default: throw new RuntimeException("Invalid WIDE operand"); } }
public static int getJumpTarget(int pos, CodeIterator iter) { int opcode = iter.byteAt(pos); pos += (opcode == JSR_W || opcode == GOTO_W) ? iter.s32bitAt(pos + 1) : iter.s16bitAt(pos + 1); return pos; }
/** * Returns true if the called method is of a superclass of the current * class. */ public boolean isSuper() { return iterator.byteAt(currentPos) == INVOKESPECIAL && !where().getDeclaringClass().getName().equals(getClassName()); }
public static int getJumpTarget(int pos, CodeIterator iter) { int opcode = iter.byteAt(pos); pos += (opcode == JSR_W || opcode == GOTO_W) ? iter.s32bitAt(pos + 1) : iter.s16bitAt(pos + 1); return pos; }
/** * Returns true if the called method is of a superclass of the current * class. */ public boolean isSuper() { return iterator.byteAt(currentPos) == INVOKESPECIAL && !where().getDeclaringClass().getName().equals(getClassName()); }
private int getNameAndType(ConstPool cp) { int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) return cp.getInterfaceMethodrefNameAndType(index); else return cp.getMethodrefNameAndType(index); }
private void evalNewObjectArray(int pos, CodeIterator iter, Frame frame) throws BadBytecode { // Convert to x[] format Type type = resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1))); String name = type.getCtClass().getName(); int opcode = iter.byteAt(pos); int dimensions; if (opcode == MULTIANEWARRAY) { dimensions = iter.byteAt(pos + 3); } else { name = name + "[]"; dimensions = 1; } while (dimensions-- > 0) { verifyAssignable(Type.INTEGER, simplePop(frame)); } simplePush(getType(name), frame); }
private int getNameAndType(ConstPool cp) { int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) return cp.getInterfaceMethodrefNameAndType(index); return cp.getMethodrefNameAndType(index); }
/** * Returns the class name of the target object, * which the method is called on. */ public String getClassName() { String cname; ConstPool cp = getConstPool(); int pos = currentPos; int c = iterator.byteAt(pos); int index = iterator.u16bitAt(pos + 1); if (c == INVOKEINTERFACE) cname = cp.getInterfaceMethodrefClassName(index); else cname = cp.getMethodrefClassName(index); if (cname.charAt(0) == '[') cname = Descriptor.toClassName(cname); return cname; }
private static void shiftIndex8(CodeIterator ci, int index, int opcode, int lessThan, int delta) throws BadBytecode { int var = ci.byteAt(index + 1); if (var < lessThan) return; var += delta; if (var < 0x100) ci.writeByte(var, index + 1); else { int pos = ci.insertExGap(2); ci.writeByte(WIDE, pos - 2); ci.writeByte(opcode, pos - 1); ci.write16bit(var, pos); } }
/** * Returns the type of array components. If the created array is * a two-dimensional array of <tt>int</tt>, * the type returned by this method is * not <tt>int[]</tt> but <tt>int</tt>. */ public CtClass getComponentType() throws NotFoundException { if (opcode == Opcode.NEWARRAY) { int atype = iterator.byteAt(currentPos + 1); return getPrimitiveType(atype); } else if (opcode == Opcode.ANEWARRAY || opcode == Opcode.MULTIANEWARRAY) { int index = iterator.u16bitAt(currentPos + 1); String desc = getConstPool().getClassInfo(index); int dim = Descriptor.arrayDimension(desc); desc = Descriptor.toArrayComponent(desc, dim); return Descriptor.toCtClass(desc, thisClass.getClassPool()); } else throw new RuntimeException("bad opcode: " + opcode); }
/** * Returns true if the method body is empty, that is, <code>{}</code>. * It also returns true if the method is an abstract method. */ public boolean isEmpty() { CodeAttribute ca = getMethodInfo2().getCodeAttribute(); if (ca == null) // abstract or native return (getModifiers() & Modifier.ABSTRACT) != 0; CodeIterator it = ca.iterator(); try { return it.hasNext() && it.byteAt(it.next()) == Opcode.RETURN && !it.hasNext(); } catch (BadBytecode e) {} return false; }
/** * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL * so that a different method is invoked. The class name in the operand * of these instructions might be a subclass of the target class specified * by <code>classname</code>. This method transforms the instruction * in that case unless the subclass overrides the target method. */ public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode { int c = iterator.byteAt(pos); if (c == INVOKEINTERFACE || c == INVOKESPECIAL || c == INVOKESTATIC || c == INVOKEVIRTUAL) { int index = iterator.u16bitAt(pos + 1); String cname = cp.eqMember(methodname, methodDescriptor, index); if (cname != null && matchClass(cname, clazz.getClassPool())) { int ntinfo = cp.getMemberNameAndType(index); pos = match(c, pos, iterator, cp.getNameAndTypeDescriptor(ntinfo), cp); } } return pos; }
private void visitBytecode(CodeIterator ci, int[] stack, int index) throws BadBytecode { int codeLength = stack.length; ci.move(index); int stackDepth = -stack[index]; int[] jsrDepth = new int[1]; jsrDepth[0] = -1; while (ci.hasNext()) { index = ci.next(); stack[index] = stackDepth; int op = ci.byteAt(index); stackDepth = visitInst(op, ci, index, stackDepth); if (stackDepth < 1) throw new BadBytecode("stack underflow at " + index); if (processBranch(op, ci, index, codeLength, stack, stackDepth, jsrDepth)) break; if (isEnd(op)) // return, ireturn, athrow, ... break; if (op == JSR || op == JSR_W) --stackDepth; } }
public int transform(CtClass tclazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode { int c = iterator.byteAt(pos); if (c == GETFIELD || c == GETSTATIC) { int index = iterator.u16bitAt(pos + 1); String typedesc = isField(tclazz.getClassPool(), cp, fieldClass, fieldname, isPrivate, index); if (typedesc != null) { if (c == GETSTATIC) { iterator.move(pos); pos = iterator.insertGap(1); // insertGap() may insert 4 bytes. iterator.writeByte(ACONST_NULL, pos); pos = iterator.next(); } String type = "(Ljava/lang/Object;)" + typedesc; int mi = cp.addClassInfo(methodClassname); int methodref = cp.addMethodrefInfo(mi, methodName, type); iterator.writeByte(INVOKESTATIC, pos); iterator.write16bit(methodref, pos + 1); return pos; } } return pos; } }
protected int match2(int pos, CodeIterator iterator) throws BadBytecode { iterator.move(pos); iterator.insert(saveCode); iterator.insert(loadCode); int p = iterator.insertGap(3); iterator.setMark(p); iterator.insert(loadCode); pos = iterator.next(); p = iterator.getMark(); iterator.writeByte(iterator.byteAt(pos), p); iterator.write16bit(iterator.u16bitAt(pos + 1), p + 1); iterator.writeByte(INVOKESTATIC, pos); iterator.write16bit(newIndex, pos + 1); iterator.move(p); return iterator.next(); } }