public void visitMaxs(final int maxStack, final int maxLocals) {
        /**
         * Computes all the stack map frames of the method, from scratch.
         */
        // computeAllFrames();
        // Create and visit the first (implicit) frame.
        Frame firstFrame = firstBasicBlock.frame;
        firstFrame.setInputFrameFromDescriptor(symbolTable, accessFlags, descriptor, this.maxLocals);
        firstFrame.accept(this);

        // Fix point algorithm: add the first basic block to a list of blocks to process (i.e. blocks
        // whose stack map frame has changed) and, while there are blocks to process, remove one from
        // the list and update the stack map frames of its successor blocks in the control flow graph
        // (which might change them, in which case these blocks must be processed too, and are thus
        // added to the list of blocks to process). Also compute the maximum stack size of the method,
        // as a by-product.
        Label listOfBlocksToProcess = firstBasicBlock;
        listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST;
        int maxStackSize = 0;
        while (listOfBlocksToProcess != Label.EMPTY_LIST) {
            // Remove a basic block from the list of blocks to process.
            Label basicBlock = listOfBlocksToProcess;
            listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
            basicBlock.nextListElement = null;
            // By definition, basicBlock is reachable.
            basicBlock.flags |= Label.FLAG_REACHABLE;
            // Update the (absolute) maximum stack size.
            int maxBlockStackSize = basicBlock.frame.inputStack.length + basicBlock.outputStackMax;
            if (maxBlockStackSize > maxStackSize) {
                maxStackSize = maxBlockStackSize;
            }
            // Update the successor blocks of basicBlock in the control flow graph.
            Edge outgoingEdge = basicBlock.outgoingEdges;
            while (outgoingEdge != null) {
                Label successorBlock = outgoingEdge.successor.getCanonicalInstance();
                boolean successorBlockChanged =
                        basicBlock.frame.merge(symbolTable, successorBlock.frame);
                if (successorBlockChanged && successorBlock.nextListElement == null) {
                    // If successorBlock has changed it must be processed. Thus, if it is not already in the
                    // list of blocks to process, add it to this list.
                    successorBlock.nextListElement = listOfBlocksToProcess;
                    listOfBlocksToProcess = successorBlock;
                }
                outgoingEdge = outgoingEdge.nextEdge;
            }
        }

        // Loop over all the basic blocks and visit the stack map frames that must be stored in the
        // StackMapTable attribute. Also replace unreachable code with NOP* ATHROW, and remove it from
        // exception handler ranges.
        Label basicBlock = firstBasicBlock;
        while (basicBlock != null) {
            if ((basicBlock.flags & (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE))
                    == (Label.FLAG_JUMP_TARGET | Label.FLAG_REACHABLE)) {
                basicBlock.frame.accept(this);
            }
            if ((basicBlock.flags & Label.FLAG_REACHABLE) == 0) {
                // Find the start and end bytecode offsets of this unreachable block.
                Label nextBasicBlock = basicBlock.nextBasicBlock;
                int startOffset = basicBlock.bytecodeOffset;
                int endOffset = (nextBasicBlock == null ? code.length : nextBasicBlock.bytecodeOffset) - 1;
                if (endOffset >= startOffset) {
                    // Replace its instructions with NOP ... NOP ATHROW.
                    for (int i = startOffset; i < endOffset; ++i) {
                        code.data[i] = Opcodes.NOP;
                    }
                    code.data[endOffset] = (byte) Opcodes.ATHROW;
                    // Emit a frame for this unreachable block, with no local and a Throwable on the stack
                    // (so that the ATHROW could consume this Throwable if it were reachable).
                    int frameIndex = visitFrameStart(startOffset, /* numLocal = */ 0, /* numStack = */ 1);
                    currentFrame[frameIndex] = Frame.REFERENCE_KIND | symbolTable.addType("java/lang/Throwable");
                    visitFrameEnd();
                    // The maximum stack size is now at least one, because of the Throwable declared above.
                    maxStackSize = Math.max(maxStackSize, 1);
                }
            }
            basicBlock = basicBlock.nextBasicBlock;
        }

        this.maxStack = maxStackSize;
    }
Constructs a new {@link MethodWriter}.

@param symbolTable where the constants used in this AnnotationWriter must be stored.
@param access      the method's access flags (see {@link Opcodes}).
@param name        the method's name.
@param descriptor  the method's descriptor (see {@link Type}).
core/src/main/java/com/alibaba/fastjson2/internal/asm/MethodWriter.java