added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / codegen / ConstantPool.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.codegen;
12
13 import org.eclipse.jdt.internal.compiler.ClassFile;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
16 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
17 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
18 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
19 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
20 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
21 /**
22  * This type is used to store all the constant pool entries.
23  */
24 public class ConstantPool implements ClassFileConstants, TypeIds {
25         public static final int DOUBLE_INITIAL_SIZE = 5;
26         public static final int FLOAT_INITIAL_SIZE = 3;
27         public static final int INT_INITIAL_SIZE = 248;
28         public static final int LONG_INITIAL_SIZE = 5;
29         public static final int UTF8_INITIAL_SIZE = 778;
30         public static final int STRING_INITIAL_SIZE = 761;
31         public static final int METHODS_AND_FIELDS_INITIAL_SIZE = 450;
32         public static final int CLASS_INITIAL_SIZE = 86;
33         public static final int NAMEANDTYPE_INITIAL_SIZE = 272;
34         public static final int CONSTANTPOOL_INITIAL_SIZE = 2000;
35         public static final int CONSTANTPOOL_GROW_SIZE = 6000;
36         protected DoubleCache doubleCache;
37         protected FloatCache floatCache;
38         protected IntegerCache intCache;
39         protected LongCache longCache;
40         public CharArrayCache UTF8Cache;
41         protected CharArrayCache stringCache;
42         protected HashtableOfObject methodsAndFieldsCache;
43         protected CharArrayCache classCache;
44         protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods;
45         public byte[] poolContent;
46         public int currentIndex = 1;
47         public int currentOffset;
48
49         public ClassFile classFile;
50         public static final char[] Append = "append".toCharArray(); //$NON-NLS-1$
51         public static final char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
52         public static final char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
53         public static final char[] ArrayCopy = "arraycopy".toCharArray(); //$NON-NLS-1$
54         public static final char[] ArrayCopySignature = "(Ljava/lang/Object;ILjava/lang/Object;II)V".toCharArray(); //$NON-NLS-1$
55         public static final char[] ArrayJavaLangClassConstantPoolName = "[Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
56         public static final char[] ArrayJavaLangObjectConstantPoolName = "[Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
57         public static final char[] booleanBooleanSignature = "(Z)Ljava/lang/Boolean;".toCharArray(); //$NON-NLS-1$
58         public static final char[] BooleanConstrSignature = "(Z)V".toCharArray(); //$NON-NLS-1$
59         public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
60         public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
61         public static final char[] byteByteSignature = "(B)Ljava/lang/Byte;".toCharArray(); //$NON-NLS-1$
62         public static final char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
63         public static final char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
64         public static final char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
65         public static final char[] charCharacterSignature = "(C)Ljava/lang/Character;".toCharArray(); //$NON-NLS-1$
66         public static final char[] CharConstrSignature = "(C)V".toCharArray(); //$NON-NLS-1$
67         public static final char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
68         public static final char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
69         public static final char[] Clinit = "<clinit>".toCharArray(); //$NON-NLS-1$
70         public static final char[] DefaultConstructorSignature = "()V".toCharArray(); //$NON-NLS-1$
71         public static final char[] ClinitSignature = DefaultConstructorSignature;
72         public static final char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
73         public static final char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
74         public static final char[] DoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
75         public static final char[] doubleDoubleSignature = "(D)Ljava/lang/Double;".toCharArray(); //$NON-NLS-1$
76         public static final char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
77         public static final char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
78         public static final char[] Equals = "equals".toCharArray(); //$NON-NLS-1$
79         public static final char[] EqualsSignature = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
80         public static final char[] Exit = "exit".toCharArray(); //$NON-NLS-1$
81         public static final char[] ExitIntSignature = "(I)V".toCharArray(); //$NON-NLS-1$
82         public static final char[] FloatConstrSignature = "(F)V".toCharArray(); //$NON-NLS-1$
83         public static final char[] floatFloatSignature = "(F)Ljava/lang/Float;".toCharArray(); //$NON-NLS-1$
84         public static final char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
85         public static final char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
86         public static final char[] ForName = "forName".toCharArray(); //$NON-NLS-1$
87         public static final char[] ForNameSignature = "(Ljava/lang/String;)Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
88         public static final char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
89         public static final char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
90         public static final char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
91         public static final char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
92         public static final char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
93         public static final char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
94         public static final char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
95         public static final char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
96         public static final char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
97         public static final char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
98         public static final char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
99         public static final char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
100         public static final char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
101         public static final char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
102         public static final char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
103         public static final char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
104         public static final char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
105         public static final char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
106         public static final char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
107         public static final char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
108         public static final char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
109         public static final char[] GetComponentTypeSignature = GetClassSignature;
110         public static final char[] GetConstructor = "getConstructor".toCharArray(); //$NON-NLS-1$
111         public static final char[] GetConstructorSignature = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
112         public static final char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
113         public static final char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
114         // predefined methods constant names
115         public static final char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
116         public static final char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
117         public static final char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
118         public static final char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
119         public static final char[] GetMessage = "getMessage".toCharArray(); //$NON-NLS-1$
120         public static final char[] GetMessageSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
121         public static final char[] HasNext = "hasNext".toCharArray();//$NON-NLS-1$
122         public static final char[] HasNextSignature = "()Z".toCharArray();//$NON-NLS-1$
123         public static final char[] Init = "<init>".toCharArray(); //$NON-NLS-1$
124         public static final char[] IntConstrSignature = "(I)V".toCharArray(); //$NON-NLS-1$
125         public static final char[] Intern = "intern".toCharArray(); //$NON-NLS-1$
126         public static final char[] InternSignature = GetMessageSignature;
127         public static final char[] IntIntegerSignature = "(I)Ljava/lang/Integer;".toCharArray(); //$NON-NLS-1$
128         public static final char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
129         public static final char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
130         public static final char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
131         public static final char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
132         public static final char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
133         public static final char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
134         // predefined type constant names
135         public static final char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
136         public static final char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
137         public static final char[] JavaIoPrintStreamSignature = "Ljava/io/PrintStream;".toCharArray(); //$NON-NLS-1$
138         public static final char[] JavaLangAssertionErrorConstantPoolName = "java/lang/AssertionError".toCharArray(); //$NON-NLS-1$
139         public static final char[] JavaLangBooleanConstantPoolName = "java/lang/Boolean".toCharArray(); //$NON-NLS-1$
140         public static final char[] JavaLangByteConstantPoolName = "java/lang/Byte".toCharArray(); //$NON-NLS-1$
141         public static final char[] JavaLangCharacterConstantPoolName = "java/lang/Character".toCharArray(); //$NON-NLS-1$
142         public static final char[] JavaLangClassConstantPoolName = "java/lang/Class".toCharArray(); //$NON-NLS-1$
143         public static final char[] JavaLangClassNotFoundExceptionConstantPoolName = "java/lang/ClassNotFoundException".toCharArray(); //$NON-NLS-1$
144         public static final char[] JavaLangClassSignature = "Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
145         public static final char[] JavaLangDoubleConstantPoolName = "java/lang/Double".toCharArray(); //$NON-NLS-1$
146         public static final char[] JavaLangErrorConstantPoolName = "java/lang/Error".toCharArray(); //$NON-NLS-1$
147         public static final char[] JavaLangExceptionConstantPoolName = "java/lang/Exception".toCharArray(); //$NON-NLS-1$
148         public static final char[] JavaLangFloatConstantPoolName = "java/lang/Float".toCharArray(); //$NON-NLS-1$
149         public static final char[] JavaLangIllegalArgumentExceptionConstantPoolName = "java/lang/IllegalArgumentException".toCharArray(); //$NON-NLS-1$
150         public static final char[] JavaLangIntegerConstantPoolName = "java/lang/Integer".toCharArray(); //$NON-NLS-1$
151         public static final char[] JavaLangLongConstantPoolName = "java/lang/Long".toCharArray(); //$NON-NLS-1$
152         public static final char[] JavaLangNoClassDefFoundErrorConstantPoolName = "java/lang/NoClassDefFoundError".toCharArray(); //$NON-NLS-1$
153         public static final char[] JavaLangObjectConstantPoolName = "java/lang/Object".toCharArray(); //$NON-NLS-1$
154         public static final char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
155         public static final char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
156         public static final char[] JavaLangReflectConstructor = "java/lang/reflect/Constructor".toCharArray();   //$NON-NLS-1$
157         public static final char[] JavaLangReflectConstructorNewInstanceSignature = "([Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
158         public static final char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
159         public static final char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
160         public static final char[] JavaLangShortConstantPoolName = "java/lang/Short".toCharArray(); //$NON-NLS-1$
161         public static final char[] JavaLangStringBufferConstantPoolName = "java/lang/StringBuffer".toCharArray(); //$NON-NLS-1$
162         public static final char[] JavaLangStringBuilderConstantPoolName = "java/lang/StringBuilder".toCharArray(); //$NON-NLS-1$
163         public static final char[] JavaLangStringConstantPoolName = "java/lang/String".toCharArray(); //$NON-NLS-1$
164         public static final char[] JavaLangStringSignature = "Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
165         public static final char[] JavaLangSystemConstantPoolName = "java/lang/System".toCharArray(); //$NON-NLS-1$
166         public static final char[] JavaLangThrowableConstantPoolName = "java/lang/Throwable".toCharArray(); //$NON-NLS-1$
167         public static final char[] JavaLangVoidConstantPoolName = "java/lang/Void".toCharArray(); //$NON-NLS-1$
168         public static final char[] JavaUtilIteratorConstantPoolName = "java/util/Iterator".toCharArray(); //$NON-NLS-1$
169         public static final char[] LongConstrSignature = "(J)V".toCharArray(); //$NON-NLS-1$
170         public static final char[] longLongSignature = "(J)Ljava/lang/Long;".toCharArray(); //$NON-NLS-1$
171         public static final char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
172         public static final char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
173         public static final char[] Name = "name".toCharArray(); //$NON-NLS-1$
174         public static final char[] NameSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
175         public static final char[] NewInstance = "newInstance".toCharArray(); //$NON-NLS-1$
176         public static final char[] NewInstanceSignature = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
177         public static final char[] Next = "next".toCharArray();//$NON-NLS-1$
178         public static final char[] NextSignature = "()Ljava/lang/Object;".toCharArray();//$NON-NLS-1$
179         public static final char[] ObjectConstrSignature = "(Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
180         public static final char[] Ordinal = "ordinal".toCharArray(); //$NON-NLS-1$
181         public static final char[] OrdinalSignature = "()I".toCharArray(); //$NON-NLS-1$
182         public static final char[] Out = "out".toCharArray(); //$NON-NLS-1$
183         public static final char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
184         public static final char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
185         public static final char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
186         public static final char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
187         public static final char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
188         public static final char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
189         public static final char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
190         public static final char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
191         public static final char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
192         public static final char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
193         public static final char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
194         public static final char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
195         public static final char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
196         public static final char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
197         public static final char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
198         public static final char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
199         public static final char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
200         public static final char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
201         public static final char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
202         public static final char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
203         public static final char[] ShortConstrSignature = "(S)V".toCharArray(); //$NON-NLS-1$
204         public static final char[] shortShortSignature = "(S)Ljava/lang/Short;".toCharArray(); //$NON-NLS-1$
205         public static final char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
206         public static final char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
207         public static final char[] StringBufferAppendBooleanSignature = "(Z)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
208         public static final char[] StringBufferAppendCharSignature = "(C)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
209         public static final char[] StringBufferAppendDoubleSignature = "(D)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
210         public static final char[] StringBufferAppendFloatSignature = "(F)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
211         public static final char[] StringBufferAppendIntSignature = "(I)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
212         public static final char[] StringBufferAppendLongSignature = "(J)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
213         public static final char[] StringBufferAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
214         public static final char[] StringBufferAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
215         public static final char[] StringBuilderAppendBooleanSignature = "(Z)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
216         public static final char[] StringBuilderAppendCharSignature = "(C)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
217         public static final char[] StringBuilderAppendDoubleSignature = "(D)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
218         public static final char[] StringBuilderAppendFloatSignature = "(F)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
219         public static final char[] StringBuilderAppendIntSignature = "(I)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
220         public static final char[] StringBuilderAppendLongSignature = "(J)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
221         public static final char[] StringBuilderAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
222         public static final char[] StringBuilderAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
223         public static final char[] StringConstructorSignature = "(Ljava/lang/String;)V".toCharArray(); //$NON-NLS-1$
224         public static final char[] This = "this".toCharArray(); //$NON-NLS-1$
225         public static final char[] ToString = "toString".toCharArray(); //$NON-NLS-1$
226         public static final char[] ToStringSignature = GetMessageSignature;
227         public static final char[] TYPE = "TYPE".toCharArray(); //$NON-NLS-1$
228         public static final char[] ValueOf = "valueOf".toCharArray(); //$NON-NLS-1$
229         public static final char[] ValueOfBooleanSignature = "(Z)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
230         public static final char[] ValueOfCharSignature = "(C)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
231         public static final char[] ValueOfDoubleSignature = "(D)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
232         public static final char[] ValueOfFloatSignature = "(F)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
233         public static final char[] ValueOfIntSignature = "(I)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
234         public static final char[] ValueOfLongSignature = "(J)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
235         public static final char[] ValueOfObjectSignature = "(Ljava/lang/Object;)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
236
237 /**
238  * ConstantPool constructor comment.
239  */
240 public ConstantPool(ClassFile classFile) {
241         this.UTF8Cache = new CharArrayCache(UTF8_INITIAL_SIZE);
242         this.stringCache = new CharArrayCache(STRING_INITIAL_SIZE);
243         this.methodsAndFieldsCache = new HashtableOfObject(METHODS_AND_FIELDS_INITIAL_SIZE);
244         this.classCache = new CharArrayCache(CLASS_INITIAL_SIZE);
245         this.nameAndTypeCacheForFieldsAndMethods = new HashtableOfObject(NAMEANDTYPE_INITIAL_SIZE);
246         this.poolContent = classFile.header;
247         this.currentOffset = classFile.headerOffset;
248         // currentOffset is initialized to 0 by default
249         this.currentIndex = 1;
250         this.classFile = classFile;
251 }
252 /**
253  * Return the content of the receiver
254  */
255 public byte[] dumpBytes() {
256         System.arraycopy(poolContent, 0, (poolContent = new byte[currentOffset]), 0, currentOffset);
257         return poolContent;
258 }
259 private int getFromCache(char[] declaringClass, char[] name, char[] signature) {
260         HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(declaringClass);
261         if (value == null) {
262                 return -1;
263         }
264         CharArrayCache value2 = (CharArrayCache) value.get(name);
265         if (value2 == null) {
266                 return -1;
267         }
268         return value2.get(signature);
269 }
270 private int getFromNameAndTypeCache(char[] name, char[] signature) {
271         CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(name);
272         if (value == null) {
273                 return -1;
274         }
275         return value.get(signature);
276 }
277 public int literalIndex(byte[] utf8encoding, char[] stringCharArray) {
278         int index;
279         if ((index = UTF8Cache.get(stringCharArray)) < 0) {
280                 // The entry doesn't exit yet
281                 index = UTF8Cache.put(stringCharArray, currentIndex);
282                 if (index > 0xFFFF){
283                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
284                 }
285                 currentIndex++;
286                 // Write the tag first
287                 writeU1(Utf8Tag);
288                 // Then the size of the stringName array
289                 //writeU2(utf8Constant.length);
290                 int savedCurrentOffset = currentOffset;
291                 int utf8encodingLength = utf8encoding.length;
292                 if (currentOffset + 2 + utf8encodingLength >= poolContent.length) {
293                         // we need to resize the poolContent array because we won't have
294                         // enough space to write the length
295                         resizePoolContents(2 + utf8encodingLength);
296                 }
297                 currentOffset += 2;
298                 // add in once the whole byte array
299                 System.arraycopy(utf8encoding, 0, poolContent, currentOffset, utf8encodingLength);
300                 currentOffset += utf8encodingLength;
301                 // Now we know the length that we have to write in the constant pool
302                 // we use savedCurrentOffset to do that
303                 poolContent[savedCurrentOffset] = (byte) (utf8encodingLength >> 8);
304                 poolContent[savedCurrentOffset + 1] = (byte) utf8encodingLength;
305         }
306         return index;
307 }
308 /**
309  * This method returns the index into the constantPool corresponding to the type descriptor.
310  *
311  * @param utf8Constant char[]
312  * @return <CODE>int</CODE>
313  */
314 public int literalIndex(char[] utf8Constant) {
315         int index;
316         if ((index = UTF8Cache.get(utf8Constant)) < 0) {
317                 // The entry doesn't exit yet
318                 // Write the tag first
319                 writeU1(Utf8Tag);
320                 // Then the size of the stringName array
321                 int savedCurrentOffset = currentOffset;
322                 if (currentOffset + 2 >= poolContent.length) {
323                         // we need to resize the poolContent array because we won't have
324                         // enough space to write the length
325                         resizePoolContents(2);
326                 }
327                 currentOffset += 2;
328                 int length = 0;
329                 for (int i = 0; i < utf8Constant.length; i++) {
330                         char current = utf8Constant[i];
331                         if ((current >= 0x0001) && (current <= 0x007F)) {
332                                 // we only need one byte: ASCII table
333                                 writeU1(current);
334                                 length++;
335                         } else
336                                 if (current > 0x07FF) {
337                                         // we need 3 bytes
338                                         length += 3;
339                                         writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
340                                         writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
341                                         writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
342                                 } else {
343                                         // we can be 0 or between 0x0080 and 0x07FF
344                                         // In that case we only need 2 bytes
345                                         length += 2;
346                                         writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
347                                         writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
348                                 }
349                 }
350                 if (length >= 65535) {
351                         currentOffset = savedCurrentOffset - 1;
352                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceForConstant(this.classFile.referenceBinding.scope.referenceType());
353                 }
354                 index = UTF8Cache.put(utf8Constant, currentIndex);
355                 if (index > 0xFFFF){
356                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
357                 }
358                 currentIndex++;     
359                 // Now we know the length that we have to write in the constant pool
360                 // we use savedCurrentOffset to do that
361                 poolContent[savedCurrentOffset] = (byte) (length >> 8);
362                 poolContent[savedCurrentOffset + 1] = (byte) length;
363         }
364         return index;
365 }
366 public int literalIndex(char[] stringCharArray, byte[] utf8encoding) {
367         int index;
368         int stringIndex;
369         if ((index = stringCache.get(stringCharArray)) < 0) {
370                 // The entry doesn't exit yet
371                 stringIndex = literalIndex(utf8encoding, stringCharArray);
372                 index = stringCache.put(stringCharArray, currentIndex++);
373                 if (index > 0xFFFF){
374                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
375                 }
376                 // Write the tag first
377                 writeU1(StringTag);
378                 // Then the string index
379                 writeU2(stringIndex);
380         }
381         return index;
382 }
383 /**
384  * This method returns the index into the constantPool corresponding to the double
385  * value. If the double is not already present into the pool, it is added. The 
386  * double cache is updated and it returns the right index.
387  *
388  * @param key <CODE>double</CODE>
389  * @return <CODE>int</CODE>
390  */
391 public int literalIndex(double key) {
392         //Retrieve the index from the cache
393         // The double constant takes two indexes into the constant pool, but we only store
394         // the first index into the long table
395         int index;
396         // lazy initialization for base type caches
397         // If it is null, initialize it, otherwise use it
398         if (doubleCache == null) {
399                         doubleCache = new DoubleCache(DOUBLE_INITIAL_SIZE);
400         }
401         if ((index = doubleCache.get(key)) < 0) {
402                 index = doubleCache.put(key, currentIndex++);
403                 if (index > 0xFFFF){
404                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
405                 }
406                 currentIndex++; // a double needs an extra place into the constant pool
407                 // Write the double into the constant pool
408                 // First add the tag
409                 writeU1(DoubleTag);
410                 // Then add the 8 bytes representing the double
411                 long temp = java.lang.Double.doubleToLongBits(key);
412                 int length = poolContent.length;
413                 if (currentOffset + 8 >= length) {
414                         resizePoolContents(8);
415                 }
416                 for (int i = 0; i < 8; i++) {
417                         poolContent[currentOffset++] = (byte) (temp >>> (56 - (i << 3)));
418                 }
419         }
420         return index;
421 }
422 /**
423  * This method returns the index into the constantPool corresponding to the float
424  * value. If the float is not already present into the pool, it is added. The 
425  * int cache is updated and it returns the right index.
426  *
427  * @param key <CODE>float</CODE>
428  * @return <CODE>int</CODE>
429  */
430 public int literalIndex(float key) {
431         //Retrieve the index from the cache
432         int index;
433         // lazy initialization for base type caches
434         // If it is null, initialize it, otherwise use it
435         if (floatCache == null) {
436                 floatCache = new FloatCache(FLOAT_INITIAL_SIZE);
437         }
438         if ((index = floatCache.get(key)) < 0) {
439                 index = floatCache.put(key, currentIndex++);
440                 if (index > 0xFFFF){
441                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
442                 }
443                 // Write the float constant entry into the constant pool
444                 // First add the tag
445                 writeU1(FloatTag);
446                 // Then add the 4 bytes representing the float
447                 int temp = java.lang.Float.floatToIntBits(key);
448                 if (currentOffset + 4 >= poolContent.length) {
449                         resizePoolContents(4);
450                 }
451                 for (int i = 0; i < 4; i++) {
452                         poolContent[currentOffset++] = (byte) (temp >>> (24 - i * 8));
453                 }
454         }
455         return index;
456 }
457 /**
458  * This method returns the index into the constantPool corresponding to the int
459  * value. If the int is not already present into the pool, it is added. The 
460  * int cache is updated and it returns the right index.
461  *
462  * @param key <CODE>int</CODE>
463  * @return <CODE>int</CODE>
464  */
465 public int literalIndex(int key) {
466         //Retrieve the index from the cache
467         int index;
468         // lazy initialization for base type caches
469         // If it is null, initialize it, otherwise use it
470         if (intCache == null) {
471                 intCache = new IntegerCache(INT_INITIAL_SIZE);
472         }
473         if ((index = intCache.get(key)) < 0) {
474                 index = intCache.put(key, currentIndex++);
475                 if (index > 0xFFFF){
476                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
477                 }
478                 // Write the integer constant entry into the constant pool
479                 // First add the tag
480                 writeU1(IntegerTag);
481                 // Then add the 4 bytes representing the int
482                 if (currentOffset + 4 >= poolContent.length) {
483                         resizePoolContents(4);
484                 }
485                 for (int i = 0; i < 4; i++) {
486                         poolContent[currentOffset++] = (byte) (key >>> (24 - i * 8));
487                 }
488         }
489         return index;
490 }
491 /**
492  * This method returns the index into the constantPool corresponding to the long
493  * value. If the long is not already present into the pool, it is added. The 
494  * long cache is updated and it returns the right index.
495  *
496  * @param key <CODE>long</CODE>
497  * @return <CODE>int</CODE>
498  */
499 public int literalIndex(long key) {
500         // Retrieve the index from the cache
501         // The long constant takes two indexes into the constant pool, but we only store
502         // the first index into the long table
503         int index;
504         // lazy initialization for base type caches
505         // If it is null, initialize it, otherwise use it
506         if (longCache == null) {
507                 longCache = new LongCache(LONG_INITIAL_SIZE);
508         }
509         if ((index = longCache.get(key)) < 0) {
510                 index = longCache.put(key, currentIndex++);
511                 if (index > 0xFFFF){
512                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
513                 }
514                 currentIndex++; // long value need an extra place into thwe constant pool
515                 // Write the long into the constant pool
516                 // First add the tag
517                 writeU1(LongTag);
518                 // Then add the 8 bytes representing the long
519                 if (currentOffset + 8 >= poolContent.length) {
520                         resizePoolContents(8);
521                 }
522                 for (int i = 0; i < 8; i++) {
523                         poolContent[currentOffset++] = (byte) (key >>> (56 - (i << 3)));
524                 }
525         }
526         return index;
527 }
528 /**
529  * This method returns the index into the constantPool corresponding to the type descriptor.
530  *
531  * @param stringConstant java.lang.String
532  * @return <CODE>int</CODE>
533  */
534 public int literalIndex(String stringConstant) {
535         int index;
536         char[] stringCharArray = stringConstant.toCharArray();
537         if ((index = stringCache.get(stringCharArray)) < 0) {
538                 // The entry doesn't exit yet
539                 int stringIndex = literalIndex(stringCharArray);
540                 index = stringCache.put(stringCharArray, currentIndex++);
541                 if (index > 0xFFFF){
542                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
543                 }
544                 // Write the tag first
545                 writeU1(StringTag);
546                 // Then the string index
547                 writeU2(stringIndex);
548         }
549         return index;
550 }
551 /**
552  * This method returns the index into the constantPool 
553  * corresponding to the field binding aFieldBinding.
554  *
555  * @param aFieldBinding FieldBinding
556  * @return <CODE>int</CODE>
557  */
558 public int literalIndex(FieldBinding aFieldBinding) {
559         int index;
560         final char[] name = aFieldBinding.name;
561         final char[] signature = aFieldBinding.type.signature();
562         final char[] declaringClassConstantPoolName = aFieldBinding.declaringClass.constantPoolName();
563         if ((index = getFromCache(declaringClassConstantPoolName, name, signature)) < 0) {
564                 // The entry doesn't exit yet
565                 int classIndex = literalIndexForType(declaringClassConstantPoolName);
566                 int nameAndTypeIndex = literalIndexForFields(literalIndex(name), literalIndex(signature), name, signature);
567                 index = putInCache(declaringClassConstantPoolName, name, signature, currentIndex++);
568                 if (index > 0xFFFF){
569                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
570                 }
571                 writeU1(FieldRefTag);
572                 writeU2(classIndex);
573                 writeU2(nameAndTypeIndex);
574         }
575         return index;
576 }
577 /**
578  * This method returns the index into the constantPool corresponding to the 
579  * method descriptor. It can be either an interface method reference constant
580  * or a method reference constant.
581  * Note: uses the method binding #constantPoolDeclaringClass which could be an array type
582  * for the array clone method (see UpdatedMethodDeclaration).
583  * @param aMethodBinding MethodBinding
584  * @return <CODE>int</CODE>
585  */
586 public int literalIndex(MethodBinding aMethodBinding) {
587         int index;
588         final TypeBinding constantPoolDeclaringClass = aMethodBinding.constantPoolDeclaringClass();
589         final char[] declaringClassConstantPoolName = constantPoolDeclaringClass.constantPoolName();
590         final char[] selector = aMethodBinding.selector;
591         final char[] signature = aMethodBinding.signature();
592         if ((index = getFromCache(declaringClassConstantPoolName, selector, signature)) < 0) {
593                 int classIndex = literalIndexForType(constantPoolDeclaringClass.constantPoolName());
594                 int nameAndTypeIndex = literalIndexForMethods(literalIndex(selector), literalIndex(signature), selector, signature);
595                 index = putInCache(declaringClassConstantPoolName, selector, signature, currentIndex++);
596                 if (index > 0xFFFF){
597                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
598                 }
599                 // Write the interface method ref constant into the constant pool
600                 // First add the tag
601                 writeU1(constantPoolDeclaringClass.isInterface() || constantPoolDeclaringClass.isAnnotationType() ? InterfaceMethodRefTag : MethodRefTag);
602                 // Then write the class index
603                 writeU2(classIndex);
604                 // The write the nameAndType index
605                 writeU2(nameAndTypeIndex);
606         }
607         return index;
608 }
609 /**
610  * This method returns the index into the constantPool corresponding to the type descriptor 
611  * corresponding to a type constant pool name.
612  */
613 public int literalIndexForType(final char[] constantPoolName) {
614         int index;
615         if ((index = classCache.get(constantPoolName)) < 0) {
616                 // The entry doesn't exit yet
617                 int nameIndex = literalIndex(constantPoolName);
618                 index = classCache.put(constantPoolName, currentIndex++);
619                 if (index > 0xFFFF){
620                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
621                 }
622                 writeU1(ClassTag);
623                 // Then add the 8 bytes representing the long
624                 writeU2(nameIndex);
625         }
626         return index;
627 }
628 public int literalIndexForMethod(char[] declaringClass, char[] selector, char[] signature, boolean isInterface) {
629         int index = getFromCache(declaringClass, selector, signature);
630         if (index == -1) {
631                 int classIndex;
632                 if ((classIndex = classCache.get(declaringClass)) < 0) {
633                         // The entry doesn't exit yet
634                         int nameIndex = literalIndex(declaringClass);
635                         classIndex = classCache.put(declaringClass, this.currentIndex++);
636                         if (index > 0xFFFF){
637                                 this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
638                         }
639                         writeU1(ClassTag);
640                         // Then add the 8 bytes representing the long
641                         writeU2(nameIndex);
642                 }
643                 int nameAndTypeIndex = literalIndexForMethod(selector, signature);
644                 index = putInCache(declaringClass, selector, signature, currentIndex++);
645                 if (index > 0xFFFF){
646                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
647                 }
648                 // Write the interface method ref constant into the constant pool
649                 // First add the tag
650                 writeU1(isInterface ? InterfaceMethodRefTag : MethodRefTag);
651                 // Then write the class index
652                 writeU2(classIndex);
653                 // The write the nameAndType index
654                 writeU2(nameAndTypeIndex);              
655         }
656         return index;
657 }
658 private int literalIndexForField(char[] name, char[] signature) {
659         int index = getFromNameAndTypeCache(name, signature);
660         if (index == -1) {
661                 // The entry doesn't exit yet
662                 int nameIndex = literalIndex(name);
663                 int typeIndex = literalIndex(signature);
664                 index = putInNameAndTypeCache(name, signature, currentIndex++);
665                 if (index > 0xFFFF){
666                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
667                 }
668                 writeU1(NameAndTypeTag);
669                 writeU2(nameIndex);
670                 writeU2(typeIndex);
671         }
672         return index;
673 }
674 public int literalIndexForMethod(char[] selector, char[] signature) {
675         int index = getFromNameAndTypeCache(selector, signature);
676         if (index == -1) {
677                 // The entry doesn't exit yet
678                 int nameIndex = literalIndex(selector);
679                 int typeIndex = literalIndex(signature);
680                 index = putInNameAndTypeCache(selector, signature, currentIndex++);
681                 if (index > 0xFFFF){
682                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
683                 }
684                 writeU1(NameAndTypeTag);
685                 writeU2(nameIndex);
686                 writeU2(typeIndex);
687         }
688         return index;
689 }
690 public int literalIndexForField(char[] declaringClass, char[] name, char[] signature) {
691         int index = getFromCache(declaringClass, name, signature);
692         if (index == -1) {
693                 int classIndex;
694                 if ((classIndex = classCache.get(declaringClass)) < 0) {
695                         // The entry doesn't exit yet
696                         int nameIndex = literalIndex(declaringClass);
697                         classIndex = classCache.put(declaringClass, this.currentIndex++);
698                         if (index > 0xFFFF){
699                                 this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
700                         }
701                         writeU1(ClassTag);
702                         // Then add the 8 bytes representing the long
703                         writeU2(nameIndex);
704                 }
705                 int nameAndTypeIndex = literalIndexForField(name, signature);
706                 index = putInCache(declaringClass, name, signature, currentIndex++);
707                 if (index > 0xFFFF){
708                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
709                 }
710                 // Write the interface method ref constant into the constant pool
711                 // First add the tag
712                 writeU1(FieldRefTag);
713                 // Then write the class index
714                 writeU2(classIndex);
715                 // The write the nameAndType index
716                 writeU2(nameAndTypeIndex);              
717         }
718         return index;
719 }
720 /**
721  * This method returns the index into the constantPool corresponding 
722  * nameAndType constant with nameIndex, typeIndex.
723  *
724  * @param nameIndex the given name index
725  * @param typeIndex the given type index
726  * @param name the given field name
727  * @param signature the given field signature
728  * @return the index into the constantPool corresponding 
729  * nameAndType constant with nameIndex, typeInde
730  */
731 private int literalIndexForFields(int nameIndex, int typeIndex, char[] name, char[] signature) {
732         int index;
733         if ((index = getFromNameAndTypeCache(name, signature)) == -1) {
734                 // The entry doesn't exit yet
735                 index = putInNameAndTypeCache(name, signature, currentIndex++);
736                 if (index > 0xFFFF){
737                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
738                 }
739                 writeU1(NameAndTypeTag);
740                 writeU2(nameIndex);
741                 writeU2(typeIndex);
742         }
743         return index;
744 }
745 /**
746  * This method returns the index into the constantPool corresponding to the type descriptor.
747  *
748  * @param stringCharArray char[]
749  * @return <CODE>int</CODE>
750  */
751 public int literalIndexForLdc(char[] stringCharArray) {
752         int index;
753         if ((index = stringCache.get(stringCharArray)) < 0) {
754                 int stringIndex;
755                 // The entry doesn't exit yet
756                 if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
757                         // The entry doesn't exit yet
758                         // Write the tag first
759                         writeU1(Utf8Tag);
760                         // Then the size of the stringName array
761                         int savedCurrentOffset = currentOffset;
762                         if (currentOffset + 2 >= poolContent.length) {
763                                 // we need to resize the poolContent array because we won't have
764                                 // enough space to write the length
765                                 resizePoolContents(2);
766                         }
767                         currentOffset += 2;
768                         int length = 0;
769                         for (int i = 0; i < stringCharArray.length; i++) {
770                                 char current = stringCharArray[i];
771                                 if ((current >= 0x0001) && (current <= 0x007F)) {
772                                         // we only need one byte: ASCII table
773                                         writeU1(current);
774                                         length++;
775                                 } else
776                                         if (current > 0x07FF) {
777                                                 // we need 3 bytes
778                                                 length += 3;
779                                                 writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
780                                                 writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
781                                                 writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
782                                         } else {
783                                                 // we can be 0 or between 0x0080 and 0x07FF
784                                                 // In that case we only need 2 bytes
785                                                 length += 2;
786                                                 writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
787                                                 writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
788                                         }
789                         }
790                         if (length >= 65535) {
791                                 currentOffset = savedCurrentOffset - 1;
792                                 return -1;
793                         }
794                         stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
795                         // Now we know the length that we have to write in the constant pool
796                         // we use savedCurrentOffset to do that
797                         if (length > 65535) {
798                                 return 0;
799                         }
800                         poolContent[savedCurrentOffset] = (byte) (length >> 8);
801                         poolContent[savedCurrentOffset + 1] = (byte) length;
802                 }
803                 index = stringCache.put(stringCharArray, currentIndex++);
804                 if (index > 0xFFFF){
805                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
806                 }
807                 // Write the tag first
808                 writeU1(StringTag);
809                 // Then the string index
810                 writeU2(stringIndex);
811         }
812         return index;
813 }
814 /**
815  * This method returns the index into the constantPool corresponding 
816  * nameAndType constant with nameIndex, typeIndex.
817  *
818  * @param nameIndex the given name index
819  * @param typeIndex the given type index
820  * @param selector the given method selector
821  * @param signature the given method signature
822  * @return <CODE>int</CODE>
823  */
824 public int literalIndexForMethods(int nameIndex, int typeIndex, char[] selector, char[] signature) {
825         int index;
826         if ((index = getFromNameAndTypeCache(selector, signature)) == -1) {
827                 // The entry doesn't exit yet
828                 index = putInNameAndTypeCache(selector, signature, currentIndex++);
829                 if (index > 0xFFFF){
830                         this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
831                 }
832                 writeU1(NameAndTypeTag);
833                 writeU2(nameIndex);
834                 writeU2(typeIndex);
835         }
836         return index;
837 }
838 private int putInNameAndTypeCache(final char[] key1, final char[] key2, int index) {
839         CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(key1);
840         if (value == null) {
841                 CharArrayCache charArrayCache = new CharArrayCache();
842                 charArrayCache.put(key2, index);
843                 this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache);
844         } else {
845                 value.put(key2, index);
846         }
847         return index;
848 }
849 /**
850  * @param key1
851  * @param key2
852  * @param key3
853  * @param index
854  * @return the given index
855  */
856 private int putInCache(final char[] key1, final char[] key2, final char[] key3, int index) {
857         HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(key1);
858         if (value == null) {
859                 value = new HashtableOfObject();
860                 this.methodsAndFieldsCache.put(key1, value);
861                 CharArrayCache charArrayCache = new CharArrayCache();
862                 charArrayCache.put(key3, index);
863                 value.put(key2, charArrayCache);
864         } else {
865                 CharArrayCache charArrayCache = (CharArrayCache) value.get(key2);
866                 if (charArrayCache == null) {
867                         charArrayCache = new CharArrayCache();
868                         charArrayCache.put(key3, index);
869                         value.put(key2, charArrayCache);
870                 } else {
871                         charArrayCache.put(key3, index);                        
872                 }
873         }
874         return index;
875 }
876 /**
877  * This method is used to clean the receiver in case of a clinit header is generated, but the 
878  * clinit has no code.
879  * This implementation assumes that the clinit is the first method to be generated.
880  * @see org.eclipse.jdt.internal.compiler.ast.TypeDeclaration#addClinit()
881  */
882 public void resetForClinit(int constantPoolIndex, int constantPoolOffset) {
883         currentIndex = constantPoolIndex;
884         currentOffset = constantPoolOffset;
885         if (UTF8Cache.get(AttributeNamesConstants.CodeName) >= constantPoolIndex) {
886                 UTF8Cache.remove(AttributeNamesConstants.CodeName);
887         }
888         if (UTF8Cache.get(ConstantPool.ClinitSignature) >= constantPoolIndex) {
889                 UTF8Cache.remove(ConstantPool.ClinitSignature);
890         }
891         if (UTF8Cache.get(ConstantPool.Clinit) >= constantPoolIndex) {
892                 UTF8Cache.remove(ConstantPool.Clinit);
893         }
894 }
895
896 /**
897  * Resize the pool contents
898  */
899 private final void resizePoolContents(int minimalSize) {
900         int length = poolContent.length;
901         int toAdd = length;
902         if (toAdd < minimalSize)
903                 toAdd = minimalSize;
904         System.arraycopy(poolContent, 0, poolContent = new byte[length + toAdd], 0, length);
905 }
906 /**
907  * Write a unsigned byte into the byte array
908  * 
909  * @param value <CODE>int</CODE> The value to write into the byte array
910  */
911 protected final void writeU1(int value) {
912         if (currentOffset + 1 >= poolContent.length) {
913                 resizePoolContents(1);
914         }
915         poolContent[currentOffset++] = (byte) value;
916 }
917 /**
918  * Write a unsigned byte into the byte array
919  * 
920  * @param value <CODE>int</CODE> The value to write into the byte array
921  */
922 protected final void writeU2(int value) {
923         if (currentOffset + 2 >= poolContent.length) {
924                 resizePoolContents(2);
925         }
926         //first byte
927         poolContent[currentOffset++] = (byte) (value >> 8);
928         poolContent[currentOffset++] = (byte) value;
929 }
930 }