Example usage for org.objectweb.asm MethodVisitor visitTableSwitchInsn

List of usage examples for org.objectweb.asm MethodVisitor visitTableSwitchInsn

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitTableSwitchInsn.

Prototype

public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) 

Source Link

Document

Visits a TABLESWITCH instruction.

Usage

From source file:org.jadira.reflection.access.asm.AsmClassAccess.java

License:Apache License

private static void enhanceForInvokeMethod(ClassVisitor cw, String accessClassNm, String clazzNm,
        Method[] methods) {//from  www.  j  a  v a2 s  .co m

    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invokeMethod",
            "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", null, null);
    mv.visitCode();

    if (methods.length > 0) {

        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, clazzNm);

        mv.visitVarInsn(ASTORE, 4);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKESPECIAL, "org/jadira/reflection/access/asm/AsmClassAccess", "getMethodIndex",
                "(Ljava/lang/reflect/Method;)I");
        mv.visitVarInsn(ISTORE, 5);
        mv.visitVarInsn(ILOAD, 5);

        Label[] labels = constructLabels(methods);
        Label defaultLabel = new Label();

        mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

        for (int i = 0; i < labels.length; i++) {

            Method method = methods[i];
            Class<?>[] parameterTypes = method.getParameterTypes();

            mv.visitLabel(labels[i]);

            if (i == 0) {
                mv.visitFrame(F_APPEND, 1, new Object[] { clazzNm }, 0, null);
            } else {
                mv.visitFrame(F_SAME, 0, null, 0, null);
            }
            mv.visitVarInsn(ALOAD, 4);

            StringBuilder methodDescriptor = new StringBuilder("(");
            for (int parameterIdx = 0; parameterIdx < parameterTypes.length; parameterIdx++) {

                Type type = Type.getType(parameterTypes[parameterIdx]);

                mv.visitVarInsn(ALOAD, 3);
                mv.visitIntInsn(BIPUSH, parameterIdx);
                mv.visitInsn(AALOAD);

                switch (type.getSort()) {
                case Type.BOOLEAN:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
                    break;
                case Type.BYTE:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
                    break;
                case Type.CHAR:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
                    break;
                case Type.SHORT:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
                    break;
                case Type.INT:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
                    break;
                case Type.FLOAT:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
                    break;
                case Type.LONG:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
                    break;
                case Type.DOUBLE:
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
                    break;
                case Type.ARRAY:
                    mv.visitTypeInsn(CHECKCAST, type.getDescriptor());
                    break;
                case Type.OBJECT:
                    mv.visitTypeInsn(CHECKCAST, type.getInternalName());
                    break;
                }
                methodDescriptor.append(type.getDescriptor());
            }

            methodDescriptor.append(')');
            methodDescriptor.append(Type.getDescriptor(method.getReturnType()));

            mv.visitMethodInsn(INVOKEVIRTUAL, clazzNm, method.getName(), methodDescriptor.toString());

            switch (Type.getType(method.getReturnType()).getSort()) {
            case Type.VOID:
                mv.visitInsn(ACONST_NULL);
                break;
            case Type.BOOLEAN:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
                break;
            case Type.BYTE:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
                break;
            case Type.CHAR:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
                break;
            case Type.SHORT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
                break;
            case Type.INT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
                break;
            case Type.FLOAT:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
                break;
            case Type.LONG:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
                break;
            case Type.DOUBLE:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
                break;
            }

            mv.visitInsn(ARETURN);
        }

        mv.visitLabel(defaultLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
    }

    enhanceForThrowingException(mv, IllegalArgumentException.class, "Method not found", "Ljava/lang/Object;",
            ALOAD, 2);

    mv.visitMaxs(8, 6);
    mv.visitEnd();
}

From source file:org.jupiter.common.util.FastMethodAccessor.java

License:Apache License

