diff 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
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/asm/ClassWriter.java	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,1415 @@
     1.4 +/***
     1.5 + * ASM: a very small and fast Java bytecode manipulation framework
     1.6 + * Copyright (c) 2000-2005 INRIA, France Telecom
     1.7 + * All rights reserved.
     1.8 + *
     1.9 + * Redistribution and use in source and binary forms, with or without
    1.10 + * modification, are permitted provided that the following conditions
    1.11 + * are met:
    1.12 + * 1. Redistributions of source code must retain the above copyright
    1.13 + *    notice, this list of conditions and the following disclaimer.
    1.14 + * 2. Redistributions in binary form must reproduce the above copyright
    1.15 + *    notice, this list of conditions and the following disclaimer in the
    1.16 + *    documentation and/or other materials provided with the distribution.
    1.17 + * 3. Neither the name of the copyright holders nor the names of its
    1.18 + *    contributors may be used to endorse or promote products derived from
    1.19 + *    this software without specific prior written permission.
    1.20 + *
    1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1.22 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    1.25 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.26 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.27 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    1.28 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    1.29 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.30 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    1.31 + * THE POSSIBILITY OF SUCH DAMAGE.
    1.32 + */
    1.33 +package clojure.asm;
    1.34 +
    1.35 +/**
    1.36 + * A {@link ClassVisitor} that generates classes in bytecode form. More
    1.37 + * precisely this visitor generates a byte array conforming to the Java class
    1.38 + * file format. It can be used alone, to generate a Java class "from scratch",
    1.39 + * or with one or more {@link ClassReader ClassReader} and adapter class visitor
    1.40 + * to generate a modified class from one or more existing Java classes.
    1.41 + *
    1.42 + * @author Eric Bruneton
    1.43 + */
    1.44 +public class ClassWriter implements ClassVisitor{
    1.45 +
    1.46 +/**
    1.47 + * Flag to automatically compute the maximum stack size and the maximum
    1.48 + * number of local variables of methods. If this flag is set, then the
    1.49 + * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
    1.50 + * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
    1.51 + * method will be ignored, and computed automatically from the signature and
    1.52 + * the bytecode of each method.
    1.53 + *
    1.54 + * @see #ClassWriter(int)
    1.55 + */
    1.56 +public final static int COMPUTE_MAXS = 1;
    1.57 +
    1.58 +/**
    1.59 + * Flag to automatically compute the stack map frames of methods from
    1.60 + * scratch. If this flag is set, then the calls to the
    1.61 + * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
    1.62 + * frames are recomputed from the methods bytecode. The arguments of the
    1.63 + * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
    1.64 + * recomputed from the bytecode. In other words, computeFrames implies
    1.65 + * computeMaxs.
    1.66 + *
    1.67 + * @see #ClassWriter(int)
    1.68 + */
    1.69 +public final static int COMPUTE_FRAMES = 2;
    1.70 +
    1.71 +/**
    1.72 + * The type of instructions without any argument.
    1.73 + */
    1.74 +final static int NOARG_INSN = 0;
    1.75 +
    1.76 +/**
    1.77 + * The type of instructions with an signed byte argument.
    1.78 + */
    1.79 +final static int SBYTE_INSN = 1;
    1.80 +
    1.81 +/**
    1.82 + * The type of instructions with an signed short argument.
    1.83 + */
    1.84 +final static int SHORT_INSN = 2;
    1.85 +
    1.86 +/**
    1.87 + * The type of instructions with a local variable index argument.
    1.88 + */
    1.89 +final static int VAR_INSN = 3;
    1.90 +
    1.91 +/**
    1.92 + * The type of instructions with an implicit local variable index argument.
    1.93 + */
    1.94 +final static int IMPLVAR_INSN = 4;
    1.95 +
    1.96 +/**
    1.97 + * The type of instructions with a type descriptor argument.
    1.98 + */
    1.99 +final static int TYPE_INSN = 5;
   1.100 +
   1.101 +/**
   1.102 + * The type of field and method invocations instructions.
   1.103 + */
   1.104 +final static int FIELDORMETH_INSN = 6;
   1.105 +
   1.106 +/**
   1.107 + * The type of the INVOKEINTERFACE instruction.
   1.108 + */
   1.109 +final static int ITFMETH_INSN = 7;
   1.110 +
   1.111 +/**
   1.112 + * The type of instructions with a 2 bytes bytecode offset label.
   1.113 + */
   1.114 +final static int LABEL_INSN = 8;
   1.115 +
   1.116 +/**
   1.117 + * The type of instructions with a 4 bytes bytecode offset label.
   1.118 + */
   1.119 +final static int LABELW_INSN = 9;
   1.120 +
   1.121 +/**
   1.122 + * The type of the LDC instruction.
   1.123 + */
   1.124 +final static int LDC_INSN = 10;
   1.125 +
   1.126 +/**
   1.127 + * The type of the LDC_W and LDC2_W instructions.
   1.128 + */
   1.129 +final static int LDCW_INSN = 11;
   1.130 +
   1.131 +/**
   1.132 + * The type of the IINC instruction.
   1.133 + */
   1.134 +final static int IINC_INSN = 12;
   1.135 +
   1.136 +/**
   1.137 + * The type of the TABLESWITCH instruction.
   1.138 + */
   1.139 +final static int TABL_INSN = 13;
   1.140 +
   1.141 +/**
   1.142 + * The type of the LOOKUPSWITCH instruction.
   1.143 + */
   1.144 +final static int LOOK_INSN = 14;
   1.145 +
   1.146 +/**
   1.147 + * The type of the MULTIANEWARRAY instruction.
   1.148 + */
   1.149 +final static int MANA_INSN = 15;
   1.150 +
   1.151 +/**
   1.152 + * The type of the WIDE instruction.
   1.153 + */
   1.154 +final static int WIDE_INSN = 16;
   1.155 +
   1.156 +/**
   1.157 + * The instruction types of all JVM opcodes.
   1.158 + */
   1.159 +static byte[] TYPE;
   1.160 +
   1.161 +/**
   1.162 + * The type of CONSTANT_Class constant pool items.
   1.163 + */
   1.164 +final static int CLASS = 7;
   1.165 +
   1.166 +/**
   1.167 + * The type of CONSTANT_Fieldref constant pool items.
   1.168 + */
   1.169 +final static int FIELD = 9;
   1.170 +
   1.171 +/**
   1.172 + * The type of CONSTANT_Methodref constant pool items.
   1.173 + */
   1.174 +final static int METH = 10;
   1.175 +
   1.176 +/**
   1.177 + * The type of CONSTANT_InterfaceMethodref constant pool items.
   1.178 + */
   1.179 +final static int IMETH = 11;
   1.180 +
   1.181 +/**
   1.182 + * The type of CONSTANT_String constant pool items.
   1.183 + */
   1.184 +final static int STR = 8;
   1.185 +
   1.186 +/**
   1.187 + * The type of CONSTANT_Integer constant pool items.
   1.188 + */
   1.189 +final static int INT = 3;
   1.190 +
   1.191 +/**
   1.192 + * The type of CONSTANT_Float constant pool items.
   1.193 + */
   1.194 +final static int FLOAT = 4;
   1.195 +
   1.196 +/**
   1.197 + * The type of CONSTANT_Long constant pool items.
   1.198 + */
   1.199 +final static int LONG = 5;
   1.200 +
   1.201 +/**
   1.202 + * The type of CONSTANT_Double constant pool items.
   1.203 + */
   1.204 +final static int DOUBLE = 6;
   1.205 +
   1.206 +/**
   1.207 + * The type of CONSTANT_NameAndType constant pool items.
   1.208 + */
   1.209 +final static int NAME_TYPE = 12;
   1.210 +
   1.211 +/**
   1.212 + * The type of CONSTANT_Utf8 constant pool items.
   1.213 + */
   1.214 +final static int UTF8 = 1;
   1.215 +
   1.216 +/**
   1.217 + * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
   1.218 + * instead of the constant pool, in order to avoid clashes with normal
   1.219 + * constant pool items in the ClassWriter constant pool's hash table.
   1.220 + */
   1.221 +final static int TYPE_NORMAL = 13;
   1.222 +
   1.223 +/**
   1.224 + * Uninitialized type Item stored in the ClassWriter
   1.225 + * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
   1.226 + * avoid clashes with normal constant pool items in the ClassWriter constant
   1.227 + * pool's hash table.
   1.228 + */
   1.229 +final static int TYPE_UNINIT = 14;
   1.230 +
   1.231 +/**
   1.232 + * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
   1.233 + * instead of the constant pool, in order to avoid clashes with normal
   1.234 + * constant pool items in the ClassWriter constant pool's hash table.
   1.235 + */
   1.236 +final static int TYPE_MERGED = 15;
   1.237 +
   1.238 +/**
   1.239 + * The class reader from which this class writer was constructed, if any.
   1.240 + */
   1.241 +ClassReader cr;
   1.242 +
   1.243 +/**
   1.244 + * Minor and major version numbers of the class to be generated.
   1.245 + */
   1.246 +int version;
   1.247 +
   1.248 +/**
   1.249 + * Index of the next item to be added in the constant pool.
   1.250 + */
   1.251 +int index;
   1.252 +
   1.253 +/**
   1.254 + * The constant pool of this class.
   1.255 + */
   1.256 +ByteVector pool;
   1.257 +
   1.258 +/**
   1.259 + * The constant pool's hash table data.
   1.260 + */
   1.261 +Item[] items;
   1.262 +
   1.263 +/**
   1.264 + * The threshold of the constant pool's hash table.
   1.265 + */
   1.266 +int threshold;
   1.267 +
   1.268 +/**
   1.269 + * A reusable key used to look for items in the {@link #items} hash table.
   1.270 + */
   1.271 +Item key;
   1.272 +
   1.273 +/**
   1.274 + * A reusable key used to look for items in the {@link #items} hash table.
   1.275 + */
   1.276 +Item key2;
   1.277 +
   1.278 +/**
   1.279 + * A reusable key used to look for items in the {@link #items} hash table.
   1.280 + */
   1.281 +Item key3;
   1.282 +
   1.283 +/**
   1.284 + * A type table used to temporarily store internal names that will not
   1.285 + * necessarily be stored in the constant pool. This type table is used by
   1.286 + * the control flow and data flow analysis algorithm used to compute stack
   1.287 + * map frames from scratch. This array associates to each index <tt>i</tt>
   1.288 + * the Item whose index is <tt>i</tt>. All Item objects stored in this
   1.289 + * array are also stored in the {@link #items} hash table. These two arrays
   1.290 + * allow to retrieve an Item from its index or, conversly, to get the index
   1.291 + * of an Item from its value. Each Item stores an internal name in its
   1.292 + * {@link Item#strVal1} field.
   1.293 + */
   1.294 +Item[] typeTable;
   1.295 +
   1.296 +/**
   1.297 + * Number of elements in the {@link #typeTable} array.
   1.298 + */
   1.299 +private short typeCount; // TODO int?
   1.300 +
   1.301 +/**
   1.302 + * The access flags of this class.
   1.303 + */
   1.304 +private int access;
   1.305 +
   1.306 +/**
   1.307 + * The constant pool item that contains the internal name of this class.
   1.308 + */
   1.309 +private int name;
   1.310 +
   1.311 +/**
   1.312 + * The internal name of this class.
   1.313 + */
   1.314 +String thisName;
   1.315 +
   1.316 +/**
   1.317 + * The constant pool item that contains the signature of this class.
   1.318 + */
   1.319 +private int signature;
   1.320 +
   1.321 +/**
   1.322 + * The constant pool item that contains the internal name of the super class
   1.323 + * of this class.
   1.324 + */
   1.325 +private int superName;
   1.326 +
   1.327 +/**
   1.328 + * Number of interfaces implemented or extended by this class or interface.
   1.329 + */
   1.330 +private int interfaceCount;
   1.331 +
   1.332 +/**
   1.333 + * The interfaces implemented or extended by this class or interface. More
   1.334 + * precisely, this array contains the indexes of the constant pool items
   1.335 + * that contain the internal names of these interfaces.
   1.336 + */
   1.337 +private int[] interfaces;
   1.338 +
   1.339 +/**
   1.340 + * The index of the constant pool item that contains the name of the source
   1.341 + * file from which this class was compiled.
   1.342 + */
   1.343 +private int sourceFile;
   1.344 +
   1.345 +/**
   1.346 + * The SourceDebug attribute of this class.
   1.347 + */
   1.348 +private ByteVector sourceDebug;
   1.349 +
   1.350 +/**
   1.351 + * The constant pool item that contains the name of the enclosing class of
   1.352 + * this class.
   1.353 + */
   1.354 +private int enclosingMethodOwner;
   1.355 +
   1.356 +/**
   1.357 + * The constant pool item that contains the name and descriptor of the
   1.358 + * enclosing method of this class.
   1.359 + */
   1.360 +private int enclosingMethod;
   1.361 +
   1.362 +/**
   1.363 + * The runtime visible annotations of this class.
   1.364 + */
   1.365 +private AnnotationWriter anns;
   1.366 +
   1.367 +/**
   1.368 + * The runtime invisible annotations of this class.
   1.369 + */
   1.370 +private AnnotationWriter ianns;
   1.371 +
   1.372 +/**
   1.373 + * The non standard attributes of this class.
   1.374 + */
   1.375 +private Attribute attrs;
   1.376 +
   1.377 +/**
   1.378 + * The number of entries in the InnerClasses attribute.
   1.379 + */
   1.380 +private int innerClassesCount;
   1.381 +
   1.382 +/**
   1.383 + * The InnerClasses attribute.
   1.384 + */
   1.385 +private ByteVector innerClasses;
   1.386 +
   1.387 +/**
   1.388 + * The fields of this class. These fields are stored in a linked list of
   1.389 + * {@link FieldWriter} objects, linked to each other by their
   1.390 + * {@link FieldWriter#next} field. This field stores the first element of
   1.391 + * this list.
   1.392 + */
   1.393 +FieldWriter firstField;
   1.394 +
   1.395 +/**
   1.396 + * The fields of this class. These fields are stored in a linked list of
   1.397 + * {@link FieldWriter} objects, linked to each other by their
   1.398 + * {@link FieldWriter#next} field. This field stores the last element of
   1.399 + * this list.
   1.400 + */
   1.401 +FieldWriter lastField;
   1.402 +
   1.403 +/**
   1.404 + * The methods of this class. These methods are stored in a linked list of
   1.405 + * {@link MethodWriter} objects, linked to each other by their
   1.406 + * {@link MethodWriter#next} field. This field stores the first element of
   1.407 + * this list.
   1.408 + */
   1.409 +MethodWriter firstMethod;
   1.410 +
   1.411 +/**
   1.412 + * The methods of this class. These methods are stored in a linked list of
   1.413 + * {@link MethodWriter} objects, linked to each other by their
   1.414 + * {@link MethodWriter#next} field. This field stores the last element of
   1.415 + * this list.
   1.416 + */
   1.417 +MethodWriter lastMethod;
   1.418 +
   1.419 +/**
   1.420 + * <tt>true</tt> if the maximum stack size and number of local variables
   1.421 + * must be automatically computed.
   1.422 + */
   1.423 +private boolean computeMaxs;
   1.424 +
   1.425 +/**
   1.426 + * <tt>true</tt> if the stack map frames must be recomputed from scratch.
   1.427 + */
   1.428 +private boolean computeFrames;
   1.429 +
   1.430 +/**
   1.431 + * <tt>true</tt> if the stack map tables of this class are invalid. The
   1.432 + * {@link MethodWriter#resizeInstructions} method cannot transform existing
   1.433 + * stack map tables, and so produces potentially invalid classes when it is
   1.434 + * executed. In this case the class is reread and rewritten with the
   1.435 + * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
   1.436 + * stack map tables when this option is used).
   1.437 + */
   1.438 +boolean invalidFrames;
   1.439 +
   1.440 +// ------------------------------------------------------------------------
   1.441 +// Static initializer
   1.442 +// ------------------------------------------------------------------------
   1.443 +
   1.444 +/**
   1.445 + * Computes the instruction types of JVM opcodes.
   1.446 + */
   1.447 +static
   1.448 +	{
   1.449 +	int i;
   1.450 +	byte[] b = new byte[220];
   1.451 +	String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
   1.452 +	           + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
   1.453 +	           + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
   1.454 +	           + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
   1.455 +	for(i = 0; i < b.length; ++i)
   1.456 +		{
   1.457 +		b[i] = (byte) (s.charAt(i) - 'A');
   1.458 +		}
   1.459 +	TYPE = b;
   1.460 +
   1.461 +	// code to generate the above string
   1.462 +	//
   1.463 +	// // SBYTE_INSN instructions
   1.464 +	// b[Constants.NEWARRAY] = SBYTE_INSN;
   1.465 +	// b[Constants.BIPUSH] = SBYTE_INSN;
   1.466 +	//
   1.467 +	// // SHORT_INSN instructions
   1.468 +	// b[Constants.SIPUSH] = SHORT_INSN;
   1.469 +	//
   1.470 +	// // (IMPL)VAR_INSN instructions
   1.471 +	// b[Constants.RET] = VAR_INSN;
   1.472 +	// for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
   1.473 +	// b[i] = VAR_INSN;
   1.474 +	// }
   1.475 +	// for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
   1.476 +	// b[i] = VAR_INSN;
   1.477 +	// }
   1.478 +	// for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
   1.479 +	// b[i] = IMPLVAR_INSN;
   1.480 +	// }
   1.481 +	// for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
   1.482 +	// b[i] = IMPLVAR_INSN;
   1.483 +	// }
   1.484 +	//
   1.485 +	// // TYPE_INSN instructions
   1.486 +	// b[Constants.NEW] = TYPE_INSN;
   1.487 +	// b[Constants.ANEWARRAY] = TYPE_INSN;
   1.488 +	// b[Constants.CHECKCAST] = TYPE_INSN;
   1.489 +	// b[Constants.INSTANCEOF] = TYPE_INSN;
   1.490 +	//
   1.491 +	// // (Set)FIELDORMETH_INSN instructions
   1.492 +	// for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
   1.493 +	// b[i] = FIELDORMETH_INSN;
   1.494 +	// }
   1.495 +	// b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
   1.496 +	//
   1.497 +	// // LABEL(W)_INSN instructions
   1.498 +	// for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
   1.499 +	// b[i] = LABEL_INSN;
   1.500 +	// }
   1.501 +	// b[Constants.IFNULL] = LABEL_INSN;
   1.502 +	// b[Constants.IFNONNULL] = LABEL_INSN;
   1.503 +	// b[200] = LABELW_INSN; // GOTO_W
   1.504 +	// b[201] = LABELW_INSN; // JSR_W
   1.505 +	// // temporary opcodes used internally by ASM - see Label and
   1.506 +	// MethodWriter
   1.507 +	// for (i = 202; i < 220; ++i) {
   1.508 +	// b[i] = LABEL_INSN;
   1.509 +	// }
   1.510 +	//
   1.511 +	// // LDC(_W) instructions
   1.512 +	// b[Constants.LDC] = LDC_INSN;
   1.513 +	// b[19] = LDCW_INSN; // LDC_W
   1.514 +	// b[20] = LDCW_INSN; // LDC2_W
   1.515 +	//
   1.516 +	// // special instructions
   1.517 +	// b[Constants.IINC] = IINC_INSN;
   1.518 +	// b[Constants.TABLESWITCH] = TABL_INSN;
   1.519 +	// b[Constants.LOOKUPSWITCH] = LOOK_INSN;
   1.520 +	// b[Constants.MULTIANEWARRAY] = MANA_INSN;
   1.521 +	// b[196] = WIDE_INSN; // WIDE
   1.522 +	//
   1.523 +	// for (i = 0; i < b.length; ++i) {
   1.524 +	// System.err.print((char)('A' + b[i]));
   1.525 +	// }
   1.526 +	// System.err.println();
   1.527 +	}
   1.528 +
   1.529 +// ------------------------------------------------------------------------
   1.530 +// Constructor
   1.531 +// ------------------------------------------------------------------------
   1.532 +
   1.533 +/**
   1.534 + * Constructs a new {@link ClassWriter} object.
   1.535 + *
   1.536 + * @param flags option flags that can be used to modify the default behavior
   1.537 + *              of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
   1.538 + */
   1.539 +public ClassWriter(final int flags){
   1.540 +	index = 1;
   1.541 +	pool = new ByteVector();
   1.542 +	items = new Item[256];
   1.543 +	threshold = (int) (0.75d * items.length);
   1.544 +	key = new Item();
   1.545 +	key2 = new Item();
   1.546 +	key3 = new Item();
   1.547 +	this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
   1.548 +	this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
   1.549 +}
   1.550 +
   1.551 +/**
   1.552 + * Constructs a new {@link ClassWriter} object and enables optimizations for
   1.553 + * "mostly add" bytecode transformations. These optimizations are the
   1.554 + * following:
   1.555 + * <p/>
   1.556 + * <ul> <li>The constant pool from the original class is copied as is in
   1.557 + * the new class, which saves time. New constant pool entries will be added
   1.558 + * at the end if necessary, but unused constant pool entries <i>won't be
   1.559 + * removed</i>.</li> <li>Methods that are not transformed are copied as
   1.560 + * is in the new class, directly from the original class bytecode (i.e.
   1.561 + * without emitting visit events for all the method instructions), which
   1.562 + * saves a <i>lot</i> of time. Untransformed methods are detected by the
   1.563 + * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
   1.564 + * that come from a {@link ClassWriter} (and not from a custom
   1.565 + * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
   1.566 + * </ul>
   1.567 + *
   1.568 + * @param classReader the {@link ClassReader} used to read the original
   1.569 + *                    class. It will be used to copy the entire constant pool from the
   1.570 + *                    original class and also to copy other fragments of original
   1.571 + *                    bytecode where applicable.
   1.572 + * @param flags       option flags that can be used to modify the default behavior
   1.573 + *                    of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
   1.574 + */
   1.575 +public ClassWriter(final ClassReader classReader, final int flags){
   1.576 +	this(flags);
   1.577 +	classReader.copyPool(this);
   1.578 +	this.cr = classReader;
   1.579 +}
   1.580 +
   1.581 +// ------------------------------------------------------------------------
   1.582 +// Implementation of the ClassVisitor interface
   1.583 +// ------------------------------------------------------------------------
   1.584 +
   1.585 +public void visit(
   1.586 +		final int version,
   1.587 +		final int access,
   1.588 +		final String name,
   1.589 +		final String signature,
   1.590 +		final String superName,
   1.591 +		final String[] interfaces){
   1.592 +	this.version = version;
   1.593 +	this.access = access;
   1.594 +	this.name = newClass(name);
   1.595 +	thisName = name;
   1.596 +	if(signature != null)
   1.597 +		{
   1.598 +		this.signature = newUTF8(signature);
   1.599 +		}
   1.600 +	this.superName = superName == null ? 0 : newClass(superName);
   1.601 +	if(interfaces != null && interfaces.length > 0)
   1.602 +		{
   1.603 +		interfaceCount = interfaces.length;
   1.604 +		this.interfaces = new int[interfaceCount];
   1.605 +		for(int i = 0; i < interfaceCount; ++i)
   1.606 +			{
   1.607 +			this.interfaces[i] = newClass(interfaces[i]);
   1.608 +			}
   1.609 +		}
   1.610 +}
   1.611 +
   1.612 +public void visitSource(final String file, final String debug){
   1.613 +	if(file != null)
   1.614 +		{
   1.615 +		sourceFile = newUTF8(file);
   1.616 +		}
   1.617 +	if(debug != null)
   1.618 +		{
   1.619 +		sourceDebug = new ByteVector().putUTF8(debug);
   1.620 +		}
   1.621 +}
   1.622 +
   1.623 +public void visitOuterClass(
   1.624 +		final String owner,
   1.625 +		final String name,
   1.626 +		final String desc){
   1.627 +	enclosingMethodOwner = newClass(owner);
   1.628 +	if(name != null && desc != null)
   1.629 +		{
   1.630 +		enclosingMethod = newNameType(name, desc);
   1.631 +		}
   1.632 +}
   1.633 +
   1.634 +public AnnotationVisitor visitAnnotation(
   1.635 +		final String desc,
   1.636 +		final boolean visible){
   1.637 +	ByteVector bv = new ByteVector();
   1.638 +	// write type, and reserve space for values count
   1.639 +	bv.putShort(newUTF8(desc)).putShort(0);
   1.640 +	AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
   1.641 +	if(visible)
   1.642 +		{
   1.643 +		aw.next = anns;
   1.644 +		anns = aw;
   1.645 +		}
   1.646 +	else
   1.647 +		{
   1.648 +		aw.next = ianns;
   1.649 +		ianns = aw;
   1.650 +		}
   1.651 +	return aw;
   1.652 +}
   1.653 +
   1.654 +public void visitAttribute(final Attribute attr){
   1.655 +	attr.next = attrs;
   1.656 +	attrs = attr;
   1.657 +}
   1.658 +
   1.659 +public void visitInnerClass(
   1.660 +		final String name,
   1.661 +		final String outerName,
   1.662 +		final String innerName,
   1.663 +		final int access){
   1.664 +	if(innerClasses == null)
   1.665 +		{
   1.666 +		innerClasses = new ByteVector();
   1.667 +		}
   1.668 +	++innerClassesCount;
   1.669 +	innerClasses.putShort(name == null ? 0 : newClass(name));
   1.670 +	innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
   1.671 +	innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
   1.672 +	innerClasses.putShort(access);
   1.673 +}
   1.674 +
   1.675 +public FieldVisitor visitField(
   1.676 +		final int access,
   1.677 +		final String name,
   1.678 +		final String desc,
   1.679 +		final String signature,
   1.680 +		final Object value){
   1.681 +	return new FieldWriter(this, access, name, desc, signature, value);
   1.682 +}
   1.683 +
   1.684 +public MethodVisitor visitMethod(
   1.685 +		final int access,
   1.686 +		final String name,
   1.687 +		final String desc,
   1.688 +		final String signature,
   1.689 +		final String[] exceptions){
   1.690 +	return new MethodWriter(this,
   1.691 +	                        access,
   1.692 +	                        name,
   1.693 +	                        desc,
   1.694 +	                        signature,
   1.695 +	                        exceptions,
   1.696 +	                        computeMaxs,
   1.697 +	                        computeFrames);
   1.698 +}
   1.699 +
   1.700 +public void visitEnd(){
   1.701 +}
   1.702 +
   1.703 +// ------------------------------------------------------------------------
   1.704 +// Other public methods
   1.705 +// ------------------------------------------------------------------------
   1.706 +
   1.707 +/**
   1.708 + * Returns the bytecode of the class that was build with this class writer.
   1.709 + *
   1.710 + * @return the bytecode of the class that was build with this class writer.
   1.711 + */
   1.712 +public byte[] toByteArray(){
   1.713 +	// computes the real size of the bytecode of this class
   1.714 +	int size = 24 + 2 * interfaceCount;
   1.715 +	int nbFields = 0;
   1.716 +	FieldWriter fb = firstField;
   1.717 +	while(fb != null)
   1.718 +		{
   1.719 +		++nbFields;
   1.720 +		size += fb.getSize();
   1.721 +		fb = fb.next;
   1.722 +		}
   1.723 +	int nbMethods = 0;
   1.724 +	MethodWriter mb = firstMethod;
   1.725 +	while(mb != null)
   1.726 +		{
   1.727 +		++nbMethods;
   1.728 +		size += mb.getSize();
   1.729 +		mb = mb.next;
   1.730 +		}
   1.731 +	int attributeCount = 0;
   1.732 +	if(signature != 0)
   1.733 +		{
   1.734 +		++attributeCount;
   1.735 +		size += 8;
   1.736 +		newUTF8("Signature");
   1.737 +		}
   1.738 +	if(sourceFile != 0)
   1.739 +		{
   1.740 +		++attributeCount;
   1.741 +		size += 8;
   1.742 +		newUTF8("SourceFile");
   1.743 +		}
   1.744 +	if(sourceDebug != null)
   1.745 +		{
   1.746 +		++attributeCount;
   1.747 +		size += sourceDebug.length + 4;
   1.748 +		newUTF8("SourceDebugExtension");
   1.749 +		}
   1.750 +	if(enclosingMethodOwner != 0)
   1.751 +		{
   1.752 +		++attributeCount;
   1.753 +		size += 10;
   1.754 +		newUTF8("EnclosingMethod");
   1.755 +		}
   1.756 +	if((access & Opcodes.ACC_DEPRECATED) != 0)
   1.757 +		{
   1.758 +		++attributeCount;
   1.759 +		size += 6;
   1.760 +		newUTF8("Deprecated");
   1.761 +		}
   1.762 +	if((access & Opcodes.ACC_SYNTHETIC) != 0
   1.763 +	   && (version & 0xffff) < Opcodes.V1_5)
   1.764 +		{
   1.765 +		++attributeCount;
   1.766 +		size += 6;
   1.767 +		newUTF8("Synthetic");
   1.768 +		}
   1.769 +	if(innerClasses != null)
   1.770 +		{
   1.771 +		++attributeCount;
   1.772 +		size += 8 + innerClasses.length;
   1.773 +		newUTF8("InnerClasses");
   1.774 +		}
   1.775 +	if(anns != null)
   1.776 +		{
   1.777 +		++attributeCount;
   1.778 +		size += 8 + anns.getSize();
   1.779 +		newUTF8("RuntimeVisibleAnnotations");
   1.780 +		}
   1.781 +	if(ianns != null)
   1.782 +		{
   1.783 +		++attributeCount;
   1.784 +		size += 8 + ianns.getSize();
   1.785 +		newUTF8("RuntimeInvisibleAnnotations");
   1.786 +		}
   1.787 +	if(attrs != null)
   1.788 +		{
   1.789 +		attributeCount += attrs.getCount();
   1.790 +		size += attrs.getSize(this, null, 0, -1, -1);
   1.791 +		}
   1.792 +	size += pool.length;
   1.793 +	// allocates a byte vector of this size, in order to avoid unnecessary
   1.794 +	// arraycopy operations in the ByteVector.enlarge() method
   1.795 +	ByteVector out = new ByteVector(size);
   1.796 +	out.putInt(0xCAFEBABE).putInt(version);
   1.797 +	out.putShort(index).putByteArray(pool.data, 0, pool.length);
   1.798 +	out.putShort(access).putShort(name).putShort(superName);
   1.799 +	out.putShort(interfaceCount);
   1.800 +	for(int i = 0; i < interfaceCount; ++i)
   1.801 +		{
   1.802 +		out.putShort(interfaces[i]);
   1.803 +		}
   1.804 +	out.putShort(nbFields);
   1.805 +	fb = firstField;
   1.806 +	while(fb != null)
   1.807 +		{
   1.808 +		fb.put(out);
   1.809 +		fb = fb.next;
   1.810 +		}
   1.811 +	out.putShort(nbMethods);
   1.812 +	mb = firstMethod;
   1.813 +	while(mb != null)
   1.814 +		{
   1.815 +		mb.put(out);
   1.816 +		mb = mb.next;
   1.817 +		}
   1.818 +	out.putShort(attributeCount);
   1.819 +	if(signature != 0)
   1.820 +		{
   1.821 +		out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
   1.822 +		}
   1.823 +	if(sourceFile != 0)
   1.824 +		{
   1.825 +		out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
   1.826 +		}
   1.827 +	if(sourceDebug != null)
   1.828 +		{
   1.829 +		int len = sourceDebug.length - 2;
   1.830 +		out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
   1.831 +		out.putByteArray(sourceDebug.data, 2, len);
   1.832 +		}
   1.833 +	if(enclosingMethodOwner != 0)
   1.834 +		{
   1.835 +		out.putShort(newUTF8("EnclosingMethod")).putInt(4);
   1.836 +		out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
   1.837 +		}
   1.838 +	if((access & Opcodes.ACC_DEPRECATED) != 0)
   1.839 +		{
   1.840 +		out.putShort(newUTF8("Deprecated")).putInt(0);
   1.841 +		}
   1.842 +	if((access & Opcodes.ACC_SYNTHETIC) != 0
   1.843 +	   && (version & 0xffff) < Opcodes.V1_5)
   1.844 +		{
   1.845 +		out.putShort(newUTF8("Synthetic")).putInt(0);
   1.846 +		}
   1.847 +	if(innerClasses != null)
   1.848 +		{
   1.849 +		out.putShort(newUTF8("InnerClasses"));
   1.850 +		out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
   1.851 +		out.putByteArray(innerClasses.data, 0, innerClasses.length);
   1.852 +		}
   1.853 +	if(anns != null)
   1.854 +		{
   1.855 +		out.putShort(newUTF8("RuntimeVisibleAnnotations"));
   1.856 +		anns.put(out);
   1.857 +		}
   1.858 +	if(ianns != null)
   1.859 +		{
   1.860 +		out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
   1.861 +		ianns.put(out);
   1.862 +		}
   1.863 +	if(attrs != null)
   1.864 +		{
   1.865 +		attrs.put(this, null, 0, -1, -1, out);
   1.866 +		}
   1.867 +	if(invalidFrames)
   1.868 +		{
   1.869 +		ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
   1.870 +		new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
   1.871 +		return cw.toByteArray();
   1.872 +		}
   1.873 +	return out.data;
   1.874 +}
   1.875 +
   1.876 +// ------------------------------------------------------------------------
   1.877 +// Utility methods: constant pool management
   1.878 +// ------------------------------------------------------------------------
   1.879 +
   1.880 +/**
   1.881 + * Adds a number or string constant to the constant pool of the class being
   1.882 + * build. Does nothing if the constant pool already contains a similar item.
   1.883 + *
   1.884 + * @param cst the value of the constant to be added to the constant pool.
   1.885 + *            This parameter must be an {@link Integer}, a {@link Float}, a
   1.886 + *            {@link Long}, a {@link Double}, a {@link String} or a
   1.887 + *            {@link Type}.
   1.888 + * @return a new or already existing constant item with the given value.
   1.889 + */
   1.890 +Item newConstItem(final Object cst){
   1.891 +	if(cst instanceof Integer)
   1.892 +		{
   1.893 +		int val = ((Integer) cst).intValue();
   1.894 +		return newInteger(val);
   1.895 +		}
   1.896 +	else if(cst instanceof Byte)
   1.897 +		{
   1.898 +		int val = ((Byte) cst).intValue();
   1.899 +		return newInteger(val);
   1.900 +		}
   1.901 +	else if(cst instanceof Character)
   1.902 +		{
   1.903 +		int val = ((Character) cst).charValue();
   1.904 +		return newInteger(val);
   1.905 +		}
   1.906 +	else if(cst instanceof Short)
   1.907 +		{
   1.908 +		int val = ((Short) cst).intValue();
   1.909 +		return newInteger(val);
   1.910 +		}
   1.911 +	else if(cst instanceof Boolean)
   1.912 +		{
   1.913 +		int val = ((Boolean) cst).booleanValue() ? 1 : 0;
   1.914 +		return newInteger(val);
   1.915 +		}
   1.916 +	else if(cst instanceof Float)
   1.917 +		{
   1.918 +		float val = ((Float) cst).floatValue();
   1.919 +		return newFloat(val);
   1.920 +		}
   1.921 +	else if(cst instanceof Long)
   1.922 +		{
   1.923 +		long val = ((Long) cst).longValue();
   1.924 +		return newLong(val);
   1.925 +		}
   1.926 +	else if(cst instanceof Double)
   1.927 +		{
   1.928 +		double val = ((Double) cst).doubleValue();
   1.929 +		return newDouble(val);
   1.930 +		}
   1.931 +	else if(cst instanceof String)
   1.932 +		{
   1.933 +		return newString((String) cst);
   1.934 +		}
   1.935 +	else if(cst instanceof Type)
   1.936 +		{
   1.937 +		Type t = (Type) cst;
   1.938 +		return newClassItem(t.getSort() == Type.OBJECT
   1.939 +		                    ? t.getInternalName()
   1.940 +		                    : t.getDescriptor());
   1.941 +		}
   1.942 +	else
   1.943 +		{
   1.944 +		throw new IllegalArgumentException("value " + cst);
   1.945 +		}
   1.946 +}
   1.947 +
   1.948 +/**
   1.949 + * Adds a number or string constant to the constant pool of the class being
   1.950 + * build. Does nothing if the constant pool already contains a similar item.
   1.951 + * <i>This method is intended for {@link Attribute} sub classes, and is
   1.952 + * normally not needed by class generators or adapters.</i>
   1.953 + *
   1.954 + * @param cst the value of the constant to be added to the constant pool.
   1.955 + *            This parameter must be an {@link Integer}, a {@link Float}, a
   1.956 + *            {@link Long}, a {@link Double} or a {@link String}.
   1.957 + * @return the index of a new or already existing constant item with the
   1.958 + *         given value.
   1.959 + */
   1.960 +public int newConst(final Object cst){
   1.961 +	return newConstItem(cst).index;
   1.962 +}
   1.963 +
   1.964 +/**
   1.965 + * Adds an UTF8 string to the constant pool of the class being build. Does
   1.966 + * nothing if the constant pool already contains a similar item. <i>This
   1.967 + * method is intended for {@link Attribute} sub classes, and is normally not
   1.968 + * needed by class generators or adapters.</i>
   1.969 + *
   1.970 + * @param value the String value.
   1.971 + * @return the index of a new or already existing UTF8 item.
   1.972 + */
   1.973 +public int newUTF8(final String value){
   1.974 +	key.set(UTF8, value, null, null);
   1.975 +	Item result = get(key);
   1.976 +	if(result == null)
   1.977 +		{
   1.978 +		pool.putByte(UTF8).putUTF8(value);
   1.979 +		result = new Item(index++, key);
   1.980 +		put(result);
   1.981 +		}
   1.982 +	return result.index;
   1.983 +}
   1.984 +
   1.985 +/**
   1.986 + * Adds a class reference to the constant pool of the class being build.
   1.987 + * Does nothing if the constant pool already contains a similar item.
   1.988 + * <i>This method is intended for {@link Attribute} sub classes, and is
   1.989 + * normally not needed by class generators or adapters.</i>
   1.990 + *
   1.991 + * @param value the internal name of the class.
   1.992 + * @return a new or already existing class reference item.
   1.993 + */
   1.994 +Item newClassItem(final String value){
   1.995 +	key2.set(CLASS, value, null, null);
   1.996 +	Item result = get(key2);
   1.997 +	if(result == null)
   1.998 +		{
   1.999 +		pool.put12(CLASS, newUTF8(value));
  1.1000 +		result = new Item(index++, key2);
  1.1001 +		put(result);
  1.1002 +		}
  1.1003 +	return result;
  1.1004 +}
  1.1005 +
  1.1006 +/**
  1.1007 + * Adds a class reference to the constant pool of the class being build.
  1.1008 + * Does nothing if the constant pool already contains a similar item.
  1.1009 + * <i>This method is intended for {@link Attribute} sub classes, and is
  1.1010 + * normally not needed by class generators or adapters.</i>
  1.1011 + *
  1.1012 + * @param value the internal name of the class.
  1.1013 + * @return the index of a new or already existing class reference item.
  1.1014 + */
  1.1015 +public int newClass(final String value){
  1.1016 +	return newClassItem(value).index;
  1.1017 +}
  1.1018 +
  1.1019 +/**
  1.1020 + * Adds a field reference to the constant pool of the class being build.
  1.1021 + * Does nothing if the constant pool already contains a similar item.
  1.1022 + *
  1.1023 + * @param owner the internal name of the field's owner class.
  1.1024 + * @param name  the field's name.
  1.1025 + * @param desc  the field's descriptor.
  1.1026 + * @return a new or already existing field reference item.
  1.1027 + */
  1.1028 +Item newFieldItem(final String owner, final String name, final String desc){
  1.1029 +	key3.set(FIELD, owner, name, desc);
  1.1030 +	Item result = get(key3);
  1.1031 +	if(result == null)
  1.1032 +		{
  1.1033 +		put122(FIELD, newClass(owner), newNameType(name, desc));
  1.1034 +		result = new Item(index++, key3);
  1.1035 +		put(result);
  1.1036 +		}
  1.1037 +	return result;
  1.1038 +}
  1.1039 +
  1.1040 +/**
  1.1041 + * Adds a field reference to the constant pool of the class being build.
  1.1042 + * Does nothing if the constant pool already contains a similar item.
  1.1043 + * <i>This method is intended for {@link Attribute} sub classes, and is
  1.1044 + * normally not needed by class generators or adapters.</i>
  1.1045 + *
  1.1046 + * @param owner the internal name of the field's owner class.
  1.1047 + * @param name  the field's name.
  1.1048 + * @param desc  the field's descriptor.
  1.1049 + * @return the index of a new or already existing field reference item.
  1.1050 + */
  1.1051 +public int newField(final String owner, final String name, final String desc){
  1.1052 +	return newFieldItem(owner, name, desc).index;
  1.1053 +}
  1.1054 +
  1.1055 +/**
  1.1056 + * Adds a method reference to the constant pool of the class being build.
  1.1057 + * Does nothing if the constant pool already contains a similar item.
  1.1058 + *
  1.1059 + * @param owner the internal name of the method's owner class.
  1.1060 + * @param name  the method's name.
  1.1061 + * @param desc  the method's descriptor.
  1.1062 + * @param itf   <tt>true</tt> if <tt>owner</tt> is an interface.
  1.1063 + * @return a new or already existing method reference item.
  1.1064 + */
  1.1065 +Item newMethodItem(
  1.1066 +		final String owner,
  1.1067 +		final String name,
  1.1068 +		final String desc,
  1.1069 +		final boolean itf){
  1.1070 +	int type = itf ? IMETH : METH;
  1.1071 +	key3.set(type, owner, name, desc);
  1.1072 +	Item result = get(key3);
  1.1073 +	if(result == null)
  1.1074 +		{
  1.1075 +		put122(type, newClass(owner), newNameType(name, desc));
  1.1076 +		result = new Item(index++, key3);
  1.1077 +		put(result);
  1.1078 +		}
  1.1079 +	return result;
  1.1080 +}
  1.1081 +
  1.1082 +/**
  1.1083 + * Adds a method reference to the constant pool of the class being build.
  1.1084 + * Does nothing if the constant pool already contains a similar item.
  1.1085 + * <i>This method is intended for {@link Attribute} sub classes, and is
  1.1086 + * normally not needed by class generators or adapters.</i>
  1.1087 + *
  1.1088 + * @param owner the internal name of the method's owner class.
  1.1089 + * @param name  the method's name.
  1.1090 + * @param desc  the method's descriptor.
  1.1091 + * @param itf   <tt>true</tt> if <tt>owner</tt> is an interface.
  1.1092 + * @return the index of a new or already existing method reference item.
  1.1093 + */
  1.1094 +public int newMethod(
  1.1095 +		final String owner,
  1.1096 +		final String name,
  1.1097 +		final String desc,
  1.1098 +		final boolean itf){
  1.1099 +	return newMethodItem(owner, name, desc, itf).index;
  1.1100 +}
  1.1101 +
  1.1102 +/**
  1.1103 + * Adds an integer to the constant pool of the class being build. Does
  1.1104 + * nothing if the constant pool already contains a similar item.
  1.1105 + *
  1.1106 + * @param value the int value.
  1.1107 + * @return a new or already existing int item.
  1.1108 + */
  1.1109 +Item newInteger(final int value){
  1.1110 +	key.set(value);
  1.1111 +	Item result = get(key);
  1.1112 +	if(result == null)
  1.1113 +		{
  1.1114 +		pool.putByte(INT).putInt(value);
  1.1115 +		result = new Item(index++, key);
  1.1116 +		put(result);
  1.1117 +		}
  1.1118 +	return result;
  1.1119 +}
  1.1120 +
  1.1121 +/**
  1.1122 + * Adds a float to the constant pool of the class being build. Does nothing
  1.1123 + * if the constant pool already contains a similar item.
  1.1124 + *
  1.1125 + * @param value the float value.
  1.1126 + * @return a new or already existing float item.
  1.1127 + */
  1.1128 +Item newFloat(final float value){
  1.1129 +	key.set(value);
  1.1130 +	Item result = get(key);
  1.1131 +	if(result == null)
  1.1132 +		{
  1.1133 +		pool.putByte(FLOAT).putInt(key.intVal);
  1.1134 +		result = new Item(index++, key);
  1.1135 +		put(result);
  1.1136 +		}
  1.1137 +	return result;
  1.1138 +}
  1.1139 +
  1.1140 +/**
  1.1141 + * Adds a long to the constant pool of the class being build. Does nothing
  1.1142 + * if the constant pool already contains a similar item.
  1.1143 + *
  1.1144 + * @param value the long value.
  1.1145 + * @return a new or already existing long item.
  1.1146 + */
  1.1147 +Item newLong(final long value){
  1.1148 +	key.set(value);
  1.1149 +	Item result = get(key);
  1.1150 +	if(result == null)
  1.1151 +		{
  1.1152 +		pool.putByte(LONG).putLong(value);
  1.1153 +		result = new Item(index, key);
  1.1154 +		put(result);
  1.1155 +		index += 2;
  1.1156 +		}
  1.1157 +	return result;
  1.1158 +}
  1.1159 +
  1.1160 +/**
  1.1161 + * Adds a double to the constant pool of the class being build. Does nothing
  1.1162 + * if the constant pool already contains a similar item.
  1.1163 + *
  1.1164 + * @param value the double value.
  1.1165 + * @return a new or already existing double item.
  1.1166 + */
  1.1167 +Item newDouble(final double value){
  1.1168 +	key.set(value);
  1.1169 +	Item result = get(key);
  1.1170 +	if(result == null)
  1.1171 +		{
  1.1172 +		pool.putByte(DOUBLE).putLong(key.longVal);
  1.1173 +		result = new Item(index, key);
  1.1174 +		put(result);
  1.1175 +		index += 2;
  1.1176 +		}
  1.1177 +	return result;
  1.1178 +}
  1.1179 +
  1.1180 +/**
  1.1181 + * Adds a string to the constant pool of the class being build. Does nothing
  1.1182 + * if the constant pool already contains a similar item.
  1.1183 + *
  1.1184 + * @param value the String value.
  1.1185 + * @return a new or already existing string item.
  1.1186 + */
  1.1187 +private Item newString(final String value){
  1.1188 +	key2.set(STR, value, null, null);
  1.1189 +	Item result = get(key2);
  1.1190 +	if(result == null)
  1.1191 +		{
  1.1192 +		pool.put12(STR, newUTF8(value));
  1.1193 +		result = new Item(index++, key2);
  1.1194 +		put(result);
  1.1195 +		}
  1.1196 +	return result;
  1.1197 +}
  1.1198 +
  1.1199 +/**
  1.1200 + * Adds a name and type to the constant pool of the class being build. Does
  1.1201 + * nothing if the constant pool already contains a similar item. <i>This
  1.1202 + * method is intended for {@link Attribute} sub classes, and is normally not
  1.1203 + * needed by class generators or adapters.</i>
  1.1204 + *
  1.1205 + * @param name a name.
  1.1206 + * @param desc a type descriptor.
  1.1207 + * @return the index of a new or already existing name and type item.
  1.1208 + */
  1.1209 +public int newNameType(final String name, final String desc){
  1.1210 +	key2.set(NAME_TYPE, name, desc, null);
  1.1211 +	Item result = get(key2);
  1.1212 +	if(result == null)
  1.1213 +		{
  1.1214 +		put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
  1.1215 +		result = new Item(index++, key2);
  1.1216 +		put(result);
  1.1217 +		}
  1.1218 +	return result.index;
  1.1219 +}
  1.1220 +
  1.1221 +/**
  1.1222 + * Adds the given internal name to {@link #typeTable} and returns its index.
  1.1223 + * Does nothing if the type table already contains this internal name.
  1.1224 + *
  1.1225 + * @param type the internal name to be added to the type table.
  1.1226 + * @return the index of this internal name in the type table.
  1.1227 + */
  1.1228 +int addType(final String type){
  1.1229 +	key.set(TYPE_NORMAL, type, null, null);
  1.1230 +	Item result = get(key);
  1.1231 +	if(result == null)
  1.1232 +		{
  1.1233 +		result = addType(key);
  1.1234 +		}
  1.1235 +	return result.index;
  1.1236 +}
  1.1237 +
  1.1238 +/**
  1.1239 + * Adds the given "uninitialized" type to {@link #typeTable} and returns its
  1.1240 + * index. This method is used for UNINITIALIZED types, made of an internal
  1.1241 + * name and a bytecode offset.
  1.1242 + *
  1.1243 + * @param type   the internal name to be added to the type table.
  1.1244 + * @param offset the bytecode offset of the NEW instruction that created
  1.1245 + *               this UNINITIALIZED type value.
  1.1246 + * @return the index of this internal name in the type table.
  1.1247 + */
  1.1248 +int addUninitializedType(final String type, final int offset){
  1.1249 +	key.type = TYPE_UNINIT;
  1.1250 +	key.intVal = offset;
  1.1251 +	key.strVal1 = type;
  1.1252 +	key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
  1.1253 +	Item result = get(key);
  1.1254 +	if(result == null)
  1.1255 +		{
  1.1256 +		result = addType(key);
  1.1257 +		}
  1.1258 +	return result.index;
  1.1259 +}
  1.1260 +
  1.1261 +/**
  1.1262 + * Adds the given Item to {@link #typeTable}.
  1.1263 + *
  1.1264 + * @param item the value to be added to the type table.
  1.1265 + * @return the added Item, which a new Item instance with the same value as
  1.1266 + *         the given Item.
  1.1267 + */
  1.1268 +private Item addType(final Item item){
  1.1269 +	++typeCount;
  1.1270 +	Item result = new Item(typeCount, key);
  1.1271 +	put(result);
  1.1272 +	if(typeTable == null)
  1.1273 +		{
  1.1274 +		typeTable = new Item[16];
  1.1275 +		}
  1.1276 +	if(typeCount == typeTable.length)
  1.1277 +		{
  1.1278 +		Item[] newTable = new Item[2 * typeTable.length];
  1.1279 +		System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
  1.1280 +		typeTable = newTable;
  1.1281 +		}
  1.1282 +	typeTable[typeCount] = result;
  1.1283 +	return result;
  1.1284 +}
  1.1285 +
  1.1286 +/**
  1.1287 + * Returns the index of the common super type of the two given types. This
  1.1288 + * method calls {@link #getCommonSuperClass} and caches the result in the
  1.1289 + * {@link #items} hash table to speedup future calls with the same
  1.1290 + * parameters.
  1.1291 + *
  1.1292 + * @param type1 index of an internal name in {@link #typeTable}.
  1.1293 + * @param type2 index of an internal name in {@link #typeTable}.
  1.1294 + * @return the index of the common super type of the two given types.
  1.1295 + */
  1.1296 +int getMergedType(final int type1, final int type2){
  1.1297 +	key2.type = TYPE_MERGED;
  1.1298 +	key2.longVal = type1 | (((long) type2) << 32);
  1.1299 +	key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
  1.1300 +	Item result = get(key2);
  1.1301 +	if(result == null)
  1.1302 +		{
  1.1303 +		String t = typeTable[type1].strVal1;
  1.1304 +		String u = typeTable[type2].strVal1;
  1.1305 +		key2.intVal = addType(getCommonSuperClass(t, u));
  1.1306 +		result = new Item((short) 0, key2);
  1.1307 +		put(result);
  1.1308 +		}
  1.1309 +	return result.intVal;
  1.1310 +}
  1.1311 +
  1.1312 +/**
  1.1313 + * Returns the common super type of the two given types. The default
  1.1314 + * implementation of this method <i>loads<i> the two given classes and uses
  1.1315 + * the java.lang.Class methods to find the common super class. It can be
  1.1316 + * overriden to compute this common super type in other ways, in particular
  1.1317 + * without actually loading any class, or to take into account the class
  1.1318 + * that is currently being generated by this ClassWriter, which can of
  1.1319 + * course not be loaded since it is under construction.
  1.1320 + *
  1.1321 + * @param type1 the internal name of a class.
  1.1322 + * @param type2 the internal name of another class.
  1.1323 + * @return the internal name of the common super class of the two given
  1.1324 + *         classes.
  1.1325 + */
  1.1326 +protected String getCommonSuperClass(final String type1, final String type2){
  1.1327 +	Class c, d;
  1.1328 +	try
  1.1329 +		{
  1.1330 +		c = Class.forName(type1.replace('/', '.'));
  1.1331 +		d = Class.forName(type2.replace('/', '.'));
  1.1332 +		}
  1.1333 +	catch(ClassNotFoundException e)
  1.1334 +		{
  1.1335 +		throw new RuntimeException(e);
  1.1336 +		}
  1.1337 +	if(c.isAssignableFrom(d))
  1.1338 +		{
  1.1339 +		return type1;
  1.1340 +		}
  1.1341 +	if(d.isAssignableFrom(c))
  1.1342 +		{
  1.1343 +		return type2;
  1.1344 +		}
  1.1345 +	if(c.isInterface() || d.isInterface())
  1.1346 +		{
  1.1347 +		return "java/lang/Object";
  1.1348 +		}
  1.1349 +	else
  1.1350 +		{
  1.1351 +		do
  1.1352 +			{
  1.1353 +			c = c.getSuperclass();
  1.1354 +			} while(!c.isAssignableFrom(d));
  1.1355 +		return c.getName().replace('.', '/');
  1.1356 +		}
  1.1357 +}
  1.1358 +
  1.1359 +/**
  1.1360 + * Returns the constant pool's hash table item which is equal to the given
  1.1361 + * item.
  1.1362 + *
  1.1363 + * @param key a constant pool item.
  1.1364 + * @return the constant pool's hash table item which is equal to the given
  1.1365 + *         item, or <tt>null</tt> if there is no such item.
  1.1366 + */
  1.1367 +private Item get(final Item key){
  1.1368 +	Item i = items[key.hashCode % items.length];
  1.1369 +	while(i != null && !key.isEqualTo(i))
  1.1370 +		{
  1.1371 +		i = i.next;
  1.1372 +		}
  1.1373 +	return i;
  1.1374 +}
  1.1375 +
  1.1376 +/**
  1.1377 + * Puts the given item in the constant pool's hash table. The hash table
  1.1378 + * <i>must</i> not already contains this item.
  1.1379 + *
  1.1380 + * @param i the item to be added to the constant pool's hash table.
  1.1381 + */
  1.1382 +private void put(final Item i){
  1.1383 +	if(index > threshold)
  1.1384 +		{
  1.1385 +		int ll = items.length;
  1.1386 +		int nl = ll * 2 + 1;
  1.1387 +		Item[] newItems = new Item[nl];
  1.1388 +		for(int l = ll - 1; l >= 0; --l)
  1.1389 +			{
  1.1390 +			Item j = items[l];
  1.1391 +			while(j != null)
  1.1392 +				{
  1.1393 +				int index = j.hashCode % newItems.length;
  1.1394 +				Item k = j.next;
  1.1395 +				j.next = newItems[index];
  1.1396 +				newItems[index] = j;
  1.1397 +				j = k;
  1.1398 +				}
  1.1399 +			}
  1.1400 +		items = newItems;
  1.1401 +		threshold = (int) (nl * 0.75);
  1.1402 +		}
  1.1403 +	int index = i.hashCode % items.length;
  1.1404 +	i.next = items[index];
  1.1405 +	items[index] = i;
  1.1406 +}
  1.1407 +
  1.1408 +/**
  1.1409 + * Puts one byte and two shorts into the constant pool.
  1.1410 + *
  1.1411 + * @param b  a byte.
  1.1412 + * @param s1 a short.
  1.1413 + * @param s2 another short.
  1.1414 + */
  1.1415 +private void put122(final int b, final int s1, final int s2){
  1.1416 +	pool.put12(b, s1).putShort(s2);
  1.1417 +}
  1.1418 +}