下面列出了org.objectweb.asm.Opcodes# ASTORE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 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 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());
}
}
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
@SuppressFBWarnings(value = "SF_SWITCH_NO_DEFAULT", justification = "No action required on default option.")
public void visitVarInsn(int opcode, int offset) {
switch (opcode) {
case Opcodes.ISTORE:
case Opcodes.FSTORE:
case Opcodes.ASTORE:
localVariableExtension = Math.max(localVariableExtension, offset + 1);
break;
case Opcodes.LSTORE:
case Opcodes.DSTORE:
localVariableExtension = Math.max(localVariableExtension, offset + 2);
break;
}
super.visitVarInsn(opcode, offset);
}
private void dupStackElementBeforeSignatureArgs(final String sig) {
final Label beginScopeLabel = new Label();
final Label endScopeLabel = new Label();
super.visitLabel(beginScopeLabel);
Type[] argTypes = Type.getArgumentTypes(sig);
int[] args = new int[argTypes.length];
for (int i = argTypes.length - 1; i >= 0; --i) {
args[i] = newLocal(argTypes[i], beginScopeLabel, endScopeLabel);
super.visitVarInsn(argTypes[i].getOpcode(Opcodes.ISTORE), args[i]);
}
super.visitInsn(Opcodes.DUP);
for (int i = 0; i < argTypes.length; ++i) {
int op = argTypes[i].getOpcode(Opcodes.ILOAD);
super.visitVarInsn(op, args[i]);
if (op == Opcodes.ALOAD) {
super.visitInsn(Opcodes.ACONST_NULL);
super.visitVarInsn(Opcodes.ASTORE, args[i]);
}
}
super.visitLabel(endScopeLabel);
}
@Override
public void visitVarInsn(final int opcode, final int var) {
ReplacingBasicValue v;
if (opcode == Opcodes.ASTORE && (v = peekFromTop(0)) != null) {
final ValueHolderSub from = oldToNew.get(v.getIndex());
final ReplacingBasicValue current = getLocal(var);
// if local var is set, then transfer to it to the existing holders in the local position.
if (current != null) {
final ValueHolderSub newSub = oldToNew.get(current.getIndex());
if (newSub.iden() == from.iden()) {
final int targetFirst = newSub.first();
from.transfer(this, targetFirst);
return;
}
}
// if local var is not set, then check map to see if existing holders are mapped to local var.
if (oldLocalToFirst.containsKey(var)) {
final ValueHolderSub sub = oldToNew.get(oldLocalToFirst.get(var));
if (sub.iden() == from.iden()) {
// if they are, then transfer to that.
from.transfer(this, sub.first());
return;
}
}
// map from variables to global space for future use.
oldLocalToFirst.put(var, v.getIndex());
return;
} else if (opcode == Opcodes.ALOAD && (v = getLocal(var)) != null) {
/*
* Not forwarding this removes a now unnecessary ALOAD for a holder. The required LOAD/STORE
* sequences will be generated by the ASTORE code above.
*/
return;
}
super.visitVarInsn(opcode, var);
}
public static int getStoreOp(char c){
switch(c){
case 'Z': return Opcodes.ISTORE ;
case 'B': return Opcodes.ISTORE ;
case 'S': return Opcodes.ISTORE;
case 'I': return Opcodes.ISTORE ;
case 'J': return Opcodes.LSTORE ;
case 'F': return Opcodes.FSTORE ;
case 'D': return Opcodes.DSTORE ;
case 'C': return Opcodes.ISTORE ;
default:
return Opcodes.ASTORE;
}
}
@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();
}
}
public boolean assignFrom(AssignableExpression ex, StringBuilder b) {
b.append(" /* VarOp.assignFrom */ ");
switch (opcode) {
case Opcodes.ISTORE:
return ex.assignTo("ilocals_"+var+"_", b);
case Opcodes.LSTORE:
return ex.assignTo("llocals_"+var+"_", b);
case Opcodes.FSTORE:
return ex.assignTo("flocals_"+var+"_", b);
case Opcodes.DSTORE:
return ex.assignTo("dlocals_"+var+"_", b);
case Opcodes.ASTORE: {
StringBuilder sb = new StringBuilder();
sb.append("locals[").append(var).append("].type=CN1_TYPE_INVALID;");
boolean res = ex.assignTo("locals["+var+"].data.o", sb);
if (!res) {
return false;
}
sb.append("locals[").append(var).append("].type=CN1_TYPE_OBJECT;");
b.append(sb);
return true;
}
}
b.append("\n");
return false;
}
@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) {
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();
}
}
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
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) {
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));
}
@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 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$
}
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (name.equals("mcp.mobius.waila.handlers.HUDHandlerFMP")) {
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
for (MethodNode mn : cn.methods) {
if (mn.name.equals("getWailaBody")) {
AbstractInsnNode n = mn.instructions.getFirst();
while (n != null) {
if (n.getOpcode() == Opcodes.ASTORE && ((VarInsnNode) n).var == 8) {
n = n.getNext();
break;
}
n = n.getNext();
}
//TODO better fmp support
if (n != null) {
mn.instructions.insertBefore(n, new FieldInsnNode(Opcodes.GETSTATIC, "mcp/mobius/waila/api/impl/DataAccessorFMP", "instance", "Lmcp/mobius/waila/api/impl/DataAccessorFMP;"));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 3));
mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKEINTERFACE, "mcp/mobius/waila/api/IWailaDataAccessor", "getWorld", "()Lnet/minecraft/world/World;", true));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 3));
mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKEINTERFACE, "mcp/mobius/waila/api/IWailaDataAccessor", "getPlayer", "()Lnet/minecraft/entity/player/EntityPlayer;", true));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 3));
mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKEINTERFACE, "mcp/mobius/waila/api/IWailaDataAccessor", "getPosition", "()Lnet/minecraft/util/MovingObjectPosition;", true));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 7));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 8));
mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "mcp/mobius/waila/api/impl/DataAccessorFMP", "set", "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;Lnet/minecraft/nbt/NBTTagCompound;Ljava/lang/String;)V", false));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ALOAD, 2));
mn.instructions.insertBefore(n, new FieldInsnNode(Opcodes.GETSTATIC, "mcp/mobius/waila/api/impl/DataAccessorFMP", "instance", "Lmcp/mobius/waila/api/impl/DataAccessorFMP;"));
mn.instructions.insertBefore(n, new MethodInsnNode(Opcodes.INVOKESTATIC, "me/exz/omniocular/handler/FMPHandler", "getWailaBody", "(Ljava/util/List;Lmcp/mobius/waila/api/IWailaFMPAccessor;)Ljava/util/List;", false));
mn.instructions.insertBefore(n, new VarInsnNode(Opcodes.ASTORE, 2));
}
// mn.instructions.clear();
// mn.instructions.add(new InsnNode(Opcodes.ICONST_1));
// mn.instructions.add(new InsnNode(Opcodes.IRETURN));
// mn.maxStack=1;
}
}
ClassWriter cw = new ClassWriter(0);
cn.accept(cw);
//LogHelper.info("inject into waila");
return cw.toByteArray();
} else {
return bytes;
}
}
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);
}