private static FastMethodAccessor create(Class<?> type) {
    ArrayList<Method> methods = Lists.newArrayList();
    boolean isInterface = type.isInterface();
    if (!isInterface) {
        Class nextClass = type;/*from  w  ww . j av  a2  s .c  om*/
        while (nextClass != Object.class) {
            addDeclaredMethodsToList(nextClass, methods);
            nextClass = nextClass.getSuperclass();
        }
    } else {
        recursiveAddInterfaceMethodsToList(type, methods);
    }

    int n = methods.size();
    String[] methodNames = new String[n];
    Class<?>[][] parameterTypes_s = new Class[n][];
    Class<?>[] returnTypes = new Class[n];
    for (int i = 0; i < n; i++) {
        Method method = methods.get(i);
        methodNames[i] = method.getName();
        parameterTypes_s[i] = method.getParameterTypes();
        returnTypes[i] = method.getReturnType();
    }

    String className = type.getName();
    String accessorClassName = className + "_FastMethodAccessor";
    String accessorClassNameInternal = accessorClassName.replace('.', '/');
    String classNameInternal = className.replace('.', '/');
    String superClassNameInternal = FastMethodAccessor.class.getName().replace('.', '/');

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    MethodVisitor mv;
    cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessorClassNameInternal, null, superClassNameInternal, null);

    // ?
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, superClassNameInternal, "<init>", "()V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

    // : public Object invoke(Object obj, int methodIndex, Object... args);
    {
        mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invoke",
                "(Ljava/lang/Object;I[Ljava/lang/Object;)Ljava/lang/Object;", null, null);
        mv.visitCode();

        if (n > 0) {
            // ?? obj  (Class<?> type)
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, classNameInternal);
            mv.visitVarInsn(ASTORE, 4);

            // ? switch ?
            mv.visitVarInsn(ILOAD, 2);
            Label[] labels = new Label[n];
            for (int i = 0; i < n; i++) {
                labels[i] = new Label();
            }
            Label defaultLabel = new Label(); // the default handler block
            mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

            StringBuilder buf = new StringBuilder(128);
            for (int i = 0; i < n; i++) {
                mv.visitLabel(labels[i]);
                if (i == 0) {
                    mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { classNameInternal }, 0, null);
                } else {
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }
                mv.visitVarInsn(ALOAD, 4);

                buf.setLength(0);
                buf.append('(');

                Class<?>[] parameterTypes = parameterTypes_s[i];
                Class<?> returnType = returnTypes[i];
                for (int p_index = 0; p_index < parameterTypes.length; p_index++) {
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitIntInsn(BIPUSH, p_index);
                    mv.visitInsn(AALOAD);

                    // ?, (?)
                    Type p_type = Type.getType(parameterTypes[p_index]);
                    switch (p_type.getSort()) {
                    case Type.BOOLEAN:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
                        break;
                    case Type.BYTE:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
                        break;
                    case Type.CHAR:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
                        break;
                    case Type.SHORT:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
                        break;
                    case Type.INT:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
                        break;
                    case Type.FLOAT:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
                        break;
                    case Type.LONG:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
                        break;
                    case Type.DOUBLE:
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
                        break;
                    case Type.ARRAY:
                        mv.visitTypeInsn(CHECKCAST, p_type.getDescriptor());
                        break;
                    case Type.OBJECT:
                        mv.visitTypeInsn(CHECKCAST, p_type.getInternalName());
                        break;
                    }
                    buf.append(p_type.getDescriptor());
                }

                buf.append(')').append(Type.getDescriptor(returnType));

                // ??, ???
                if (isInterface) {
                    mv.visitMethodInsn(INVOKEINTERFACE, classNameInternal, methodNames[i], buf.toString(),
                            true);
                } else if (Modifier.isStatic(methods.get(i).getModifiers())) {
                    mv.visitMethodInsn(INVOKESTATIC, classNameInternal, methodNames[i], buf.toString(), false);
                } else {
                    mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, methodNames[i], buf.toString(), false);
                }

                Type r_type = Type.getType(returnType);
                switch (r_type.getSort()) {
                case Type.VOID:
                    mv.visitInsn(ACONST_NULL);
                    break;
                case Type.BOOLEAN:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;",
                            false);
                    break;
                case Type.BYTE:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
                    break;
                case Type.CHAR:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf",
                            "(C)Ljava/lang/Character;", false);
                    break;
                case Type.SHORT:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;",
                            false);
                    break;
                case Type.INT:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;",
                            false);
                    break;
                case Type.FLOAT:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;",
                            false);
                    break;
                case Type.LONG:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
                    break;
                case Type.DOUBLE:
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;",
                            false);
                    break;
                }
                mv.visitInsn(ARETURN);
            }
            mv.visitLabel(defaultLabel); //  default ??
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }

        // throw exception (method not found)
        mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
        mv.visitInsn(DUP);
        mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("method not found: ");
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;",
                false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>",
                "(Ljava/lang/String;)V", false);
        mv.visitInsn(ATHROW);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

    cw.visitEnd();
    byte[] bytes = cw.toByteArray();

    AccessorClassLoader loader = AccessorClassLoader.get(type);
    Class<?> accessorClass = loader.defineClass(accessorClassName, bytes);
    try {
        FastMethodAccessor accessor = (FastMethodAccessor) accessorClass.newInstance();
        accessor.methodNames = methodNames;
        accessor.parameterTypes_s = parameterTypes_s;
        return accessor;
    } catch (Throwable t) {
        throw new RuntimeException("Error constructing method access class: " + accessorClass, t);
    }
}

From source file:org.mbte.groovypp.compiler.asm.VisitTableSwitchInsn.java

License:Apache License

