1
2
3
4
5
6 package mockit.asm.classes;
7
8 import static mockit.asm.jvmConstants.ConstantPoolTypes.CLASS;
9 import static mockit.asm.jvmConstants.ConstantPoolTypes.DOUBLE;
10 import static mockit.asm.jvmConstants.ConstantPoolTypes.DYNAMIC;
11 import static mockit.asm.jvmConstants.ConstantPoolTypes.FIELD_REF;
12 import static mockit.asm.jvmConstants.ConstantPoolTypes.FLOAT;
13 import static mockit.asm.jvmConstants.ConstantPoolTypes.IMETHOD_REF;
14 import static mockit.asm.jvmConstants.ConstantPoolTypes.INTEGER;
15 import static mockit.asm.jvmConstants.ConstantPoolTypes.INVOKE_DYNAMIC;
16 import static mockit.asm.jvmConstants.ConstantPoolTypes.LONG;
17 import static mockit.asm.jvmConstants.ConstantPoolTypes.METHOD_HANDLE;
18 import static mockit.asm.jvmConstants.ConstantPoolTypes.METHOD_REF;
19 import static mockit.asm.jvmConstants.ConstantPoolTypes.METHOD_TYPE;
20 import static mockit.asm.jvmConstants.ConstantPoolTypes.MODULE;
21 import static mockit.asm.jvmConstants.ConstantPoolTypes.NAME_TYPE;
22 import static mockit.asm.jvmConstants.ConstantPoolTypes.PACKAGE;
23 import static mockit.asm.jvmConstants.ConstantPoolTypes.STRING;
24 import static mockit.asm.jvmConstants.ConstantPoolTypes.UTF8;
25
26 import edu.umd.cs.findbugs.annotations.NonNull;
27 import edu.umd.cs.findbugs.annotations.Nullable;
28
29 import mockit.asm.constantPool.ClassMemberItem;
30 import mockit.asm.constantPool.DoubleItem;
31 import mockit.asm.constantPool.DynamicItem;
32 import mockit.asm.constantPool.FloatItem;
33 import mockit.asm.constantPool.IntItem;
34 import mockit.asm.constantPool.Item;
35 import mockit.asm.constantPool.LongItem;
36 import mockit.asm.constantPool.MethodHandleItem;
37 import mockit.asm.constantPool.ModuleItem;
38 import mockit.asm.constantPool.NameAndTypeItem;
39 import mockit.asm.constantPool.PackageItem;
40 import mockit.asm.constantPool.StringItem;
41 import mockit.asm.util.MethodHandle;
42
43 import org.checkerframework.checker.index.qual.NonNegative;
44
45
46
47
48 final class ConstantPoolCopying {
49 @NonNull
50 private final ClassReader source;
51 @NonNull
52 private final ClassWriter destination;
53 @NonNull
54 private final Item[] newItems;
55 @NonNegative
56 private int itemIndex;
57
58 ConstantPoolCopying(@NonNull ClassReader source, @NonNull ClassWriter destination) {
59 this.source = source;
60 this.destination = destination;
61 newItems = new Item[source.items.length];
62 }
63
64 void copyPool(@Nullable BootstrapMethodsWriter bootstrapMethods) {
65 if (bootstrapMethods != null) {
66 bootstrapMethods.copyBootstrapMethods(source, newItems);
67 }
68
69 int[] items = source.items;
70 int itemCount = items.length;
71
72 for (itemIndex = 1; itemIndex < itemCount; itemIndex++) {
73 source.codeIndex = items[itemIndex] - 1;
74 int itemType = source.readSignedByte();
75
76 Item newItem = copyItem(itemType);
77 newItem.setNext(newItems);
78 }
79
80 int off = items[1] - 1;
81 destination.getConstantPoolGeneration().copy(source.code, off, source.header, newItems);
82 }
83
84 @NonNull
85 @SuppressWarnings("OverlyComplexMethod")
86 private Item copyItem(int itemType) {
87 switch (itemType) {
88 case UTF8:
89 return copyUTF8Item();
90 case INTEGER:
91 return copyIntItem();
92 case FLOAT:
93 return copyFloatItem();
94 case LONG:
95 return copyLongItem();
96 case DOUBLE:
97 return copyDoubleItem();
98 case FIELD_REF:
99 case METHOD_REF:
100 case IMETHOD_REF:
101 return copyFieldOrMethodReferenceItem(itemType);
102 case NAME_TYPE:
103 return copyNameAndTypeItem();
104 case METHOD_HANDLE:
105 return copyHandleItem();
106 case DYNAMIC:
107 case INVOKE_DYNAMIC:
108 return copyDynamicItem(itemType);
109 case STRING:
110 case CLASS:
111 case METHOD_TYPE:
112 return copyNameReferenceItem(itemType);
113 case MODULE:
114 return copyModule();
115 case PACKAGE:
116 return copyPackage();
117 default:
118 throw new IllegalArgumentException("Unknown CP type, cannot copy: " + itemType);
119 }
120 }
121
122 @NonNull
123 private Item copyIntItem() {
124 int itemValue = source.readInt();
125 IntItem item = new IntItem(itemIndex);
126 item.setValue(itemValue);
127 return item;
128 }
129
130 @NonNull
131 private Item copyLongItem() {
132 long itemValue = source.readLong();
133 LongItem item = new LongItem(itemIndex);
134 item.setValue(itemValue);
135 itemIndex++;
136 return item;
137 }
138
139 @NonNull
140 private Item copyFloatItem() {
141 float itemValue = source.readFloat();
142 FloatItem item = new FloatItem(itemIndex);
143 item.set(itemValue);
144 return item;
145 }
146
147 @NonNull
148 private Item copyDoubleItem() {
149 double itemValue = source.readDouble();
150 DoubleItem item = new DoubleItem(itemIndex);
151 item.set(itemValue);
152 itemIndex++;
153 return item;
154 }
155
156 @NonNull
157 private Item copyUTF8Item() {
158 String strVal = source.readString(itemIndex);
159 return new StringItem(itemIndex, UTF8, strVal);
160 }
161
162 @NonNull
163 private Item copyNameReferenceItem(int type) {
164 String strVal = source.readNonnullUTF8();
165 return new StringItem(itemIndex, type, strVal);
166 }
167
168 @NonNull
169 private Item copyNameAndTypeItem() {
170 String name = source.readNonnullUTF8();
171 String type = source.readNonnullUTF8();
172
173 NameAndTypeItem item = new NameAndTypeItem(itemIndex);
174 item.set(name, type);
175 return item;
176 }
177
178 @NonNull
179 private Item copyFieldOrMethodReferenceItem(int type) {
180 String classDesc = source.readNonnullClass();
181 int nameCodeIndex = source.readItem();
182 String methodName = source.readNonnullUTF8(nameCodeIndex);
183 String methodDesc = source.readNonnullUTF8(nameCodeIndex + 2);
184
185 ClassMemberItem item = new ClassMemberItem(itemIndex);
186 item.set(type, classDesc, methodName, methodDesc);
187 return item;
188 }
189
190 @NonNull
191 private Item copyHandleItem() {
192 int tag = source.readUnsignedByte();
193
194 int fieldOrMethodRef = source.readItem();
195 int nameCodeIndex = source.readItem(fieldOrMethodRef + 2);
196
197 String classDesc = source.readNonnullClass(fieldOrMethodRef);
198 String name = source.readNonnullUTF8(nameCodeIndex);
199 String desc = source.readNonnullUTF8(nameCodeIndex + 2);
200
201 MethodHandle handle = new MethodHandle(tag, classDesc, name, desc);
202 MethodHandleItem item = new MethodHandleItem(itemIndex);
203 item.set(handle);
204 return item;
205 }
206
207 @NonNull
208 private Item copyDynamicItem(int type) {
209 int bsmIndex = source.readUnsignedShort();
210 int nameCodeIndex = source.readItem();
211 String name = source.readNonnullUTF8(nameCodeIndex);
212 String desc = source.readNonnullUTF8(nameCodeIndex + 2);
213
214 DynamicItem item = new DynamicItem(itemIndex);
215 item.set(type, name, desc, bsmIndex);
216 return item;
217 }
218
219 @NonNull
220 private Item copyModule() {
221 int nameIndex = source.readItem();
222 String name = source.readNonnullUTF8(nameIndex);
223 return new ModuleItem(itemIndex, MODULE, name);
224 }
225
226 @NonNull
227 private Item copyPackage() {
228 int nameIndex = source.readItem();
229 String name = source.readNonnullUTF8(nameIndex);
230 return new PackageItem(itemIndex, PACKAGE, name);
231 }
232 }