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
15
16 final class LocalVariableTableWriter extends AttributeWriter {
17
18
19
20 @NonNegative
21 private int localVarCount;
22
23
24
25
26 @Nullable
27 private ByteVector localVarTable;
28
29 @NonNegative
30 private int localVarTypeAttributeIndex;
31
32
33
34
35 @NonNegative
36 private int localVarTypeCount;
37
38
39
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 }