View Javadoc
1   /*
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3    *
4    * This code is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU General Public License version 2 only, as
6    * published by the Free Software Foundation.  Oracle designates this
7    * particular file as subject to the "Classpath" exception as provided
8    * by Oracle in the LICENSE file that accompanied this code.
9    *
10   * This code is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13   * version 2 for more details (a copy is included in the LICENSE file that
14   * accompanied this code).
15   *
16   * You should have received a copy of the GNU General Public License version
17   * 2 along with this work; if not, write to the Free Software Foundation,
18   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19   *
20   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21   * or visit www.oracle.com if you need additional information or have any
22   * questions.
23   */
24  
25  /*
26   * This file is available under and governed by the GNU General Public
27   * License version 2 only, as published by the Free Software Foundation.
28   * However, the following notice accompanied the original version of this
29   * file:
30   *
31   * ASM: a very small and fast Java bytecode manipulation framework
32   * Copyright (c) 2000-2011 INRIA, France Telecom
33   * All rights reserved.
34   *
35   * Redistribution and use in source and binary forms, with or without
36   * modification, are permitted provided that the following conditions
37   * are met:
38   * 1. Redistributions of source code must retain the above copyright
39   *    notice, this list of conditions and the following disclaimer.
40   * 2. Redistributions in binary form must reproduce the above copyright
41   *    notice, this list of conditions and the following disclaimer in the
42   *    documentation and/or other materials provided with the distribution.
43   * 3. Neither the name of the copyright holders nor the names of its
44   *    contributors may be used to endorse or promote products derived from
45   *    this software without specific prior written permission.
46   *
47   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57   * THE POSSIBILITY OF SUCH DAMAGE.
58   */
59  package jdk.internal.org.objectweb.asm;
60  
61  /**
62   * A constant pool item. Constant pool items can be created with the 'newXXX'
63   * methods in the {@link ClassWriter} class.
64   *
65   * @author Eric Bruneton
66   */
67  final class Item {
68  
69      /**
70       * Index of this item in the constant pool.
71       */
72      int index;
73  
74      /**
75       * Type of this constant pool item. A single class is used to represent all
76       * constant pool item types, in order to minimize the bytecode size of this
77       * package. The value of this field is one of {@link ClassWriter#INT},
78       * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
79       * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
80       * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
81       * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
82       * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
83       * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
84       *
85       * MethodHandle constant 9 variations are stored using a range of 9 values
86       * from {@link ClassWriter#HANDLE_BASE} + 1 to
87       * {@link ClassWriter#HANDLE_BASE} + 9.
88       *
89       * Special Item types are used for Items that are stored in the ClassWriter
90       * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
91       * avoid clashes with normal constant pool items in the ClassWriter constant
92       * pool's hash table. These special item types are
93       * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
94       * {@link ClassWriter#TYPE_MERGED}.
95       */
96      int type;
97  
98      /**
99       * Value of this item, for an integer item.
100      */
101     int intVal;
102 
103     /**
104      * Value of this item, for a long item.
105      */
106     long longVal;
107 
108     /**
109      * First part of the value of this item, for items that do not hold a
110      * primitive value.
111      */
112     String strVal1;
113 
114     /**
115      * Second part of the value of this item, for items that do not hold a
116      * primitive value.
117      */
118     String strVal2;
119 
120     /**
121      * Third part of the value of this item, for items that do not hold a
122      * primitive value.
123      */
124     String strVal3;
125 
126     /**
127      * The hash code value of this constant pool item.
128      */
129     int hashCode;
130 
131     /**
132      * Link to another constant pool item, used for collision lists in the
133      * constant pool's hash table.
134      */
135     Item next;
136 
137     /**
138      * Constructs an uninitialized {@link Item}.
139      */
140     Item() {
141     }
142 
143     /**
144      * Constructs an uninitialized {@link Item} for constant pool element at
145      * given position.
146      *
147      * @param index
148      *            index of the item to be constructed.
149      */
150     Item(final int index) {
151         this.index = index;
152     }
153 
154     /**
155      * Constructs a copy of the given item.
156      *
157      * @param index
158      *            index of the item to be constructed.
159      * @param i
160      *            the item that must be copied into the item to be constructed.
161      */
162     Item(final int index, final Item i) {
163         this.index = index;
164         type = i.type;
165         intVal = i.intVal;
166         longVal = i.longVal;
167         strVal1 = i.strVal1;
168         strVal2 = i.strVal2;
169         strVal3 = i.strVal3;
170         hashCode = i.hashCode;
171     }
172 
173     /**
174      * Sets this item to an integer item.
175      *
176      * @param intVal
177      *            the value of this item.
178      */
179     void set(final int intVal) {
180         this.type = ClassWriter.INT;
181         this.intVal = intVal;
182         this.hashCode = 0x7FFFFFFF & (type + intVal);
183     }
184 
185     /**
186      * Sets this item to a long item.
187      *
188      * @param longVal
189      *            the value of this item.
190      */
191     void set(final long longVal) {
192         this.type = ClassWriter.LONG;
193         this.longVal = longVal;
194         this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
195     }
196 
197     /**
198      * Sets this item to a float item.
199      *
200      * @param floatVal
201      *            the value of this item.
202      */
203     void set(final float floatVal) {
204         this.type = ClassWriter.FLOAT;
205         this.intVal = Float.floatToRawIntBits(floatVal);
206         this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
207     }
208 
209     /**
210      * Sets this item to a double item.
211      *
212      * @param doubleVal
213      *            the value of this item.
214      */
215     void set(final double doubleVal) {
216         this.type = ClassWriter.DOUBLE;
217         this.longVal = Double.doubleToRawLongBits(doubleVal);
218         this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
219     }
220 
221     /**
222      * Sets this item to an item that do not hold a primitive value.
223      *
224      * @param type
225      *            the type of this item.
226      * @param strVal1
227      *            first part of the value of this item.
228      * @param strVal2
229      *            second part of the value of this item.
230      * @param strVal3
231      *            third part of the value of this item.
232      */
233     void set(final int type, final String strVal1, final String strVal2,
234             final String strVal3) {
235         this.type = type;
236         this.strVal1 = strVal1;
237         this.strVal2 = strVal2;
238         this.strVal3 = strVal3;
239         switch (type) {
240         case ClassWriter.UTF8:
241         case ClassWriter.STR:
242         case ClassWriter.CLASS:
243         case ClassWriter.MTYPE:
244         case ClassWriter.TYPE_NORMAL:
245             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
246             return;
247         case ClassWriter.NAME_TYPE: {
248             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
249                     * strVal2.hashCode());
250             return;
251         }
252         // ClassWriter.FIELD:
253         // ClassWriter.METH:
254         // ClassWriter.IMETH:
255         // ClassWriter.HANDLE_BASE + 1..9
256         default:
257             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
258                     * strVal2.hashCode() * strVal3.hashCode());
259         }
260     }
261 
262     /**
263      * Sets the item to an InvokeDynamic item.
264      *
265      * @param name
266      *            invokedynamic's name.
267      * @param desc
268      *            invokedynamic's desc.
269      * @param bsmIndex
270      *            zero based index into the class attribute BootrapMethods.
271      */
272     void set(String name, String desc, int bsmIndex) {
273         this.type = ClassWriter.INDY;
274         this.longVal = bsmIndex;
275         this.strVal1 = name;
276         this.strVal2 = desc;
277         this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
278                 * strVal1.hashCode() * strVal2.hashCode());
279     }
280 
281     /**
282      * Sets the item to a BootstrapMethod item.
283      *
284      * @param position
285      *            position in byte in the class attribute BootrapMethods.
286      * @param hashCode
287      *            hashcode of the item. This hashcode is processed from the
288      *            hashcode of the bootstrap method and the hashcode of all
289      *            bootstrap arguments.
290      */
291     void set(int position, int hashCode) {
292         this.type = ClassWriter.BSM;
293         this.intVal = position;
294         this.hashCode = hashCode;
295     }
296 
297     /**
298      * Indicates if the given item is equal to this one. <i>This method assumes
299      * that the two items have the same {@link #type}</i>.
300      *
301      * @param i
302      *            the item to be compared to this one. Both items must have the
303      *            same {@link #type}.
304      * @return <tt>true</tt> if the given item if equal to this one,
305      *         <tt>false</tt> otherwise.
306      */
307     boolean isEqualTo(final Item i) {
308         switch (type) {
309         case ClassWriter.UTF8:
310         case ClassWriter.STR:
311         case ClassWriter.CLASS:
312         case ClassWriter.MTYPE:
313         case ClassWriter.TYPE_NORMAL:
314             return i.strVal1.equals(strVal1);
315         case ClassWriter.TYPE_MERGED:
316         case ClassWriter.LONG:
317         case ClassWriter.DOUBLE:
318             return i.longVal == longVal;
319         case ClassWriter.INT:
320         case ClassWriter.FLOAT:
321             return i.intVal == intVal;
322         case ClassWriter.TYPE_UNINIT:
323             return i.intVal == intVal && i.strVal1.equals(strVal1);
324         case ClassWriter.NAME_TYPE:
325             return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
326         case ClassWriter.INDY: {
327             return i.longVal == longVal && i.strVal1.equals(strVal1)
328                     && i.strVal2.equals(strVal2);
329         }
330         // case ClassWriter.FIELD:
331         // case ClassWriter.METH:
332         // case ClassWriter.IMETH:
333         // case ClassWriter.HANDLE_BASE + 1..9
334         default:
335             return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
336                     && i.strVal3.equals(strVal3);
337         }
338     }
339 
340 }