View Javadoc
1   package mockit.asm.methods;
2   
3   import edu.umd.cs.findbugs.annotations.NonNull;
4   import edu.umd.cs.findbugs.annotations.Nullable;
5   
6   import mockit.asm.constantPool.AttributeWriter;
7   import mockit.asm.constantPool.ConstantPoolGeneration;
8   import mockit.asm.controlFlow.Label;
9   import mockit.asm.util.ByteVector;
10  
11  import org.checkerframework.checker.index.qual.NonNegative;
12  
13  /**
14   * Writes the bytecode for the "LocalVariableTable" and "LocalVariableTypeTable" method code attributes.
15   */
16  final class LocalVariableTableWriter extends AttributeWriter {
17      /**
18       * Number of entries in the LocalVariableTable attribute.
19       */
20      @NonNegative
21      private int localVarCount;
22  
23      /**
24       * The LocalVariableTable attribute.
25       */
26      @Nullable
27      private ByteVector localVarTable;
28  
29      @NonNegative
30      private int localVarTypeAttributeIndex;
31  
32      /**
33       * Number of entries in the LocalVariableTypeTable attribute.
34       */
35      @NonNegative
36      private int localVarTypeCount;
37  
38      /**
39       * The LocalVariableTypeTable attribute.
40       */
41      @Nullable
42      private ByteVector localVarTypeTable;
43  
44      LocalVariableTableWriter(@NonNull ConstantPoolGeneration cp) {
45          super(cp);
46      }
47  
48      @NonNegative
49      int addLocalVariable(@NonNull String name, @NonNull String desc, @Nullable String signature, @NonNull Label start,
50              @NonNull Label end, @NonNegative int index) {
51          if (signature != null) {
52              if (localVarTypeTable == null) {
53                  localVarTypeAttributeIndex = cp.newUTF8("LocalVariableTypeTable");
54                  localVarTypeTable = new ByteVector();
55              }
56  
57              addAttribute(localVarTypeTable, name, signature, start, end, index);
58              localVarTypeCount++;
59          }
60  
61          if (localVarTable == null) {
62              setAttribute("LocalVariableTable");
63              localVarTable = new ByteVector();
64          }
65  
66          addAttribute(localVarTable, name, desc, start, end, index);
67          localVarCount++;
68  
69          char c = desc.charAt(0);
70          return index + (c == 'J' || c == 'D' ? 2 : 1);
71      }
72  
73      private void addAttribute(@NonNull ByteVector attribute, @NonNull String name, @NonNull String desc,
74              @NonNull Label start, @NonNull Label end, @NonNegative int index) {
75          attribute.putShort(start.position).putShort(end.position - start.position).putShort(cp.newUTF8(name))
76                  .putShort(cp.newUTF8(desc)).putShort(index);
77      }
78  
79      @NonNegative
80      @Override
81      public int getSize() {
82          return getSize(localVarTable) + getSize(localVarTypeTable);
83      }
84  
85      @NonNegative
86      private static int getSize(@Nullable ByteVector attribute) {
87          return attribute == null ? 0 : 8 + attribute.getLength();
88      }
89  
90      @NonNegative
91      int getAttributeCount() {
92          return (localVarTable == null ? 0 : 1) + (localVarTypeTable == null ? 0 : 1);
93      }
94  
95      @Override
96      public void put(@NonNull ByteVector out) {
97          put(out, localVarTable, localVarCount);
98          attributeIndex = localVarTypeAttributeIndex;
99          put(out, localVarTypeTable, localVarTypeCount);
100     }
101 
102     private void put(@NonNull ByteVector out, @Nullable ByteVector attribute, @NonNegative int numEntries) {
103         if (attribute != null) {
104             put(out, 2 + attribute.getLength());
105             out.putShort(numEntries);
106             out.putByteVector(attribute);
107         }
108     }
109 }