Example usage for org.objectweb.asm Opcodes PUTFIELD

List of usage examples for org.objectweb.asm Opcodes PUTFIELD

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes PUTFIELD.

Prototype

int PUTFIELD

To view the source code for org.objectweb.asm Opcodes PUTFIELD.

Click Source Link

Usage

From source file:com.codename1.tools.translator.bytecodes.Field.java

License:Open Source License

@Override
public void appendInstruction(StringBuilder sbOut) {
    valueOpAppended = false;//from w w w . ja  v a2 s .  com
    targetOpAppended = false;
    StringBuilder b = new StringBuilder();
    b.append("    ");
    switch (opcode) {
    case Opcodes.GETSTATIC:
        switch (desc.charAt(0)) {
        case 'L':
        case '[':
            b.append("PUSH_POINTER");
            break;
        case 'D':
            b.append("PUSH_DOUBLE");
            break;
        case 'F':
            b.append("PUSH_FLOAT");
            break;
        case 'J':
            b.append("PUSH_LONG");
            break;
        default:
            b.append("PUSH_INT");
            break;
        }
        b.append("(get_static_");
        b.append(owner.replace('/', '_').replace('$', '_'));
        b.append("_");
        b.append(name.replace('/', '_').replace('$', '_'));
        b.append("(threadStateData));\n");
        break;
    case Opcodes.PUTSTATIC: {
        //b.append("SAFE_RETAIN(1);\n    ");
        b.append("set_static_");
        b.append(owner.replace('/', '_').replace('$', '_'));
        b.append("_");
        b.append(name.replace('/', '_').replace('$', '_'));
        b.append("(threadStateData, ");
        StringBuilder sb2 = new StringBuilder();
        StringBuilder sb3 = new StringBuilder();
        if (valueOp != null && valueOp instanceof AssignableExpression
                && ((AssignableExpression) valueOp).assignTo(null, sb2)) {
            b.append(sb2.toString().trim()).append(");\n");
            valueOpAppended = true;
        } else if (valueOp != null && valueOp instanceof CustomInvoke
                && ((CustomInvoke) valueOp).appendExpression(sb3)) {
            b.append(sb3.toString().trim()).append(");\n");
            valueOpAppended = true;
        } else {

            switch (desc.charAt(0)) {
            case 'L':
            case '[':
                b.append("PEEK_OBJ(1));\n    SP--;\n");
                sbOut.append(b);
                return;
            case 'D':
                b.append("POP_DOUBLE");
                break;
            case 'F':
                b.append("POP_FLOAT");
                break;
            case 'J':
                b.append("POP_LONG");
                break;
            default:
                b.append("POP_INT");
                break;
            }
            b.append("());\n");
        }

        break;
    }
    case Opcodes.GETFIELD: {
        StringBuilder sb3 = new StringBuilder();
        boolean targetProvided = (targetOp != null && targetOp instanceof AssignableExpression
                && ((AssignableExpression) targetOp).assignTo(null, sb3));

        switch (desc.charAt(0)) {
        case 'L':
        case '[':
            b.append("PUSH_POINTER");
            break;
        case 'D':
            b.append("PUSH_DOUBLE");
            break;
        case 'F':
            b.append("PUSH_FLOAT");
            break;
        case 'J':
            b.append("PUSH_LONG");
            break;
        default:
            b.append("PUSH_INT");
            break;
        }

        b.append("(get_field_");
        b.append(owner.replace('/', '_').replace('$', '_'));
        b.append("_");
        b.append(name);

        if (targetProvided) {
            b.append("(").append(sb3.toString().trim()).append("));\n");
            targetOpAppended = true;
            //} else if(useThis) {
            //    b.append("(__cn1ThisObject));\n");
        } else {
            b.append("(POP_OBJ()));\n");
        }
        break;
    }
    case Opcodes.PUTFIELD: {
        //b.append("SAFE_RETAIN(1);\n    ");
        b.append("set_field_");
        b.append(owner.replace('/', '_').replace('$', '_'));
        b.append("_");
        b.append(name);
        b.append("(threadStateData, ");

        StringBuilder sb2 = new StringBuilder();
        StringBuilder sb3 = new StringBuilder();

        String targetLiteral = null;
        String valueLiteral = null;
        if (valueOp != null && valueOp instanceof AssignableExpression
                && ((AssignableExpression) valueOp).assignTo(null, sb2)) {
            valueLiteral = sb2.toString().trim();
        } else if (valueOp != null && valueOp instanceof CustomInvoke
                && ((CustomInvoke) valueOp).appendExpression(sb3)) {
            valueLiteral = sb3.toString().trim();
        }
        sb3.setLength(0);
        if (targetOp != null && targetOp instanceof AssignableExpression
                && ((AssignableExpression) targetOp).assignTo(null, sb3)) {
            targetLiteral = sb3.toString().trim();
        }

        if (valueLiteral != null && targetLiteral != null) {
            b.append(valueLiteral).append(", ").append(targetLiteral).append(");\n");
            valueOpAppended = true;
            targetOpAppended = true;
        } else {
            switch (desc.charAt(0)) {
            case 'L':
            case '[':
                b.append("PEEK_OBJ");
                //if(useThis) {
                //    b.append("(1), __cn1ThisObject);\n    SP--;\n");
                //} else {
                b.append("(1), PEEK_OBJ(2));\n    POP_MANY(2);\n");
                //}
                sbOut.append(b);
                return;
            case 'D':
                b.append("POP_DOUBLE");
                break;
            case 'F':
                b.append("POP_FLOAT");
                break;
            case 'J':
                b.append("POP_LONG");
                break;
            default:
                b.append("POP_INT");
                break;
            }
            //if(useThis) {
            //    b.append("(), __cn1ThisObject);\n");
            //} else {
            b.append("(), POP_OBJ());\n");
            //}
        }
        break;
    }
    }
    if (valueOp != null && !valueOpAppended) {
        valueOp.appendInstruction(sbOut);
        valueOpAppended = true;
    }
    if (targetOp != null && !targetOpAppended) {
        targetOp.appendInstruction(sbOut);
        targetOpAppended = true;
    }
    sbOut.append(b);
}

