annotate src/clojure/asm/ClassWriter.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 /***
rlm@10 2 * ASM: a very small and fast Java bytecode manipulation framework
rlm@10 3 * Copyright (c) 2000-2005 INRIA, France Telecom
rlm@10 4 * All rights reserved.
rlm@10 5 *
rlm@10 6 * Redistribution and use in source and binary forms, with or without
rlm@10 7 * modification, are permitted provided that the following conditions
rlm@10 8 * are met:
rlm@10 9 * 1. Redistributions of source code must retain the above copyright
rlm@10 10 * notice, this list of conditions and the following disclaimer.
rlm@10 11 * 2. Redistributions in binary form must reproduce the above copyright
rlm@10 12 * notice, this list of conditions and the following disclaimer in the
rlm@10 13 * documentation and/or other materials provided with the distribution.
rlm@10 14 * 3. Neither the name of the copyright holders nor the names of its
rlm@10 15 * contributors may be used to endorse or promote products derived from
rlm@10 16 * this software without specific prior written permission.
rlm@10 17 *
rlm@10 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
rlm@10 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
rlm@10 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
rlm@10 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
rlm@10 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
rlm@10 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
rlm@10 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
rlm@10 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
rlm@10 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
rlm@10 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
rlm@10 28 * THE POSSIBILITY OF SUCH DAMAGE.
rlm@10 29 */
rlm@10 30 package clojure.asm;
rlm@10 31
rlm@10 32 /**
rlm@10 33 * A {@link ClassVisitor} that generates classes in bytecode form. More
rlm@10 34 * precisely this visitor generates a byte array conforming to the Java class
rlm@10 35 * file format. It can be used alone, to generate a Java class "from scratch",
rlm@10 36 * or with one or more {@link ClassReader ClassReader} and adapter class visitor
rlm@10 37 * to generate a modified class from one or more existing Java classes.
rlm@10 38 *
rlm@10 39 * @author Eric Bruneton
rlm@10 40 */
rlm@10 41 public class ClassWriter implements ClassVisitor{
rlm@10 42
rlm@10 43 /**
rlm@10 44 * Flag to automatically compute the maximum stack size and the maximum
rlm@10 45 * number of local variables of methods. If this flag is set, then the
rlm@10 46 * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
rlm@10 47 * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
rlm@10 48 * method will be ignored, and computed automatically from the signature and
rlm@10 49 * the bytecode of each method.
rlm@10 50 *
rlm@10 51 * @see #ClassWriter(int)
rlm@10 52 */
rlm@10 53 public final static int COMPUTE_MAXS = 1;
rlm@10 54
rlm@10 55 /**
rlm@10 56 * Flag to automatically compute the stack map frames of methods from
rlm@10 57 * scratch. If this flag is set, then the calls to the
rlm@10 58 * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
rlm@10 59 * frames are recomputed from the methods bytecode. The arguments of the
rlm@10 60 * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
rlm@10 61 * recomputed from the bytecode. In other words, computeFrames implies
rlm@10 62 * computeMaxs.
rlm@10 63 *
rlm@10 64 * @see #ClassWriter(int)
rlm@10 65 */
rlm@10 66 public final static int COMPUTE_FRAMES = 2;
rlm@10 67
rlm@10 68 /**
rlm@10 69 * The type of instructions without any argument.
rlm@10 70 */
rlm@10 71 final static int NOARG_INSN = 0;
rlm@10 72
rlm@10 73 /**
rlm@10 74 * The type of instructions with an signed byte argument.
rlm@10 75 */
rlm@10 76 final static int SBYTE_INSN = 1;
rlm@10 77
rlm@10 78 /**
rlm@10 79 * The type of instructions with an signed short argument.
rlm@10 80 */
rlm@10 81 final static int SHORT_INSN = 2;
rlm@10 82
rlm@10 83 /**
rlm@10 84 * The type of instructions with a local variable index argument.
rlm@10 85 */
rlm@10 86 final static int VAR_INSN = 3;
rlm@10 87
rlm@10 88 /**
rlm@10 89 * The type of instructions with an implicit local variable index argument.
rlm@10 90 */
rlm@10 91 final static int IMPLVAR_INSN = 4;
rlm@10 92
rlm@10 93 /**
rlm@10 94 * The type of instructions with a type descriptor argument.
rlm@10 95 */
rlm@10 96 final static int TYPE_INSN = 5;
rlm@10 97
rlm@10 98 /**
rlm@10 99 * The type of field and method invocations instructions.
rlm@10 100 */
rlm@10 101 final static int FIELDORMETH_INSN = 6;
rlm@10 102
rlm@10 103 /**
rlm@10 104 * The type of the INVOKEINTERFACE instruction.
rlm@10 105 */
rlm@10 106 final static int ITFMETH_INSN = 7;
rlm@10 107
rlm@10 108 /**
rlm@10 109 * The type of instructions with a 2 bytes bytecode offset label.
rlm@10 110 */
rlm@10 111 final static int LABEL_INSN = 8;
rlm@10 112
rlm@10 113 /**
rlm@10 114 * The type of instructions with a 4 bytes bytecode offset label.
rlm@10 115 */
rlm@10 116 final static int LABELW_INSN = 9;
rlm@10 117
rlm@10 118 /**
rlm@10 119 * The type of the LDC instruction.
rlm@10 120 */
rlm@10 121 final static int LDC_INSN = 10;
rlm@10 122
rlm@10 123 /**
rlm@10 124 * The type of the LDC_W and LDC2_W instructions.
rlm@10 125 */
rlm@10 126 final static int LDCW_INSN = 11;
rlm@10 127
rlm@10 128 /**
rlm@10 129 * The type of the IINC instruction.
rlm@10 130 */
rlm@10 131 final static int IINC_INSN = 12;
rlm@10 132
rlm@10 133 /**
rlm@10 134 * The type of the TABLESWITCH instruction.
rlm@10 135 */
rlm@10 136 final static int TABL_INSN = 13;
rlm@10 137
rlm@10 138 /**
rlm@10 139 * The type of the LOOKUPSWITCH instruction.
rlm@10 140 */
rlm@10 141 final static int LOOK_INSN = 14;
rlm@10 142
rlm@10 143 /**
rlm@10 144 * The type of the MULTIANEWARRAY instruction.
rlm@10 145 */
rlm@10 146 final static int MANA_INSN = 15;
rlm@10 147
rlm@10 148 /**
rlm@10 149 * The type of the WIDE instruction.
rlm@10 150 */
rlm@10 151 final static int WIDE_INSN = 16;
rlm@10 152
rlm@10 153 /**
rlm@10 154 * The instruction types of all JVM opcodes.
rlm@10 155 */
rlm@10 156 static byte[] TYPE;
rlm@10 157
rlm@10 158 /**
rlm@10 159 * The type of CONSTANT_Class constant pool items.
rlm@10 160 */
rlm@10 161 final static int CLASS = 7;
rlm@10 162
rlm@10 163 /**
rlm@10 164 * The type of CONSTANT_Fieldref constant pool items.
rlm@10 165 */
rlm@10 166 final static int FIELD = 9;
rlm@10 167
rlm@10 168 /**
rlm@10 169 * The type of CONSTANT_Methodref constant pool items.
rlm@10 170 */
rlm@10 171 final static int METH = 10;
rlm@10 172
rlm@10 173 /**
rlm@10 174 * The type of CONSTANT_InterfaceMethodref constant pool items.
rlm@10 175 */
rlm@10 176 final static int IMETH = 11;
rlm@10 177
rlm@10 178 /**
rlm@10 179 * The type of CONSTANT_String constant pool items.
rlm@10 180 */
rlm@10 181 final static int STR = 8;
rlm@10 182
rlm@10 183 /**
rlm@10 184 * The type of CONSTANT_Integer constant pool items.
rlm@10 185 */
rlm@10 186 final static int INT = 3;
rlm@10 187
rlm@10 188 /**
rlm@10 189 * The type of CONSTANT_Float constant pool items.
rlm@10 190 */
rlm@10 191 final static int FLOAT = 4;
rlm@10 192
rlm@10 193 /**
rlm@10 194 * The type of CONSTANT_Long constant pool items.
rlm@10 195 */
rlm@10 196 final static int LONG = 5;
rlm@10 197
rlm@10 198 /**
rlm@10 199 * The type of CONSTANT_Double constant pool items.
rlm@10 200 */
rlm@10 201 final static int DOUBLE = 6;
rlm@10 202
rlm@10 203 /**
rlm@10 204 * The type of CONSTANT_NameAndType constant pool items.
rlm@10 205 */
rlm@10 206 final static int NAME_TYPE = 12;
rlm@10 207
rlm@10 208 /**
rlm@10 209 * The type of CONSTANT_Utf8 constant pool items.
rlm@10 210 */
rlm@10 211 final static int UTF8 = 1;
rlm@10 212
rlm@10 213 /**
rlm@10 214 * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
rlm@10 215 * instead of the constant pool, in order to avoid clashes with normal
rlm@10 216 * constant pool items in the ClassWriter constant pool's hash table.
rlm@10 217 */
rlm@10 218 final static int TYPE_NORMAL = 13;
rlm@10 219
rlm@10 220 /**
rlm@10 221 * Uninitialized type Item stored in the ClassWriter
rlm@10 222 * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
rlm@10 223 * avoid clashes with normal constant pool items in the ClassWriter constant
rlm@10 224 * pool's hash table.
rlm@10 225 */
rlm@10 226 final static int TYPE_UNINIT = 14;
rlm@10 227
rlm@10 228 /**
rlm@10 229 * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
rlm@10 230 * instead of the constant pool, in order to avoid clashes with normal
rlm@10 231 * constant pool items in the ClassWriter constant pool's hash table.
rlm@10 232 */
rlm@10 233 final static int TYPE_MERGED = 15;
rlm@10 234
rlm@10 235 /**
rlm@10 236 * The class reader from which this class writer was constructed, if any.
rlm@10 237 */
rlm@10 238 ClassReader cr;
rlm@10 239
rlm@10 240 /**
rlm@10 241 * Minor and major version numbers of the class to be generated.
rlm@10 242 */
rlm@10 243 int version;
rlm@10 244
rlm@10 245 /**
rlm@10 246 * Index of the next item to be added in the constant pool.
rlm@10 247 */
rlm@10 248 int index;
rlm@10 249
rlm@10 250 /**
rlm@10 251 * The constant pool of this class.
rlm@10 252 */
rlm@10 253 ByteVector pool;
rlm@10 254
rlm@10 255 /**
rlm@10 256 * The constant pool's hash table data.
rlm@10 257 */
rlm@10 258 Item[] items;
rlm@10 259
rlm@10 260 /**
rlm@10 261 * The threshold of the constant pool's hash table.
rlm@10 262 */
rlm@10 263 int threshold;
rlm@10 264
rlm@10 265 /**
rlm@10 266 * A reusable key used to look for items in the {@link #items} hash table.
rlm@10 267 */
rlm@10 268 Item key;
rlm@10 269
rlm@10 270 /**
rlm@10 271 * A reusable key used to look for items in the {@link #items} hash table.
rlm@10 272 */
rlm@10 273 Item key2;
rlm@10 274
rlm@10 275 /**
rlm@10 276 * A reusable key used to look for items in the {@link #items} hash table.
rlm@10 277 */
rlm@10 278 Item key3;
rlm@10 279
rlm@10 280 /**
rlm@10 281 * A type table used to temporarily store internal names that will not
rlm@10 282 * necessarily be stored in the constant pool. This type table is used by
rlm@10 283 * the control flow and data flow analysis algorithm used to compute stack
rlm@10 284 * map frames from scratch. This array associates to each index <tt>i</tt>
rlm@10 285 * the Item whose index is <tt>i</tt>. All Item objects stored in this
rlm@10 286 * array are also stored in the {@link #items} hash table. These two arrays
rlm@10 287 * allow to retrieve an Item from its index or, conversly, to get the index
rlm@10 288 * of an Item from its value. Each Item stores an internal name in its
rlm@10 289 * {@link Item#strVal1} field.
rlm@10 290 */
rlm@10 291 Item[] typeTable;
rlm@10 292
rlm@10 293 /**
rlm@10 294 * Number of elements in the {@link #typeTable} array.
rlm@10 295 */
rlm@10 296 private short typeCount; // TODO int?
rlm@10 297
rlm@10 298 /**
rlm@10 299 * The access flags of this class.
rlm@10 300 */
rlm@10 301 private int access;
rlm@10 302
rlm@10 303 /**
rlm@10 304 * The constant pool item that contains the internal name of this class.
rlm@10 305 */
rlm@10 306 private int name;
rlm@10 307
rlm@10 308 /**
rlm@10 309 * The internal name of this class.
rlm@10 310 */
rlm@10 311 String thisName;
rlm@10 312
rlm@10 313 /**
rlm@10 314 * The constant pool item that contains the signature of this class.
rlm@10 315 */
rlm@10 316 private int signature;
rlm@10 317
rlm@10 318 /**
rlm@10 319 * The constant pool item that contains the internal name of the super class
rlm@10 320 * of this class.
rlm@10 321 */
rlm@10 322 private int superName;
rlm@10 323
rlm@10 324 /**
rlm@10 325 * Number of interfaces implemented or extended by this class or interface.
rlm@10 326 */
rlm@10 327 private int interfaceCount;
rlm@10 328
rlm@10 329 /**
rlm@10 330 * The interfaces implemented or extended by this class or interface. More
rlm@10 331 * precisely, this array contains the indexes of the constant pool items
rlm@10 332 * that contain the internal names of these interfaces.
rlm@10 333 */
rlm@10 334 private int[] interfaces;
rlm@10 335
rlm@10 336 /**
rlm@10 337 * The index of the constant pool item that contains the name of the source
rlm@10 338 * file from which this class was compiled.
rlm@10 339 */
rlm@10 340 private int sourceFile;
rlm@10 341
rlm@10 342 /**
rlm@10 343 * The SourceDebug attribute of this class.
rlm@10 344 */
rlm@10 345 private ByteVector sourceDebug;
rlm@10 346
rlm@10 347 /**
rlm@10 348 * The constant pool item that contains the name of the enclosing class of
rlm@10 349 * this class.
rlm@10 350 */
rlm@10 351 private int enclosingMethodOwner;
rlm@10 352
rlm@10 353 /**
rlm@10 354 * The constant pool item that contains the name and descriptor of the
rlm@10 355 * enclosing method of this class.
rlm@10 356 */
rlm@10 357 private int enclosingMethod;
rlm@10 358
rlm@10 359 /**
rlm@10 360 * The runtime visible annotations of this class.
rlm@10 361 */
rlm@10 362 private AnnotationWriter anns;
rlm@10 363
rlm@10 364 /**
rlm@10 365 * The runtime invisible annotations of this class.
rlm@10 366 */
rlm@10 367 private AnnotationWriter ianns;
rlm@10 368
rlm@10 369 /**
rlm@10 370 * The non standard attributes of this class.
rlm@10 371 */
rlm@10 372 private Attribute attrs;
rlm@10 373
rlm@10 374 /**
rlm@10 375 * The number of entries in the InnerClasses attribute.
rlm@10 376 */
rlm@10 377 private int innerClassesCount;
rlm@10 378
rlm@10 379 /**
rlm@10 380 * The InnerClasses attribute.
rlm@10 381 */
rlm@10 382 private ByteVector innerClasses;
rlm@10 383
rlm@10 384 /**
rlm@10 385 * The fields of this class. These fields are stored in a linked list of
rlm@10 386 * {@link FieldWriter} objects, linked to each other by their
rlm@10 387 * {@link FieldWriter#next} field. This field stores the first element of
rlm@10 388 * this list.
rlm@10 389 */
rlm@10 390 FieldWriter firstField;
rlm@10 391
rlm@10 392 /**
rlm@10 393 * The fields of this class. These fields are stored in a linked list of
rlm@10 394 * {@link FieldWriter} objects, linked to each other by their
rlm@10 395 * {@link FieldWriter#next} field. This field stores the last element of
rlm@10 396 * this list.
rlm@10 397 */
rlm@10 398 FieldWriter lastField;
rlm@10 399
rlm@10 400 /**
rlm@10 401 * The methods of this class. These methods are stored in a linked list of
rlm@10 402 * {@link MethodWriter} objects, linked to each other by their
rlm@10 403 * {@link MethodWriter#next} field. This field stores the first element of
rlm@10 404 * this list.
rlm@10 405 */
rlm@10 406 MethodWriter firstMethod;
rlm@10 407
rlm@10 408 /**
rlm@10 409 * The methods of this class. These methods are stored in a linked list of
rlm@10 410 * {@link MethodWriter} objects, linked to each other by their
rlm@10 411 * {@link MethodWriter#next} field. This field stores the last element of
rlm@10 412 * this list.
rlm@10 413 */
rlm@10 414 MethodWriter lastMethod;
rlm@10 415
rlm@10 416 /**
rlm@10 417 * <tt>true</tt> if the maximum stack size and number of local variables
rlm@10 418 * must be automatically computed.
rlm@10 419 */
rlm@10 420 private boolean computeMaxs;
rlm@10 421
rlm@10 422 /**
rlm@10 423 * <tt>true</tt> if the stack map frames must be recomputed from scratch.
rlm@10 424 */
rlm@10 425 private boolean computeFrames;
rlm@10 426
rlm@10 427 /**
rlm@10 428 * <tt>true</tt> if the stack map tables of this class are invalid. The
rlm@10 429 * {@link MethodWriter#resizeInstructions} method cannot transform existing
rlm@10 430 * stack map tables, and so produces potentially invalid classes when it is
rlm@10 431 * executed. In this case the class is reread and rewritten with the
rlm@10 432 * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
rlm@10 433 * stack map tables when this option is used).
rlm@10 434 */
rlm@10 435 boolean invalidFrames;
rlm@10 436
rlm@10 437 // ------------------------------------------------------------------------
rlm@10 438 // Static initializer
rlm@10 439 // ------------------------------------------------------------------------
rlm@10 440
rlm@10 441 /**
rlm@10 442 * Computes the instruction types of JVM opcodes.
rlm@10 443 */
rlm@10 444 static
rlm@10 445 {
rlm@10 446 int i;
rlm@10 447 byte[] b = new byte[220];
rlm@10 448 String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
rlm@10 449 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
rlm@10 450 + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
rlm@10 451 + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
rlm@10 452 for(i = 0; i < b.length; ++i)
rlm@10 453 {
rlm@10 454 b[i] = (byte) (s.charAt(i) - 'A');
rlm@10 455 }
rlm@10 456 TYPE = b;
rlm@10 457
rlm@10 458 // code to generate the above string
rlm@10 459 //
rlm@10 460 // // SBYTE_INSN instructions
rlm@10 461 // b[Constants.NEWARRAY] = SBYTE_INSN;
rlm@10 462 // b[Constants.BIPUSH] = SBYTE_INSN;
rlm@10 463 //
rlm@10 464 // // SHORT_INSN instructions
rlm@10 465 // b[Constants.SIPUSH] = SHORT_INSN;
rlm@10 466 //
rlm@10 467 // // (IMPL)VAR_INSN instructions
rlm@10 468 // b[Constants.RET] = VAR_INSN;
rlm@10 469 // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
rlm@10 470 // b[i] = VAR_INSN;
rlm@10 471 // }
rlm@10 472 // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
rlm@10 473 // b[i] = VAR_INSN;
rlm@10 474 // }
rlm@10 475 // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
rlm@10 476 // b[i] = IMPLVAR_INSN;
rlm@10 477 // }
rlm@10 478 // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
rlm@10 479 // b[i] = IMPLVAR_INSN;
rlm@10 480 // }
rlm@10 481 //
rlm@10 482 // // TYPE_INSN instructions
rlm@10 483 // b[Constants.NEW] = TYPE_INSN;
rlm@10 484 // b[Constants.ANEWARRAY] = TYPE_INSN;
rlm@10 485 // b[Constants.CHECKCAST] = TYPE_INSN;
rlm@10 486 // b[Constants.INSTANCEOF] = TYPE_INSN;
rlm@10 487 //
rlm@10 488 // // (Set)FIELDORMETH_INSN instructions
rlm@10 489 // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
rlm@10 490 // b[i] = FIELDORMETH_INSN;
rlm@10 491 // }
rlm@10 492 // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
rlm@10 493 //
rlm@10 494 // // LABEL(W)_INSN instructions
rlm@10 495 // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
rlm@10 496 // b[i] = LABEL_INSN;
rlm@10 497 // }
rlm@10 498 // b[Constants.IFNULL] = LABEL_INSN;
rlm@10 499 // b[Constants.IFNONNULL] = LABEL_INSN;
rlm@10 500 // b[200] = LABELW_INSN; // GOTO_W
rlm@10 501 // b[201] = LABELW_INSN; // JSR_W
rlm@10 502 // // temporary opcodes used internally by ASM - see Label and
rlm@10 503 // MethodWriter
rlm@10 504 // for (i = 202; i < 220; ++i) {
rlm@10 505 // b[i] = LABEL_INSN;
rlm@10 506 // }
rlm@10 507 //
rlm@10 508 // // LDC(_W) instructions
rlm@10 509 // b[Constants.LDC] = LDC_INSN;
rlm@10 510 // b[19] = LDCW_INSN; // LDC_W
rlm@10 511 // b[20] = LDCW_INSN; // LDC2_W
rlm@10 512 //
rlm@10 513 // // special instructions
rlm@10 514 // b[Constants.IINC] = IINC_INSN;
rlm@10 515 // b[Constants.TABLESWITCH] = TABL_INSN;
rlm@10 516 // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
rlm@10 517 // b[Constants.MULTIANEWARRAY] = MANA_INSN;
rlm@10 518 // b[196] = WIDE_INSN; // WIDE
rlm@10 519 //
rlm@10 520 // for (i = 0; i < b.length; ++i) {
rlm@10 521 // System.err.print((char)('A' + b[i]));
rlm@10 522 // }
rlm@10 523 // System.err.println();
rlm@10 524 }
rlm@10 525
rlm@10 526 // ------------------------------------------------------------------------
rlm@10 527 // Constructor
rlm@10 528 // ------------------------------------------------------------------------
rlm@10 529
rlm@10 530 /**
rlm@10 531 * Constructs a new {@link ClassWriter} object.
rlm@10 532 *
rlm@10 533 * @param flags option flags that can be used to modify the default behavior
rlm@10 534 * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
rlm@10 535 */
rlm@10 536 public ClassWriter(final int flags){
rlm@10 537 index = 1;
rlm@10 538 pool = new ByteVector();
rlm@10 539 items = new Item[256];
rlm@10 540 threshold = (int) (0.75d * items.length);
rlm@10 541 key = new Item();
rlm@10 542 key2 = new Item();
rlm@10 543 key3 = new Item();
rlm@10 544 this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
rlm@10 545 this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
rlm@10 546 }
rlm@10 547
rlm@10 548 /**
rlm@10 549 * Constructs a new {@link ClassWriter} object and enables optimizations for
rlm@10 550 * "mostly add" bytecode transformations. These optimizations are the
rlm@10 551 * following:
rlm@10 552 * <p/>
rlm@10 553 * <ul> <li>The constant pool from the original class is copied as is in
rlm@10 554 * the new class, which saves time. New constant pool entries will be added
rlm@10 555 * at the end if necessary, but unused constant pool entries <i>won't be
rlm@10 556 * removed</i>.</li> <li>Methods that are not transformed are copied as
rlm@10 557 * is in the new class, directly from the original class bytecode (i.e.
rlm@10 558 * without emitting visit events for all the method instructions), which
rlm@10 559 * saves a <i>lot</i> of time. Untransformed methods are detected by the
rlm@10 560 * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
rlm@10 561 * that come from a {@link ClassWriter} (and not from a custom
rlm@10 562 * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
rlm@10 563 * </ul>
rlm@10 564 *
rlm@10 565 * @param classReader the {@link ClassReader} used to read the original
rlm@10 566 * class. It will be used to copy the entire constant pool from the
rlm@10 567 * original class and also to copy other fragments of original
rlm@10 568 * bytecode where applicable.
rlm@10 569 * @param flags option flags that can be used to modify the default behavior
rlm@10 570 * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
rlm@10 571 */
rlm@10 572 public ClassWriter(final ClassReader classReader, final int flags){
rlm@10 573 this(flags);
rlm@10 574 classReader.copyPool(this);
rlm@10 575 this.cr = classReader;
rlm@10 576 }
rlm@10 577
rlm@10 578 // ------------------------------------------------------------------------
rlm@10 579 // Implementation of the ClassVisitor interface
rlm@10 580 // ------------------------------------------------------------------------
rlm@10 581
rlm@10 582 public void visit(
rlm@10 583 final int version,
rlm@10 584 final int access,
rlm@10 585 final String name,
rlm@10 586 final String signature,
rlm@10 587 final String superName,
rlm@10 588 final String[] interfaces){
rlm@10 589 this.version = version;
rlm@10 590 this.access = access;
rlm@10 591 this.name = newClass(name);
rlm@10 592 thisName = name;
rlm@10 593 if(signature != null)
rlm@10 594 {
rlm@10 595 this.signature = newUTF8(signature);
rlm@10 596 }
rlm@10 597 this.superName = superName == null ? 0 : newClass(superName);
rlm@10 598 if(interfaces != null && interfaces.length > 0)
rlm@10 599 {
rlm@10 600 interfaceCount = interfaces.length;
rlm@10 601 this.interfaces = new int[interfaceCount];
rlm@10 602 for(int i = 0; i < interfaceCount; ++i)
rlm@10 603 {
rlm@10 604 this.interfaces[i] = newClass(interfaces[i]);
rlm@10 605 }
rlm@10 606 }
rlm@10 607 }
rlm@10 608
rlm@10 609 public void visitSource(final String file, final String debug){
rlm@10 610 if(file != null)
rlm@10 611 {
rlm@10 612 sourceFile = newUTF8(file);
rlm@10 613 }
rlm@10 614 if(debug != null)
rlm@10 615 {
rlm@10 616 sourceDebug = new ByteVector().putUTF8(debug);
rlm@10 617 }
rlm@10 618 }
rlm@10 619
rlm@10 620 public void visitOuterClass(
rlm@10 621 final String owner,
rlm@10 622 final String name,
rlm@10 623 final String desc){
rlm@10 624 enclosingMethodOwner = newClass(owner);
rlm@10 625 if(name != null && desc != null)
rlm@10 626 {
rlm@10 627 enclosingMethod = newNameType(name, desc);
rlm@10 628 }
rlm@10 629 }
rlm@10 630
rlm@10 631 public AnnotationVisitor visitAnnotation(
rlm@10 632 final String desc,
rlm@10 633 final boolean visible){
rlm@10 634 ByteVector bv = new ByteVector();
rlm@10 635 // write type, and reserve space for values count
rlm@10 636 bv.putShort(newUTF8(desc)).putShort(0);
rlm@10 637 AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
rlm@10 638 if(visible)
rlm@10 639 {
rlm@10 640 aw.next = anns;
rlm@10 641 anns = aw;
rlm@10 642 }
rlm@10 643 else
rlm@10 644 {
rlm@10 645 aw.next = ianns;
rlm@10 646 ianns = aw;
rlm@10 647 }
rlm@10 648 return aw;
rlm@10 649 }
rlm@10 650
rlm@10 651 public void visitAttribute(final Attribute attr){
rlm@10 652 attr.next = attrs;
rlm@10 653 attrs = attr;
rlm@10 654 }
rlm@10 655
rlm@10 656 public void visitInnerClass(
rlm@10 657 final String name,
rlm@10 658 final String outerName,
rlm@10 659 final String innerName,
rlm@10 660 final int access){
rlm@10 661 if(innerClasses == null)
rlm@10 662 {
rlm@10 663 innerClasses = new ByteVector();
rlm@10 664 }
rlm@10 665 ++innerClassesCount;
rlm@10 666 innerClasses.putShort(name == null ? 0 : newClass(name));
rlm@10 667 innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
rlm@10 668 innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
rlm@10 669 innerClasses.putShort(access);
rlm@10 670 }
rlm@10 671
rlm@10 672 public FieldVisitor visitField(
rlm@10 673 final int access,
rlm@10 674 final String name,
rlm@10 675 final String desc,
rlm@10 676 final String signature,
rlm@10 677 final Object value){
rlm@10 678 return new FieldWriter(this, access, name, desc, signature, value);
rlm@10 679 }
rlm@10 680
rlm@10 681 public MethodVisitor visitMethod(
rlm@10 682 final int access,
rlm@10 683 final String name,
rlm@10 684 final String desc,
rlm@10 685 final String signature,
rlm@10 686 final String[] exceptions){
rlm@10 687 return new MethodWriter(this,
rlm@10 688 access,
rlm@10 689 name,
rlm@10 690 desc,
rlm@10 691 signature,
rlm@10 692 exceptions,
rlm@10 693 computeMaxs,
rlm@10 694 computeFrames);
rlm@10 695 }
rlm@10 696
rlm@10 697 public void visitEnd(){
rlm@10 698 }
rlm@10 699
rlm@10 700 // ------------------------------------------------------------------------
rlm@10 701 // Other public methods
rlm@10 702 // ------------------------------------------------------------------------
rlm@10 703
rlm@10 704 /**
rlm@10 705 * Returns the bytecode of the class that was build with this class writer.
rlm@10 706 *
rlm@10 707 * @return the bytecode of the class that was build with this class writer.
rlm@10 708 */
rlm@10 709 public byte[] toByteArray(){
rlm@10 710 // computes the real size of the bytecode of this class
rlm@10 711 int size = 24 + 2 * interfaceCount;
rlm@10 712 int nbFields = 0;
rlm@10 713 FieldWriter fb = firstField;
rlm@10 714 while(fb != null)
rlm@10 715 {
rlm@10 716 ++nbFields;
rlm@10 717 size += fb.getSize();
rlm@10 718 fb = fb.next;
rlm@10 719 }
rlm@10 720 int nbMethods = 0;
rlm@10 721 MethodWriter mb = firstMethod;
rlm@10 722 while(mb != null)
rlm@10 723 {
rlm@10 724 ++nbMethods;
rlm@10 725 size += mb.getSize();
rlm@10 726 mb = mb.next;
rlm@10 727 }
rlm@10 728 int attributeCount = 0;
rlm@10 729 if(signature != 0)
rlm@10 730 {
rlm@10 731 ++attributeCount;
rlm@10 732 size += 8;
rlm@10 733 newUTF8("Signature");
rlm@10 734 }
rlm@10 735 if(sourceFile != 0)
rlm@10 736 {
rlm@10 737 ++attributeCount;
rlm@10 738 size += 8;
rlm@10 739 newUTF8("SourceFile");
rlm@10 740 }
rlm@10 741 if(sourceDebug != null)
rlm@10 742 {
rlm@10 743 ++attributeCount;
rlm@10 744 size += sourceDebug.length + 4;
rlm@10 745 newUTF8("SourceDebugExtension");
rlm@10 746 }
rlm@10 747 if(enclosingMethodOwner != 0)
rlm@10 748 {
rlm@10 749 ++attributeCount;
rlm@10 750 size += 10;
rlm@10 751 newUTF8("EnclosingMethod");
rlm@10 752 }
rlm@10 753 if((access & Opcodes.ACC_DEPRECATED) != 0)
rlm@10 754 {
rlm@10 755 ++attributeCount;
rlm@10 756 size += 6;
rlm@10 757 newUTF8("Deprecated");
rlm@10 758 }
rlm@10 759 if((access & Opcodes.ACC_SYNTHETIC) != 0
rlm@10 760 && (version & 0xffff) < Opcodes.V1_5)
rlm@10 761 {
rlm@10 762 ++attributeCount;
rlm@10 763 size += 6;
rlm@10 764 newUTF8("Synthetic");
rlm@10 765 }
rlm@10 766 if(innerClasses != null)
rlm@10 767 {
rlm@10 768 ++attributeCount;
rlm@10 769 size += 8 + innerClasses.length;
rlm@10 770 newUTF8("InnerClasses");
rlm@10 771 }
rlm@10 772 if(anns != null)
rlm@10 773 {
rlm@10 774 ++attributeCount;
rlm@10 775 size += 8 + anns.getSize();
rlm@10 776 newUTF8("RuntimeVisibleAnnotations");
rlm@10 777 }
rlm@10 778 if(ianns != null)
rlm@10 779 {
rlm@10 780 ++attributeCount;
rlm@10 781 size += 8 + ianns.getSize();
rlm@10 782 newUTF8("RuntimeInvisibleAnnotations");
rlm@10 783 }
rlm@10 784 if(attrs != null)
rlm@10 785 {
rlm@10 786 attributeCount += attrs.getCount();
rlm@10 787 size += attrs.getSize(this, null, 0, -1, -1);
rlm@10 788 }
rlm@10 789 size += pool.length;
rlm@10 790 // allocates a byte vector of this size, in order to avoid unnecessary
rlm@10 791 // arraycopy operations in the ByteVector.enlarge() method
rlm@10 792 ByteVector out = new ByteVector(size);
rlm@10 793 out.putInt(0xCAFEBABE).putInt(version);
rlm@10 794 out.putShort(index).putByteArray(pool.data, 0, pool.length);
rlm@10 795 out.putShort(access).putShort(name).putShort(superName);
rlm@10 796 out.putShort(interfaceCount);
rlm@10 797 for(int i = 0; i < interfaceCount; ++i)
rlm@10 798 {
rlm@10 799 out.putShort(interfaces[i]);
rlm@10 800 }
rlm@10 801 out.putShort(nbFields);
rlm@10 802 fb = firstField;
rlm@10 803 while(fb != null)
rlm@10 804 {
rlm@10 805 fb.put(out);
rlm@10 806 fb = fb.next;
rlm@10 807 }
rlm@10 808 out.putShort(nbMethods);
rlm@10 809 mb = firstMethod;
rlm@10 810 while(mb != null)
rlm@10 811 {
rlm@10 812 mb.put(out);
rlm@10 813 mb = mb.next;
rlm@10 814 }
rlm@10 815 out.putShort(attributeCount);
rlm@10 816 if(signature != 0)
rlm@10 817 {
rlm@10 818 out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
rlm@10 819 }
rlm@10 820 if(sourceFile != 0)
rlm@10 821 {
rlm@10 822 out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
rlm@10 823 }
rlm@10 824 if(sourceDebug != null)
rlm@10 825 {
rlm@10 826 int len = sourceDebug.length - 2;
rlm@10 827 out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
rlm@10 828 out.putByteArray(sourceDebug.data, 2, len);
rlm@10 829 }
rlm@10 830 if(enclosingMethodOwner != 0)
rlm@10 831 {
rlm@10 832 out.putShort(newUTF8("EnclosingMethod")).putInt(4);
rlm@10 833 out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
rlm@10 834 }
rlm@10 835 if((access & Opcodes.ACC_DEPRECATED) != 0)
rlm@10 836 {
rlm@10 837 out.putShort(newUTF8("Deprecated")).putInt(0);
rlm@10 838 }
rlm@10 839 if((access & Opcodes.ACC_SYNTHETIC) != 0
rlm@10 840 && (version & 0xffff) < Opcodes.V1_5)
rlm@10 841 {
rlm@10 842 out.putShort(newUTF8("Synthetic")).putInt(0);
rlm@10 843 }
rlm@10 844 if(innerClasses != null)
rlm@10 845 {
rlm@10 846 out.putShort(newUTF8("InnerClasses"));
rlm@10 847 out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
rlm@10 848 out.putByteArray(innerClasses.data, 0, innerClasses.length);
rlm@10 849 }
rlm@10 850 if(anns != null)
rlm@10 851 {
rlm@10 852 out.putShort(newUTF8("RuntimeVisibleAnnotations"));
rlm@10 853 anns.put(out);
rlm@10 854 }
rlm@10 855 if(ianns != null)
rlm@10 856 {
rlm@10 857 out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
rlm@10 858 ianns.put(out);
rlm@10 859 }
rlm@10 860 if(attrs != null)
rlm@10 861 {
rlm@10 862 attrs.put(this, null, 0, -1, -1, out);
rlm@10 863 }
rlm@10 864 if(invalidFrames)
rlm@10 865 {
rlm@10 866 ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
rlm@10 867 new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
rlm@10 868 return cw.toByteArray();
rlm@10 869 }
rlm@10 870 return out.data;
rlm@10 871 }
rlm@10 872
rlm@10 873 // ------------------------------------------------------------------------
rlm@10 874 // Utility methods: constant pool management
rlm@10 875 // ------------------------------------------------------------------------
rlm@10 876
rlm@10 877 /**
rlm@10 878 * Adds a number or string constant to the constant pool of the class being
rlm@10 879 * build. Does nothing if the constant pool already contains a similar item.
rlm@10 880 *
rlm@10 881 * @param cst the value of the constant to be added to the constant pool.
rlm@10 882 * This parameter must be an {@link Integer}, a {@link Float}, a
rlm@10 883 * {@link Long}, a {@link Double}, a {@link String} or a
rlm@10 884 * {@link Type}.
rlm@10 885 * @return a new or already existing constant item with the given value.
rlm@10 886 */
rlm@10 887 Item newConstItem(final Object cst){
rlm@10 888 if(cst instanceof Integer)
rlm@10 889 {
rlm@10 890 int val = ((Integer) cst).intValue();
rlm@10 891 return newInteger(val);
rlm@10 892 }
rlm@10 893 else if(cst instanceof Byte)
rlm@10 894 {
rlm@10 895 int val = ((Byte) cst).intValue();
rlm@10 896 return newInteger(val);
rlm@10 897 }
rlm@10 898 else if(cst instanceof Character)
rlm@10 899 {
rlm@10 900 int val = ((Character) cst).charValue();
rlm@10 901 return newInteger(val);
rlm@10 902 }
rlm@10 903 else if(cst instanceof Short)
rlm@10 904 {
rlm@10 905 int val = ((Short) cst).intValue();
rlm@10 906 return newInteger(val);
rlm@10 907 }
rlm@10 908 else if(cst instanceof Boolean)
rlm@10 909 {
rlm@10 910 int val = ((Boolean) cst).booleanValue() ? 1 : 0;
rlm@10 911 return newInteger(val);
rlm@10 912 }
rlm@10 913 else if(cst instanceof Float)
rlm@10 914 {
rlm@10 915 float val = ((Float) cst).floatValue();
rlm@10 916 return newFloat(val);
rlm@10 917 }
rlm@10 918 else if(cst instanceof Long)
rlm@10 919 {
rlm@10 920 long val = ((Long) cst).longValue();
rlm@10 921 return newLong(val);
rlm@10 922 }
rlm@10 923 else if(cst instanceof Double)
rlm@10 924 {
rlm@10 925 double val = ((Double) cst).doubleValue();
rlm@10 926 return newDouble(val);
rlm@10 927 }
rlm@10 928 else if(cst instanceof String)
rlm@10 929 {
rlm@10 930 return newString((String) cst);
rlm@10 931 }
rlm@10 932 else if(cst instanceof Type)
rlm@10 933 {
rlm@10 934 Type t = (Type) cst;
rlm@10 935 return newClassItem(t.getSort() == Type.OBJECT
rlm@10 936 ? t.getInternalName()
rlm@10 937 : t.getDescriptor());
rlm@10 938 }
rlm@10 939 else
rlm@10 940 {
rlm@10 941 throw new IllegalArgumentException("value " + cst);
rlm@10 942 }
rlm@10 943 }
rlm@10 944
rlm@10 945 /**
rlm@10 946 * Adds a number or string constant to the constant pool of the class being
rlm@10 947 * build. Does nothing if the constant pool already contains a similar item.
rlm@10 948 * <i>This method is intended for {@link Attribute} sub classes, and is
rlm@10 949 * normally not needed by class generators or adapters.</i>
rlm@10 950 *
rlm@10 951 * @param cst the value of the constant to be added to the constant pool.
rlm@10 952 * This parameter must be an {@link Integer}, a {@link Float}, a
rlm@10 953 * {@link Long}, a {@link Double} or a {@link String}.
rlm@10 954 * @return the index of a new or already existing constant item with the
rlm@10 955 * given value.
rlm@10 956 */
rlm@10 957 public int newConst(final Object cst){
rlm@10 958 return newConstItem(cst).index;
rlm@10 959 }
rlm@10 960
rlm@10 961 /**
rlm@10 962 * Adds an UTF8 string to the constant pool of the class being build. Does
rlm@10 963 * nothing if the constant pool already contains a similar item. <i>This
rlm@10 964 * method is intended for {@link Attribute} sub classes, and is normally not
rlm@10 965 * needed by class generators or adapters.</i>
rlm@10 966 *
rlm@10 967 * @param value the String value.
rlm@10 968 * @return the index of a new or already existing UTF8 item.
rlm@10 969 */
rlm@10 970 public int newUTF8(final String value){
rlm@10 971 key.set(UTF8, value, null, null);
rlm@10 972 Item result = get(key);
rlm@10 973 if(result == null)
rlm@10 974 {
rlm@10 975 pool.putByte(UTF8).putUTF8(value);
rlm@10 976 result = new Item(index++, key);
rlm@10 977 put(result);
rlm@10 978 }
rlm@10 979 return result.index;
rlm@10 980 }
rlm@10 981
rlm@10 982 /**
rlm@10 983 * Adds a class reference to the constant pool of the class being build.
rlm@10 984 * Does nothing if the constant pool already contains a similar item.
rlm@10 985 * <i>This method is intended for {@link Attribute} sub classes, and is
rlm@10 986 * normally not needed by class generators or adapters.</i>
rlm@10 987 *
rlm@10 988 * @param value the internal name of the class.
rlm@10 989 * @return a new or already existing class reference item.
rlm@10 990 */
rlm@10 991 Item newClassItem(final String value){
rlm@10 992 key2.set(CLASS, value, null, null);
rlm@10 993 Item result = get(key2);
rlm@10 994 if(result == null)
rlm@10 995 {
rlm@10 996 pool.put12(CLASS, newUTF8(value));
rlm@10 997 result = new Item(index++, key2);
rlm@10 998 put(result);
rlm@10 999 }
rlm@10 1000 return result;
rlm@10 1001 }
rlm@10 1002
rlm@10 1003 /**
rlm@10 1004 * Adds a class reference to the constant pool of the class being build.
rlm@10 1005 * Does nothing if the constant pool already contains a similar item.
rlm@10 1006 * <i>This method is intended for {@link Attribute} sub classes, and is
rlm@10 1007 * normally not needed by class generators or adapters.</i>
rlm@10 1008 *
rlm@10 1009 * @param value the internal name of the class.
rlm@10 1010 * @return the index of a new or already existing class reference item.
rlm@10 1011 */
rlm@10 1012 public int newClass(final String value){
rlm@10 1013 return newClassItem(value).index;
rlm@10 1014 }
rlm@10 1015
rlm@10 1016 /**
rlm@10 1017 * Adds a field reference to the constant pool of the class being build.
rlm@10 1018 * Does nothing if the constant pool already contains a similar item.
rlm@10 1019 *
rlm@10 1020 * @param owner the internal name of the field's owner class.
rlm@10 1021 * @param name the field's name.
rlm@10 1022 * @param desc the field's descriptor.
rlm@10 1023 * @return a new or already existing field reference item.
rlm@10 1024 */
rlm@10 1025 Item newFieldItem(final String owner, final String name, final String desc){
rlm@10 1026 key3.set(FIELD, owner, name, desc);
rlm@10 1027 Item result = get(key3);
rlm@10 1028 if(result == null)
rlm@10 1029 {
rlm@10 1030 put122(FIELD, newClass(owner), newNameType(name, desc));
rlm@10 1031 result = new Item(index++, key3);
rlm@10 1032 put(result);
rlm@10 1033 }
rlm@10 1034 return result;
rlm@10 1035 }
rlm@10 1036
rlm@10 1037 /**
rlm@10 1038 * Adds a field reference to the constant pool of the class being build.
rlm@10 1039 * Does nothing if the constant pool already contains a similar item.
rlm@10 1040 * <i>This method is intended for {@link Attribute} sub classes, and is
rlm@10 1041 * normally not needed by class generators or adapters.</i>
rlm@10 1042 *
rlm@10 1043 * @param owner the internal name of the field's owner class.
rlm@10 1044 * @param name the field's name.
rlm@10 1045 * @param desc the field's descriptor.
rlm@10 1046 * @return the index of a new or already existing field reference item.
rlm@10 1047 */
rlm@10 1048 public int newField(final String owner, final String name, final String desc){
rlm@10 1049 return newFieldItem(owner, name, desc).index;
rlm@10 1050 }
rlm@10 1051
rlm@10 1052 /**
rlm@10 1053 * Adds a method reference to the constant pool of the class being build.
rlm@10 1054 * Does nothing if the constant pool already contains a similar item.
rlm@10 1055 *
rlm@10 1056 * @param owner the internal name of the method's owner class.
rlm@10 1057 * @param name the method's name.
rlm@10 1058 * @param desc the method's descriptor.
rlm@10 1059 * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
rlm@10 1060 * @return a new or already existing method reference item.
rlm@10 1061 */
rlm@10 1062 Item newMethodItem(
rlm@10 1063 final String owner,
rlm@10 1064 final String name,
rlm@10 1065 final String desc,
rlm@10 1066 final boolean itf){
rlm@10 1067 int type = itf ? IMETH : METH;
rlm@10 1068 key3.set(type, owner, name, desc);
rlm@10 1069 Item result = get(key3);
rlm@10 1070 if(result == null)
rlm@10 1071 {
rlm@10 1072 put122(type, newClass(owner), newNameType(name, desc));
rlm@10 1073 result = new Item(index++, key3);
rlm@10 1074 put(result);
rlm@10 1075 }
rlm@10 1076 return result;
rlm@10 1077 }
rlm@10 1078
rlm@10 1079 /**
rlm@10 1080 * Adds a method reference to the constant pool of the class being build.
rlm@10 1081 * Does nothing if the constant pool already contains a similar item.
rlm@10 1082 * <i>This method is intended for {@link Attribute} sub classes, and is
rlm@10 1083 * normally not needed by class generators or adapters.</i>
rlm@10 1084 *
rlm@10 1085 * @param owner the internal name of the method's owner class.
rlm@10 1086 * @param name the method's name.
rlm@10 1087 * @param desc the method's descriptor.
rlm@10 1088 * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
rlm@10 1089 * @return the index of a new or already existing method reference item.
rlm@10 1090 */
rlm@10 1091 public int newMethod(
rlm@10 1092 final String owner,
rlm@10 1093 final String name,
rlm@10 1094 final String desc,
rlm@10 1095 final boolean itf){
rlm@10 1096 return newMethodItem(owner, name, desc, itf).index;
rlm@10 1097 }
rlm@10 1098
rlm@10 1099 /**
rlm@10 1100 * Adds an integer to the constant pool of the class being build. Does
rlm@10 1101 * nothing if the constant pool already contains a similar item.
rlm@10 1102 *
rlm@10 1103 * @param value the int value.
rlm@10 1104 * @return a new or already existing int item.
rlm@10 1105 */
rlm@10 1106 Item newInteger(final int value){
rlm@10 1107 key.set(value);
rlm@10 1108 Item result = get(key);
rlm@10 1109 if(result == null)
rlm@10 1110 {
rlm@10 1111 pool.putByte(INT).putInt(value);
rlm@10 1112 result = new Item(index++, key);
rlm@10 1113 put(result);
rlm@10 1114 }
rlm@10 1115 return result;
rlm@10 1116 }
rlm@10 1117
rlm@10 1118 /**
rlm@10 1119 * Adds a float to the constant pool of the class being build. Does nothing
rlm@10 1120 * if the constant pool already contains a similar item.
rlm@10 1121 *
rlm@10 1122 * @param value the float value.
rlm@10 1123 * @return a new or already existing float item.
rlm@10 1124 */
rlm@10 1125 Item newFloat(final float value){
rlm@10 1126 key.set(value);
rlm@10 1127 Item result = get(key);
rlm@10 1128 if(result == null)
rlm@10 1129 {
rlm@10 1130 pool.putByte(FLOAT).putInt(key.intVal);
rlm@10 1131 result = new Item(index++, key);
rlm@10 1132 put(result);
rlm@10 1133 }
rlm@10 1134 return result;
rlm@10 1135 }
rlm@10 1136
rlm@10 1137 /**
rlm@10 1138 * Adds a long to the constant pool of the class being build. Does nothing
rlm@10 1139 * if the constant pool already contains a similar item.
rlm@10 1140 *
rlm@10 1141 * @param value the long value.
rlm@10 1142 * @return a new or already existing long item.
rlm@10 1143 */
rlm@10 1144 Item newLong(final long value){
rlm@10 1145 key.set(value);
rlm@10 1146 Item result = get(key);
rlm@10 1147 if(result == null)
rlm@10 1148 {
rlm@10 1149 pool.putByte(LONG).putLong(value);
rlm@10 1150 result = new Item(index, key);
rlm@10 1151 put(result);
rlm@10 1152 index += 2;
rlm@10 1153 }
rlm@10 1154 return result;
rlm@10 1155 }
rlm@10 1156
rlm@10 1157 /**
rlm@10 1158 * Adds a double to the constant pool of the class being build. Does nothing
rlm@10 1159 * if the constant pool already contains a similar item.
rlm@10 1160 *
rlm@10 1161 * @param value the double value.
rlm@10 1162 * @return a new or already existing double item.
rlm@10 1163 */
rlm@10 1164 Item newDouble(final double value){
rlm@10 1165 key.set(value);
rlm@10 1166 Item result = get(key);
rlm@10 1167 if(result == null)
rlm@10 1168 {
rlm@10 1169 pool.putByte(DOUBLE).putLong(key.longVal);
rlm@10 1170 result = new Item(index, key);
rlm@10 1171 put(result);
rlm@10 1172 index += 2;
rlm@10 1173 }
rlm@10 1174 return result;
rlm@10 1175 }
rlm@10 1176
rlm@10 1177 /**
rlm@10 1178 * Adds a string to the constant pool of the class being build. Does nothing
rlm@10 1179 * if the constant pool already contains a similar item.
rlm@10 1180 *
rlm@10 1181 * @param value the String value.
rlm@10 1182 * @return a new or already existing string item.
rlm@10 1183 */
rlm@10 1184 private Item newString(final String value){
rlm@10 1185 key2.set(STR, value, null, null);
rlm@10 1186 Item result = get(key2);
rlm@10 1187 if(result == null)
rlm@10 1188 {
rlm@10 1189 pool.put12(STR, newUTF8(value));
rlm@10 1190 result = new Item(index++, key2);
rlm@10 1191 put(result);
rlm@10 1192 }
rlm@10 1193 return result;
rlm@10 1194 }
rlm@10 1195
rlm@10 1196 /**
rlm@10 1197 * Adds a name and type to the constant pool of the class being build. Does
rlm@10 1198 * nothing if the constant pool already contains a similar item. <i>This
rlm@10 1199 * method is intended for {@link Attribute} sub classes, and is normally not
rlm@10 1200 * needed by class generators or adapters.</i>
rlm@10 1201 *
rlm@10 1202 * @param name a name.
rlm@10 1203 * @param desc a type descriptor.
rlm@10 1204 * @return the index of a new or already existing name and type item.
rlm@10 1205 */
rlm@10 1206 public int newNameType(final String name, final String desc){
rlm@10 1207 key2.set(NAME_TYPE, name, desc, null);
rlm@10 1208 Item result = get(key2);
rlm@10 1209 if(result == null)
rlm@10 1210 {
rlm@10 1211 put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
rlm@10 1212 result = new Item(index++, key2);
rlm@10 1213 put(result);
rlm@10 1214 }
rlm@10 1215 return result.index;
rlm@10 1216 }
rlm@10 1217
rlm@10 1218 /**
rlm@10 1219 * Adds the given internal name to {@link #typeTable} and returns its index.
rlm@10 1220 * Does nothing if the type table already contains this internal name.
rlm@10 1221 *
rlm@10 1222 * @param type the internal name to be added to the type table.
rlm@10 1223 * @return the index of this internal name in the type table.
rlm@10 1224 */
rlm@10 1225 int addType(final String type){
rlm@10 1226 key.set(TYPE_NORMAL, type, null, null);
rlm@10 1227 Item result = get(key);
rlm@10 1228 if(result == null)
rlm@10 1229 {
rlm@10 1230 result = addType(key);
rlm@10 1231 }
rlm@10 1232 return result.index;
rlm@10 1233 }
rlm@10 1234
rlm@10 1235 /**
rlm@10 1236 * Adds the given "uninitialized" type to {@link #typeTable} and returns its
rlm@10 1237 * index. This method is used for UNINITIALIZED types, made of an internal
rlm@10 1238 * name and a bytecode offset.
rlm@10 1239 *
rlm@10 1240 * @param type the internal name to be added to the type table.
rlm@10 1241 * @param offset the bytecode offset of the NEW instruction that created
rlm@10 1242 * this UNINITIALIZED type value.
rlm@10 1243 * @return the index of this internal name in the type table.
rlm@10 1244 */
rlm@10 1245 int addUninitializedType(final String type, final int offset){
rlm@10 1246 key.type = TYPE_UNINIT;
rlm@10 1247 key.intVal = offset;
rlm@10 1248 key.strVal1 = type;
rlm@10 1249 key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
rlm@10 1250 Item result = get(key);
rlm@10 1251 if(result == null)
rlm@10 1252 {
rlm@10 1253 result = addType(key);
rlm@10 1254 }
rlm@10 1255 return result.index;
rlm@10 1256 }
rlm@10 1257
rlm@10 1258 /**
rlm@10 1259 * Adds the given Item to {@link #typeTable}.
rlm@10 1260 *
rlm@10 1261 * @param item the value to be added to the type table.
rlm@10 1262 * @return the added Item, which a new Item instance with the same value as
rlm@10 1263 * the given Item.
rlm@10 1264 */
rlm@10 1265 private Item addType(final Item item){
rlm@10 1266 ++typeCount;
rlm@10 1267 Item result = new Item(typeCount, key);
rlm@10 1268 put(result);
rlm@10 1269 if(typeTable == null)
rlm@10 1270 {
rlm@10 1271 typeTable = new Item[16];
rlm@10 1272 }
rlm@10 1273 if(typeCount == typeTable.length)
rlm@10 1274 {
rlm@10 1275 Item[] newTable = new Item[2 * typeTable.length];
rlm@10 1276 System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
rlm@10 1277 typeTable = newTable;
rlm@10 1278 }
rlm@10 1279 typeTable[typeCount] = result;
rlm@10 1280 return result;
rlm@10 1281 }
rlm@10 1282
rlm@10 1283 /**
rlm@10 1284 * Returns the index of the common super type of the two given types. This
rlm@10 1285 * method calls {@link #getCommonSuperClass} and caches the result in the
rlm@10 1286 * {@link #items} hash table to speedup future calls with the same
rlm@10 1287 * parameters.
rlm@10 1288 *
rlm@10 1289 * @param type1 index of an internal name in {@link #typeTable}.
rlm@10 1290 * @param type2 index of an internal name in {@link #typeTable}.
rlm@10 1291 * @return the index of the common super type of the two given types.
rlm@10 1292 */
rlm@10 1293 int getMergedType(final int type1, final int type2){
rlm@10 1294 key2.type = TYPE_MERGED;
rlm@10 1295 key2.longVal = type1 | (((long) type2) << 32);
rlm@10 1296 key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
rlm@10 1297 Item result = get(key2);
rlm@10 1298 if(result == null)
rlm@10 1299 {
rlm@10 1300 String t = typeTable[type1].strVal1;
rlm@10 1301 String u = typeTable[type2].strVal1;
rlm@10 1302 key2.intVal = addType(getCommonSuperClass(t, u));
rlm@10 1303 result = new Item((short) 0, key2);
rlm@10 1304 put(result);
rlm@10 1305 }
rlm@10 1306 return result.intVal;
rlm@10 1307 }
rlm@10 1308
rlm@10 1309 /**
rlm@10 1310 * Returns the common super type of the two given types. The default
rlm@10 1311 * implementation of this method <i>loads<i> the two given classes and uses
rlm@10 1312 * the java.lang.Class methods to find the common super class. It can be
rlm@10 1313 * overriden to compute this common super type in other ways, in particular
rlm@10 1314 * without actually loading any class, or to take into account the class
rlm@10 1315 * that is currently being generated by this ClassWriter, which can of
rlm@10 1316 * course not be loaded since it is under construction.
rlm@10 1317 *
rlm@10 1318 * @param type1 the internal name of a class.
rlm@10 1319 * @param type2 the internal name of another class.
rlm@10 1320 * @return the internal name of the common super class of the two given
rlm@10 1321 * classes.
rlm@10 1322 */
rlm@10 1323 protected String getCommonSuperClass(final String type1, final String type2){
rlm@10 1324 Class c, d;
rlm@10 1325 try
rlm@10 1326 {
rlm@10 1327 c = Class.forName(type1.replace('/', '.'));
rlm@10 1328 d = Class.forName(type2.replace('/', '.'));
rlm@10 1329 }
rlm@10 1330 catch(ClassNotFoundException e)
rlm@10 1331 {
rlm@10 1332 throw new RuntimeException(e);
rlm@10 1333 }
rlm@10 1334 if(c.isAssignableFrom(d))
rlm@10 1335 {
rlm@10 1336 return type1;
rlm@10 1337 }
rlm@10 1338 if(d.isAssignableFrom(c))
rlm@10 1339 {
rlm@10 1340 return type2;
rlm@10 1341 }
rlm@10 1342 if(c.isInterface() || d.isInterface())
rlm@10 1343 {
rlm@10 1344 return "java/lang/Object";
rlm@10 1345 }
rlm@10 1346 else
rlm@10 1347 {
rlm@10 1348 do
rlm@10 1349 {
rlm@10 1350 c = c.getSuperclass();
rlm@10 1351 } while(!c.isAssignableFrom(d));
rlm@10 1352 return c.getName().replace('.', '/');
rlm@10 1353 }
rlm@10 1354 }
rlm@10 1355
rlm@10 1356 /**
rlm@10 1357 * Returns the constant pool's hash table item which is equal to the given
rlm@10 1358 * item.
rlm@10 1359 *
rlm@10 1360 * @param key a constant pool item.
rlm@10 1361 * @return the constant pool's hash table item which is equal to the given
rlm@10 1362 * item, or <tt>null</tt> if there is no such item.
rlm@10 1363 */
rlm@10 1364 private Item get(final Item key){
rlm@10 1365 Item i = items[key.hashCode % items.length];
rlm@10 1366 while(i != null && !key.isEqualTo(i))
rlm@10 1367 {
rlm@10 1368 i = i.next;
rlm@10 1369 }
rlm@10 1370 return i;
rlm@10 1371 }
rlm@10 1372
rlm@10 1373 /**
rlm@10 1374 * Puts the given item in the constant pool's hash table. The hash table
rlm@10 1375 * <i>must</i> not already contains this item.
rlm@10 1376 *
rlm@10 1377 * @param i the item to be added to the constant pool's hash table.
rlm@10 1378 */
rlm@10 1379 private void put(final Item i){
rlm@10 1380 if(index > threshold)
rlm@10 1381 {
rlm@10 1382 int ll = items.length;
rlm@10 1383 int nl = ll * 2 + 1;
rlm@10 1384 Item[] newItems = new Item[nl];
rlm@10 1385 for(int l = ll - 1; l >= 0; --l)
rlm@10 1386 {
rlm@10 1387 Item j = items[l];
rlm@10 1388 while(j != null)
rlm@10 1389 {
rlm@10 1390 int index = j.hashCode % newItems.length;
rlm@10 1391 Item k = j.next;
rlm@10 1392 j.next = newItems[index];
rlm@10 1393 newItems[index] = j;
rlm@10 1394 j = k;
rlm@10 1395 }
rlm@10 1396 }
rlm@10 1397 items = newItems;
rlm@10 1398 threshold = (int) (nl * 0.75);
rlm@10 1399 }
rlm@10 1400 int index = i.hashCode % items.length;
rlm@10 1401 i.next = items[index];
rlm@10 1402 items[index] = i;
rlm@10 1403 }
rlm@10 1404
rlm@10 1405 /**
rlm@10 1406 * Puts one byte and two shorts into the constant pool.
rlm@10 1407 *
rlm@10 1408 * @param b a byte.
rlm@10 1409 * @param s1 a short.
rlm@10 1410 * @param s2 another short.
rlm@10 1411 */
rlm@10 1412 private void put122(final int b, final int s1, final int s2){
rlm@10 1413 pool.put12(b, s1).putShort(s2);
rlm@10 1414 }
rlm@10 1415 }