added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ClassFile.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;
12
13 import java.io.*;
14 import java.util.StringTokenizer;
15
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.core.compiler.IProblem;
18 import org.eclipse.jdt.internal.compiler.ast.*;
19 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20 import org.eclipse.jdt.internal.compiler.codegen.*;
21 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
22 import org.eclipse.jdt.internal.compiler.impl.Constant;
23 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
24 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
25 import org.eclipse.jdt.internal.compiler.lookup.*;
26 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
27 import org.eclipse.jdt.internal.compiler.util.Util;
28
29 /**
30  * Represents a class file wrapper on bytes, it is aware of its actual
31  * type name.
32  *
33  * Public APIs are listed below:
34  *
35  * byte[] getBytes();
36  *              Answer the actual bytes of the class file
37  *
38  * char[][] getCompoundName();
39  *              Answer the compound name of the class file.
40  *              For example, {{java}, {util}, {Hashtable}}.
41  *
42  * byte[] getReducedBytes();
43  *              Answer a smaller byte format, which is only contains some structural 
44  *      information. Those bytes are decodable with a regular class file reader, 
45  *      such as DietClassFileReader
46  */
47 public class ClassFile
48         implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
49         public static final int INITIAL_CONTENTS_SIZE = 400;
50         public static final int INITIAL_HEADER_SIZE = 1500;
51         public static final int INNER_CLASSES_SIZE = 5;
52
53         /**
54          * INTERNAL USE-ONLY
55          * Build all the directories and subdirectories corresponding to the packages names
56          * into the directory specified in parameters.
57          *
58          * outputPath is formed like:
59          *         c:\temp\ the last character is a file separator
60          * relativeFileName is formed like:
61          *     java\lang\String.class *
62          * 
63          * @param outputPath java.lang.String
64          * @param relativeFileName java.lang.String
65          * @return java.lang.String
66          */
67         public static String buildAllDirectoriesInto(
68                 String outputPath,
69                 String relativeFileName)
70                 throws IOException {
71                 char fileSeparatorChar = File.separatorChar;
72                 String fileSeparator = File.separator;
73                 File f;
74                 // First we ensure that the outputPath exists
75                 outputPath = outputPath.replace('/', fileSeparatorChar);
76                 // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
77                 if (outputPath.endsWith(fileSeparator)) {
78                         outputPath = outputPath.substring(0, outputPath.length() - 1);
79                 }
80                 f = new File(outputPath);
81                 if (f.exists()) {
82                         if (!f.isDirectory()) {
83                                 System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
84                                 throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
85                         }
86                 } else {
87                         // we have to create that directory
88                         if (!f.mkdirs()) {
89                                 System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
90                                 throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
91                         }
92                 }
93                 StringBuffer outDir = new StringBuffer(outputPath);
94                 outDir.append(fileSeparator);
95                 StringTokenizer tokenizer =
96                         new StringTokenizer(relativeFileName, fileSeparator);
97                 String token = tokenizer.nextToken();
98                 while (tokenizer.hasMoreTokens()) {
99                         f = new File(outDir.append(token).append(fileSeparator).toString());
100                         if (f.exists()) {
101                                 // The outDir already exists, so we proceed the next entry
102                                 // System.out.println("outDir: " + outDir + " already exists.");
103                         } else {
104                                 // Need to add the outDir
105                                 if (!f.mkdir()) {
106                                         System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
107                                         throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
108                                 }
109                         }
110                         token = tokenizer.nextToken();
111                 }
112                 // token contains the last one
113                 return outDir.append(token).toString();
114         }
115
116         /**
117          * INTERNAL USE-ONLY
118          * Request the creation of a ClassFile compatible representation of a problematic type
119          *
120          * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
121          * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
122          */
123         public static void createProblemType(
124                 TypeDeclaration typeDeclaration,
125                 CompilationResult unitResult) {
126                 SourceTypeBinding typeBinding = typeDeclaration.binding;
127                 ClassFile classFile = new ClassFile(typeBinding, null, true);
128         
129                 // TODO (olivier) handle cases where a field cannot be generated (name too long)
130                 // TODO (olivier) handle too many methods
131                 // inner attributes
132                 if (typeBinding.isMemberType())
133                         classFile.recordEnclosingTypeAttributes(typeBinding);
134         
135                 // add its fields
136                 FieldBinding[] fields = typeBinding.fields;
137                 if ((fields != null) && (fields != NoFields)) {
138                         for (int i = 0, max = fields.length; i < max; i++) {
139                                 if (fields[i].constant() == null) {
140                                         FieldReference.getConstantFor(fields[i], null, false, null);
141                                 }
142                         }
143                         classFile.addFieldInfos();
144                 } else {
145                         // we have to set the number of fields to be equals to 0
146                         classFile.contents[classFile.contentsOffset++] = 0;
147                         classFile.contents[classFile.contentsOffset++] = 0;
148                 }
149                 // leave some space for the methodCount
150                 classFile.setForMethodInfos();
151                 // add its user defined methods
152                 MethodBinding[] methods = typeBinding.methods;
153                 AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
154                 int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
155                 int problemsLength;
156                 IProblem[] problems = unitResult.getErrors();
157                 if (problems == null) {
158                         problems = new IProblem[0];
159                 }
160                 IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
161                 System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
162                 if (methods != null) {
163                         if (typeBinding.isInterface()) {
164                                 // we cannot create problem methods for an interface. So we have to generate a clinit
165                                 // which should contain all the problem
166                                 classFile.addProblemClinit(problemsCopy);
167                                 for (int i = 0, max = methods.length; i < max; i++) {
168                                         MethodBinding methodBinding;
169                                         if ((methodBinding = methods[i]) != null) {
170                                                 // find the corresponding method declaration
171                                                 for (int j = 0; j < maxMethodDecl; j++) {
172                                                         if ((methodDeclarations[j] != null)
173                                                                 && (methodDeclarations[j].binding == methods[i])) {
174                                                                 if (!methodBinding.isConstructor()) {
175                                                                         classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
176                                                                 }
177                                                                 break;
178                                                         }
179                                                 }
180                                         }
181                                 }
182                         } else {
183                                 for (int i = 0, max = methods.length; i < max; i++) {
184                                         MethodBinding methodBinding;
185                                         if ((methodBinding = methods[i]) != null) {
186                                                 // find the corresponding method declaration
187                                                 for (int j = 0; j < maxMethodDecl; j++) {
188                                                         if ((methodDeclarations[j] != null)
189                                                                 && (methodDeclarations[j].binding == methods[i])) {
190                                                                 AbstractMethodDeclaration methodDecl;
191                                                                 if ((methodDecl = methodDeclarations[j]).isConstructor()) {
192                                                                         classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
193                                                                 } else {
194                                                                         classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
195                                                                 }
196                                                                 break;
197                                                         }
198                                                 }
199                                         }
200                                 }
201                         }
202                         // add abstract methods
203                         classFile.addDefaultAbstractMethods();
204                 }
205                 // propagate generation of (problem) member types
206                 if (typeDeclaration.memberTypes != null) {
207                         for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
208                                 TypeDeclaration memberType = typeDeclaration.memberTypes[i];
209                                 if (memberType.binding != null) {
210                                         classFile.recordNestedMemberAttribute(memberType.binding);
211                                         ClassFile.createProblemType(memberType, unitResult);
212                                 }
213                         }
214                 }
215                 classFile.addAttributes();
216                 unitResult.record(typeBinding.constantPoolName(), classFile);
217         }
218
219         /**
220          * INTERNAL USE-ONLY
221          * Search the line number corresponding to a specific position
222          */
223         public static final int searchLineNumber(
224                 int[] startLineIndexes,
225                 int position) {
226                 // this code is completely useless, but it is the same implementation than
227                 // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
228                 // if (startLineIndexes == null)
229                 //      return 1;
230                 int length = startLineIndexes.length;
231                 if (length == 0)
232                         return 1;
233                 int g = 0, d = length - 1;
234                 int m = 0;
235                 while (g <= d) {
236                         m = (g + d) / 2;
237                         if (position < startLineIndexes[m]) {
238                                 d = m - 1;
239                         } else
240                                 if (position > startLineIndexes[m]) {
241                                         g = m + 1;
242                                 } else {
243                                         return m + 1;
244                                 }
245                 }
246                 if (position < startLineIndexes[m]) {
247                         return m + 1;
248                 }
249                 return m + 2;
250         }
251
252         /**
253          * INTERNAL USE-ONLY
254          * outputPath is formed like:
255          *         c:\temp\ the last character is a file separator
256          * relativeFileName is formed like:
257          *     java\lang\String.class
258          * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
259          * @param outputPath the output directory
260          * @param relativeFileName java.lang.String
261          * @param contents byte[]
262          * 
263          */
264         public static void writeToDisk(
265                 boolean generatePackagesStructure,
266                 String outputPath,
267                 String relativeFileName,
268                 byte[] contents)
269                 throws IOException {
270                         
271                 BufferedOutputStream output = null;
272                 if (generatePackagesStructure) {
273                         output = new BufferedOutputStream(
274                                 new FileOutputStream(
275                                                 new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
276                 } else {
277                         String fileName = null;
278                         char fileSeparatorChar = File.separatorChar;
279                         String fileSeparator = File.separator;
280                         // First we ensure that the outputPath exists
281                         outputPath = outputPath.replace('/', fileSeparatorChar);
282                         // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
283                         int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
284                         if (indexOfPackageSeparator == -1) {
285                                 if (outputPath.endsWith(fileSeparator)) {
286                                         fileName = outputPath + relativeFileName;
287                                 } else {
288                                         fileName = outputPath + fileSeparator + relativeFileName;
289                                 }
290                         } else {
291                                 int length = relativeFileName.length();
292                                 if (outputPath.endsWith(fileSeparator)) {
293                                         fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
294                                 } else {
295                                         fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
296                                 }
297                         }
298                         output = new BufferedOutputStream(
299                                 new FileOutputStream(
300                                                 new File(fileName)));
301                 }
302                 try {
303                         output.write(contents);
304                 } finally {
305                         output.flush();
306                         output.close();
307                 }
308         }
309         public CodeStream codeStream;
310         public ConstantPool constantPool;
311         public int constantPoolOffset;
312         // the header contains all the bytes till the end of the constant pool
313         public byte[] contents;
314         public int contentsOffset;
315         protected boolean creatingProblemType;
316         public ClassFile enclosingClassFile;
317         public byte[] header;
318         // that collection contains all the remaining bytes of the .class file
319         public int headerOffset;
320         public ReferenceBinding[] innerClassesBindings;
321         public int methodCount;
322         public int methodCountOffset;
323         public int numberOfInnerClasses;
324         public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
325         // used to generate private access methods
326         public int produceDebugAttributes;
327         public SourceTypeBinding referenceBinding;
328         public long targetJDK;
329         
330         /**
331          * INTERNAL USE-ONLY
332          * This methods creates a new instance of the receiver.
333          */
334         public ClassFile() {
335                 // default constructor for subclasses
336         }
337
338         /**
339          * INTERNAL USE-ONLY
340          * This methods creates a new instance of the receiver.
341          *
342          * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
343          * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
344          * @param creatingProblemType <CODE>boolean</CODE>
345          */
346         public ClassFile(
347                 SourceTypeBinding aType,
348                 ClassFile enclosingClassFile,
349                 boolean creatingProblemType) {
350             
351                 this.referenceBinding = aType;
352                 initByteArrays();
353
354                 // generate the magic numbers inside the header
355                 header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
356                 header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
357                 header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
358                 header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
359                 
360                 final CompilerOptions options = aType.scope.environment().options;
361                 this.targetJDK = options.targetJDK;
362                 header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
363                 header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
364                 header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
365                 header[headerOffset++] = (byte) (this.targetJDK >> 16); // major low
366
367                 constantPoolOffset = headerOffset;
368                 headerOffset += 2;
369                 constantPool = new ConstantPool(this);
370                 
371                 // Modifier manipulations for classfile
372                 int accessFlags = aType.getAccessFlags();
373                 if (aType.isPrivate()) { // rewrite private to non-public
374                         accessFlags &= ~AccPublic;
375                 }
376                 if (aType.isProtected()) { // rewrite protected into public
377                         accessFlags |= AccPublic;
378                 }
379                 // clear all bits that are illegal for a class or an interface
380                 accessFlags
381                         &= ~(
382                                 AccStrictfp
383                                         | AccProtected
384                                         | AccPrivate
385                                         | AccStatic
386                                         | AccSynchronized
387                                         | AccNative);
388                                         
389                 // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
390                 if (aType.isClass()) {
391                         accessFlags |= AccSuper;
392                 }
393                 
394                 this.enclosingClassFile = enclosingClassFile;
395                 // innerclasses get their names computed at code gen time
396
397                 // now we continue to generate the bytes inside the contents array
398                 contents[contentsOffset++] = (byte) (accessFlags >> 8);
399                 contents[contentsOffset++] = (byte) accessFlags;
400                 int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName());
401                 contents[contentsOffset++] = (byte) (classNameIndex >> 8);
402                 contents[contentsOffset++] = (byte) classNameIndex;
403                 int superclassNameIndex;
404                 if (aType.isInterface()) {
405                         superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
406                 } else {
407                         superclassNameIndex =
408                                 (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName()));
409                 }
410                 contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
411                 contents[contentsOffset++] = (byte) superclassNameIndex;
412                 ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
413                 int interfacesCount = superInterfacesBinding.length;
414                 contents[contentsOffset++] = (byte) (interfacesCount >> 8);
415                 contents[contentsOffset++] = (byte) interfacesCount;
416                 for (int i = 0; i < interfacesCount; i++) {
417                         int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
418                         contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
419                         contents[contentsOffset++] = (byte) interfaceIndex;
420                 }
421                 produceDebugAttributes = options.produceDebugAttributes;
422                 innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
423                 this.creatingProblemType = creatingProblemType;
424                 codeStream = new CodeStream(this, this.targetJDK);
425
426                 // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
427                 // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
428                 ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
429                 if (this == outermostClassFile) {
430                         codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
431                 } else {
432                         codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
433                 }
434         }
435
436         /**
437          * INTERNAL USE-ONLY
438          * Generate the byte for a problem method info that correspond to a boggus method.
439          *
440          * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
441          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
442          */
443         public void addAbstractMethod(
444                 AbstractMethodDeclaration method,
445                 MethodBinding methodBinding) {
446
447                 // force the modifiers to be public and abstract
448                 methodBinding.modifiers = AccPublic | AccAbstract;
449
450                 this.generateMethodInfoHeader(methodBinding);
451                 int methodAttributeOffset = this.contentsOffset;
452                 int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
453                 this.completeMethodInfo(methodAttributeOffset, attributeNumber);
454         }
455
456         /**
457          * INTERNAL USE-ONLY
458          * This methods generate all the attributes for the receiver.
459          * For a class they could be:
460          * - source file attribute
461          * - inner classes attribute
462          * - deprecated attribute
463          */
464         public void addAttributes() {
465                 // update the method count
466                 contents[methodCountOffset++] = (byte) (methodCount >> 8);
467                 contents[methodCountOffset] = (byte) methodCount;
468
469                 int attributeNumber = 0;
470                 // leave two bytes for the number of attributes and store the current offset
471                 int attributeOffset = contentsOffset;
472                 contentsOffset += 2;
473
474                 // source attribute
475                 if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
476                         String fullFileName =
477                                 new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
478                         fullFileName = fullFileName.replace('\\', '/');
479                         int lastIndex = fullFileName.lastIndexOf('/');
480                         if (lastIndex != -1) {
481                                 fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
482                         }
483                         // check that there is enough space to write all the bytes for the field info corresponding
484                         // to the @fieldBinding
485                         if (contentsOffset + 8 >= contents.length) {
486                                 resizeContents(8);
487                         }
488                         int sourceAttributeNameIndex =
489                                 constantPool.literalIndex(AttributeNamesConstants.SourceName);
490                         contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
491                         contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
492                         // The length of a source file attribute is 2. This is a fixed-length
493                         // attribute
494                         contents[contentsOffset++] = 0;
495                         contents[contentsOffset++] = 0;
496                         contents[contentsOffset++] = 0;
497                         contents[contentsOffset++] = 2;
498                         // write the source file name
499                         int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
500                         contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
501                         contents[contentsOffset++] = (byte) fileNameIndex;
502                         attributeNumber++;
503                 }
504                 // Deprecated attribute
505                 if (referenceBinding.isDeprecated()) {
506                         // check that there is enough space to write all the bytes for the field info corresponding
507                         // to the @fieldBinding
508                         if (contentsOffset + 6 >= contents.length) {
509                                 resizeContents(6);
510                         }
511                         int deprecatedAttributeNameIndex =
512                                 constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
513                         contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
514                         contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
515                         // the length of a deprecated attribute is equals to 0
516                         contents[contentsOffset++] = 0;
517                         contents[contentsOffset++] = 0;
518                         contents[contentsOffset++] = 0;
519                         contents[contentsOffset++] = 0;
520                         attributeNumber++;
521                 }
522                 // Inner class attribute
523                 if (numberOfInnerClasses != 0) {
524                         // Generate the inner class attribute
525                         int exSize = 8 * numberOfInnerClasses + 8;
526                         if (exSize + contentsOffset >= this.contents.length) {
527                                 resizeContents(exSize);
528                         }
529                         // Now we now the size of the attribute and the number of entries
530                         // attribute name
531                         int attributeNameIndex =
532                                 constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
533                         contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
534                         contents[contentsOffset++] = (byte) attributeNameIndex;
535                         int value = (numberOfInnerClasses << 3) + 2;
536                         contents[contentsOffset++] = (byte) (value >> 24);
537                         contents[contentsOffset++] = (byte) (value >> 16);
538                         contents[contentsOffset++] = (byte) (value >> 8);
539                         contents[contentsOffset++] = (byte) value;
540                         contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
541                         contents[contentsOffset++] = (byte) numberOfInnerClasses;
542                         for (int i = 0; i < numberOfInnerClasses; i++) {
543                                 ReferenceBinding innerClass = innerClassesBindings[i];
544                                 int accessFlags = innerClass.getAccessFlags();
545                                 int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
546                                 // inner class index
547                                 contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
548                                 contents[contentsOffset++] = (byte) innerClassIndex;
549                                 // outer class index: anonymous and local have no outer class index
550                                 if (innerClass.isMemberType()) {
551                                         // member or member of local
552                                         int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
553                                         contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
554                                         contents[contentsOffset++] = (byte) outerClassIndex;
555                                 } else {
556                                         // equals to 0 if the innerClass is not a member type
557                                         contents[contentsOffset++] = 0;
558                                         contents[contentsOffset++] = 0;
559                                 }
560                                 // name index
561                                 if (!innerClass.isAnonymousType()) {
562                                         int nameIndex = constantPool.literalIndex(innerClass.sourceName());
563                                         contents[contentsOffset++] = (byte) (nameIndex >> 8);
564                                         contents[contentsOffset++] = (byte) nameIndex;
565                                 } else {
566                                         // equals to 0 if the innerClass is an anonymous type
567                                         contents[contentsOffset++] = 0;
568                                         contents[contentsOffset++] = 0;
569                                 }
570                                 // access flag
571                                 if (innerClass.isAnonymousType()) {
572                                         accessFlags |= AccPrivate;
573                                 } else if (innerClass.isLocalType() && !innerClass.isMemberType()) {
574                                         accessFlags |= AccPrivate;
575                                 } else if (innerClass.isMemberType() && (innerClass.isInterface() || innerClass.isAnnotationType())) {
576                                         accessFlags |= AccStatic; // implicitely static
577                                 }
578                                 contents[contentsOffset++] = (byte) (accessFlags >> 8);
579                                 contents[contentsOffset++] = (byte) accessFlags;
580                         }
581                         attributeNumber++;
582                 }
583                 // add signature attribute
584                 char[] genericSignature = referenceBinding.genericSignature();
585                 if (genericSignature != null) {
586                         // check that there is enough space to write all the bytes for the field info corresponding
587                         // to the @fieldBinding
588                         if (contentsOffset + 8 >= contents.length) {
589                                 resizeContents(8);
590                         }
591                         int signatureAttributeNameIndex =
592                                 constantPool.literalIndex(AttributeNamesConstants.SignatureName);
593                         contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
594                         contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
595                         // the length of a signature attribute is equals to 2
596                         contents[contentsOffset++] = 0;
597                         contents[contentsOffset++] = 0;
598                         contents[contentsOffset++] = 0;
599                         contents[contentsOffset++] = 2;
600                         int signatureIndex =
601                                 constantPool.literalIndex(genericSignature);
602                         contents[contentsOffset++] = (byte) (signatureIndex >> 8);
603                         contents[contentsOffset++] = (byte) signatureIndex;
604                         attributeNumber++;
605                 }
606                 if (targetJDK >= ClassFileConstants.JDK1_5
607                                 && (this.referenceBinding.isAnonymousType() || this.referenceBinding.isLocalType())) {
608                         // add enclosing method attribute (1.5 mode only)
609                         if (contentsOffset + 10 >= contents.length) {
610                                 resizeContents(10);
611                         }
612                         int enclosingMethodAttributeNameIndex =
613                                 constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
614                         contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
615                         contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
616                         // the length of a signature attribute is equals to 2
617                         contents[contentsOffset++] = 0;
618                         contents[contentsOffset++] = 0;
619                         contents[contentsOffset++] = 0;
620                         contents[contentsOffset++] = 4;
621                         
622                         int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
623                         contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
624                         contents[contentsOffset++] = (byte) enclosingTypeIndex;
625                         byte methodIndexByte1 = 0;
626                         byte methodIndexByte2 = 0;
627                         if (this.referenceBinding.scope != null) {
628                                 MethodScope methodScope = this.referenceBinding.scope.methodScope();
629                                 if (methodScope != null) {
630                                         ReferenceContext referenceContext = methodScope.referenceContext;
631                                         if (referenceContext instanceof AbstractMethodDeclaration) {
632                                                 AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
633                                                 MethodBinding methodBinding = methodDeclaration.binding;
634                                                 int enclosingMethodIndex = constantPool.literalIndexForMethod(methodBinding.selector, methodBinding.signature());
635                                                 methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
636                                                 methodIndexByte2 = (byte) enclosingMethodIndex;
637                                         }
638                                 }
639                         }
640                         contents[contentsOffset++] = methodIndexByte1;
641                         contents[contentsOffset++] = methodIndexByte2;
642                         attributeNumber++;                      
643                 }
644                 if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
645                         TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
646                         if (typeDeclaration != null) {
647                                 final Annotation[] annotations = typeDeclaration.annotations;
648                                 if (annotations != null) {
649                                         attributeNumber += generateRuntimeAnnotations(annotations);
650                                 }
651                         }
652                 }
653                 // update the number of attributes
654                 if (attributeOffset + 2 >= this.contents.length) {
655                         resizeContents(2);
656                 }
657                 contents[attributeOffset++] = (byte) (attributeNumber >> 8);
658                 contents[attributeOffset] = (byte) attributeNumber;
659
660                 // resynchronize all offsets of the classfile
661                 header = constantPool.poolContent;
662                 headerOffset = constantPool.currentOffset;
663                 int constantPoolCount = constantPool.currentIndex;
664                 header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
665                 header[constantPoolOffset] = (byte) constantPoolCount;
666         }
667         
668         /**
669          * INTERNAL USE-ONLY
670          * This methods generate all the default abstract method infos that correpond to
671          * the abstract methods inherited from superinterfaces.
672          */
673         public void addDefaultAbstractMethods() { // default abstract methods
674                 MethodBinding[] defaultAbstractMethods =
675                         referenceBinding.getDefaultAbstractMethods();
676                 for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
677                         generateMethodInfoHeader(defaultAbstractMethods[i]);
678                         int methodAttributeOffset = contentsOffset;
679                         int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
680                         completeMethodInfo(methodAttributeOffset, attributeNumber);
681                 }
682         }
683
684         private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
685                 int attributesNumber = 0;
686                 // 4.7.2 only static constant fields get a ConstantAttribute
687                 // Generate the constantValueAttribute
688                 if (fieldBinding.isConstantValue()){
689                         if (contentsOffset + 8 >= contents.length) {
690                                 resizeContents(8);
691                         }
692                         // Now we generate the constant attribute corresponding to the fieldBinding
693                         int constantValueNameIndex =
694                                 constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
695                         contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
696                         contents[contentsOffset++] = (byte) constantValueNameIndex;
697                         // The attribute length = 2 in case of a constantValue attribute
698                         contents[contentsOffset++] = 0;
699                         contents[contentsOffset++] = 0;
700                         contents[contentsOffset++] = 0;
701                         contents[contentsOffset++] = 2;
702                         attributesNumber++;
703                         // Need to add the constant_value_index
704                         Constant fieldConstant = fieldBinding.constant();
705                         switch (fieldConstant.typeID()) {
706                                 case T_boolean :
707                                         int booleanValueIndex =
708                                                 constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
709                                         contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
710                                         contents[contentsOffset++] = (byte) booleanValueIndex;
711                                         break;
712                                 case T_byte :
713                                 case T_char :
714                                 case T_int :
715                                 case T_short :
716                                         int integerValueIndex =
717                                                 constantPool.literalIndex(fieldConstant.intValue());
718                                         contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
719                                         contents[contentsOffset++] = (byte) integerValueIndex;
720                                         break;
721                                 case T_float :
722                                         int floatValueIndex =
723                                                 constantPool.literalIndex(fieldConstant.floatValue());
724                                         contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
725                                         contents[contentsOffset++] = (byte) floatValueIndex;
726                                         break;
727                                 case T_double :
728                                         int doubleValueIndex =
729                                                 constantPool.literalIndex(fieldConstant.doubleValue());
730                                         contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
731                                         contents[contentsOffset++] = (byte) doubleValueIndex;
732                                         break;
733                                 case T_long :
734                                         int longValueIndex =
735                                                 constantPool.literalIndex(fieldConstant.longValue());
736                                         contents[contentsOffset++] = (byte) (longValueIndex >> 8);
737                                         contents[contentsOffset++] = (byte) longValueIndex;
738                                         break;
739                                 case T_JavaLangString :
740                                         int stringValueIndex =
741                                                 constantPool.literalIndex(
742                                                         ((StringConstant) fieldConstant).stringValue());
743                                         if (stringValueIndex == -1) {
744                                                 if (!creatingProblemType) {
745                                                         // report an error and abort: will lead to a problem type classfile creation
746                                                         TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
747                                                         FieldDeclaration[] fieldDecls = typeDeclaration.fields;
748                                                         for (int i = 0, max = fieldDecls.length; i < max; i++) {
749                                                                 if (fieldDecls[i].binding == fieldBinding) {
750                                                                         // problem should abort
751                                                                         typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
752                                                                                 fieldDecls[i]);
753                                                                 }
754                                                         }
755                                                 } else {
756                                                         // already inside a problem type creation : no constant for this field
757                                                         contentsOffset = fieldAttributeOffset;
758                                                 }
759                                         } else {
760                                                 contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
761                                                 contents[contentsOffset++] = (byte) stringValueIndex;
762                                         }
763                         }
764                 }
765                 if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
766                         if (contentsOffset + 6 >= contents.length) {
767                                 resizeContents(6);
768                         }
769                         int syntheticAttributeNameIndex =
770                                 constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
771                         contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
772                         contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
773                         // the length of a synthetic attribute is equals to 0
774                         contents[contentsOffset++] = 0;
775                         contents[contentsOffset++] = 0;
776                         contents[contentsOffset++] = 0;
777                         contents[contentsOffset++] = 0;
778                         attributesNumber++;
779                 }
780                 if (fieldBinding.isDeprecated()) {
781                         if (contentsOffset + 6 >= contents.length) {
782                                 resizeContents(6);
783                         }
784                         int deprecatedAttributeNameIndex =
785                                 constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
786                         contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
787                         contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
788                         // the length of a deprecated attribute is equals to 0
789                         contents[contentsOffset++] = 0;
790                         contents[contentsOffset++] = 0;
791                         contents[contentsOffset++] = 0;
792                         contents[contentsOffset++] = 0;
793                         attributesNumber++;
794                 }
795                 // add signature attribute
796                 char[] genericSignature = fieldBinding.genericSignature();
797                 if (genericSignature != null) {
798                         // check that there is enough space to write all the bytes for the field info corresponding
799                         // to the @fieldBinding
800                         if (contentsOffset + 8 >= contents.length) {
801                                 resizeContents(8);
802                         }
803                         int signatureAttributeNameIndex =
804                                 constantPool.literalIndex(AttributeNamesConstants.SignatureName);
805                         contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
806                         contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
807                         // the length of a signature attribute is equals to 2
808                         contents[contentsOffset++] = 0;
809                         contents[contentsOffset++] = 0;
810                         contents[contentsOffset++] = 0;
811                         contents[contentsOffset++] = 2;
812                         int signatureIndex =
813                                 constantPool.literalIndex(genericSignature);
814                         contents[contentsOffset++] = (byte) (signatureIndex >> 8);
815                         contents[contentsOffset++] = (byte) signatureIndex;
816                         attributesNumber++;
817                 }
818                 if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
819                         FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
820                         if (fieldDeclaration != null) {
821                                 Annotation[] annotations = fieldDeclaration.annotations;
822                                 if (annotations != null) {
823                                         attributesNumber += generateRuntimeAnnotations(annotations);
824                                 }
825                         }
826                 }
827                 return attributesNumber;
828         }
829         /**
830          * INTERNAL USE-ONLY
831          * This methods generates the bytes for the given field binding
832          * @param fieldBinding the given field binding
833          */
834         private void addFieldInfo(FieldBinding fieldBinding) {
835                 // check that there is enough space to write all the bytes for the field info corresponding
836                 // to the @fieldBinding
837                 if (contentsOffset + 8 >= contents.length) {
838                         resizeContents(8);
839                 }
840                 // Now we can generate all entries into the byte array
841                 // First the accessFlags
842                 int accessFlags = fieldBinding.getAccessFlags();
843                 if (targetJDK < ClassFileConstants.JDK1_5) {
844                     // pre 1.5, synthetic was an attribute, not a modifier
845                     accessFlags &= ~AccSynthetic;
846                 }               
847                 contents[contentsOffset++] = (byte) (accessFlags >> 8);
848                 contents[contentsOffset++] = (byte) accessFlags;
849                 // Then the nameIndex
850                 int nameIndex = constantPool.literalIndex(fieldBinding.name);
851                 contents[contentsOffset++] = (byte) (nameIndex >> 8);
852                 contents[contentsOffset++] = (byte) nameIndex;
853                 // Then the descriptorIndex
854                 int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
855                 contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
856                 contents[contentsOffset++] = (byte) descriptorIndex;
857                 int fieldAttributeOffset = contentsOffset;
858                 int attributeNumber = 0;
859                 // leave some space for the number of attributes
860                 contentsOffset += 2;
861                 attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
862                 contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
863                 contents[fieldAttributeOffset] = (byte) attributeNumber;
864         }
865
866         /**
867          * INTERNAL USE-ONLY
868          * This methods generate all the fields infos for the receiver.
869          * This includes:
870          * - a field info for each defined field of that class
871          * - a field info for each synthetic field (e.g. this$0)
872          */
873         /**
874          * INTERNAL USE-ONLY
875          * This methods generate all the fields infos for the receiver.
876          * This includes:
877          * - a field info for each defined field of that class
878          * - a field info for each synthetic field (e.g. this$0)
879          */
880         public void addFieldInfos() {
881                 SourceTypeBinding currentBinding = referenceBinding;
882                 FieldBinding[] syntheticFields = currentBinding.syntheticFields();
883                 int fieldCount =
884                         currentBinding.fieldCount()
885                                 + (syntheticFields == null ? 0 : syntheticFields.length);
886
887                 // write the number of fields
888                 if (fieldCount > 0xFFFF) {
889                         referenceBinding.scope.problemReporter().tooManyFields(referenceBinding.scope.referenceType());
890                 }
891                 contents[contentsOffset++] = (byte) (fieldCount >> 8);
892                 contents[contentsOffset++] = (byte) fieldCount;
893
894                 FieldBinding[] fieldBindings = currentBinding.fields();
895                 for (int i = 0, max = fieldBindings.length; i < max; i++) {
896                         addFieldInfo(fieldBindings[i]);
897                 }
898                 if (syntheticFields != null) {
899                         for (int i = 0, max = syntheticFields.length; i < max; i++) {
900                                 addFieldInfo(syntheticFields[i]);
901                         }
902                 }
903         }
904
905         /**
906          * INTERNAL USE-ONLY
907          * This methods stores the bindings for each inner class. They will be used to know which entries
908          * have to be generated for the inner classes attributes.
909          * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
910          */
911         private void addInnerClasses(ReferenceBinding refBinding) {
912                 // check first if that reference binding is there
913                 for (int i = 0; i < numberOfInnerClasses; i++) {
914                         if (innerClassesBindings[i] == refBinding)
915                                 return;
916                 }
917                 int length = innerClassesBindings.length;
918                 if (numberOfInnerClasses == length) {
919                         System.arraycopy(
920                                 innerClassesBindings,
921                                 0,
922                                 innerClassesBindings = new ReferenceBinding[length * 2],
923                                 0,
924                                 length);
925                 }
926                 innerClassesBindings[numberOfInnerClasses++] = refBinding;
927         }
928         
929         private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
930                 // always clear the strictfp/native/abstract bit for a problem method
931                 generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
932                 int methodAttributeOffset = contentsOffset;
933                 int attributeNumber = generateMethodInfoAttribute(methodBinding);
934                 
935                 // Code attribute
936                 attributeNumber++;
937                 
938                 int codeAttributeOffset = contentsOffset;
939                 generateCodeAttributeHeader();
940                 StringBuffer buffer = new StringBuffer(25);
941                 buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
942                 buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
943                 String problemString = buffer.toString();
944                 
945                 codeStream.init(this);
946                 codeStream.preserveUnusedLocals = true;
947                 codeStream.initializeMaxLocals(methodBinding);
948
949                 // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
950                 codeStream.generateCodeAttributeForProblemMethod(problemString);
951                                 
952                 completeCodeAttributeForMissingAbstractProblemMethod(
953                         methodBinding,
954                         codeAttributeOffset,
955                         compilationResult.lineSeparatorPositions,
956                         problem.getSourceLineNumber());
957                         
958                 completeMethodInfo(methodAttributeOffset, attributeNumber);
959         }
960
961         /**
962          * INTERNAL USE-ONLY
963          * Generate the byte for a problem clinit method info that correspond to a boggus method.
964          *
965          * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
966          */
967         public void addProblemClinit(IProblem[] problems) {
968                 generateMethodInfoHeaderForClinit();
969                 // leave two spaces for the number of attributes
970                 contentsOffset -= 2;
971                 int attributeOffset = contentsOffset;
972                 contentsOffset += 2;
973                 int attributeNumber = 0;
974
975                 int codeAttributeOffset = contentsOffset;
976                 generateCodeAttributeHeader();
977                 codeStream.resetForProblemClinit(this);
978                 String problemString = "" ; //$NON-NLS-1$
979                 int problemLine = 0;
980                 if (problems != null) {
981                         int max = problems.length;
982                         StringBuffer buffer = new StringBuffer(25);
983                         int count = 0;
984                         for (int i = 0; i < max; i++) {
985                                 IProblem problem = problems[i];
986                                 if ((problem != null) && (problem.isError())) {
987                                         buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
988                                         count++;
989                                         if (problemLine == 0) {
990                                                 problemLine = problem.getSourceLineNumber();
991                                         }
992                                         problems[i] = null;
993                                 }
994                         } // insert the top line afterwards, once knowing how many problems we have to consider
995                         if (count > 1) {
996                                 buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
997                         } else {
998                                 buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
999                         }
1000                         problemString = buffer.toString();
1001                 }
1002
1003                 // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1004                 codeStream.generateCodeAttributeForProblemMethod(problemString);
1005                 attributeNumber++; // code attribute
1006                 completeCodeAttributeForClinit(
1007                         codeAttributeOffset,
1008                         referenceBinding
1009                                 .scope
1010                                 .referenceCompilationUnit()
1011                                 .compilationResult
1012                                 .lineSeparatorPositions,
1013                         problemLine);
1014                 contents[attributeOffset++] = (byte) (attributeNumber >> 8);
1015                 contents[attributeOffset] = (byte) attributeNumber;
1016         }
1017
1018         /**
1019          * INTERNAL USE-ONLY
1020          * Generate the byte for a problem method info that correspond to a boggus constructor.
1021          *
1022          * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1023          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1024          * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1025          */
1026         public void addProblemConstructor(
1027                 AbstractMethodDeclaration method,
1028                 MethodBinding methodBinding,
1029                 IProblem[] problems) {
1030
1031                 // always clear the strictfp/native/abstract bit for a problem method
1032                 generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
1033                 int methodAttributeOffset = contentsOffset;
1034                 int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
1035                 
1036                 // Code attribute
1037                 attributeNumber++;
1038                 int codeAttributeOffset = contentsOffset;
1039                 generateCodeAttributeHeader();
1040                 codeStream.reset(method, this);
1041                 String problemString = "" ; //$NON-NLS-1$
1042                 int problemLine = 0;
1043                 if (problems != null) {
1044                         int max = problems.length;
1045                         StringBuffer buffer = new StringBuffer(25);
1046                         int count = 0;
1047                         for (int i = 0; i < max; i++) {
1048                                 IProblem problem = problems[i];
1049                                 if ((problem != null) && (problem.isError())) {
1050                                         buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
1051                                         count++;
1052                                         if (problemLine == 0) {
1053                                                 problemLine = problem.getSourceLineNumber();
1054                                         }
1055                                 }
1056                         } // insert the top line afterwards, once knowing how many problems we have to consider
1057                         if (count > 1) {
1058                                 buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
1059                         } else {
1060                                 buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
1061                         }
1062                         problemString = buffer.toString();
1063                 }
1064
1065                 // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1066                 codeStream.generateCodeAttributeForProblemMethod(problemString);
1067                 completeCodeAttributeForProblemMethod(
1068                         method,
1069                         methodBinding,
1070                         codeAttributeOffset,
1071                         ((SourceTypeBinding) methodBinding.declaringClass)
1072                                 .scope
1073                                 .referenceCompilationUnit()
1074                                 .compilationResult
1075                                 .lineSeparatorPositions,
1076                         problemLine);
1077                 completeMethodInfo(methodAttributeOffset, attributeNumber);
1078         }
1079
1080         /**
1081          * INTERNAL USE-ONLY
1082          * Generate the byte for a problem method info that correspond to a boggus constructor.
1083          * Reset the position inside the contents byte array to the savedOffset.
1084          *
1085          * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1086          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1087          * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1088          * @param savedOffset <CODE>int</CODE>
1089          */
1090         public void addProblemConstructor(
1091                 AbstractMethodDeclaration method,
1092                 MethodBinding methodBinding,
1093                 IProblem[] problems,
1094                 int savedOffset) {
1095                 // we need to move back the contentsOffset to the value at the beginning of the method
1096                 contentsOffset = savedOffset;
1097                 methodCount--; // we need to remove the method that causes the problem
1098                 addProblemConstructor(method, methodBinding, problems);
1099         }
1100
1101         /**
1102          * INTERNAL USE-ONLY
1103          * Generate the byte for a problem method info that correspond to a boggus method.
1104          *
1105          * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1106          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1107          * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1108          */
1109         public void addProblemMethod(
1110                 AbstractMethodDeclaration method,
1111                 MethodBinding methodBinding,
1112                 IProblem[] problems) {
1113                 if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
1114                         method.abort(ProblemSeverities.AbortType, null);
1115                 }
1116                 // always clear the strictfp/native/abstract bit for a problem method
1117                 generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
1118                 int methodAttributeOffset = contentsOffset;
1119                 int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
1120                 
1121                 // Code attribute
1122                 attributeNumber++;
1123                 
1124                 int codeAttributeOffset = contentsOffset;
1125                 generateCodeAttributeHeader();
1126                 codeStream.reset(method, this);
1127                 String problemString = "" ; //$NON-NLS-1$
1128                 int problemLine = 0;
1129                 if (problems != null) {
1130                         int max = problems.length;
1131                         StringBuffer buffer = new StringBuffer(25);
1132                         int count = 0;
1133                         for (int i = 0; i < max; i++) {
1134                                 IProblem problem = problems[i];
1135                                 if ((problem != null)
1136                                         && (problem.isError())
1137                                         && (problem.getSourceStart() >= method.declarationSourceStart)
1138                                         && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
1139                                         buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
1140                                         count++;
1141                                         if (problemLine == 0) {
1142                                                 problemLine = problem.getSourceLineNumber();
1143                                         }
1144                                         problems[i] = null;
1145                                 }
1146                         } // insert the top line afterwards, once knowing how many problems we have to consider
1147                         if (count > 1) {
1148                                 buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
1149                         } else {
1150                                 buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
1151                         }
1152                         problemString = buffer.toString();
1153                 }
1154
1155                 // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1156                 codeStream.generateCodeAttributeForProblemMethod(problemString);
1157                 completeCodeAttributeForProblemMethod(
1158                         method,
1159                         methodBinding,
1160                         codeAttributeOffset,
1161                         ((SourceTypeBinding) methodBinding.declaringClass)
1162                                 .scope
1163                                 .referenceCompilationUnit()
1164                                 .compilationResult
1165                                 .lineSeparatorPositions,
1166                         problemLine);
1167                 completeMethodInfo(methodAttributeOffset, attributeNumber);
1168         }
1169
1170         /**
1171          * INTERNAL USE-ONLY
1172          * Generate the byte for a problem method info that correspond to a boggus method.
1173          * Reset the position inside the contents byte array to the savedOffset.
1174          *
1175          * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1176          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1177          * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1178          * @param savedOffset <CODE>int</CODE>
1179          */
1180         public void addProblemMethod(
1181                 AbstractMethodDeclaration method,
1182                 MethodBinding methodBinding,
1183                 IProblem[] problems,
1184                 int savedOffset) {
1185                 // we need to move back the contentsOffset to the value at the beginning of the method
1186                 contentsOffset = savedOffset;
1187                 methodCount--; // we need to remove the method that causes the problem
1188                 addProblemMethod(method, methodBinding, problems);
1189         }
1190
1191         /**
1192          * INTERNAL USE-ONLY
1193          * Generate the byte for all the special method infos.
1194          * They are:
1195          * - synthetic access methods
1196          * - default abstract methods
1197          */
1198         public void addSpecialMethods() {
1199             
1200                 // add all methods (default abstract methods and synthetic)
1201
1202                 // default abstract methods
1203                 generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);
1204
1205                 MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
1206                 for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
1207                         generateMethodInfoHeader(defaultAbstractMethods[i]);
1208                         int methodAttributeOffset = contentsOffset;
1209                         int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
1210                         completeMethodInfo(methodAttributeOffset, attributeNumber);
1211                 }
1212                 // add synthetic methods infos
1213                 SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
1214                 if (syntheticMethods != null) {
1215                         for (int i = 0, max = syntheticMethods.length; i < max; i++) {
1216                                 SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
1217                                 switch (syntheticMethod.kind) {
1218                                         case SyntheticMethodBinding.FieldReadAccess :
1219                                                 // generate a method info to emulate an reading access to
1220                                                 // a non-accessible field
1221                                                 addSyntheticFieldReadAccessMethod(syntheticMethod);
1222                                                 break;
1223                                         case SyntheticMethodBinding.FieldWriteAccess :
1224                                                 // generate a method info to emulate an writing access to
1225                                                 // a non-accessible field
1226                                                 addSyntheticFieldWriteAccessMethod(syntheticMethod);
1227                                                 break;
1228                                         case SyntheticMethodBinding.MethodAccess :
1229                                         case SyntheticMethodBinding.SuperMethodAccess :
1230                                         case SyntheticMethodBinding.BridgeMethod :
1231                                                 // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
1232                                                 addSyntheticMethodAccessMethod(syntheticMethod);
1233                                                 break;
1234                                         case SyntheticMethodBinding.ConstructorAccess :
1235                                                 // generate a method info to emulate an access to a non-accessible constructor
1236                                                 addSyntheticConstructorAccessMethod(syntheticMethod);
1237                                                 break;
1238                                         case SyntheticMethodBinding.EnumValues :
1239                                                 // generate a method info to define <enum>#values()
1240                                                 addSyntheticEnumValuesMethod(syntheticMethod);
1241                                                 break;
1242                                         case SyntheticMethodBinding.EnumValueOf :
1243                                                 // generate a method info to define <enum>#valueOf(String)
1244                                                 addSyntheticEnumValueOfMethod(syntheticMethod);
1245                                                 break;
1246                                 }
1247                         }
1248                 }
1249         }
1250                 
1251         /**
1252          * INTERNAL USE-ONLY
1253          * Generate the bytes for a synthetic method that provides an access to a private constructor.
1254          *
1255          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1256          */
1257         public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
1258                 generateMethodInfoHeader(methodBinding);
1259                 // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
1260                 contents[contentsOffset++] = 0;
1261                 contents[contentsOffset++] = 2;
1262                 // Code attribute
1263                 int codeAttributeOffset = contentsOffset;
1264                 generateCodeAttributeHeader();
1265                 codeStream.init(this);
1266                 codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
1267                 completeCodeAttributeForSyntheticMethod(
1268                         methodBinding,
1269                         codeAttributeOffset,
1270                         ((SourceTypeBinding) methodBinding.declaringClass)
1271                                 .scope
1272                                 .referenceCompilationUnit()
1273                                 .compilationResult
1274                                 .lineSeparatorPositions);
1275                 // add the synthetic attribute
1276                 int syntheticAttributeNameIndex =
1277                         constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1278                 contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1279                 contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1280                 // the length of a synthetic attribute is equals to 0
1281                 contents[contentsOffset++] = 0;
1282                 contents[contentsOffset++] = 0;
1283                 contents[contentsOffset++] = 0;
1284                 contents[contentsOffset++] = 0;
1285         }
1286
1287         /**
1288          * INTERNAL USE-ONLY
1289          *  Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
1290          *
1291          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1292          */     
1293         public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
1294
1295                 generateMethodInfoHeader(methodBinding);
1296                 // We know that we won't get more than 1 attribute: the code attribute 
1297                 contents[contentsOffset++] = 0;
1298                 contents[contentsOffset++] = 1;
1299                 // Code attribute
1300                 int codeAttributeOffset = contentsOffset;
1301                 generateCodeAttributeHeader();
1302                 codeStream.init(this);
1303                 codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
1304                 completeCodeAttributeForSyntheticMethod(
1305                         methodBinding,
1306                         codeAttributeOffset,
1307                         ((SourceTypeBinding) methodBinding.declaringClass)
1308                                 .scope
1309                                 .referenceCompilationUnit()
1310                                 .compilationResult
1311                                 .lineSeparatorPositions);
1312 //              // add the synthetic attribute
1313 //              int syntheticAttributeNameIndex =
1314 //                      constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1315 //              contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1316 //              contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1317 //              // the length of a synthetic attribute is equals to 0
1318 //              contents[contentsOffset++] = 0;
1319 //              contents[contentsOffset++] = 0;
1320 //              contents[contentsOffset++] = 0;
1321 //              contents[contentsOffset++] = 0;
1322                         
1323         }
1324
1325         /**
1326          * INTERNAL USE-ONLY
1327          *  Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
1328          *
1329          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1330          */     
1331         public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
1332
1333                 generateMethodInfoHeader(methodBinding);
1334                 // We know that we won't get more than 1 attribute: the code attribute 
1335                 contents[contentsOffset++] = 0;
1336                 contents[contentsOffset++] = 1;
1337                 // Code attribute
1338                 int codeAttributeOffset = contentsOffset;
1339                 generateCodeAttributeHeader();
1340                 codeStream.init(this);
1341                 codeStream.generateSyntheticBodyForEnumValues(methodBinding);
1342                 completeCodeAttributeForSyntheticMethod(
1343                         methodBinding,
1344                         codeAttributeOffset,
1345                         ((SourceTypeBinding) methodBinding.declaringClass)
1346                                 .scope
1347                                 .referenceCompilationUnit()
1348                                 .compilationResult
1349                                 .lineSeparatorPositions);
1350 //              // add the synthetic attribute
1351 //              int syntheticAttributeNameIndex =
1352 //                      constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1353 //              contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1354 //              contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1355 //              // the length of a synthetic attribute is equals to 0
1356 //              contents[contentsOffset++] = 0;
1357 //              contents[contentsOffset++] = 0;
1358 //              contents[contentsOffset++] = 0;
1359 //              contents[contentsOffset++] = 0;
1360                         
1361         }
1362
1363         /**
1364          * INTERNAL USE-ONLY
1365          * Generate the byte for a problem method info that correspond to a synthetic method that
1366          * generate an read access to a private field.
1367          *
1368          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1369          */
1370         public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
1371                 generateMethodInfoHeader(methodBinding);
1372                 // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
1373                 contents[contentsOffset++] = 0;
1374                 contents[contentsOffset++] = 2;
1375                 // Code attribute
1376                 int codeAttributeOffset = contentsOffset;
1377                 generateCodeAttributeHeader();
1378                 codeStream.init(this);
1379                 codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
1380                 completeCodeAttributeForSyntheticMethod(
1381                         methodBinding,
1382                         codeAttributeOffset,
1383                         ((SourceTypeBinding) methodBinding.declaringClass)
1384                                 .scope
1385                                 .referenceCompilationUnit()
1386                                 .compilationResult
1387                                 .lineSeparatorPositions);
1388                 // add the synthetic attribute
1389                 int syntheticAttributeNameIndex =
1390                         constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1391                 contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1392                 contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1393                 // the length of a synthetic attribute is equals to 0
1394                 contents[contentsOffset++] = 0;
1395                 contents[contentsOffset++] = 0;
1396                 contents[contentsOffset++] = 0;
1397                 contents[contentsOffset++] = 0;
1398         }
1399
1400         /**
1401          * INTERNAL USE-ONLY
1402          * Generate the byte for a problem method info that correspond to a synthetic method that
1403          * generate an write access to a private field.
1404          *
1405          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1406          */
1407         public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
1408                 generateMethodInfoHeader(methodBinding);
1409                 // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
1410                 contents[contentsOffset++] = 0;
1411                 contents[contentsOffset++] = 2;
1412                 // Code attribute
1413                 int codeAttributeOffset = contentsOffset;
1414                 generateCodeAttributeHeader();
1415                 codeStream.init(this);
1416                 codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
1417                 completeCodeAttributeForSyntheticMethod(
1418                         methodBinding,
1419                         codeAttributeOffset,
1420                         ((SourceTypeBinding) methodBinding.declaringClass)
1421                                 .scope
1422                                 .referenceCompilationUnit()
1423                                 .compilationResult
1424                                 .lineSeparatorPositions);
1425                 // add the synthetic attribute
1426                 int syntheticAttributeNameIndex =
1427                         constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1428                 contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1429                 contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1430                 // the length of a synthetic attribute is equals to 0
1431                 contents[contentsOffset++] = 0;
1432                 contents[contentsOffset++] = 0;
1433                 contents[contentsOffset++] = 0;
1434                 contents[contentsOffset++] = 0;
1435         }
1436
1437         /**
1438          * INTERNAL USE-ONLY
1439          * Generate the bytes for a synthetic method that provides access to a private method.
1440          *
1441          * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1442          */
1443         public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
1444                 generateMethodInfoHeader(methodBinding);
1445                 // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
1446                 contents[contentsOffset++] = 0;
1447                 contents[contentsOffset++] = 2;
1448                 // Code attribute
1449                 int codeAttributeOffset = contentsOffset;
1450                 generateCodeAttributeHeader();
1451                 codeStream.init(this);
1452                 codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
1453                 completeCodeAttributeForSyntheticMethod(
1454                         methodBinding,
1455                         codeAttributeOffset,
1456                         ((SourceTypeBinding) methodBinding.declaringClass)
1457                                 .scope
1458                                 .referenceCompilationUnit()
1459                                 .compilationResult
1460                                 .lineSeparatorPositions);
1461                 // add the synthetic attribute
1462                 int syntheticAttributeNameIndex =
1463                         constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
1464                 contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
1465                 contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
1466                 // the length of a synthetic attribute is equals to 0
1467                 contents[contentsOffset++] = 0;
1468                 contents[contentsOffset++] = 0;
1469                 contents[contentsOffset++] = 0;
1470                 contents[contentsOffset++] = 0;
1471         }
1472
1473         /**
1474          * INTERNAL USE-ONLY
1475          * That method completes the creation of the code attribute by setting
1476          * - the attribute_length
1477          * - max_stack
1478          * - max_locals
1479          * - code_length
1480          * - exception table
1481          * - and debug attributes if necessary.
1482          *
1483          * @param codeAttributeOffset <CODE>int</CODE>
1484          */
1485         public void completeCodeAttribute(int codeAttributeOffset) {
1486                 // reinitialize the localContents with the byte modified by the code stream
1487                 this.contents = codeStream.bCodeStream;
1488                 int localContentsOffset = codeStream.classFileOffset;
1489                 // codeAttributeOffset is the position inside localContents byte array before we started to write
1490                 // any information about the codeAttribute
1491                 // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
1492                 // to get the right position, 6 for the max_stack etc...
1493                 int code_length = codeStream.position;
1494                 if (code_length > 65535) {
1495                         codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
1496                                 codeStream.methodDeclaration);
1497                 }
1498                 if (localContentsOffset + 20 >= this.contents.length) {
1499                         resizeContents(20);
1500                 }
1501                 int max_stack = codeStream.stackMax;
1502                 this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
1503                 this.contents[codeAttributeOffset + 7] = (byte) max_stack;
1504                 int max_locals = codeStream.maxLocals;
1505                 this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
1506                 this.contents[codeAttributeOffset + 9] = (byte) max_locals;
1507                 this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
1508                 this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
1509                 this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
1510                 this.contents[codeAttributeOffset + 13] = (byte) code_length;
1511
1512                 // write the exception table
1513                 int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
1514                 ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
1515                 int exSize = exceptionHandlersNumber * 8 + 2;
1516                 if (exSize + localContentsOffset >= this.contents.length) {
1517                         resizeContents(exSize);
1518                 }
1519                 // there is no exception table, so we need to offset by 2 the current offset and move 
1520                 // on the attribute generation
1521                 this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
1522                 this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
1523                 for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
1524                         ExceptionLabel exceptionHandler = exceptionHandlers[i];
1525                         if (exceptionHandler != null) {
1526                                 int start = exceptionHandler.start;
1527                                 this.contents[localContentsOffset++] = (byte) (start >> 8);
1528                                 this.contents[localContentsOffset++] = (byte) start;
1529                                 int end = exceptionHandler.end;
1530                                 this.contents[localContentsOffset++] = (byte) (end >> 8);
1531                                 this.contents[localContentsOffset++] = (byte) end;
1532                                 int handlerPC = exceptionHandler.position;
1533                                 this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
1534                                 this.contents[localContentsOffset++] = (byte) handlerPC;
1535                                 if (exceptionHandler.exceptionType == null) {
1536                                         // any exception handler
1537                                         this.contents[localContentsOffset++] = 0;
1538                                         this.contents[localContentsOffset++] = 0;
1539                                 } else {
1540                                         int nameIndex;
1541                                         if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
1542                                                 /* represents ClassNotFoundException, see class literal access*/
1543                                                 nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
1544                                         } else {
1545                                                 nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
1546                                         }
1547                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1548                                         this.contents[localContentsOffset++] = (byte) nameIndex;
1549                                 }
1550                         }
1551                 }
1552                 // debug attributes
1553                 int codeAttributeAttributeOffset = localContentsOffset;
1554                 int attributeNumber = 0;
1555                 // leave two bytes for the attribute_length
1556                 localContentsOffset += 2;
1557
1558                 // first we handle the linenumber attribute
1559                 if (codeStream.generateLineNumberAttributes) {
1560                         /* Create and add the line number attribute (used for debugging) 
1561                          * Build the pairs of:
1562                          *      (bytecodePC lineNumber)
1563                          * according to the table of start line indexes and the pcToSourceMap table
1564                          * contained into the codestream
1565                          */
1566                         int[] pcToSourceMapTable;
1567                         if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
1568                                 && (codeStream.pcToSourceMapSize != 0)) {
1569                                 int lineNumberNameIndex =
1570                                         constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
1571                                 if (localContentsOffset + 8 >= this.contents.length) {
1572                                         resizeContents(8);
1573                                 }
1574                                 this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
1575                                 this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
1576                                 int lineNumberTableOffset = localContentsOffset;
1577                                 localContentsOffset += 6;
1578                                 // leave space for attribute_length and line_number_table_length
1579                                 int numberOfEntries = 0;
1580                                 int length = codeStream.pcToSourceMapSize;
1581                                 for (int i = 0; i < length;) {
1582                                         // write the entry
1583                                         if (localContentsOffset + 4 >= this.contents.length) {
1584                                                 resizeContents(4);
1585                                         }
1586                                         int pc = pcToSourceMapTable[i++];
1587                                         this.contents[localContentsOffset++] = (byte) (pc >> 8);
1588                                         this.contents[localContentsOffset++] = (byte) pc;
1589                                         int lineNumber = pcToSourceMapTable[i++];
1590                                         this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
1591                                         this.contents[localContentsOffset++] = (byte) lineNumber;
1592                                         numberOfEntries++;
1593                                 }
1594                                 // now we change the size of the line number attribute
1595                                 int lineNumberAttr_length = numberOfEntries * 4 + 2;
1596                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
1597                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
1598                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
1599                                 this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
1600                                 this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
1601                                 this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
1602                                 attributeNumber++;
1603                         }
1604                 }
1605                 // then we do the local variable attribute
1606                 if (codeStream.generateLocalVariableTableAttributes) {
1607                         int localVariableTableOffset = localContentsOffset;
1608                         int numberOfEntries = 0;
1609                         int localVariableNameIndex =
1610                                 constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
1611                         final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
1612                         int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
1613                         for (int i = 0; i < codeStream.allLocalsCounter; i++) {
1614                                 maxOfEntries += 10 * codeStream.locals[i].initializationCount;
1615                         }
1616                         // reserve enough space
1617                         if (localContentsOffset + maxOfEntries >= this.contents.length) {
1618                                 resizeContents(maxOfEntries);
1619                         }
1620                         this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
1621                         this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
1622                         localContentsOffset += 6;
1623                         // leave space for attribute_length and local_variable_table_length
1624                         int nameIndex;
1625                         int descriptorIndex;
1626                         SourceTypeBinding declaringClassBinding = null;
1627                         if (!methodDeclarationIsStatic) {
1628                                 numberOfEntries++;
1629                                 this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
1630                                 this.contents[localContentsOffset++] = 0;
1631                                 this.contents[localContentsOffset++] = (byte) (code_length >> 8);
1632                                 this.contents[localContentsOffset++] = (byte) code_length;
1633                                 nameIndex = constantPool.literalIndex(ConstantPool.This);
1634                                 this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1635                                 this.contents[localContentsOffset++] = (byte) nameIndex;
1636                                 declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
1637                                 descriptorIndex =
1638                                         constantPool.literalIndex(
1639                                                 declaringClassBinding.signature());
1640                                 this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1641                                 this.contents[localContentsOffset++] = (byte) descriptorIndex;
1642                                 this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1643                                 this.contents[localContentsOffset++] = 0;
1644                         }
1645                         // used to remember the local variable with a generic type
1646                         int genericLocalVariablesCounter = 0;
1647                         LocalVariableBinding[] genericLocalVariables = null;
1648                         int numberOfGenericEntries = 0;
1649                         
1650                         for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
1651                                 LocalVariableBinding localVariable = codeStream.locals[i];
1652                                 final TypeBinding localVariableTypeBinding = localVariable.type;
1653                                 boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
1654                                 if (localVariable.initializationCount != 0 && isParameterizedType) {
1655                                         if (genericLocalVariables == null) {
1656                                                 // we cannot have more than max locals
1657                                                 genericLocalVariables = new LocalVariableBinding[max];
1658                                         }
1659                                         genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
1660                                 }
1661                                 for (int j = 0; j < localVariable.initializationCount; j++) {
1662                                         int startPC = localVariable.initializationPCs[j << 1];
1663                                         int endPC = localVariable.initializationPCs[(j << 1) + 1];
1664                                         if (startPC != endPC) { // only entries for non zero length
1665                                                 if (endPC == -1) {
1666                                                         localVariable.declaringScope.problemReporter().abortDueToInternalError(
1667                                                                 Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
1668                                                                 (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
1669                                                 }
1670                                                 if (isParameterizedType) {
1671                                                         numberOfGenericEntries++;
1672                                                 }
1673                                                 // now we can safely add the local entry
1674                                                 numberOfEntries++;
1675                                                 this.contents[localContentsOffset++] = (byte) (startPC >> 8);
1676                                                 this.contents[localContentsOffset++] = (byte) startPC;
1677                                                 int length = endPC - startPC;
1678                                                 this.contents[localContentsOffset++] = (byte) (length >> 8);
1679                                                 this.contents[localContentsOffset++] = (byte) length;
1680                                                 nameIndex = constantPool.literalIndex(localVariable.name);
1681                                                 this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1682                                                 this.contents[localContentsOffset++] = (byte) nameIndex;
1683                                                 descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
1684                                                 this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1685                                                 this.contents[localContentsOffset++] = (byte) descriptorIndex;
1686                                                 int resolvedPosition = localVariable.resolvedPosition;
1687                                                 this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1688                                                 this.contents[localContentsOffset++] = (byte) resolvedPosition;
1689                                         }
1690                                 }
1691                         }
1692                         int value = numberOfEntries * 10 + 2;
1693                         localVariableTableOffset += 2;
1694                         this.contents[localVariableTableOffset++] = (byte) (value >> 24);
1695                         this.contents[localVariableTableOffset++] = (byte) (value >> 16);
1696                         this.contents[localVariableTableOffset++] = (byte) (value >> 8);
1697                         this.contents[localVariableTableOffset++] = (byte) value;
1698                         this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
1699                         this.contents[localVariableTableOffset] = (byte) numberOfEntries;
1700                         attributeNumber++;
1701                         
1702                         final boolean currentInstanceIsGeneric = 
1703                                 !methodDeclarationIsStatic
1704                                 && declaringClassBinding != null 
1705                                 && declaringClassBinding.typeVariables != NoTypeVariables;
1706                         if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
1707                                 // add the local variable type table attribute
1708                                 numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
1709                                 maxOfEntries = 8 + numberOfGenericEntries * 10;
1710                                 // reserve enough space
1711                                 if (localContentsOffset + maxOfEntries >= this.contents.length) {
1712                                         resizeContents(maxOfEntries);
1713                                 }
1714                                 int localVariableTypeNameIndex =
1715                                         constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
1716                                 this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
1717                                 this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
1718                                 value = numberOfGenericEntries * 10 + 2;
1719                                 this.contents[localContentsOffset++] = (byte) (value >> 24);
1720                                 this.contents[localContentsOffset++] = (byte) (value >> 16);
1721                                 this.contents[localContentsOffset++] = (byte) (value >> 8);
1722                                 this.contents[localContentsOffset++] = (byte) value;
1723                                 this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
1724                                 this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
1725                                 if (currentInstanceIsGeneric) {
1726                                         this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
1727                                         this.contents[localContentsOffset++] = 0;
1728                                         this.contents[localContentsOffset++] = (byte) (code_length >> 8);
1729                                         this.contents[localContentsOffset++] = (byte) code_length;
1730                                         nameIndex = constantPool.literalIndex(ConstantPool.This);
1731                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1732                                         this.contents[localContentsOffset++] = (byte) nameIndex;
1733                                         descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
1734                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1735                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
1736                                         this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1737                                         this.contents[localContentsOffset++] = 0;
1738                                 }
1739                                 
1740                                 for (int i = 0; i < genericLocalVariablesCounter; i++) {
1741                                         LocalVariableBinding localVariable = genericLocalVariables[i];
1742                                         for (int j = 0; j < localVariable.initializationCount; j++) {
1743                                                 int startPC = localVariable.initializationPCs[j << 1];
1744                                                 int endPC = localVariable.initializationPCs[(j << 1) + 1];
1745                                                 if (startPC != endPC) {
1746                                                         // only entries for non zero length
1747                                                         // now we can safely add the local entry
1748                                                         this.contents[localContentsOffset++] = (byte) (startPC >> 8);
1749                                                         this.contents[localContentsOffset++] = (byte) startPC;
1750                                                         int length = endPC - startPC;
1751                                                         this.contents[localContentsOffset++] = (byte) (length >> 8);
1752                                                         this.contents[localContentsOffset++] = (byte) length;
1753                                                         nameIndex = constantPool.literalIndex(localVariable.name);
1754                                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1755                                                         this.contents[localContentsOffset++] = (byte) nameIndex;
1756                                                         descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
1757                                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1758                                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
1759                                                         int resolvedPosition = localVariable.resolvedPosition;
1760                                                         this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1761                                                         this.contents[localContentsOffset++] = (byte) resolvedPosition;
1762                                                 }
1763                                         }
1764                                 }
1765                                 attributeNumber++;
1766                         }
1767                 }
1768                 // update the number of attributes
1769                 // ensure first that there is enough space available inside the localContents array
1770                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
1771                         resizeContents(2);
1772                 }
1773                 this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
1774                 this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
1775
1776                 // update the attribute length
1777                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
1778                 this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
1779                 this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
1780                 this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
1781                 this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
1782                 contentsOffset = localContentsOffset;
1783         }
1784
1785         /**
1786          * INTERNAL USE-ONLY
1787          * That method completes the creation of the code attribute by setting
1788          * - the attribute_length
1789          * - max_stack
1790          * - max_locals
1791          * - code_length
1792          * - exception table
1793          * - and debug attributes if necessary.
1794          *
1795          * @param codeAttributeOffset <CODE>int</CODE>
1796          */
1797         public void completeCodeAttributeForClinit(int codeAttributeOffset) {
1798                 // reinitialize the contents with the byte modified by the code stream
1799                 this.contents = codeStream.bCodeStream;
1800                 int localContentsOffset = codeStream.classFileOffset;
1801                 // codeAttributeOffset is the position inside contents byte array before we started to write
1802                 // any information about the codeAttribute
1803                 // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
1804                 // to get the right position, 6 for the max_stack etc...
1805                 int code_length = codeStream.position;
1806                 if (code_length > 65535) {
1807                         codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
1808                                 codeStream.methodDeclaration.scope.referenceType());
1809                 }
1810                 if (localContentsOffset + 20 >= this.contents.length) {
1811                         resizeContents(20);
1812                 }
1813                 int max_stack = codeStream.stackMax;
1814                 this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
1815                 this.contents[codeAttributeOffset + 7] = (byte) max_stack;
1816                 int max_locals = codeStream.maxLocals;
1817                 this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
1818                 this.contents[codeAttributeOffset + 9] = (byte) max_locals;
1819                 this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
1820                 this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
1821                 this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
1822                 this.contents[codeAttributeOffset + 13] = (byte) code_length;
1823
1824                 // write the exception table
1825                 int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
1826                 ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
1827                 int exSize = exceptionHandlersNumber * 8 + 2;
1828                 if (exSize + localContentsOffset >= this.contents.length) {
1829                         resizeContents(exSize);
1830                 }
1831                 // there is no exception table, so we need to offset by 2 the current offset and move 
1832                 // on the attribute generation
1833                 this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
1834                 this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
1835                 for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
1836                         ExceptionLabel exceptionHandler = exceptionHandlers[i];
1837                         if (exceptionHandler != null) {
1838                                 int start = exceptionHandler.start;
1839                                 this.contents[localContentsOffset++] = (byte) (start >> 8);
1840                                 this.contents[localContentsOffset++] = (byte) start;
1841                                 int end = exceptionHandler.end;
1842                                 this.contents[localContentsOffset++] = (byte) (end >> 8);
1843                                 this.contents[localContentsOffset++] = (byte) end;
1844                                 int handlerPC = exceptionHandler.position;
1845                                 this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
1846                                 this.contents[localContentsOffset++] = (byte) handlerPC;
1847                                 if (exceptionHandler.exceptionType == null) {
1848                                         // any exception handler
1849                                         this.contents[localContentsOffset++] = 0;
1850                                         this.contents[localContentsOffset++] = 0;
1851                                 } else {
1852                                         int nameIndex;
1853                                         if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
1854                                                 /* represents denote ClassNotFoundException, see class literal access*/
1855                                                 nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
1856                                         } else {
1857                                                 nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
1858                                         }
1859                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1860                                         this.contents[localContentsOffset++] = (byte) nameIndex;
1861                                 }
1862                         }
1863                 }
1864                 // debug attributes
1865                 int codeAttributeAttributeOffset = localContentsOffset;
1866                 int attributeNumber = 0;
1867                 // leave two bytes for the attribute_length
1868                 localContentsOffset += 2;
1869
1870                 // first we handle the linenumber attribute
1871                 if (codeStream.generateLineNumberAttributes) {
1872                         /* Create and add the line number attribute (used for debugging) 
1873                          * Build the pairs of:
1874                          *      (bytecodePC lineNumber)
1875                          * according to the table of start line indexes and the pcToSourceMap table
1876                          * contained into the codestream
1877                          */
1878                         int[] pcToSourceMapTable;
1879                         if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
1880                                 && (codeStream.pcToSourceMapSize != 0)) {
1881                                 int lineNumberNameIndex =
1882                                         constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
1883                                 if (localContentsOffset + 8 >= this.contents.length) {
1884                                         resizeContents(8);
1885                                 }
1886                                 this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
1887                                 this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
1888                                 int lineNumberTableOffset = localContentsOffset;
1889                                 localContentsOffset += 6;
1890                                 // leave space for attribute_length and line_number_table_length
1891                                 int numberOfEntries = 0;
1892                                 int length = codeStream.pcToSourceMapSize;
1893                                 for (int i = 0; i < length;) {
1894                                         // write the entry
1895                                         if (localContentsOffset + 4 >= this.contents.length) {
1896                                                 resizeContents(4);
1897                                         }
1898                                         int pc = pcToSourceMapTable[i++];
1899                                         this.contents[localContentsOffset++] = (byte) (pc >> 8);
1900                                         this.contents[localContentsOffset++] = (byte) pc;
1901                                         int lineNumber = pcToSourceMapTable[i++];
1902                                         this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
1903                                         this.contents[localContentsOffset++] = (byte) lineNumber;
1904                                         numberOfEntries++;
1905                                 }
1906                                 // now we change the size of the line number attribute
1907                                 int lineNumberAttr_length = numberOfEntries * 4 + 2;
1908                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
1909                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
1910                                 this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
1911                                 this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
1912                                 this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
1913                                 this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
1914                                 attributeNumber++;
1915                         }
1916                 }
1917                 // then we do the local variable attribute
1918                 if (codeStream.generateLocalVariableTableAttributes) {
1919                         int localVariableTableOffset = localContentsOffset;
1920                         int numberOfEntries = 0;
1921                         //              codeAttribute.addLocalVariableTableAttribute(this);
1922                         if ((codeStream.pcToSourceMap != null)
1923                                 && (codeStream.pcToSourceMapSize != 0)) {
1924                                 int localVariableNameIndex =
1925                                         constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
1926                                 if (localContentsOffset + 8 >= this.contents.length) {
1927                                         resizeContents(8);
1928                                 }
1929                                 this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
1930                                 this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
1931                                 localContentsOffset += 6;
1932
1933                                 // leave space for attribute_length and local_variable_table_length
1934                                 int nameIndex;
1935                                 int descriptorIndex;
1936
1937                                 // used to remember the local variable with a generic type
1938                                 int genericLocalVariablesCounter = 0;
1939                                 LocalVariableBinding[] genericLocalVariables = null;
1940                                 int numberOfGenericEntries = 0;
1941
1942                                 for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
1943                                         LocalVariableBinding localVariable = codeStream.locals[i];
1944                                         final TypeBinding localVariableTypeBinding = localVariable.type;
1945                                         boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
1946                                         if (localVariable.initializationCount != 0 && isParameterizedType) {
1947                                                 if (genericLocalVariables == null) {
1948                                                         // we cannot have more than max locals
1949                                                         genericLocalVariables = new LocalVariableBinding[max];
1950                                                 }
1951                                                 genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
1952                                         }
1953                                         for (int j = 0; j < localVariable.initializationCount; j++) {
1954                                                 int startPC = localVariable.initializationPCs[j << 1];
1955                                                 int endPC = localVariable.initializationPCs[(j << 1) + 1];
1956                                                 if (startPC != endPC) { // only entries for non zero length
1957                                                         if (endPC == -1) {
1958                                                                 localVariable.declaringScope.problemReporter().abortDueToInternalError(
1959                                                                         Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
1960                                                                         (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
1961                                                         }
1962                                                         if (localContentsOffset + 10 >= this.contents.length) {
1963                                                                 resizeContents(10);
1964                                                         }
1965                                                         // now we can safely add the local entry
1966                                                         numberOfEntries++;
1967                                                         if (isParameterizedType) {
1968                                                                 numberOfGenericEntries++;
1969                                                         }
1970                                                         this.contents[localContentsOffset++] = (byte) (startPC >> 8);
1971                                                         this.contents[localContentsOffset++] = (byte) startPC;
1972                                                         int length = endPC - startPC;
1973                                                         this.contents[localContentsOffset++] = (byte) (length >> 8);
1974                                                         this.contents[localContentsOffset++] = (byte) length;
1975                                                         nameIndex = constantPool.literalIndex(localVariable.name);
1976                                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1977                                                         this.contents[localContentsOffset++] = (byte) nameIndex;
1978                                                         descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
1979                                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1980                                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
1981                                                         int resolvedPosition = localVariable.resolvedPosition;
1982                                                         this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1983                                                         this.contents[localContentsOffset++] = (byte) resolvedPosition;
1984                                                 }
1985                                         }
1986                                 }
1987                                 int value = numberOfEntries * 10 + 2;
1988                                 localVariableTableOffset += 2;
1989                                 this.contents[localVariableTableOffset++] = (byte) (value >> 24);
1990                                 this.contents[localVariableTableOffset++] = (byte) (value >> 16);
1991                                 this.contents[localVariableTableOffset++] = (byte) (value >> 8);
1992                                 this.contents[localVariableTableOffset++] = (byte) value;
1993                                 this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
1994                                 this.contents[localVariableTableOffset] = (byte) numberOfEntries;
1995                                 attributeNumber++;
1996
1997                                 if (genericLocalVariablesCounter != 0) {
1998                                         // add the local variable type table attribute
1999                                         // reserve enough space
2000                                         int maxOfEntries = 8 + numberOfGenericEntries * 10;
2001
2002                                         if (localContentsOffset + maxOfEntries >= this.contents.length) {
2003                                                 resizeContents(maxOfEntries);
2004                                         }
2005                                         int localVariableTypeNameIndex =
2006                                                 constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
2007                                         this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
2008                                         this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
2009                                         value = numberOfGenericEntries * 10 + 2;
2010                                         this.contents[localContentsOffset++] = (byte) (value >> 24);
2011                                         this.contents[localContentsOffset++] = (byte) (value >> 16);
2012                                         this.contents[localContentsOffset++] = (byte) (value >> 8);
2013                                         this.contents[localContentsOffset++] = (byte) value;
2014                                         this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
2015                                         this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
2016                                         for (int i = 0; i < genericLocalVariablesCounter; i++) {
2017                                                 LocalVariableBinding localVariable = genericLocalVariables[i];
2018                                                 for (int j = 0; j < localVariable.initializationCount; j++) {
2019                                                         int startPC = localVariable.initializationPCs[j << 1];
2020                                                         int endPC = localVariable.initializationPCs[(j << 1) + 1];
2021                                                         if (startPC != endPC) { // only entries for non zero length
2022                                                                 // now we can safely add the local entry
2023                                                                 this.contents[localContentsOffset++] = (byte) (startPC >> 8);
2024                                                                 this.contents[localContentsOffset++] = (byte) startPC;
2025                                                                 int length = endPC - startPC;
2026                                                                 this.contents[localContentsOffset++] = (byte) (length >> 8);
2027                                                                 this.contents[localContentsOffset++] = (byte) length;
2028                                                                 nameIndex = constantPool.literalIndex(localVariable.name);
2029                                                                 this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2030                                                                 this.contents[localContentsOffset++] = (byte) nameIndex;
2031                                                                 descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
2032                                                                 this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2033                                                                 this.contents[localContentsOffset++] = (byte) descriptorIndex;
2034                                                                 int resolvedPosition = localVariable.resolvedPosition;
2035                                                                 this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2036                                                                 this.contents[localContentsOffset++] = (byte) resolvedPosition;
2037                                                         }
2038                                                 }
2039                                         }
2040                                         attributeNumber++;
2041                                 }
2042                         }
2043                 }
2044                 // update the number of attributes
2045                 // ensure first that there is enough space available inside the contents array
2046                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2047                         resizeContents(2);
2048                 }
2049                 this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2050                 this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2051                 // update the attribute length
2052                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2053                 this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2054                 this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2055                 this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2056                 this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2057                 contentsOffset = localContentsOffset;
2058         }
2059
2060         /**
2061          * INTERNAL USE-ONLY
2062          * That method completes the creation of the code attribute by setting
2063          * - the attribute_length
2064          * - max_stack
2065          * - max_locals
2066          * - code_length
2067          * - exception table
2068          * - and debug attributes if necessary.
2069          *
2070          * @param codeAttributeOffset <CODE>int</CODE>
2071          * @param startLineIndexes int[]
2072          */
2073         public void completeCodeAttributeForClinit(
2074                 int codeAttributeOffset,
2075                 int[] startLineIndexes,
2076                 int problemLine) {
2077                 // reinitialize the contents with the byte modified by the code stream
2078                 this.contents = codeStream.bCodeStream;
2079                 int localContentsOffset = codeStream.classFileOffset;
2080                 // codeAttributeOffset is the position inside contents byte array before we started to write
2081                 // any information about the codeAttribute
2082                 // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
2083                 // to get the right position, 6 for the max_stack etc...
2084                 int code_length = codeStream.position;
2085                 if (code_length > 65535) {
2086                         codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
2087                                 codeStream.methodDeclaration.scope.referenceType());
2088                 }
2089                 if (localContentsOffset + 20 >= this.contents.length) {
2090                         resizeContents(20);
2091                 }
2092                 int max_stack = codeStream.stackMax;
2093                 this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2094                 this.contents[codeAttributeOffset + 7] = (byte) max_stack;
2095                 int max_locals = codeStream.maxLocals;
2096                 this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2097                 this.contents[codeAttributeOffset + 9] = (byte) max_locals;
2098                 this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2099                 this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2100                 this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2101                 this.contents[codeAttributeOffset + 13] = (byte) code_length;
2102
2103                 // write the exception table
2104                 this.contents[localContentsOffset++] = 0;
2105                 this.contents[localContentsOffset++] = 0;
2106
2107                 // debug attributes
2108                 int codeAttributeAttributeOffset = localContentsOffset;
2109                 int attributeNumber = 0; // leave two bytes for the attribute_length
2110                 localContentsOffset += 2; // first we handle the linenumber attribute
2111
2112                 // first we handle the linenumber attribute
2113                 if (codeStream.generateLineNumberAttributes) {
2114                         if (localContentsOffset + 20 >= this.contents.length) {
2115                                 resizeContents(20);
2116                         }                       
2117                         /* Create and add the line number attribute (used for debugging) 
2118                             * Build the pairs of:
2119                             * (bytecodePC lineNumber)
2120                             * according to the table of start line indexes and the pcToSourceMap table
2121                             * contained into the codestream
2122                             */
2123                         int lineNumberNameIndex =
2124                                 constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2125                         this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2126                         this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2127                         this.contents[localContentsOffset++] = 0;
2128                         this.contents[localContentsOffset++] = 0;
2129                         this.contents[localContentsOffset++] = 0;
2130                         this.contents[localContentsOffset++] = 6;
2131                         this.contents[localContentsOffset++] = 0;
2132                         this.contents[localContentsOffset++] = 1;
2133                         // first entry at pc = 0
2134                         this.contents[localContentsOffset++] = 0;
2135                         this.contents[localContentsOffset++] = 0;
2136                         this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
2137                         this.contents[localContentsOffset++] = (byte) problemLine;
2138                         // now we change the size of the line number attribute
2139                         attributeNumber++;
2140                 }
2141                 // then we do the local variable attribute
2142                 if (codeStream.generateLocalVariableTableAttributes) {
2143                         int localVariableNameIndex =
2144                                 constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
2145                         if (localContentsOffset + 8 >= this.contents.length) {
2146                                 resizeContents(8);
2147                         }
2148                         this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2149                         this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
2150                         this.contents[localContentsOffset++] = 0;
2151                         this.contents[localContentsOffset++] = 0;
2152                         this.contents[localContentsOffset++] = 0;
2153                         this.contents[localContentsOffset++] = 2;
2154                         this.contents[localContentsOffset++] = 0;
2155                         this.contents[localContentsOffset++] = 0;
2156                         attributeNumber++;
2157                 }
2158                 // update the number of attributes
2159                 // ensure first that there is enough space available inside the contents array
2160                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2161                         resizeContents(2);
2162                 }
2163                 this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2164                 this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2165                 // update the attribute length
2166                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2167                 this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2168                 this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2169                 this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2170                 this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2171                 contentsOffset = localContentsOffset;
2172         }
2173
2174         /**
2175          * 
2176          */
2177         public void completeCodeAttributeForMissingAbstractProblemMethod(
2178                 MethodBinding binding,
2179                 int codeAttributeOffset,
2180                 int[] startLineIndexes,
2181                 int problemLine) {
2182                 // reinitialize the localContents with the byte modified by the code stream
2183                 this.contents = codeStream.bCodeStream;
2184                 int localContentsOffset = codeStream.classFileOffset;
2185                 // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
2186                 int max_stack = codeStream.stackMax;
2187                 this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2188                 this.contents[codeAttributeOffset + 7] = (byte) max_stack;
2189                 int max_locals = codeStream.maxLocals;
2190                 this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2191                 this.contents[codeAttributeOffset + 9] = (byte) max_locals;
2192                 int code_length = codeStream.position;
2193                 this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2194                 this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2195                 this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2196                 this.contents[codeAttributeOffset + 13] = (byte) code_length;
2197                 // write the exception table
2198                 if (localContentsOffset + 50 >= this.contents.length) {
2199                         resizeContents(50);
2200                 }
2201                 this.contents[localContentsOffset++] = 0;
2202                 this.contents[localContentsOffset++] = 0;
2203                 // debug attributes
2204                 int codeAttributeAttributeOffset = localContentsOffset;
2205                 int attributeNumber = 0; // leave two bytes for the attribute_length
2206                 localContentsOffset += 2; // first we handle the linenumber attribute
2207
2208                 if (codeStream.generateLineNumberAttributes) {
2209                         /* Create and add the line number attribute (used for debugging) 
2210                             * Build the pairs of:
2211                             * (bytecodePC lineNumber)
2212                             * according to the table of start line indexes and the pcToSourceMap table
2213                             * contained into the codestream
2214                             */
2215                         int lineNumberNameIndex =
2216                                 constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2217                         this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2218                         this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2219                         this.contents[localContentsOffset++] = 0;
2220                         this.contents[localContentsOffset++] = 0;
2221                         this.contents[localContentsOffset++] = 0;
2222                         this.contents[localContentsOffset++] = 6;
2223                         this.contents[localContentsOffset++] = 0;
2224                         this.contents[localContentsOffset++] = 1;
2225                         if (problemLine == 0) {
2226                                 problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
2227                         }
2228                         // first entry at pc = 0
2229                         this.contents[localContentsOffset++] = 0;
2230                         this.contents[localContentsOffset++] = 0;
2231                         this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
2232                         this.contents[localContentsOffset++] = (byte) problemLine;
2233                         // now we change the size of the line number attribute
2234                         attributeNumber++;
2235                 }
2236                 
2237                 // then we do the local variable attribute
2238                 // update the number of attributes// ensure first that there is enough space available inside the localContents array
2239                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2240                         resizeContents(2);
2241                 }
2242                 this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2243                 this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2244                 // update the attribute length
2245                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2246                 this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2247                 this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2248                 this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2249                 this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2250                 contentsOffset = localContentsOffset;
2251         }
2252
2253         /**
2254          * INTERNAL USE-ONLY
2255          * That method completes the creation of the code attribute by setting
2256          * - the attribute_length
2257          * - max_stack
2258          * - max_locals
2259          * - code_length
2260          * - exception table
2261          * - and debug attributes if necessary.
2262          *
2263          * @param codeAttributeOffset <CODE>int</CODE>
2264          */
2265         public void completeCodeAttributeForProblemMethod(
2266                 AbstractMethodDeclaration method,
2267                 MethodBinding binding,
2268                 int codeAttributeOffset,
2269                 int[] startLineIndexes,
2270                 int problemLine) {
2271                 // reinitialize the localContents with the byte modified by the code stream
2272                 this.contents = codeStream.bCodeStream;
2273                 int localContentsOffset = codeStream.classFileOffset;
2274                 // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
2275                 int max_stack = codeStream.stackMax;
2276                 this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2277                 this.contents[codeAttributeOffset + 7] = (byte) max_stack;
2278                 int max_locals = codeStream.maxLocals;
2279                 this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2280                 this.contents[codeAttributeOffset + 9] = (byte) max_locals;
2281                 int code_length = codeStream.position;
2282                 this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2283                 this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2284                 this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2285                 this.contents[codeAttributeOffset + 13] = (byte) code_length;
2286                 // write the exception table
2287                 if (localContentsOffset + 50 >= this.contents.length) {
2288                         resizeContents(50);
2289                 }
2290
2291                 // write the exception table
2292                 this.contents[localContentsOffset++] = 0;
2293                 this.contents[localContentsOffset++] = 0;
2294                 // debug attributes
2295                 int codeAttributeAttributeOffset = localContentsOffset;
2296                 int attributeNumber = 0; // leave two bytes for the attribute_length
2297                 localContentsOffset += 2; // first we handle the linenumber attribute
2298
2299                 if (codeStream.generateLineNumberAttributes) {
2300                         if (localContentsOffset + 20 >= this.contents.length) {
2301                                 resizeContents(20);
2302                         }
2303                         /* Create and add the line number attribute (used for debugging) 
2304                             * Build the pairs of:
2305                             * (bytecodePC lineNumber)
2306                             * according to the table of start line indexes and the pcToSourceMap table
2307                             * contained into the codestream
2308                             */
2309                         int lineNumberNameIndex =
2310                                 constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2311                         this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2312                         this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2313                         this.contents[localContentsOffset++] = 0;
2314                         this.contents[localContentsOffset++] = 0;
2315                         this.contents[localContentsOffset++] = 0;
2316                         this.contents[localContentsOffset++] = 6;
2317                         this.contents[localContentsOffset++] = 0;
2318                         this.contents[localContentsOffset++] = 1;
2319                         if (problemLine == 0) {
2320                                 problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
2321                         }
2322                         // first entry at pc = 0
2323                         this.contents[localContentsOffset++] = 0;
2324                         this.contents[localContentsOffset++] = 0;
2325                         this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
2326                         this.contents[localContentsOffset++] = (byte) problemLine;
2327                         // now we change the size of the line number attribute
2328                         attributeNumber++;
2329                 }
2330                 // then we do the local variable attribute
2331                 if (codeStream.generateLocalVariableTableAttributes) {
2332                         // compute the resolved position for the arguments of the method
2333                         int argSize;
2334                         int localVariableTableOffset = localContentsOffset;
2335                         int numberOfEntries = 0;
2336                         //              codeAttribute.addLocalVariableTableAttribute(this);
2337                         int localVariableNameIndex =
2338                                 constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
2339                         if (localContentsOffset + 8 >= this.contents.length) {
2340                                 resizeContents(8);
2341                         }
2342                         this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2343                         this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
2344                         localContentsOffset += 6;
2345                         // leave space for attribute_length and local_variable_table_length
2346                         int descriptorIndex;
2347                         int nameIndex;
2348                         SourceTypeBinding declaringClassBinding = null;
2349                         final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
2350                         if (!methodDeclarationIsStatic) {
2351                                 numberOfEntries++;
2352                                 if (localContentsOffset + 10 >= this.contents.length) {
2353                                         resizeContents(10);
2354                                 }
2355                                 this.contents[localContentsOffset++] = 0;
2356                                 this.contents[localContentsOffset++] = 0;
2357                                 this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2358                                 this.contents[localContentsOffset++] = (byte) code_length;
2359                                 nameIndex = constantPool.literalIndex(ConstantPool.This);
2360                                 this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2361                                 this.contents[localContentsOffset++] = (byte) nameIndex;
2362                                 declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
2363                                 descriptorIndex =
2364                                         constantPool.literalIndex(declaringClassBinding.signature());
2365                                 this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2366                                 this.contents[localContentsOffset++] = (byte) descriptorIndex;
2367                                 // the resolved position for this is always 0
2368                                 this.contents[localContentsOffset++] = 0;
2369                                 this.contents[localContentsOffset++] = 0;
2370                         }
2371                         // used to remember the local variable with a generic type
2372                         int genericLocalVariablesCounter = 0;
2373                         LocalVariableBinding[] genericLocalVariables = null;
2374                         int numberOfGenericEntries = 0;
2375                         
2376                         if (binding.isConstructor()) {
2377                                 ReferenceBinding declaringClass = binding.declaringClass;
2378                                 if (declaringClass.isNestedType()) {
2379                                         NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
2380                                         argSize = methodDeclaringClass.enclosingInstancesSlotSize;
2381                                         SyntheticArgumentBinding[] syntheticArguments;
2382                                         if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
2383                                                 for (int i = 0, max = syntheticArguments.length; i < max; i++) {
2384                                                         LocalVariableBinding localVariable = syntheticArguments[i];
2385                                                         final TypeBinding localVariableTypeBinding = localVariable.type;
2386                                                         if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
2387                                                                 if (genericLocalVariables == null) {
2388                                                                         // we cannot have more than max locals
2389                                                                         genericLocalVariables = new LocalVariableBinding[max];
2390                                                                 }
2391                                                                 genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
2392                                                                 numberOfGenericEntries++;                                                               
2393                                                         }
2394                                                         if (localContentsOffset + 10 >= this.contents.length) {
2395                                                                 resizeContents(10);
2396                                                         }
2397                                                         // now we can safely add the local entry
2398                                                         numberOfEntries++;
2399                                                         this.contents[localContentsOffset++] = 0;
2400                                                         this.contents[localContentsOffset++] = 0;
2401                                                         this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2402                                                         this.contents[localContentsOffset++] = (byte) code_length;
2403                                                         nameIndex = constantPool.literalIndex(localVariable.name);
2404                                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2405                                                         this.contents[localContentsOffset++] = (byte) nameIndex;
2406                                                         descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
2407                                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2408                                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
2409                                                         int resolvedPosition = localVariable.resolvedPosition;
2410                                                         this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2411                                                         this.contents[localContentsOffset++] = (byte) resolvedPosition;
2412                                                 }
2413                                         }
2414                                 } else {
2415                                         argSize = 1;
2416                                 }
2417                         } else {
2418                                 argSize = binding.isStatic() ? 0 : 1;
2419                         }
2420                         
2421                         int genericArgumentsCounter = 0;
2422                         int[] genericArgumentsNameIndexes = null;
2423                         int[] genericArgumentsResolvedPositions = null;
2424                         TypeBinding[] genericArgumentsTypeBindings = null;
2425
2426                         if (method.binding != null) {
2427                                 TypeBinding[] parameters = method.binding.parameters;
2428                                 Argument[] arguments = method.arguments;
2429                                 if ((parameters != null) && (arguments != null)) {
2430                                         for (int i = 0, max = parameters.length; i < max; i++) {
2431                                                 TypeBinding argumentBinding = parameters[i];
2432                                                 if (localContentsOffset + 10 >= this.contents.length) {
2433                                                         resizeContents(10);
2434                                                 }
2435                                                 // now we can safely add the local entry
2436                                                 numberOfEntries++;
2437                                                 this.contents[localContentsOffset++] = 0;
2438                                                 this.contents[localContentsOffset++] = 0;
2439                                                 this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2440                                                 this.contents[localContentsOffset++] = (byte) code_length;
2441                                                 nameIndex = constantPool.literalIndex(arguments[i].name);
2442                                                 this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2443                                                 this.contents[localContentsOffset++] = (byte) nameIndex;
2444                                                 int resolvedPosition = argSize;
2445                                                 if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
2446                                                         if (genericArgumentsCounter == 0) {
2447                                                                 // we cannot have more than max locals
2448                                                                 genericArgumentsNameIndexes = new int[max];
2449                                                                 genericArgumentsResolvedPositions = new int[max];
2450                                                                 genericArgumentsTypeBindings = new TypeBinding[max];
2451                                                         }
2452                                                         genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
2453                                                         genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
2454                                                         genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
2455                                                 }
2456                                                 descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
2457                                                 this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2458                                                 this.contents[localContentsOffset++] = (byte) descriptorIndex;
2459                                                 if ((argumentBinding == BaseTypes.LongBinding)
2460                                                         || (argumentBinding == BaseTypes.DoubleBinding))
2461                                                         argSize += 2;
2462                                                 else
2463                                                         argSize++;
2464                                                 this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2465                                                 this.contents[localContentsOffset++] = (byte) resolvedPosition;
2466                                         }
2467                                 }
2468                         }
2469                         int value = numberOfEntries * 10 + 2;
2470                         localVariableTableOffset += 2;
2471                         this.contents[localVariableTableOffset++] = (byte) (value >> 24);
2472                         this.contents[localVariableTableOffset++] = (byte) (value >> 16);
2473                         this.contents[localVariableTableOffset++] = (byte) (value >> 8);
2474                         this.contents[localVariableTableOffset++] = (byte) value;
2475                         this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
2476                         this.contents[localVariableTableOffset] = (byte) numberOfEntries;
2477                         attributeNumber++;
2478                         
2479                         final boolean currentInstanceIsGeneric = 
2480                                 !methodDeclarationIsStatic
2481                                 && declaringClassBinding != null
2482                                 && declaringClassBinding.typeVariables != NoTypeVariables;
2483                         if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
2484                                 // add the local variable type table attribute
2485                                 numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
2486                                 // reserve enough space
2487                                 int maxOfEntries = 8 + numberOfEntries * 10;
2488                                 if (localContentsOffset + maxOfEntries >= this.contents.length) {
2489                                         resizeContents(maxOfEntries);
2490                                 }
2491                                 int localVariableTypeNameIndex =
2492                                         constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
2493                                 this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
2494                                 this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
2495                                 value = numberOfEntries * 10 + 2;
2496                                 this.contents[localContentsOffset++] = (byte) (value >> 24);
2497                                 this.contents[localContentsOffset++] = (byte) (value >> 16);
2498                                 this.contents[localContentsOffset++] = (byte) (value >> 8);
2499                                 this.contents[localContentsOffset++] = (byte) value;
2500                                 this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
2501                                 this.contents[localContentsOffset++] = (byte) numberOfEntries;
2502                                 if (currentInstanceIsGeneric) {
2503                                         numberOfEntries++;
2504                                         this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
2505                                         this.contents[localContentsOffset++] = 0;
2506                                         this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2507                                         this.contents[localContentsOffset++] = (byte) code_length;
2508                                         nameIndex = constantPool.literalIndex(ConstantPool.This);
2509                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2510                                         this.contents[localContentsOffset++] = (byte) nameIndex;
2511                                         descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
2512                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2513                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
2514                                         this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
2515                                         this.contents[localContentsOffset++] = 0;
2516                                 }
2517                                 
2518                                 for (int i = 0; i < genericLocalVariablesCounter; i++) {
2519                                         LocalVariableBinding localVariable = genericLocalVariables[i];
2520                                         this.contents[localContentsOffset++] = 0;
2521                                         this.contents[localContentsOffset++] = 0;
2522                                         this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2523                                         this.contents[localContentsOffset++] = (byte) code_length;
2524                                         nameIndex = constantPool.literalIndex(localVariable.name);
2525                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2526                                         this.contents[localContentsOffset++] = (byte) nameIndex;
2527                                         descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
2528                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2529                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
2530                                         int resolvedPosition = localVariable.resolvedPosition;
2531                                         this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2532                                         this.contents[localContentsOffset++] = (byte) resolvedPosition;
2533                                 }
2534                                 for (int i = 0; i < genericArgumentsCounter; i++) {
2535                                         this.contents[localContentsOffset++] = 0;
2536                                         this.contents[localContentsOffset++] = 0;
2537                                         this.contents[localContentsOffset++] = (byte) (code_length >> 8);
2538                                         this.contents[localContentsOffset++] = (byte) code_length;
2539                                         nameIndex = genericArgumentsNameIndexes[i];
2540                                         this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2541                                         this.contents[localContentsOffset++] = (byte) nameIndex;
2542                                         descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
2543                                         this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2544                                         this.contents[localContentsOffset++] = (byte) descriptorIndex;
2545                                         int resolvedPosition = genericArgumentsResolvedPositions[i];
2546                                         this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2547                                         this.contents[localContentsOffset++] = (byte) resolvedPosition;
2548                                 }                               
2549                                 attributeNumber++;
2550                         }                       
2551                 }
2552                 // update the number of attributes// ensure first that there is enough space available inside the localContents array
2553                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2554                         resizeContents(2);
2555                 }
2556                 this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2557                 this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2558                 // update the attribute length
2559                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2560                 this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2561                 this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2562                 this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2563                 this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2564                 contentsOffset = localContentsOffset;
2565         }
2566
2567         /**
2568          * INTERNAL USE-ONLY
2569          * That method completes the creation of the code attribute by setting
2570          * - the attribute_length
2571          * - max_stack
2572          * - max_locals
2573          * - code_length
2574          * - exception table
2575          * - and debug attributes if necessary.
2576          *
2577          * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
2578          * @param codeAttributeOffset <CODE>int</CODE>
2579          */
2580         public void completeCodeAttributeForSyntheticMethod(
2581                 SyntheticMethodBinding binding,
2582                 int codeAttributeOffset,
2583                 int[] startLineIndexes) {
2584                 // reinitialize the contents with the byte modified by the code stream
2585                 this.contents = codeStream.bCodeStream;
2586                 int localContentsOffset = codeStream.classFileOffset;
2587                 // codeAttributeOffset is the position inside contents byte array before we started to write
2588                 // any information about the codeAttribute
2589                 // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
2590                 // to get the right position, 6 for the max_stack etc...
2591                 int max_stack = codeStream.stackMax;
2592                 contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2593                 contents[codeAttributeOffset + 7] = (byte) max_stack;
2594                 int max_locals = codeStream.maxLocals;
2595                 contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2596                 contents[codeAttributeOffset + 9] = (byte) max_locals;
2597                 int code_length = codeStream.position;
2598                 contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2599                 contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2600                 contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2601                 contents[codeAttributeOffset + 13] = (byte) code_length;
2602                 if ((localContentsOffset + 40) >= this.contents.length) {
2603                         resizeContents(40);
2604                 }
2605                 // there is no exception table, so we need to offset by 2 the current offset and move 
2606                 // on the attribute generation
2607                 contents[localContentsOffset++] = 0;
2608                 contents[localContentsOffset++] = 0;
2609                 // debug attributes
2610                 int codeAttributeAttributeOffset = localContentsOffset;
2611                 int attributeNumber = 0;
2612                 // leave two bytes for the attribute_length
2613                 localContentsOffset += 2;
2614
2615                 // first we handle the linenumber attribute
2616                 if (codeStream.generateLineNumberAttributes) {
2617                         int index = 0;
2618                         int lineNumberNameIndex =
2619                                 constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2620                         contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2621                         contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2622                         int lineNumberTableOffset = localContentsOffset;
2623                         localContentsOffset += 6;
2624                         // leave space for attribute_length and line_number_table_length
2625                         // Seems like do would be better, but this preserves the existing behavior.
2626                         index = searchLineNumber(startLineIndexes, binding.sourceStart);
2627                         contents[localContentsOffset++] = 0;
2628                         contents[localContentsOffset++] = 0;
2629                         contents[localContentsOffset++] = (byte) (index >> 8);
2630                         contents[localContentsOffset++] = (byte) index;
2631                         // now we change the size of the line number attribute
2632                         contents[lineNumberTableOffset++] = 0;
2633                         contents[lineNumberTableOffset++] = 0;
2634                         contents[lineNumberTableOffset++] = 0;
2635                         contents[lineNumberTableOffset++] = 6;
2636                         contents[lineNumberTableOffset++] = 0;
2637                         contents[lineNumberTableOffset++] = 1;
2638                         attributeNumber++;
2639                 }
2640                 // then we do the local variable attribute
2641                 if (codeStream.generateLocalVariableTableAttributes) {
2642                         int localVariableTableOffset = localContentsOffset;
2643                         int numberOfEntries = 0;
2644                         int localVariableNameIndex =
2645                                 constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
2646                         if (localContentsOffset + 8 > this.contents.length) {
2647                                 resizeContents(8);
2648                         }
2649                         contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2650                         contents[localContentsOffset++] = (byte) localVariableNameIndex;
2651                         localContentsOffset += 6;
2652                         // leave space for attribute_length and local_variable_table_length
2653                         int nameIndex;
2654                         int descriptorIndex;
2655
2656                         // used to remember the local variable with a generic type
2657                         int genericLocalVariablesCounter = 0;
2658                         LocalVariableBinding[] genericLocalVariables = null;
2659                         int numberOfGenericEntries = 0;
2660                         
2661                         for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
2662                                 LocalVariableBinding localVariable = codeStream.locals[i];
2663                                 final TypeBinding localVariableTypeBinding = localVariable.type;
2664                                 boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
2665                                 if (localVariable.initializationCount != 0 && isParameterizedType) {
2666                                         if (genericLocalVariables == null) {
2667                                                 // we cannot have more than max locals
2668                                                 genericLocalVariables = new LocalVariableBinding[max];
2669                                         }
2670                                         genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
2671                                 }
2672                                 for (int j = 0; j < localVariable.initializationCount; j++) {
2673                                         int startPC = localVariable.initializationPCs[j << 1];
2674                                         int endPC = localVariable.initializationPCs[(j << 1) + 1];
2675                                         if (startPC != endPC) { // only entries for non zero length
2676                                                 if (endPC == -1) {
2677                                                         localVariable.declaringScope.problemReporter().abortDueToInternalError(
2678                                                                 Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
2679                                                                 (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
2680                                                 }
2681                                                 if (localContentsOffset + 10 > this.contents.length) {
2682                                                         resizeContents(10);
2683                                                 }
2684                                                 // now we can safely add the local entry
2685                                                 numberOfEntries++;
2686                                                 if (isParameterizedType) {
2687                                                         numberOfGenericEntries++;
2688                                                 }
2689                                                 contents[localContentsOffset++] = (byte) (startPC >> 8);
2690                                                 contents[localContentsOffset++] = (byte) startPC;
2691                                                 int length = endPC - startPC;
2692                                                 contents[localContentsOffset++] = (byte) (length >> 8);
2693                                                 contents[localContentsOffset++] = (byte) length;
2694                                                 nameIndex = constantPool.literalIndex(localVariable.name);
2695                                                 contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2696                                                 contents[localContentsOffset++] = (byte) nameIndex;
2697                                                 descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
2698                                                 contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2699                                                 contents[localContentsOffset++] = (byte) descriptorIndex;
2700                                                 int resolvedPosition = localVariable.resolvedPosition;
2701                                                 contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2702                                                 contents[localContentsOffset++] = (byte) resolvedPosition;
2703                                         }
2704                                 }
2705                         }
2706                         int value = numberOfEntries * 10 + 2;
2707                         localVariableTableOffset += 2;
2708                         contents[localVariableTableOffset++] = (byte) (value >> 24);
2709                         contents[localVariableTableOffset++] = (byte) (value >> 16);
2710                         contents[localVariableTableOffset++] = (byte) (value >> 8);
2711                         contents[localVariableTableOffset++] = (byte) value;
2712                         contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
2713                         contents[localVariableTableOffset] = (byte) numberOfEntries;
2714                         attributeNumber++;
2715
2716                         if (genericLocalVariablesCounter != 0) {
2717                                 // add the local variable type table attribute
2718                                 int maxOfEntries = 8 + numberOfGenericEntries * 10;
2719                                 // reserve enough space
2720                                 if (localContentsOffset + maxOfEntries >= this.contents.length) {
2721                                         resizeContents(maxOfEntries);
2722                                 }
2723                                 int localVariableTypeNameIndex =
2724                                         constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
2725                                 contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
2726                                 contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
2727                                 value = numberOfGenericEntries * 10 + 2;
2728                                 contents[localContentsOffset++] = (byte) (value >> 24);
2729                                 contents[localContentsOffset++] = (byte) (value >> 16);
2730                                 contents[localContentsOffset++] = (byte) (value >> 8);
2731                                 contents[localContentsOffset++] = (byte) value;
2732                                 contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
2733                                 contents[localContentsOffset++] = (byte) numberOfGenericEntries;
2734
2735                                 for (int i = 0; i < genericLocalVariablesCounter; i++) {
2736                                         LocalVariableBinding localVariable = genericLocalVariables[i];
2737                                         for (int j = 0; j < localVariable.initializationCount; j++) {
2738                                                 int startPC = localVariable.initializationPCs[j << 1];
2739                                                 int endPC = localVariable.initializationPCs[(j << 1) + 1];
2740                                                 if (startPC != endPC) { // only entries for non zero length
2741                                                         // now we can safely add the local entry
2742                                                         contents[localContentsOffset++] = (byte) (startPC >> 8);
2743                                                         contents[localContentsOffset++] = (byte) startPC;
2744                                                         int length = endPC - startPC;
2745                                                         contents[localContentsOffset++] = (byte) (length >> 8);
2746                                                         contents[localContentsOffset++] = (byte) length;
2747                                                         nameIndex = constantPool.literalIndex(localVariable.name);
2748                                                         contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2749                                                         contents[localContentsOffset++] = (byte) nameIndex;
2750                                                         descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
2751                                                         contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2752                                                         contents[localContentsOffset++] = (byte) descriptorIndex;
2753                                                         int resolvedPosition = localVariable.resolvedPosition;
2754                                                         contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2755                                                         contents[localContentsOffset++] = (byte) resolvedPosition;
2756                                                 }
2757                                         }
2758                                 }
2759                                 attributeNumber++;
2760                         }
2761                 }
2762                 // update the number of attributes
2763                 // ensure first that there is enough space available inside the contents array
2764                 if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2765                         resizeContents(2);
2766                 }
2767                 contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2768                 contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2769
2770                 // update the attribute length
2771                 int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2772                 contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2773                 contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2774                 contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2775                 contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2776                 contentsOffset = localContentsOffset;
2777         }
2778
2779         /**
2780          * INTERNAL USE-ONLY
2781          * Complete the creation of a method info by setting up the number of attributes at the right offset.
2782          *
2783          * @param methodAttributeOffset <CODE>int</CODE>
2784          * @param attributeNumber <CODE>int</CODE> 
2785          */
2786         public void completeMethodInfo(
2787                 int methodAttributeOffset,
2788                 int attributeNumber) {
2789                 // update the number of attributes
2790                 contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
2791                 contents[methodAttributeOffset] = (byte) attributeNumber;
2792         }
2793
2794         /**
2795          * INTERNAL USE-ONLY
2796          * This methods returns a char[] representing the file name of the receiver
2797          *
2798          * @return char[]
2799          */
2800         public char[] fileName() {
2801                 return constantPool.UTF8Cache.returnKeyFor(1);
2802         }
2803
2804         private void generateAnnotation(Annotation annotation, int attributeOffset) {
2805                 if (contentsOffset + 4 >= this.contents.length) {
2806                         resizeContents(4);
2807                 }
2808                 TypeBinding annotationTypeBinding = annotation.resolvedType;
2809                 if (annotationTypeBinding == null) {
2810                         this.contentsOffset = attributeOffset;
2811                         return;
2812                 }
2813                 final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
2814                 contents[contentsOffset++] = (byte) (typeIndex >> 8);
2815                 contents[contentsOffset++] = (byte) typeIndex;
2816                 if (annotation instanceof NormalAnnotation) {
2817                         NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
2818                         MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
2819                         if (memberValuePairs != null) {
2820                                 final int memberValuePairsLength = memberValuePairs.length;
2821                                 contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
2822                                 contents[contentsOffset++] = (byte) memberValuePairsLength;
2823                                 for (int i = 0; i < memberValuePairsLength; i++) {
2824                                         MemberValuePair memberValuePair = memberValuePairs[i];
2825                                         if (contentsOffset + 2 >= this.contents.length) {
2826                                                 resizeContents(2);
2827                                         }
2828                                         final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
2829                                         contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
2830                                         contents[contentsOffset++] = (byte) elementNameIndex;
2831                                         MethodBinding methodBinding = memberValuePair.binding;
2832                                         if (methodBinding == null) {
2833                                                 contentsOffset = attributeOffset;
2834                                         } else {
2835                                                 generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
2836                                         }
2837                                 }
2838                         } else {
2839                                 contents[contentsOffset++] = 0;
2840                                 contents[contentsOffset++] = 0;
2841                         }
2842                 } else if (annotation instanceof SingleMemberAnnotation) {
2843                         SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
2844                         // this is a single member annotation (one member value)
2845                         contents[contentsOffset++] = 0;
2846                         contents[contentsOffset++] = 1;
2847                         if (contentsOffset + 2 >= this.contents.length) {
2848                                 resizeContents(2);
2849                         }
2850                         final int elementNameIndex = constantPool.literalIndex(VALUE);
2851                         contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
2852                         contents[contentsOffset++] = (byte) elementNameIndex;
2853                         MethodBinding methodBinding = singleMemberAnnotation.singlePair.binding;
2854                         if (methodBinding == null) {
2855                                 contentsOffset = attributeOffset;
2856                         } else {
2857                                 generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
2858                         }
2859                 } else {
2860                         // this is a marker annotation (no member value pairs)
2861                         contents[contentsOffset++] = 0;
2862                         contents[contentsOffset++] = 0;
2863                 }
2864         }
2865
2866         /**
2867          * INTERNAL USE-ONLY
2868          * That method generates the header of a code attribute.
2869          * - the index inside the constant pool for the attribute name ("Code")
2870          * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
2871          */
2872         public void generateCodeAttributeHeader() {
2873                 if (contentsOffset + 20 >= this.contents.length) {
2874                         resizeContents(20);
2875                 }
2876                 int constantValueNameIndex =
2877                         constantPool.literalIndex(AttributeNamesConstants.CodeName);
2878                 contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
2879                 contents[contentsOffset++] = (byte) constantValueNameIndex;
2880                 // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
2881                 contentsOffset += 12;
2882         }
2883
2884         private void generateElementValue(
2885                         Expression defaultValue,
2886                         TypeBinding memberValuePairReturnType,
2887                         int attributeOffset) {
2888                 Constant constant = defaultValue.constant;
2889                 TypeBinding defaultValueBinding = defaultValue.resolvedType;
2890                 if (defaultValueBinding == null) {
2891                         contentsOffset = attributeOffset;
2892                 } else {
2893                         if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
2894                                 // automatic wrapping
2895                                 if (contentsOffset + 3 >= this.contents.length) {
2896                                         resizeContents(3);
2897                                 }
2898                                 contents[contentsOffset++] = (byte) '[';
2899                                 contents[contentsOffset++] = (byte) 0;
2900                                 contents[contentsOffset++] = (byte) 1;
2901                         }
2902                         if (constant != null && constant != Constant.NotAConstant) {
2903                                 generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
2904                         } else {
2905                                 generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
2906                         }
2907                 }
2908         }
2909
2910         /**
2911          * @param attributeOffset
2912          */
2913         private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
2914                 if (contentsOffset + 3 >= this.contents.length) {
2915                         resizeContents(3);
2916                 }
2917                 switch (binding.id) {
2918                         case T_boolean :
2919                                 contents[contentsOffset++] = (byte) 'Z';
2920                                 int booleanValueIndex =
2921                                         constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
2922                                 contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
2923                                 contents[contentsOffset++] = (byte) booleanValueIndex;
2924                                 break;
2925                         case T_byte :
2926                                 contents[contentsOffset++] = (byte) 'B';
2927                                 int integerValueIndex =
2928                                         constantPool.literalIndex(constant.intValue());
2929                                 contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
2930                                 contents[contentsOffset++] = (byte) integerValueIndex;
2931                                 break;
2932                         case T_char :
2933                                 contents[contentsOffset++] = (byte) 'C';
2934                                 integerValueIndex =
2935                                         constantPool.literalIndex(constant.intValue());
2936                                 contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
2937                                 contents[contentsOffset++] = (byte) integerValueIndex;
2938                                 break;
2939                         case T_int :
2940                                 contents[contentsOffset++] = (byte) 'I';
2941                                 integerValueIndex =
2942                                         constantPool.literalIndex(constant.intValue());
2943                                 contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
2944                                 contents[contentsOffset++] = (byte) integerValueIndex;
2945                                 break;
2946                         case T_short :
2947                                 contents[contentsOffset++] = (byte) 'S';
2948                                 integerValueIndex =
2949                                         constantPool.literalIndex(constant.intValue());
2950                                 contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
2951                                 contents[contentsOffset++] = (byte) integerValueIndex;
2952                                 break;
2953                         case T_float :
2954                                 contents[contentsOffset++] = (byte) 'F';
2955                                 int floatValueIndex =
2956                                         constantPool.literalIndex(constant.floatValue());
2957                                 contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
2958                                 contents[contentsOffset++] = (byte) floatValueIndex;
2959                                 break;
2960                         case T_double :
2961                                 contents[contentsOffset++] = (byte) 'D';
2962                                 int doubleValueIndex =
2963                                         constantPool.literalIndex(constant.doubleValue());
2964                                 contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
2965                                 contents[contentsOffset++] = (byte) doubleValueIndex;
2966                                 break;
2967                         case T_long :
2968                                 contents[contentsOffset++] = (byte) 'J';
2969                                 int longValueIndex =
2970                                         constantPool.literalIndex(constant.longValue());
2971                                 contents[contentsOffset++] = (byte) (longValueIndex >> 8);
2972                                 contents[contentsOffset++] = (byte) longValueIndex;
2973                                 break;
2974                         case T_JavaLangString :
2975                                 contents[contentsOffset++] = (byte) 's';
2976                                 int stringValueIndex =
2977                                         constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
2978                                 if (stringValueIndex == -1) {
2979                                         if (!creatingProblemType) {
2980                                                 // report an error and abort: will lead to a problem type classfile creation
2981                                                 TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
2982                                                 typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
2983                                         } else {
2984                                                 // already inside a problem type creation : no attribute
2985                                                 contentsOffset = attributeOffset;
2986                                         }
2987                                 } else {
2988                                         contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
2989                                         contents[contentsOffset++] = (byte) stringValueIndex;
2990                                 }
2991                 }
2992         }
2993         
2994         private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
2995                 if (defaultValueBinding != null) {
2996                         if (defaultValueBinding.isEnum()) {
2997                                 if (contentsOffset + 5 >= this.contents.length) {
2998                                         resizeContents(5);
2999                                 }
3000                                 contents[contentsOffset++] = (byte) 'e';
3001                                 FieldBinding fieldBinding = null;
3002                                 if (defaultValue instanceof QualifiedNameReference) {
3003                                         QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
3004                                         fieldBinding = (FieldBinding) nameReference.binding;
3005                                 } else if (defaultValue instanceof SingleNameReference) {
3006                                         SingleNameReference nameReference = (SingleNameReference) defaultValue;
3007                                         fieldBinding = (FieldBinding) nameReference.binding;
3008                                 } else {
3009                                         contentsOffset = attributeOffset;
3010                                 }
3011                                 if (fieldBinding != null) {
3012                                         final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
3013                                         final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
3014                                         contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
3015                                         contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
3016                                         contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
3017                                         contents[contentsOffset++] = (byte) enumConstantNameIndex;
3018                                 }
3019                         } else if (defaultValueBinding.isAnnotationType()) {
3020                                 if (contentsOffset + 1 >= this.contents.length) {
3021                                         resizeContents(1);
3022                                 }
3023                                 contents[contentsOffset++] = (byte) '@';
3024                                 generateAnnotation((Annotation) defaultValue, attributeOffset);
3025                         } else if (defaultValueBinding.isArrayType()) {
3026                                 // array type
3027                                 if (contentsOffset + 3 >= this.contents.length) {
3028                                         resizeContents(3);
3029                                 }
3030                                 contents[contentsOffset++] = (byte) '[';
3031                                 if (defaultValue instanceof ArrayInitializer) {
3032                                         ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
3033                                         int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
3034                                         contents[contentsOffset++] = (byte) (arrayLength >> 8);
3035                                         contents[contentsOffset++] = (byte) arrayLength;
3036                                         for (int i = 0; i < arrayLength; i++) {
3037                                                 generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
3038                                         }
3039                                 } else {
3040                                         contentsOffset = attributeOffset;
3041                                 }
3042                         } else {
3043                                 // class type
3044                                 if (contentsOffset + 3 >= this.contents.length) {
3045                                         resizeContents(3);
3046                                 }
3047                                 contents[contentsOffset++] = (byte) 'c';
3048                                 if (defaultValue instanceof ClassLiteralAccess) {
3049                                         ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
3050                                         final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
3051                                         contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
3052                                         contents[contentsOffset++] = (byte) classInfoIndex;
3053                                 } else {
3054                                         contentsOffset = attributeOffset;
3055                                 }
3056                         }
3057                 } else {
3058                         contentsOffset = attributeOffset;
3059                 }
3060         }
3061
3062         public int generateMethodInfoAttribute(MethodBinding methodBinding) {
3063                 return generateMethodInfoAttribute(methodBinding, false);
3064         }
3065         /**
3066          * INTERNAL USE-ONLY
3067          * That method generates the attributes of a code attribute.
3068          * They could be:
3069          * - an exception attribute for each try/catch found inside the method
3070          * - a deprecated attribute
3071          * - a synthetic attribute for synthetic access methods
3072          *
3073          * It returns the number of attributes created for the code attribute.
3074          *
3075          * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
3076          * @return <CODE>int</CODE>
3077          */
3078         public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
3079                 // leave two bytes for the attribute_number
3080                 contentsOffset += 2;
3081                 // now we can handle all the attribute for that method info:
3082                 // it could be:
3083                 // - a CodeAttribute
3084                 // - a ExceptionAttribute
3085                 // - a DeprecatedAttribute
3086                 // - a SyntheticAttribute
3087
3088                 // Exception attribute
3089                 ReferenceBinding[] thrownsExceptions;
3090                 int attributeNumber = 0;
3091                 if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
3092                         // The method has a throw clause. So we need to add an exception attribute
3093                         // check that there is enough space to write all the bytes for the exception attribute
3094                         int length = thrownsExceptions.length;
3095                         int exSize = 8 + length * 2;
3096                         if (exSize + contentsOffset >= this.contents.length) {
3097                                 resizeContents(exSize);
3098                         }
3099                         int exceptionNameIndex =
3100                                 constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
3101                         contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
3102                         contents[contentsOffset++] = (byte) exceptionNameIndex;
3103                         // The attribute length = length * 2 + 2 in case of a exception attribute
3104                         int attributeLength = length * 2 + 2;
3105                         contents[contentsOffset++] = (byte) (attributeLength >> 24);
3106                         contents[contentsOffset++] = (byte) (attributeLength >> 16);
3107                         contents[contentsOffset++] = (byte) (attributeLength >> 8);
3108                         contents[contentsOffset++] = (byte) attributeLength;
3109                         contents[contentsOffset++] = (byte) (length >> 8);
3110                         contents[contentsOffset++] = (byte) length;
3111                         for (int i = 0; i < length; i++) {
3112                                 int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName());
3113                                 contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
3114                                 contents[contentsOffset++] = (byte) exceptionIndex;
3115                         }
3116                         attributeNumber++;
3117                 }
3118                 if (methodBinding.isDeprecated()) {
3119                         // Deprecated attribute
3120                         // Check that there is enough space to write the deprecated attribute
3121                         if (contentsOffset + 6 >= this.contents.length) {
3122                                 resizeContents(6);
3123                         }
3124                         int deprecatedAttributeNameIndex =
3125                                 constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
3126                         contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
3127                         contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
3128                         // the length of a deprecated attribute is equals to 0
3129                         contents[contentsOffset++] = 0;
3130                         contents[contentsOffset++] = 0;
3131                         contents[contentsOffset++] = 0;
3132                         contents[contentsOffset++] = 0;
3133
3134                         attributeNumber++;
3135                 }
3136                 if (this.targetJDK < ClassFileConstants.JDK1_5 && methodBinding.isSynthetic()) {
3137                         // Synthetic attribute
3138                         // Check that there is enough space to write the deprecated attribute
3139                         if (contentsOffset + 6 >= this.contents.length) {
3140                                 resizeContents(6);
3141                         }
3142                         int syntheticAttributeNameIndex =
3143                                 constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
3144                         contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
3145                         contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
3146                         // the length of a synthetic attribute is equals to 0
3147                         contents[contentsOffset++] = 0;
3148                         contents[contentsOffset++] = 0;
3149                         contents[contentsOffset++] = 0;
3150                         contents[contentsOffset++] = 0;
3151
3152                         attributeNumber++;
3153                 }
3154                 // add signature attribute
3155                 char[] genericSignature = methodBinding.genericSignature();
3156                 if (genericSignature != null) {
3157                         // check that there is enough space to write all the bytes for the field info corresponding
3158                         // to the @fieldBinding
3159                         if (contentsOffset + 8 >= this.contents.length) {
3160                                 resizeContents(8);
3161                         }
3162                         int signatureAttributeNameIndex =
3163                                 constantPool.literalIndex(AttributeNamesConstants.SignatureName);
3164                         contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
3165                         contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
3166                         // the length of a signature attribute is equals to 2
3167                         contents[contentsOffset++] = 0;
3168                         contents[contentsOffset++] = 0;
3169                         contents[contentsOffset++] = 0;
3170                         contents[contentsOffset++] = 2;
3171                         int signatureIndex =
3172                                 constantPool.literalIndex(genericSignature);
3173                         contents[contentsOffset++] = (byte) (signatureIndex >> 8);
3174                         contents[contentsOffset++] = (byte) signatureIndex;
3175                         attributeNumber++;
3176                 }
3177                 if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
3178                         AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
3179                         if (methodDeclaration != null) {
3180                                 Annotation[] annotations = methodDeclaration.annotations;
3181                                 if (annotations != null) {
3182                                         attributeNumber += generateRuntimeAnnotations(annotations);
3183                                 }
3184                                 if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
3185                                         Argument[] arguments = methodDeclaration.arguments;
3186                                         if (arguments != null) {
3187                                                 attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
3188                                         }
3189                                 }
3190                         }
3191                 }
3192                 return attributeNumber;
3193         }
3194
3195         public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
3196                 int attributesNumber = generateMethodInfoAttribute(methodBinding);
3197                 int attributeOffset = contentsOffset;
3198                 if ((declaration.modifiers & AccAnnotationDefault) != 0) {
3199                         // add an annotation default attribute
3200                         int annotationDefaultNameIndex =
3201                                 constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
3202                         contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
3203                         contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
3204                         int attributeLengthOffset = contentsOffset;
3205                         contentsOffset += 4;
3206
3207                         generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
3208                         if (contentsOffset != attributeOffset) {
3209                                 int attributeLength = contentsOffset - attributeLengthOffset - 4;
3210                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
3211                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
3212                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
3213                                 contents[attributeLengthOffset++] = (byte) attributeLength;                     
3214                                 attributesNumber++;
3215                         }
3216                 }
3217                 return attributesNumber;
3218         }
3219
3220         /**
3221          * INTERNAL USE-ONLY
3222          * That method generates the header of a method info:
3223          * The header consists in:
3224          * - the access flags
3225          * - the name index of the method name inside the constant pool
3226          * - the descriptor index of the signature of the method inside the constant pool.
3227          *
3228          * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
3229          */
3230         public void generateMethodInfoHeader(MethodBinding methodBinding) {
3231                 generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
3232         }
3233         /**
3234          * INTERNAL USE-ONLY
3235          * That method generates the header of a method info:
3236          * The header consists in:
3237          * - the access flags
3238          * - the name index of the method name inside the constant pool
3239          * - the descriptor index of the signature of the method inside the constant pool.
3240          *
3241          * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
3242          * @param accessFlags the access flags
3243          */
3244         public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
3245                 // check that there is enough space to write all the bytes for the method info corresponding
3246                 // to the @methodBinding
3247                 methodCount++; // add one more method
3248                 if (contentsOffset + 10 >= this.contents.length) {
3249                         resizeContents(10);
3250                 }
3251                 if (targetJDK < ClassFileConstants.JDK1_5) {
3252                     // pre 1.5, synthetic was an attribute, not a modifier
3253                     accessFlags &= ~AccSynthetic;
3254                 }
3255                 if (methodBinding.isRequiredToClearPrivateModifier()) {
3256                         accessFlags &= ~AccPrivate;
3257                 }
3258                 contents[contentsOffset++] = (byte) (accessFlags >> 8);
3259                 contents[contentsOffset++] = (byte) accessFlags;
3260                 int nameIndex = constantPool.literalIndex(methodBinding.selector);
3261                 contents[contentsOffset++] = (byte) (nameIndex >> 8);
3262                 contents[contentsOffset++] = (byte) nameIndex;
3263                 int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
3264                 contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
3265                 contents[contentsOffset++] = (byte) descriptorIndex;
3266         }
3267
3268         /**
3269          * INTERNAL USE-ONLY
3270          * That method generates the method info header of a clinit:
3271          * The header consists in:
3272          * - the access flags (always default access + static)
3273          * - the name index of the method name (always <clinit>) inside the constant pool 
3274          * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
3275          */
3276         public void generateMethodInfoHeaderForClinit() {
3277                 // check that there is enough space to write all the bytes for the method info corresponding
3278                 // to the @methodBinding
3279                 methodCount++; // add one more method
3280                 if (contentsOffset + 10 >= this.contents.length) {
3281                         resizeContents(10);
3282                 }
3283                 contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
3284                 contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
3285                 int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
3286                 contents[contentsOffset++] = (byte) (nameIndex >> 8);
3287                 contents[contentsOffset++] = (byte) nameIndex;
3288                 int descriptorIndex =
3289                         constantPool.literalIndex(ConstantPool.ClinitSignature);
3290                 contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
3291                 contents[contentsOffset++] = (byte) descriptorIndex;
3292                 // We know that we won't get more than 1 attribute: the code attribute
3293                 contents[contentsOffset++] = 0;
3294                 contents[contentsOffset++] = 1;
3295         }
3296
3297         /**
3298          * INTERNAL USE-ONLY
3299          * Generate the byte for problem method infos that correspond to missing abstract methods.
3300          * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
3301          *
3302          * @param methodDeclarations Array of all missing abstract methods
3303          */
3304         public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
3305                 if (methodDeclarations != null) {
3306                         for (int i = 0, max = methodDeclarations.length; i < max; i++) {
3307                                 MethodDeclaration methodDeclaration = methodDeclarations[i];
3308                                 MethodBinding methodBinding = methodDeclaration.binding;
3309                                 String readableName = new String(methodBinding.readableName());
3310                                 IProblem[] problems = compilationResult.problems;
3311                                 int problemsCount = compilationResult.problemCount;
3312                                 for (int j = 0; j < problemsCount; j++) {
3313                                         IProblem problem = problems[j];
3314                                         if (problem != null
3315                                                 && problem.getID() == IProblem.AbstractMethodMustBeImplemented
3316                                                 && problem.getMessage().indexOf(readableName) != -1) {
3317                                                         // we found a match
3318                                                         addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
3319                                                 }
3320                                 }
3321                         }
3322                 }
3323         }
3324
3325         /**
3326          * @param annotations
3327          * @return the number of attributes created while dumping the annotations in the .class file
3328          */
3329         private int generateRuntimeAnnotations(final Annotation[] annotations) {
3330                 int attributesNumber = 0;
3331                 final int length = annotations.length;
3332                 int visibleAnnotationsCounter = 0;
3333                 int invisibleAnnotationsCounter = 0;
3334                 
3335                 for (int i = 0; i < length; i++) {
3336                         Annotation annotation = annotations[i];
3337                         if (isRuntimeInvisible(annotation)) {
3338                                 invisibleAnnotationsCounter++;
3339                         } else if (isRuntimeVisible(annotation)) {
3340                                 visibleAnnotationsCounter++;
3341                         }
3342                 }
3343
3344                 if (invisibleAnnotationsCounter != 0) {
3345                         int annotationAttributeOffset = contentsOffset;
3346                         if (contentsOffset + 10 >= contents.length) {
3347                                 resizeContents(10);
3348                         }
3349                         int runtimeInvisibleAnnotationsAttributeNameIndex =
3350                                 constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
3351                         contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
3352                         contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
3353                         int attributeLengthOffset = contentsOffset;
3354                         contentsOffset += 4; // leave space for the attribute length
3355         
3356                         int annotationsLengthOffset = contentsOffset;
3357                         contentsOffset += 2; // leave space for the annotations length
3358                 
3359                         contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
3360                         contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
3361
3362                         loop: for (int i = 0; i < length; i++) {
3363                                 if (invisibleAnnotationsCounter == 0) break loop;
3364                                 Annotation annotation = annotations[i];
3365                                 if (isRuntimeInvisible(annotation)) {
3366                                         generateAnnotation(annotation, annotationAttributeOffset);
3367                                         invisibleAnnotationsCounter--;
3368                                         if (this.contentsOffset == annotationAttributeOffset) {
3369                                                 break loop;
3370                                         }
3371                                 }
3372                         }
3373                         if (contentsOffset != annotationAttributeOffset) {
3374                                 int attributeLength = contentsOffset - attributeLengthOffset - 4;
3375                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
3376                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
3377                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
3378                                 contents[attributeLengthOffset++] = (byte) attributeLength;                     
3379                                 attributesNumber++;
3380                         } else {                
3381                                 contentsOffset = annotationAttributeOffset;
3382                         }
3383                 }
3384         
3385                 if (visibleAnnotationsCounter != 0) {
3386                         int annotationAttributeOffset = contentsOffset;
3387                         if (contentsOffset + 10 >= contents.length) {
3388                                 resizeContents(10);
3389                         }
3390                         int runtimeVisibleAnnotationsAttributeNameIndex =
3391                                 constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
3392                         contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
3393                         contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
3394                         int attributeLengthOffset = contentsOffset;
3395                         contentsOffset += 4; // leave space for the attribute length
3396         
3397                         int annotationsLengthOffset = contentsOffset;
3398                         contentsOffset += 2; // leave space for the annotations length
3399                 
3400                         contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
3401                         contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
3402
3403                         loop: for (int i = 0; i < length; i++) {
3404                                 if (visibleAnnotationsCounter == 0) break loop;
3405                                 Annotation annotation = annotations[i];
3406                                 if (isRuntimeVisible(annotation)) {
3407                                         visibleAnnotationsCounter--;
3408                                         generateAnnotation(annotation, annotationAttributeOffset);
3409                                         if (this.contentsOffset == annotationAttributeOffset) {
3410                                                 break loop;
3411                                         }
3412                                 }
3413                         }
3414                         if (contentsOffset != annotationAttributeOffset) {
3415                                 int attributeLength = contentsOffset - attributeLengthOffset - 4;
3416                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
3417                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
3418                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
3419                                 contents[attributeLengthOffset++] = (byte) attributeLength;                     
3420                                 attributesNumber++;
3421                         } else {
3422                                 contentsOffset = annotationAttributeOffset;
3423                         }
3424                 }
3425                 return attributesNumber;
3426         }
3427         
3428         private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
3429                 final int argumentsLength = arguments.length;
3430                 final int VISIBLE_INDEX = 0;
3431                 final int INVISIBLE_INDEX = 1;
3432                 int invisibleParametersAnnotationsCounter = 0;
3433                 int visibleParametersAnnotationsCounter = 0;
3434                 int[][] annotationsCounters = new int[argumentsLength][2];
3435                 for (int i = 0; i < argumentsLength; i++) {
3436                         Argument argument = arguments[i];
3437                         Annotation[] annotations = argument.annotations;
3438                         if (annotations != null) {
3439                                 for (int j = 0, max2 = annotations.length; j < max2; j++) {
3440                                         Annotation annotation = annotations[j];
3441                                         if (isRuntimeInvisible(annotation)) {
3442                                                 annotationsCounters[i][INVISIBLE_INDEX]++;
3443                                                 invisibleParametersAnnotationsCounter++;
3444                                         } else if (isRuntimeVisible(annotation)) {
3445                                                 annotationsCounters[i][VISIBLE_INDEX]++;
3446                                                 visibleParametersAnnotationsCounter++;
3447                                         }
3448                                 }
3449                         }
3450                 }
3451                 int attributesNumber = 0;
3452                 int annotationAttributeOffset = contentsOffset;
3453                 if (invisibleParametersAnnotationsCounter != 0) {
3454                         if (contentsOffset + 7 >= contents.length) {
3455                                 resizeContents(7);
3456                         }
3457                         int attributeNameIndex =
3458                                 constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
3459                         contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
3460                         contents[contentsOffset++] = (byte) attributeNameIndex;
3461                         int attributeLengthOffset = contentsOffset;
3462                         contentsOffset += 4; // leave space for the attribute length
3463
3464                         contents[contentsOffset++] = (byte) argumentsLength;
3465                         invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
3466                                 if (contentsOffset + 2 >= contents.length) {
3467                                         resizeContents(2);
3468                                 }
3469                                 if (invisibleParametersAnnotationsCounter == 0) {
3470                                         contents[contentsOffset++] = (byte) 0;
3471                                         contents[contentsOffset++] = (byte) 0;                                  
3472                                 } else {
3473                                         final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
3474                                         contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
3475                                         contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
3476                                         if (numberOfInvisibleAnnotations != 0) {
3477                                                 Argument argument = arguments[i];
3478                                                 Annotation[] annotations = argument.annotations;
3479                                                 for (int j = 0, max = annotations.length; j < max; j++) {
3480                                                         Annotation annotation = annotations[j];
3481                                                         if (isRuntimeInvisible(annotation)) {
3482                                                                 generateAnnotation(annotation, annotationAttributeOffset);
3483                                                                 if (contentsOffset == annotationAttributeOffset) {
3484                                                                         break invisibleLoop;
3485                                                                 }
3486                                                                 invisibleParametersAnnotationsCounter--;
3487                                                         }
3488                                                 }
3489                                         }
3490                                 }
3491                         }
3492                         if (contentsOffset != annotationAttributeOffset) {
3493                                 int attributeLength = contentsOffset - attributeLengthOffset - 4;
3494                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
3495                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
3496                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
3497                                 contents[attributeLengthOffset++] = (byte) attributeLength;                     
3498                                 attributesNumber++;
3499                         } else {
3500                                 contentsOffset = annotationAttributeOffset;
3501                         }
3502                 }
3503                 if (visibleParametersAnnotationsCounter != 0) {
3504                         if (contentsOffset + 7 >= contents.length) {
3505                                 resizeContents(7);
3506                         }
3507                         int attributeNameIndex =
3508                                 constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
3509                         contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
3510                         contents[contentsOffset++] = (byte) attributeNameIndex;
3511                         int attributeLengthOffset = contentsOffset;
3512                         contentsOffset += 4; // leave space for the attribute length
3513
3514                         contents[contentsOffset++] = (byte) argumentsLength;
3515                         visibleLoop: for (int i = 0; i < argumentsLength; i++) {
3516                                 if (contentsOffset + 2 >= contents.length) {
3517                                         resizeContents(2);
3518                                 }
3519                                 if (visibleParametersAnnotationsCounter == 0) {
3520                                         contents[contentsOffset++] = (byte) 0;
3521                                         contents[contentsOffset++] = (byte) 0;                                  
3522                                 } else {
3523                                         final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
3524                                         contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
3525                                         contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
3526                                         if (numberOfVisibleAnnotations != 0) {
3527                                                 Argument argument = arguments[i];
3528                                                 Annotation[] annotations = argument.annotations;
3529                                                 for (int j = 0, max = annotations.length; j < max; j++) {
3530                                                         Annotation annotation = annotations[j];
3531                                                         if (isRuntimeVisible(annotation)) {
3532                                                                 generateAnnotation(annotation, annotationAttributeOffset);
3533                                                                 if (contentsOffset == annotationAttributeOffset) {
3534                                                                         break visibleLoop;
3535                                                                 }
3536                                                                 visibleParametersAnnotationsCounter--;
3537                                                         }
3538                                                 }
3539                                         }
3540                                 }
3541                         }
3542                         if (contentsOffset != annotationAttributeOffset) {
3543                                 int attributeLength = contentsOffset - attributeLengthOffset - 4;
3544                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
3545                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
3546                                 contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
3547                                 contents[attributeLengthOffset++] = (byte) attributeLength;                     
3548                                 attributesNumber++;
3549                         } else {
3550                                 contentsOffset = annotationAttributeOffset;
3551                         }
3552                 }
3553                 return attributesNumber;
3554         }
3555         /**
3556          * EXTERNAL API
3557          * Answer the actual bytes of the class file
3558          *
3559          * This method encodes the receiver structure into a byte array which is the content of the classfile.
3560          * Returns the byte array that represents the encoded structure of the receiver.
3561          *
3562          * @return byte[]
3563          */
3564         public byte[] getBytes() {
3565                 byte[] fullContents = new byte[headerOffset + contentsOffset];
3566                 System.arraycopy(header, 0, fullContents, 0, headerOffset);
3567                 System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
3568                 return fullContents;
3569         }
3570
3571         /**
3572          * EXTERNAL API
3573          * Answer the compound name of the class file.
3574          * @return char[][]
3575          * e.g. {{java}, {util}, {Hashtable}}.
3576          */
3577         public char[][] getCompoundName() {
3578                 return CharOperation.splitOn('/', fileName());
3579         }
3580
3581         protected void initByteArrays() {
3582                 LookupEnvironment env = this.referenceBinding.scope.environment();
3583                 synchronized (env) {
3584                         if (env.sharedArraysUsed) {
3585                                 this.ownSharedArrays = false;
3586                                 int members = referenceBinding.methods().length + referenceBinding.fields().length;
3587                                 this.header = new byte[INITIAL_HEADER_SIZE];
3588                                 this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
3589                         } else {
3590                                 this.ownSharedArrays = env.sharedArraysUsed = true;
3591                                 this.header = env.sharedClassFileHeader;
3592                                 this.contents = env.sharedClassFileContents;
3593                         }
3594                 }
3595         }
3596
3597         
3598         private boolean isRuntimeInvisible(Annotation annotation) {
3599                 final TypeBinding annotationBinding = annotation.resolvedType;
3600                 if (annotationBinding == null) {
3601                         return false;
3602                 }
3603                 long metaTagBits = annotationBinding.getAnnotationTagBits();
3604                 if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
3605                         return true; // by default the retention is CLASS
3606                         
3607                 return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
3608         }
3609
3610         private boolean isRuntimeVisible(Annotation annotation) {
3611                 final TypeBinding annotationBinding = annotation.resolvedType;
3612                 if (annotationBinding == null) {
3613                         return false;
3614                 }
3615                 long metaTagBits = annotationBinding.tagBits;
3616                 if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
3617                         return false; // by default the retention is CLASS
3618                         
3619                 return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
3620         }
3621
3622         /**
3623          * INTERNAL USE-ONLY
3624          * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
3625          * for all inner types of the receiver.
3626          * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
3627          */
3628         public ClassFile outerMostEnclosingClassFile() {
3629                 ClassFile current = this;
3630                 while (current.enclosingClassFile != null)
3631                         current = current.enclosingClassFile;
3632                 return current;
3633         }
3634
3635         /**
3636          * INTERNAL USE-ONLY
3637          * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
3638          * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
3639          *
3640          * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
3641          */
3642         public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
3643                 // add all the enclosing types
3644                 ReferenceBinding enclosingType = referenceBinding.enclosingType();
3645                 int depth = 0;
3646                 while (enclosingType != null) {
3647                         depth++;
3648                         enclosingType = enclosingType.enclosingType();
3649                 }
3650                 enclosingType = referenceBinding;
3651                 ReferenceBinding enclosingTypes[];
3652                 if (depth >= 2) {
3653                         enclosingTypes = new ReferenceBinding[depth];
3654                         for (int i = depth - 1; i >= 0; i--) {
3655                                 enclosingTypes[i] = enclosingType;
3656                                 enclosingType = enclosingType.enclosingType();
3657                         }
3658                         for (int i = 0; i < depth; i++) {
3659                                 addInnerClasses(enclosingTypes[i]);
3660                         }
3661                 } else {
3662                         addInnerClasses(referenceBinding);
3663                 }
3664         }
3665
3666         /**
3667          * INTERNAL USE-ONLY
3668          * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
3669          * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
3670          *
3671          * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
3672          */
3673         public void recordNestedLocalAttribute(ReferenceBinding binding) {
3674                 // add all the enclosing types
3675                 ReferenceBinding enclosingType = referenceBinding.enclosingType();
3676                 int depth = 0;
3677                 while (enclosingType != null) {
3678                         depth++;
3679                         enclosingType = enclosingType.enclosingType();
3680                 }
3681                 enclosingType = referenceBinding;
3682                 ReferenceBinding enclosingTypes[];
3683                 if (depth >= 2) {
3684                         enclosingTypes = new ReferenceBinding[depth];
3685                         for (int i = depth - 1; i >= 0; i--) {
3686                                 enclosingTypes[i] = enclosingType;
3687                                 enclosingType = enclosingType.enclosingType();
3688                         }
3689                         for (int i = 0; i < depth; i++)
3690                                 addInnerClasses(enclosingTypes[i]);
3691                 } else {
3692                         addInnerClasses(binding);
3693                 }
3694         }
3695
3696         /**
3697          * INTERNAL USE-ONLY
3698          * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
3699          * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
3700          *
3701          * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
3702          */
3703         public void recordNestedMemberAttribute(ReferenceBinding binding) {
3704                 addInnerClasses(binding);
3705         }
3706         
3707         /**
3708          * Resize the pool contents
3709          */
3710         private final void resizeContents(int minimalSize) {
3711                 int length = this.contents.length;
3712                 int toAdd = length;
3713                 if (toAdd < minimalSize)
3714                         toAdd = minimalSize;
3715                 System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
3716         }
3717
3718         /**
3719          * INTERNAL USE-ONLY
3720          * This methods leaves the space for method counts recording.
3721          */
3722         public void setForMethodInfos() {
3723                 // leave some space for the methodCount
3724                 methodCountOffset = contentsOffset;
3725                 contentsOffset += 2;
3726         }
3727 }