Class JSRInlinerAdapter

All Implemented Interfaces:
Opcodes

public class JSRInlinerAdapter extends MethodNode implements Opcodes
A MethodVisitor that removes JSR instructions and inlines the referenced subroutines.
  • Field Details

    • DEFAULT_MAX_MEMORY_LIMIT

      static final int DEFAULT_MAX_MEMORY_LIMIT
      The default max memory limit for setComputeLimits(int, long). Update the comment in setComputeLimits(int, long) is you change this value.
      See Also:
    • DEFAULT_MAX_OPERATIONS_LIMIT

      static final long DEFAULT_MAX_OPERATIONS_LIMIT
      The default max operations limit for setComputeLimits(int, long). Update the comment in setComputeLimits(int, long) is you change this value.
      See Also:
    • LABEL_NODE_SIZE

      private static final int LABEL_NODE_SIZE
      The size of a LabelNode and of its nested Label, in bytes. Two object headers + (1 field + 6 inherited fields + padding) for LabelNode + 12 "equivalent int" fields for Label.
      See Also:
    • TRY_CATCH_BLOCK_NODE_SIZE

      private static final int TRY_CATCH_BLOCK_NODE_SIZE
      The size of a TryCatchBlockNode in bytes. One object header + (6 fields + 6 inherited fields).
      See Also:
    • LOCAL_VARIABLE_NODE_SIZE

      private static final int LOCAL_VARIABLE_NODE_SIZE
      The size of a LocalVariableNode in bytes. One object header + (6 fields + 6 inherited fields).
      See Also:
    • mainSubroutineInsns

      private final BitSet mainSubroutineInsns
      The instructions that belong to the main "subroutine". Bit i is set iff instruction at index i belongs to this main "subroutine".
    • subroutinesInsns

      private final Map<LabelNode,BitSet> subroutinesInsns
      The instructions that belong to each subroutine. For each label which is the target of a JSR instruction, bit i of the corresponding BitSet in this map is set iff instruction at index i belongs to this subroutine.
    • sharedSubroutineInsns

      final BitSet sharedSubroutineInsns
      The instructions that belong to more that one subroutine. Bit i is set iff instruction at index i belongs to more than one subroutine.
    • numInlinedInstructions

      int numInlinedInstructions
      The number of instructions after inlining.
    • remainingBytes

      int remainingBytes
      The number of bytes which can be allocated.
    • remainingOperations

      long remainingOperations
      The number of operations which can be performed.
  • Constructor Details

    • JSRInlinerAdapter

      public JSRInlinerAdapter(MethodVisitor methodVisitor, int access, String name, String descriptor, String signature, String[] exceptions)
      Constructs a new JSRInlinerAdapter. Subclasses must not use this constructor. Instead, they must use the JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[]) version.
      Parameters:
      methodVisitor - the method visitor to send the resulting inlined method code to, or null.
      access - the method's access flags.
      name - the method's name.
      descriptor - the method's descriptor.
      signature - the method's signature. May be null.
      exceptions - the internal names of the method's exception classes (see Type.getInternalName()). May be null.
      Throws:
      IllegalStateException - if a subclass calls this constructor.
    • JSRInlinerAdapter

      protected JSRInlinerAdapter(int api, MethodVisitor methodVisitor, int access, String name, String descriptor, String signature, String[] exceptions)
      Constructs a new JSRInlinerAdapter.
      Parameters:
      api - the ASM API version implemented by this visitor. Must be one of the ASMx values in Opcodes.
      methodVisitor - the method visitor to send the resulting inlined method code to, or null.
      access - the method's access flags (see Opcodes). This parameter also indicates if the method is synthetic and/or deprecated.
      name - the method's name.
      descriptor - the method's descriptor.
      signature - the method's signature. May be null.
      exceptions - the internal names of the method's exception classes (see Type.getInternalName()). May be null.
  • Method Details

    • setComputeLimits

      public void setComputeLimits(int maxBytes, long maxOperations)
      Sets the maximum number of bytes which can be allocated, and the maximum number of "operations" which can be performed, to inline the subroutines. Operations are not formally defined but their total number is deterministic and approximatively proportional to the computation time.

      The default limits should be sufficient for any "normal" class. You only need to set new limits if visitEnd() throws a LimitExceededException on some of your classes.

      Parameters:
      maxBytes - the maximum number of bytes which can be allocated. Not all object instantiations are tracked (and garbage collection is ignored), but the most important ones are. The default value is 20MB.
      maxOperations - the maximum number of "operations" that can be performed. The default value is 100M.
    • visitJumpInsn

      public void visitJumpInsn(int opcode, Label label)
      Description copied from class: MethodVisitor
      Visits a jump instruction. A jump instruction is an instruction that may jump to another instruction.
      Overrides:
      visitJumpInsn in class MethodNode
      Parameters:
      opcode - the opcode of the type instruction to be visited. This opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
      label - the operand of the instruction to be visited. This operand is a label that designates the instruction to which the jump instruction may jump.
    • visitEnd

      public void visitEnd()
      Description copied from class: MethodVisitor
      Visits the end of the method. This method, which is the last one to be called, is used to inform the visitor that all the annotations and attributes of the method have been visited.
      Overrides:
      visitEnd in class MethodNode
    • findSubroutinesInsns

      private void findSubroutinesInsns()
      Determines, for each instruction, to which subroutine(s) it belongs.
    • findSubroutineInsns

      private void findSubroutineInsns(int startInsnIndex, BitSet subroutineInsns, BitSet visitedInsns)
      Finds the instructions that belong to the subroutine starting at the given instruction index. For this the control flow graph is visited with a depth first search (this includes the normal control flow and the exception handlers).
      Parameters:
      startInsnIndex - the index of the first instruction of the subroutine.
      subroutineInsns - where the indices of the instructions of the subroutine must be stored.
      visitedInsns - the indices of the instructions that have been visited so far (including in previous calls to this method). This bitset is updated by this method each time a new instruction is visited. It is used to make sure each instruction is visited at most once.
    • findReachableInsns

      private void findReachableInsns(int insnIndex, BitSet subroutineInsns, BitSet visitedInsns)
      Finds the instructions that are reachable from the given instruction, without following any JSR instruction nor any exception handler. For this the control flow graph is visited with a depth first search.
      Parameters:
      insnIndex - the index of an instruction of the subroutine.
      subroutineInsns - where the indices of the instructions of the subroutine must be stored.
      visitedInsns - the indices of the instructions that have been visited so far (including in previous calls to this method). This bitset is updated by this method each time a new instruction is visited. It is used to make sure each instruction is visited at most once.
    • emitCode

      private void emitCode()
      Creates the new instructions, inlining each instantiation of each subroutine until the code is fully elaborated.
    • emitInstantiation

      private void emitInstantiation(JSRInlinerAdapter.Instantiation instantiation, List<JSRInlinerAdapter.Instantiation> worklist, InsnList newInstructions, List<TryCatchBlockNode> newTryCatchBlocks, List<LocalVariableNode> newLocalVariables)
      Emits an instantiation of a subroutine, specified by instantiation. May add new instantiations that are invoked by this one to the worklist, and new try/catch blocks to newTryCatchBlocks.
      Parameters:
      instantiation - the instantiation that must be performed.
      worklist - list of the instantiations that remain to be done.
      newInstructions - the instruction list to which the instantiated code must be appended.
      newTryCatchBlocks - the exception handler list to which the instantiated handlers must be appended.
      newLocalVariables - the local variables list to which the instantiated local variables must be appended.
    • checkNewAllocation

      void checkNewAllocation(int numBytes)
      Checks if some bytes can be allocated.
      Parameters:
      numBytes - the number of bytes to allocate. Can be negative if an overflow occurs when computing it (e.g., if computed as a product "number of elements" * "size per element").
      Throws:
      LimitExceededException - if the memory limit is exceeded.
    • checkNewOperations

      void checkNewOperations(int numOperations)
      Checks if some operations can be done without exceeding the limit.
      Parameters:
      numOperations - the number of operations to perform. Can be negative if an overflow occurs when computing it.
      Throws:
      LimitExceededException - if the memory limit is exceeded. LimitExceededException