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