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