View Javadoc
1   package mockit.asm.exceptionHandling;
2   
3   import edu.umd.cs.findbugs.annotations.NonNull;
4   import edu.umd.cs.findbugs.annotations.Nullable;
5   
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import mockit.asm.constantPool.ConstantPoolGeneration;
10  import mockit.asm.controlFlow.Edge;
11  import mockit.asm.controlFlow.FrameTypeMask;
12  import mockit.asm.controlFlow.Label;
13  import mockit.asm.util.ByteVector;
14  
15  import org.checkerframework.checker.index.qual.NonNegative;
16  
17  public final class ExceptionHandling {
18      @NonNull
19      private final List<ExceptionHandler> handlers;
20      @NonNull
21      private final ConstantPoolGeneration cp;
22  
23      public ExceptionHandling(@NonNull ConstantPoolGeneration cp) {
24          handlers = new ArrayList<>();
25          this.cp = cp;
26      }
27  
28      public void addHandler(@NonNull Label start, @NonNull Label end, @NonNull Label handler, @Nullable String type) {
29          int handlerType = type == null ? 0 : cp.newClass(type);
30          handlers.add(new ExceptionHandler(start, end, handler, type, handlerType));
31      }
32  
33      public void completeControlFlowGraphWithExceptionHandlerBlocksFromComputedFrames() {
34          for (ExceptionHandler exceptionHandler : handlers) {
35              Label handler = exceptionHandler.handler.getFirst();
36              Label start = exceptionHandler.start.getFirst();
37              Label end = exceptionHandler.end.getFirst();
38  
39              // Computes the kind of the edges to 'handler'.
40              String catchType = exceptionHandler.getCatchTypeDesc();
41              int kindOfEdge = FrameTypeMask.OBJECT | cp.addNormalType(catchType);
42  
43              // 'handler' is an exception handler.
44              handler.markAsTarget();
45  
46              addHandlerLabelAsSuccessor(kindOfEdge, handler, start, end);
47          }
48      }
49  
50      public void completeControlFlowGraphWithExceptionHandlerBlocks() {
51          for (ExceptionHandler exceptionHandler : handlers) {
52              addHandlerLabelAsSuccessor(Edge.EXCEPTION, exceptionHandler.handler, exceptionHandler.start,
53                      exceptionHandler.end);
54          }
55      }
56  
57      // Adds 'handler' as a successor of labels between 'start' and 'end'.
58      private static void addHandlerLabelAsSuccessor(int kindOfEdge, @NonNull Label handler, @NonNull Label start,
59              @NonNull Label end) {
60          while (start != end) {
61              Edge edge = new Edge(kindOfEdge, handler);
62              // noinspection ConstantConditions
63              start = start.setSuccessors(edge);
64          }
65      }
66  
67      public boolean hasHandlers() {
68          return !handlers.isEmpty();
69      }
70  
71      @NonNegative
72      public int getSize() {
73          return 8 * handlers.size();
74      }
75  
76      public void put(@NonNull ByteVector out) {
77          out.putShort(handlers.size());
78  
79          for (ExceptionHandler exceptionHandler : handlers) {
80              exceptionHandler.put(out);
81          }
82      }
83  }