From source file:com.codename1.tools.translator.bytecodes.Field.java

License:Open Source License

/**
 * @param useThis the useThis to set//  w w w.  jav  a  2s .  c  om
 */
//public void setUseThis(boolean useThis) {
//    this.useThis = useThis;
//}

public static int tryReduce(List<Instruction> instructions, int index) {
    Instruction instr = instructions.get(index);
    if (!(instr instanceof Field)) {
        return -1;
    }
    if (instr.getOpcode() == Opcodes.PUTFIELD) {
        if (index < 2) {
            return -1;
        }

        Field f = (Field) instr;
        if (f.targetOp != null || f.valueOp != null) {
            return -1;
        }
        Instruction targetInstr = instructions.get(index - 2);
        if (!(targetInstr instanceof AssignableExpression)) {
            return -1;
        }
        Instruction valueInstr = instructions.get(index - 1);
        if (!(valueInstr instanceof AssignableExpression)) {
            return -1;
        }

        StringBuilder sb = new StringBuilder();

        AssignableExpression targetExpr = (AssignableExpression) targetInstr;
        if (!targetExpr.assignTo(null, sb)) {
            return -1;
        }

        AssignableExpression valueExpr = (AssignableExpression) valueInstr;
        if (!valueExpr.assignTo(null, sb)) {
            return -1;
        }

        f.targetOp = targetInstr;
        f.valueOp = valueInstr;

        instructions.remove(index - 2);
        instructions.remove(index - 2);
        return index - 2;
    } else if (instr.getOpcode() == Opcodes.PUTSTATIC) {
        if (index < 1) {
            return -1;
        }

        Field f = (Field) instr;
        if (f.valueOp != null) {
            return -1;
        }

        Instruction valueInstr = instructions.get(index - 1);
        if (!(valueInstr instanceof AssignableExpression)) {
            return -1;
        }

        StringBuilder sb = new StringBuilder();

        AssignableExpression valueExpr = (AssignableExpression) valueInstr;
        if (!valueExpr.assignTo(null, sb)) {
            return -1;
        }

        f.valueOp = valueInstr;

        instructions.remove(index - 1);

        return index - 1;
    } else if (instr.getOpcode() == Opcodes.GETFIELD) {
        if (index < 1) {
            return -1;
        }

        Field f = (Field) instr;
        //if (f.useThis) {
        //    return -1;
        //}

        Instruction targetInstr = instructions.get(index - 1);
        if (!(targetInstr instanceof AssignableExpression)) {
            return -1;
        }

        StringBuilder sb = new StringBuilder();

        AssignableExpression targetExpr = (AssignableExpression) targetInstr;
        if (!targetExpr.assignTo(null, sb)) {
            return -1;
        }

        f.targetOp = targetInstr;

        instructions.remove(index - 1);

        return index - 1;
    }
    return -1;
}

