public void accept()

in src/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassReader.java [471:1487]


    public void accept(
        final ClassVisitor classVisitor,
        final Attribute[] attrs,
        final int flags)
    {
        byte[] b = this.b; // the bytecode array
        char[] c = new char[maxStringLength]; // buffer used to read strings
        int i, j, k; // loop variables
        int u, v, w; // indexes in b
        Attribute attr;

        int access;
        String name;
        String desc;
        String attrName;
        String signature;
        int anns = 0;
        int ianns = 0;
        Attribute cattrs = null;

        // visits the header
        u = header;
        access = readUnsignedShort(u);
        name = readClass(u + 2, c);
        v = items[readUnsignedShort(u + 4)];
        String superClassName = v == 0 ? null : readUTF8(v, c);
        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
        w = 0;
        u += 8;
        for (i = 0; i < implementedItfs.length; ++i) {
            implementedItfs[i] = readClass(u, c);
            u += 2;
        }

        boolean skipCode = (flags & SKIP_CODE) != 0;
        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
        boolean unzip = (flags & EXPAND_FRAMES) != 0;

        // skips fields and methods
        v = u;
        i = readUnsignedShort(v);
        v += 2;
        for (; i > 0; --i) {
            j = readUnsignedShort(v + 6);
            v += 8;
            for (; j > 0; --j) {
                v += 6 + readInt(v + 2);
            }
        }
        i = readUnsignedShort(v);
        v += 2;
        for (; i > 0; --i) {
            j = readUnsignedShort(v + 6);
            v += 8;
            for (; j > 0; --j) {
                v += 6 + readInt(v + 2);
            }
        }
        // reads the class's attributes
        signature = null;
        String sourceFile = null;
        String sourceDebug = null;
        String enclosingOwner = null;
        String enclosingName = null;
        String enclosingDesc = null;

        i = readUnsignedShort(v);
        v += 2;
        for (; i > 0; --i) {
            attrName = readUTF8(v, c);
            // tests are sorted in decreasing frequency order
            // (based on frequencies observed on typical classes)
            if ("SourceFile".equals(attrName)) {
                sourceFile = readUTF8(v + 6, c);
            } else if ("InnerClasses".equals(attrName)) {
                w = v + 6;
            } else if ("EnclosingMethod".equals(attrName)) {
                enclosingOwner = readClass(v + 6, c);
                int item = readUnsignedShort(v + 8);
                if (item != 0) {
                    enclosingName = readUTF8(items[item], c);
                    enclosingDesc = readUTF8(items[item] + 2, c);
                }
            } else if (SIGNATURES && "Signature".equals(attrName)) {
                signature = readUTF8(v + 6, c);
            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
                anns = v + 6;
            } else if ("Deprecated".equals(attrName)) {
                access |= Opcodes.ACC_DEPRECATED;
            } else if ("Synthetic".equals(attrName)) {
                access |= Opcodes.ACC_SYNTHETIC;
            } else if ("SourceDebugExtension".equals(attrName)) {
                int len = readInt(v + 2);
                sourceDebug = readUTF(v + 6, len, new char[len]);
            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
                ianns = v + 6;
            } else {
                attr = readAttribute(attrs,
                        attrName,
                        v + 6,
                        readInt(v + 2),
                        c,
                        -1,
                        null);
                if (attr != null) {
                    attr.next = cattrs;
                    cattrs = attr;
                }
            }
            v += 6 + readInt(v + 2);
        }
        // calls the visit method
        classVisitor.visit(readInt(4),
                access,
                name,
                signature,
                superClassName,
                implementedItfs);

        // calls the visitSource method
        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
            classVisitor.visitSource(sourceFile, sourceDebug);
        }

        // calls the visitOuterClass method
        if (enclosingOwner != null) {
            classVisitor.visitOuterClass(enclosingOwner,
                    enclosingName,
                    enclosingDesc);
        }

        // visits the class annotations
        if (ANNOTATIONS) {
            for (i = 1; i >= 0; --i) {
                v = i == 0 ? ianns : anns;
                if (v != 0) {
                    j = readUnsignedShort(v);
                    v += 2;
                    for (; j > 0; --j) {
                        v = readAnnotationValues(v + 2,
                                c,
                                true,
                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
                    }
                }
            }
        }

        // visits the class attributes
        while (cattrs != null) {
            attr = cattrs.next;
            cattrs.next = null;
            classVisitor.visitAttribute(cattrs);
            cattrs = attr;
        }

        // calls the visitInnerClass method
        if (w != 0) {
            i = readUnsignedShort(w);
            w += 2;
            for (; i > 0; --i) {
                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
                        ? null
                        : readClass(w, c), readUnsignedShort(w + 2) == 0
                        ? null
                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
                        ? null
                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
                w += 8;
            }
        }

        // visits the fields
        i = readUnsignedShort(u);
        u += 2;
        for (; i > 0; --i) {
            access = readUnsignedShort(u);
            name = readUTF8(u + 2, c);
            desc = readUTF8(u + 4, c);
            // visits the field's attributes and looks for a ConstantValue
            // attribute
            int fieldValueItem = 0;
            signature = null;
            anns = 0;
            ianns = 0;
            cattrs = null;

            j = readUnsignedShort(u + 6);
            u += 8;
            for (; j > 0; --j) {
                attrName = readUTF8(u, c);
                // tests are sorted in decreasing frequency order
                // (based on frequencies observed on typical classes)
                if ("ConstantValue".equals(attrName)) {
                    fieldValueItem = readUnsignedShort(u + 6);
                } else if (SIGNATURES && "Signature".equals(attrName)) {
                    signature = readUTF8(u + 6, c);
                } else if ("Deprecated".equals(attrName)) {
                    access |= Opcodes.ACC_DEPRECATED;
                } else if ("Synthetic".equals(attrName)) {
                    access |= Opcodes.ACC_SYNTHETIC;
                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
                    anns = u + 6;
                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
                    ianns = u + 6;
                } else {
                    attr = readAttribute(attrs,
                            attrName,
                            u + 6,
                            readInt(u + 2),
                            c,
                            -1,
                            null);
                    if (attr != null) {
                        attr.next = cattrs;
                        cattrs = attr;
                    }
                }
                u += 6 + readInt(u + 2);
            }
            // visits the field
            FieldVisitor fv = classVisitor.visitField(access,
                    name,
                    desc,
                    signature,
                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
            // visits the field annotations and attributes
            if (fv != null) {
                if (ANNOTATIONS) {
                    for (j = 1; j >= 0; --j) {
                        v = j == 0 ? ianns : anns;
                        if (v != 0) {
                            k = readUnsignedShort(v);
                            v += 2;
                            for (; k > 0; --k) {
                                v = readAnnotationValues(v + 2,
                                        c,
                                        true,
                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
                            }
                        }
                    }
                }
                while (cattrs != null) {
                    attr = cattrs.next;
                    cattrs.next = null;
                    fv.visitAttribute(cattrs);
                    cattrs = attr;
                }
                fv.visitEnd();
            }
        }

        // visits the methods
        i = readUnsignedShort(u);
        u += 2;
        for (; i > 0; --i) {
            int u0 = u + 6;
            access = readUnsignedShort(u);
            name = readUTF8(u + 2, c);
            desc = readUTF8(u + 4, c);
            signature = null;
            anns = 0;
            ianns = 0;
            int dann = 0;
            int mpanns = 0;
            int impanns = 0;
            cattrs = null;
            v = 0;
            w = 0;

            // looks for Code and Exceptions attributes
            j = readUnsignedShort(u + 6);
            u += 8;
            for (; j > 0; --j) {
                attrName = readUTF8(u, c);
                int attrSize = readInt(u + 2);
                u += 6;
                // tests are sorted in decreasing frequency order
                // (based on frequencies observed on typical classes)
                if ("Code".equals(attrName)) {
                    if (!skipCode) {
                        v = u;
                    }
                } else if ("Exceptions".equals(attrName)) {
                    w = u;
                } else if (SIGNATURES && "Signature".equals(attrName)) {
                    signature = readUTF8(u, c);
                } else if ("Deprecated".equals(attrName)) {
                    access |= Opcodes.ACC_DEPRECATED;
                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
                    anns = u;
                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
                    dann = u;
                } else if ("Synthetic".equals(attrName)) {
                    access |= Opcodes.ACC_SYNTHETIC;
                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
                    ianns = u;
                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
                {
                    mpanns = u;
                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
                {
                    impanns = u;
                } else {
                    attr = readAttribute(attrs,
                            attrName,
                            u,
                            attrSize,
                            c,
                            -1,
                            null);
                    if (attr != null) {
                        attr.next = cattrs;
                        cattrs = attr;
                    }
                }
                u += attrSize;
            }
            // reads declared exceptions
            String[] exceptions;
            if (w == 0) {
                exceptions = null;
            } else {
                exceptions = new String[readUnsignedShort(w)];
                w += 2;
                for (j = 0; j < exceptions.length; ++j) {
                    exceptions[j] = readClass(w, c);
                    w += 2;
                }
            }

            // visits the method's code, if any
            MethodVisitor mv = classVisitor.visitMethod(access,
                    name,
                    desc,
                    signature,
                    exceptions);

            if (mv != null) {
                /*
                 * if the returned MethodVisitor is in fact a MethodWriter, it
                 * means there is no method adapter between the reader and the
                 * writer. If, in addition, the writer's constant pool was
                 * copied from this reader (mw.cw.cr == this), and the signature
                 * and exceptions of the method have not been changed, then it
                 * is possible to skip all visit events and just copy the
                 * original code of the method to the writer (the access, name
                 * and descriptor can have been changed, this is not important
                 * since they are not copied as is from the reader).
                 */
                if (WRITER && mv instanceof MethodWriter) {
                    MethodWriter mw = (MethodWriter) mv;
                    if (mw.cw.cr == this) {
                        if (signature == mw.signature) {
                            boolean sameExceptions = false;
                            if (exceptions == null) {
                                sameExceptions = mw.exceptionCount == 0;
                            } else {
                                if (exceptions.length == mw.exceptionCount) {
                                    sameExceptions = true;
                                    for (j = exceptions.length - 1; j >= 0; --j)
                                    {
                                        w -= 2;
                                        if (mw.exceptions[j] != readUnsignedShort(w))
                                        {
                                            sameExceptions = false;
                                            break;
                                        }
                                    }
                                }
                            }
                            if (sameExceptions) {
                                /*
                                 * we do not copy directly the code into
                                 * MethodWriter to save a byte array copy
                                 * operation. The real copy will be done in
                                 * ClassWriter.toByteArray().
                                 */
                                mw.classReaderOffset = u0;
                                mw.classReaderLength = u - u0;
                                continue;
                            }
                        }
                    }
                }

                if (ANNOTATIONS && dann != 0) {
                    AnnotationVisitor dv = mv.visitAnnotationDefault();
                    readAnnotationValue(dann, c, null, dv);
                    if (dv != null) {
                        dv.visitEnd();
                    }
                }
                if (ANNOTATIONS) {
                    for (j = 1; j >= 0; --j) {
                        w = j == 0 ? ianns : anns;
                        if (w != 0) {
                            k = readUnsignedShort(w);
                            w += 2;
                            for (; k > 0; --k) {
                                w = readAnnotationValues(w + 2,
                                        c,
                                        true,
                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
                            }
                        }
                    }
                }
                if (ANNOTATIONS && mpanns != 0) {
                    readParameterAnnotations(mpanns, desc, c, true, mv);
                }
                if (ANNOTATIONS && impanns != 0) {
                    readParameterAnnotations(impanns, desc, c, false, mv);
                }
                while (cattrs != null) {
                    attr = cattrs.next;
                    cattrs.next = null;
                    mv.visitAttribute(cattrs);
                    cattrs = attr;
                }
            }

            if (mv != null && v != 0) {
                int maxStack = readUnsignedShort(v);
                int maxLocals = readUnsignedShort(v + 2);
                int codeLength = readInt(v + 4);
                v += 8;

                int codeStart = v;
                int codeEnd = v + codeLength;

                mv.visitCode();

                // 1st phase: finds the labels
                int label;
                Label[] labels = new Label[codeLength + 2];
                readLabel(codeLength + 1, labels);
                while (v < codeEnd) {
                    w = v - codeStart;
                    int opcode = b[v] & 0xFF;
                    switch (ClassWriter.TYPE[opcode]) {
                        case ClassWriter.NOARG_INSN:
                        case ClassWriter.IMPLVAR_INSN:
                            v += 1;
                            break;
                        case ClassWriter.LABEL_INSN:
                            readLabel(w + readShort(v + 1), labels);
                            v += 3;
                            break;
                        case ClassWriter.LABELW_INSN:
                            readLabel(w + readInt(v + 1), labels);
                            v += 5;
                            break;
                        case ClassWriter.WIDE_INSN:
                            opcode = b[v + 1] & 0xFF;
                            if (opcode == Opcodes.IINC) {
                                v += 6;
                            } else {
                                v += 4;
                            }
                            break;
                        case ClassWriter.TABL_INSN:
                            // skips 0 to 3 padding bytes*
                            v = v + 4 - (w & 3);
                            // reads instruction
                            readLabel(w + readInt(v), labels);
                            j = readInt(v + 8) - readInt(v + 4) + 1;
                            v += 12;
                            for (; j > 0; --j) {
                                readLabel(w + readInt(v), labels);
                                v += 4;
                            }
                            break;
                        case ClassWriter.LOOK_INSN:
                            // skips 0 to 3 padding bytes*
                            v = v + 4 - (w & 3);
                            // reads instruction
                            readLabel(w + readInt(v), labels);
                            j = readInt(v + 4);
                            v += 8;
                            for (; j > 0; --j) {
                                readLabel(w + readInt(v + 4), labels);
                                v += 8;
                            }
                            break;
                        case ClassWriter.VAR_INSN:
                        case ClassWriter.SBYTE_INSN:
                        case ClassWriter.LDC_INSN:
                            v += 2;
                            break;
                        case ClassWriter.SHORT_INSN:
                        case ClassWriter.LDCW_INSN:
                        case ClassWriter.FIELDORMETH_INSN:
                        case ClassWriter.TYPE_INSN:
                        case ClassWriter.IINC_INSN:
                            v += 3;
                            break;
                        case ClassWriter.ITFMETH_INSN:
                            v += 5;
                            break;
                        // case MANA_INSN:
                        default:
                            v += 4;
                            break;
                    }
                }
                // parses the try catch entries
                j = readUnsignedShort(v);
                v += 2;
                for (; j > 0; --j) {
                    Label start = readLabel(readUnsignedShort(v), labels);
                    Label end = readLabel(readUnsignedShort(v + 2), labels);
                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
                    int type = readUnsignedShort(v + 6);
                    if (type == 0) {
                        mv.visitTryCatchBlock(start, end, handler, null);
                    } else {
                        mv.visitTryCatchBlock(start,
                                end,
                                handler,
                                readUTF8(items[type], c));
                    }
                    v += 8;
                }
                // parses the local variable, line number tables, and code
                // attributes
                int varTable = 0;
                int varTypeTable = 0;
                int stackMap = 0;
                int frameCount = 0;
                int frameMode = 0;
                int frameOffset = 0;
                int frameLocalCount = 0;
                int frameLocalDiff = 0;
                int frameStackCount = 0;
                Object[] frameLocal = null;
                Object[] frameStack = null;
                boolean zip = true;
                cattrs = null;
                j = readUnsignedShort(v);
                v += 2;
                for (; j > 0; --j) {
                    attrName = readUTF8(v, c);
                    if ("LocalVariableTable".equals(attrName)) {
                        if (!skipDebug) {
                            varTable = v + 6;
                            k = readUnsignedShort(v + 6);
                            w = v + 8;
                            for (; k > 0; --k) {
                                label = readUnsignedShort(w);
                                if (labels[label] == null) {
                                    readLabel(label, labels).status |= Label.DEBUG;
                                }
                                label += readUnsignedShort(w + 2);
                                if (labels[label] == null) {
                                    readLabel(label, labels).status |= Label.DEBUG;
                                }
                                w += 10;
                            }
                        }
                    } else if ("LocalVariableTypeTable".equals(attrName)) {
                        varTypeTable = v + 6;
                    } else if ("LineNumberTable".equals(attrName)) {
                        if (!skipDebug) {
                            k = readUnsignedShort(v + 6);
                            w = v + 8;
                            for (; k > 0; --k) {
                                label = readUnsignedShort(w);
                                if (labels[label] == null) {
                                    readLabel(label, labels).status |= Label.DEBUG;
                                }
                                labels[label].line = readUnsignedShort(w + 2);
                                w += 4;
                            }
                        }
                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
                        if ((flags & SKIP_FRAMES) == 0) {
                            stackMap = v + 8;
                            frameCount = readUnsignedShort(v + 6);
                        }
                        /*
                         * here we do not extract the labels corresponding to
                         * the attribute content. This would require a full
                         * parsing of the attribute, which would need to be
                         * repeated in the second phase (see below). Instead the
                         * content of the attribute is read one frame at a time
                         * (i.e. after a frame has been visited, the next frame
                         * is read), and the labels it contains are also
                         * extracted one frame at a time. Thanks to the ordering
                         * of frames, having only a "one frame lookahead" is not
                         * a problem, i.e. it is not possible to see an offset
                         * smaller than the offset of the current insn and for
                         * which no Label exist.
                         */
                        // TODO true for frame offsets,
                        // but for UNINITIALIZED type offsets?
                    } else if (FRAMES && "StackMap".equals(attrName)) {
                        if ((flags & SKIP_FRAMES) == 0) {
                            stackMap = v + 8;
                            frameCount = readUnsignedShort(v + 6);
                            zip = false;
                        }
                        /*
                         * IMPORTANT! here we assume that the frames are
                         * ordered, as in the StackMapTable attribute, although
                         * this is not guaranteed by the attribute format.
                         */
                    } else {
                        for (k = 0; k < attrs.length; ++k) {
                            if (attrs[k].type.equals(attrName)) {
                                attr = attrs[k].read(this,
                                        v + 6,
                                        readInt(v + 2),
                                        c,
                                        codeStart - 8,
                                        labels);
                                if (attr != null) {
                                    attr.next = cattrs;
                                    cattrs = attr;
                                }
                            }
                        }
                    }
                    v += 6 + readInt(v + 2);
                }

                // 2nd phase: visits each instruction
                if (FRAMES && stackMap != 0) {
                    // creates the very first (implicit) frame from the method
                    // descriptor
                    frameLocal = new Object[maxLocals];
                    frameStack = new Object[maxStack];
                    if (unzip) {
                        int local = 0;
                        if ((access & Opcodes.ACC_STATIC) == 0) {
                            if ("<init>".equals(name)) {
                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
                            } else {
                                frameLocal[local++] = readClass(header + 2, c);
                            }
                        }
                        j = 1;
                        loop: while (true) {
                            k = j;
                            switch (desc.charAt(j++)) {
                                case 'Z':
                                case 'C':
                                case 'B':
                                case 'S':
                                case 'I':
                                    frameLocal[local++] = Opcodes.INTEGER;
                                    break;
                                case 'F':
                                    frameLocal[local++] = Opcodes.FLOAT;
                                    break;
                                case 'J':
                                    frameLocal[local++] = Opcodes.LONG;
                                    break;
                                case 'D':
                                    frameLocal[local++] = Opcodes.DOUBLE;
                                    break;
                                case '[':
                                    while (desc.charAt(j) == '[') {
                                        ++j;
                                    }
                                    if (desc.charAt(j) == 'L') {
                                        ++j;
                                        while (desc.charAt(j) != ';') {
                                            ++j;
                                        }
                                    }
                                    frameLocal[local++] = desc.substring(k, ++j);
                                    break;
                                case 'L':
                                    while (desc.charAt(j) != ';') {
                                        ++j;
                                    }
                                    frameLocal[local++] = desc.substring(k + 1,
                                            j++);
                                    break;
                                default:
                                    break loop;
                            }
                        }
                        frameLocalCount = local;
                    }
                    /*
                     * for the first explicit frame the offset is not
                     * offset_delta + 1 but only offset_delta; setting the
                     * implicit frame offset to -1 allow the use of the
                     * "offset_delta + 1" rule in all cases
                     */
                    frameOffset = -1;
                }
                v = codeStart;
                Label l;
                while (v < codeEnd) {
                    w = v - codeStart;

                    l = labels[w];
                    if (l != null) {
                        mv.visitLabel(l);
                        if (!skipDebug && l.line > 0) {
                            mv.visitLineNumber(l.line, l);
                        }
                    }

                    while (FRAMES && frameLocal != null
                            && (frameOffset == w || frameOffset == -1))
                    {
                        // if there is a frame for this offset,
                        // makes the visitor visit it,
                        // and reads the next frame if there is one.
                        if (!zip || unzip) {
                            mv.visitFrame(Opcodes.F_NEW,
                                    frameLocalCount,
                                    frameLocal,
                                    frameStackCount,
                                    frameStack);
                        } else if (frameOffset != -1) {
                            mv.visitFrame(frameMode,
                                    frameLocalDiff,
                                    frameLocal,
                                    frameStackCount,
                                    frameStack);
                        }

                        if (frameCount > 0) {
                            int tag, delta, n;
                            if (zip) {
                                tag = b[stackMap++] & 0xFF;
                            } else {
                                tag = MethodWriter.FULL_FRAME;
                                frameOffset = -1;
                            }
                            frameLocalDiff = 0;
                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
                            {
                                delta = tag;
                                frameMode = Opcodes.F_SAME;
                                frameStackCount = 0;
                            } else if (tag < MethodWriter.RESERVED) {
                                delta = tag
                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
                                stackMap = readFrameType(frameStack,
                                        0,
                                        stackMap,
                                        c,
                                        labels);
                                frameMode = Opcodes.F_SAME1;
                                frameStackCount = 1;
                            } else {
                                delta = readUnsignedShort(stackMap);
                                stackMap += 2;
                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
                                {
                                    stackMap = readFrameType(frameStack,
                                            0,
                                            stackMap,
                                            c,
                                            labels);
                                    frameMode = Opcodes.F_SAME1;
                                    frameStackCount = 1;
                                } else if (tag >= MethodWriter.CHOP_FRAME
                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
                                {
                                    frameMode = Opcodes.F_CHOP;
                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
                                            - tag;
                                    frameLocalCount -= frameLocalDiff;
                                    frameStackCount = 0;
                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
                                {
                                    frameMode = Opcodes.F_SAME;
                                    frameStackCount = 0;
                                } else if (tag < MethodWriter.FULL_FRAME) {
                                    j = unzip ? frameLocalCount : 0;
                                    for (k = tag
                                            - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
                                    {
                                        stackMap = readFrameType(frameLocal,
                                                j++,
                                                stackMap,
                                                c,
                                                labels);
                                    }
                                    frameMode = Opcodes.F_APPEND;
                                    frameLocalDiff = tag
                                            - MethodWriter.SAME_FRAME_EXTENDED;
                                    frameLocalCount += frameLocalDiff;
                                    frameStackCount = 0;
                                } else { // if (tag == FULL_FRAME) {
                                    frameMode = Opcodes.F_FULL;
                                    n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
                                    stackMap += 2;
                                    for (j = 0; n > 0; n--) {
                                        stackMap = readFrameType(frameLocal,
                                                j++,
                                                stackMap,
                                                c,
                                                labels);
                                    }
                                    n = frameStackCount = readUnsignedShort(stackMap);
                                    stackMap += 2;
                                    for (j = 0; n > 0; n--) {
                                        stackMap = readFrameType(frameStack,
                                                j++,
                                                stackMap,
                                                c,
                                                labels);
                                    }
                                }
                            }
                            frameOffset += delta + 1;
                            readLabel(frameOffset, labels);

                            --frameCount;
                        } else {
                            frameLocal = null;
                        }
                    }

                    int opcode = b[v] & 0xFF;
                    switch (ClassWriter.TYPE[opcode]) {
                        case ClassWriter.NOARG_INSN:
                            mv.visitInsn(opcode);
                            v += 1;
                            break;
                        case ClassWriter.IMPLVAR_INSN:
                            if (opcode > Opcodes.ISTORE) {
                                opcode -= 59; // ISTORE_0
                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
                                        opcode & 0x3);
                            } else {
                                opcode -= 26; // ILOAD_0
                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
                                        opcode & 0x3);
                            }
                            v += 1;
                            break;
                        case ClassWriter.LABEL_INSN:
                            mv.visitJumpInsn(opcode, labels[w
                                    + readShort(v + 1)]);
                            v += 3;
                            break;
                        case ClassWriter.LABELW_INSN:
                            mv.visitJumpInsn(opcode - 33, labels[w
                                    + readInt(v + 1)]);
                            v += 5;
                            break;
                        case ClassWriter.WIDE_INSN:
                            opcode = b[v + 1] & 0xFF;
                            if (opcode == Opcodes.IINC) {
                                mv.visitIincInsn(readUnsignedShort(v + 2),
                                        readShort(v + 4));
                                v += 6;
                            } else {
                                mv.visitVarInsn(opcode,
                                        readUnsignedShort(v + 2));
                                v += 4;
                            }
                            break;
                        case ClassWriter.TABL_INSN:
                            // skips 0 to 3 padding bytes
                            v = v + 4 - (w & 3);
                            // reads instruction
                            label = w + readInt(v);
                            int min = readInt(v + 4);
                            int max = readInt(v + 8);
                            v += 12;
                            Label[] table = new Label[max - min + 1];
                            for (j = 0; j < table.length; ++j) {
                                table[j] = labels[w + readInt(v)];
                                v += 4;
                            }
                            mv.visitTableSwitchInsn(min,
                                    max,
                                    labels[label],
                                    table);
                            break;
                        case ClassWriter.LOOK_INSN:
                            // skips 0 to 3 padding bytes
                            v = v + 4 - (w & 3);
                            // reads instruction
                            label = w + readInt(v);
                            j = readInt(v + 4);
                            v += 8;
                            int[] keys = new int[j];
                            Label[] values = new Label[j];
                            for (j = 0; j < keys.length; ++j) {
                                keys[j] = readInt(v);
                                values[j] = labels[w + readInt(v + 4)];
                                v += 8;
                            }
                            mv.visitLookupSwitchInsn(labels[label],
                                    keys,
                                    values);
                            break;
                        case ClassWriter.VAR_INSN:
                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
                            v += 2;
                            break;
                        case ClassWriter.SBYTE_INSN:
                            mv.visitIntInsn(opcode, b[v + 1]);
                            v += 2;
                            break;
                        case ClassWriter.SHORT_INSN:
                            mv.visitIntInsn(opcode, readShort(v + 1));
                            v += 3;
                            break;
                        case ClassWriter.LDC_INSN:
                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
                            v += 2;
                            break;
                        case ClassWriter.LDCW_INSN:
                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
                                    c));
                            v += 3;
                            break;
                        case ClassWriter.FIELDORMETH_INSN:
                        case ClassWriter.ITFMETH_INSN:
                            int cpIndex = items[readUnsignedShort(v + 1)];
                            String iowner = readClass(cpIndex, c);
                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
                            String iname = readUTF8(cpIndex, c);
                            String idesc = readUTF8(cpIndex + 2, c);
                            if (opcode < Opcodes.INVOKEVIRTUAL) {
                                mv.visitFieldInsn(opcode, iowner, iname, idesc);
                            } else {
                                mv.visitMethodInsn(opcode, iowner, iname, idesc);
                            }
                            if (opcode == Opcodes.INVOKEINTERFACE) {
                                v += 5;
                            } else {
                                v += 3;
                            }
                            break;
                        case ClassWriter.TYPE_INSN:
                            mv.visitTypeInsn(opcode, readClass(v + 1, c));
                            v += 3;
                            break;
                        case ClassWriter.IINC_INSN:
                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
                            v += 3;
                            break;
                        // case MANA_INSN:
                        default:
                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),
                                    b[v + 3] & 0xFF);
                            v += 4;
                            break;
                    }
                }
                l = labels[codeEnd - codeStart];
                if (l != null) {
                    mv.visitLabel(l);
                }
                // visits the local variable tables
                if (!skipDebug && varTable != 0) {
                    int[] typeTable = null;
                    if (varTypeTable != 0) {
                        k = readUnsignedShort(varTypeTable) * 3;
                        w = varTypeTable + 2;
                        typeTable = new int[k];
                        while (k > 0) {
                            typeTable[--k] = w + 6; // signature
                            typeTable[--k] = readUnsignedShort(w + 8); // index
                            typeTable[--k] = readUnsignedShort(w); // start
                            w += 10;
                        }
                    }
                    k = readUnsignedShort(varTable);
                    w = varTable + 2;
                    for (; k > 0; --k) {
                        int start = readUnsignedShort(w);
                        int length = readUnsignedShort(w + 2);
                        int index = readUnsignedShort(w + 8);
                        String vsignature = null;
                        if (typeTable != null) {
                            for (int a = 0; a < typeTable.length; a += 3) {
                                if (typeTable[a] == start
                                        && typeTable[a + 1] == index)
                                {
                                    vsignature = readUTF8(typeTable[a + 2], c);
                                    break;
                                }
                            }
                        }
                        mv.visitLocalVariable(readUTF8(w + 4, c),
                                readUTF8(w + 6, c),
                                vsignature,
                                labels[start],
                                labels[start + length],
                                index);
                        w += 10;
                    }
                }
                // visits the other attributes
                while (cattrs != null) {
                    attr = cattrs.next;
                    cattrs.next = null;
                    mv.visitAttribute(cattrs);
                    cattrs = attr;
                }
                // visits the max stack and max locals values
                mv.visitMaxs(maxStack, maxLocals);
            }

            if (mv != null) {
                mv.visitEnd();
            }
        }

        // visits the end of the class
        classVisitor.visitEnd();
    }