jodd-proxetta/src/main/java/jodd/asm7/MethodWriter.java
private void computeMaxStackAndLocal() {
    // Complete the control flow graph with exception handler blocks.
    Handler handler = firstHandler;
    while (handler != null) {
      Label handlerBlock = handler.handlerPc;
      Label handlerRangeBlock = handler.startPc;
      Label handlerRangeEnd = handler.endPc;
      // Add handlerBlock as a successor of all the basic blocks in the exception handler range.
      while (handlerRangeBlock != handlerRangeEnd) {
        if ((handlerRangeBlock.flags & Label.FLAG_SUBROUTINE_CALLER) == 0) {
          handlerRangeBlock.outgoingEdges =
              new Edge(Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges);
        } else {
          // If handlerRangeBlock is a JSR block, add handlerBlock after the first two outgoing
          // edges to preserve the hypothesis about JSR block successors order (see
          // {@link #visitJumpInsn}).
          handlerRangeBlock.outgoingEdges.nextEdge.nextEdge =
              new Edge(
                  Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges.nextEdge.nextEdge);
        }
        handlerRangeBlock = handlerRangeBlock.nextBasicBlock;
      }
      handler = handler.nextHandler;
    }

    // Complete the control flow graph with the successor blocks of subroutines, if needed.
    if (hasSubroutines) {
      // First step: find the subroutines. This step determines, for each basic block, to which
      // subroutine(s) it belongs. Start with the main "subroutine":
      short numSubroutines = 1;
      firstBasicBlock.markSubroutine(numSubroutines);
      // Then, mark the subroutines called by the main subroutine, then the subroutines called by
      // those called by the main subroutine, etc.
      for (short currentSubroutine = 1; currentSubroutine <= numSubroutines; ++currentSubroutine) {
        Label basicBlock = firstBasicBlock;
        while (basicBlock != null) {
          if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0
              && basicBlock.subroutineId == currentSubroutine) {
            Label jsrTarget = basicBlock.outgoingEdges.nextEdge.successor;
            if (jsrTarget.subroutineId == 0) {
              // If this subroutine has not been marked yet, find its basic blocks.
              jsrTarget.markSubroutine(++numSubroutines);
            }
          }
          basicBlock = basicBlock.nextBasicBlock;
        }
      }
      // Second step: find the successors in the control flow graph of each subroutine basic block
      // 'r' ending with a RET instruction. These successors are the virtual successors of the basic
      // blocks ending with JSR instructions (see {@link #visitJumpInsn)} that can reach 'r'.
      Label basicBlock = firstBasicBlock;
      while (basicBlock != null) {
        if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
          // By construction, jsr targets are stored in the second outgoing edge of basic blocks
          // that ends with a jsr instruction (see {@link #FLAG_SUBROUTINE_CALLER}).
          Label subroutine = basicBlock.outgoingEdges.nextEdge.successor;
          subroutine.addSubroutineRetSuccessors(basicBlock);
        }
        basicBlock = basicBlock.nextBasicBlock;
      }
    }

    // Data flow algorithm: put the first basic block in a list of blocks to process (i.e. blocks
    // whose input stack size has changed) and, while there are blocks to process, remove one
    // from the list, update the input stack size of its successor blocks in the control flow
    // graph, and add these blocks to the list of blocks to process (if not already done).
    Label listOfBlocksToProcess = firstBasicBlock;
    listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST;
    int maxStackSize = maxStack;
    while (listOfBlocksToProcess != Label.EMPTY_LIST) {
      // Remove a basic block from the list of blocks to process. Note that we don't reset
      // basicBlock.nextListElement to null on purpose, to make sure we don't reprocess already
      // processed basic blocks.
      Label basicBlock = listOfBlocksToProcess;
      listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
      // Compute the (absolute) input stack size and maximum stack size of this block.
      int inputStackTop = basicBlock.inputStackSize;
      int maxBlockStackSize = inputStackTop + basicBlock.outputStackMax;
      // Update the absolute maximum stack size of the method.
      if (maxBlockStackSize > maxStackSize) {
        maxStackSize = maxBlockStackSize;
      }
      // Update the input stack size of the successor blocks of basicBlock in the control flow
      // graph, and add these blocks to the list of blocks to process, if not already done.
      Edge outgoingEdge = basicBlock.outgoingEdges;
      if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
        // Ignore the first outgoing edge of the basic blocks ending with a jsr: these are virtual
        // edges which lead to the instruction just after the jsr, and do not correspond to a
        // possible execution path (see {@link #visitJumpInsn} and
        // {@link Label#FLAG_SUBROUTINE_CALLER}).
        outgoingEdge = outgoingEdge.nextEdge;
      }
      while (outgoingEdge != null) {
        Label successorBlock = outgoingEdge.successor;
        if (successorBlock.nextListElement == null) {
          successorBlock.inputStackSize =
              (short) (outgoingEdge.info == Edge.EXCEPTION ? 1 : inputStackTop + outgoingEdge.info);
          successorBlock.nextListElement = listOfBlocksToProcess;
          listOfBlocksToProcess = successorBlock;
        }
        outgoingEdge = outgoingEdge.nextEdge;
      }
    }
    this.maxStack = maxStackSize;
  }