public void visit(MethodVisitor mv) {
    mv.visitTableSwitchInsn(min, max, dflt, labels);
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static boolean encodeSwitchStatement(JavaStatement.SwitchStatement switchStatement,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    // Append the instructions to evaluate the condition, leaving the result on the operand stack.
    JavaExpression condition = switchStatement.getCondition();
    encodeExpr(condition, context);//  w  w w.  jav  a2 s. c  om

    // Follow (what seems to be) javac's rule for deciding between a lookup switch and a table switch:
    //      Use a table switch if allowed by maxTableSize, where
    //          maxTableSize = (# cases - 2) * 5  , (# cases) doesn't include the default.
    //
    // eg. if there are 2 case alternatives (+ default): 
    //          maxTableSize = ((2 - 2) * 5) = 0, so always use a lookup switch.
    //     if there are cases {1, 2, 3, 4, 15}:
    //          maxTableSize = ((5 - 2) * 5) = 15.  A table would contain 15 entries {1, 2, .., 15}, so use a table switch.
    //     if there are cases {1, 2, 3, 4, 16}:
    //          A table would contain 16 entries {1, 2, .., 16}, so use a lookup switch.
    List<IntCaseGroup> caseGroups = switchStatement.getCaseGroups();
    int nTotalCases = 0;

    // Calculate the first and last values.
    int firstValue = Integer.MAX_VALUE;
    int lastValue = Integer.MIN_VALUE;
    for (int caseN = 0; caseN < caseGroups.size(); ++caseN) {
        SwitchStatement.IntCaseGroup switchCaseGroup = caseGroups.get(caseN);
        for (int i = 0, nCaseLabels = switchCaseGroup.getNCaseLabels(); i < nCaseLabels; i++) {
            nTotalCases++;
            int caseLabel = switchCaseGroup.getNthCaseLabel(i);
            if (firstValue > caseLabel) {
                firstValue = caseLabel;
            }

            if (lastValue < caseLabel) {
                lastValue = caseLabel;
            }
        }
    }

    if (nTotalCases == 0) {
        // If the switch statement contains no cases, javac's behaviour is to generate a pop instruction
        // to pop the condition value off the operand stack.
        mv.visitInsn(Opcodes.POP);

    } else {

        int nSpannedCases = lastValue - firstValue + 1;

        int maxTableSize = (nTotalCases - 2) * 5;
        boolean useTableSwitch = !(nSpannedCases > maxTableSize);

        // Create the default label and declare the other case labels.
        Label defaultLabel = new Label();

        // (SwitchStatement.IntCaseGroup->Label) A map from case group to label.
        Map<IntCaseGroup, Label> caseGroupToLabelMap = new HashMap<IntCaseGroup, Label>();

        if (!useTableSwitch) {
            // A lookup switch.  Each case match gets its own label.

            // Map from case label to label, sorted by case label.
            SortedMap<Integer, Label> caseLabelToLabelMap = new TreeMap<Integer, Label>();

            // A count of the number of case labels.
            int nCaseLabels = 0;

            // Create the labels, and populate the map.
            for (int caseN = 0; caseN < caseGroups.size(); ++caseN) {
                SwitchStatement.IntCaseGroup switchCaseGroup = caseGroups.get(caseN);

                // The label for this case group.
                Label label = new Label();
                caseGroupToLabelMap.put(switchCaseGroup, label);

                for (int i = 0, nCaseGroupLabels = switchCaseGroup
                        .getNCaseLabels(); i < nCaseGroupLabels; i++) {
                    int caseLabel = switchCaseGroup.getNthCaseLabel(i);
                    caseLabelToLabelMap.put(Integer.valueOf(caseLabel), label);
                    nCaseLabels++;
                }
            }

            // Create the array for case matches and the corresponding labels.
            int[] caseMatches = new int[nCaseLabels];
            Label[] labels = new Label[nCaseLabels];

            int index = 0;
            for (final Map.Entry<Integer, Label> entry : caseLabelToLabelMap.entrySet()) {
                Integer caseLabelInteger = entry.getKey();
                caseMatches[index] = caseLabelInteger.intValue();
                labels[index] = entry.getValue();
                index++;
            }

            // Visit the lookup switch instruction.
            mv.visitLookupSwitchInsn(defaultLabel, caseMatches, labels);

        } else {
            // A table switch 
            // The cases which aren't given should be set to the default case.

            Label[] labels = new Label[nSpannedCases];

            // Initially set all elements to the default label, if they won't all be set to something else later.
            if (nSpannedCases != nTotalCases) {
                Arrays.fill(labels, defaultLabel);
            }

            // For each switch case provided, create a new label.
            for (int caseN = 0; caseN < caseGroups.size(); ++caseN) {
                SwitchStatement.IntCaseGroup switchCaseGroup = caseGroups.get(caseN);

                // The label for this case group.
                Label label = new Label();
                caseGroupToLabelMap.put(switchCaseGroup, label);

                for (int i = 0, nCaseGroupLabels = switchCaseGroup
                        .getNCaseLabels(); i < nCaseGroupLabels; i++) {
                    int caseLabel = switchCaseGroup.getNthCaseLabel(i);
                    int labelArrayIndex = caseLabel - firstValue;

                    labels[labelArrayIndex] = label;
                }
            }

            // Visit the table switch instruction.
            mv.visitTableSwitchInsn(firstValue, lastValue, defaultLabel, labels);
        }

        // Iterate over the cases.       
        for (int caseN = 0; caseN < caseGroups.size(); ++caseN) {
            SwitchStatement.IntCaseGroup switchCase = caseGroups.get(caseN);
            JavaStatement caseStatementGroup = switchCase.getStatement();

            // Add a local scope..
            GenerationContext innerContext = new GenerationContext(context);

            // Get the label to visit..
            Label labelToVisit = caseGroupToLabelMap.get(switchCase);

            //mark the location of the code for the i'th case.
            mv.visitLabel(labelToVisit);

            // get the instructions for the case statement.
            boolean caseStatementIsTerminating = encodeStatement(caseStatementGroup, innerContext);
            context.addJumpReturnLabelInfo(innerContext);

            // We don't (yet) handle non-terminating code in a case block.
            if (!caseStatementIsTerminating) {
                throw new JavaGenerationException("Can't (yet) handle non-terminating code in a case block.");
            }
        }

        JavaStatement defaultStatementGroup = switchStatement.getDefaultStatement();
        //mark the location of the default statements (even if there are none, this means just progress to the next instruction..)
        mv.visitLabel(defaultLabel);
        if (defaultStatementGroup != null) {
            // Add a local scope..
            GenerationContext innerContext = new GenerationContext(context);

            boolean defaultStatementIsTerminating = encodeStatement(defaultStatementGroup, innerContext);
            context.addJumpReturnLabelInfo(innerContext);

            // We don't (yet) handle non-terminating code in a case block.
            if (!defaultStatementIsTerminating) {
                throw new JavaGenerationException("Can't (yet) handle non-terminating code in a case block.");
            }
        }
    }

    // Note: we should add GOTO instructions to each case block to jump to after the switch statement if necessary.
    //   But for now it's not necessary since all cases are terminated.
    boolean isTerminating = true;

    return isTerminating;
}

From source file:org.simantics.databoard.binding.reflection.AsmBindingClassLoader.java

License:Open Source License

public byte[] createBindingClass(ClassInfo ci, String bindingClassName) {
    //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");
    int count = ci.fields.length;
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = cw;//new CheckClassAdapter(cw);

    FieldVisitor fv;// w w  w .  j a v a2s  .c  om
    MethodVisitor mv;
    AnnotationVisitor av0;

    String className = ci.clazz.getName().replaceAll("\\.", "/");
    bindingClassName = bindingClassName.replaceAll("\\.", "/");
    Object[] classNameX = new Object[] { className };
    String signature = "L" + bindingClassName + ";";

    // Constructor
    String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";
    cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null);

    // Constructor
    {
        mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });

        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitLdcInsn(Type.getType("L" + className + ";"));
        mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");

        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");

        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitInsn(RETURN);

        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLocalVariable("this", signature, null, l0, l3, 0);
        mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }

    // getComponent
    {
        mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 3);
        Label l1 = new Label();
        mv.visitLabel(l1);

        Label caseLabels[] = createFieldLabels(ci);
        Label elseLabel = new Label();

        if (count > 0) {
            // Switch
            mv.visitVarInsn(ILOAD, 2);
            mv.visitTableSwitchInsn(0, count - 1, elseLabel, caseLabels);

            // case i: x.field = value[i]
            for (int i = 0; i < count; i++) {
                Label label = caseLabels[i];
                Field field = ci.fields[i];
                String fieldName = field.getName();
                Class<?> fieldClass = ci.fields[i].getType();
                String typeDescriptor = toTypeDescriptor(fieldClass);

                Method getter = ci.getters[i];
                boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter != null;

                mv.visitLabel(label);
                if (i == 0) {
                    mv.visitFrame(Opcodes.F_APPEND, 1, classNameX, 0, null);
                } else {
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }

                // Read instance argument
                mv.visitVarInsn(ALOAD, 3);

                if (useGetter) {
                    // call getField
                    mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()" + typeDescriptor);
                } else {
                    // Read field
                    mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);
                }

                // Box 
                box(mv, fieldClass);

                mv.visitInsn(ARETURN);
            }

        }

        mv.visitLabel(elseLabel);
        if (count > 0) {
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }
        mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Illegal field index");
        mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>",
                "(Ljava/lang/String;)V");
        mv.visitInsn(ATHROW);

        // End 
        Label l19 = new Label();
        mv.visitLabel(l19);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l19, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);
        mv.visitLocalVariable("index", "I", null, l0, l19, 2);
        //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // Create
    {
        mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        if (ci.beanConstructor != null) {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>",
                    "(Lorg/simantics/databoard/binding/Binding;)V");
            mv.visitVarInsn(ASTORE, 2);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents",
                    "(Ljava/lang/Object;[Ljava/lang/Object;)V");
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitInsn(ARETURN);
            Label l3 = new Label();
            mv.visitLabel(l3);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l3, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
            //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        } else if (ci.argsConstructor != null) {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);

            String constArgsDescriptor = "(";
            Class<?>[] args = ci.argsConstructor.getParameterTypes();
            for (int i = 0; i < count; i++) {
                Label label = new Label();
                Class<?> field = args[i];
                String fieldName = field.getName();
                Method getter = ci.getters[i];
                Class<?> fieldClass = ci.fields[i].getType();
                Class<?> boxClass = getBoxClass(fieldClass);
                String typeDescriptor = toTypeDescriptor(fieldClass);
                String boxTypeDescriptor = toTypeDescriptor(boxClass);
                constArgsDescriptor += typeDescriptor;

                mv.visitLabel(label);
                mv.visitVarInsn(ALOAD, 1);
                if (i < 6) {
                    mv.visitInsn(ICONST_0 + i);
                } else {
                    mv.visitIntInsn(BIPUSH, i);
                }

                mv.visitInsn(AALOAD);
                mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));
                unbox(mv, fieldClass);
            }

            Label l17 = new Label();
            mv.visitLabel(l17);
            constArgsDescriptor += ")V";
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);
            mv.visitInsn(ARETURN);
            Label l18 = new Label();
            mv.visitLabel(l18);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l18, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);
            mv.visitMaxs(21, 2);
            mv.visitEnd();

        } else {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
            mv.visitVarInsn(ASTORE, 2);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents",
                    "(Ljava/lang/Object;[Ljava/lang/Object;)V");
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitInsn(ARETURN);
            Label l3 = new Label();
            mv.visitLabel(l3);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l3, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
            //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        }
    }

    // CreatePartial
    mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null,
            new String[] { "org/simantics/databoard/binding/error/BindingException" });
    if (ci.beanConstructor != null) {
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitTypeInsn(NEW, className);
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");
        mv.visitInsn(ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l1, 0);
        mv.visitMaxs(3, 1);
        mv.visitEnd();
    } else if (ci.noArgsConstructor != null) {
        // return new MyClass();
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitTypeInsn(NEW, className);
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
        mv.visitInsn(ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l1, 0);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    } else {
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitIntInsn(BIPUSH, count);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitVarInsn(ASTORE, 1);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ISTORE, 2);
        Label l2 = new Label();
        mv.visitLabel(l2);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_APPEND, 2, new Object[] { "[Ljava/lang/Object;", Opcodes.INTEGER }, 0, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings",
                "[Lorg/simantics/databoard/binding/Binding;");
        mv.visitVarInsn(ILOAD, 2);
        mv.visitInsn(AALOAD);
        mv.visitVarInsn(ASTORE, 3);
        Label l5 = new Label();
        mv.visitLabel(l5);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault",
                "()Ljava/lang/Object;");
        mv.visitInsn(AASTORE);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitIincInsn(2, 1);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(ARRAYLENGTH);
        mv.visitJumpInsn(IF_ICMPLT, l4);
        Label l7 = new Label();
        mv.visitLabel(l7);
        mv.visitLineNumber(109, l7);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create",
                "([Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(ARETURN);
        Label l8 = new Label();
        mv.visitLabel(l8);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l8, 0);
        mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);
        mv.visitLocalVariable("i", "I", null, l2, l7, 2);
        mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // setComponent
    {
        mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 4);
        Label endLabel = new Label();
        Label l1 = new Label();
        mv.visitLabel(l1);

        Label elseLabel = new Label();
        Label labels[] = new Label[count];
        for (int i = 0; i < count; i++)
            labels[i] = new Label();

        if (count > 0) {
            mv.visitVarInsn(ILOAD, 2);
            mv.visitTableSwitchInsn(0, count - 1, elseLabel, labels);

            for (int i = 0; i < count; i++) {
                Label label = labels[i];
                mv.visitLabel(label);
                Field field = ci.fields[i];
                String fieldName = field.getName();
                Class<?> fieldClass = ci.fields[i].getType();
                Class<?> boxClass = getBoxClass(fieldClass);
                String typeDescriptor = toTypeDescriptor(fieldClass);
                String boxTypeDescriptor = toTypeDescriptor(boxClass);

                Method setter = ci.setters[i];
                Class<?> setterClass = setter != null ? setter.getParameterTypes()[0] : null;
                boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter != null;

                if (i == 0) {
                    mv.visitFrame(Opcodes.F_APPEND, 1, classNameX, 0, null);
                } else {
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }
                mv.visitVarInsn(ALOAD, 4);
                mv.visitVarInsn(ALOAD, 3);
                mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));

                if (useSetter) {
                    unbox(mv, setterClass);
                    mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "(" + typeDescriptor + ")V");
                } else {
                    unbox(mv, fieldClass);
                    mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
                }
                mv.visitInsn(RETURN);
            }
        }

        mv.visitLabel(elseLabel);
        mv.visitLineNumber(178, elseLabel);
        if (count > 0) {
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }
        mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Illegal field index");
        mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>",
                "(Ljava/lang/String;)V");
        mv.visitInsn(ATHROW);

        mv.visitLabel(endLabel);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, endLabel, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
        mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);
        mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);
        //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);
        mv.visitMaxs(3, 5);
        mv.visitEnd();
    }

    // IsImmutable
    {
        mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitInsn(ICONST_0);
        mv.visitInsn(IRETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    // IsInstance
    {
        mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(INSTANCEOF, className);
        mv.visitInsn(IRETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);
        mv.visitMaxs(1, 2);
        mv.visitEnd();
    }

    // SetComponents
    {
        mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "setComponents",
                "(Ljava/lang/Object;[Ljava/lang/Object;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 3);
        Label firstLabel = l0;

        for (int i = 0; i < count; i++) {
            Label label = new Label();
            if (firstLabel == l0)
                firstLabel = label;
            Field field = ci.fields[i];
            String fieldName = field.getName();
            Class<?> fieldClass = ci.fields[i].getType();
            Class<?> boxClass = getBoxClass(fieldClass);
            String typeDescriptor = toTypeDescriptor(fieldClass);
            String boxTypeDescriptor = toTypeDescriptor(boxClass);

            Method setter = ci.setters[i];
            Class<?> setterClass = setter != null ? setter.getParameterTypes()[0] : null;
            boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter != null;

            mv.visitLabel(label);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitVarInsn(ALOAD, 2);
            if (i < 6) {
                mv.visitInsn(ICONST_0 + i);
            } else {
                mv.visitIntInsn(BIPUSH, i);
            }
            mv.visitInsn(AALOAD);
            mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));

            if (useSetter) {
                unbox(mv, setterClass);
                mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "(" + typeDescriptor + ")V");
            } else {
                unbox(mv, fieldClass);
                mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
            }

        }
        Label l17 = new Label();
        mv.visitLabel(l17);
        mv.visitInsn(RETURN);
        Label endLabel = new Label();
        mv.visitLabel(endLabel);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, endLabel, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
        mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);
        //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // Add primitive setters
    {
        addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);
        addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);
        addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);
        addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);
        addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);
        addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);
    }

    cv.visitEnd();
    return cw.toByteArray();
}

