Computes all the stack map frames of the method, from scratch.
()
| 1550 | |
| 1551 | /** Computes all the stack map frames of the method, from scratch. */ |
| 1552 | private void computeAllFrames() { |
| 1553 | // Complete the control flow graph with exception handler blocks. |
| 1554 | Handler handler = firstHandler; |
| 1555 | while (handler != null) { |
| 1556 | String catchTypeDescriptor = |
| 1557 | handler.catchTypeDescriptor == null ? "java/lang/Throwable" : handler.catchTypeDescriptor; |
| 1558 | int catchType = Frame.getAbstractTypeFromInternalName(symbolTable, catchTypeDescriptor); |
| 1559 | // Mark handlerBlock as an exception handler. |
| 1560 | Label handlerBlock = handler.handlerPc.getCanonicalInstance(); |
| 1561 | handlerBlock.flags |= Label.FLAG_JUMP_TARGET; |
| 1562 | // Add handlerBlock as a successor of all the basic blocks in the exception handler range. |
| 1563 | Label handlerRangeBlock = handler.startPc.getCanonicalInstance(); |
| 1564 | Label handlerRangeEnd = handler.endPc.getCanonicalInstance(); |
| 1565 | while (handlerRangeBlock != handlerRangeEnd) { |
| 1566 | handlerRangeBlock.outgoingEdges = |
| 1567 | new Edge(catchType, handlerBlock, handlerRangeBlock.outgoingEdges); |
| 1568 | handlerRangeBlock = handlerRangeBlock.nextBasicBlock; |
| 1569 | } |
| 1570 | handler = handler.nextHandler; |
| 1571 | } |
| 1572 | |
| 1573 | // Create and visit the first (implicit) frame. |
| 1574 | Frame firstFrame = firstBasicBlock.frame; |
| 1575 | firstFrame.setInputFrameFromDescriptor(symbolTable, accessFlags, descriptor, this.maxLocals); |
| 1576 | firstFrame.accept(this); |
| 1577 | |
| 1578 | // Fix point algorithm: add the first basic block to a list of blocks to process (i.e. blocks |
| 1579 | // whose stack map frame has changed) and, while there are blocks to process, remove one from |
| 1580 | // the list and update the stack map frames of its successor blocks in the control flow graph |
| 1581 | // (which might change them, in which case these blocks must be processed too, and are thus |
| 1582 | // added to the list of blocks to process). Also compute the maximum stack size of the method, |
| 1583 | // as a by-product. |
| 1584 | Label listOfBlocksToProcess = firstBasicBlock; |
| 1585 | listOfBlocksToProcess.nextListElement = Label.EMPTY_LIST; |
| 1586 | int maxStackSize = 0; |
| 1587 | while (listOfBlocksToProcess != Label.EMPTY_LIST) { |
| 1588 | // Remove a basic block from the list of blocks to process. |
| 1589 | Label basicBlock = listOfBlocksToProcess; |
| 1590 | listOfBlocksToProcess = listOfBlocksToProcess.nextListElement; |
| 1591 | basicBlock.nextListElement = null; |
| 1592 | // By definition, basicBlock is reachable. |
| 1593 | basicBlock.flags |= Label.FLAG_REACHABLE; |
| 1594 | // Update the (absolute) maximum stack size. |
| 1595 | int maxBlockStackSize = basicBlock.frame.getInputStackSize() + basicBlock.outputStackMax; |
| 1596 | if (maxBlockStackSize > maxStackSize) { |
| 1597 | maxStackSize = maxBlockStackSize; |
| 1598 | } |
| 1599 | // Update the successor blocks of basicBlock in the control flow graph. |
| 1600 | Edge outgoingEdge = basicBlock.outgoingEdges; |
| 1601 | while (outgoingEdge != null) { |
| 1602 | Label successorBlock = outgoingEdge.successor.getCanonicalInstance(); |
| 1603 | boolean successorBlockChanged = |
| 1604 | basicBlock.frame.merge(symbolTable, successorBlock.frame, outgoingEdge.info); |
| 1605 | if (successorBlockChanged && successorBlock.nextListElement == null) { |
| 1606 | // If successorBlock has changed it must be processed. Thus, if it is not already in the |
| 1607 | // list of blocks to process, add it to this list. |
| 1608 | successorBlock.nextListElement = listOfBlocksToProcess; |
| 1609 | listOfBlocksToProcess = successorBlock; |
no test coverage detected