下面列出了org.objectweb.asm.Opcodes# ICONST_0 ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Determine if the given opcode is a load of a constant (xCONST_y).
*
* @param opcode the opcode
* @return true if the opcode is one of the constant loading ones, false otherwise
*/
public static boolean isXconst(final int opcode) {
switch(opcode) {
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.ICONST_M1:
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
return true;
}
return false;
}
/**
* Given an integer, returns an InsnNode that will properly represent the int.
*
* @param i
* @return
*/
public static AbstractInsnNode toInt(int i) {
switch (i) {
case -1:
return new InsnNode(Opcodes.ICONST_M1);
case 0:
return new InsnNode(Opcodes.ICONST_0);
case 1:
return new InsnNode(Opcodes.ICONST_1);
case 2:
return new InsnNode(Opcodes.ICONST_2);
case 3:
return new InsnNode(Opcodes.ICONST_3);
case 4:
return new InsnNode(Opcodes.ICONST_4);
case 5:
return new InsnNode(Opcodes.ICONST_5);
}
if (i > -129 && i < 128) {
return new IntInsnNode(Opcodes.BIPUSH, i);
}
return new LdcInsnNode(i);
}
static void intOpcode(MethodVisitor mv, int input)
{
if(input ==-1){
mv.visitInsn(Opcodes.ICONST_M1);
} else if(input >= 0 && input <= 5) {
int res = Opcodes.ICONST_5;
switch(input)
{
case 0: res = Opcodes.ICONST_0; break;
case 1: res = Opcodes.ICONST_1; break;
case 2: res = Opcodes.ICONST_2; break;
case 3: res = Opcodes.ICONST_3; break;
case 4: res = Opcodes.ICONST_4; break;
}
mv.visitInsn(res);
} else if( -128 <= input && input <= 127){//8 bit
mv.visitIntInsn(Opcodes.BIPUSH, input);
} else if( -32768 <= input && input <= 32767){//16 bit
mv.visitIntInsn(Opcodes.SIPUSH, input);
} else{//32 bit - ldc
mv.visitLdcInsn(new Integer(input));
}
}
public static AbstractInsnNode getPushInstruction(int value) {
if (value == -1) {
return new InsnNode(Opcodes.ICONST_M1);
} else if (value == 0) {
return new InsnNode(Opcodes.ICONST_0);
} else if (value == 1) {
return new InsnNode(Opcodes.ICONST_1);
} else if (value == 2) {
return new InsnNode(Opcodes.ICONST_2);
} else if (value == 3) {
return new InsnNode(Opcodes.ICONST_3);
} else if (value == 4) {
return new InsnNode(Opcodes.ICONST_4);
} else if (value == 5) {
return new InsnNode(Opcodes.ICONST_5);
} else if ((value >= -128) && (value <= 127)) {
return new IntInsnNode(Opcodes.BIPUSH, value);
} else if ((value >= -32768) && (value <= 32767)) {
return new IntInsnNode(Opcodes.SIPUSH, value);
} else {
return new LdcInsnNode(value);
}
}
@Override
public boolean isConstant() {
switch (opcode) {
case Opcodes.ACONST_NULL:
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.ICONST_M1:
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
case Opcodes.LDC:
return true;
}
return super.isConstant();
}
/**
* Given an integer, returns an InsnNode that will properly represent the
* int.
*
* @param i
* @return
*/
public static AbstractInsnNode toInt(int i) {
switch (i) {
case -1:
return new InsnNode(Opcodes.ICONST_M1);
case 0:
return new InsnNode(Opcodes.ICONST_0);
case 1:
return new InsnNode(Opcodes.ICONST_1);
case 2:
return new InsnNode(Opcodes.ICONST_2);
case 3:
return new InsnNode(Opcodes.ICONST_3);
case 4:
return new InsnNode(Opcodes.ICONST_4);
case 5:
return new InsnNode(Opcodes.ICONST_5);
}
if (i > -129 && i < 128) {
return new IntInsnNode(Opcodes.BIPUSH, i);
}
return new LdcInsnNode(i);
}
/**
* Gets the integer value of a given opcode.
*
* @param opcode
* @return
*/
public static int getIntValue(int opcode) {
if (opcode == Opcodes.ICONST_0) {
return 0;
} else if (opcode == Opcodes.ICONST_1) {
return 1;
} else if (opcode == Opcodes.ICONST_2) {
return 2;
} else if (opcode == Opcodes.ICONST_3) {
return 3;
} else if (opcode == Opcodes.ICONST_4) {
return 4;
} else if (opcode == Opcodes.ICONST_5) {
return 5;
} else {
return -1;
}
}
private void mutatePrimitiveIntegerReturn() {
if (shouldMutate("primitive boolean/byte/short/integer",
"(x == 1) ? 0 : x + 1")) {
final Label label = new Label();
super.visitInsn(Opcodes.DUP);
super.visitInsn(Opcodes.ICONST_1);
super.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
super.visitInsn(Opcodes.ICONST_1);
super.visitInsn(Opcodes.IADD);
super.visitInsn(Opcodes.IRETURN);
super.visitLabel(label);
super.visitInsn(Opcodes.ICONST_0);
super.visitInsn(Opcodes.IRETURN);
}
}
public static void intOpcode(MethodVisitor mv, int input)
{//TODO: nasty copy paste
if(input ==-1)
{
mv.visitInsn(Opcodes.ICONST_M1);
}
else if(input > -1 && input <= 5)
{
int res = Opcodes.ICONST_5;
switch(input)
{
case 0: res = Opcodes.ICONST_0; break;
case 1: res = Opcodes.ICONST_1; break;
case 2: res = Opcodes.ICONST_2; break;
case 3: res = Opcodes.ICONST_3; break;
case 4: res = Opcodes.ICONST_4; break;
}
mv.visitInsn(res);
}
else if( -128 <= input && input <= 127)
{//8 bit
mv.visitIntInsn(Opcodes.BIPUSH, input);
}
else if( -32768 <= input && input <= 32767)
{//16 bit
mv.visitIntInsn(Opcodes.SIPUSH, input);
}
else
{//32 bit - ldc
mv.visitLdcInsn(new Integer(input));
}
}
@Test
public void test_checkTableSwitch() throws Exception {
List<BasicBlock> hashCodeBlocks = METHOD_BLOCKS.get("checkTableSwitch(I)I");
int[][] expectedHashCodeBlocks = new int[][]{
{Opcodes.ICONST_5, Opcodes.ISTORE, Opcodes.ILOAD, Opcodes.TABLESWITCH},
{Opcodes.ICONST_1, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_2, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_3, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_0, Opcodes.ISTORE},
{Opcodes.ILOAD, Opcodes.IRETURN},
};
int[][] expectedSwitchCounts = new int[][]{
{4},
{},
{},
{},
{},
{},
};
// Verify the shape of the blocks.
boolean didMatch = compareBlocks(expectedHashCodeBlocks, hashCodeBlocks);
Assert.assertTrue(didMatch);
// Verify the switch option value.
didMatch = compareSwitches(expectedSwitchCounts, hashCodeBlocks);
Assert.assertTrue(didMatch);
}
@Test
public void test_checkLookupSwitch() throws Exception {
List<BasicBlock> hashCodeBlocks = METHOD_BLOCKS.get("checkLookupSwitch(I)I");
int[][] expectedHashCodeBlocks = new int[][]{
{Opcodes.ICONST_5, Opcodes.ISTORE, Opcodes.ILOAD, Opcodes.LOOKUPSWITCH},
{Opcodes.ICONST_1, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_2, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_3, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_0, Opcodes.ISTORE},
{Opcodes.ILOAD, Opcodes.IRETURN},
};
int[][] expectedSwitchCounts = new int[][]{
{4},
{},
{},
{},
{},
{},
};
// Verify the shape of the blocks.
boolean didMatch = compareBlocks(expectedHashCodeBlocks, hashCodeBlocks);
Assert.assertTrue(didMatch);
// Verify the switch option value.
didMatch = compareSwitches(expectedSwitchCounts, hashCodeBlocks);
Assert.assertTrue(didMatch);
}
void translateToByteCode(final Integer constant) {
switch (constant) {
case -1:
super.visitInsn(Opcodes.ICONST_M1);
break;
case 0:
super.visitInsn(Opcodes.ICONST_0);
break;
case 1:
super.visitInsn(Opcodes.ICONST_1);
break;
case 2:
super.visitInsn(Opcodes.ICONST_2);
break;
case 3:
super.visitInsn(Opcodes.ICONST_3);
break;
case 4:
super.visitInsn(Opcodes.ICONST_4);
break;
case 5:
super.visitInsn(Opcodes.ICONST_5);
break;
default:
super.visitLdcInsn(constant);
break;
}
}
Number translateToNumber(final int opcode) {
switch (opcode) {
case Opcodes.ICONST_M1:
return Integer.valueOf(-1);
case Opcodes.ICONST_0:
return Integer.valueOf(0);
case Opcodes.ICONST_1:
return Integer.valueOf(1);
case Opcodes.ICONST_2:
return Integer.valueOf(2);
case Opcodes.ICONST_3:
return Integer.valueOf(3);
case Opcodes.ICONST_4:
return Integer.valueOf(4);
case Opcodes.ICONST_5:
return Integer.valueOf(5);
case Opcodes.LCONST_0:
return Long.valueOf(0L);
case Opcodes.LCONST_1:
return Long.valueOf(1L);
case Opcodes.FCONST_0:
return Float.valueOf(0F);
case Opcodes.FCONST_1:
return Float.valueOf(1F);
case Opcodes.FCONST_2:
return Float.valueOf(2F);
case Opcodes.DCONST_0:
return Double.valueOf(0D);
case Opcodes.DCONST_1:
return Double.valueOf(1D);
default:
return null;
}
}
private void translateToByteCode(final Integer constant) {
switch (constant) {
case -1:
super.visitInsn(Opcodes.ICONST_M1);
break;
case 0:
super.visitInsn(Opcodes.ICONST_0);
break;
case 1:
super.visitInsn(Opcodes.ICONST_1);
break;
case 2:
super.visitInsn(Opcodes.ICONST_2);
break;
case 3:
super.visitInsn(Opcodes.ICONST_3);
break;
case 4:
super.visitInsn(Opcodes.ICONST_4);
break;
case 5:
super.visitInsn(Opcodes.ICONST_5);
break;
default:
super.visitLdcInsn(constant);
break;
}
}
void calculateArrayLengthAndDispatch(String typeName, int dimCount) {
// Since the dimensions of the array are not known at instrumentation
// time, we take the created multi-dimensional array and peel off nesting
// levels from the left. For each nesting layer we probe the array length
// and accumulate a partial product which we can then feed the recording
// function.
// below we note the partial product of dimensions 1 to X-1 as productToX
// (so productTo1 == 1 == no dimensions yet). We denote by aref0 the
// array reference at the current nesting level (the containing aref's [0]
// element). If we hit a level whose arraylength is 0 or whose
// reference is null, there's no point continuing, so we shortcut
// out.
// This approach works pretty well when you create a new array with the
// newarray bytecodes. You can also create a new array by cloning an
// existing array; an existing multidimensional array might have had some
// of its [0] elements nulled out. We currently deal with this by bailing
// out, but arguably we should do something more principled (like calculate
// the size of the multidimensional array from scratch if you are using
// clone()).
// TODO(java-platform-team): Do something about modified multidimensional
// arrays and clone().
Label zeroDimension = new Label();
super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0
super.visitLdcInsn(1); // -> stack: ... origaref aref0 productTo1
for (int i = 0; i < dimCount; ++i) {
// pre: stack: ... origaref aref0 productToI
super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP);
Label nonNullDimension = new Label();
// -> stack: ... origaref productToI aref aref
super.visitJumpInsn(Opcodes.IFNONNULL, nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.SWAP);
// -> stack: ... origaref aref productToI
super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
super.visitLabel(nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP_X1);
// -> stack: ... origaref aref0 productToI aref
super.visitInsn(Opcodes.ARRAYLENGTH);
// -> stack: ... origaref aref0 productToI dimI
Label nonZeroDimension = new Label();
super.visitInsn(Opcodes.DUP);
// -> stack: ... origaref aref0 productToI dimI dimI
super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension);
// -> stack: ... origaref aref0 productToI dimI
super.visitInsn(Opcodes.POP);
// -> stack: ... origaref aref0 productToI
super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
super.visitLabel(nonZeroDimension);
// -> stack: ... origaref aref0 productToI max(dimI,1)
super.visitInsn(Opcodes.IMUL);
// -> stack: ... origaref aref0 productTo{I+1}
if (i < dimCount - 1) {
super.visitInsn(Opcodes.SWAP);
// -> stack: ... origaref productTo{I+1} aref0
super.visitInsn(Opcodes.ICONST_0);
// -> stack: ... origaref productTo{I+1} aref0 0
super.visitInsn(Opcodes.AALOAD);
// -> stack: ... origaref productTo{I+1} aref0'
super.visitInsn(Opcodes.SWAP);
}
// post: stack: ... origaref aref0 productTo{I+1}
}
super.visitLabel(zeroDimension);
super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref product aref0
super.visitInsn(Opcodes.POP); // -> stack: ... origaref product
super.visitInsn(Opcodes.SWAP); // -> stack: ... product origaref
invokeRecordAllocation(typeName);
}
public InsnValue createConstant(AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case Opcodes.ACONST_NULL:
return InsnValue.NULL_REFERENCE_VALUE;
case Opcodes.ICONST_M1:
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.BIPUSH:
case Opcodes.SIPUSH:
return InsnValue.intValue(insn);
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
return InsnValue.longValue(insn.getOpcode());
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
return InsnValue.floatValue(insn.getOpcode());
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
return InsnValue.doubleValue(insn.getOpcode());
case Opcodes.LDC:
Object obj = ((LdcInsnNode) insn).cst;
if (obj instanceof Type) {
return new InsnValue((Type) obj);
} else {
Type t = Type.getType(obj.getClass());
int sort = t.getSort();
// Non-included types:
// Type.ARRAY
// Type.VOID
// Type.METHOD
switch (sort) {
case Type.BOOLEAN:
return InsnValue.intValue((int) obj);
case Type.CHAR:
return InsnValue.charValue((char) obj);
case Type.BYTE:
return InsnValue.byteValue((byte) obj);
case Type.SHORT:
return InsnValue.shortValue((short) obj);
case Type.INT:
return InsnValue.intValue((int) obj);
case Type.FLOAT:
return InsnValue.floatValue((float) obj);
case Type.LONG:
return InsnValue.longValue((long) obj);
case Type.DOUBLE:
return InsnValue.doubleValue((double) obj);
case Type.OBJECT:
return new InsnValue(t, obj);
}
return new InsnValue(t);
}
case Opcodes.NEW:
return new InsnValue(Type.getType(((TypeInsnNode) insn).desc));
case Opcodes.JSR:
// TODO: IDK if this is right.
return InsnValue.REFERENCE_VALUE;
}
return null;
}
public static int toAsmBool(boolean value) {
return value ? Opcodes.ICONST_1 : Opcodes.ICONST_0;
}
private List<AbstractInsnNode> getPossibleInsns(AbstractInsnNode ain)
{
List<AbstractInsnNode> instrs = new ArrayList<>();
while(ain != null)
{
if(ain instanceof LineNumberNode || ain instanceof FrameNode)
{
ain = ain.getNext();
continue;
}
instrs.add(ain);
if(instrs.size() >= 23)
break;
ain = ain.getNext();
}
if(instrs.size() == 23 && instrs.get(0).getOpcode() == Opcodes.ILOAD
&& instrs.get(1).getOpcode() == Opcodes.ICONST_1
&& instrs.get(2).getOpcode() == Opcodes.ISUB
&& instrs.get(3).getOpcode() == Opcodes.ISTORE)
{
int var1 = ((VarInsnNode)instrs.get(0)).var;
int var2 = ((VarInsnNode)instrs.get(3)).var;
if(instrs.get(4).getOpcode() == Opcodes.ILOAD
&& ((VarInsnNode)instrs.get(4)).var == var1
&& instrs.get(5).getOpcode() == Opcodes.ILOAD
&& ((VarInsnNode)instrs.get(5)).var == var2
&& instrs.get(6).getOpcode() == Opcodes.IMUL
&& instrs.get(7).getOpcode() == Opcodes.ISTORE
&& ((VarInsnNode)instrs.get(7)).var == var2
&& instrs.get(8).getOpcode() == Opcodes.ILOAD
&& ((VarInsnNode)instrs.get(8)).var == var2
&& instrs.get(9).getOpcode() == Opcodes.ICONST_2
&& instrs.get(10).getOpcode() == Opcodes.IREM
&& instrs.get(11).getOpcode() == Opcodes.ISTORE
&& ((VarInsnNode)instrs.get(11)).var == var2
&& instrs.get(12).getOpcode() == Opcodes.ILOAD
&& ((VarInsnNode)instrs.get(12)).var == var2
&& instrs.get(13).getOpcode() == Opcodes.I2L
&& instrs.get(14).getOpcode() == Opcodes.ICONST_0
&& instrs.get(15).getOpcode() == Opcodes.I2L
&& instrs.get(16).getOpcode() == Opcodes.LCMP
&& instrs.get(17).getOpcode() == Opcodes.ICONST_1
&& instrs.get(18).getOpcode() == Opcodes.IXOR
&& instrs.get(19).getOpcode() == Opcodes.ICONST_1
&& instrs.get(20).getOpcode() == Opcodes.IAND
&& instrs.get(21).getOpcode() == Opcodes.IFEQ
&& instrs.get(22).getOpcode() == Opcodes.IINC)
return instrs;
}
return null;
}
/**
* Returns whether a given instruction can be used to push argument of {@code type} on stack.
*/
private /* static */ boolean isPushForType(AbstractInsnNode insn, Type type) {
int opcode = insn.getOpcode();
if (opcode == type.getOpcode(Opcodes.ILOAD)) {
return true;
}
// b/62060793: AsyncAwait rewrites bytecode to convert java methods into state machine with
// support of lambdas. Constant zero values are pushed on stack for all yet uninitialized
// local variables. And SIPUSH instruction is used to advance an internal state of a state
// machine.
switch (type.getSort()) {
case Type.BOOLEAN:
return opcode == Opcodes.ICONST_0 || opcode == Opcodes.ICONST_1;
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
return opcode == Opcodes.SIPUSH
|| opcode == Opcodes.ICONST_0
|| opcode == Opcodes.ICONST_1
|| opcode == Opcodes.ICONST_2
|| opcode == Opcodes.ICONST_3
|| opcode == Opcodes.ICONST_4
|| opcode == Opcodes.ICONST_5
|| opcode == Opcodes.ICONST_M1;
case Type.LONG:
return opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1;
case Type.FLOAT:
return opcode == Opcodes.FCONST_0
|| opcode == Opcodes.FCONST_1
|| opcode == Opcodes.FCONST_2;
case Type.DOUBLE:
return opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1;
case Type.OBJECT:
case Type.ARRAY:
return opcode == Opcodes.ACONST_NULL;
default:
// Support for BIPUSH and LDC* opcodes is not implemented as there is no known use case.
return false;
}
}
private void pushProductOfIntArrayOnStack() {
Label beginScopeLabel = new Label();
Label endScopeLabel = new Label();
int dimsArrayIndex = newLocal("[I", beginScopeLabel, endScopeLabel);
int counterIndex = newLocal("I", beginScopeLabel, endScopeLabel);
int productIndex = newLocal("I", beginScopeLabel, endScopeLabel);
Label loopLabel = new Label();
Label endLabel = new Label();
super.visitLabel(beginScopeLabel);
// stack: ... intArray
super.visitVarInsn(Opcodes.ASTORE, dimsArrayIndex);
// -> stack: ...
// counter = 0
super.visitInsn(Opcodes.ICONST_0);
super.visitVarInsn(Opcodes.ISTORE, counterIndex);
// product = 1
super.visitInsn(Opcodes.ICONST_1);
super.visitVarInsn(Opcodes.ISTORE, productIndex);
// loop:
super.visitLabel(loopLabel);
// if index >= arraylength goto end:
super.visitVarInsn(Opcodes.ILOAD, counterIndex);
super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
super.visitInsn(Opcodes.ARRAYLENGTH);
super.visitJumpInsn(Opcodes.IF_ICMPGE, endLabel);
// product = product * max(array[counter],1)
super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
super.visitVarInsn(Opcodes.ILOAD, counterIndex);
super.visitInsn(Opcodes.IALOAD);
super.visitInsn(Opcodes.DUP);
Label nonZeroDimension = new Label();
super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension);
super.visitInsn(Opcodes.POP);
super.visitInsn(Opcodes.ICONST_1);
super.visitLabel(nonZeroDimension);
super.visitVarInsn(Opcodes.ILOAD, productIndex);
super.visitInsn(Opcodes.IMUL); // if overflow happens it happens.
super.visitVarInsn(Opcodes.ISTORE, productIndex);
// iinc counter 1
super.visitIincInsn(counterIndex, 1);
// goto loop
super.visitJumpInsn(Opcodes.GOTO, loopLabel);
// end:
super.visitLabel(endLabel);
// re-push dimensions array
super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
// push product
super.visitVarInsn(Opcodes.ILOAD, productIndex);
super.visitLabel(endScopeLabel);
}