From source file:com.dank.analysis.impl.landscape.DynamicObject.java

License:GNU General Public License

private FieldInsnNode load(final MethodNode mn, final int opcode, final int index, final Hook owner) {
    for (final AbstractInsnNode ain : mn.instructions.toArray()) {
        if (ain instanceof VarInsnNode) {
            final VarInsnNode vin = (VarInsnNode) ain;
            if (vin.var == index && vin.opcode() == opcode) {
                AbstractInsnNode dog = vin;
                for (int i = 0; i < 7; i++) {
                    if (dog == null)
                        break;
                    if (dog.opcode() == Opcodes.PUTFIELD
                            && ((FieldInsnNode) dog).owner.equals(owner.getInternalName())) {
                        return (FieldInsnNode) dog;
                    }/* ww  w . j av a 2s  .  c  o  m*/
                    dog = dog.next();
                }
            }
        }
    }
    return null;
}

From source file:com.github.anba.es6draft.compiler.assembler.InstructionAssembler.java

License:Open Source License

public void putfield(Type owner, String name, Type desc) {
    methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, owner.internalName(), name, desc.descriptor());
    stack.putfield(owner, desc);
}

From source file:com.github.jasmo.obfuscate.InlineAccessors.java

License:Open Source License

@Override
public void transform(Map<String, ClassNode> classMap) {
    this.classMap = classMap;
    for (ClassNode node : new ArrayList<>(classMap.values())) {
        for (FieldNode field : node.fields) {
            for (MethodNode method : new ArrayList<>(node.methods)) {
                if (isGetterFor(node, field, method)) {
                    node.methods.remove(method);
                    log.debug("Inlining getter {}.{}{}", node.name, method.name, method.desc);
                    replace(Opcodes.GETFIELD, node, field, method);
                }/*w w  w . j a  va  2s. c  o m*/
                if (isSetterFor(node, field, method)) {
                    node.methods.remove(method);
                    log.debug("Inlining setter {}.{}{}", node.name, method.name, method.desc);
                    replace(Opcodes.PUTFIELD, node, field, method);
                }
            }
        }
    }
}

From source file:com.github.jasmo.obfuscate.InlineAccessors.java

License:Open Source License