From source file:org.springframework.migrationanalyzer.contributions.bytecode.DelegatingMethodVisitor.java

License:Apache License

@Override
public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
    for (MethodVisitor delegate : this.delegates) {
        delegate.visitTableSwitchInsn(min, max, dflt, labels);
    }//from  w w w. j ava2  s  .c om
}

From source file:org.xnio.http.tool.Generator.java

License:Open Source License

public static void main(String[] args) {
    MethodVisitor mv = null;
    mv.visitCode();/*from   w  ww  . ja v  a  2 s .c  o m*/
    final Label unknownMethod = new Label();
    final Label readMethod = new Label();
    final Label readUri = new Label();
    final Label readUriSubsequent = new Label();
    final Label readProto = new Label();
    final Label readProtoSubsequent = new Label();
    final Label readHeaders = new Label();
    final Label matchC = new Label();
    final Label matchCO = new Label();
    final Label matchCON = new Label();
    final Label matchCONN = new Label();
    final Label matchCONNE = new Label();
    final Label matchCONNEC = new Label();
    final Label matchCONNECT = new Label();
    final Label matchD = new Label();
    final Label matchDE = new Label();
    final Label matchDEL = new Label();
    final Label matchDELE = new Label();
    final Label matchDELET = new Label();
    final Label matchDELETE = new Label();
    final Label matchG = new Label();
    final Label matchGE = new Label();
    final Label matchGET = new Label();
    final Label matchH = new Label();
    final Label matchHE = new Label();
    final Label matchHEA = new Label();
    final Label matchHEAD = new Label();
    final Label matchO = new Label();
    final Label matchOP = new Label();
    final Label matchOPT = new Label();
    final Label matchOPTI = new Label();
    final Label matchOPTIO = new Label();
    final Label matchOPTION = new Label();
    final Label matchOPTIONS = new Label();
    final Label matchP = new Label();
    final Label matchPO = new Label();
    final Label matchPOS = new Label();
    final Label matchPOST = new Label();
    final Label matchPU = new Label();
    final Label matchPUT = new Label();
    final Label matchT = new Label();
    final Label matchTR = new Label();
    final Label matchTRA = new Label();
    final Label matchTRAC = new Label();
    final Label matchTRACE = new Label();
    final Label doReturn = new Label();
    final Label badState = new Label();

    final Label badRequest = new Label();

    mv.visitFieldInsn(GETFIELD, READ_LISTENER, "state", "I");
    final Label[] states = { readMethod, matchC, matchCO, matchCON, matchCONN, matchCONNE, matchCONNEC,
            matchCONNECT, matchD, matchDE, matchDEL, matchDELE, matchDELET, matchDELETE, matchG, matchGE,
            matchGET, matchH, matchHE, matchHEA, matchHEAD, matchO, matchOP, matchOPT, matchOPTI, matchOPTIO,
            matchOPTION, matchOPTIONS, matchP, matchPO, matchPOS, matchPOST, matchPU, matchPUT, matchT, matchTR,
            matchTRA, matchTRAC, matchTRACE, unknownMethod, readUri, readUriSubsequent, readProto,
            readProtoSubsequent, readHeaders, };
    mv.visitTableSwitchInsn(0, states.length - 1, badState, states);

    int c = 0;

    // Read an HTTP method
    mv.visitLabel(readMethod);
    visitRead(mv);
    final Label exitReadMethod = new Label();
    mv.visitLookupSwitchInsn(unknownMethod, new int[] { -1, 'C', 'D', 'G', 'H', 'O', 'P', 'T' },
            new Label[] { exitReadMethod, matchC, matchD, matchG, matchH, matchO, matchP, matchT });

    mv.visitLabel(exitReadMethod);
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitLabel(doReturn);
    mv.visitFieldInsn(PUTFIELD, READ_LISTENER, "state", "I");
    mv.visitIntInsn(BIPUSH, 1);
    mv.visitInsn(IRETURN);

    mv.visitLabel(badRequest);
    mv.visitIntInsn(BIPUSH, 0);
    mv.visitInsn(IRETURN);

    // match CONNECT
    doFirstStep(mv, c++, 'C', 'O', readUri, doReturn, unknownMethod, matchC, matchCO, badRequest);
    doSimpleStep(mv, c++, "CO", 'N', readUri, doReturn, unknownMethod, matchCO, matchCON, badRequest);
    doSimpleStep(mv, c++, "CON", 'N', readUri, doReturn, unknownMethod, matchCON, matchCONN, badRequest);
    doSimpleStep(mv, c++, "CONN", 'E', readUri, doReturn, unknownMethod, matchCONN, matchCONNE, badRequest);
    doSimpleStep(mv, c++, "CONNE", 'C', readUri, doReturn, unknownMethod, matchCONNE, matchCONNEC, badRequest);
    doSimpleStep(mv, c++, "CONNEC", 'T', readUri, doReturn, unknownMethod, matchCONNEC, matchCONNECT,
            badRequest);
    doFinalStep(mv, c++, "CONNECT", readUri, doReturn, unknownMethod, matchCONNECT, badRequest);

    // match DELETE
    doFirstStep(mv, c++, 'D', 'E', readUri, doReturn, unknownMethod, matchD, matchDE, badRequest);
    doSimpleStep(mv, c++, "DE", 'L', readUri, doReturn, unknownMethod, matchDE, matchDEL, badRequest);
    doSimpleStep(mv, c++, "DEL", 'E', readUri, doReturn, unknownMethod, matchDEL, matchDELE, badRequest);
    doSimpleStep(mv, c++, "DELE", 'T', readUri, doReturn, unknownMethod, matchDELE, matchDELET, badRequest);
    doSimpleStep(mv, c++, "DELET", 'E', readUri, doReturn, unknownMethod, matchDELET, matchDELETE, badRequest);
    doFinalStep(mv, c++, "DELETE", readUri, doReturn, unknownMethod, matchDELETE, badRequest);

    // match GET
    doFirstStep(mv, c++, 'G', 'E', readUri, doReturn, unknownMethod, matchG, matchGE, badRequest);
    doSimpleStep(mv, c++, "GE", 'T', readUri, doReturn, unknownMethod, matchGE, matchGET, badRequest);
    doFinalStep(mv, c++, "GET", readUri, doReturn, unknownMethod, matchGET, badRequest);

    // match HEAD
    doFirstStep(mv, c++, 'H', 'E', readUri, doReturn, unknownMethod, matchH, matchHE, badRequest);
    doSimpleStep(mv, c++, "HE", 'A', readUri, doReturn, unknownMethod, matchHE, matchHEA, badRequest);
    doSimpleStep(mv, c++, "HEA", 'D', readUri, doReturn, unknownMethod, matchHEA, matchHEAD, badRequest);
    doFinalStep(mv, c++, "HEAD", readUri, doReturn, unknownMethod, matchHEAD, badRequest);

    // match OPTIONS
    doFirstStep(mv, c++, 'O', 'P', readUri, doReturn, unknownMethod, matchO, matchOP, badRequest);
    doSimpleStep(mv, c++, "OP", 'T', readUri, doReturn, unknownMethod, matchOP, matchOPT, badRequest);
    doSimpleStep(mv, c++, "OPT", 'I', readUri, doReturn, unknownMethod, matchOPT, matchOPTI, badRequest);
    doSimpleStep(mv, c++, "OPTI", 'O', readUri, doReturn, unknownMethod, matchOPTI, matchOPTIO, badRequest);
    doSimpleStep(mv, c++, "OPTIO", 'N', readUri, doReturn, unknownMethod, matchOPTIO, matchOPTION, badRequest);
    doSimpleStep(mv, c++, "OPTION", 'S', readUri, doReturn, unknownMethod, matchOPTION, matchOPTIONS,
            badRequest);
    doFinalStep(mv, c++, "OPTIONS", readUri, doReturn, unknownMethod, matchOPTIONS, badRequest);

    // match POST or PUT
    doTwoStep(mv, c++, 'P', 'O', 'U', readUri, doReturn, unknownMethod, matchP, matchPO, matchPU, badRequest);

    // match POST
    doSimpleStep(mv, c++, "PO", 'S', readUri, doReturn, unknownMethod, matchPO, matchPOS, badRequest);
    doSimpleStep(mv, c++, "POS", 'T', readUri, doReturn, unknownMethod, matchPOS, matchPOST, badRequest);
    doFinalStep(mv, c++, "POST", readUri, doReturn, unknownMethod, matchPOST, badRequest);

    // match PUT
    doSimpleStep(mv, c++, "PU", 'T', readUri, doReturn, unknownMethod, matchPU, matchPUT, badRequest);
    doFinalStep(mv, c++, "PUT", readUri, doReturn, unknownMethod, matchPUT, badRequest);

    // match TRACE
    doFirstStep(mv, c++, 'T', 'R', readUri, doReturn, unknownMethod, matchT, matchTR, badRequest);
    doSimpleStep(mv, c++, "TR", 'A', readUri, doReturn, unknownMethod, matchTR, matchTRA, badRequest);
    doSimpleStep(mv, c++, "TRA", 'C', readUri, doReturn, unknownMethod, matchTRA, matchTRAC, badRequest);
    doSimpleStep(mv, c++, "TRAC", 'E', readUri, doReturn, unknownMethod, matchTRAC, matchTRACE, badRequest);
    doFinalStep(mv, c++, "TRACE", readUri, doReturn, unknownMethod, matchTRACE, badRequest);

    // build method from string using string builder
    mv.visitLabel(unknownMethod);
    visitRead(mv);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "isControl", "(C)Z");
    mv.visitJumpInsn(IFNE, badRequest);
    final Label doAppendMethod = new Label();
    final Label exitReadMethodBuild = new Label();
    final Label prepareReadUri = new Label();
    mv.visitLookupSwitchInsn(doAppendMethod, new int[] { -1, ' ' },
            new Label[] { exitReadMethodBuild, prepareReadUri });

    mv.visitLabel(doAppendMethod);
    mv.visitVarInsn(ALOAD, STRING_BUILDER);
    mv.visitVarInsn(ILOAD, CH);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(C)Ljava/lang/StringBuilder;");
    mv.visitJumpInsn(GOTO, unknownMethod);

    mv.visitLabel(exitReadMethodBuild); // ran out of buffer
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitJumpInsn(GOTO, doReturn);

    mv.visitLabel(prepareReadUri); // finished reading method, clear builder and move on to URI
    mv.visitVarInsn(ALOAD, STRING_BUILDER);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
    mv.visitFieldInsn(PUTFIELD, READ_LISTENER, "method", "Ljava/lang/String;");
    mv.visitIntInsn(BIPUSH, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "setLength", "(I)V");
    //mv.visitJumpInsn(GOTO, readUri); // fall through

    // read URI
    mv.visitLabel(readUri);
    visitRead(mv);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "isControl", "(C)Z");
    mv.visitJumpInsn(IFNE, badRequest);
    final Label doAppendUri = new Label();
    final Label exitReadUri = new Label();
    mv.visitLookupSwitchInsn(doAppendUri, new int[] { -1, ' ' }, new Label[] { exitReadUri, readUri });

    mv.visitLabel(exitReadUri);
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitJumpInsn(GOTO, doReturn);

    mv.visitLabel(doAppendUri);
    mv.visitVarInsn(ALOAD, STRING_BUILDER);
    mv.visitVarInsn(ILOAD, CH);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(C)Ljava/lang/StringBuilder;");
    //mv.visitJumpInsn(GOTO, readUriSubsequent); // fall through

    mv.visitLabel(readUriSubsequent);
    visitRead(mv);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "isControl", "(C)Z");
    mv.visitJumpInsn(IFNE, badRequest);
    final Label exitReadUriSubsequent = new Label();
    final Label prepareReadProtocol = new Label();
    mv.visitLookupSwitchInsn(doAppendUri, new int[] { -1, ' ', },
            new Label[] { exitReadUriSubsequent, prepareReadProtocol });

    mv.visitLabel(exitReadUriSubsequent);
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitJumpInsn(GOTO, doReturn);

    mv.visitLabel(prepareReadProtocol);
    mv.visitVarInsn(ALOAD, STRING_BUILDER);
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
    mv.visitFieldInsn(PUTFIELD, READ_LISTENER, "requestUri", "Ljava/lang/String;");
    mv.visitIntInsn(BIPUSH, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "setLength", "(I)V");
    //mv.visitJumpInsn(GOTO, readProto); // fall through

    mv.visitLabel(readProto);
    visitRead(mv);
    final Label doAppendProto = new Label();
    final Label exitReadProto = new Label();
    mv.visitLookupSwitchInsn(doAppendProto, new int[] { -1, ' ' }, new Label[] { exitReadProto, readProto });

    mv.visitLabel(exitReadProto);
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitJumpInsn(GOTO, doReturn);

    mv.visitLabel(doAppendProto);
    mv.visitVarInsn(ILOAD, CH);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "isControl", "(C)Z");
    mv.visitJumpInsn(IFNE, badRequest);
    mv.visitVarInsn(ALOAD, STRING_BUILDER);
    mv.visitVarInsn(ILOAD, CH);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(C)Ljava/lang/StringBuilder;");
    //mv.visitJumpInsn(GOTO, readProtoSubsequent); // fall through

    mv.visitLabel(readProtoSubsequent);
    visitRead(mv);
    final Label exitReadProtoSubsequent = new Label();
    final Label prepareReadHeaders = new Label();
    mv.visitLookupSwitchInsn(doAppendProto, new int[] { -1, '\r', ' ' },
            new Label[] { exitReadProtoSubsequent, prepareReadHeaders, badRequest });

    mv.visitLabel(exitReadProtoSubsequent);
    mv.visitIntInsn(BIPUSH, c++);
    mv.visitJumpInsn(GOTO, doReturn);

    mv.visitLabel(prepareReadHeaders);

    // done!
    mv.visitMaxs();
}