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