private Query[] getPattern(boolean get, ClassNode owner, FieldNode field) {
    Type type = Type.getType(field.desc);
    List<Query> queries = new LinkedList<>();
    boolean local = local(field.access);
    if (local)// w  w  w. ja  va2 s  .  c  o m
        queries.add(new Query("opcode", Opcodes.ALOAD, "var", 0));
    if (get) {
        int opcode = local ? Opcodes.GETFIELD : Opcodes.GETSTATIC;
        queries.add(new Query("opcode", opcode, "owner", owner.name, "name", field.name, "desc", field.desc));
        queries.add(new Query("opcode", type.getOpcode(Opcodes.IRETURN)));
    } else {
        int opcode = local ? Opcodes.PUTFIELD : Opcodes.PUTSTATIC;
        queries.add(new Query("opcode", type.getOpcode(Opcodes.ILOAD), "var", 0));
        queries.add(new Query("opcode", opcode, "owner", owner.name, "name", field.name, "desc", field.desc));
        queries.add(new Query("opcode", Opcodes.RETURN));
    }
    return queries.toArray(new Query[queries.size()]);
}

From source file:com.google.code.jconts.instrument.gen.AsyncMethodAdapter.java

License:Apache License

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
    checkProlog();//  w ww  .j av a2  s . c o  m

    if (opcode == Opcodes.INVOKESTATIC && ASYNC_NAME.equals(owner) && ARETURN_NAME.equals(name)) {

        if (ARETURN_VOID_DESC.equals(desc)) {
            mv.visitInsn(Opcodes.ACONST_NULL);
        }

        // state variable
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, CONTINUATION_FIELD, CONTINUATION_DESC);
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, CONTINUATION_NAME, CONTINUATION_INVOKE_NAME,
                CONTINUATION_INVOKE_DESC);

        // Will be dropped while replacing ARETURN with RETURN.
        // FIXME: Should verify this value is NOT used.
        mv.visitInsn(Opcodes.ACONST_NULL);
        return;
    }
    if (opcode == Opcodes.INVOKESTATIC && ASYNC_NAME.equals(owner) && AWAIT_NAME.equals(name)
            && AWAIT_DESC.equals(desc)) {

        // Computation<T> is on stack

        // FIXME: ...
        // if (stack.size() != 1) {
        // throw new IllegalStateException(
        // "Stack preserving is not supported!");
        // }

        int index = dispatchTable.size();

        // Save state
        List<Type> l = new ArrayList<Type>(locals);
        if (!info.isStatic()) {
            l.remove(0);
        }

        // state.varX = locX
        String[] vars = info.tracker.stateFields(l.toArray(new Type[0]));
        for (int i = 0; i < vars.length; ++i) {
            // state variable
            target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
            mv.visitVarInsn(l.get(i).getOpcode(Opcodes.ILOAD), i + info.thisOffset);
            mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, vars[i], l.get(i).getDescriptor());
        }

        // Create instance of continuation
        // new Continuation([this, ]state, index);
        mv.visitTypeInsn(Opcodes.NEW, info.continuationClassName);
        mv.visitInsn(Opcodes.DUP);

        // "this' for new Continuation([this, ]state, index)
        if (!info.isStatic()) {
            mv.visitVarInsn(Opcodes.ALOAD, 0);
        }

        // state and index
        target.visitVarInsn(Opcodes.ALOAD, 0 + info.thisOffset);
        mv.visitIntInsn(Opcodes.BIPUSH, index);

        String ctorDesc;
        if (info.isStatic()) {
            ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE });
        } else {
            ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { Type.getObjectType(info.owner), info.stateType, Type.INT_TYPE });
        }
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, info.continuationClassName, CTOR_NAME, ctorDesc);

        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, COMPUTATION_NAME, COMPUTATION_EXECUTE_NAME,
                COMPUTATION_EXECUTE_DESC);
        super.visitInsn(Opcodes.RETURN);

        // Restore state
        // mv.visitFrame(Opcodes.F_SAME, 0, new Object[0], 0, new
        // Object[0]);
        Label label = new Label();

        int invokeIndex = dispatchTable.size();
        dispatchTable.add(label); // for invoke
        dispatchTable.add(label); // for setException
        mv.visitLabel(label);
        for (int i = 0; i < vars.length; ++i) {
            // state variable
            target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
            mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, vars[i], l.get(i).getDescriptor());
            mv.visitVarInsn(l.get(i).getOpcode(Opcodes.ISTORE), i + info.thisOffset);
        }

        // if (index == invokeIndex) goto invokeLabel;
        Label invokeLabel = new Label();
        target.visitVarInsn(Opcodes.ILOAD, 1 + info.thisOffset);
        mv.visitIntInsn(Opcodes.BIPUSH, invokeIndex);
        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, invokeLabel);

        // Throw exception
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, "exception", THROWABLE_DESC);
        mv.visitInsn(Opcodes.ATHROW);

        // Push result value
        // invokeLabel:
        mv.visitLabel(invokeLabel);
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, "result", OBJECT_DESC);
        return;
    }
    super.visitMethodInsn(opcode, owner, name, desc);
}

