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