private void computeMaxStackAndLocal() {
    // Complete the control flow graph with exception handler blocks.
    Handler handler = firstHandler;
    while (handler != null) {
      Label handlerBlock = handler.handlerPc;
      Label handlerRangeBlock = handler.startPc;
      Label handlerRangeEnd = handler.endPc;
      // Add handlerBlock as a successor of all the basic blocks in the exception handler range.
      while (handlerRangeBlock != handlerRangeEnd) {
        if ((handlerRangeBlock.flags & Label.FLAG_SUBROUTINE_CALLER) == 0) {
          handlerRangeBlock.outgoingEdges =
              new Edge(Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges);
        } else {
          // If handlerRangeBlock is a JSR block, add handlerBlock after the first two outgoing
          // edges to preserve the hypothesis about JSR block successors order (see
          // {@link #visitJumpInsn}).
          handlerRangeBlock.outgoingEdges.nextEdge.nextEdge =
              new Edge(
                  Edge.EXCEPTION, handlerBlock, handlerRangeBlock.outgoingEdges.nextEdge.nextEdge);
        }
        handlerRangeBlock = handlerRangeBlock.nextBasicBlock;
      }
      handler = handler.nextHandler;
    }

    // Complete the control flow graph with the successor blocks of subroutines, if needed.
    if (hasSubroutines) {
      // First step: find the subroutines. This step determines, for each basic block, to which
      // subroutine(s) it belongs. Start with the main "subroutine":
      short numSubroutines = 1;
      firstBasicBlock.markSubroutine(numSubroutines);
      // Then, mark the subroutines called by the main subroutine, then the subroutines called by
      // those called by the main subroutine, etc.
      for (short currentSubroutine = 1; currentSubroutine <= numSubroutines; ++currentSubroutine) {
        Label basicBlock = firstBasicBlock;
        while (basicBlock != null) {
          if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0
              && basicBlock.subroutineId == currentSubroutine) {
            Label jsrTarget = basicBlock.outgoingEdges.nextEdge.successor;
            if (jsrTarget.subroutineId == 0) {
              // If this subroutine has not been marked yet, find its basic blocks.
              jsrTarget.markSubroutine(++numSubroutines);
            }
          }
          basicBlock = basicBlock.nextBasicBlock;
        }
      }
      // Second step: find the successors in the control flow graph of each subroutine basic block
      // 'r' ending with a RET instruction. These successors are the virtual successors of the basic
      // blocks ending with JSR instructions (see {@link #visitJumpInsn)} that can reach 'r'.
      Label basicBlock = firstBasicBlock;
      while (basicBlock != null) {
        if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
          // By construction, jsr targets are stored in the second outgoing edge of basic blocks
          // that ends with a jsr instruction (see {@link #FLAG_SUBROUTINE_CALLER}).
          Label subroutine = basicBlock.outgoingEdges.nextEdge.successor;
          subroutine.addSubroutineRetSuccessors(basicBlock);
        }
        basicBlock = basicBlock.nextBasicBlock;
      }
    }

    // Data flow algorithm: put the first basic block in a list of blocks to process (i.e. blocks
    // whose input stack size has changed) and, while there are blocks to process, remove one
    // from the list, update the input stack size of its successor blocks in the control flow
    // graph, and add these blocks to the list of blocks to process (if not already done).
    Label listOfBlocksToProcess = firstBasicBlock;
    listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST;
    int maxStackSize = maxStack;
    while (listOfBlocksToProcess != Label.EMPTY_LIST) {
      // Remove a basic block from the list of blocks to process. Note that we don't reset
      // basicBlock.nextListElement to null on purpose, to make sure we don't reprocess already
      // processed basic blocks.
      Label basicBlock = listOfBlocksToProcess;
      listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
      // Compute the (absolute) input stack size and maximum stack size of this block.
      int inputStackTop = basicBlock.inputStackSize;
      int maxBlockStackSize = inputStackTop + basicBlock.outputStackMax;
      // Update the absolute maximum stack size of the method.
      if (maxBlockStackSize > maxStackSize) {
        maxStackSize = maxBlockStackSize;
      }
      // Update the input stack size of the successor blocks of basicBlock in the control flow
      // graph, and add these blocks to the list of blocks to process, if not already done.
      Edge outgoingEdge = basicBlock.outgoingEdges;
      if ((basicBlock.flags & Label.FLAG_SUBROUTINE_CALLER) != 0) {
        // Ignore the first outgoing edge of the basic blocks ending with a jsr: these are virtual
        // edges which lead to the instruction just after the jsr, and do not correspond to a
        // possible execution path (see {@link #visitJumpInsn} and
        // {@link Label#FLAG_SUBROUTINE_CALLER}).
        outgoingEdge = outgoingEdge.nextEdge;
      }
      while (outgoingEdge != null) {
        Label successorBlock = outgoingEdge.successor;
        if (successorBlock.nextListElement == null) {
          successorBlock.inputStackSize =
              (short) (outgoingEdge.info == Edge.EXCEPTION ? 1 : inputStackTop + outgoingEdge.info);
          successorBlock.nextListElement = listOfBlocksToProcess;
          listOfBlocksToProcess = successorBlock;
        }
        outgoingEdge = outgoingEdge.nextEdge;
      }
    }
    this.maxStack = maxStackSize;
  }
