--- old/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java 2017-08-08 16:04:52.428358645 -0700
+++ new/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java 2017-08-08 16:04:52.344354439 -0700
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -18,736 +17,773 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.sun.org.apache.bcel.internal.generic;
-
-import com.sun.org.apache.bcel.internal.Constants;
-import com.sun.org.apache.bcel.internal.classfile.*;
import java.util.HashMap;
+import java.util.Map;
+
+import com.sun.org.apache.bcel.internal.Const;
+import com.sun.org.apache.bcel.internal.classfile.Constant;
+import com.sun.org.apache.bcel.internal.classfile.ConstantCP;
+import com.sun.org.apache.bcel.internal.classfile.ConstantClass;
+import com.sun.org.apache.bcel.internal.classfile.ConstantDouble;
+import com.sun.org.apache.bcel.internal.classfile.ConstantFieldref;
+import com.sun.org.apache.bcel.internal.classfile.ConstantFloat;
+import com.sun.org.apache.bcel.internal.classfile.ConstantInteger;
+import com.sun.org.apache.bcel.internal.classfile.ConstantInterfaceMethodref;
+import com.sun.org.apache.bcel.internal.classfile.ConstantInvokeDynamic;
+import com.sun.org.apache.bcel.internal.classfile.ConstantLong;
+import com.sun.org.apache.bcel.internal.classfile.ConstantMethodref;
+import com.sun.org.apache.bcel.internal.classfile.ConstantNameAndType;
+import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
+import com.sun.org.apache.bcel.internal.classfile.ConstantString;
+import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8;
/**
- * This class is used to build up a constant pool. The user adds
- * constants via `addXXX' methods, `addString', `addClass',
- * etc.. These methods return an index into the constant
- * pool. Finally, `getFinalConstantPool()' returns the constant pool
- * built up. Intermediate versions of the constant pool can be
+ * This class is used to build up a constant pool. The user adds constants via
+ * `addXXX' methods, `addString', `addClass', etc.. These methods return an
+ * index into the constant pool. Finally, `getFinalConstantPool()' returns the
+ * constant pool built up. Intermediate versions of the constant pool can be
* obtained with `getConstantPool()'. A constant pool has capacity for
- * Constants.MAX_SHORT entries. Note that the first (0) is used by the
- * JVM and that Double and Long constants need two slots.
+ * Constants.MAX_SHORT entries. Note that the first (0) is used by the JVM and
+ * that Double and Long constants need two slots.
*
- * @author M. Dahm
+ * @version $Id: ConstantPoolGen.java 1749603 2016-06-21 20:50:19Z ggregory $
* @see Constant
*/
-public class ConstantPoolGen implements java.io.Serializable {
- protected int size = 1024; // Inital size, sufficient in most cases
- protected Constant[] constants = new Constant[size];
- protected int index = 1; // First entry (0) used by JVM
-
- private static final String METHODREF_DELIM = ":";
- private static final String IMETHODREF_DELIM = "#";
- private static final String FIELDREF_DELIM = "&";
- private static final String NAT_DELIM = "%";
-
- private static class Index implements java.io.Serializable {
- int index;
- Index(int i) { index = i; }
- }
-
- /**
- * Initialize with given array of constants.
- *
- * @param c array of given constants, new ones will be appended
- */
- public ConstantPoolGen(Constant[] cs) {
- if(cs.length > size) {
- size = cs.length;
- constants = new Constant[size];
- }
-
- System.arraycopy(cs, 0, constants, 0, cs.length);
-
- if(cs.length > 0)
- index = cs.length;
-
- for(int i=1; i < index; i++) {
- Constant c = constants[i];
-
- if(c instanceof ConstantString) {
- ConstantString s = (ConstantString)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[s.getStringIndex()];
-
- string_table.put(u8.getBytes(), new Index(i));
- } else if(c instanceof ConstantClass) {
- ConstantClass s = (ConstantClass)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[s.getNameIndex()];
-
- class_table.put(u8.getBytes(), new Index(i));
- } else if(c instanceof ConstantNameAndType) {
- ConstantNameAndType n = (ConstantNameAndType)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[n.getNameIndex()];
- ConstantUtf8 u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
-
- n_a_t_table.put(u8.getBytes() + NAT_DELIM + u8_2.getBytes(), new Index(i));
- } else if(c instanceof ConstantUtf8) {
- ConstantUtf8 u = (ConstantUtf8)c;
-
- utf8_table.put(u.getBytes(), new Index(i));
- } else if(c instanceof ConstantCP) {
- ConstantCP m = (ConstantCP)c;
- ConstantClass clazz = (ConstantClass)constants[m.getClassIndex()];
- ConstantNameAndType n = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
-
- ConstantUtf8 u8 = (ConstantUtf8)constants[clazz.getNameIndex()];
- String class_name = u8.getBytes().replace('/', '.');
-
- u8 = (ConstantUtf8)constants[n.getNameIndex()];
- String method_name = u8.getBytes();
-
- u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
- String signature = u8.getBytes();
-
- String delim = METHODREF_DELIM;
-
- if(c instanceof ConstantInterfaceMethodref)
- delim = IMETHODREF_DELIM;
- else if(c instanceof ConstantFieldref)
- delim = FIELDREF_DELIM;
-
- cp_table.put(class_name + delim + method_name + delim + signature, new Index(i));
- }
- }
- }
-
- /**
- * Initialize with given constant pool.
- */
- public ConstantPoolGen(ConstantPool cp) {
- this(cp.getConstantPool());
- }
-
- /**
- * Create empty constant pool.
- */
- public ConstantPoolGen() {}
-
- /** Resize internal array of constants.
- */
- protected void adjustSize() {
- if(index + 3 >= size) {
- Constant[] cs = constants;
-
- size *= 2;
- constants = new Constant[size];
- System.arraycopy(cs, 0, constants, 0, index);
- }
- }
-
- private HashMap string_table = new HashMap();
-
- /**
- * Look for ConstantString in ConstantPool containing String `str'.
- *
- * @param str String to search for
- * @return index on success, -1 otherwise
- */
- public int lookupString(String str) {
- Index index = (Index)string_table.get(str);
- return (index != null)? index.index : -1;
- }
-
- /**
- * Add a new String constant to the ConstantPool, if it is not already in there.
- *
- * @param str String to add
- * @return index of entry
- */
- public int addString(String str) {
- int ret;
-
- if((ret = lookupString(str)) != -1)
- return ret; // Already in CP
-
- int utf8 = addUtf8(str);
-
- adjustSize();
-
- ConstantString s = new ConstantString(utf8);
-
- ret = index;
- constants[index++] = s;
-
- string_table.put(str, new Index(ret));
-
- return ret;
- }
-
- private HashMap class_table = new HashMap();
-
- /**
- * Look for ConstantClass in ConstantPool named `str'.
- *
- * @param str String to search for
- * @return index on success, -1 otherwise
- */
- public int lookupClass(String str) {
- Index index = (Index)class_table.get(str.replace('.', '/'));
- return (index != null)? index.index : -1;
- }
-
- private int addClass_(String clazz) {
- int ret;
-
- if((ret = lookupClass(clazz)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ConstantClass c = new ConstantClass(addUtf8(clazz));
-
- ret = index;
- constants[index++] = c;
-
- class_table.put(clazz, new Index(ret));
-
- return ret;
- }
-
- /**
- * Add a new Class reference to the ConstantPool, if it is not already in there.
- *
- * @param str Class to add
- * @return index of entry
- */
- public int addClass(String str) {
- return addClass_(str.replace('.', '/'));
- }
-
- /**
- * Add a new Class reference to the ConstantPool for a given type.
- *
- * @param str Class to add
- * @return index of entry
- */
- public int addClass(ObjectType type) {
- return addClass(type.getClassName());
- }
-
- /**
- * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
- * instruction, e.g. to the ConstantPool.
- *
- * @param type type of array class
- * @return index of entry
- */
- public int addArrayClass(ArrayType type) {
- return addClass_(type.getSignature());
- }
-
- /**
- * Look for ConstantInteger in ConstantPool.
- *
- * @param n integer number to look for
- * @return index on success, -1 otherwise
- */
- public int lookupInteger(int n) {
- for(int i=1; i < index; i++) {
- if(constants[i] instanceof ConstantInteger) {
- ConstantInteger c = (ConstantInteger)constants[i];
-
- if(c.getBytes() == n)
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Add a new Integer constant to the ConstantPool, if it is not already in there.
- *
- * @param n integer number to add
- * @return index of entry
- */
- public int addInteger(int n) {
- int ret;
-
- if((ret = lookupInteger(n)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ret = index;
- constants[index++] = new ConstantInteger(n);
-
- return ret;
- }
-
- /**
- * Look for ConstantFloat in ConstantPool.
- *
- * @param n Float number to look for
- * @return index on success, -1 otherwise
- */
- public int lookupFloat(float n) {
- int bits = Float.floatToIntBits(n);
-
- for(int i=1; i < index; i++) {
- if(constants[i] instanceof ConstantFloat) {
- ConstantFloat c = (ConstantFloat)constants[i];
-
- if(Float.floatToIntBits(c.getBytes()) == bits)
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Add a new Float constant to the ConstantPool, if it is not already in there.
- *
- * @param n Float number to add
- * @return index of entry
- */
- public int addFloat(float n) {
- int ret;
-
- if((ret = lookupFloat(n)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ret = index;
- constants[index++] = new ConstantFloat(n);
-
- return ret;
- }
-
- private HashMap utf8_table = new HashMap();
-
- /**
- * Look for ConstantUtf8 in ConstantPool.
- *
- * @param n Utf8 string to look for
- * @return index on success, -1 otherwise
- */
- public int lookupUtf8(String n) {
- Index index = (Index)utf8_table.get(n);
-
- return (index != null)? index.index : -1;
- }
-
- /**
- * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
- *
- * @param n Utf8 string to add
- * @return index of entry
- */
- public int addUtf8(String n) {
- int ret;
-
- if((ret = lookupUtf8(n)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ret = index;
- constants[index++] = new ConstantUtf8(n);
-
- utf8_table.put(n, new Index(ret));
-
- return ret;
- }
-
- /**
- * Look for ConstantLong in ConstantPool.
- *
- * @param n Long number to look for
- * @return index on success, -1 otherwise
- */
- public int lookupLong(long n) {
- for(int i=1; i < index; i++) {
- if(constants[i] instanceof ConstantLong) {
- ConstantLong c = (ConstantLong)constants[i];
-
- if(c.getBytes() == n)
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Add a new long constant to the ConstantPool, if it is not already in there.
- *
- * @param n Long number to add
- * @return index of entry
- */
- public int addLong(long n) {
- int ret;
-
- if((ret = lookupLong(n)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ret = index;
- constants[index] = new ConstantLong(n);
- index += 2; // Wastes one entry according to spec
-
- return ret;
- }
-
- /**
- * Look for ConstantDouble in ConstantPool.
- *
- * @param n Double number to look for
- * @return index on success, -1 otherwise
- */
- public int lookupDouble(double n) {
- long bits = Double.doubleToLongBits(n);
-
- for(int i=1; i < index; i++) {
- if(constants[i] instanceof ConstantDouble) {
- ConstantDouble c = (ConstantDouble)constants[i];
-
- if(Double.doubleToLongBits(c.getBytes()) == bits)
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Add a new double constant to the ConstantPool, if it is not already in there.
- *
- * @param n Double number to add
- * @return index of entry
- */
- public int addDouble(double n) {
- int ret;
-
- if((ret = lookupDouble(n)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- ret = index;
- constants[index] = new ConstantDouble(n);
- index += 2; // Wastes one entry according to spec
-
- return ret;
- }
-
- private HashMap n_a_t_table = new HashMap();
-
- /**
- * Look for ConstantNameAndType in ConstantPool.
- *
- * @param name of variable/method
- * @param signature of variable/method
- * @return index on success, -1 otherwise
- */
- public int lookupNameAndType(String name, String signature) {
- Index index = (Index)n_a_t_table.get(name + NAT_DELIM + signature);
- return (index != null)? index.index : -1;
- }
-
- /**
- * Add a new NameAndType constant to the ConstantPool if it is not already
- * in there.
- *
- * @param n NameAndType string to add
- * @return index of entry
- */
- public int addNameAndType(String name, String signature) {
- int ret;
- int name_index, signature_index;
-
- if((ret = lookupNameAndType(name, signature)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- name_index = addUtf8(name);
- signature_index = addUtf8(signature);
- ret = index;
- constants[index++] = new ConstantNameAndType(name_index, signature_index);
-
- n_a_t_table.put(name + NAT_DELIM + signature, new Index(ret));
- return ret;
- }
-
- private HashMap cp_table = new HashMap();
-
- /**
- * Look for ConstantMethodref in ConstantPool.
- *
- * @param class_name Where to find method
- * @param method_name Guess what
- * @param signature return and argument types
- * @return index on success, -1 otherwise
- */
- public int lookupMethodref(String class_name, String method_name, String signature) {
- Index index = (Index)cp_table.get(class_name + METHODREF_DELIM + method_name +
- METHODREF_DELIM + signature);
- return (index != null)? index.index : -1;
- }
-
- public int lookupMethodref(MethodGen method) {
- return lookupMethodref(method.getClassName(), method.getName(),
- method.getSignature());
- }
-
- /**
- * Add a new Methodref constant to the ConstantPool, if it is not already
- * in there.
- *
- * @param n Methodref string to add
- * @return index of entry
- */
- public int addMethodref(String class_name, String method_name, String signature) {
- int ret, class_index, name_and_type_index;
-
- if((ret = lookupMethodref(class_name, method_name, signature)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- name_and_type_index = addNameAndType(method_name, signature);
- class_index = addClass(class_name);
- ret = index;
- constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
-
- cp_table.put(class_name + METHODREF_DELIM + method_name +
- METHODREF_DELIM + signature, new Index(ret));
-
- return ret;
- }
-
- public int addMethodref(MethodGen method) {
- return addMethodref(method.getClassName(), method.getName(),
- method.getSignature());
- }
-
- /**
- * Look for ConstantInterfaceMethodref in ConstantPool.
- *
- * @param class_name Where to find method
- * @param method_name Guess what
- * @param signature return and argument types
- * @return index on success, -1 otherwise
- */
- public int lookupInterfaceMethodref(String class_name, String method_name, String signature) {
- Index index = (Index)cp_table.get(class_name + IMETHODREF_DELIM + method_name +
- IMETHODREF_DELIM + signature);
- return (index != null)? index.index : -1;
- }
-
- public int lookupInterfaceMethodref(MethodGen method) {
- return lookupInterfaceMethodref(method.getClassName(), method.getName(),
- method.getSignature());
- }
-
- /**
- * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already
- * in there.
- *
- * @param n InterfaceMethodref string to add
- * @return index of entry
- */
- public int addInterfaceMethodref(String class_name, String method_name, String signature) {
- int ret, class_index, name_and_type_index;
-
- if((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- class_index = addClass(class_name);
- name_and_type_index = addNameAndType(method_name, signature);
- ret = index;
- constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
-
- cp_table.put(class_name + IMETHODREF_DELIM + method_name +
- IMETHODREF_DELIM + signature, new Index(ret));
-
- return ret;
- }
-
- public int addInterfaceMethodref(MethodGen method) {
- return addInterfaceMethodref(method.getClassName(), method.getName(),
- method.getSignature());
- }
-
- /**
- * Look for ConstantFieldref in ConstantPool.
- *
- * @param class_name Where to find method
- * @param field_name Guess what
- * @param signature return and argument types
- * @return index on success, -1 otherwise
- */
- public int lookupFieldref(String class_name, String field_name, String signature) {
- Index index = (Index)cp_table.get(class_name + FIELDREF_DELIM + field_name +
- FIELDREF_DELIM + signature);
- return (index != null)? index.index : -1;
- }
-
- /**
- * Add a new Fieldref constant to the ConstantPool, if it is not already
- * in there.
- *
- * @param n Fieldref string to add
- * @return index of entry
- */
- public int addFieldref(String class_name, String field_name, String signature) {
- int ret;
- int class_index, name_and_type_index;
-
- if((ret = lookupFieldref(class_name, field_name, signature)) != -1)
- return ret; // Already in CP
-
- adjustSize();
-
- class_index = addClass(class_name);
- name_and_type_index = addNameAndType(field_name, signature);
- ret = index;
- constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
-
- cp_table.put(class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature, new Index(ret));
-
- return ret;
- }
-
- /**
- * @param i index in constant pool
- * @return constant pool entry at index i
- */
- public Constant getConstant(int i) { return constants[i]; }
-
- /**
- * Use with care!
- *
- * @param i index in constant pool
- * @param c new constant pool entry at index i
- */
- public void setConstant(int i, Constant c) { constants[i] = c; }
-
- /**
- * @return intermediate constant pool
- */
- public ConstantPool getConstantPool() {
- return new ConstantPool(constants);
- }
-
- /**
- * @return current size of constant pool
- */
- public int getSize() {
- return index;
- }
-
- /**
- * @return constant pool with proper length
- */
- public ConstantPool getFinalConstantPool() {
- Constant[] cs = new Constant[index];
-
- System.arraycopy(constants, 0, cs, 0, index);
-
- return new ConstantPool(cs);
- }
-
- /**
- * @return String representation.
- */
- public String toString() {
- StringBuffer buf = new StringBuffer();
-
- for(int i=1; i < index; i++)
- buf.append(i + ")" + constants[i] + "\n");
-
- return buf.toString();
- }
-
- /** Import constant from another ConstantPool and return new index.
- */
- public int addConstant(Constant c, ConstantPoolGen cp) {
- Constant[] constants = cp.getConstantPool().getConstantPool();
-
- switch(c.getTag()) {
- case Constants.CONSTANT_String: {
- ConstantString s = (ConstantString)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[s.getStringIndex()];
-
- return addString(u8.getBytes());
- }
-
- case Constants.CONSTANT_Class: {
- ConstantClass s = (ConstantClass)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[s.getNameIndex()];
-
- return addClass(u8.getBytes());
- }
-
- case Constants.CONSTANT_NameAndType: {
- ConstantNameAndType n = (ConstantNameAndType)c;
- ConstantUtf8 u8 = (ConstantUtf8)constants[n.getNameIndex()];
- ConstantUtf8 u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
-
- return addNameAndType(u8.getBytes(), u8_2.getBytes());
- }
-
- case Constants.CONSTANT_Utf8:
- return addUtf8(((ConstantUtf8)c).getBytes());
-
- case Constants.CONSTANT_Double:
- return addDouble(((ConstantDouble)c).getBytes());
-
- case Constants.CONSTANT_Float:
- return addFloat(((ConstantFloat)c).getBytes());
-
- case Constants.CONSTANT_Long:
- return addLong(((ConstantLong)c).getBytes());
-
- case Constants.CONSTANT_Integer:
- return addInteger(((ConstantInteger)c).getBytes());
-
- case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
- case Constants.CONSTANT_Fieldref: {
- ConstantCP m = (ConstantCP)c;
- ConstantClass clazz = (ConstantClass)constants[m.getClassIndex()];
- ConstantNameAndType n = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
- ConstantUtf8 u8 = (ConstantUtf8)constants[clazz.getNameIndex()];
- String class_name = u8.getBytes().replace('/', '.');
-
- u8 = (ConstantUtf8)constants[n.getNameIndex()];
- String name = u8.getBytes();
-
- u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
- String signature = u8.getBytes();
-
- switch(c.getTag()) {
- case Constants.CONSTANT_InterfaceMethodref:
- return addInterfaceMethodref(class_name, name, signature);
-
- case Constants.CONSTANT_Methodref:
- return addMethodref(class_name, name, signature);
-
- case Constants.CONSTANT_Fieldref:
- return addFieldref(class_name, name, signature);
-
- default: // Never reached
- throw new RuntimeException("Unknown constant type " + c);
- }
- }
+public class ConstantPoolGen {
- default: // Never reached
- throw new RuntimeException("Unknown constant type " + c);
+ private static final int DEFAULT_BUFFER_SIZE = 256;
+ private int size;
+ private Constant[] constants;
+ private int index = 1; // First entry (0) used by JVM
+
+ private static final String METHODREF_DELIM = ":";
+ private static final String IMETHODREF_DELIM = "#";
+ private static final String FIELDREF_DELIM = "&";
+ private static final String NAT_DELIM = "%"; // Name and Type
+
+ private static class Index {
+
+ final int index;
+
+ Index(final int i) {
+ index = i;
+ }
+ }
+
+ /**
+ * Initialize with given array of constants.
+ *
+ * @param cs array of given constants, new ones will be appended
+ */
+ public ConstantPoolGen(final Constant[] cs) {
+ final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
+
+ size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64);
+ constants = new Constant[size];
+
+ System.arraycopy(cs, 0, constants, 0, cs.length);
+ if (cs.length > 0) {
+ index = cs.length;
+ }
+
+ for (int i = 1; i < index; i++) {
+ final Constant c = constants[i];
+ if (c instanceof ConstantString) {
+ final ConstantString s = (ConstantString) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
+ final String key = u8.getBytes();
+ if (!string_table.containsKey(key)) {
+ string_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantClass) {
+ final ConstantClass s = (ConstantClass) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
+ final String key = u8.getBytes();
+ if (!class_table.containsKey(key)) {
+ class_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantNameAndType) {
+ final ConstantNameAndType n = (ConstantNameAndType) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
+
+ sb.append(u8.getBytes());
+ sb.append(NAT_DELIM);
+ sb.append(u8_2.getBytes());
+ final String key = sb.toString();
+ sb.delete(0, sb.length());
+
+ if (!n_a_t_table.containsKey(key)) {
+ n_a_t_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantUtf8) {
+ final ConstantUtf8 u = (ConstantUtf8) c;
+ final String key = u.getBytes();
+ if (!utf8_table.containsKey(key)) {
+ utf8_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantCP) {
+ final ConstantCP m = (ConstantCP) c;
+ String class_name;
+ ConstantUtf8 u8;
+
+ if (c instanceof ConstantInvokeDynamic) {
+ class_name = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex());
+ // since name can't begin with digit, can use
+ // METHODREF_DELIM with out fear of duplicates.
+ } else {
+ final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
+ u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
+ class_name = u8.getBytes().replace('/', '.');
+ }
+
+ final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
+ u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ final String method_name = u8.getBytes();
+ u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ final String signature = u8.getBytes();
+
+ String delim = METHODREF_DELIM;
+ if (c instanceof ConstantInterfaceMethodref) {
+ delim = IMETHODREF_DELIM;
+ } else if (c instanceof ConstantFieldref) {
+ delim = FIELDREF_DELIM;
+ }
+
+ sb.append(class_name);
+ sb.append(delim);
+ sb.append(method_name);
+ sb.append(delim);
+ sb.append(signature);
+ final String key = sb.toString();
+ sb.delete(0, sb.length());
+
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(i));
+ }
+ } else if (c == null) { // entries may be null
+ // nothing to do
+ } else if (c instanceof ConstantInteger) {
+ // nothing to do
+ } else if (c instanceof ConstantLong) {
+ // nothing to do
+ } else if (c instanceof ConstantFloat) {
+ // nothing to do
+ } else if (c instanceof ConstantDouble) {
+ // nothing to do
+ } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodType) {
+ // TODO should this be handled somehow?
+ } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodHandle) {
+ // TODO should this be handled somehow?
+ } else {
+ assert false : "Unexpected constant type: " + c.getClass().getName();
+ }
+ }
+ }
+
+ /**
+ * Initialize with given constant pool.
+ */
+ public ConstantPoolGen(final ConstantPool cp) {
+ this(cp.getConstantPool());
+ }
+
+ /**
+ * Create empty constant pool.
+ */
+ public ConstantPoolGen() {
+ size = DEFAULT_BUFFER_SIZE;
+ constants = new Constant[size];
+ }
+
+ /**
+ * Resize internal array of constants.
+ */
+ protected void adjustSize() {
+ if (index + 3 >= size) {
+ final Constant[] cs = constants;
+ size *= 2;
+ constants = new Constant[size];
+ System.arraycopy(cs, 0, constants, 0, index);
+ }
+ }
+
+ private final Map string_table = new HashMap<>();
+
+ /**
+ * Look for ConstantString in ConstantPool containing String `str'.
+ *
+ * @param str String to search for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupString(final String str) {
+ final Index index = string_table.get(str);
+ return (index != null) ? index.index : -1;
+ }
+
+ /**
+ * Add a new String constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param str String to add
+ * @return index of entry
+ */
+ public int addString(final String str) {
+ int ret;
+ if ((ret = lookupString(str)) != -1) {
+ return ret; // Already in CP
+ }
+ final int utf8 = addUtf8(str);
+ adjustSize();
+ final ConstantString s = new ConstantString(utf8);
+ ret = index;
+ constants[index++] = s;
+ if (!string_table.containsKey(str)) {
+ string_table.put(str, new Index(ret));
+ }
+ return ret;
+ }
+
+ private final Map class_table = new HashMap<>();
+
+ /**
+ * Look for ConstantClass in ConstantPool named `str'.
+ *
+ * @param str String to search for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupClass(final String str) {
+ final Index index = class_table.get(str.replace('.', '/'));
+ return (index != null) ? index.index : -1;
+ }
+
+ private int addClass_(final String clazz) {
+ int ret;
+ if ((ret = lookupClass(clazz)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ final ConstantClass c = new ConstantClass(addUtf8(clazz));
+ ret = index;
+ constants[index++] = c;
+ if (!class_table.containsKey(clazz)) {
+ class_table.put(clazz, new Index(ret));
+ }
+ return ret;
+ }
+
+ /**
+ * Add a new Class reference to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param str Class to add
+ * @return index of entry
+ */
+ public int addClass(final String str) {
+ return addClass_(str.replace('.', '/'));
+ }
+
+ /**
+ * Add a new Class reference to the ConstantPool for a given type.
+ *
+ * @param type Class to add
+ * @return index of entry
+ */
+ public int addClass(final ObjectType type) {
+ return addClass(type.getClassName());
+ }
+
+ /**
+ * Add a reference to an array class (e.g. String[][]) as needed by
+ * MULTIANEWARRAY instruction, e.g. to the ConstantPool.
+ *
+ * @param type type of array class
+ * @return index of entry
+ */
+ public int addArrayClass(final ArrayType type) {
+ return addClass_(type.getSignature());
+ }
+
+ /**
+ * Look for ConstantInteger in ConstantPool.
+ *
+ * @param n integer number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupInteger(final int n) {
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantInteger) {
+ final ConstantInteger c = (ConstantInteger) constants[i];
+ if (c.getBytes() == n) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Add a new Integer constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param n integer number to add
+ * @return index of entry
+ */
+ public int addInteger(final int n) {
+ int ret;
+ if ((ret = lookupInteger(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantInteger(n);
+ return ret;
+ }
+
+ /**
+ * Look for ConstantFloat in ConstantPool.
+ *
+ * @param n Float number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupFloat(final float n) {
+ final int bits = Float.floatToIntBits(n);
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantFloat) {
+ final ConstantFloat c = (ConstantFloat) constants[i];
+ if (Float.floatToIntBits(c.getBytes()) == bits) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Add a new Float constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param n Float number to add
+ * @return index of entry
+ */
+ public int addFloat(final float n) {
+ int ret;
+ if ((ret = lookupFloat(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantFloat(n);
+ return ret;
+ }
+
+ private final Map utf8_table = new HashMap<>();
+
+ /**
+ * Look for ConstantUtf8 in ConstantPool.
+ *
+ * @param n Utf8 string to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupUtf8(final String n) {
+ final Index index = utf8_table.get(n);
+ return (index != null) ? index.index : -1;
+ }
+
+ /**
+ * Add a new Utf8 constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param n Utf8 string to add
+ * @return index of entry
+ */
+ public int addUtf8(final String n) {
+ int ret;
+ if ((ret = lookupUtf8(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantUtf8(n);
+ if (!utf8_table.containsKey(n)) {
+ utf8_table.put(n, new Index(ret));
+ }
+ return ret;
+ }
+
+ /**
+ * Look for ConstantLong in ConstantPool.
+ *
+ * @param n Long number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupLong(final long n) {
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantLong) {
+ final ConstantLong c = (ConstantLong) constants[i];
+ if (c.getBytes() == n) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Add a new long constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param n Long number to add
+ * @return index of entry
+ */
+ public int addLong(final long n) {
+ int ret;
+ if ((ret = lookupLong(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index] = new ConstantLong(n);
+ index += 2; // Wastes one entry according to spec
+ return ret;
+ }
+
+ /**
+ * Look for ConstantDouble in ConstantPool.
+ *
+ * @param n Double number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupDouble(final double n) {
+ final long bits = Double.doubleToLongBits(n);
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantDouble) {
+ final ConstantDouble c = (ConstantDouble) constants[i];
+ if (Double.doubleToLongBits(c.getBytes()) == bits) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Add a new double constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param n Double number to add
+ * @return index of entry
+ */
+ public int addDouble(final double n) {
+ int ret;
+ if ((ret = lookupDouble(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index] = new ConstantDouble(n);
+ index += 2; // Wastes one entry according to spec
+ return ret;
+ }
+
+ private final Map n_a_t_table = new HashMap<>();
+
+ /**
+ * Look for ConstantNameAndType in ConstantPool.
+ *
+ * @param name of variable/method
+ * @param signature of variable/method
+ * @return index on success, -1 otherwise
+ */
+ public int lookupNameAndType(final String name, final String signature) {
+ final Index _index = n_a_t_table.get(name + NAT_DELIM + signature);
+ return (_index != null) ? _index.index : -1;
+ }
+
+ /**
+ * Add a new NameAndType constant to the ConstantPool if it is not already
+ * in there.
+ *
+ * @param name Name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addNameAndType(final String name, final String signature) {
+ int ret;
+ int name_index;
+ int signature_index;
+ if ((ret = lookupNameAndType(name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ name_index = addUtf8(name);
+ signature_index = addUtf8(signature);
+ ret = index;
+ constants[index++] = new ConstantNameAndType(name_index, signature_index);
+ final String key = name + NAT_DELIM + signature;
+ if (!n_a_t_table.containsKey(key)) {
+ n_a_t_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+ private final Map cp_table = new HashMap<>();
+
+ /**
+ * Look for ConstantMethodref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param method_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupMethodref(final String class_name, final String method_name, final String signature) {
+ final Index index = cp_table.get(class_name + METHODREF_DELIM + method_name
+ + METHODREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+ public int lookupMethodref(final MethodGen method) {
+ return lookupMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+ /**
+ * Add a new Methodref constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param class_name class name string to add
+ * @param method_name method name string to add
+ * @param signature method signature string to add
+ * @return index of entry
+ */
+ public int addMethodref(final String class_name, final String method_name, final String signature) {
+ int ret;
+ int class_index;
+ int name_and_type_index;
+ if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ name_and_type_index = addNameAndType(method_name, signature);
+ class_index = addClass(class_name);
+ ret = index;
+ constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
+ final String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+ public int addMethodref(final MethodGen method) {
+ return addMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+ /**
+ * Look for ConstantInterfaceMethodref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param method_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupInterfaceMethodref(final String class_name, final String method_name, final String signature) {
+ final Index index = cp_table.get(class_name + IMETHODREF_DELIM + method_name
+ + IMETHODREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+ public int lookupInterfaceMethodref(final MethodGen method) {
+ return lookupInterfaceMethodref(method.getClassName(), method.getName(), method
+ .getSignature());
+ }
+
+ /**
+ * Add a new InterfaceMethodref constant to the ConstantPool, if it is not
+ * already in there.
+ *
+ * @param class_name class name string to add
+ * @param method_name method name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addInterfaceMethodref(final String class_name, final String method_name, final String signature) {
+ int ret;
+ int class_index;
+ int name_and_type_index;
+ if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ class_index = addClass(class_name);
+ name_and_type_index = addNameAndType(method_name, signature);
+ ret = index;
+ constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
+ final String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+ public int addInterfaceMethodref(final MethodGen method) {
+ return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+ /**
+ * Look for ConstantFieldref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param field_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupFieldref(final String class_name, final String field_name, final String signature) {
+ final Index index = cp_table.get(class_name + FIELDREF_DELIM + field_name
+ + FIELDREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+ /**
+ * Add a new Fieldref constant to the ConstantPool, if it is not already in
+ * there.
+ *
+ * @param class_name class name string to add
+ * @param field_name field name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addFieldref(final String class_name, final String field_name, final String signature) {
+ int ret;
+ int class_index;
+ int name_and_type_index;
+ if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ class_index = addClass(class_name);
+ name_and_type_index = addNameAndType(field_name, signature);
+ ret = index;
+ constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
+ final String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+ /**
+ * @param i index in constant pool
+ * @return constant pool entry at index i
+ */
+ public Constant getConstant(final int i) {
+ return constants[i];
+ }
+
+ /**
+ * Use with care!
+ *
+ * @param i index in constant pool
+ * @param c new constant pool entry at index i
+ */
+ public void setConstant(final int i, final Constant c) {
+ constants[i] = c;
+ }
+
+ /**
+ * @return intermediate constant pool
+ */
+ public ConstantPool getConstantPool() {
+ return new ConstantPool(constants);
+ }
+
+ /**
+ * @return current size of constant pool
+ */
+ public int getSize() {
+ return index;
+ }
+
+ /**
+ * @return constant pool with proper length
+ */
+ public ConstantPool getFinalConstantPool() {
+ final Constant[] cs = new Constant[index];
+ System.arraycopy(constants, 0, cs, 0, index);
+ return new ConstantPool(cs);
+ }
+
+ /**
+ * @return String representation.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ for (int i = 1; i < index; i++) {
+ buf.append(i).append(")").append(constants[i]).append("\n");
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Import constant from another ConstantPool and return new index.
+ */
+ public int addConstant(final Constant c, final ConstantPoolGen cp) {
+ final Constant[] constants = cp.getConstantPool().getConstantPool();
+ switch (c.getTag()) {
+ case Const.CONSTANT_String: {
+ final ConstantString s = (ConstantString) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
+ return addString(u8.getBytes());
+ }
+ case Const.CONSTANT_Class: {
+ final ConstantClass s = (ConstantClass) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
+ return addClass(u8.getBytes());
+ }
+ case Const.CONSTANT_NameAndType: {
+ final ConstantNameAndType n = (ConstantNameAndType) c;
+ final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ return addNameAndType(u8.getBytes(), u8_2.getBytes());
+ }
+ case Const.CONSTANT_Utf8:
+ return addUtf8(((ConstantUtf8) c).getBytes());
+ case Const.CONSTANT_Double:
+ return addDouble(((ConstantDouble) c).getBytes());
+ case Const.CONSTANT_Float:
+ return addFloat(((ConstantFloat) c).getBytes());
+ case Const.CONSTANT_Long:
+ return addLong(((ConstantLong) c).getBytes());
+ case Const.CONSTANT_Integer:
+ return addInteger(((ConstantInteger) c).getBytes());
+ case Const.CONSTANT_InterfaceMethodref:
+ case Const.CONSTANT_Methodref:
+ case Const.CONSTANT_Fieldref: {
+ final ConstantCP m = (ConstantCP) c;
+ final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
+ final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
+ ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
+ final String class_name = u8.getBytes().replace('/', '.');
+ u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ final String name = u8.getBytes();
+ u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ final String signature = u8.getBytes();
+ switch (c.getTag()) {
+ case Const.CONSTANT_InterfaceMethodref:
+ return addInterfaceMethodref(class_name, name, signature);
+ case Const.CONSTANT_Methodref:
+ return addMethodref(class_name, name, signature);
+ case Const.CONSTANT_Fieldref:
+ return addFieldref(class_name, name, signature);
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + c);
+ }
+ }
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + c);
+ }
}
- }
}