View Javadoc
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   * Copies the constant pool data from a {@link ClassReader} into a {@link ClassWriter}.
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 }