下面列出了org.objectweb.asm.Opcodes# ISTORE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void addVariableOperation(int opcode, int var) {
VarOp op = new VarOp(opcode, var);
LocalVariable lv = null;
switch (opcode) {
case Opcodes.ISTORE:
lv = new LocalVariable("v"+var, "I", "I", null, null, var); break;
case Opcodes.LSTORE:
lv = new LocalVariable("v"+var, "J", "J", null, null, var); break;
case Opcodes.FSTORE:
lv = new LocalVariable("v"+var, "F", "F", null, null, var); break;
case Opcodes.DSTORE:
lv = new LocalVariable("v"+var, "D", "D", null, null, var); break;
}
if (lv != null && !localVariables.contains(lv)) {
localVariables.add(lv);
}
addInstruction(op);
}
/**
* Given a *STORE opcode, it returns the type associated to the variable, or null if
* not a valid opcode.
*/
static Type getTypeForStoreOpcode(int opcode) {
switch (opcode) {
case Opcodes.ISTORE:
return Type.INT_TYPE;
case Opcodes.LSTORE:
return Type.LONG_TYPE;
case Opcodes.FSTORE:
return Type.FLOAT_TYPE;
case Opcodes.DSTORE:
return Type.DOUBLE_TYPE;
case Opcodes.ASTORE:
return Type.getType(Object.class);
}
return null;
}
public static int getVarOpcode(Type type, boolean store) {
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return store ? Opcodes.ISTORE : Opcodes.ILOAD;
case Type.FLOAT:
return store ? Opcodes.FSTORE : Opcodes.FLOAD;
case Type.LONG:
return store ? Opcodes.LSTORE : Opcodes.LLOAD;
case Type.DOUBLE:
return store ? Opcodes.DSTORE : Opcodes.DLOAD;
case Type.ARRAY:
case Type.OBJECT:
return store ? Opcodes.ASTORE : Opcodes.ALOAD;
default:
throw new AssertionError("Unknown type: " + type.getClassName());
}
}
@Override
public void visitVarInsn(final int opcode, final int var) {
Type varType;
switch (opcode) {
case Opcodes.LLOAD:
case Opcodes.LSTORE:
varType = Type.LONG_TYPE;
break;
case Opcodes.DLOAD:
case Opcodes.DSTORE:
varType = Type.DOUBLE_TYPE;
break;
case Opcodes.FLOAD:
case Opcodes.FSTORE:
varType = Type.FLOAT_TYPE;
break;
case Opcodes.ILOAD:
case Opcodes.ISTORE:
varType = Type.INT_TYPE;
break;
case Opcodes.ALOAD:
case Opcodes.ASTORE:
case Opcodes.RET:
varType = OBJECT_TYPE;
break;
default:
throw new IllegalArgumentException("Invalid opcode " + opcode);
}
super.visitVarInsn(opcode, remap(var, varType));
}
@Override
public void visitVarInsn(final int opcode, final int var) {
Type varType;
switch (opcode) {
case Opcodes.LLOAD:
case Opcodes.LSTORE:
varType = Type.LONG_TYPE;
break;
case Opcodes.DLOAD:
case Opcodes.DSTORE:
varType = Type.DOUBLE_TYPE;
break;
case Opcodes.FLOAD:
case Opcodes.FSTORE:
varType = Type.FLOAT_TYPE;
break;
case Opcodes.ILOAD:
case Opcodes.ISTORE:
varType = Type.INT_TYPE;
break;
case Opcodes.ALOAD:
case Opcodes.ASTORE:
case Opcodes.RET:
varType = OBJECT_TYPE;
break;
default:
throw new IllegalArgumentException("Invalid opcode " + opcode);
}
super.visitVarInsn(opcode, remap(var, varType));
}
@Test
public void test_checkBranch() throws Exception {
List<BasicBlock> hashCodeBlocks = METHOD_BLOCKS.get("checkBranch(I)I");
int[][] expectedHashCodeBlocks = new int[][]{
{Opcodes.ICONST_5, Opcodes.ISTORE, Opcodes.ILOAD, Opcodes.BIPUSH, Opcodes.IF_ICMPLE},
{Opcodes.BIPUSH, Opcodes.ISTORE, Opcodes.GOTO},
{Opcodes.ICONST_4, Opcodes.ISTORE},
{Opcodes.ILOAD, Opcodes.IRETURN},
};
boolean didMatch = compareBlocks(expectedHashCodeBlocks, hashCodeBlocks);
Assert.assertTrue(didMatch);
}
@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);
}
private static byte[] createDeepPushClass(String className, int pushCount, boolean isLong) {
// Note that the setup for the method requires at least 2 stack depth.
Assert.assertTrue(pushCount >= 2);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, className, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
Object oneLong = Long.valueOf(1L);
Object oneInt = Integer.valueOf(1);
Object value = isLong
? oneLong
: oneInt;
// visitLdcInsn uses a type check so make sure that we got the type we were expecting (some compilers try to get clever here).
if (isLong) {
Assert.assertTrue(value instanceof Long);
} else {
Assert.assertTrue(value instanceof Integer);
}
method.visitLdcInsn(value);
int storeOpcode = isLong ? Opcodes.LSTORE : Opcodes.ISTORE;
method.visitVarInsn(storeOpcode, 0);
int loadOpcode = isLong ? Opcodes.LLOAD : Opcodes.ILOAD;
// Reduce the push count by 1 since we have at least one more slot for the return value.
for (int i = 0; i < (pushCount - 1); ++i) {
method.visitVarInsn(loadOpcode, 0);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
private static byte[] createVarHeavyClass(String className, int varCount, boolean isLong) {
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
writer.visit(Opcodes.V10, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, className, null, "java/lang/Object", new String[0]);
MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", "()[B", null, null);
Object oneLong = Long.valueOf(1L);
Object oneInt = Integer.valueOf(1);
Object value = isLong
? oneLong
: oneInt;
int storeOpcode = isLong ? Opcodes.LSTORE : Opcodes.ISTORE;
// visitLdcInsn uses a type check so make sure that we got the type we were expecting (some compilers try to get clever here).
if (isLong) {
Assert.assertTrue(value instanceof Long);
} else {
Assert.assertTrue(value instanceof Integer);
}
// Note that we will actually invalidate the local variable n-1 when writing a long, but this is just to verify that it reserves the next slot.
for (int i = 0; i < varCount; ++i) {
method.visitLdcInsn(value);
method.visitVarInsn(storeOpcode, i);
}
method.visitInsn(Opcodes.ACONST_NULL);
method.visitInsn(Opcodes.ARETURN);
method.visitMaxs(0, 0);
method.visitEnd();
writer.visitEnd();
return writer.toByteArray();
}
@Override
public void visitVarInsn(final int opcode, final int var) {
switch (opcode) {
case Opcodes.ILOAD:
load(var, Type.INT_TYPE);
break;
case Opcodes.LLOAD:
load(var, Type.LONG_TYPE);
break;
case Opcodes.FLOAD:
load(var, Type.FLOAT_TYPE);
break;
case Opcodes.DLOAD:
load(var, Type.DOUBLE_TYPE);
break;
case Opcodes.ALOAD:
load(var, OBJECT_TYPE);
break;
case Opcodes.ISTORE:
store(var, Type.INT_TYPE);
break;
case Opcodes.LSTORE:
store(var, Type.LONG_TYPE);
break;
case Opcodes.FSTORE:
store(var, Type.FLOAT_TYPE);
break;
case Opcodes.DSTORE:
store(var, Type.DOUBLE_TYPE);
break;
case Opcodes.ASTORE:
store(var, OBJECT_TYPE);
break;
case Opcodes.RET:
ret(var);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitVarInsn(final int opcode, final int var) {
Type varType;
switch (opcode) {
case Opcodes.LLOAD:
case Opcodes.LSTORE:
varType = Type.LONG_TYPE;
break;
case Opcodes.DLOAD:
case Opcodes.DSTORE:
varType = Type.DOUBLE_TYPE;
break;
case Opcodes.FLOAD:
case Opcodes.FSTORE:
varType = Type.FLOAT_TYPE;
break;
case Opcodes.ILOAD:
case Opcodes.ISTORE:
varType = Type.INT_TYPE;
break;
case Opcodes.ALOAD:
case Opcodes.ASTORE:
case Opcodes.RET:
varType = OBJECT_TYPE;
break;
default:
throw new IllegalArgumentException("Invalid opcode " + opcode);
}
super.visitVarInsn(opcode, remap(var, varType));
}
private List<AbstractInsnNode> getPossibleInsns4(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() >= 11)
break;
ain = ain.getNext();
}
if(instrs.size() == 11 && 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)
return instrs;
}
return null;
}
public static VarInsnNode getStoreInst(Type type, int position) {
int opCode = -1;
switch (type.getDescriptor().charAt(0)) {
case 'B':
opCode = Opcodes.ISTORE;
break;
case 'C':
opCode = Opcodes.ISTORE;
break;
case 'D':
opCode = Opcodes.DSTORE;
break;
case 'F':
opCode = Opcodes.FSTORE;
break;
case 'I':
opCode = Opcodes.ISTORE;
break;
case 'J':
opCode = Opcodes.LSTORE;
break;
case 'L':
opCode = Opcodes.ASTORE;
break;
case '[':
opCode = Opcodes.ASTORE;
break;
case 'Z':
opCode = Opcodes.ISTORE;
break;
case 'S':
opCode = Opcodes.ISTORE;
break;
default:
throw new ClassFormatError("Invalid method signature: "
+ type.getDescriptor());
}
return new VarInsnNode(opCode, position);
}
@Override
protected boolean addInsn(InsnList insns, Collection<AbstractInsnNode> nodes, AbstractInsnNode insn) {
MethodInsnNode methodNode = (MethodInsnNode)insn;
if (Type.getReturnType(methodNode.desc) == Type.VOID_TYPE) {
return false;
}
insn = InjectionPoint.nextNode(insns, insn);
if (insn instanceof VarInsnNode && insn.getOpcode() >= Opcodes.ISTORE) {
insn = InjectionPoint.nextNode(insns, insn);
}
nodes.add(insn);
return true;
}
public boolean assignFrom(CustomInvoke ex, StringBuilder b) {
b.append(" /* VarOp.assignFrom */ ");
StringBuilder sb = new StringBuilder();
switch (opcode) {
case Opcodes.ISTORE:
if (ex.appendExpression(sb)) {
b.append("ilocals_").append(var).append("_ = ").append(sb.toString().trim()).append(";\n");
return true;
}
break;
case Opcodes.LSTORE:
if (ex.appendExpression(sb)) {
b.append("llocals_").append(var).append("_ = ").append(sb.toString().trim()).append(";\n");
return true;
}
break;
case Opcodes.FSTORE:
if (ex.appendExpression(sb)) {
b.append("flocals_").append(var).append("_ = ").append(sb.toString().trim()).append(";\n");
return true;
}
break;
case Opcodes.DSTORE:
if (ex.appendExpression(sb)) {
b.append("dlocals_").append(var).append("_ = ").append(sb.toString().trim()).append(";\n");
return true;
}
break;
case Opcodes.ASTORE: {
StringBuilder sb2 = new StringBuilder();
//sb2.append("locals[").append(var).append("].type=CN1_TYPE_INVALID; ");
if (ex.appendExpression(sb)) {
sb2.append("locals[").append(var).append("].data.o = ").append(sb.toString().trim()).append(";");
sb2.append("locals[").append(var).append("].type=CN1_TYPE_OBJECT;");
b.append(sb2);
return true;
}
break;
}
}
//b.append("\n");
return false;
}
@Override
public void appendInstruction(StringBuilder b) {
b.append(" ");
switch(opcode) {
case Opcodes.ILOAD:
b.append("(*SP).type = CN1_TYPE_INT; /* ILOAD */ \n" +
" (*SP).data.i = ilocals_");
b.append(var);
b.append("_; \n SP++;\n");
return;
case Opcodes.LLOAD:
b.append("BC_LLOAD(");
break;
case Opcodes.FLOAD:
b.append("BC_FLOAD(");
break;
case Opcodes.DLOAD:
b.append("BC_DLOAD(");
break;
case Opcodes.ALOAD:
b.append("BC_ALOAD(");
break;
case Opcodes.ISTORE:
b.append("BC_ISTORE(");
break;
case Opcodes.LSTORE:
b.append("BC_LSTORE(");
break;
case Opcodes.FSTORE:
b.append("BC_FSTORE(");
break;
case Opcodes.DSTORE:
b.append("BC_DSTORE(");
break;
case Opcodes.ASTORE:
b.append("BC_ASTORE(");
break;
case Opcodes.RET:
b.append("/* RET TODO */");
//b.append("goto label_");
//b.append(var);
//b.append("; /* RET */\n");
return;
case Opcodes.SIPUSH:
case Opcodes.BIPUSH:
b.append("PUSH_INT(");
break;
case Opcodes.NEWARRAY:
switch(var) {
case 4: // boolean
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_BOOLEAN, sizeof(JAVA_ARRAY_BOOLEAN), 1));\n");
break;
case 5: // char
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_CHAR, sizeof(JAVA_ARRAY_CHAR), 1));\n");
break;
case 6: // float
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_FLOAT, sizeof(JAVA_ARRAY_FLOAT), 1));\n");
break;
case 7: // double
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_DOUBLE, sizeof(JAVA_ARRAY_DOUBLE), 1));\n");
break;
case 8: // byte
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_BYTE, sizeof(JAVA_ARRAY_BYTE), 1));\n");
break;
case 9: // short
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_SHORT, sizeof(JAVA_ARRAY_SHORT), 1));\n");
break;
case 10: // int
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_INT, sizeof(JAVA_ARRAY_INT), 1));\n");
break;
case 11: // long
b.append("PUSH_OBJ(allocArray(threadStateData, POP_INT(), &class_array1__JAVA_LONG, sizeof(JAVA_ARRAY_LONG), 1));\n");
break;
}
return;
default:
throw new RuntimeException("Missing opcode: " + opcode);
}
b.append(var);
b.append(");\n");
}
/**
* @param opcode
* @param var
* @param s
*/
static void handleVarInsn ( int opcode, int var, JVMStackState s ) {
Set<BaseType> v;
switch ( opcode ) {
case Opcodes.LLOAD:
case Opcodes.ILOAD:
case Opcodes.FLOAD:
case Opcodes.DLOAD:
case Opcodes.ALOAD:
v = s.getVariable(var);
if ( log.isTraceEnabled() ) {
log.trace("LOAD " + opcode + "@" + var + ":" + v); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if ( v == null || v.isEmpty() ) {
s.push(new BasicVariable(toType(opcode), "unknown " + var, true)); //$NON-NLS-1$
}
else if ( v.size() == 1 ) {
s.push(v.iterator().next());
}
else {
Set<BaseType> alts = new HashSet<>();
for ( BaseType o : v ) {
if ( o instanceof MultiAlternatives && ! ( (MultiAlternatives) o ).getAlternatives().isEmpty() ) {
alts.addAll( ( (MultiAlternatives) o ).getAlternatives());
}
else {
alts.add(o);
}
}
s.push(new MultiAlternatives(alts));
}
break;
case Opcodes.LSTORE:
case Opcodes.ISTORE:
case Opcodes.FSTORE:
case Opcodes.DSTORE:
case Opcodes.ASTORE:
s.getVariable(var).add(s.pop());
break;
case Opcodes.RET:
break;
default:
log.warn("Unimplemented opcode " + opcode); //$NON-NLS-1$
}
}
private List<AbstractInsnNode> getPossibleInsns2(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() >= 14)
break;
ain = ain.getNext();
}
if(instrs.size() == 14 && 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.IADD)
return instrs;
}
return null;
}
public AfterStoreLocal(InjectionPointData data) {
super(data, Opcodes.ISTORE, true);
}