private void computeMaxStackAndLocal ( ) { // Complete the control flow graph with exception handler blocks. Handler handler = firstHandler ; while ( handler != null ) { Label handlerBlock = handler . handlerPc ; Label handlerRangeBlock = handler . startPc ; Label handlerRangeEnd = handler . endPc ; // Add handlerBlock as a successor of all the basic blocks in the exception handler range. while ( handlerRangeBlock != handlerRangeEnd ) { if ( ( handlerRangeBlock . flags & Label . FLAG_SUBROUTINE_CALLER ) == 0 ) { handlerRangeBlock . outgoingEdges = new Edge ( Edge . EXCEPTION , handlerBlock , handlerRangeBlock . outgoingEdges ) ; } else { // If handlerRangeBlock is a JSR block, add handlerBlock after the first two outgoing // edges to preserve the hypothesis about JSR block successors order (see // {@link #visitJumpInsn}). handlerRangeBlock . outgoingEdges . nextEdge . nextEdge = new Edge ( Edge . EXCEPTION , handlerBlock , handlerRangeBlock . outgoingEdges . nextEdge . nextEdge ) ; } handlerRangeBlock = handlerRangeBlock . nextBasicBlock ; } handler = handler . nextHandler ; } // Complete the control flow graph with the successor blocks of subroutines, if needed. if ( hasSubroutines ) { // First step: find the subroutines. This step determines, for each basic block, to which // subroutine(s) it belongs. Start with the main "subroutine": short numSubroutines = 1 ; firstBasicBlock . markSubroutine ( numSubroutines ) ; // Then, mark the subroutines called by the main subroutine, then the subroutines called by // those called by the main subroutine, etc. for ( short currentSubroutine = 1 ; currentSubroutine <= numSubroutines ; ++ currentSubroutine ) { Label basicBlock = firstBasicBlock ; while ( basicBlock != null ) { if ( ( basicBlock . flags & Label . FLAG_SUBROUTINE_CALLER ) != 0 && basicBlock . subroutineId == currentSubroutine ) { Label jsrTarget = basicBlock . outgoingEdges . nextEdge . successor ; if ( jsrTarget . subroutineId == 0 ) { // If this subroutine has not been marked yet, find its basic blocks. jsrTarget . markSubroutine ( ++ numSubroutines ) ; } } basicBlock = basicBlock . nextBasicBlock ; } } // Second step: find the successors in the control flow graph of each subroutine basic block // 'r' ending with a RET instruction. These successors are the virtual successors of the basic // blocks ending with JSR instructions (see {@link #visitJumpInsn)} that can reach 'r'. Label basicBlock = firstBasicBlock ; while ( basicBlock != null ) { if ( ( basicBlock . flags & Label . FLAG_SUBROUTINE_CALLER ) != 0 ) { // By construction, jsr targets are stored in the second outgoing edge of basic blocks // that ends with a jsr instruction (see {@link #FLAG_SUBROUTINE_CALLER}). Label subroutine = basicBlock . outgoingEdges . nextEdge . successor ; subroutine . addSubroutineRetSuccessors ( basicBlock ) ; } basicBlock = basicBlock . nextBasicBlock ; } } // Data flow algorithm: put the first basic block in a list of blocks to process (i.e. blocks // whose input stack size has changed) and, while there are blocks to process, remove one // from the list, update the input stack size of its successor blocks in the control flow // graph, and add these blocks to the list of blocks to process (if not already done). Label listOfBlocksToProcess = firstBasicBlock ; listOfBlocksToProcess . nextListElement = Label . EMPTY_LIST ; int maxStackSize = maxStack ; while ( listOfBlocksToProcess != Label . EMPTY_LIST ) { // Remove a basic block from the list of blocks to process. Note that we don't reset // basicBlock.nextListElement to null on purpose, to make sure we don't reprocess already // processed basic blocks. Label basicBlock = listOfBlocksToProcess ; listOfBlocksToProcess = listOfBlocksToProcess . nextListElement ; // Compute the (absolute) input stack size and maximum stack size of this block. int inputStackTop = basicBlock . inputStackSize ; int maxBlockStackSize = inputStackTop + basicBlock . outputStackMax ; // Update the absolute maximum stack size of the method. if ( maxBlockStackSize > maxStackSize ) { maxStackSize = maxBlockStackSize ; } // Update the input stack size of the successor blocks of basicBlock in the control flow // graph, and add these blocks to the list of blocks to process, if not already done. Edge outgoingEdge = basicBlock . outgoingEdges ; if ( ( basicBlock . flags & Label . FLAG_SUBROUTINE_CALLER ) != 0 ) { // Ignore the first outgoing edge of the basic blocks ending with a jsr: these are virtual // edges which lead to the instruction just after the jsr, and do not correspond to a // possible execution path (see {@link #visitJumpInsn} and // {@link Label#FLAG_SUBROUTINE_CALLER}). outgoingEdge = outgoingEdge . nextEdge ; } while ( outgoingEdge != null ) { Label successorBlock = outgoingEdge . successor ; if ( successorBlock . nextListElement == null ) { successorBlock . inputStackSize = ( short ) ( outgoingEdge . info == Edge . EXCEPTION ? 1 : inputStackTop + outgoingEdge . info ) ; successorBlock . nextListElement = listOfBlocksToProcess ; listOfBlocksToProcess = successorBlock ; } outgoingEdge = outgoingEdge . nextEdge ; } } this . maxStack = maxStackSize ; }
Computes the maximum stack size of the method.
Computes the maximum stack size of the method .