From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java

License:Apache License

private void generateConstructor(ClassVisitor cv) {
    final String name = info.computationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Constructor have form either <init>(OuterClass this$0, State state)
    // or <init>(State state)
    String ctorDesc;/*  w w  w. j  a v a 2 s. com*/
    if (info.isStatic()) {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType });
    } else {
        cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null);

        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { outerType, info.stateType });
    }

    // Generate constructor
    MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC);

    // Save state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc);

    // Save outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor());
    }
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }
    mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset);

    mv.visitMaxs(2, 2 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java

License:Apache License

private void generateExecute(ClassVisitor cv) {
    final String name = info.computationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Generate execute(Continuation<T> cont);
    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, COMPUTATION_EXECUTE_NAME,
            COMPUTATION_EXECUTE_DESC, executeSignature(), null);
    mv.visitCode();/*from   w  w w  .jav  a2  s.co  m*/
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    // Load outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, name, "this$0", outerType.getDescriptor());
    }

    // Load state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);

    // state.continuation = continuation
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, CONTINUATION_FIELD, CONTINUATION_DESC);

    // Initial state (0)
    mv.visitIntInsn(Opcodes.BIPUSH, 0);
    mv.visitMethodInsn(info.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, info.owner,
            info.name + "$async",
            Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE }));

    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }

    SignatureWriter sign = new SignatureWriter();
    contSignature(sign);
    mv.visitLocalVariable("continuation", CONTINUATION_DESC, sign.toString(), start, end, 1 + info.thisOffset);

    mv.visitMaxs(3 + info.thisOffset, 2 + info.thisOffset);
    mv.visitEnd();
}

From source file:com.google.code.jconts.instrument.gen.ContinuationClassGenerator.java

License:Apache License

private void generateConstructor(ClassVisitor cv) {
    final String name = info.continuationClassName;
    final Type outerType = Type.getObjectType(info.owner);

    // Constructor have form either <init>(OuterClass this$0, State state,
    // int index)
    // or <init>(State state, int index)
    String ctorDesc;/*from  w ww  .j ava2s .  c  o  m*/
    if (info.isStatic()) {
        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE });
    } else {
        cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null);

        ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
                new Type[] { outerType, info.stateType, Type.INT_TYPE });
    }

    // Generate constructor
    MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null);
    mv.visitCode();
    Label start = new Label();
    Label end = new Label();
    mv.visitLabel(start);

    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC);

    // Save state field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc);

    // Save index field
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ILOAD, 2 + info.thisOffset);
    mv.visitFieldInsn(Opcodes.PUTFIELD, name, "index", "I");

    // Save outer this
    if (!info.isStatic()) {
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor());
    }
    mv.visitInsn(Opcodes.RETURN);
    mv.visitLabel(end);

    mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0);
    if (!info.isStatic()) {
        mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1);
    }
    mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset);
    mv.visitLocalVariable("index", "I", null, start, end, 2 + info.thisOffset);

    mv.visitMaxs(2, 3 + info.thisOffset);
    mv.visitEnd();
}