KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ClassFile


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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.BufferedOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.FileOutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Arrays JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Comparator JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Set JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24
25 import org.eclipse.jdt.core.compiler.CategorizedProblem;
26 import org.eclipse.jdt.core.compiler.CharOperation;
27 import org.eclipse.jdt.core.compiler.IProblem;
28 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
29 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
30 import org.eclipse.jdt.internal.compiler.ast.Annotation;
31 import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
32 import org.eclipse.jdt.internal.compiler.ast.Argument;
33 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
34 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
35 import org.eclipse.jdt.internal.compiler.ast.Expression;
36 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
37 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
38 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
39 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
40 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
41 import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
42 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
43 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
44 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
45 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
46 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
47 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
48 import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
49 import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
50 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
51 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
52 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
53 import org.eclipse.jdt.internal.compiler.impl.Constant;
54 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
55 import org.eclipse.jdt.internal.compiler.lookup.Binding;
56 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
57 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
58 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
59 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
60 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
61 import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
62 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
63 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
64 import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
65 import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
66 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
67 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
68 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
69 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
70 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
71 import org.eclipse.jdt.internal.compiler.util.Messages;
72 import org.eclipse.jdt.internal.compiler.util.Util;
73
74 /**
75  * Represents a class file wrapper on bytes, it is aware of its actual
76  * type name.
77  *
78  * Public APIs are listed below:
79  *
80  * byte[] getBytes();
81  * Answer the actual bytes of the class file
82  *
83  * char[][] getCompoundName();
84  * Answer the compound name of the class file.
85  * For example, {{java}, {util}, {Hashtable}}.
86  *
87  * byte[] getReducedBytes();
88  * Answer a smaller byte format, which is only contains some structural
89  * information. Those bytes are decodable with a regular class file reader,
90  * such as DietClassFileReader
91  */

92 public class ClassFile
93     implements TypeConstants, TypeIds {
94
95     private byte[] bytes;
96     public CodeStream codeStream;
97     public ConstantPool constantPool;
98
99     public int constantPoolOffset;
100
101     // the header contains all the bytes till the end of the constant pool
102
public byte[] contents;
103
104     public int contentsOffset;
105
106     protected boolean creatingProblemType;
107     
108     public ClassFile enclosingClassFile;
109     public byte[] header;
110     // that collection contains all the remaining bytes of the .class file
111
public int headerOffset;
112     public Set JavaDoc innerClassesBindings;
113     public int methodCount;
114     public int methodCountOffset;
115     // pool managment
116
public boolean isShared = false;
117     // used to generate private access methods
118
// debug and stack map attributes
119
public int produceAttributes;
120     public SourceTypeBinding referenceBinding;
121     public long targetJDK;
122     public static final int INITIAL_CONTENTS_SIZE = 400;
123     public static final int INITIAL_HEADER_SIZE = 1500;
124     public static final int INNER_CLASSES_SIZE = 5;
125     
126     /**
127      * INTERNAL USE-ONLY
128      * Build all the directories and subdirectories corresponding to the packages names
129      * into the directory specified in parameters.
130      *
131      * outputPath is formed like:
132      * c:\temp\ the last character is a file separator
133      * relativeFileName is formed like:
134      * java\lang\String.class *
135      *
136      * @param outputPath java.lang.String
137      * @param relativeFileName java.lang.String
138      * @return java.lang.String
139      */

140     public static String JavaDoc buildAllDirectoriesInto(
141         String JavaDoc outputPath,
142         String JavaDoc relativeFileName)
143         throws IOException JavaDoc {
144         char fileSeparatorChar = File.separatorChar;
145         String JavaDoc fileSeparator = File.separator;
146         File JavaDoc f;
147         outputPath = outputPath.replace('/', fileSeparatorChar);
148             // these could be optimized out if we normalized paths once and for
149
// all
150
relativeFileName = relativeFileName.replace('/', fileSeparatorChar);
151         String JavaDoc outputDirPath, fileName;
152         int separatorIndex = relativeFileName.lastIndexOf(fileSeparatorChar);
153         if (separatorIndex == -1) {
154             if (outputPath.endsWith(fileSeparator)) {
155                 outputDirPath = outputPath.substring(0, outputPath.length() - 1);
156                 fileName = outputPath + relativeFileName;
157             } else {
158                 outputDirPath = outputPath;
159                 fileName = outputPath + fileSeparator + relativeFileName;
160             }
161         } else {
162             if (outputPath.endsWith(fileSeparator)) {
163                 outputDirPath = outputPath +
164                     relativeFileName.substring(0, separatorIndex);
165                 fileName = outputPath + relativeFileName;
166             } else {
167                 outputDirPath = outputPath + fileSeparator +
168                     relativeFileName.substring(0, separatorIndex);
169                 fileName = outputPath + fileSeparator + relativeFileName;
170             }
171         }
172         f = new File JavaDoc(outputDirPath);
173         f.mkdirs();
174         if (f.isDirectory()) {
175             return fileName;
176         } else {
177             // the directory creation failed for some reason - retry using
178
// a slower algorithm so as to refine the diagnostic
179
if (outputPath.endsWith(fileSeparator)) {
180                 outputPath = outputPath.substring(0, outputPath.length() - 1);
181             }
182             f = new File JavaDoc(outputPath);
183             boolean checkFileType = false;
184             if (f.exists()) {
185                 checkFileType = true; // pre-existed
186
} else {
187                 // we have to create that directory
188
if (!f.mkdirs()) {
189                     if (f.exists()) {
190                         // someone else created f -- need to check its type
191
checkFileType = true;
192                     } else {
193                         // no one could create f -- complain
194
throw new IOException JavaDoc(Messages.bind(
195                             Messages.output_notValidAll, f.getAbsolutePath()));
196                     }
197                 }
198             }
199             if (checkFileType) {
200                 if (!f.isDirectory()) {
201                     throw new IOException JavaDoc(Messages.bind(
202                         Messages.output_isFile, f.getAbsolutePath()));
203                 }
204             }
205             StringBuffer JavaDoc outDir = new StringBuffer JavaDoc(outputPath);
206             outDir.append(fileSeparator);
207             StringTokenizer JavaDoc tokenizer =
208                 new StringTokenizer JavaDoc(relativeFileName, fileSeparator);
209             String JavaDoc token = tokenizer.nextToken();
210             while (tokenizer.hasMoreTokens()) {
211                 f = new File JavaDoc(outDir.append(token).append(fileSeparator).toString());
212                 checkFileType = false; // reset
213
if (f.exists()) {
214                     checkFileType = true; // this is suboptimal, but it catches corner cases
215
// in which a regular file pre-exists
216
} else {
217                 // we have to create that directory
218
if (!f.mkdir()) {
219                         if (f.exists()) {
220                             // someone else created f -- need to check its type
221
checkFileType = true;
222                         } else {
223                             // no one could create f -- complain
224
throw new IOException JavaDoc(Messages.bind(
225                                 Messages.output_notValid,
226                                     outDir.substring(outputPath.length() + 1,
227                                         outDir.length() - 1),
228                                     outputPath));
229                         }
230                     }
231                 }
232                 if (checkFileType) {
233                     if (!f.isDirectory()) {
234                         throw new IOException JavaDoc(Messages.bind(
235                             Messages.output_isFile, f.getAbsolutePath()));
236                     }
237                 }
238                 token = tokenizer.nextToken();
239             }
240             // token contains the last one
241
return outDir.append(token).toString();
242         }
243     }
244     /**
245      * INTERNAL USE-ONLY
246      * Request the creation of a ClassFile compatible representation of a problematic type
247      *
248      * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
249      * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
250      */

251     public static void createProblemType(
252         TypeDeclaration typeDeclaration,
253         CompilationResult unitResult) {
254         SourceTypeBinding typeBinding = typeDeclaration.binding;
255         ClassFile classFile = ClassFile.getNewInstance(typeBinding);
256         classFile.initialize(typeBinding, null, true);
257     
258         if (typeBinding.hasMemberTypes()) {
259             // see bug 180109
260
ReferenceBinding[] members = typeBinding.memberTypes;
261             for (int i = 0, l = members.length; i < l; i++)
262                 classFile.recordInnerClasses(members[i]);
263         }
264         // TODO (olivier) handle cases where a field cannot be generated (name too long)
265
// TODO (olivier) handle too many methods
266
// inner attributes
267
if (typeBinding.isNestedType()) {
268             classFile.recordInnerClasses(typeBinding);
269         }
270
271         // add its fields
272
FieldBinding[] fields = typeBinding.fields();
273         if ((fields != null) && (fields != Binding.NO_FIELDS)) {
274             classFile.addFieldInfos();
275         } else {
276             // we have to set the number of fields to be equals to 0
277
classFile.contents[classFile.contentsOffset++] = 0;
278             classFile.contents[classFile.contentsOffset++] = 0;
279         }
280         // leave some space for the methodCount
281
classFile.setForMethodInfos();
282         // add its user defined methods
283
int problemsLength;
284         CategorizedProblem[] problems = unitResult.getErrors();
285         if (problems == null) {
286             problems = new CategorizedProblem[0];
287         }
288         CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
289         System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
290         
291         AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods;
292         if (methodDecls != null) {
293             if (typeBinding.isInterface()) {
294                 // we cannot create problem methods for an interface. So we have to generate a clinit
295
// which should contain all the problem
296
classFile.addProblemClinit(problemsCopy);
297                 for (int i = 0, length = methodDecls.length; i < length; i++) {
298                     AbstractMethodDeclaration methodDecl = methodDecls[i];
299                     MethodBinding method = methodDecl.binding;
300                     if (method == null || method.isConstructor()) continue;
301                     classFile.addAbstractMethod(methodDecl, method);
302                 }
303             } else {
304                 for (int i = 0, length = methodDecls.length; i < length; i++) {
305                     AbstractMethodDeclaration methodDecl = methodDecls[i];
306                     MethodBinding method = methodDecl.binding;
307                     if (method == null) continue;
308                     if (method.isConstructor()) {
309                         classFile.addProblemConstructor(methodDecl, method, problemsCopy);
310                     } else {
311                         classFile.addProblemMethod(methodDecl, method, problemsCopy);
312                     }
313                 }
314             }
315             // add abstract methods
316
classFile.addDefaultAbstractMethods();
317         }
318         
319         // propagate generation of (problem) member types
320
if (typeDeclaration.memberTypes != null) {
321             for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
322                 TypeDeclaration memberType = typeDeclaration.memberTypes[i];
323                 if (memberType.binding != null) {
324                     ClassFile.createProblemType(memberType, unitResult);
325                 }
326             }
327         }
328         classFile.addAttributes();
329         unitResult.record(typeBinding.constantPoolName(), classFile);
330     }
331     public static ClassFile getNewInstance(SourceTypeBinding typeBinding) {
332         LookupEnvironment env = typeBinding.scope.environment();
333         return env.classFilePool.acquire(typeBinding);
334     }
335     
336     /**
337      * INTERNAL USE-ONLY
338      * outputPath is formed like:
339      * c:\temp\ the last character is a file separator
340      * relativeFileName is formed like:
341      * java\lang\String.class
342      * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
343      * @param outputPath the given output directory
344      * @param relativeFileName the given relative file name
345      * @param classFile the given classFile to write
346      *
347      */

348     public static void writeToDisk(
349         boolean generatePackagesStructure,
350         String JavaDoc outputPath,
351         String JavaDoc relativeFileName,
352         ClassFile classFile) throws IOException JavaDoc {
353             
354         BufferedOutputStream JavaDoc output = null;
355         if (generatePackagesStructure) {
356             output = new BufferedOutputStream JavaDoc(
357                 new FileOutputStream JavaDoc(
358                     new File JavaDoc(buildAllDirectoriesInto(outputPath, relativeFileName))));
359         } else {
360             String JavaDoc fileName = null;
361             char fileSeparatorChar = File.separatorChar;
362             String JavaDoc fileSeparator = File.separator;
363             // First we ensure that the outputPath exists
364
outputPath = outputPath.replace('/', fileSeparatorChar);
365             // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
366
int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
367             if (indexOfPackageSeparator == -1) {
368                 if (outputPath.endsWith(fileSeparator)) {
369                     fileName = outputPath + relativeFileName;
370                 } else {
371                     fileName = outputPath + fileSeparator + relativeFileName;
372                 }
373             } else {
374                 int length = relativeFileName.length();
375                 if (outputPath.endsWith(fileSeparator)) {
376                     fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
377                 } else {
378                     fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
379                 }
380             }
381             output = new BufferedOutputStream JavaDoc(
382                 new FileOutputStream JavaDoc(
383                         new File JavaDoc(fileName)));
384         }
385         try {
386             // if no IOException occured, output cannot be null
387
output.write(classFile.header, 0, classFile.headerOffset);
388             output.write(classFile.contents, 0, classFile.contentsOffset);
389             output.flush();
390         } catch(IOException JavaDoc e) {
391             throw e;
392         } finally {
393             output.close();
394         }
395     }
396     
397     /**
398      * INTERNAL USE-ONLY
399      * This methods creates a new instance of the receiver.
400      */

401     protected ClassFile() {
402         // default constructor for subclasses
403
}
404     
405     public ClassFile(SourceTypeBinding typeBinding) {
406         // default constructor for subclasses
407
this.constantPool = new ConstantPool(this);
408         final CompilerOptions options = typeBinding.scope.compilerOptions();
409         this.targetJDK = options.targetJDK;
410         this.produceAttributes = options.produceDebugAttributes;
411         this.referenceBinding = typeBinding;
412         if (this.targetJDK >= ClassFileConstants.JDK1_6) {
413             this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
414             this.codeStream = new StackMapFrameCodeStream(this);
415         } else {
416             this.codeStream = new CodeStream(this);
417         }
418         this.initByteArrays();
419     }
420
421     /**
422      * INTERNAL USE-ONLY
423      * Generate the byte for a problem method info that correspond to a boggus method.
424      *
425      * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
426      * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
427      */

428     public void addAbstractMethod(
429         AbstractMethodDeclaration method,
430         MethodBinding methodBinding) {
431
432         // force the modifiers to be public and abstract
433
methodBinding.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
434
435         this.generateMethodInfoHeader(methodBinding);
436         int methodAttributeOffset = this.contentsOffset;
437         int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
438         this.completeMethodInfo(methodAttributeOffset, attributeNumber);
439     }
440
441     /**
442      * INTERNAL USE-ONLY
443      * This methods generate all the attributes for the receiver.
444      * For a class they could be:
445      * - source file attribute
446      * - inner classes attribute
447      * - deprecated attribute
448      */

449     public void addAttributes() {
450         // update the method count
451
contents[methodCountOffset++] = (byte) (methodCount >> 8);
452         contents[methodCountOffset] = (byte) methodCount;
453
454         int attributeNumber = 0;
455         // leave two bytes for the number of attributes and store the current offset
456
int attributeOffset = contentsOffset;
457         contentsOffset += 2;
458
459         // source attribute
460
if ((produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) {
461             String JavaDoc fullFileName =
462                 new String JavaDoc(referenceBinding.scope.referenceCompilationUnit().getFileName());
463             fullFileName = fullFileName.replace('\\', '/');
464             int lastIndex = fullFileName.lastIndexOf('/');
465             if (lastIndex != -1) {
466                 fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
467             }
468             // check that there is enough space to write all the bytes for the field info corresponding
469
// to the @fieldBinding
470
if (contentsOffset + 8 >= contents.length) {
471                 resizeContents(8);
472             }
473             int sourceAttributeNameIndex =
474                 constantPool.literalIndex(AttributeNamesConstants.SourceName);
475             contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
476             contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
477             // The length of a source file attribute is 2. This is a fixed-length
478
// attribute
479
contents[contentsOffset++] = 0;
480             contents[contentsOffset++] = 0;
481             contents[contentsOffset++] = 0;
482             contents[contentsOffset++] = 2;
483             // write the source file name
484
int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
485             contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
486             contents[contentsOffset++] = (byte) fileNameIndex;
487             attributeNumber++;
488         }
489         // Deprecated attribute
490
if (referenceBinding.isDeprecated()) {
491             // check that there is enough space to write all the bytes for the field info corresponding
492
// to the @fieldBinding
493
if (contentsOffset + 6 >= contents.length) {
494                 resizeContents(6);
495             }
496             int deprecatedAttributeNameIndex =
497                 constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
498             contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
499             contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
500             // the length of a deprecated attribute is equals to 0
501
contents[contentsOffset++] = 0;
502             contents[contentsOffset++] = 0;
503             contents[contentsOffset++] = 0;
504             contents[contentsOffset++] = 0;
505             attributeNumber++;
506         }
507         // add signature attribute
508
char[] genericSignature = referenceBinding.genericSignature();
509         if (genericSignature != null) {
510             // check that there is enough space to write all the bytes for the field info corresponding
511
// to the @fieldBinding
512
if (contentsOffset + 8 >= contents.length) {
513                 resizeContents(8);
514             }
515             int signatureAttributeNameIndex =
516                 constantPool.literalIndex(AttributeNamesConstants.SignatureName);
517             contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
518             contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
519             // the length of a signature attribute is equals to 2
520
contents[contentsOffset++] = 0;
521             contents[contentsOffset++] = 0;
522             contents[contentsOffset++] = 0;
523             contents[contentsOffset++] = 2;
524             int signatureIndex =
525                 constantPool.literalIndex(genericSignature);
526             contents[contentsOffset++] = (byte) (signatureIndex >> 8);
527             contents[contentsOffset++] = (byte) signatureIndex;
528             attributeNumber++;
529         }
530         if (targetJDK >= ClassFileConstants.JDK1_5
531                 && this.referenceBinding.isNestedType()
532                 && !this.referenceBinding.isMemberType()) {
533             // add enclosing method attribute (1.5 mode only)
534
if (contentsOffset + 10 >= contents.length) {
535                 resizeContents(10);
536             }
537             int enclosingMethodAttributeNameIndex =
538                 constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
539             contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
540             contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
541             // the length of a signature attribute is equals to 2
542
contents[contentsOffset++] = 0;
543             contents[contentsOffset++] = 0;
544             contents[contentsOffset++] = 0;
545             contents[contentsOffset++] = 4;
546             
547             int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
548             contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
549             contents[contentsOffset++] = (byte) enclosingTypeIndex;
550             byte methodIndexByte1 = 0;
551             byte methodIndexByte2 = 0;
552             if (this.referenceBinding instanceof LocalTypeBinding) {
553                 MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod;
554                 if (methodBinding != null) {
555                     int enclosingMethodIndex = constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature(this));
556                     methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
557                     methodIndexByte2 = (byte) enclosingMethodIndex;
558                 }
559             }
560             contents[contentsOffset++] = methodIndexByte1;
561             contents[contentsOffset++] = methodIndexByte2;
562             attributeNumber++;
563         }
564         if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
565             TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
566             if (typeDeclaration != null) {
567                 final Annotation[] annotations = typeDeclaration.annotations;
568                 if (annotations != null) {
569                     attributeNumber += generateRuntimeAnnotations(annotations);
570                 }
571             }
572         }
573         
574         if (this.referenceBinding.isHierarchyInconsistent()) {
575             // add an attribute for inconsistent hierarchy
576
if (contentsOffset + 6 >= contents.length) {
577                 resizeContents(6);
578             }
579             int inconsistentHierarchyNameIndex =
580                 constantPool.literalIndex(AttributeNamesConstants.InconsistentHierarchy);
581             contents[contentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8);
582             contents[contentsOffset++] = (byte) inconsistentHierarchyNameIndex;
583             // the length of an inconsistent hierarchy attribute is equals to 0
584
contents[contentsOffset++] = 0;
585             contents[contentsOffset++] = 0;
586             contents[contentsOffset++] = 0;
587             contents[contentsOffset++] = 0;
588             attributeNumber++;
589         }
590         // Inner class attribute
591
int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size();
592         if (numberOfInnerClasses != 0) {
593             ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses];
594             this.innerClassesBindings.toArray(innerClasses);
595             Arrays.sort(innerClasses, new Comparator JavaDoc() {
596                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
597                     TypeBinding binding1 = (TypeBinding) o1;
598                     TypeBinding binding2 = (TypeBinding) o2;
599                     return CharOperation.compareTo(binding1.constantPoolName(), binding2.constantPoolName());
600                 }
601             });
602             // Generate the inner class attribute
603
int exSize = 8 * numberOfInnerClasses + 8;
604             if (exSize + contentsOffset >= this.contents.length) {
605                 resizeContents(exSize);
606             }
607             // Now we now the size of the attribute and the number of entries
608
// attribute name
609
int attributeNameIndex =
610                 constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
611             contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
612             contents[contentsOffset++] = (byte) attributeNameIndex;
613             int value = (numberOfInnerClasses << 3) + 2;
614             contents[contentsOffset++] = (byte) (value >> 24);
615             contents[contentsOffset++] = (byte) (value >> 16);
616             contents[contentsOffset++] = (byte) (value >> 8);
617             contents[contentsOffset++] = (byte) value;
618             contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
619             contents[contentsOffset++] = (byte) numberOfInnerClasses;
620             for (int i = 0; i < numberOfInnerClasses; i++) {
621                 ReferenceBinding innerClass = innerClasses[i];
622                 int accessFlags = innerClass.getAccessFlags();
623                 int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
624                 // inner class index
625
contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
626                 contents[contentsOffset++] = (byte) innerClassIndex;
627                 // outer class index: anonymous and local have no outer class index
628
if (innerClass.isMemberType()) {
629                     // member or member of local
630
int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
631                     contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
632                     contents[contentsOffset++] = (byte) outerClassIndex;
633                 } else {
634                     // equals to 0 if the innerClass is not a member type
635
contents[contentsOffset++] = 0;
636                     contents[contentsOffset++] = 0;
637                 }
638                 // name index
639
if (!innerClass.isAnonymousType()) {
640                     int nameIndex = constantPool.literalIndex(innerClass.sourceName());
641                     contents[contentsOffset++] = (byte) (nameIndex >> 8);
642                     contents[contentsOffset++] = (byte) nameIndex;
643                 } else {
644                     // equals to 0 if the innerClass is an anonymous type
645
contents[contentsOffset++] = 0;
646                     contents[contentsOffset++] = 0;
647                 }
648                 // access flag
649
if (innerClass.isAnonymousType()) {
650                     accessFlags &= ~ClassFileConstants.AccFinal;
651                 } else if (innerClass.isMemberType() && innerClass.isInterface()) {
652                     accessFlags |= ClassFileConstants.AccStatic; // implicitely static
653
}
654                 contents[contentsOffset++] = (byte) (accessFlags >> 8);
655                 contents[contentsOffset++] = (byte) accessFlags;
656             }
657             attributeNumber++;
658         }
659         // update the number of attributes
660
if (attributeOffset + 2 >= this.contents.length) {
661             resizeContents(2);
662         }
663         contents[attributeOffset++] = (byte) (attributeNumber >> 8);
664         contents[attributeOffset] = (byte) attributeNumber;
665
666         // resynchronize all offsets of the classfile
667
header = constantPool.poolContent;
668         headerOffset = constantPool.currentOffset;
669         int constantPoolCount = constantPool.currentIndex;
670         header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
671         header[constantPoolOffset] = (byte) constantPoolCount;
672     }
673
674     /**
675      * INTERNAL USE-ONLY
676      * This methods generate all the default abstract method infos that correpond to
677      * the abstract methods inherited from superinterfaces.
678      */

679     public void addDefaultAbstractMethods() { // default abstract methods
680
MethodBinding[] defaultAbstractMethods =
681             referenceBinding.getDefaultAbstractMethods();
682         for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
683             generateMethodInfoHeader(defaultAbstractMethods[i]);
684             int methodAttributeOffset = contentsOffset;
685             int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
686             completeMethodInfo(methodAttributeOffset, attributeNumber);
687         }
688     }
689     
690     private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
691         int attributesNumber = 0;
692         // 4.7.2 only static constant fields get a ConstantAttribute
693
// Generate the constantValueAttribute
694
Constant fieldConstant = fieldBinding.constant();
695         if (fieldConstant != Constant.NotAConstant){
696             if (contentsOffset + 8 >= contents.length) {
697                 resizeContents(8);
698             }
699             // Now we generate the constant attribute corresponding to the fieldBinding
700
int constantValueNameIndex =
701                 constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
702             contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
703             contents[contentsOffset++] = (byte) constantValueNameIndex;
704             // The attribute length = 2 in case of a constantValue attribute
705
contents[contentsOffset++] = 0;
706             contents[contentsOffset++] = 0;
707             contents[contentsOffset++] = 0;
708             contents[contentsOffset++] = 2;
709             attributesNumber++;
710             // Need to add the constant_value_index
711
switch (fieldConstant.typeID()) {
712                 case T_boolean :
713                     int booleanValueIndex =
714                         constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
715                     contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
716                     contents[contentsOffset++] = (byte) booleanValueIndex;
717                     break;
718                 case T_byte :
719                 case T_char :
720                 case T_int :
721                 case T_short :
722                     int integerValueIndex =
723                         constantPool.literalIndex(fieldConstant.intValue());
724                     contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
725                     contents[contentsOffset++] = (byte) integerValueIndex;
726                     break;
727                 case T_float :
728                     int floatValueIndex =
729                         constantPool.literalIndex(fieldConstant.floatValue());
730                     contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
731                     contents[contentsOffset++] = (byte) floatValueIndex;
732                     break;
733                 case T_double :
734                     int doubleValueIndex =
735                         constantPool.literalIndex(fieldConstant.doubleValue());
736                     contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
737                     contents[contentsOffset++] = (byte) doubleValueIndex;
738                     break;
739                 case T_long :
740                     int longValueIndex =
741                         constantPool.literalIndex(fieldConstant.longValue());
742                     contents[contentsOffset++] = (byte) (longValueIndex >> 8);
743                     contents[contentsOffset++] = (byte) longValueIndex;
744                     break;
745                 case T_JavaLangString :
746                     int stringValueIndex =
747                         constantPool.literalIndex(
748                             ((StringConstant) fieldConstant).stringValue());
749                     if (stringValueIndex == -1) {
750                         if (!creatingProblemType) {
751                             // report an error and abort: will lead to a problem type classfile creation
752
TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
753                             FieldDeclaration[] fieldDecls = typeDeclaration.fields;
754                             for (int i = 0, max = fieldDecls.length; i < max; i++) {
755                                 if (fieldDecls[i].binding == fieldBinding) {
756                                     // problem should abort
757
typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
758                                         fieldDecls[i]);
759                                 }
760                             }
761                         } else {
762                             // already inside a problem type creation : no constant for this field
763
contentsOffset = fieldAttributeOffset;
764                         }
765                     } else {
766                         contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
767                         contents[contentsOffset++] = (byte) stringValueIndex;
768                     }
769             }
770         }
771         if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
772             if (contentsOffset + 6 >= contents.length) {
773                 resizeContents(6);
774             }
775             int syntheticAttributeNameIndex =
776                 constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
777             contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
778             contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
779             // the length of a synthetic attribute is equals to 0
780
contents[contentsOffset++] = 0;
781             contents[contentsOffset++] = 0;
782             contents[contentsOffset++] = 0;
783             contents[contentsOffset++] = 0;
784             attributesNumber++;
785         }
786         if (fieldBinding.isDeprecated()) {
787             if (contentsOffset + 6 >= contents.length) {
788                 resizeContents(6);
789             }
790             int deprecatedAttributeNameIndex =
791                 constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
792             contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
793             contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
794             // the length of a deprecated attribute is equals to 0
795
contents[contentsOffset++] = 0;
796             contents[contentsOffset++] = 0;
797             contents[contentsOffset++] = 0;
798             contents[contentsOffset++] = 0;
799             attributesNumber++;
800         }
801         // add signature attribute
802
char[] genericSignature = fieldBinding.genericSignature();
803         if (genericSignature != null) {
804             // check that there is enough space to write all the bytes for the field info corresponding
805
// to the @fieldBinding
806
if (contentsOffset + 8 >= contents.length) {
807                 resizeContents(8);
808             }
809             int signatureAttributeNameIndex =
810                 constantPool.literalIndex(AttributeNamesConstants.SignatureName);
811             contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
812             contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
813             // the length of a signature attribute is equals to 2
814
contents[contentsOffset++] = 0;
815             contents[contentsOffset++] = 0;
816             contents[contentsOffset++] = 0;
817             contents[contentsOffset++] = 2;
818             int signatureIndex =
819                 constantPool.literalIndex(genericSignature);
820             contents[contentsOffset++] = (byte) (signatureIndex >> 8);
821             contents[contentsOffset++] = (byte) signatureIndex;
822             attributesNumber++;
823         }
824         if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
825             FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
826             if (fieldDeclaration != null) {
827                 Annotation[] annotations = fieldDeclaration.annotations;
828                 if (annotations != null) {
829                     attributesNumber += generateRuntimeAnnotations(annotations);
830                 }
831             }
832         }
833         return attributesNumber;
834     }
835
836     /**
837      * INTERNAL USE-ONLY
838      * This methods generates the bytes for the given field binding
839      * @param fieldBinding the given field binding
840      */

841     private void addFieldInfo(FieldBinding fieldBinding) {
842         // check that there is enough space to write all the bytes for the field info corresponding
843
// to the @fieldBinding
844
if (contentsOffset + 8 >= contents.length) {
845             resizeContents(8);
846         }
847         // Now we can generate all entries into the byte array
848
// First the accessFlags
849
int accessFlags = fieldBinding.getAccessFlags();
850         if (targetJDK < ClassFileConstants.JDK1_5) {
851             // pre 1.5, synthetic was an attribute, not a modifier
852
accessFlags &= ~ClassFileConstants.AccSynthetic;
853         }
854         contents[contentsOffset++] = (byte) (accessFlags >> 8);
855         contents[contentsOffset++] = (byte) accessFlags;
856         // Then the nameIndex
857
int nameIndex = constantPool.literalIndex(fieldBinding.name);
858         contents[contentsOffset++] = (byte) (nameIndex >> 8);
859         contents[contentsOffset++] = (byte) nameIndex;
860         // Then the descriptorIndex
861
int descriptorIndex = constantPool.literalIndex(fieldBinding.type);
862         contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
863         contents[contentsOffset++] = (byte) descriptorIndex;
864         int fieldAttributeOffset = contentsOffset;
865         int attributeNumber = 0;
866         // leave some space for the number of attributes
867
contentsOffset += 2;
868         attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
869         if (contentsOffset + 2 >= contents.length) {
870             resizeContents(2);
871         }
872         contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
873         contents[fieldAttributeOffset] = (byte) attributeNumber;
874     }
875     /**
876      * INTERNAL USE-ONLY
877      * This methods generate all the fields infos for the receiver.
878      * This includes:
879      * - a field info for each defined field of that class
880      * - a field info for each synthetic field (e.g. this$0)
881      */

882     /**
883      * INTERNAL USE-ONLY
884      * This methods generate all the fields infos for the receiver.
885      * This includes:
886      * - a field info for each defined field of that class
887      * - a field info for each synthetic field (e.g. this$0)
888      */

889     public void addFieldInfos() {
890         SourceTypeBinding currentBinding = referenceBinding;
891         FieldBinding[] syntheticFields = currentBinding.syntheticFields();
892         int fieldCount =
893             currentBinding.fieldCount()
894                 + (syntheticFields == null ? 0 : syntheticFields.length);
895
896         // write the number of fields
897
if (fieldCount > 0xFFFF) {
898             referenceBinding.scope.problemReporter().tooManyFields(referenceBinding.scope.referenceType());
899         }
900         contents[contentsOffset++] = (byte) (fieldCount >> 8);
901         contents[contentsOffset++] = (byte) fieldCount;
902
903         FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields;
904         for (int i = 0, max = fieldDecls == null ? 0 : fieldDecls.length; i < max; i++) {
905             FieldDeclaration fieldDecl = fieldDecls[i];
906             if (fieldDecl.binding != null) {
907                 addFieldInfo(fieldDecl.binding);
908             }
909         }
910
911         if (syntheticFields != null) {
912             for (int i = 0, max = syntheticFields.length; i < max; i++) {
913                 addFieldInfo(syntheticFields[i]);
914             }
915         }
916     }
917     private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) {
918         // always clear the strictfp/native/abstract bit for a problem method
919
generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
920         int methodAttributeOffset = contentsOffset;
921         int attributeNumber = generateMethodInfoAttribute(methodBinding);
922         
923         // Code attribute
924
attributeNumber++;
925         
926         int codeAttributeOffset = contentsOffset;
927         generateCodeAttributeHeader();
928         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(25);
929         buffer.append("\t" + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
930
buffer.insert(0, Messages.compilation_unresolvedProblem);
931         String JavaDoc problemString = buffer.toString();
932         
933         codeStream.init(this);
934         codeStream.preserveUnusedLocals = true;
935         codeStream.initializeMaxLocals(methodBinding);
936
937         // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
938
codeStream.generateCodeAttributeForProblemMethod(problemString);
939                 
940         completeCodeAttributeForMissingAbstractProblemMethod(
941             methodBinding,
942             codeAttributeOffset,
943             compilationResult.getLineSeparatorPositions(),
944             problem.getSourceLineNumber());
945             
946         completeMethodInfo(methodAttributeOffset, attributeNumber);
947     }
948     
949     /**
950      * INTERNAL USE-ONLY
951      * Generate the byte for a problem clinit method info that correspond to a boggus method.
952      *
953      * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
954      */

955     public void addProblemClinit(CategorizedProblem[] problems) {
956         generateMethodInfoHeaderForClinit();
957         // leave two spaces for the number of attributes
958
contentsOffset -= 2;
959         int attributeOffset = contentsOffset;
960         contentsOffset += 2;
961         int attributeNumber = 0;
962
963         int codeAttributeOffset = contentsOffset;
964         generateCodeAttributeHeader();
965         codeStream.resetForProblemClinit(this);
966         String JavaDoc problemString = "" ; //$NON-NLS-1$
967
int problemLine = 0;
968         if (problems != null) {
969             int max = problems.length;
970             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(25);
971             int count = 0;
972             for (int i = 0; i < max; i++) {
973                 CategorizedProblem problem = problems[i];
974                 if ((problem != null) && (problem.isError())) {
975                     buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
976
count++;
977                     if (problemLine == 0) {
978                         problemLine = problem.getSourceLineNumber();
979                     }
980                     problems[i] = null;
981                 }
982             } // insert the top line afterwards, once knowing how many problems we have to consider
983
if (count > 1) {
984                 buffer.insert(0, Messages.compilation_unresolvedProblems);
985             } else {
986                 buffer.insert(0, Messages.compilation_unresolvedProblem);
987             }
988             problemString = buffer.toString();
989         }
990
991         // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
992
codeStream.generateCodeAttributeForProblemMethod(problemString);
993         attributeNumber++; // code attribute
994
completeCodeAttributeForClinit(
995             codeAttributeOffset,
996             problemLine);
997         if (contentsOffset + 2 >= contents.length) {
998             resizeContents(2);
999         }
1000        contents[attributeOffset++] = (byte) (attributeNumber >> 8);
1001        contents[attributeOffset] = (byte) attributeNumber;
1002    }
1003
1004    /**
1005     * INTERNAL USE-ONLY
1006     * Generate the byte for a problem method info that correspond to a boggus constructor.
1007     *
1008     * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1009     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1010     * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1011     */

1012    public void addProblemConstructor(
1013        AbstractMethodDeclaration method,
1014        MethodBinding methodBinding,
1015        CategorizedProblem[] problems) {
1016
1017        // always clear the strictfp/native/abstract bit for a problem method
1018
generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
1019        int methodAttributeOffset = contentsOffset;
1020        int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
1021        
1022        // Code attribute
1023
attributeNumber++;
1024        int codeAttributeOffset = contentsOffset;
1025        generateCodeAttributeHeader();
1026        codeStream.reset(method, this);
1027        String JavaDoc problemString = "" ; //$NON-NLS-1$
1028
int problemLine = 0;
1029        if (problems != null) {
1030            int max = problems.length;
1031            StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(25);
1032            int count = 0;
1033            for (int i = 0; i < max; i++) {
1034                CategorizedProblem problem = problems[i];
1035                if ((problem != null) && (problem.isError())) {
1036                    buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
1037
count++;
1038                    if (problemLine == 0) {
1039                        problemLine = problem.getSourceLineNumber();
1040                    }
1041                }
1042            } // insert the top line afterwards, once knowing how many problems we have to consider
1043
if (count > 1) {
1044                buffer.insert(0, Messages.compilation_unresolvedProblems);
1045            } else {
1046                buffer.insert(0, Messages.compilation_unresolvedProblem);
1047            }
1048            problemString = buffer.toString();
1049        }
1050
1051        // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1052
codeStream.generateCodeAttributeForProblemMethod(problemString);
1053        completeCodeAttributeForProblemMethod(
1054            method,
1055            methodBinding,
1056            codeAttributeOffset,
1057            ((SourceTypeBinding) methodBinding.declaringClass)
1058                .scope
1059                .referenceCompilationUnit()
1060                .compilationResult
1061                .getLineSeparatorPositions(),
1062            problemLine);
1063        completeMethodInfo(methodAttributeOffset, attributeNumber);
1064    }
1065
1066    /**
1067     * INTERNAL USE-ONLY
1068     * Generate the byte for a problem method info that correspond to a boggus constructor.
1069     * Reset the position inside the contents byte array to the savedOffset.
1070     *
1071     * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1072     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1073     * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1074     * @param savedOffset <CODE>int</CODE>
1075     */

1076    public void addProblemConstructor(
1077        AbstractMethodDeclaration method,
1078        MethodBinding methodBinding,
1079        CategorizedProblem[] problems,
1080        int savedOffset) {
1081        // we need to move back the contentsOffset to the value at the beginning of the method
1082
contentsOffset = savedOffset;
1083        methodCount--; // we need to remove the method that causes the problem
1084
addProblemConstructor(method, methodBinding, problems);
1085    }
1086
1087    /**
1088     * INTERNAL USE-ONLY
1089     * Generate the byte for a problem method info that correspond to a boggus method.
1090     *
1091     * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1092     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1093     * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1094     */

1095    public void addProblemMethod(
1096        AbstractMethodDeclaration method,
1097        MethodBinding methodBinding,
1098        CategorizedProblem[] problems) {
1099        if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
1100            method.abort(ProblemSeverities.AbortType, null);
1101        }
1102        // always clear the strictfp/native/abstract bit for a problem method
1103
generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
1104        int methodAttributeOffset = contentsOffset;
1105        int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
1106        
1107        // Code attribute
1108
attributeNumber++;
1109        
1110        int codeAttributeOffset = contentsOffset;
1111        generateCodeAttributeHeader();
1112        codeStream.reset(method, this);
1113        String JavaDoc problemString = "" ; //$NON-NLS-1$
1114
int problemLine = 0;
1115        if (problems != null) {
1116            int max = problems.length;
1117            StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(25);
1118            int count = 0;
1119            for (int i = 0; i < max; i++) {
1120                CategorizedProblem problem = problems[i];
1121                if ((problem != null)
1122                    && (problem.isError())
1123                    && (problem.getSourceStart() >= method.declarationSourceStart)
1124                    && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
1125                    buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
1126
count++;
1127                    if (problemLine == 0) {
1128                        problemLine = problem.getSourceLineNumber();
1129                    }
1130                    problems[i] = null;
1131                }
1132            } // insert the top line afterwards, once knowing how many problems we have to consider
1133
if (count > 1) {
1134                buffer.insert(0, Messages.compilation_unresolvedProblems);
1135            } else {
1136                buffer.insert(0, Messages.compilation_unresolvedProblem);
1137            }
1138            problemString = buffer.toString();
1139        }
1140
1141        // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1142
codeStream.generateCodeAttributeForProblemMethod(problemString);
1143        completeCodeAttributeForProblemMethod(
1144            method,
1145            methodBinding,
1146            codeAttributeOffset,
1147            ((SourceTypeBinding) methodBinding.declaringClass)
1148                .scope
1149                .referenceCompilationUnit()
1150                .compilationResult
1151                .getLineSeparatorPositions(),
1152            problemLine);
1153        completeMethodInfo(methodAttributeOffset, attributeNumber);
1154    }
1155
1156    /**
1157     * INTERNAL USE-ONLY
1158     * Generate the byte for a problem method info that correspond to a boggus method.
1159     * Reset the position inside the contents byte array to the savedOffset.
1160     *
1161     * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1162     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1163     * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1164     * @param savedOffset <CODE>int</CODE>
1165     */

1166    public void addProblemMethod(
1167        AbstractMethodDeclaration method,
1168        MethodBinding methodBinding,
1169        CategorizedProblem[] problems,
1170        int savedOffset) {
1171        // we need to move back the contentsOffset to the value at the beginning of the method
1172
contentsOffset = savedOffset;
1173        methodCount--; // we need to remove the method that causes the problem
1174
addProblemMethod(method, methodBinding, problems);
1175    }
1176
1177    /**
1178     * INTERNAL USE-ONLY
1179     * Generate the byte for all the special method infos.
1180     * They are:
1181     * - synthetic access methods
1182     * - default abstract methods
1183     */

1184    public void addSpecialMethods() {
1185        
1186        // add all methods (default abstract methods and synthetic)
1187

1188        // default abstract methods
1189
generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);
1190
1191        MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
1192        for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
1193            generateMethodInfoHeader(defaultAbstractMethods[i]);
1194            int methodAttributeOffset = contentsOffset;
1195            int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
1196            completeMethodInfo(methodAttributeOffset, attributeNumber);
1197        }
1198        // add synthetic methods infos
1199
SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
1200        if (syntheticMethods != null) {
1201            for (int i = 0, max = syntheticMethods.length; i < max; i++) {
1202                SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
1203                switch (syntheticMethod.kind) {
1204                    case SyntheticMethodBinding.FieldReadAccess :
1205                        // generate a method info to emulate an reading access to
1206
// a non-accessible field
1207
addSyntheticFieldReadAccessMethod(syntheticMethod);
1208                        break;
1209                    case SyntheticMethodBinding.FieldWriteAccess :
1210                        // generate a method info to emulate an writing access to
1211
// a non-accessible field
1212
addSyntheticFieldWriteAccessMethod(syntheticMethod);
1213                        break;
1214                    case SyntheticMethodBinding.MethodAccess :
1215                    case SyntheticMethodBinding.SuperMethodAccess :
1216                    case SyntheticMethodBinding.BridgeMethod :
1217                        // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
1218
addSyntheticMethodAccessMethod(syntheticMethod);
1219                        break;
1220                    case SyntheticMethodBinding.ConstructorAccess :
1221                        // generate a method info to emulate an access to a non-accessible constructor
1222
addSyntheticConstructorAccessMethod(syntheticMethod);
1223                        break;
1224                    case SyntheticMethodBinding.EnumValues :
1225                        // generate a method info to define <enum>#values()
1226
addSyntheticEnumValuesMethod(syntheticMethod);
1227                        break;
1228                    case SyntheticMethodBinding.EnumValueOf :
1229                        // generate a method info to define <enum>#valueOf(String)
1230
addSyntheticEnumValueOfMethod(syntheticMethod);
1231                        break;
1232                    case SyntheticMethodBinding.SwitchTable :
1233                        // generate a method info to define the switch table synthetic method
1234
addSyntheticSwitchTable(syntheticMethod);
1235                }
1236            }
1237        }
1238    }
1239
1240    /**
1241     * INTERNAL USE-ONLY
1242     * Generate the bytes for a synthetic method that provides an access to a private constructor.
1243     *
1244     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1245     */

1246    public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
1247        generateMethodInfoHeader(methodBinding);
1248        int methodAttributeOffset = this.contentsOffset;
1249        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1250
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1251        // Code attribute
1252
int codeAttributeOffset = contentsOffset;
1253        attributeNumber++; // add code attribute
1254
generateCodeAttributeHeader();
1255        codeStream.init(this);
1256        codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
1257        completeCodeAttributeForSyntheticMethod(
1258            methodBinding,
1259            codeAttributeOffset,
1260            ((SourceTypeBinding) methodBinding.declaringClass)
1261                .scope
1262                .referenceCompilationUnit()
1263                .compilationResult
1264                .getLineSeparatorPositions());
1265        // update the number of attributes
1266
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1267        contents[methodAttributeOffset] = (byte) attributeNumber;
1268    }
1269        
1270    /**
1271     * INTERNAL USE-ONLY
1272     * Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
1273     *
1274     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1275     */

1276    public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
1277        generateMethodInfoHeader(methodBinding);
1278        int methodAttributeOffset = this.contentsOffset;
1279        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1280
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1281        // Code attribute
1282
int codeAttributeOffset = contentsOffset;
1283        attributeNumber++; // add code attribute
1284
generateCodeAttributeHeader();
1285        codeStream.init(this);
1286        codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
1287        completeCodeAttributeForSyntheticMethod(
1288            methodBinding,
1289            codeAttributeOffset,
1290            ((SourceTypeBinding) methodBinding.declaringClass)
1291                .scope
1292                .referenceCompilationUnit()
1293                .compilationResult
1294                .getLineSeparatorPositions());
1295        // update the number of attributes
1296
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1297        contents[methodAttributeOffset] = (byte) attributeNumber;
1298    }
1299
1300    /**
1301     * INTERNAL USE-ONLY
1302     * Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
1303     *
1304     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1305     */

1306    public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
1307        generateMethodInfoHeader(methodBinding);
1308        int methodAttributeOffset = this.contentsOffset;
1309        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1310
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1311        // Code attribute
1312
int codeAttributeOffset = contentsOffset;
1313        attributeNumber++; // add code attribute
1314
generateCodeAttributeHeader();
1315        codeStream.init(this);
1316        codeStream.generateSyntheticBodyForEnumValues(methodBinding);
1317        completeCodeAttributeForSyntheticMethod(
1318            methodBinding,
1319            codeAttributeOffset,
1320            ((SourceTypeBinding) methodBinding.declaringClass)
1321                .scope
1322                .referenceCompilationUnit()
1323                .compilationResult
1324                .getLineSeparatorPositions());
1325        // update the number of attributes
1326
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1327        contents[methodAttributeOffset] = (byte) attributeNumber;
1328    }
1329
1330    /**
1331     * INTERNAL USE-ONLY
1332     * Generate the byte for a problem method info that correspond to a synthetic method that
1333     * generate an read access to a private field.
1334     *
1335     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1336     */

1337    public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
1338        generateMethodInfoHeader(methodBinding);
1339        int methodAttributeOffset = this.contentsOffset;
1340        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1341
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1342        // Code attribute
1343
int codeAttributeOffset = contentsOffset;
1344        attributeNumber++; // add code attribute
1345
generateCodeAttributeHeader();
1346        codeStream.init(this);
1347        codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
1348        completeCodeAttributeForSyntheticMethod(
1349            methodBinding,
1350            codeAttributeOffset,
1351            ((SourceTypeBinding) methodBinding.declaringClass)
1352                .scope
1353                .referenceCompilationUnit()
1354                .compilationResult
1355                .getLineSeparatorPositions());
1356        // update the number of attributes
1357
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1358        contents[methodAttributeOffset] = (byte) attributeNumber;
1359    }
1360    /**
1361     * INTERNAL USE-ONLY
1362     * Generate the byte for a problem method info that correspond to a synthetic method that
1363     * generate an write access to a private field.
1364     *
1365     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1366     */

1367    public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
1368        generateMethodInfoHeader(methodBinding);
1369        int methodAttributeOffset = this.contentsOffset;
1370        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1371
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1372        // Code attribute
1373
int codeAttributeOffset = contentsOffset;
1374        attributeNumber++; // add code attribute
1375
generateCodeAttributeHeader();
1376        codeStream.init(this);
1377        codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
1378        completeCodeAttributeForSyntheticMethod(
1379            methodBinding,
1380            codeAttributeOffset,
1381            ((SourceTypeBinding) methodBinding.declaringClass)
1382                .scope
1383                .referenceCompilationUnit()
1384                .compilationResult
1385                .getLineSeparatorPositions());
1386        // update the number of attributes
1387
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1388        contents[methodAttributeOffset] = (byte) attributeNumber;
1389    }
1390
1391    /**
1392     * INTERNAL USE-ONLY
1393     * Generate the bytes for a synthetic method that provides access to a private method.
1394     *
1395     * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1396     */

1397    public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
1398        generateMethodInfoHeader(methodBinding);
1399        int methodAttributeOffset = this.contentsOffset;
1400        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1401
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1402        // Code attribute
1403
int codeAttributeOffset = contentsOffset;
1404        attributeNumber++; // add code attribute
1405
generateCodeAttributeHeader();
1406        codeStream.init(this);
1407        codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
1408        completeCodeAttributeForSyntheticMethod(
1409            methodBinding,
1410            codeAttributeOffset,
1411            ((SourceTypeBinding) methodBinding.declaringClass)
1412                .scope
1413                .referenceCompilationUnit()
1414                .compilationResult
1415                .getLineSeparatorPositions());
1416        // update the number of attributes
1417
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1418        contents[methodAttributeOffset] = (byte) attributeNumber;
1419    }
1420
1421    public void addSyntheticSwitchTable(SyntheticMethodBinding methodBinding) {
1422        generateMethodInfoHeader(methodBinding);
1423        int methodAttributeOffset = this.contentsOffset;
1424        // this will add exception attribute, synthetic attribute, deprecated attribute,...
1425
int attributeNumber = generateMethodInfoAttribute(methodBinding);
1426        // Code attribute
1427
int codeAttributeOffset = contentsOffset;
1428        attributeNumber++; // add code attribute
1429
generateCodeAttributeHeader();
1430        codeStream.init(this);
1431        codeStream.generateSyntheticBodyForSwitchTable(methodBinding);
1432        completeCodeAttributeForSyntheticMethod(
1433            true,
1434            methodBinding,
1435            codeAttributeOffset,
1436            ((SourceTypeBinding) methodBinding.declaringClass)
1437                .scope
1438                .referenceCompilationUnit()
1439                .compilationResult
1440                .getLineSeparatorPositions());
1441        // update the number of attributes
1442
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1443        contents[methodAttributeOffset] = (byte) attributeNumber;
1444    }
1445
1446    /**
1447     * INTERNAL USE-ONLY
1448     * That method completes the creation of the code attribute by setting
1449     * - the attribute_length
1450     * - max_stack
1451     * - max_locals
1452     * - code_length
1453     * - exception table
1454     * - and debug attributes if necessary.
1455     *
1456     * @param codeAttributeOffset <CODE>int</CODE>
1457     */

1458    public void completeCodeAttribute(int codeAttributeOffset) {
1459        // reinitialize the localContents with the byte modified by the code stream
1460
this.contents = codeStream.bCodeStream;
1461        int localContentsOffset = codeStream.classFileOffset;
1462        // codeAttributeOffset is the position inside localContents byte array before we started to write
1463
// any information about the codeAttribute
1464
// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
1465
// to get the right position, 6 for the max_stack etc...
1466
int code_length = codeStream.position;
1467        if (code_length > 65535) {
1468            codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
1469                codeStream.methodDeclaration);
1470        }
1471        if (localContentsOffset + 20 >= this.contents.length) {
1472            resizeContents(20);
1473        }
1474        int max_stack = codeStream.stackMax;
1475        this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
1476        this.contents[codeAttributeOffset + 7] = (byte) max_stack;
1477        int max_locals = codeStream.maxLocals;
1478        this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
1479        this.contents[codeAttributeOffset + 9] = (byte) max_locals;
1480        this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
1481        this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
1482        this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
1483        this.contents[codeAttributeOffset + 13] = (byte) code_length;
1484
1485        // write the exception table
1486
ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
1487        int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
1488
for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
1489            exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
1490        }
1491        int exSize = exceptionHandlersCount * 8 + 2;
1492        if (exSize + localContentsOffset >= this.contents.length) {
1493            resizeContents(exSize);
1494        }
1495        // there is no exception table, so we need to offset by 2 the current offset and move
1496
// on the attribute generation
1497
this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
1498        this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
1499        for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
1500            ExceptionLabel exceptionLabel = exceptionLabels[i];
1501            if (exceptionLabel != null) {
1502                int iRange = 0, maxRange = exceptionLabel.count;
1503                if ((maxRange & 1) != 0) {
1504                    codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
1505                            Messages.bind(Messages.abort_invalidExceptionAttribute, new String JavaDoc(codeStream.methodDeclaration.selector)),
1506                            codeStream.methodDeclaration);
1507                }
1508                while (iRange < maxRange) {
1509                    int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
1510
this.contents[localContentsOffset++] = (byte) (start >> 8);
1511                    this.contents[localContentsOffset++] = (byte) start;
1512                    int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
1513
this.contents[localContentsOffset++] = (byte) (end >> 8);
1514                    this.contents[localContentsOffset++] = (byte) end;
1515                    int handlerPC = exceptionLabel.position;
1516                    this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
1517                    this.contents[localContentsOffset++] = (byte) handlerPC;
1518                    if (exceptionLabel.exceptionType == null) {
1519                        // any exception handler
1520
this.contents[localContentsOffset++] = 0;
1521                        this.contents[localContentsOffset++] = 0;
1522                    } else {
1523                        int nameIndex;
1524                        if (exceptionLabel.exceptionType == TypeBinding.NULL) {
1525                            /* represents ClassNotFoundException, see class literal access*/
1526                            nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
1527                        } else {
1528                            nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType);
1529                        }
1530                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1531                        this.contents[localContentsOffset++] = (byte) nameIndex;
1532                    }
1533                }
1534            }
1535        }
1536        // debug attributes
1537
int codeAttributeAttributeOffset = localContentsOffset;
1538        int attributeNumber = 0;
1539        // leave two bytes for the attribute_length
1540
localContentsOffset += 2;
1541        if (localContentsOffset + 2 >= this.contents.length) {
1542            resizeContents(2);
1543        }
1544
1545        // first we handle the linenumber attribute
1546
if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
1547            /* Create and add the line number attribute (used for debugging)
1548             * Build the pairs of:
1549             * (bytecodePC lineNumber)
1550             * according to the table of start line indexes and the pcToSourceMap table
1551             * contained into the codestream
1552             */

1553            int[] pcToSourceMapTable;
1554            if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
1555                && (codeStream.pcToSourceMapSize != 0)) {
1556                int lineNumberNameIndex =
1557                    constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
1558                if (localContentsOffset + 8 >= this.contents.length) {
1559                    resizeContents(8);
1560                }
1561                this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
1562                this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
1563                int lineNumberTableOffset = localContentsOffset;
1564                localContentsOffset += 6;
1565                // leave space for attribute_length and line_number_table_length
1566
int numberOfEntries = 0;
1567                int length = codeStream.pcToSourceMapSize;
1568                for (int i = 0; i < length;) {
1569                    // write the entry
1570
if (localContentsOffset + 4 >= this.contents.length) {
1571                        resizeContents(4);
1572                    }
1573                    int pc = pcToSourceMapTable[i++];
1574                    this.contents[localContentsOffset++] = (byte) (pc >> 8);
1575                    this.contents[localContentsOffset++] = (byte) pc;
1576                    int lineNumber = pcToSourceMapTable[i++];
1577                    this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
1578                    this.contents[localContentsOffset++] = (byte) lineNumber;
1579                    numberOfEntries++;
1580                }
1581                // now we change the size of the line number attribute
1582
int lineNumberAttr_length = numberOfEntries * 4 + 2;
1583                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
1584                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
1585                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
1586                this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
1587                this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
1588                this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
1589                attributeNumber++;
1590            }
1591        }
1592        // then we do the local variable attribute
1593
if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
1594            int numberOfEntries = 0;
1595            int localVariableNameIndex =
1596                constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
1597            final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
1598            int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
1599            for (int i = 0; i < codeStream.allLocalsCounter; i++) {
1600                maxOfEntries += 10 * codeStream.locals[i].initializationCount;
1601            }
1602            // reserve enough space
1603
if (localContentsOffset + maxOfEntries >= this.contents.length) {
1604                resizeContents(maxOfEntries);
1605            }
1606            this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
1607            this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
1608            int localVariableTableOffset = localContentsOffset;
1609            // leave space for attribute_length and local_variable_table_length
1610
localContentsOffset += 6;
1611            int nameIndex;
1612            int descriptorIndex;
1613            SourceTypeBinding declaringClassBinding = null;
1614            if (!methodDeclarationIsStatic) {
1615                numberOfEntries++;
1616                this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
1617
this.contents[localContentsOffset++] = 0;
1618                this.contents[localContentsOffset++] = (byte) (code_length >> 8);
1619                this.contents[localContentsOffset++] = (byte) code_length;
1620                nameIndex = constantPool.literalIndex(ConstantPool.This);
1621                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1622                this.contents[localContentsOffset++] = (byte) nameIndex;
1623                declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
1624                descriptorIndex =
1625                    constantPool.literalIndex(
1626                        declaringClassBinding.signature());
1627                this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1628                this.contents[localContentsOffset++] = (byte) descriptorIndex;
1629                this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1630
this.contents[localContentsOffset++] = 0;
1631            }
1632            // used to remember the local variable with a generic type
1633
int genericLocalVariablesCounter = 0;
1634            LocalVariableBinding[] genericLocalVariables = null;
1635            int numberOfGenericEntries = 0;
1636            
1637            for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
1638                LocalVariableBinding localVariable = codeStream.locals[i];
1639                final TypeBinding localVariableTypeBinding = localVariable.type;
1640                boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
1641                if (localVariable.initializationCount != 0 && isParameterizedType) {
1642                    if (genericLocalVariables == null) {
1643                        // we cannot have more than max locals
1644
genericLocalVariables = new LocalVariableBinding[max];
1645                    }
1646                    genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
1647                }
1648                for (int j = 0; j < localVariable.initializationCount; j++) {
1649                    int startPC = localVariable.initializationPCs[j << 1];
1650                    int endPC = localVariable.initializationPCs[(j << 1) + 1];
1651                    if (startPC != endPC) { // only entries for non zero length
1652
if (endPC == -1) {
1653                            localVariable.declaringScope.problemReporter().abortDueToInternalError(
1654                                    Messages.bind(Messages.abort_invalidAttribute, new String JavaDoc(localVariable.name)),
1655                                    (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
1656                        }
1657                        if (isParameterizedType) {
1658                            numberOfGenericEntries++;
1659                        }
1660                        // now we can safely add the local entry
1661
numberOfEntries++;
1662                        this.contents[localContentsOffset++] = (byte) (startPC >> 8);
1663                        this.contents[localContentsOffset++] = (byte) startPC;
1664                        int length = endPC - startPC;
1665                        this.contents[localContentsOffset++] = (byte) (length >> 8);
1666                        this.contents[localContentsOffset++] = (byte) length;
1667                        nameIndex = constantPool.literalIndex(localVariable.name);
1668                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1669                        this.contents[localContentsOffset++] = (byte) nameIndex;
1670                        descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
1671                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1672                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
1673                        int resolvedPosition = localVariable.resolvedPosition;
1674                        this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1675                        this.contents[localContentsOffset++] = (byte) resolvedPosition;
1676                    }
1677                }
1678            }
1679            int value = numberOfEntries * 10 + 2;
1680            this.contents[localVariableTableOffset++] = (byte) (value >> 24);
1681            this.contents[localVariableTableOffset++] = (byte) (value >> 16);
1682            this.contents[localVariableTableOffset++] = (byte) (value >> 8);
1683            this.contents[localVariableTableOffset++] = (byte) value;
1684            this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
1685            this.contents[localVariableTableOffset] = (byte) numberOfEntries;
1686            attributeNumber++;
1687            
1688            final boolean currentInstanceIsGeneric =
1689                !methodDeclarationIsStatic
1690                && declaringClassBinding != null
1691                && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
1692            if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
1693                // add the local variable type table attribute
1694
numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
1695                maxOfEntries = 8 + numberOfGenericEntries * 10;
1696                // reserve enough space
1697
if (localContentsOffset + maxOfEntries >= this.contents.length) {
1698                    resizeContents(maxOfEntries);
1699                }
1700                int localVariableTypeNameIndex =
1701                    constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
1702                this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
1703                this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
1704                value = numberOfGenericEntries * 10 + 2;
1705                this.contents[localContentsOffset++] = (byte) (value >> 24);
1706                this.contents[localContentsOffset++] = (byte) (value >> 16);
1707                this.contents[localContentsOffset++] = (byte) (value >> 8);
1708                this.contents[localContentsOffset++] = (byte) value;
1709                this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
1710                this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
1711                if (currentInstanceIsGeneric) {
1712                    this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
1713
this.contents[localContentsOffset++] = 0;
1714                    this.contents[localContentsOffset++] = (byte) (code_length >> 8);
1715                    this.contents[localContentsOffset++] = (byte) code_length;
1716                    nameIndex = constantPool.literalIndex(ConstantPool.This);
1717                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1718                    this.contents[localContentsOffset++] = (byte) nameIndex;
1719                    descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
1720                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1721                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
1722                    this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1723
this.contents[localContentsOffset++] = 0;
1724                }
1725                
1726                for (int i = 0; i < genericLocalVariablesCounter; i++) {
1727                    LocalVariableBinding localVariable = genericLocalVariables[i];
1728                    for (int j = 0; j < localVariable.initializationCount; j++) {
1729                        int startPC = localVariable.initializationPCs[j << 1];
1730                        int endPC = localVariable.initializationPCs[(j << 1) + 1];
1731                        if (startPC != endPC) {
1732                            // only entries for non zero length
1733
// now we can safely add the local entry
1734
this.contents[localContentsOffset++] = (byte) (startPC >> 8);
1735                            this.contents[localContentsOffset++] = (byte) startPC;
1736                            int length = endPC - startPC;
1737                            this.contents[localContentsOffset++] = (byte) (length >> 8);
1738                            this.contents[localContentsOffset++] = (byte) length;
1739                            nameIndex = constantPool.literalIndex(localVariable.name);
1740                            this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1741                            this.contents[localContentsOffset++] = (byte) nameIndex;
1742                            descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
1743                            this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1744                            this.contents[localContentsOffset++] = (byte) descriptorIndex;
1745                            int resolvedPosition = localVariable.resolvedPosition;
1746                            this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1747                            this.contents[localContentsOffset++] = (byte) resolvedPosition;
1748                        }
1749                    }
1750                }
1751                attributeNumber++;
1752            }
1753        }
1754
1755        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
1756            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
1757            final int framesPositionsSize = framesPositions.size();
1758            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
1759
if (numberOfFrames > 0) {
1760                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
1761                framePositions.addAll(framesPositions);
1762                Collections.sort(framePositions);
1763                int stackMapTableAttributeOffset = localContentsOffset;
1764                // add the stack map table attribute
1765
if (localContentsOffset + 8 >= this.contents.length) {
1766                    resizeContents(8);
1767                }
1768                int stackMapTableAttributeNameIndex =
1769                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
1770                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
1771                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
1772                
1773                int stackMapTableAttributeLengthOffset = localContentsOffset;
1774                // generate the attribute
1775
localContentsOffset += 4;
1776                if (localContentsOffset + 4 >= this.contents.length) {
1777                    resizeContents(4);
1778                }
1779                numberOfFrames = 0;
1780                int numberOfFramesOffset = localContentsOffset;
1781                localContentsOffset += 2;
1782                if (localContentsOffset + 2 >= this.contents.length) {
1783                    resizeContents(2);
1784                }
1785                ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
1786                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
1787                StackMapFrame prevFrame = null;
1788                int framesSize = frames.size();
1789                int frameIndex = 0;
1790                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
1791                    // select next frame
1792
prevFrame = currentFrame;
1793                    currentFrame = null;
1794                    for (; frameIndex < framesSize; frameIndex++) {
1795                        currentFrame = (StackMapFrame) frames.get(frameIndex);
1796                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
1797                            break;
1798                        }
1799                    }
1800                    if (currentFrame == null) break;
1801                    // generate current frame
1802
// need to find differences between the current frame and the previous frame
1803
numberOfFrames++;
1804                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
1805                    switch (currentFrame.getFrameType(prevFrame)) {
1806                        case StackMapFrame.APPEND_FRAME :
1807                            if (localContentsOffset + 3 >= this.contents.length) {
1808                                resizeContents(3);
1809                            }
1810                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
1811                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
1812                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1813                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1814                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
1815                            int numberOfLocals = currentFrame.getNumberOfLocals();
1816                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
1817                                if (localContentsOffset + 6 >= this.contents.length) {
1818                                    resizeContents(6);
1819                                }
1820                                VerificationTypeInfo info = currentFrame.locals[i];
1821                                if (info == null) {
1822                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
1823                                } else {
1824                                    switch(info.id()) {
1825                                        case T_boolean :
1826                                        case T_byte :
1827                                        case T_char :
1828                                        case T_int :
1829                                        case T_short :
1830                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
1831                                            break;
1832                                        case T_float :
1833                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
1834                                            break;
1835                                        case T_long :
1836                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
1837                                            i++;
1838                                            break;
1839                                        case T_double :
1840                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
1841                                            i++;
1842                                            break;
1843                                        case T_null :
1844                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
1845                                            break;
1846                                        default:
1847                                            this.contents[localContentsOffset++] = (byte) info.tag;
1848                                            switch (info.tag) {
1849                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
1850                                                    int offset = info.offset;
1851                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
1852                                                    this.contents[localContentsOffset++] = (byte) offset;
1853                                                    break;
1854                                                case VerificationTypeInfo.ITEM_OBJECT :
1855                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
1856                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
1857                                                    this.contents[localContentsOffset++] = (byte) indexForType;
1858                                            }
1859                                    }
1860                                    numberOfDifferentLocals--;
1861                                }
1862                            }
1863                            break;
1864                        case StackMapFrame.SAME_FRAME :
1865                            if (localContentsOffset + 1 >= this.contents.length) {
1866                                resizeContents(1);
1867                            }
1868                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1869                            break;
1870                        case StackMapFrame.SAME_FRAME_EXTENDED :
1871                            if (localContentsOffset + 3 >= this.contents.length) {
1872                                resizeContents(3);
1873                            }
1874                            this.contents[localContentsOffset++] = (byte) 251;
1875                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1876                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1877                            break;
1878                        case StackMapFrame.CHOP_FRAME :
1879                            if (localContentsOffset + 3 >= this.contents.length) {
1880                                resizeContents(3);
1881                            }
1882                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
1883                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
1884                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1885                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1886                            break;
1887                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
1888                            if (localContentsOffset + 4 >= this.contents.length) {
1889                                resizeContents(4);
1890                            }
1891                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
1892                            if (currentFrame.stackItems[0] == null) {
1893                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
1894                            } else {
1895                                switch(currentFrame.stackItems[0].id()) {
1896                                    case T_boolean :
1897                                    case T_byte :
1898                                    case T_char :
1899                                    case T_int :
1900                                    case T_short :
1901                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
1902                                        break;
1903                                    case T_float :
1904                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
1905                                        break;
1906                                    case T_long :
1907                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
1908                                        break;
1909                                    case T_double :
1910                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
1911                                        break;
1912                                    case T_null :
1913                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
1914                                        break;
1915                                    default:
1916                                        VerificationTypeInfo info = currentFrame.stackItems[0];
1917                                        byte tag = (byte) info.tag;
1918                                        this.contents[localContentsOffset++] = tag;
1919                                        switch (tag) {
1920                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
1921                                                int offset = info.offset;
1922                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
1923                                                this.contents[localContentsOffset++] = (byte) offset;
1924                                                break;
1925                                            case VerificationTypeInfo.ITEM_OBJECT :
1926                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
1927                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
1928                                                this.contents[localContentsOffset++] = (byte) indexForType;
1929                                        }
1930                                }
1931                            }
1932                            break;
1933                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
1934                            if (localContentsOffset + 6 >= this.contents.length) {
1935                                resizeContents(6);
1936                            }
1937                            this.contents[localContentsOffset++] = (byte) 247;
1938                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1939                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1940                            if (currentFrame.stackItems[0] == null) {
1941                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
1942                            } else {
1943                                switch(currentFrame.stackItems[0].id()) {
1944                                    case T_boolean :
1945                                    case T_byte :
1946                                    case T_char :
1947                                    case T_int :
1948                                    case T_short :
1949                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
1950                                        break;
1951                                    case T_float :
1952                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
1953                                        break;
1954                                    case T_long :
1955                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
1956                                        break;
1957                                    case T_double :
1958                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
1959                                        break;
1960                                    case T_null :
1961                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
1962                                        break;
1963                                    default:
1964                                        VerificationTypeInfo info = currentFrame.stackItems[0];
1965                                        byte tag = (byte) info.tag;
1966                                        this.contents[localContentsOffset++] = tag;
1967                                        switch (tag) {
1968                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
1969                                                int offset = info.offset;
1970                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
1971                                                this.contents[localContentsOffset++] = (byte) offset;
1972                                                break;
1973                                            case VerificationTypeInfo.ITEM_OBJECT :
1974                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
1975                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
1976                                                this.contents[localContentsOffset++] = (byte) indexForType;
1977                                        }
1978                                }
1979                            }
1980                            break;
1981                        default :
1982                            // FULL_FRAME
1983
if (localContentsOffset + 5 >= this.contents.length) {
1984                                resizeContents(5);
1985                            }
1986                            this.contents[localContentsOffset++] = (byte) 255;
1987                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1988                            this.contents[localContentsOffset++] = (byte) offsetDelta;
1989                            int numberOfLocalOffset = localContentsOffset;
1990                            localContentsOffset += 2; // leave two spots for number of locals
1991
int numberOfLocalEntries = 0;
1992                            numberOfLocals = currentFrame.getNumberOfLocals();
1993                            int numberOfEntries = 0;
1994                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
1995                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
1996                                if (localContentsOffset + 3 >= this.contents.length) {
1997                                    resizeContents(3);
1998                                }
1999                                VerificationTypeInfo info = currentFrame.locals[i];
2000                                if (info == null) {
2001                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2002                                } else {
2003                                    switch(info.id()) {
2004                                        case T_boolean :
2005                                        case T_byte :
2006                                        case T_char :
2007                                        case T_int :
2008                                        case T_short :
2009                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2010                                            break;
2011                                        case T_float :
2012                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2013                                            break;
2014                                        case T_long :
2015                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2016                                            i++;
2017                                            break;
2018                                        case T_double :
2019                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2020                                            i++;
2021                                            break;
2022                                        case T_null :
2023                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2024                                            break;
2025                                        default:
2026                                            this.contents[localContentsOffset++] = (byte) info.tag;
2027                                            switch (info.tag) {
2028                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2029                                                    int offset = info.offset;
2030                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2031                                                    this.contents[localContentsOffset++] = (byte) offset;
2032                                                    break;
2033                                                case VerificationTypeInfo.ITEM_OBJECT :
2034                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2035                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2036                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2037                                            }
2038                                    }
2039                                    numberOfLocalEntries++;
2040                                }
2041                                numberOfEntries++;
2042                            }
2043                            if (localContentsOffset + 4 >= this.contents.length) {
2044                                resizeContents(4);
2045                            }
2046                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
2047                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
2048                            int numberOfStackItems = currentFrame.numberOfStackItems;
2049                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
2050                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
2051                            for (int i = 0; i < numberOfStackItems; i++) {
2052                                if (localContentsOffset + 3 >= this.contents.length) {
2053                                    resizeContents(3);
2054                                }
2055                                VerificationTypeInfo info = currentFrame.stackItems[i];
2056                                if (info == null) {
2057                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2058                                } else {
2059                                    switch(info.id()) {
2060                                        case T_boolean :
2061                                        case T_byte :
2062                                        case T_char :
2063                                        case T_int :
2064                                        case T_short :
2065                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2066                                            break;
2067                                        case T_float :
2068                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2069                                            break;
2070                                        case T_long :
2071                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2072                                            break;
2073                                        case T_double :
2074                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2075                                            break;
2076                                        case T_null :
2077                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2078                                            break;
2079                                        default:
2080                                            this.contents[localContentsOffset++] = (byte) info.tag;
2081                                            switch (info.tag) {
2082                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2083                                                    int offset = info.offset;
2084                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2085                                                    this.contents[localContentsOffset++] = (byte) offset;
2086                                                    break;
2087                                                case VerificationTypeInfo.ITEM_OBJECT :
2088                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2089                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2090                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2091                                            }
2092                                    }
2093                                }
2094                            }
2095                    }
2096                }
2097                
2098                if (numberOfFrames != 0) {
2099                    this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
2100                    this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
2101    
2102                    int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
2103                    this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
2104                    this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
2105                    this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
2106                    this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
2107                    attributeNumber++;
2108                } else {
2109                    localContentsOffset = stackMapTableAttributeOffset;
2110                }
2111            }
2112        }
2113
2114        this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2115        this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2116
2117        // update the attribute length
2118
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2119        this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2120        this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2121        this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2122        this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2123        contentsOffset = localContentsOffset;
2124    }
2125
2126    /**
2127     * INTERNAL USE-ONLY
2128     * That method completes the creation of the code attribute by setting
2129     * - the attribute_length
2130     * - max_stack
2131     * - max_locals
2132     * - code_length
2133     * - exception table
2134     * - and debug attributes if necessary.
2135     *
2136     * @param codeAttributeOffset <CODE>int</CODE>
2137     */

2138    public void completeCodeAttributeForClinit(int codeAttributeOffset) {
2139        // reinitialize the contents with the byte modified by the code stream
2140
this.contents = codeStream.bCodeStream;
2141        int localContentsOffset = codeStream.classFileOffset;
2142        // codeAttributeOffset is the position inside contents byte array before we started to write
2143
// any information about the codeAttribute
2144
// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
2145
// to get the right position, 6 for the max_stack etc...
2146
int code_length = codeStream.position;
2147        if (code_length > 65535) {
2148            codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
2149                codeStream.methodDeclaration.scope.referenceType());
2150        }
2151        if (localContentsOffset + 20 >= this.contents.length) {
2152            resizeContents(20);
2153        }
2154        int max_stack = codeStream.stackMax;
2155        this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2156        this.contents[codeAttributeOffset + 7] = (byte) max_stack;
2157        int max_locals = codeStream.maxLocals;
2158        this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2159        this.contents[codeAttributeOffset + 9] = (byte) max_locals;
2160        this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2161        this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2162        this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2163        this.contents[codeAttributeOffset + 13] = (byte) code_length;
2164
2165        // write the exception table
2166
ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
2167        int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
2168
for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
2169            exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
2170        }
2171        int exSize = exceptionHandlersCount * 8 + 2;
2172        if (exSize + localContentsOffset >= this.contents.length) {
2173            resizeContents(exSize);
2174        }
2175        // there is no exception table, so we need to offset by 2 the current offset and move
2176
// on the attribute generation
2177
this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
2178        this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
2179        for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
2180            ExceptionLabel exceptionLabel = exceptionLabels[i];
2181            if (exceptionLabel != null) {
2182                int iRange = 0, maxRange = exceptionLabel.count;
2183                if ((maxRange & 1) != 0) {
2184                    codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
2185                            Messages.bind(Messages.abort_invalidExceptionAttribute, new String JavaDoc(codeStream.methodDeclaration.selector)),
2186                            codeStream.methodDeclaration);
2187                }
2188                while (iRange < maxRange) {
2189                    int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
2190
this.contents[localContentsOffset++] = (byte) (start >> 8);
2191                    this.contents[localContentsOffset++] = (byte) start;
2192                    int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
2193
this.contents[localContentsOffset++] = (byte) (end >> 8);
2194                    this.contents[localContentsOffset++] = (byte) end;
2195                    int handlerPC = exceptionLabel.position;
2196                    this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
2197                    this.contents[localContentsOffset++] = (byte) handlerPC;
2198                    if (exceptionLabel.exceptionType == null) {
2199                        // any exception handler
2200
this.contents[localContentsOffset++] = 0;
2201                        this.contents[localContentsOffset++] = 0;
2202                    } else {
2203                        int nameIndex;
2204                        if (exceptionLabel.exceptionType == TypeBinding.NULL) {
2205                            /* represents denote ClassNotFoundException, see class literal access*/
2206                            nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
2207                        } else {
2208                            nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType);
2209                        }
2210                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2211                        this.contents[localContentsOffset++] = (byte) nameIndex;
2212                    }
2213                }
2214            }
2215        }
2216        // debug attributes
2217
int codeAttributeAttributeOffset = localContentsOffset;
2218        int attributeNumber = 0;
2219        // leave two bytes for the attribute_length
2220
localContentsOffset += 2;
2221        if (localContentsOffset + 2 >= this.contents.length) {
2222            resizeContents(2);
2223        }
2224
2225        // first we handle the linenumber attribute
2226
if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
2227            /* Create and add the line number attribute (used for debugging)
2228             * Build the pairs of:
2229             * (bytecodePC lineNumber)
2230             * according to the table of start line indexes and the pcToSourceMap table
2231             * contained into the codestream
2232             */

2233            int[] pcToSourceMapTable;
2234            if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
2235                && (codeStream.pcToSourceMapSize != 0)) {
2236                int lineNumberNameIndex =
2237                    constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2238                if (localContentsOffset + 8 >= this.contents.length) {
2239                    resizeContents(8);
2240                }
2241                this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2242                this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2243                int lineNumberTableOffset = localContentsOffset;
2244                localContentsOffset += 6;
2245                // leave space for attribute_length and line_number_table_length
2246
int numberOfEntries = 0;
2247                int length = codeStream.pcToSourceMapSize;
2248                for (int i = 0; i < length;) {
2249                    // write the entry
2250
if (localContentsOffset + 4 >= this.contents.length) {
2251                        resizeContents(4);
2252                    }
2253                    int pc = pcToSourceMapTable[i++];
2254                    this.contents[localContentsOffset++] = (byte) (pc >> 8);
2255                    this.contents[localContentsOffset++] = (byte) pc;
2256                    int lineNumber = pcToSourceMapTable[i++];
2257                    this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
2258                    this.contents[localContentsOffset++] = (byte) lineNumber;
2259                    numberOfEntries++;
2260                }
2261                // now we change the size of the line number attribute
2262
int lineNumberAttr_length = numberOfEntries * 4 + 2;
2263                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
2264                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
2265                this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
2266                this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
2267                this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
2268                this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
2269                attributeNumber++;
2270            }
2271        }
2272        // then we do the local variable attribute
2273
if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
2274            int numberOfEntries = 0;
2275            // codeAttribute.addLocalVariableTableAttribute(this);
2276
if ((codeStream.pcToSourceMap != null)
2277                && (codeStream.pcToSourceMapSize != 0)) {
2278                int localVariableNameIndex =
2279                    constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
2280                if (localContentsOffset + 8 >= this.contents.length) {
2281                    resizeContents(8);
2282                }
2283                this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2284                this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
2285                int localVariableTableOffset = localContentsOffset;
2286                localContentsOffset += 6;
2287
2288                // leave space for attribute_length and local_variable_table_length
2289
int nameIndex;
2290                int descriptorIndex;
2291
2292                // used to remember the local variable with a generic type
2293
int genericLocalVariablesCounter = 0;
2294                LocalVariableBinding[] genericLocalVariables = null;
2295                int numberOfGenericEntries = 0;
2296
2297                for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
2298                    LocalVariableBinding localVariable = codeStream.locals[i];
2299                    final TypeBinding localVariableTypeBinding = localVariable.type;
2300                    boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
2301                    if (localVariable.initializationCount != 0 && isParameterizedType) {
2302                        if (genericLocalVariables == null) {
2303                            // we cannot have more than max locals
2304
genericLocalVariables = new LocalVariableBinding[max];
2305                        }
2306                        genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
2307                    }
2308                    for (int j = 0; j < localVariable.initializationCount; j++) {
2309                        int startPC = localVariable.initializationPCs[j << 1];
2310                        int endPC = localVariable.initializationPCs[(j << 1) + 1];
2311                        if (startPC != endPC) { // only entries for non zero length
2312
if (endPC == -1) {
2313                                localVariable.declaringScope.problemReporter().abortDueToInternalError(
2314                                    Messages.bind(Messages.abort_invalidAttribute, new String JavaDoc(localVariable.name)),
2315                                    (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
2316                            }
2317                            if (localContentsOffset + 10 >= this.contents.length) {
2318                                resizeContents(10);
2319                            }
2320                            // now we can safely add the local entry
2321
numberOfEntries++;
2322                            if (isParameterizedType) {
2323                                numberOfGenericEntries++;
2324                            }
2325                            this.contents[localContentsOffset++] = (byte) (startPC >> 8);
2326                            this.contents[localContentsOffset++] = (byte) startPC;
2327                            int length = endPC - startPC;
2328                            this.contents[localContentsOffset++] = (byte) (length >> 8);
2329                            this.contents[localContentsOffset++] = (byte) length;
2330                            nameIndex = constantPool.literalIndex(localVariable.name);
2331                            this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2332                            this.contents[localContentsOffset++] = (byte) nameIndex;
2333                            descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
2334                            this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2335                            this.contents[localContentsOffset++] = (byte) descriptorIndex;
2336                            int resolvedPosition = localVariable.resolvedPosition;
2337                            this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2338                            this.contents[localContentsOffset++] = (byte) resolvedPosition;
2339                        }
2340                    }
2341                }
2342                int value = numberOfEntries * 10 + 2;
2343                this.contents[localVariableTableOffset++] = (byte) (value >> 24);
2344                this.contents[localVariableTableOffset++] = (byte) (value >> 16);
2345                this.contents[localVariableTableOffset++] = (byte) (value >> 8);
2346                this.contents[localVariableTableOffset++] = (byte) value;
2347                this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
2348                this.contents[localVariableTableOffset] = (byte) numberOfEntries;
2349                attributeNumber++;
2350
2351                if (genericLocalVariablesCounter != 0) {
2352                    // add the local variable type table attribute
2353
// reserve enough space
2354
int maxOfEntries = 8 + numberOfGenericEntries * 10;
2355
2356                    if (localContentsOffset + maxOfEntries >= this.contents.length) {
2357                        resizeContents(maxOfEntries);
2358                    }
2359                    int localVariableTypeNameIndex =
2360                        constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
2361                    this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
2362                    this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
2363                    value = numberOfGenericEntries * 10 + 2;
2364                    this.contents[localContentsOffset++] = (byte) (value >> 24);
2365                    this.contents[localContentsOffset++] = (byte) (value >> 16);
2366                    this.contents[localContentsOffset++] = (byte) (value >> 8);
2367                    this.contents[localContentsOffset++] = (byte) value;
2368                    this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
2369                    this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
2370                    for (int i = 0; i < genericLocalVariablesCounter; i++) {
2371                        LocalVariableBinding localVariable = genericLocalVariables[i];
2372                        for (int j = 0; j < localVariable.initializationCount; j++) {
2373                            int startPC = localVariable.initializationPCs[j << 1];
2374                            int endPC = localVariable.initializationPCs[(j << 1) + 1];
2375                            if (startPC != endPC) { // only entries for non zero length
2376
// now we can safely add the local entry
2377
this.contents[localContentsOffset++] = (byte) (startPC >> 8);
2378                                this.contents[localContentsOffset++] = (byte) startPC;
2379                                int length = endPC - startPC;
2380                                this.contents[localContentsOffset++] = (byte) (length >> 8);
2381                                this.contents[localContentsOffset++] = (byte) length;
2382                                nameIndex = constantPool.literalIndex(localVariable.name);
2383                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2384                                this.contents[localContentsOffset++] = (byte) nameIndex;
2385                                descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
2386                                this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2387                                this.contents[localContentsOffset++] = (byte) descriptorIndex;
2388                                int resolvedPosition = localVariable.resolvedPosition;
2389                                this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2390                                this.contents[localContentsOffset++] = (byte) resolvedPosition;
2391                            }
2392                        }
2393                    }
2394                    attributeNumber++;
2395                }
2396            }
2397        }
2398        
2399        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
2400            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
2401            final int framesPositionsSize = framesPositions.size();
2402            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
2403
if (numberOfFrames > 0) {
2404                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
2405                framePositions.addAll(framesPositions);
2406                Collections.sort(framePositions);
2407                // add the stack map table attribute
2408
if (localContentsOffset + 8 >= this.contents.length) {
2409                    resizeContents(8);
2410                }
2411                int stackMapTableAttributeNameIndex =
2412                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
2413                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
2414                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
2415                
2416                int stackMapTableAttributeLengthOffset = localContentsOffset;
2417                // generate the attribute
2418
localContentsOffset += 4;
2419                numberOfFrames = 0;
2420                int numberOfFramesOffset = localContentsOffset;
2421                localContentsOffset += 2;
2422                // generate all frames
2423
ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
2424                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
2425                StackMapFrame prevFrame = null;
2426                int framesSize = frames.size();
2427                int frameIndex = 0;
2428                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
2429                    // select next frame
2430
prevFrame = currentFrame;
2431                    currentFrame = null;
2432                    for (; frameIndex < framesSize; frameIndex++) {
2433                        currentFrame = (StackMapFrame) frames.get(frameIndex);
2434                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
2435                            break;
2436                        }
2437                    }
2438                    if (currentFrame == null) break;
2439                    numberOfFrames++;
2440                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
2441                    switch (currentFrame.getFrameType(prevFrame)) {
2442                        case StackMapFrame.APPEND_FRAME :
2443                            if (localContentsOffset + 3 >= this.contents.length) {
2444                                resizeContents(3);
2445                            }
2446                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
2447                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
2448                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2449                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2450                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
2451                            int numberOfLocals = currentFrame.getNumberOfLocals();
2452                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
2453                                if (localContentsOffset + 6 >= this.contents.length) {
2454                                    resizeContents(6);
2455                                }
2456                                VerificationTypeInfo info = currentFrame.locals[i];
2457                                if (info == null) {
2458                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2459                                } else {
2460                                    switch(info.id()) {
2461                                        case T_boolean :
2462                                        case T_byte :
2463                                        case T_char :
2464                                        case T_int :
2465                                        case T_short :
2466                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2467                                            break;
2468                                        case T_float :
2469                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2470                                            break;
2471                                        case T_long :
2472                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2473                                            i++;
2474                                            break;
2475                                        case T_double :
2476                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2477                                            i++;
2478                                            break;
2479                                        case T_null :
2480                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2481                                            break;
2482                                        default:
2483                                            this.contents[localContentsOffset++] = (byte) info.tag;
2484                                            switch (info.tag) {
2485                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2486                                                    int offset = info.offset;
2487                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2488                                                    this.contents[localContentsOffset++] = (byte) offset;
2489                                                    break;
2490                                                case VerificationTypeInfo.ITEM_OBJECT :
2491                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2492                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2493                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2494                                            }
2495                                    }
2496                                    numberOfDifferentLocals--;
2497                                }
2498                            }
2499                            break;
2500                        case StackMapFrame.SAME_FRAME :
2501                            if (localContentsOffset + 1 >= this.contents.length) {
2502                                resizeContents(1);
2503                            }
2504                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2505                            break;
2506                        case StackMapFrame.SAME_FRAME_EXTENDED :
2507                            if (localContentsOffset + 3 >= this.contents.length) {
2508                                resizeContents(3);
2509                            }
2510                            this.contents[localContentsOffset++] = (byte) 251;
2511                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2512                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2513                            break;
2514                        case StackMapFrame.CHOP_FRAME :
2515                            if (localContentsOffset + 3 >= this.contents.length) {
2516                                resizeContents(3);
2517                            }
2518                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
2519                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
2520                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2521                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2522                            break;
2523                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
2524                            if (localContentsOffset + 4 >= this.contents.length) {
2525                                resizeContents(4);
2526                            }
2527                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
2528                            if (currentFrame.stackItems[0] == null) {
2529                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2530                            } else {
2531                                switch(currentFrame.stackItems[0].id()) {
2532                                    case T_boolean :
2533                                    case T_byte :
2534                                    case T_char :
2535                                    case T_int :
2536                                    case T_short :
2537                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2538                                        break;
2539                                    case T_float :
2540                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2541                                        break;
2542                                    case T_long :
2543                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2544                                        break;
2545                                    case T_double :
2546                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2547                                        break;
2548                                    case T_null :
2549                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2550                                        break;
2551                                    default:
2552                                        VerificationTypeInfo info = currentFrame.stackItems[0];
2553                                        this.contents[localContentsOffset++] = (byte) info.tag;
2554                                        switch (info.tag) {
2555                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
2556                                                int offset = info.offset;
2557                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
2558                                                this.contents[localContentsOffset++] = (byte) offset;
2559                                                break;
2560                                            case VerificationTypeInfo.ITEM_OBJECT :
2561                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2562                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2563                                                this.contents[localContentsOffset++] = (byte) indexForType;
2564                                        }
2565                                }
2566                            }
2567                            break;
2568                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
2569                            if (localContentsOffset + 6 >= this.contents.length) {
2570                                resizeContents(6);
2571                            }
2572                            this.contents[localContentsOffset++] = (byte) 247;
2573                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2574                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2575                            if (currentFrame.stackItems[0] == null) {
2576                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2577                            } else {
2578                                switch(currentFrame.stackItems[0].id()) {
2579                                    case T_boolean :
2580                                    case T_byte :
2581                                    case T_char :
2582                                    case T_int :
2583                                    case T_short :
2584                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2585                                        break;
2586                                    case T_float :
2587                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2588                                        break;
2589                                    case T_long :
2590                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2591                                        break;
2592                                    case T_double :
2593                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2594                                        break;
2595                                    case T_null :
2596                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2597                                        break;
2598                                    default:
2599                                        VerificationTypeInfo info = currentFrame.stackItems[0];
2600                                        this.contents[localContentsOffset++] = (byte) info.tag;
2601                                        switch (info.tag) {
2602                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
2603                                                int offset = info.offset;
2604                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
2605                                                this.contents[localContentsOffset++] = (byte) offset;
2606                                                break;
2607                                            case VerificationTypeInfo.ITEM_OBJECT :
2608                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2609                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2610                                                this.contents[localContentsOffset++] = (byte) indexForType;
2611                                        }
2612                                }
2613                            }
2614                            break;
2615                        default :
2616                            // FULL_FRAME
2617
if (localContentsOffset + 5 >= this.contents.length) {
2618                                resizeContents(5);
2619                            }
2620                            this.contents[localContentsOffset++] = (byte) 255;
2621                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2622                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2623                            int numberOfLocalOffset = localContentsOffset;
2624                            localContentsOffset += 2; // leave two spots for number of locals
2625
int numberOfLocalEntries = 0;
2626                            numberOfLocals = currentFrame.getNumberOfLocals();
2627                            int numberOfEntries = 0;
2628                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
2629                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
2630                                if (localContentsOffset + 3 >= this.contents.length) {
2631                                    resizeContents(3);
2632                                }
2633                                VerificationTypeInfo info = currentFrame.locals[i];
2634                                if (info == null) {
2635                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2636                                } else {
2637                                    switch(info.id()) {
2638                                        case T_boolean :
2639                                        case T_byte :
2640                                        case T_char :
2641                                        case T_int :
2642                                        case T_short :
2643                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2644                                            break;
2645                                        case T_float :
2646                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2647                                            break;
2648                                        case T_long :
2649                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2650                                            i++;
2651                                            break;
2652                                        case T_double :
2653                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2654                                            i++;
2655                                            break;
2656                                        case T_null :
2657                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2658                                            break;
2659                                        default:
2660                                            this.contents[localContentsOffset++] = (byte) info.tag;
2661                                            switch (info.tag) {
2662                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2663                                                    int offset = info.offset;
2664                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2665                                                    this.contents[localContentsOffset++] = (byte) offset;
2666                                                    break;
2667                                                case VerificationTypeInfo.ITEM_OBJECT :
2668                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2669                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2670                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2671                                            }
2672                                    }
2673                                    numberOfLocalEntries++;
2674                                }
2675                                numberOfEntries++;
2676                            }
2677                            if (localContentsOffset + 4 >= this.contents.length) {
2678                                resizeContents(4);
2679                            }
2680                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
2681                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
2682                            int numberOfStackItems = currentFrame.numberOfStackItems;
2683                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
2684                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
2685                            for (int i = 0; i < numberOfStackItems; i++) {
2686                                if (localContentsOffset + 3 >= this.contents.length) {
2687                                    resizeContents(3);
2688                                }
2689                                VerificationTypeInfo info = currentFrame.stackItems[i];
2690                                if (info == null) {
2691                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2692                                } else {
2693                                    switch(info.id()) {
2694                                        case T_boolean :
2695                                        case T_byte :
2696                                        case T_char :
2697                                        case T_int :
2698                                        case T_short :
2699                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2700                                            break;
2701                                        case T_float :
2702                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2703                                            break;
2704                                        case T_long :
2705                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2706                                            break;
2707                                        case T_double :
2708                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2709                                            break;
2710                                        case T_null :
2711                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2712                                            break;
2713                                        default:
2714                                            this.contents[localContentsOffset++] = (byte) info.tag;
2715                                            switch (info.tag) {
2716                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2717                                                    int offset = info.offset;
2718                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2719                                                    this.contents[localContentsOffset++] = (byte) offset;
2720                                                    break;
2721                                                case VerificationTypeInfo.ITEM_OBJECT :
2722                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2723                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2724                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2725                                            }
2726                                    }
2727                                }
2728                            }
2729                    }
2730                }
2731                
2732                this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
2733                this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
2734
2735                int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
2736                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
2737                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
2738                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
2739                this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
2740                attributeNumber++;
2741            }
2742        }
2743        
2744        // update the number of attributes
2745
// ensure first that there is enough space available inside the contents array
2746
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
2747            resizeContents(2);
2748        }
2749        this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2750        this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2751        // update the attribute length
2752
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
2753        this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2754        this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2755        this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2756        this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2757        contentsOffset = localContentsOffset;
2758    }
2759
2760    /**
2761     * INTERNAL USE-ONLY
2762     * That method completes the creation of the code attribute by setting
2763     * - the attribute_length
2764     * - max_stack
2765     * - max_locals
2766     * - code_length
2767     * - exception table
2768     * - and debug attributes if necessary.
2769     */

2770    public void completeCodeAttributeForClinit(
2771        int codeAttributeOffset,
2772        int problemLine) {
2773        // reinitialize the contents with the byte modified by the code stream
2774
this.contents = codeStream.bCodeStream;
2775        int localContentsOffset = codeStream.classFileOffset;
2776        // codeAttributeOffset is the position inside contents byte array before we started to write
2777
// any information about the codeAttribute
2778
// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
2779
// to get the right position, 6 for the max_stack etc...
2780
int code_length = codeStream.position;
2781        if (code_length > 65535) {
2782            codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
2783                codeStream.methodDeclaration.scope.referenceType());
2784        }
2785        if (localContentsOffset + 20 >= this.contents.length) {
2786            resizeContents(20);
2787        }
2788        int max_stack = codeStream.stackMax;
2789        this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2790        this.contents[codeAttributeOffset + 7] = (byte) max_stack;
2791        int max_locals = codeStream.maxLocals;
2792        this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2793        this.contents[codeAttributeOffset + 9] = (byte) max_locals;
2794        this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2795        this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2796        this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2797        this.contents[codeAttributeOffset + 13] = (byte) code_length;
2798
2799        // write the exception table
2800
this.contents[localContentsOffset++] = 0;
2801        this.contents[localContentsOffset++] = 0;
2802
2803        // debug attributes
2804
int codeAttributeAttributeOffset = localContentsOffset;
2805        int attributeNumber = 0; // leave two bytes for the attribute_length
2806
localContentsOffset += 2; // first we handle the linenumber attribute
2807
if (localContentsOffset + 2 >= this.contents.length) {
2808            resizeContents(2);
2809        }
2810
2811        // first we handle the linenumber attribute
2812
if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
2813            if (localContentsOffset + 20 >= this.contents.length) {
2814                resizeContents(20);
2815            }
2816            /* Create and add the line number attribute (used for debugging)
2817                * Build the pairs of:
2818                * (bytecodePC lineNumber)
2819                * according to the table of start line indexes and the pcToSourceMap table
2820                * contained into the codestream
2821                */

2822            int lineNumberNameIndex =
2823                constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
2824            this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2825            this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2826            this.contents[localContentsOffset++] = 0;
2827            this.contents[localContentsOffset++] = 0;
2828            this.contents[localContentsOffset++] = 0;
2829            this.contents[localContentsOffset++] = 6;
2830            this.contents[localContentsOffset++] = 0;
2831            this.contents[localContentsOffset++] = 1;
2832            // first entry at pc = 0
2833
this.contents[localContentsOffset++] = 0;
2834            this.contents[localContentsOffset++] = 0;
2835            this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
2836            this.contents[localContentsOffset++] = (byte) problemLine;
2837            // now we change the size of the line number attribute
2838
attributeNumber++;
2839        }
2840        // then we do the local variable attribute
2841
if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
2842            int localVariableNameIndex =
2843                constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
2844            if (localContentsOffset + 8 >= this.contents.length) {
2845                resizeContents(8);
2846            }
2847            this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2848            this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
2849            this.contents[localContentsOffset++] = 0;
2850            this.contents[localContentsOffset++] = 0;
2851            this.contents[localContentsOffset++] = 0;
2852            this.contents[localContentsOffset++] = 2;
2853            this.contents[localContentsOffset++] = 0;
2854            this.contents[localContentsOffset++] = 0;
2855            attributeNumber++;
2856        }
2857        
2858        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
2859            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
2860            final int framesPositionsSize = framesPositions.size();
2861            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
2862
if (numberOfFrames > 0) {
2863                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
2864                framePositions.addAll(framesPositions);
2865                Collections.sort(framePositions);
2866                // add the stack map table attribute
2867
if (localContentsOffset + 8 >= this.contents.length) {
2868                    resizeContents(8);
2869                }
2870                int stackMapTableAttributeNameIndex =
2871                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
2872                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
2873                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
2874                
2875                int stackMapTableAttributeLengthOffset = localContentsOffset;
2876                // generate the attribute
2877
localContentsOffset += 4;
2878                numberOfFrames = 0;
2879                int numberOfFramesOffset = localContentsOffset;
2880                localContentsOffset += 2;
2881                // generate all frames
2882
ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
2883                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
2884                StackMapFrame prevFrame = null;
2885                int framesSize = frames.size();
2886                int frameIndex = 0;
2887                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
2888                    // select next frame
2889
prevFrame = currentFrame;
2890                    currentFrame = null;
2891                    for (; frameIndex < framesSize; frameIndex++) {
2892                        currentFrame = (StackMapFrame) frames.get(frameIndex);
2893                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
2894                            break;
2895                        }
2896                    }
2897                    if (currentFrame == null) break;
2898                    // generate current frame
2899
// need to find differences between the current frame and the previous frame
2900
numberOfFrames++;
2901                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
2902                    switch (currentFrame.getFrameType(prevFrame)) {
2903                        case StackMapFrame.APPEND_FRAME :
2904                            if (localContentsOffset + 3 >= this.contents.length) {
2905                                resizeContents(3);
2906                            }
2907                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
2908                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
2909                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2910                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2911                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
2912                            int numberOfLocals = currentFrame.getNumberOfLocals();
2913                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
2914                                if (localContentsOffset + 6 >= this.contents.length) {
2915                                    resizeContents(6);
2916                                }
2917                                VerificationTypeInfo info = currentFrame.locals[i];
2918                                if (info == null) {
2919                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2920                                } else {
2921                                    switch(info.id()) {
2922                                        case T_boolean :
2923                                        case T_byte :
2924                                        case T_char :
2925                                        case T_int :
2926                                        case T_short :
2927                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2928                                            break;
2929                                        case T_float :
2930                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2931                                            break;
2932                                        case T_long :
2933                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2934                                            i++;
2935                                            break;
2936                                        case T_double :
2937                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2938                                            i++;
2939                                            break;
2940                                        case T_null :
2941                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2942                                            break;
2943                                        default:
2944                                            this.contents[localContentsOffset++] = (byte) info.tag;
2945                                            switch (info.tag) {
2946                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
2947                                                    int offset = info.offset;
2948                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
2949                                                    this.contents[localContentsOffset++] = (byte) offset;
2950                                                    break;
2951                                                case VerificationTypeInfo.ITEM_OBJECT :
2952                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
2953                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
2954                                                    this.contents[localContentsOffset++] = (byte) indexForType;
2955                                            }
2956                                    }
2957                                    numberOfDifferentLocals--;
2958                                }
2959                            }
2960                            break;
2961                        case StackMapFrame.SAME_FRAME :
2962                            if (localContentsOffset + 1 >= this.contents.length) {
2963                                resizeContents(1);
2964                            }
2965                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2966                            break;
2967                        case StackMapFrame.SAME_FRAME_EXTENDED :
2968                            if (localContentsOffset + 3 >= this.contents.length) {
2969                                resizeContents(3);
2970                            }
2971                            this.contents[localContentsOffset++] = (byte) 251;
2972                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2973                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2974                            break;
2975                        case StackMapFrame.CHOP_FRAME :
2976                            if (localContentsOffset + 3 >= this.contents.length) {
2977                                resizeContents(3);
2978                            }
2979                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
2980                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
2981                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2982                            this.contents[localContentsOffset++] = (byte) offsetDelta;
2983                            break;
2984                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
2985                            if (localContentsOffset + 4 >= this.contents.length) {
2986                                resizeContents(4);
2987                            }
2988                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
2989                            if (currentFrame.stackItems[0] == null) {
2990                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2991                            } else {
2992                                switch(currentFrame.stackItems[0].id()) {
2993                                    case T_boolean :
2994                                    case T_byte :
2995                                    case T_char :
2996                                    case T_int :
2997                                    case T_short :
2998                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2999                                        break;
3000                                    case T_float :
3001                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3002                                        break;
3003                                    case T_long :
3004                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3005                                        break;
3006                                    case T_double :
3007                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3008                                        break;
3009                                    case T_null :
3010                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3011                                        break;
3012                                    default:
3013                                        VerificationTypeInfo info = currentFrame.stackItems[0];
3014                                        this.contents[localContentsOffset++] = (byte) info.tag;
3015                                        switch (info.tag) {
3016                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
3017                                                int offset = info.offset;
3018                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
3019                                                this.contents[localContentsOffset++] = (byte) offset;
3020                                                break;
3021                                            case VerificationTypeInfo.ITEM_OBJECT :
3022                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3023                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3024                                                this.contents[localContentsOffset++] = (byte) indexForType;
3025                                        }
3026                                }
3027                            }
3028                            break;
3029                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
3030                            if (localContentsOffset + 6 >= this.contents.length) {
3031                                resizeContents(6);
3032                            }
3033                            this.contents[localContentsOffset++] = (byte) 247;
3034                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3035                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3036                            if (currentFrame.stackItems[0] == null) {
3037                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3038                            } else {
3039                                switch(currentFrame.stackItems[0].id()) {
3040                                    case T_boolean :
3041                                    case T_byte :
3042                                    case T_char :
3043                                    case T_int :
3044                                    case T_short :
3045                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3046                                        break;
3047                                    case T_float :
3048                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3049                                        break;
3050                                    case T_long :
3051                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3052                                        break;
3053                                    case T_double :
3054                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3055                                        break;
3056                                    case T_null :
3057                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3058                                        break;
3059                                    default:
3060                                        VerificationTypeInfo info = currentFrame.stackItems[0];
3061                                        this.contents[localContentsOffset++] = (byte) info.tag;
3062                                        switch (info.tag) {
3063                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
3064                                                int offset = info.offset;
3065                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
3066                                                this.contents[localContentsOffset++] = (byte) offset;
3067                                                break;
3068                                            case VerificationTypeInfo.ITEM_OBJECT :
3069                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3070                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3071                                                this.contents[localContentsOffset++] = (byte) indexForType;
3072                                        }
3073                                }
3074                            }
3075                            break;
3076                        default :
3077                            // FULL_FRAME
3078
if (localContentsOffset + 5 >= this.contents.length) {
3079                                resizeContents(5);
3080                            }
3081                            this.contents[localContentsOffset++] = (byte) 255;
3082                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3083                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3084                            int numberOfLocalOffset = localContentsOffset;
3085                            localContentsOffset += 2; // leave two spots for number of locals
3086
int numberOfLocalEntries = 0;
3087                            numberOfLocals = currentFrame.getNumberOfLocals();
3088                            int numberOfEntries = 0;
3089                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
3090                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
3091                                if (localContentsOffset + 3 >= this.contents.length) {
3092                                    resizeContents(3);
3093                                }
3094                                VerificationTypeInfo info = currentFrame.locals[i];
3095                                if (info == null) {
3096                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3097                                } else {
3098                                    switch(info.id()) {
3099                                        case T_boolean :
3100                                        case T_byte :
3101                                        case T_char :
3102                                        case T_int :
3103                                        case T_short :
3104                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3105                                            break;
3106                                        case T_float :
3107                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3108                                            break;
3109                                        case T_long :
3110                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3111                                            i++;
3112                                            break;
3113                                        case T_double :
3114                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3115                                            i++;
3116                                            break;
3117                                        case T_null :
3118                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3119                                            break;
3120                                        default:
3121                                            this.contents[localContentsOffset++] = (byte) info.tag;
3122                                            switch (info.tag) {
3123                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
3124                                                    int offset = info.offset;
3125                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
3126                                                    this.contents[localContentsOffset++] = (byte) offset;
3127                                                    break;
3128                                                case VerificationTypeInfo.ITEM_OBJECT :
3129                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3130                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3131                                                    this.contents[localContentsOffset++] = (byte) indexForType;
3132                                            }
3133                                    }
3134                                    numberOfLocalEntries++;
3135                                }
3136                                numberOfEntries++;
3137                            }
3138                            if (localContentsOffset + 4 >= this.contents.length) {
3139                                resizeContents(4);
3140                            }
3141                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3142                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
3143                            int numberOfStackItems = currentFrame.numberOfStackItems;
3144                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3145                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
3146                            for (int i = 0; i < numberOfStackItems; i++) {
3147                                if (localContentsOffset + 3 >= this.contents.length) {
3148                                    resizeContents(3);
3149                                }
3150                                VerificationTypeInfo info = currentFrame.stackItems[i];
3151                                if (info == null) {
3152                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3153                                } else {
3154                                    switch(info.id()) {
3155                                        case T_boolean :
3156                                        case T_byte :
3157                                        case T_char :
3158                                        case T_int :
3159                                        case T_short :
3160                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3161                                            break;
3162                                        case T_float :
3163                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3164                                            break;
3165                                        case T_long :
3166                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3167                                            break;
3168                                        case T_double :
3169                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3170                                            break;
3171                                        case T_null :
3172                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3173                                            break;
3174                                        default:
3175                                            this.contents[localContentsOffset++] = (byte) info.tag;
3176                                            switch (info.tag) {
3177                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
3178                                                    int offset = info.offset;
3179                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
3180                                                    this.contents[localContentsOffset++] = (byte) offset;
3181                                                    break;
3182                                                case VerificationTypeInfo.ITEM_OBJECT :
3183                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3184                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3185                                                    this.contents[localContentsOffset++] = (byte) indexForType;
3186                                            }
3187                                    }
3188                                }
3189                            }
3190                    }
3191                }
3192                
3193                this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3194                this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
3195
3196                int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
3197                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3198                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3199                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3200                this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
3201                attributeNumber++;
3202            }
3203        }
3204        
3205        // update the number of attributes
3206
// ensure first that there is enough space available inside the contents array
3207
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
3208            resizeContents(2);
3209        }
3210        this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
3211        this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
3212        // update the attribute length
3213
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
3214        this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
3215        this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
3216        this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
3217        this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
3218        contentsOffset = localContentsOffset;
3219    }
3220
3221    /**
3222     *
3223     */

3224    public void completeCodeAttributeForMissingAbstractProblemMethod(
3225        MethodBinding binding,
3226        int codeAttributeOffset,
3227        int[] startLineIndexes,
3228        int problemLine) {
3229        // reinitialize the localContents with the byte modified by the code stream
3230
this.contents = codeStream.bCodeStream;
3231        int localContentsOffset = codeStream.classFileOffset;
3232        // 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...
3233
int max_stack = codeStream.stackMax;
3234        this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
3235        this.contents[codeAttributeOffset + 7] = (byte) max_stack;
3236        int max_locals = codeStream.maxLocals;
3237        this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
3238        this.contents[codeAttributeOffset + 9] = (byte) max_locals;
3239        int code_length = codeStream.position;
3240        this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
3241        this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
3242        this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
3243        this.contents[codeAttributeOffset + 13] = (byte) code_length;
3244        // write the exception table
3245
if (localContentsOffset + 50 >= this.contents.length) {
3246            resizeContents(50);
3247        }
3248        this.contents[localContentsOffset++] = 0;
3249        this.contents[localContentsOffset++] = 0;
3250        // debug attributes
3251
int codeAttributeAttributeOffset = localContentsOffset;
3252        int attributeNumber = 0; // leave two bytes for the attribute_length
3253
localContentsOffset += 2; // first we handle the linenumber attribute
3254
if (localContentsOffset + 2 >= this.contents.length) {
3255            resizeContents(2);
3256        }
3257
3258        if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
3259            if (localContentsOffset + 12 >= this.contents.length) {
3260                resizeContents(12);
3261            }
3262            /* Create and add the line number attribute (used for debugging)
3263                * Build the pairs of:
3264                * (bytecodePC lineNumber)
3265                * according to the table of start line indexes and the pcToSourceMap table
3266                * contained into the codestream
3267                */

3268            int lineNumberNameIndex =
3269                constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
3270            this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
3271            this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
3272            this.contents[localContentsOffset++] = 0;
3273            this.contents[localContentsOffset++] = 0;
3274            this.contents[localContentsOffset++] = 0;
3275            this.contents[localContentsOffset++] = 6;
3276            this.contents[localContentsOffset++] = 0;
3277            this.contents[localContentsOffset++] = 1;
3278            if (problemLine == 0) {
3279                problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1);
3280            }
3281            // first entry at pc = 0
3282
this.contents[localContentsOffset++] = 0;
3283            this.contents[localContentsOffset++] = 0;
3284            this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
3285            this.contents[localContentsOffset++] = (byte) problemLine;
3286            // now we change the size of the line number attribute
3287
attributeNumber++;
3288        }
3289
3290        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
3291            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
3292            final int framesPositionsSize = framesPositions.size();
3293            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
3294
if (numberOfFrames > 0) {
3295                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
3296                framePositions.addAll(framesPositions);
3297                Collections.sort(framePositions);
3298                // add the stack map table attribute
3299
if (localContentsOffset + 8 >= this.contents.length) {
3300                    resizeContents(8);
3301                }
3302                int stackMapTableAttributeNameIndex =
3303                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
3304                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
3305                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
3306                
3307                int stackMapTableAttributeLengthOffset = localContentsOffset;
3308                // generate the attribute
3309
localContentsOffset += 4;
3310                numberOfFrames = 0;
3311                int numberOfFramesOffset = localContentsOffset;
3312                localContentsOffset += 2;
3313                // generate all frames
3314
ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
3315                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
3316                StackMapFrame prevFrame = null;
3317                int framesSize = frames.size();
3318                int frameIndex = 0;
3319                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
3320                    // select next frame
3321
prevFrame = currentFrame;
3322                    currentFrame = null;
3323                    for (; frameIndex < framesSize; frameIndex++) {
3324                        currentFrame = (StackMapFrame) frames.get(frameIndex);
3325                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
3326                            break;
3327                        }
3328                    }
3329                    if (currentFrame == null) break;
3330                    numberOfFrames++;
3331                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
3332                    switch (currentFrame.getFrameType(prevFrame)) {
3333                        case StackMapFrame.APPEND_FRAME :
3334                            if (localContentsOffset + 3 >= this.contents.length) {
3335                                resizeContents(3);
3336                            }
3337                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
3338                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
3339                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3340                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3341                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
3342                            int numberOfLocals = currentFrame.getNumberOfLocals();
3343                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
3344                                if (localContentsOffset + 6 >= this.contents.length) {
3345                                    resizeContents(6);
3346                                }
3347                                VerificationTypeInfo info = currentFrame.locals[i];
3348                                if (info == null) {
3349                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3350                                } else {
3351                                    switch(info.id()) {
3352                                        case T_boolean :
3353                                        case T_byte :
3354                                        case T_char :
3355                                        case T_int :
3356                                        case T_short :
3357                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3358                                            break;
3359                                        case T_float :
3360                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3361                                            break;
3362                                        case T_long :
3363                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3364                                            i++;
3365                                            break;
3366                                        case T_double :
3367                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3368                                            i++;
3369                                            break;
3370                                        case T_null :
3371                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3372                                            break;
3373                                        default:
3374                                            this.contents[localContentsOffset++] = (byte) info.tag;
3375                                            switch (info.tag) {
3376                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
3377                                                    int offset = info.offset;
3378                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
3379                                                    this.contents[localContentsOffset++] = (byte) offset;
3380                                                    break;
3381                                                case VerificationTypeInfo.ITEM_OBJECT :
3382                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3383                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3384                                                    this.contents[localContentsOffset++] = (byte) indexForType;
3385                                            }
3386                                    }
3387                                    numberOfDifferentLocals--;
3388                                }
3389                            }
3390                            break;
3391                        case StackMapFrame.SAME_FRAME :
3392                            if (localContentsOffset + 1 >= this.contents.length) {
3393                                resizeContents(1);
3394                            }
3395                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3396                            break;
3397                        case StackMapFrame.SAME_FRAME_EXTENDED :
3398                            if (localContentsOffset + 3 >= this.contents.length) {
3399                                resizeContents(3);
3400                            }
3401                            this.contents[localContentsOffset++] = (byte) 251;
3402                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3403                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3404                            break;
3405                        case StackMapFrame.CHOP_FRAME :
3406                            if (localContentsOffset + 3 >= this.contents.length) {
3407                                resizeContents(3);
3408                            }
3409                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
3410                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
3411                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3412                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3413                            break;
3414                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
3415                            if (localContentsOffset + 4 >= this.contents.length) {
3416                                resizeContents(4);
3417                            }
3418                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
3419                            if (currentFrame.stackItems[0] == null) {
3420                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3421                            } else {
3422                                switch(currentFrame.stackItems[0].id()) {
3423                                    case T_boolean :
3424                                    case T_byte :
3425                                    case T_char :
3426                                    case T_int :
3427                                    case T_short :
3428                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3429                                        break;
3430                                    case T_float :
3431                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3432                                        break;
3433                                    case T_long :
3434                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3435                                        break;
3436                                    case T_double :
3437                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3438                                        break;
3439                                    case T_null :
3440                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3441                                        break;
3442                                    default:
3443                                        VerificationTypeInfo info = currentFrame.stackItems[0];
3444                                        this.contents[localContentsOffset++] = (byte) info.tag;
3445                                        switch (info.tag) {
3446                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
3447                                                int offset = info.offset;
3448                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
3449                                                this.contents[localContentsOffset++] = (byte) offset;
3450                                                break;
3451                                            case VerificationTypeInfo.ITEM_OBJECT :
3452                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3453                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3454                                                this.contents[localContentsOffset++] = (byte) indexForType;
3455                                        }
3456                                }
3457                            }
3458                            break;
3459                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
3460                            if (localContentsOffset + 6 >= this.contents.length) {
3461                                resizeContents(6);
3462                            }
3463                            this.contents[localContentsOffset++] = (byte) 247;
3464                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3465                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3466                            if (currentFrame.stackItems[0] == null) {
3467                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3468                            } else {
3469                                switch(currentFrame.stackItems[0].id()) {
3470                                    case T_boolean :
3471                                    case T_byte :
3472                                    case T_char :
3473                                    case T_int :
3474                                    case T_short :
3475                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3476                                        break;
3477                                    case T_float :
3478                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3479                                        break;
3480                                    case T_long :
3481                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3482                                        break;
3483                                    case T_double :
3484                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3485                                        break;
3486                                    case T_null :
3487                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3488                                        break;
3489                                    default:
3490                                        VerificationTypeInfo info = currentFrame.stackItems[0];
3491                                        this.contents[localContentsOffset++] = (byte) info.tag;
3492                                        switch (info.tag) {
3493                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
3494                                                int offset = info.offset;
3495                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
3496                                                this.contents[localContentsOffset++] = (byte) offset;
3497                                                break;
3498                                            case VerificationTypeInfo.ITEM_OBJECT :
3499                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3500                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3501                                                this.contents[localContentsOffset++] = (byte) indexForType;
3502                                        }
3503                                }
3504                            }
3505                            break;
3506                        default :
3507                            // FULL_FRAME
3508
if (localContentsOffset + 5 >= this.contents.length) {
3509                                resizeContents(5);
3510                            }
3511                            this.contents[localContentsOffset++] = (byte) 255;
3512                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3513                            this.contents[localContentsOffset++] = (byte) offsetDelta;
3514                            int numberOfLocalOffset = localContentsOffset;
3515                            localContentsOffset += 2; // leave two spots for number of locals
3516
int numberOfLocalEntries = 0;
3517                            numberOfLocals = currentFrame.getNumberOfLocals();
3518                            int numberOfEntries = 0;
3519                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
3520                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
3521                                if (localContentsOffset + 3 >= this.contents.length) {
3522                                    resizeContents(3);
3523                                }
3524                                VerificationTypeInfo info = currentFrame.locals[i];
3525                                if (info == null) {
3526                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3527                                } else {
3528                                    switch(info.id()) {
3529                                        case T_boolean :
3530                                        case T_byte :
3531                                        case T_char :
3532                                        case T_int :
3533                                        case T_short :
3534                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3535                                            break;
3536                                        case T_float :
3537                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3538                                            break;
3539                                        case T_long :
3540                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3541                                            i++;
3542                                            break;
3543                                        case T_double :
3544                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3545                                            i++;
3546                                            break;
3547                                        case T_null :
3548                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3549                                            break;
3550                                        default:
3551                                            this.contents[localContentsOffset++] = (byte) info.tag;
3552                                            switch (info.tag) {
3553                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
3554                                                    int offset = info.offset;
3555                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
3556                                                    this.contents[localContentsOffset++] = (byte) offset;
3557                                                    break;
3558                                                case VerificationTypeInfo.ITEM_OBJECT :
3559                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3560                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3561                                                    this.contents[localContentsOffset++] = (byte) indexForType;
3562                                            }
3563                                    }
3564                                    numberOfLocalEntries++;
3565                                }
3566                                numberOfEntries++;
3567                            }
3568                            if (localContentsOffset + 4 >= this.contents.length) {
3569                                resizeContents(4);
3570                            }
3571                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3572                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
3573                            int numberOfStackItems = currentFrame.numberOfStackItems;
3574                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3575                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
3576                            for (int i = 0; i < numberOfStackItems; i++) {
3577                                if (localContentsOffset + 3 >= this.contents.length) {
3578                                    resizeContents(3);
3579                                }
3580                                VerificationTypeInfo info = currentFrame.stackItems[i];
3581                                if (info == null) {
3582                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3583                                } else {
3584                                    switch(info.id()) {
3585                                        case T_boolean :
3586                                        case T_byte :
3587                                        case T_char :
3588                                        case T_int :
3589                                        case T_short :
3590                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3591                                            break;
3592                                        case T_float :
3593                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3594                                            break;
3595                                        case T_long :
3596                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3597                                            break;
3598                                        case T_double :
3599                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3600                                            break;
3601                                        case T_null :
3602                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3603                                            break;
3604                                        default:
3605                                            this.contents[localContentsOffset++] = (byte) info.tag;
3606                                            switch (info.tag) {
3607                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
3608                                                    int offset = info.offset;
3609                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
3610                                                    this.contents[localContentsOffset++] = (byte) offset;
3611                                                    break;
3612                                                case VerificationTypeInfo.ITEM_OBJECT :
3613                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
3614                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
3615                                                    this.contents[localContentsOffset++] = (byte) indexForType;
3616                                            }
3617                                    }
3618                                }
3619                            }
3620                    }
3621                }
3622                
3623                this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3624                this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
3625
3626                int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
3627                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3628                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3629                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3630                this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
3631                attributeNumber++;
3632            }
3633        }
3634        
3635        // then we do the local variable attribute
3636
// update the number of attributes// ensure first that there is enough space available inside the localContents array
3637
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
3638            resizeContents(2);
3639        }
3640        this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
3641        this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
3642        // update the attribute length
3643
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
3644        this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
3645        this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
3646        this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
3647        this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
3648        contentsOffset = localContentsOffset;
3649    }
3650
3651    /**
3652     * INTERNAL USE-ONLY
3653     * That method completes the creation of the code attribute by setting
3654     * - the attribute_length
3655     * - max_stack
3656     * - max_locals
3657     * - code_length
3658     * - exception table
3659     * - and debug attributes if necessary.
3660     *
3661     * @param codeAttributeOffset <CODE>int</CODE>
3662     */

3663    public void completeCodeAttributeForProblemMethod(
3664        AbstractMethodDeclaration method,
3665        MethodBinding binding,
3666        int codeAttributeOffset,
3667        int[] startLineIndexes,
3668        int problemLine) {
3669        // reinitialize the localContents with the byte modified by the code stream
3670
this.contents = codeStream.bCodeStream;
3671        int localContentsOffset = codeStream.classFileOffset;
3672        // 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...
3673
int max_stack = codeStream.stackMax;
3674        this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
3675        this.contents[codeAttributeOffset + 7] = (byte) max_stack;
3676        int max_locals = codeStream.maxLocals;
3677        this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
3678        this.contents[codeAttributeOffset + 9] = (byte) max_locals;
3679        int code_length = codeStream.position;
3680        this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
3681        this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
3682        this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
3683        this.contents[codeAttributeOffset + 13] = (byte) code_length;
3684        // write the exception table
3685
if (localContentsOffset + 50 >= this.contents.length) {
3686            resizeContents(50);
3687        }
3688
3689        // write the exception table
3690
this.contents[localContentsOffset++] = 0;
3691        this.contents[localContentsOffset++] = 0;
3692        // debug attributes
3693
int codeAttributeAttributeOffset = localContentsOffset;
3694        int attributeNumber = 0; // leave two bytes for the attribute_length
3695
localContentsOffset += 2; // first we handle the linenumber attribute
3696
if (localContentsOffset + 2 >= this.contents.length) {
3697            resizeContents(2);
3698        }
3699
3700        if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
3701            if (localContentsOffset + 20 >= this.contents.length) {
3702                resizeContents(20);
3703            }
3704            /* Create and add the line number attribute (used for debugging)
3705                * Build the pairs of:
3706                * (bytecodePC lineNumber)
3707                * according to the table of start line indexes and the pcToSourceMap table
3708                * contained into the codestream
3709                */

3710            int lineNumberNameIndex =
3711                constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
3712            this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
3713            this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
3714            this.contents[localContentsOffset++] = 0;
3715            this.contents[localContentsOffset++] = 0;
3716            this.contents[localContentsOffset++] = 0;
3717            this.contents[localContentsOffset++] = 6;
3718            this.contents[localContentsOffset++] = 0;
3719            this.contents[localContentsOffset++] = 1;
3720            if (problemLine == 0) {
3721                problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1);
3722            }
3723            // first entry at pc = 0
3724
this.contents[localContentsOffset++] = 0;
3725            this.contents[localContentsOffset++] = 0;
3726            this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
3727            this.contents[localContentsOffset++] = (byte) problemLine;
3728            // now we change the size of the line number attribute
3729
attributeNumber++;
3730        }
3731        // then we do the local variable attribute
3732
if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
3733            // compute the resolved position for the arguments of the method
3734
int argSize;
3735            int numberOfEntries = 0;
3736            // codeAttribute.addLocalVariableTableAttribute(this);
3737
int localVariableNameIndex =
3738                constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
3739            if (localContentsOffset + 8 >= this.contents.length) {
3740                resizeContents(8);
3741            }
3742            this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
3743            this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
3744            int localVariableTableOffset = localContentsOffset;
3745            localContentsOffset += 6;
3746            // leave space for attribute_length and local_variable_table_length
3747
int descriptorIndex;
3748            int nameIndex;
3749            SourceTypeBinding declaringClassBinding = null;
3750            final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
3751            if (!methodDeclarationIsStatic) {
3752                numberOfEntries++;
3753                if (localContentsOffset + 10 >= this.contents.length) {
3754                    resizeContents(10);
3755                }
3756                this.contents[localContentsOffset++] = 0;
3757                this.contents[localContentsOffset++] = 0;
3758                this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3759                this.contents[localContentsOffset++] = (byte) code_length;
3760                nameIndex = constantPool.literalIndex(ConstantPool.This);
3761                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3762                this.contents[localContentsOffset++] = (byte) nameIndex;
3763                declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
3764                descriptorIndex =
3765                    constantPool.literalIndex(declaringClassBinding.signature());
3766                this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3767                this.contents[localContentsOffset++] = (byte) descriptorIndex;
3768                // the resolved position for this is always 0
3769
this.contents[localContentsOffset++] = 0;
3770                this.contents[localContentsOffset++] = 0;
3771            }
3772            // used to remember the local variable with a generic type
3773
int genericLocalVariablesCounter = 0;
3774            LocalVariableBinding[] genericLocalVariables = null;
3775            int numberOfGenericEntries = 0;
3776            
3777            if (binding.isConstructor()) {
3778                ReferenceBinding declaringClass = binding.declaringClass;
3779                if (declaringClass.isNestedType()) {
3780                    NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
3781                    argSize = methodDeclaringClass.enclosingInstancesSlotSize;
3782                    SyntheticArgumentBinding[] syntheticArguments;
3783                    if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
3784                        for (int i = 0, max = syntheticArguments.length; i < max; i++) {
3785                            LocalVariableBinding localVariable = syntheticArguments[i];
3786                            final TypeBinding localVariableTypeBinding = localVariable.type;
3787                            if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
3788                                if (genericLocalVariables == null) {
3789                                    // we cannot have more than max locals
3790
genericLocalVariables = new LocalVariableBinding[max];
3791                                }
3792                                genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
3793                                numberOfGenericEntries++;
3794                            }
3795                            if (localContentsOffset + 10 >= this.contents.length) {
3796                                resizeContents(10);
3797                            }
3798                            // now we can safely add the local entry
3799
numberOfEntries++;
3800                            this.contents[localContentsOffset++] = 0;
3801                            this.contents[localContentsOffset++] = 0;
3802                            this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3803                            this.contents[localContentsOffset++] = (byte) code_length;
3804                            nameIndex = constantPool.literalIndex(localVariable.name);
3805                            this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3806                            this.contents[localContentsOffset++] = (byte) nameIndex;
3807                            descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
3808                            this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3809                            this.contents[localContentsOffset++] = (byte) descriptorIndex;
3810                            int resolvedPosition = localVariable.resolvedPosition;
3811                            this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
3812                            this.contents[localContentsOffset++] = (byte) resolvedPosition;
3813                        }
3814                    }
3815                } else {
3816                    argSize = 1;
3817                }
3818            } else {
3819                argSize = binding.isStatic() ? 0 : 1;
3820            }
3821            
3822            int genericArgumentsCounter = 0;
3823            int[] genericArgumentsNameIndexes = null;
3824            int[] genericArgumentsResolvedPositions = null;
3825            TypeBinding[] genericArgumentsTypeBindings = null;
3826
3827            if (method.binding != null) {
3828                TypeBinding[] parameters = method.binding.parameters;
3829                Argument[] arguments = method.arguments;
3830                if ((parameters != null) && (arguments != null)) {
3831                    for (int i = 0, max = parameters.length; i < max; i++) {
3832                        TypeBinding argumentBinding = parameters[i];
3833                        if (localContentsOffset + 10 >= this.contents.length) {
3834                            resizeContents(10);
3835                        }
3836                        // now we can safely add the local entry
3837
numberOfEntries++;
3838                        this.contents[localContentsOffset++] = 0;
3839                        this.contents[localContentsOffset++] = 0;
3840                        this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3841                        this.contents[localContentsOffset++] = (byte) code_length;
3842                        nameIndex = constantPool.literalIndex(arguments[i].name);
3843                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3844                        this.contents[localContentsOffset++] = (byte) nameIndex;
3845                        int resolvedPosition = argSize;
3846                        if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
3847                            if (genericArgumentsCounter == 0) {
3848                                // we cannot have more than max locals
3849
genericArgumentsNameIndexes = new int[max];
3850                                genericArgumentsResolvedPositions = new int[max];
3851                                genericArgumentsTypeBindings = new TypeBinding[max];
3852                            }
3853                            genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
3854                            genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
3855                            genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
3856                        }
3857                        descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
3858                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3859                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
3860                        if ((argumentBinding == TypeBinding.LONG)
3861                            || (argumentBinding == TypeBinding.DOUBLE))
3862                            argSize += 2;
3863                        else
3864                            argSize++;
3865                        this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
3866                        this.contents[localContentsOffset++] = (byte) resolvedPosition;
3867                    }
3868                }
3869            }
3870            int value = numberOfEntries * 10 + 2;
3871            this.contents[localVariableTableOffset++] = (byte) (value >> 24);
3872            this.contents[localVariableTableOffset++] = (byte) (value >> 16);
3873            this.contents[localVariableTableOffset++] = (byte) (value >> 8);
3874            this.contents[localVariableTableOffset++] = (byte) value;
3875            this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
3876            this.contents[localVariableTableOffset] = (byte) numberOfEntries;
3877            attributeNumber++;
3878            
3879            final boolean currentInstanceIsGeneric =
3880                !methodDeclarationIsStatic
3881                && declaringClassBinding != null
3882                && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
3883            if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
3884                // add the local variable type table attribute
3885
numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
3886                // reserve enough space
3887
int maxOfEntries = 8 + numberOfEntries * 10;
3888                if (localContentsOffset + maxOfEntries >= this.contents.length) {
3889                    resizeContents(maxOfEntries);
3890                }
3891                int localVariableTypeNameIndex =
3892                    constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
3893                this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
3894                this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
3895                value = numberOfEntries * 10 + 2;
3896                this.contents[localContentsOffset++] = (byte) (value >> 24);
3897                this.contents[localContentsOffset++] = (byte) (value >> 16);
3898                this.contents[localContentsOffset++] = (byte) (value >> 8);
3899                this.contents[localContentsOffset++] = (byte) value;
3900                this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
3901                this.contents[localContentsOffset++] = (byte) numberOfEntries;
3902                if (currentInstanceIsGeneric) {
3903                    numberOfEntries++;
3904                    this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
3905
this.contents[localContentsOffset++] = 0;
3906                    this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3907                    this.contents[localContentsOffset++] = (byte) code_length;
3908                    nameIndex = constantPool.literalIndex(ConstantPool.This);
3909                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3910                    this.contents[localContentsOffset++] = (byte) nameIndex;
3911                    descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
3912                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3913                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
3914                    this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
3915
this.contents[localContentsOffset++] = 0;
3916                }
3917                
3918                for (int i = 0; i < genericLocalVariablesCounter; i++) {
3919                    LocalVariableBinding localVariable = genericLocalVariables[i];
3920                    this.contents[localContentsOffset++] = 0;
3921                    this.contents[localContentsOffset++] = 0;
3922                    this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3923                    this.contents[localContentsOffset++] = (byte) code_length;
3924                    nameIndex = constantPool.literalIndex(localVariable.name);
3925                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3926                    this.contents[localContentsOffset++] = (byte) nameIndex;
3927                    descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
3928                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3929                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
3930                    int resolvedPosition = localVariable.resolvedPosition;
3931                    this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
3932                    this.contents[localContentsOffset++] = (byte) resolvedPosition;
3933                }
3934                for (int i = 0; i < genericArgumentsCounter; i++) {
3935                    this.contents[localContentsOffset++] = 0;
3936                    this.contents[localContentsOffset++] = 0;
3937                    this.contents[localContentsOffset++] = (byte) (code_length >> 8);
3938                    this.contents[localContentsOffset++] = (byte) code_length;
3939                    nameIndex = genericArgumentsNameIndexes[i];
3940                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
3941                    this.contents[localContentsOffset++] = (byte) nameIndex;
3942                    descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
3943                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
3944                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
3945                    int resolvedPosition = genericArgumentsResolvedPositions[i];
3946                    this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
3947                    this.contents[localContentsOffset++] = (byte) resolvedPosition;
3948                }
3949                attributeNumber++;
3950            }
3951        }
3952        
3953        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
3954            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
3955            final int framesPositionsSize = framesPositions.size();
3956            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
3957
if (numberOfFrames > 0) {
3958                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
3959                framePositions.addAll(framesPositions);
3960                Collections.sort(framePositions);
3961                // add the stack map table attribute
3962
if (localContentsOffset + 8 >= this.contents.length) {
3963                    resizeContents(8);
3964                }
3965                int stackMapTableAttributeNameIndex =
3966                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
3967                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
3968                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
3969                
3970                int stackMapTableAttributeLengthOffset = localContentsOffset;
3971                // generate the attribute
3972
localContentsOffset += 4;
3973                numberOfFrames = 0;
3974                int numberOfFramesOffset = localContentsOffset;
3975                localContentsOffset += 2;
3976                // generate all frames
3977
ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
3978                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
3979                StackMapFrame prevFrame = null;
3980                int framesSize = frames.size();
3981                int frameIndex = 0;
3982                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
3983                    // select next frame
3984
prevFrame = currentFrame;
3985                    currentFrame = null;
3986                    for (; frameIndex < framesSize; frameIndex++) {
3987                        currentFrame = (StackMapFrame) frames.get(frameIndex);
3988                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
3989                            break;
3990                        }
3991                    }
3992                    if (currentFrame == null) break;
3993                    numberOfFrames++;
3994                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
3995                    switch (currentFrame.getFrameType(prevFrame)) {
3996                        case StackMapFrame.APPEND_FRAME :
3997                            if (localContentsOffset + 3 >= this.contents.length) {
3998                                resizeContents(3);
3999                            }
4000                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
4001                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
4002                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4003                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4004                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
4005                            int numberOfLocals = currentFrame.getNumberOfLocals();
4006                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
4007                                if (localContentsOffset + 6 >= this.contents.length) {
4008                                    resizeContents(6);
4009                                }
4010                                VerificationTypeInfo info = currentFrame.locals[i];
4011                                if (info == null) {
4012                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4013                                } else {
4014                                    switch(info.id()) {
4015                                        case T_boolean :
4016                                        case T_byte :
4017                                        case T_char :
4018                                        case T_int :
4019                                        case T_short :
4020                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4021                                            break;
4022                                        case T_float :
4023                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4024                                            break;
4025                                        case T_long :
4026                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4027                                            i++;
4028                                            break;
4029                                        case T_double :
4030                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4031                                            i++;
4032                                            break;
4033                                        case T_null :
4034                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4035                                            break;
4036                                        default:
4037                                            this.contents[localContentsOffset++] = (byte) info.tag;
4038                                            switch (info.tag) {
4039                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4040                                                    int offset = info.offset;
4041                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4042                                                    this.contents[localContentsOffset++] = (byte) offset;
4043                                                    break;
4044                                                case VerificationTypeInfo.ITEM_OBJECT :
4045                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4046                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4047                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4048                                            }
4049                                    }
4050                                    numberOfDifferentLocals--;
4051                                }
4052                            }
4053                            break;
4054                        case StackMapFrame.SAME_FRAME :
4055                            if (localContentsOffset + 1 >= this.contents.length) {
4056                                resizeContents(1);
4057                            }
4058                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4059                            break;
4060                        case StackMapFrame.SAME_FRAME_EXTENDED :
4061                            if (localContentsOffset + 3 >= this.contents.length) {
4062                                resizeContents(3);
4063                            }
4064                            this.contents[localContentsOffset++] = (byte) 251;
4065                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4066                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4067                            break;
4068                        case StackMapFrame.CHOP_FRAME :
4069                            if (localContentsOffset + 3 >= this.contents.length) {
4070                                resizeContents(3);
4071                            }
4072                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
4073                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
4074                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4075                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4076                            break;
4077                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
4078                            if (localContentsOffset + 4 >= this.contents.length) {
4079                                resizeContents(4);
4080                            }
4081                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
4082                            if (currentFrame.stackItems[0] == null) {
4083                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4084                            } else {
4085                                switch(currentFrame.stackItems[0].id()) {
4086                                    case T_boolean :
4087                                    case T_byte :
4088                                    case T_char :
4089                                    case T_int :
4090                                    case T_short :
4091                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4092                                        break;
4093                                    case T_float :
4094                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4095                                        break;
4096                                    case T_long :
4097                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4098                                        break;
4099                                    case T_double :
4100                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4101                                        break;
4102                                    case T_null :
4103                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4104                                        break;
4105                                    default:
4106                                        VerificationTypeInfo info = currentFrame.stackItems[0];
4107                                        this.contents[localContentsOffset++] = (byte) info.tag;
4108                                        switch (info.tag) {
4109                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
4110                                                int offset = info.offset;
4111                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
4112                                                this.contents[localContentsOffset++] = (byte) offset;
4113                                                break;
4114                                            case VerificationTypeInfo.ITEM_OBJECT :
4115                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4116                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4117                                                this.contents[localContentsOffset++] = (byte) indexForType;
4118                                        }
4119                                }
4120                            }
4121                            break;
4122                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
4123                            if (localContentsOffset + 6 >= this.contents.length) {
4124                                resizeContents(6);
4125                            }
4126                            this.contents[localContentsOffset++] = (byte) 247;
4127                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4128                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4129                            if (currentFrame.stackItems[0] == null) {
4130                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4131                            } else {
4132                                switch(currentFrame.stackItems[0].id()) {
4133                                    case T_boolean :
4134                                    case T_byte :
4135                                    case T_char :
4136                                    case T_int :
4137                                    case T_short :
4138                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4139                                        break;
4140                                    case T_float :
4141                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4142                                        break;
4143                                    case T_long :
4144                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4145                                        break;
4146                                    case T_double :
4147                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4148                                        break;
4149                                    case T_null :
4150                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4151                                        break;
4152                                    default:
4153                                        VerificationTypeInfo info = currentFrame.stackItems[0];
4154                                        this.contents[localContentsOffset++] = (byte) info.tag;
4155                                        switch (info.tag) {
4156                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
4157                                                int offset = info.offset;
4158                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
4159                                                this.contents[localContentsOffset++] = (byte) offset;
4160                                                break;
4161                                            case VerificationTypeInfo.ITEM_OBJECT :
4162                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4163                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4164                                                this.contents[localContentsOffset++] = (byte) indexForType;
4165                                        }
4166                                }
4167                            }
4168                            break;
4169                        default :
4170                            // FULL_FRAME
4171
if (localContentsOffset + 5 >= this.contents.length) {
4172                                resizeContents(5);
4173                            }
4174                            this.contents[localContentsOffset++] = (byte) 255;
4175                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4176                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4177                            int numberOfLocalOffset = localContentsOffset;
4178                            localContentsOffset += 2; // leave two spots for number of locals
4179
int numberOfLocalEntries = 0;
4180                            numberOfLocals = currentFrame.getNumberOfLocals();
4181                            int numberOfEntries = 0;
4182                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
4183                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
4184                                if (localContentsOffset + 3 >= this.contents.length) {
4185                                    resizeContents(3);
4186                                }
4187                                VerificationTypeInfo info = currentFrame.locals[i];
4188                                if (info == null) {
4189                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4190                                } else {
4191                                    switch(info.id()) {
4192                                        case T_boolean :
4193                                        case T_byte :
4194                                        case T_char :
4195                                        case T_int :
4196                                        case T_short :
4197                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4198                                            break;
4199                                        case T_float :
4200                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4201                                            break;
4202                                        case T_long :
4203                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4204                                            i++;
4205                                            break;
4206                                        case T_double :
4207                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4208                                            i++;
4209                                            break;
4210                                        case T_null :
4211                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4212                                            break;
4213                                        default:
4214                                            this.contents[localContentsOffset++] = (byte) info.tag;
4215                                            switch (info.tag) {
4216                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4217                                                    int offset = info.offset;
4218                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4219                                                    this.contents[localContentsOffset++] = (byte) offset;
4220                                                    break;
4221                                                case VerificationTypeInfo.ITEM_OBJECT :
4222                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4223                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4224                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4225                                            }
4226                                    }
4227                                    numberOfLocalEntries++;
4228                                }
4229                                numberOfEntries++;
4230                            }
4231                            if (localContentsOffset + 4 >= this.contents.length) {
4232                                resizeContents(4);
4233                            }
4234                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
4235                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
4236                            int numberOfStackItems = currentFrame.numberOfStackItems;
4237                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
4238                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
4239                            for (int i = 0; i < numberOfStackItems; i++) {
4240                                if (localContentsOffset + 3 >= this.contents.length) {
4241                                    resizeContents(3);
4242                                }
4243                                VerificationTypeInfo info = currentFrame.stackItems[i];
4244                                if (info == null) {
4245                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4246                                } else {
4247                                    switch(info.id()) {
4248                                        case T_boolean :
4249                                        case T_byte :
4250                                        case T_char :
4251                                        case T_int :
4252                                        case T_short :
4253                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4254                                            break;
4255                                        case T_float :
4256                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4257                                            break;
4258                                        case T_long :
4259                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4260                                            break;
4261                                        case T_double :
4262                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4263                                            break;
4264                                        case T_null :
4265                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4266                                            break;
4267                                        default:
4268                                            this.contents[localContentsOffset++] = (byte) info.tag;
4269                                            switch (info.tag) {
4270                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4271                                                    int offset = info.offset;
4272                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4273                                                    this.contents[localContentsOffset++] = (byte) offset;
4274                                                    break;
4275                                                case VerificationTypeInfo.ITEM_OBJECT :
4276                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4277                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4278                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4279                                            }
4280                                    }
4281                                }
4282                            }
4283                    }
4284                }
4285                
4286                this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
4287                this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
4288
4289                int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
4290                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
4291                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
4292                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
4293                this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
4294                attributeNumber++;
4295            }
4296        }
4297        
4298        // update the number of attributes// ensure first that there is enough space available inside the localContents array
4299
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
4300            resizeContents(2);
4301        }
4302        this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
4303        this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
4304        // update the attribute length
4305
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
4306        this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
4307        this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
4308        this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
4309        this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
4310        contentsOffset = localContentsOffset;
4311    }
4312
4313    /**
4314     * INTERNAL USE-ONLY
4315     * That method completes the creation of the code attribute by setting
4316     * - the attribute_length
4317     * - max_stack
4318     * - max_locals
4319     * - code_length
4320     * - exception table
4321     * - and debug attributes if necessary.
4322     *
4323     * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
4324     * @param codeAttributeOffset <CODE>int</CODE>
4325     */

4326    public void completeCodeAttributeForSyntheticMethod(
4327        boolean hasExceptionHandlers,
4328        SyntheticMethodBinding binding,
4329        int codeAttributeOffset,
4330        int[] startLineIndexes) {
4331        // reinitialize the contents with the byte modified by the code stream
4332
this.contents = codeStream.bCodeStream;
4333        int localContentsOffset = codeStream.classFileOffset;
4334        // codeAttributeOffset is the position inside contents byte array before we started to write
4335
// any information about the codeAttribute
4336
// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
4337
// to get the right position, 6 for the max_stack etc...
4338
int max_stack = codeStream.stackMax;
4339        contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
4340        contents[codeAttributeOffset + 7] = (byte) max_stack;
4341        int max_locals = codeStream.maxLocals;
4342        contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
4343        contents[codeAttributeOffset + 9] = (byte) max_locals;
4344        int code_length = codeStream.position;
4345        contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
4346        contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
4347        contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
4348        contents[codeAttributeOffset + 13] = (byte) code_length;
4349        if ((localContentsOffset + 40) >= this.contents.length) {
4350            resizeContents(40);
4351        }
4352        
4353        if (hasExceptionHandlers) {
4354            // write the exception table
4355
ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
4356            int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
4357
for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
4358                exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
4359            }
4360            int exSize = exceptionHandlersCount * 8 + 2;
4361            if (exSize + localContentsOffset >= this.contents.length) {
4362                resizeContents(exSize);
4363            }
4364            // there is no exception table, so we need to offset by 2 the current offset and move
4365
// on the attribute generation
4366
this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
4367            this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
4368            for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
4369                ExceptionLabel exceptionLabel = exceptionLabels[i];
4370                if (exceptionLabel != null) {
4371                    int iRange = 0, maxRange = exceptionLabel.count;
4372                    if ((maxRange & 1) != 0) {
4373                        referenceBinding.scope.problemReporter().abortDueToInternalError(
4374                                Messages.bind(Messages.abort_invalidExceptionAttribute, new String JavaDoc(binding.selector),
4375                                        referenceBinding.scope.problemReporter().referenceContext));
4376                    }
4377                    while (iRange < maxRange) {
4378                        int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
4379
this.contents[localContentsOffset++] = (byte) (start >> 8);
4380                        this.contents[localContentsOffset++] = (byte) start;
4381                        int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
4382
this.contents[localContentsOffset++] = (byte) (end >> 8);
4383                        this.contents[localContentsOffset++] = (byte) end;
4384                        int handlerPC = exceptionLabel.position;
4385                        this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
4386                        this.contents[localContentsOffset++] = (byte) handlerPC;
4387                        if (exceptionLabel.exceptionType == null) {
4388                            // any exception handler
4389
this.contents[localContentsOffset++] = 0;
4390                            this.contents[localContentsOffset++] = 0;
4391                        } else {
4392                            int nameIndex;
4393                            switch(exceptionLabel.exceptionType.id) {
4394                                case T_null :
4395                                    /* represents ClassNotFoundException, see class literal access*/
4396                                    nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
4397                                    break;
4398                                case T_long :
4399                                    /* represents NoSuchFieldError, see switch table generation*/
4400                                    nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName);
4401                                    break;
4402                                default:
4403                                    nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType);
4404                            }
4405                            this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4406                            this.contents[localContentsOffset++] = (byte) nameIndex;
4407                        }
4408                    }
4409                }
4410            }
4411        } else {
4412            // there is no exception table, so we need to offset by 2 the current offset and move
4413
// on the attribute generation
4414
contents[localContentsOffset++] = 0;
4415            contents[localContentsOffset++] = 0;
4416        }
4417        // debug attributes
4418
int codeAttributeAttributeOffset = localContentsOffset;
4419        int attributeNumber = 0;
4420        // leave two bytes for the attribute_length
4421
localContentsOffset += 2;
4422        if (localContentsOffset + 2 >= this.contents.length) {
4423            resizeContents(2);
4424        }
4425
4426        // first we handle the linenumber attribute
4427
if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
4428            if (localContentsOffset + 12 >= this.contents.length) {
4429                resizeContents(12);
4430            }
4431            int index = 0;
4432            int lineNumberNameIndex =
4433                constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
4434            contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
4435            contents[localContentsOffset++] = (byte) lineNumberNameIndex;
4436            int lineNumberTableOffset = localContentsOffset;
4437            localContentsOffset += 6;
4438            // leave space for attribute_length and line_number_table_length
4439
// Seems like do would be better, but this preserves the existing behavior.
4440
index = Util.getLineNumber(binding.sourceStart, startLineIndexes, 0, startLineIndexes.length-1);
4441            contents[localContentsOffset++] = 0;
4442            contents[localContentsOffset++] = 0;
4443            contents[localContentsOffset++] = (byte) (index >> 8);
4444            contents[localContentsOffset++] = (byte) index;
4445            // now we change the size of the line number attribute
4446
contents[lineNumberTableOffset++] = 0;
4447            contents[lineNumberTableOffset++] = 0;
4448            contents[lineNumberTableOffset++] = 0;
4449            contents[lineNumberTableOffset++] = 6;
4450            contents[lineNumberTableOffset++] = 0;
4451            contents[lineNumberTableOffset++] = 1;
4452            attributeNumber++;
4453        }
4454        // then we do the local variable attribute
4455
if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
4456            int numberOfEntries = 0;
4457            int localVariableNameIndex =
4458                constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
4459            if (localContentsOffset + 8 > this.contents.length) {
4460                resizeContents(8);
4461            }
4462            contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
4463            contents[localContentsOffset++] = (byte) localVariableNameIndex;
4464            int localVariableTableOffset = localContentsOffset;
4465            localContentsOffset += 6;
4466            // leave space for attribute_length and local_variable_table_length
4467
int nameIndex;
4468            int descriptorIndex;
4469
4470            // used to remember the local variable with a generic type
4471
int genericLocalVariablesCounter = 0;
4472            LocalVariableBinding[] genericLocalVariables = null;
4473            int numberOfGenericEntries = 0;
4474            
4475            for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
4476                LocalVariableBinding localVariable = codeStream.locals[i];
4477                final TypeBinding localVariableTypeBinding = localVariable.type;
4478                boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
4479                if (localVariable.initializationCount != 0 && isParameterizedType) {
4480                    if (genericLocalVariables == null) {
4481                        // we cannot have more than max locals
4482
genericLocalVariables = new LocalVariableBinding[max];
4483                    }
4484                    genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
4485                }
4486                for (int j = 0; j < localVariable.initializationCount; j++) {
4487                    int startPC = localVariable.initializationPCs[j << 1];
4488                    int endPC = localVariable.initializationPCs[(j << 1) + 1];
4489                    if (startPC != endPC) { // only entries for non zero length
4490
if (endPC == -1) {
4491                            localVariable.declaringScope.problemReporter().abortDueToInternalError(
4492                                Messages.bind(Messages.abort_invalidAttribute, new String JavaDoc(localVariable.name)),
4493                                (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
4494                        }
4495                        if (localContentsOffset + 10 > this.contents.length) {
4496                            resizeContents(10);
4497                        }
4498                        // now we can safely add the local entry
4499
numberOfEntries++;
4500                        if (isParameterizedType) {
4501                            numberOfGenericEntries++;
4502                        }
4503                        contents[localContentsOffset++] = (byte) (startPC >> 8);
4504                        contents[localContentsOffset++] = (byte) startPC;
4505                        int length = endPC - startPC;
4506                        contents[localContentsOffset++] = (byte) (length >> 8);
4507                        contents[localContentsOffset++] = (byte) length;
4508                        nameIndex = constantPool.literalIndex(localVariable.name);
4509                        contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4510                        contents[localContentsOffset++] = (byte) nameIndex;
4511                        descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
4512                        contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4513                        contents[localContentsOffset++] = (byte) descriptorIndex;
4514                        int resolvedPosition = localVariable.resolvedPosition;
4515                        contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4516                        contents[localContentsOffset++] = (byte) resolvedPosition;
4517                    }
4518                }
4519            }
4520            int value = numberOfEntries * 10 + 2;
4521            contents[localVariableTableOffset++] = (byte) (value >> 24);
4522            contents[localVariableTableOffset++] = (byte) (value >> 16);
4523            contents[localVariableTableOffset++] = (byte) (value >> 8);
4524            contents[localVariableTableOffset++] = (byte) value;
4525            contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
4526            contents[localVariableTableOffset] = (byte) numberOfEntries;
4527            attributeNumber++;
4528
4529            if (genericLocalVariablesCounter != 0) {
4530                // add the local variable type table attribute
4531
int maxOfEntries = 8 + numberOfGenericEntries * 10;
4532                // reserve enough space
4533
if (localContentsOffset + maxOfEntries >= this.contents.length) {
4534                    resizeContents(maxOfEntries);
4535                }
4536                int localVariableTypeNameIndex =
4537                    constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
4538                contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
4539                contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
4540                value = numberOfGenericEntries * 10 + 2;
4541                contents[localContentsOffset++] = (byte) (value >> 24);
4542                contents[localContentsOffset++] = (byte) (value >> 16);
4543                contents[localContentsOffset++] = (byte) (value >> 8);
4544                contents[localContentsOffset++] = (byte) value;
4545                contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
4546                contents[localContentsOffset++] = (byte) numberOfGenericEntries;
4547
4548                for (int i = 0; i < genericLocalVariablesCounter; i++) {
4549                    LocalVariableBinding localVariable = genericLocalVariables[i];
4550                    for (int j = 0; j < localVariable.initializationCount; j++) {
4551                        int startPC = localVariable.initializationPCs[j << 1];
4552                        int endPC = localVariable.initializationPCs[(j << 1) + 1];
4553                        if (startPC != endPC) { // only entries for non zero length
4554
// now we can safely add the local entry
4555
contents[localContentsOffset++] = (byte) (startPC >> 8);
4556                            contents[localContentsOffset++] = (byte) startPC;
4557                            int length = endPC - startPC;
4558                            contents[localContentsOffset++] = (byte) (length >> 8);
4559                            contents[localContentsOffset++] = (byte) length;
4560                            nameIndex = constantPool.literalIndex(localVariable.name);
4561                            contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4562                            contents[localContentsOffset++] = (byte) nameIndex;
4563                            descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
4564                            contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4565                            contents[localContentsOffset++] = (byte) descriptorIndex;
4566                            int resolvedPosition = localVariable.resolvedPosition;
4567                            contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4568                            contents[localContentsOffset++] = (byte) resolvedPosition;
4569                        }
4570                    }
4571                }
4572                attributeNumber++;
4573            }
4574        }
4575        
4576        if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
4577            final Set JavaDoc framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
4578            final int framesPositionsSize = framesPositions.size();
4579            int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
4580
if (numberOfFrames > 0) {
4581                ArrayList JavaDoc framePositions = new ArrayList JavaDoc(framesPositionsSize);
4582                framePositions.addAll(framesPositions);
4583                Collections.sort(framePositions);
4584                // add the stack map table attribute
4585
if (localContentsOffset + 8 >= this.contents.length) {
4586                    resizeContents(8);
4587                }
4588                int stackMapTableAttributeNameIndex =
4589                    constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
4590                this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
4591                this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
4592                
4593                int stackMapTableAttributeLengthOffset = localContentsOffset;
4594                // generate the attribute
4595
localContentsOffset += 4;
4596                numberOfFrames = 0;
4597                int numberOfFramesOffset = localContentsOffset;
4598                localContentsOffset += 2;
4599                // generate all frames
4600
ArrayList JavaDoc frames = ((StackMapFrameCodeStream) codeStream).frames;
4601                StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
4602                StackMapFrame prevFrame = null;
4603                int framesSize = frames.size();
4604                int frameIndex = 0;
4605                for (int j = 0; j < framesPositionsSize && ((Integer JavaDoc) framePositions.get(j)).intValue() < code_length; j++) {
4606                    // select next frame
4607
prevFrame = currentFrame;
4608                    currentFrame = null;
4609                    for (; frameIndex < framesSize; frameIndex++) {
4610                        currentFrame = (StackMapFrame) frames.get(frameIndex);
4611                        if (currentFrame.pc == ((Integer JavaDoc) framePositions.get(j)).intValue()) {
4612                            break;
4613                        }
4614                    }
4615                    if (currentFrame == null) break;
4616                    numberOfFrames++;
4617                    int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
4618                    switch (currentFrame.getFrameType(prevFrame)) {
4619                        case StackMapFrame.APPEND_FRAME :
4620                            if (localContentsOffset + 3 >= this.contents.length) {
4621                                resizeContents(3);
4622                            }
4623                            int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
4624                            this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
4625                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4626                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4627                            int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
4628                            int numberOfLocals = currentFrame.getNumberOfLocals();
4629                            for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
4630                                if (localContentsOffset + 6 >= this.contents.length) {
4631                                    resizeContents(6);
4632                                }
4633                                VerificationTypeInfo info = currentFrame.locals[i];
4634                                if (info == null) {
4635                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4636                                } else {
4637                                    switch(info.id()) {
4638                                        case T_boolean :
4639                                        case T_byte :
4640                                        case T_char :
4641                                        case T_int :
4642                                        case T_short :
4643                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4644                                            break;
4645                                        case T_float :
4646                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4647                                            break;
4648                                        case T_long :
4649                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4650                                            i++;
4651                                            break;
4652                                        case T_double :
4653                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4654                                            i++;
4655                                            break;
4656                                        case T_null :
4657                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4658                                            break;
4659                                        default:
4660                                            this.contents[localContentsOffset++] = (byte) info.tag;
4661                                            switch (info.tag) {
4662                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4663                                                    int offset = info.offset;
4664                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4665                                                    this.contents[localContentsOffset++] = (byte) offset;
4666                                                    break;
4667                                                case VerificationTypeInfo.ITEM_OBJECT :
4668                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4669                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4670                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4671                                            }
4672                                    }
4673                                    numberOfDifferentLocals--;
4674                                }
4675                            }
4676                            break;
4677                        case StackMapFrame.SAME_FRAME :
4678                            if (localContentsOffset + 1 >= this.contents.length) {
4679                                resizeContents(1);
4680                            }
4681                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4682                            break;
4683                        case StackMapFrame.SAME_FRAME_EXTENDED :
4684                            if (localContentsOffset + 3 >= this.contents.length) {
4685                                resizeContents(3);
4686                            }
4687                            this.contents[localContentsOffset++] = (byte) 251;
4688                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4689                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4690                            break;
4691                        case StackMapFrame.CHOP_FRAME :
4692                            if (localContentsOffset + 3 >= this.contents.length) {
4693                                resizeContents(3);
4694                            }
4695                            numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
4696                            this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
4697                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4698                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4699                            break;
4700                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
4701                            if (localContentsOffset + 4 >= this.contents.length) {
4702                                resizeContents(4);
4703                            }
4704                            this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
4705                            if (currentFrame.stackItems[0] == null) {
4706                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4707                            } else {
4708                                switch(currentFrame.stackItems[0].id()) {
4709                                    case T_boolean :
4710                                    case T_byte :
4711                                    case T_char :
4712                                    case T_int :
4713                                    case T_short :
4714                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4715                                        break;
4716                                    case T_float :
4717                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4718                                        break;
4719                                    case T_long :
4720                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4721                                        break;
4722                                    case T_double :
4723                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4724                                        break;
4725                                    case T_null :
4726                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4727                                        break;
4728                                    default:
4729                                        VerificationTypeInfo info = currentFrame.stackItems[0];
4730                                        this.contents[localContentsOffset++] = (byte) info.tag;
4731                                        switch (info.tag) {
4732                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
4733                                                int offset = info.offset;
4734                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
4735                                                this.contents[localContentsOffset++] = (byte) offset;
4736                                                break;
4737                                            case VerificationTypeInfo.ITEM_OBJECT :
4738                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4739                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4740                                                this.contents[localContentsOffset++] = (byte) indexForType;
4741                                        }
4742                                }
4743                            }
4744                            break;
4745                        case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
4746                            if (localContentsOffset + 6 >= this.contents.length) {
4747                                resizeContents(6);
4748                            }
4749                            this.contents[localContentsOffset++] = (byte) 247;
4750                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4751                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4752                            if (currentFrame.stackItems[0] == null) {
4753                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4754                            } else {
4755                                switch(currentFrame.stackItems[0].id()) {
4756                                    case T_boolean :
4757                                    case T_byte :
4758                                    case T_char :
4759                                    case T_int :
4760                                    case T_short :
4761                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4762                                        break;
4763                                    case T_float :
4764                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4765                                        break;
4766                                    case T_long :
4767                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4768                                        break;
4769                                    case T_double :
4770                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4771                                        break;
4772                                    case T_null :
4773                                        this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4774                                        break;
4775                                    default:
4776                                        VerificationTypeInfo info = currentFrame.stackItems[0];
4777                                        this.contents[localContentsOffset++] = (byte) info.tag;
4778                                        switch (info.tag) {
4779                                            case VerificationTypeInfo.ITEM_UNINITIALIZED :
4780                                                int offset = info.offset;
4781                                                this.contents[localContentsOffset++] = (byte) (offset >> 8);
4782                                                this.contents[localContentsOffset++] = (byte) offset;
4783                                                break;
4784                                            case VerificationTypeInfo.ITEM_OBJECT :
4785                                                int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4786                                                this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4787                                                this.contents[localContentsOffset++] = (byte) indexForType;
4788                                        }
4789                                }
4790                            }
4791                            break;
4792                        default :
4793                            // FULL_FRAME
4794
if (localContentsOffset + 5 >= this.contents.length) {
4795                                resizeContents(5);
4796                            }
4797                            this.contents[localContentsOffset++] = (byte) 255;
4798                            this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4799                            this.contents[localContentsOffset++] = (byte) offsetDelta;
4800                            int numberOfLocalOffset = localContentsOffset;
4801                            localContentsOffset += 2; // leave two spots for number of locals
4802
int numberOfLocalEntries = 0;
4803                            numberOfLocals = currentFrame.getNumberOfLocals();
4804                            int numberOfEntries = 0;
4805                            int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
4806                            for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
4807                                if (localContentsOffset + 3 >= this.contents.length) {
4808                                    resizeContents(3);
4809                                }
4810                                VerificationTypeInfo info = currentFrame.locals[i];
4811                                if (info == null) {
4812                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4813                                } else {
4814                                    switch(info.id()) {
4815                                        case T_boolean :
4816                                        case T_byte :
4817                                        case T_char :
4818                                        case T_int :
4819                                        case T_short :
4820                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4821                                            break;
4822                                        case T_float :
4823                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4824                                            break;
4825                                        case T_long :
4826                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4827                                            i++;
4828                                            break;
4829                                        case T_double :
4830                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4831                                            i++;
4832                                            break;
4833                                        case T_null :
4834                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4835                                            break;
4836                                        default:
4837                                            this.contents[localContentsOffset++] = (byte) info.tag;
4838                                            switch (info.tag) {
4839                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4840                                                    int offset = info.offset;
4841                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4842                                                    this.contents[localContentsOffset++] = (byte) offset;
4843                                                    break;
4844                                                case VerificationTypeInfo.ITEM_OBJECT :
4845                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4846                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4847                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4848                                            }
4849                                    }
4850                                    numberOfLocalEntries++;
4851                                }
4852                                numberOfEntries++;
4853                            }
4854                            if (localContentsOffset + 4 >= this.contents.length) {
4855                                resizeContents(4);
4856                            }
4857                            this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
4858                            this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
4859                            int numberOfStackItems = currentFrame.numberOfStackItems;
4860                            this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
4861                            this.contents[localContentsOffset++] = (byte) numberOfStackItems;
4862                            for (int i = 0; i < numberOfStackItems; i++) {
4863                                if (localContentsOffset + 3 >= this.contents.length) {
4864                                    resizeContents(3);
4865                                }
4866                                VerificationTypeInfo info = currentFrame.stackItems[i];
4867                                if (info == null) {
4868                                    this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4869                                } else {
4870                                    switch(info.id()) {
4871                                        case T_boolean :
4872                                        case T_byte :
4873                                        case T_char :
4874                                        case T_int :
4875                                        case T_short :
4876                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4877                                            break;
4878                                        case T_float :
4879                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4880                                            break;
4881                                        case T_long :
4882                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4883                                            break;
4884                                        case T_double :
4885                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4886                                            break;
4887                                        case T_null :
4888                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4889                                            break;
4890                                        default:
4891                                            this.contents[localContentsOffset++] = (byte) info.tag;
4892                                            switch (info.tag) {
4893                                                case VerificationTypeInfo.ITEM_UNINITIALIZED :
4894                                                    int offset = info.offset;
4895                                                    this.contents[localContentsOffset++] = (byte) (offset >> 8);
4896                                                    this.contents[localContentsOffset++] = (byte) offset;
4897                                                    break;
4898                                                case VerificationTypeInfo.ITEM_OBJECT :
4899                                                    int indexForType = constantPool.literalIndexForType(info.constantPoolName());
4900                                                    this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
4901                                                    this.contents[localContentsOffset++] = (byte) indexForType;
4902                                            }
4903                                    }
4904                                }
4905                            }
4906                    }
4907                }
4908                
4909                this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
4910                this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
4911
4912                int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
4913                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
4914                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
4915                this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
4916                this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
4917                attributeNumber++;
4918            }
4919        }
4920        
4921        // update the number of attributes
4922
// ensure first that there is enough space available inside the contents array
4923
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
4924            resizeContents(2);
4925        }
4926        contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
4927        contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
4928
4929        // update the attribute length
4930
int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
4931        contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
4932        contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
4933        contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
4934        contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
4935        contentsOffset = localContentsOffset;
4936    }
4937
4938    /**
4939     * INTERNAL USE-ONLY
4940     * That method completes the creation of the code attribute by setting
4941     * - the attribute_length
4942     * - max_stack
4943     * - max_locals
4944     * - code_length
4945     * - exception table
4946     * - and debug attributes if necessary.
4947     *
4948     * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
4949     * @param codeAttributeOffset <CODE>int</CODE>
4950     */

4951    public void completeCodeAttributeForSyntheticMethod(
4952        SyntheticMethodBinding binding,
4953        int codeAttributeOffset,
4954        int[] startLineIndexes) {
4955        
4956        this.completeCodeAttributeForSyntheticMethod(
4957                false,
4958                binding,
4959                codeAttributeOffset,
4960                startLineIndexes);
4961    }
4962
4963    /**
4964     * INTERNAL USE-ONLY
4965     * Complete the creation of a method info by setting up the number of attributes at the right offset.
4966     *
4967     * @param methodAttributeOffset <CODE>int</CODE>
4968     * @param attributeNumber <CODE>int</CODE>
4969     */

4970    public void completeMethodInfo(
4971        int methodAttributeOffset,
4972        int attributeNumber) {
4973        // update the number of attributes
4974
contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
4975        contents[methodAttributeOffset] = (byte) attributeNumber;
4976    }
4977    
4978    /**
4979     * INTERNAL USE-ONLY
4980     * This methods returns a char[] representing the file name of the receiver
4981     *
4982     * @return char[]
4983     */

4984    public char[] fileName() {
4985        return constantPool.UTF8Cache.returnKeyFor(2);
4986    }
4987
4988    private void generateAnnotation(Annotation annotation, int attributeOffset) {
4989        if (contentsOffset + 4 >= this.contents.length) {
4990            resizeContents(4);
4991        }
4992        TypeBinding annotationTypeBinding = annotation.resolvedType;
4993        if (annotationTypeBinding == null) {
4994            this.contentsOffset = attributeOffset;
4995            return;
4996        }
4997        final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
4998        contents[contentsOffset++] = (byte) (typeIndex >> 8);
4999        contents[contentsOffset++] = (byte) typeIndex;
5000        if (annotation instanceof NormalAnnotation) {
5001            NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
5002            MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
5003            if (memberValuePairs != null) {
5004                final int memberValuePairsLength = memberValuePairs.length;
5005                contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
5006                contents[contentsOffset++] = (byte) memberValuePairsLength;
5007                for (int i = 0; i < memberValuePairsLength; i++) {
5008                    MemberValuePair memberValuePair = memberValuePairs[i];
5009                    if (contentsOffset + 2 >= this.contents.length) {
5010                        resizeContents(2);
5011                    }
5012                    final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
5013                    contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
5014                    contents[contentsOffset++] = (byte) elementNameIndex;
5015                    MethodBinding methodBinding = memberValuePair.binding;
5016                    if (methodBinding == null) {
5017                        contentsOffset = attributeOffset;
5018                    } else {
5019                        generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
5020                    }
5021                }
5022            } else {
5023                contents[contentsOffset++] = 0;
5024                contents[contentsOffset++] = 0;
5025            }
5026        } else if (annotation instanceof SingleMemberAnnotation) {
5027            SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
5028            // this is a single member annotation (one member value)
5029
contents[contentsOffset++] = 0;
5030            contents[contentsOffset++] = 1;
5031            if (contentsOffset + 2 >= this.contents.length) {
5032                resizeContents(2);
5033            }
5034            final int elementNameIndex = constantPool.literalIndex(VALUE);
5035            contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
5036            contents[contentsOffset++] = (byte) elementNameIndex;
5037            MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding;
5038            if (methodBinding == null) {
5039                contentsOffset = attributeOffset;
5040            } else {
5041                generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
5042            }
5043        } else {
5044            // this is a marker annotation (no member value pairs)
5045
contents[contentsOffset++] = 0;
5046            contents[contentsOffset++] = 0;
5047        }
5048    }
5049
5050    /**
5051     * INTERNAL USE-ONLY
5052     * That method generates the header of a code attribute.
5053     * - the index inside the constant pool for the attribute name ("Code")
5054     * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
5055     */

5056    public void generateCodeAttributeHeader() {
5057        if (contentsOffset + 20 >= this.contents.length) {
5058            resizeContents(20);
5059        }
5060        int constantValueNameIndex =
5061            constantPool.literalIndex(AttributeNamesConstants.CodeName);
5062        contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
5063        contents[contentsOffset++] = (byte) constantValueNameIndex;
5064        // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
5065
contentsOffset += 12;
5066    }
5067
5068    private void generateElementValue(
5069            Expression defaultValue,
5070            TypeBinding memberValuePairReturnType,
5071            int attributeOffset) {
5072        Constant constant = defaultValue.constant;
5073        TypeBinding defaultValueBinding = defaultValue.resolvedType;
5074        if (defaultValueBinding == null) {
5075            contentsOffset = attributeOffset;
5076        } else {
5077            if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
5078                // automatic wrapping
5079
if (contentsOffset + 3 >= this.contents.length) {
5080                    resizeContents(3);
5081                }
5082                contents[contentsOffset++] = (byte) '[';
5083                contents[contentsOffset++] = (byte) 0;
5084                contents[contentsOffset++] = (byte) 1;
5085            }
5086            if (constant != null && constant != Constant.NotAConstant) {
5087                generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
5088            } else {
5089                generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
5090            }
5091        }
5092    }
5093
5094    /**
5095     * @param attributeOffset
5096     */

5097    private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
5098        if (contentsOffset + 3 >= this.contents.length) {
5099            resizeContents(3);
5100        }
5101        switch (binding.id) {
5102            case T_boolean :
5103                contents[contentsOffset++] = (byte) 'Z';
5104                int booleanValueIndex =
5105                    constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
5106                contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
5107                contents[contentsOffset++] = (byte) booleanValueIndex;
5108                break;
5109            case T_byte :
5110                contents[contentsOffset++] = (byte) 'B';
5111                int integerValueIndex =
5112                    constantPool.literalIndex(constant.intValue());
5113                contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
5114                contents[contentsOffset++] = (byte) integerValueIndex;
5115                break;
5116            case T_char :
5117                contents[contentsOffset++] = (byte) 'C';
5118                integerValueIndex =
5119                    constantPool.literalIndex(constant.intValue());
5120                contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
5121                contents[contentsOffset++] = (byte) integerValueIndex;
5122                break;
5123            case T_int :
5124                contents[contentsOffset++] = (byte) 'I';
5125                integerValueIndex =
5126                    constantPool.literalIndex(constant.intValue());
5127                contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
5128                contents[contentsOffset++] = (byte) integerValueIndex;
5129                break;
5130            case T_short :
5131                contents[contentsOffset++] = (byte) 'S';
5132                integerValueIndex =
5133                    constantPool.literalIndex(constant.intValue());
5134                contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
5135                contents[contentsOffset++] = (byte) integerValueIndex;
5136                break;
5137            case T_float :
5138                contents[contentsOffset++] = (byte) 'F';
5139                int floatValueIndex =
5140                    constantPool.literalIndex(constant.floatValue());
5141                contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
5142                contents[contentsOffset++] = (byte) floatValueIndex;
5143                break;
5144            case T_double :
5145                contents[contentsOffset++] = (byte) 'D';
5146                int doubleValueIndex =
5147                    constantPool.literalIndex(constant.doubleValue());
5148                contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
5149                contents[contentsOffset++] = (byte) doubleValueIndex;
5150                break;
5151            case T_long :
5152                contents[contentsOffset++] = (byte) 'J';
5153                int longValueIndex =
5154                    constantPool.literalIndex(constant.longValue());
5155                contents[contentsOffset++] = (byte) (longValueIndex >> 8);
5156                contents[contentsOffset++] = (byte) longValueIndex;
5157                break;
5158            case T_JavaLangString :
5159                contents[contentsOffset++] = (byte) 's';
5160                int stringValueIndex =
5161                    constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
5162                if (stringValueIndex == -1) {
5163                    if (!creatingProblemType) {
5164                        // report an error and abort: will lead to a problem type classfile creation
5165
TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
5166                        typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
5167                    } else {
5168                        // already inside a problem type creation : no attribute
5169
contentsOffset = attributeOffset;
5170                    }
5171                } else {
5172                    contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
5173                    contents[contentsOffset++] = (byte) stringValueIndex;
5174                }
5175        }
5176    }
5177
5178    private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
5179        if (defaultValueBinding != null) {
5180            if (defaultValueBinding.isEnum()) {
5181                if (contentsOffset + 5 >= this.contents.length) {
5182                    resizeContents(5);
5183                }
5184                contents[contentsOffset++] = (byte) 'e';
5185                FieldBinding fieldBinding = null;
5186                if (defaultValue instanceof QualifiedNameReference) {
5187                    QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
5188                    fieldBinding = (FieldBinding) nameReference.binding;
5189                } else if (defaultValue instanceof SingleNameReference) {
5190                    SingleNameReference nameReference = (SingleNameReference) defaultValue;
5191                    fieldBinding = (FieldBinding) nameReference.binding;
5192                } else {
5193                    contentsOffset = attributeOffset;
5194                }
5195                if (fieldBinding != null) {
5196                    final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
5197                    final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
5198                    contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
5199                    contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
5200                    contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
5201                    contents[contentsOffset++] = (byte) enumConstantNameIndex;
5202                }
5203            } else if (defaultValueBinding.isAnnotationType()) {
5204                if (contentsOffset + 1 >= this.contents.length) {
5205                    resizeContents(1);
5206                }
5207                contents[contentsOffset++] = (byte) '@';
5208                generateAnnotation((Annotation) defaultValue, attributeOffset);
5209            } else if (defaultValueBinding.isArrayType()) {
5210                // array type
5211
if (contentsOffset + 3 >= this.contents.length) {
5212                    resizeContents(3);
5213                }
5214                contents[contentsOffset++] = (byte) '[';
5215                if (defaultValue instanceof ArrayInitializer) {
5216                    ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
5217                    int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
5218                    contents[contentsOffset++] = (byte) (arrayLength >> 8);
5219                    contents[contentsOffset++] = (byte) arrayLength;
5220                    for (int i = 0; i < arrayLength; i++) {
5221                        generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
5222                    }
5223                } else {
5224                    contentsOffset = attributeOffset;
5225                }
5226            } else {
5227                // class type
5228
if (contentsOffset + 3 >= this.contents.length) {
5229                    resizeContents(3);
5230                }
5231                contents[contentsOffset++] = (byte) 'c';
5232                if (defaultValue instanceof ClassLiteralAccess) {
5233                    ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
5234                    final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
5235                    contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
5236                    contents[contentsOffset++] = (byte) classInfoIndex;
5237                } else {
5238                    contentsOffset = attributeOffset;
5239                }
5240            }
5241        } else {
5242            contentsOffset = attributeOffset;
5243        }
5244    }
5245    
5246    public int generateMethodInfoAttribute(MethodBinding methodBinding) {
5247        return generateMethodInfoAttribute(methodBinding, false);
5248    }
5249
5250    public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
5251        int attributesNumber = generateMethodInfoAttribute(methodBinding);
5252        int attributeOffset = contentsOffset;
5253        if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) {
5254            // add an annotation default attribute
5255
int annotationDefaultNameIndex =
5256                constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
5257            contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
5258            contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
5259            int attributeLengthOffset = contentsOffset;
5260            contentsOffset += 4;
5261            if (contentsOffset + 4 >= this.contents.length) {
5262                resizeContents(4);
5263            }
5264            generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
5265            if (contentsOffset != attributeOffset) {
5266                int attributeLength = contentsOffset - attributeLengthOffset - 4;
5267                contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
5268                contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
5269                contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
5270                contents[attributeLengthOffset++] = (byte) attributeLength;
5271                attributesNumber++;
5272            }
5273        }
5274        return attributesNumber;
5275    }
5276    /**
5277     * INTERNAL USE-ONLY
5278     * That method generates the attributes of a code attribute.
5279     * They could be:
5280     * - an exception attribute for each try/catch found inside the method
5281     * - a deprecated attribute
5282     * - a synthetic attribute for synthetic access methods
5283     *
5284     * It returns the number of attributes created for the code attribute.
5285     *
5286     * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
5287     * @return <CODE>int</CODE>
5288     */

5289    public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
5290        // leave two bytes for the attribute_number
5291
contentsOffset += 2;
5292        if (contentsOffset + 2 >= this.contents.length) {
5293            resizeContents(2);
5294        }
5295        // now we can handle all the attribute for that method info:
5296
// it could be:
5297
// - a CodeAttribute
5298
// - a ExceptionAttribute
5299
// - a DeprecatedAttribute
5300
// - a SyntheticAttribute
5301

5302        // Exception attribute
5303
ReferenceBinding[] thrownsExceptions;
5304        int attributeNumber = 0;
5305        if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
5306            // The method has a throw clause. So we need to add an exception attribute
5307
// check that there is enough space to write all the bytes for the exception attribute
5308
int length = thrownsExceptions.length;
5309            int exSize = 8 + length * 2;
5310            if (exSize + contentsOffset >= this.contents.length) {
5311                resizeContents(exSize);
5312            }
5313            int exceptionNameIndex =
5314                constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
5315            contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
5316            contents[contentsOffset++] = (byte) exceptionNameIndex;
5317            // The attribute length = length * 2 + 2 in case of a exception attribute
5318
int attributeLength = length * 2 + 2;
5319            contents[contentsOffset++] = (byte) (attributeLength >> 24);
5320            contents[contentsOffset++] = (byte) (attributeLength >> 16);
5321            contents[contentsOffset++] = (byte) (attributeLength >> 8);
5322            contents[contentsOffset++] = (byte) attributeLength;
5323            contents[contentsOffset++] = (byte) (length >> 8);
5324            contents[contentsOffset++] = (byte) length;
5325            for (int i = 0; i < length; i++) {
5326                int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i]);
5327                contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
5328                contents[contentsOffset++] = (byte) exceptionIndex;
5329            }
5330            attributeNumber++;
5331        }
5332        if (methodBinding.isDeprecated()) {
5333            // Deprecated attribute
5334
// Check that there is enough space to write the deprecated attribute
5335
if (contentsOffset + 6 >= this.contents.length) {
5336                resizeContents(6);
5337            }
5338            int deprecatedAttributeNameIndex =
5339                constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
5340            contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
5341            contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
5342            // the length of a deprecated attribute is equals to 0
5343
contents[contentsOffset++] = 0;
5344            contents[contentsOffset++] = 0;
5345            contents[contentsOffset++] = 0;
5346            contents[contentsOffset++] = 0;
5347
5348            attributeNumber++;
5349        }
5350        if (this.targetJDK < ClassFileConstants.JDK1_5) {
5351            if (methodBinding.isSynthetic()) {
5352                // Synthetic attribute
5353
// Check that there is enough space to write the deprecated attribute
5354
if (contentsOffset + 6 >= this.contents.length) {
5355                    resizeContents(6);
5356                }
5357                int syntheticAttributeNameIndex =
5358                    constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
5359                contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
5360                contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
5361                // the length of a synthetic attribute is equals to 0
5362
contents[contentsOffset++] = 0;
5363                contents[contentsOffset++] = 0;
5364                contents[contentsOffset++] = 0;
5365                contents[contentsOffset++] = 0;
5366    
5367                attributeNumber++;
5368            }
5369            if (methodBinding.isVarargs()) {
5370                /*
5371                 * handle of the target jsr14 for varargs in the source
5372                 * Varargs attribute
5373                 * Check that there is enough space to write the deprecated attribute
5374                 */

5375                if (contentsOffset + 6 >= this.contents.length) {
5376                    resizeContents(6);
5377                }
5378                int varargsAttributeNameIndex =
5379                    constantPool.literalIndex(AttributeNamesConstants.VarargsName);
5380                contents[contentsOffset++] = (byte) (varargsAttributeNameIndex >> 8);
5381                contents[contentsOffset++] = (byte) varargsAttributeNameIndex;
5382                // the length of a varargs attribute is equals to 0
5383
contents[contentsOffset++] = 0;
5384                contents[contentsOffset++] = 0;
5385                contents[contentsOffset++] = 0;
5386                contents[contentsOffset++] = 0;
5387    
5388                attributeNumber++;
5389            }
5390        }
5391        // add signature attribute
5392
char[] genericSignature = methodBinding.genericSignature();
5393        if (genericSignature != null) {
5394            // check that there is enough space to write all the bytes for the field info corresponding
5395
// to the @fieldBinding
5396
if (contentsOffset + 8 >= this.contents.length) {
5397                resizeContents(8);
5398            }
5399            int signatureAttributeNameIndex =
5400                constantPool.literalIndex(AttributeNamesConstants.SignatureName);
5401            contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
5402            contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
5403            // the length of a signature attribute is equals to 2
5404
contents[contentsOffset++] = 0;
5405            contents[contentsOffset++] = 0;
5406            contents[contentsOffset++] = 0;
5407            contents[contentsOffset++] = 2;
5408            int signatureIndex =
5409                constantPool.literalIndex(genericSignature);
5410            contents[contentsOffset++] = (byte) (signatureIndex >> 8);
5411            contents[contentsOffset++] = (byte) signatureIndex;
5412            attributeNumber++;
5413        }
5414        if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
5415            AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
5416            if (methodDeclaration != null) {
5417                Annotation[] annotations = methodDeclaration.annotations;
5418                if (annotations != null) {
5419                    attributeNumber += generateRuntimeAnnotations(annotations);
5420                }
5421                if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
5422                    Argument[] arguments = methodDeclaration.arguments;
5423                    if (arguments != null) {
5424                        attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
5425                    }
5426                }
5427            }
5428        }
5429        return attributeNumber;
5430    }
5431
5432    /**
5433     * INTERNAL USE-ONLY
5434     * That method generates the header of a method info:
5435     * The header consists in:
5436     * - the access flags
5437     * - the name index of the method name inside the constant pool
5438     * - the descriptor index of the signature of the method inside the constant pool.
5439     *
5440     * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
5441     */

5442    public void generateMethodInfoHeader(MethodBinding methodBinding) {
5443        generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
5444    }
5445
5446    /**
5447     * INTERNAL USE-ONLY
5448     * That method generates the header of a method info:
5449     * The header consists in:
5450     * - the access flags
5451     * - the name index of the method name inside the constant pool
5452     * - the descriptor index of the signature of the method inside the constant pool.
5453     *
5454     * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
5455     * @param accessFlags the access flags
5456     */

5457    public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
5458        // check that there is enough space to write all the bytes for the method info corresponding
5459
// to the @methodBinding
5460
methodCount++; // add one more method
5461
if (contentsOffset + 10 >= this.contents.length) {
5462            resizeContents(10);
5463        }
5464        if (targetJDK < ClassFileConstants.JDK1_5) {
5465            // pre 1.5, synthetic is an attribute, not a modifier
5466
// pre 1.5, varargs is an attribute, not a modifier (-target jsr14 mode)
5467
accessFlags &= ~(ClassFileConstants.AccSynthetic | ClassFileConstants.AccVarargs);
5468        }
5469        if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) {
5470            accessFlags &= ~ClassFileConstants.AccPrivate;
5471        }
5472        contents[contentsOffset++] = (byte) (accessFlags >> 8);
5473        contents[contentsOffset++] = (byte) accessFlags;
5474        int nameIndex = constantPool.literalIndex(methodBinding.selector);
5475        contents[contentsOffset++] = (byte) (nameIndex >> 8);
5476        contents[contentsOffset++] = (byte) nameIndex;
5477        int descriptorIndex = constantPool.literalIndex(methodBinding.signature(this));
5478        contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
5479        contents[contentsOffset++] = (byte) descriptorIndex;
5480    }
5481    /**
5482     * INTERNAL USE-ONLY
5483     * That method generates the method info header of a clinit:
5484     * The header consists in:
5485     * - the access flags (always default access + static)
5486     * - the name index of the method name (always <clinit>) inside the constant pool
5487     * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
5488     */

5489    public void generateMethodInfoHeaderForClinit() {
5490        // check that there is enough space to write all the bytes for the method info corresponding
5491
// to the @methodBinding
5492
methodCount++; // add one more method
5493
if (contentsOffset + 10 >= this.contents.length) {
5494            resizeContents(10);
5495        }
5496        contents[contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8);
5497        contents[contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic);
5498        int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
5499        contents[contentsOffset++] = (byte) (nameIndex >> 8);
5500        contents[contentsOffset++] = (byte) nameIndex;
5501        int descriptorIndex =
5502            constantPool.literalIndex(ConstantPool.ClinitSignature);
5503        contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
5504        contents[contentsOffset++] = (byte) descriptorIndex;
5505        // We know that we won't get more than 1 attribute: the code attribute
5506
contents[contentsOffset++] = 0;
5507        contents[contentsOffset++] = 1;
5508    }
5509
5510    /**
5511     * INTERNAL USE-ONLY
5512     * Generate the byte for problem method infos that correspond to missing abstract methods.
5513     * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
5514     *
5515     * @param methodDeclarations Array of all missing abstract methods
5516     */

5517    public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
5518        if (methodDeclarations != null) {
5519            TypeDeclaration currentDeclaration = this.referenceBinding.scope.referenceContext;
5520            int typeDeclarationSourceStart = currentDeclaration.sourceStart();
5521            int typeDeclarationSourceEnd = currentDeclaration.sourceEnd();
5522            for (int i = 0, max = methodDeclarations.length; i < max; i++) {
5523                MethodDeclaration methodDeclaration = methodDeclarations[i];
5524                MethodBinding methodBinding = methodDeclaration.binding;
5525                String JavaDoc readableName = new String JavaDoc(methodBinding.readableName());
5526                CategorizedProblem[] problems = compilationResult.problems;
5527                int problemsCount = compilationResult.problemCount;
5528                for (int j = 0; j < problemsCount; j++) {
5529                    CategorizedProblem problem = problems[j];
5530                    if (problem != null
5531                            && problem.getID() == IProblem.AbstractMethodMustBeImplemented
5532                            && problem.getMessage().indexOf(readableName) != -1
5533                            && problem.getSourceStart() >= typeDeclarationSourceStart
5534                            && problem.getSourceEnd() <= typeDeclarationSourceEnd) {
5535                        // we found a match
5536
addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
5537                    }
5538                }
5539            }
5540        }
5541    }
5542
5543    /**
5544     * @param annotations
5545     * @return the number of attributes created while dumping the annotations in the .class file
5546     */

5547    private int generateRuntimeAnnotations(final Annotation[] annotations) {
5548        int attributesNumber = 0;
5549        final int length = annotations.length;
5550        int visibleAnnotationsCounter = 0;
5551        int invisibleAnnotationsCounter = 0;
5552        
5553        for (int i = 0; i < length; i++) {
5554            Annotation annotation = annotations[i];
5555            if (isRuntimeInvisible(annotation)) {
5556                invisibleAnnotationsCounter++;
5557            } else if (isRuntimeVisible(annotation)) {
5558                visibleAnnotationsCounter++;
5559            }
5560        }
5561
5562        if (invisibleAnnotationsCounter != 0) {
5563            int annotationAttributeOffset = contentsOffset;
5564            if (contentsOffset + 10 >= contents.length) {
5565                resizeContents(10);
5566            }
5567            int runtimeInvisibleAnnotationsAttributeNameIndex =
5568                constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
5569            contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
5570            contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
5571            int attributeLengthOffset = contentsOffset;
5572            contentsOffset += 4; // leave space for the attribute length
5573

5574            int annotationsLengthOffset = contentsOffset;
5575            contentsOffset += 2; // leave space for the annotations length
5576

5577            contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
5578            contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
5579
5580            loop: for (int i = 0; i < length; i++) {
5581                if (invisibleAnnotationsCounter == 0) break loop;
5582                Annotation annotation = annotations[i];
5583                if (isRuntimeInvisible(annotation)) {
5584                    generateAnnotation(annotation, annotationAttributeOffset);
5585                    invisibleAnnotationsCounter--;
5586                    if (this.contentsOffset == annotationAttributeOffset) {
5587                        break loop;
5588                    }
5589                }
5590            }
5591            if (contentsOffset != annotationAttributeOffset) {
5592                int attributeLength = contentsOffset - attributeLengthOffset - 4;
5593                contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
5594                contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
5595                contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
5596                contents[attributeLengthOffset++] = (byte) attributeLength;
5597                attributesNumber++;
5598            } else {
5599                contentsOffset = annotationAttributeOffset;
5600            }
5601        }
5602    
5603        if (visibleAnnotationsCounter != 0) {
5604            int annotationAttributeOffset = contentsOffset;
5605            if (contentsOffset + 10 >= contents.length) {
5606                resizeContents(10);
5607            }
5608            int runtimeVisibleAnnotationsAttributeNameIndex =
5609                constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
5610            contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
5611            contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
5612            int attributeLengthOffset = contentsOffset;
5613            contentsOffset += 4; // leave space for the attribute length
5614

5615            int annotationsLengthOffset = contentsOffset;
5616            contentsOffset += 2; // leave space for the annotations length
5617

5618            contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
5619            contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
5620
5621            loop: for (int i = 0; i < length; i++) {
5622                if (visibleAnnotationsCounter == 0) break loop;
5623                Annotation annotation = annotations[i];
5624                if (isRuntimeVisible(annotation)) {
5625                    visibleAnnotationsCounter--;
5626                    generateAnnotation(annotation, annotationAttributeOffset);
5627                    if (this.contentsOffset == annotationAttributeOffset) {
5628                        break loop;
5629                    }
5630                }
5631            }
5632            if (contentsOffset != annotationAttributeOffset) {
5633                int attributeLength = contentsOffset - attributeLengthOffset - 4;
5634                contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
5635                contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
5636                contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
5637                contents[attributeLengthOffset++] = (byte) attributeLength;
5638                attributesNumber++;
5639            } else {
5640                contentsOffset = annotationAttributeOffset;
5641            }
5642        }
5643        return attributesNumber;
5644    }
5645
5646    private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
5647        final int argumentsLength = arguments.length;
5648        final int VISIBLE_INDEX = 0;
5649        final int INVISIBLE_INDEX = 1;
5650        int invisibleParametersAnnotationsCounter = 0;
5651        int visibleParametersAnnotationsCounter = 0;
5652        int[][] annotationsCounters = new int[argumentsLength][2];
5653        for (int i = 0; i < argumentsLength; i++) {
5654            Argument argument = arguments[i];
5655            Annotation[] annotations = argument.annotations;
5656            if (annotations != null) {
5657                for (int j = 0, max2 = annotations.length; j < max2; j++) {
5658                    Annotation annotation = annotations[j];
5659                    if (isRuntimeInvisible(annotation)) {
5660                        annotationsCounters[i][INVISIBLE_INDEX]++;
5661                        invisibleParametersAnnotationsCounter++;
5662                    } else if (isRuntimeVisible(annotation)) {
5663                        annotationsCounters[i][VISIBLE_INDEX]++;
5664                        visibleParametersAnnotationsCounter++;
5665                    }
5666                }
5667            }
5668        }
5669        int attributesNumber = 0;
5670        int annotationAttributeOffset = contentsOffset;
5671        if (invisibleParametersAnnotationsCounter != 0) {
5672            if (contentsOffset + 7 >= contents.length) {
5673                resizeContents(7);
5674            }
5675            int attributeNameIndex =
5676                constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
5677            contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
5678            contents[contentsOffset++] = (byte) attributeNameIndex;
5679            int attributeLengthOffset = contentsOffset;
5680            contentsOffset += 4; // leave space for the attribute length
5681

5682            contents[contentsOffset++] = (byte) argumentsLength;
5683            invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
5684                if (contentsOffset + 2 >= contents.length) {
5685                    resizeContents(2);
5686                }
5687                if (invisibleParametersAnnotationsCounter == 0) {
5688                    contents[contentsOffset++] = (byte) 0;
5689                    contents[contentsOffset++] = (byte) 0;
5690                } else {
5691                    final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
5692                    contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
5693                    contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
5694                    if (numberOfInvisibleAnnotations != 0) {
5695                        Argument argument = arguments[i];
5696                        Annotation[] annotations = argument.annotations;
5697                        for (int j = 0, max = annotations.length; j < max; j++) {
5698                            Annotation annotation = annotations[j];
5699                            if (isRuntimeInvisible(annotation)) {
5700                                generateAnnotation(annotation, annotationAttributeOffset);
5701                                if (contentsOffset == annotationAttributeOffset) {
5702                                    break invisibleLoop;
5703                                }
5704                                invisibleParametersAnnotationsCounter--;
5705                            }
5706                        }
5707                    }
5708                }
5709            }
5710            if (contentsOffset != annotationAttributeOffset) {
5711                int attributeLength = contentsOffset - attributeLengthOffset - 4;
5712                contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
5713                contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
5714                contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
5715                contents[attributeLengthOffset++] = (byte) attributeLength;
5716                attributesNumber++;
5717            } else {
5718                contentsOffset = annotationAttributeOffset;
5719            }
5720        }
5721        if (visibleParametersAnnotationsCounter != 0) {
5722            if (contentsOffset + 7 >= contents.length) {
5723                resizeContents(7);
5724            }
5725            int attributeNameIndex =
5726                constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
5727            contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
5728            contents[contentsOffset++] = (byte) attributeNameIndex;
5729            int attributeLengthOffset = contentsOffset;
5730            contentsOffset += 4; // leave space for the attribute length
5731

5732            contents[contentsOffset++] = (byte) argumentsLength;
5733            visibleLoop: for (int i = 0; i < argumentsLength; i++) {
5734                if (contentsOffset + 2 >= contents.length) {
5735                    resizeContents(2);
5736                }
5737                if (visibleParametersAnnotationsCounter == 0) {
5738                    contents[contentsOffset++] = (byte) 0;
5739                    contents[contentsOffset++] = (byte) 0;
5740                } else {
5741                    final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
5742                    contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
5743                    contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
5744                    if (numberOfVisibleAnnotations != 0) {
5745                        Argument argument = arguments[i];
5746                        Annotation[] annotations = argument.annotations;
5747                        for (int j = 0, max = annotations.length; j < max; j++) {
5748                            Annotation annotation = annotations[j];
5749                            if (isRuntimeVisible(annotation)) {
5750                                generateAnnotation(annotation, annotationAttributeOffset);
5751                                if (contentsOffset == annotationAttributeOffset) {
5752                                    break visibleLoop;
5753                                }
5754                                visibleParametersAnnotationsCounter--;
5755                            }
5756                        }
5757                    }
5758                }
5759            }
5760            if (contentsOffset != annotationAttributeOffset) {
5761                int attributeLength = contentsOffset - attributeLengthOffset - 4;
5762                contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
5763                contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
5764                contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
5765                contents[attributeLengthOffset++] = (byte) attributeLength;
5766                attributesNumber++;
5767            } else {
5768                contentsOffset = annotationAttributeOffset;
5769            }
5770        }
5771        return attributesNumber;
5772    }
5773    
5774    /**
5775     * EXTERNAL API
5776     * Answer the actual bytes of the class file
5777     *
5778     * This method encodes the receiver structure into a byte array which is the content of the classfile.
5779     * Returns the byte array that represents the encoded structure of the receiver.
5780     *
5781     * @return byte[]
5782     */

5783    public byte[] getBytes() {
5784        if (this.bytes == null) {
5785            this.bytes = new byte[this.headerOffset + this.contentsOffset];
5786            System.arraycopy(this.header, 0, this.bytes, 0, this.headerOffset);
5787            System.arraycopy(this.contents, 0, this.bytes, this.headerOffset, this.contentsOffset);
5788        }
5789        return this.bytes;
5790    }
5791    /**
5792     * EXTERNAL API
5793     * Answer the compound name of the class file.
5794     * @return char[][]
5795     * e.g. {{java}, {util}, {Hashtable}}.
5796     */

5797    public char[][] getCompoundName() {
5798        return CharOperation.splitOn('/', fileName());
5799    }
5800
5801    protected void initByteArrays() {
5802        int members = referenceBinding.methods().length + referenceBinding.fields().length;
5803        this.header = new byte[INITIAL_HEADER_SIZE];
5804        this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
5805    }
5806
5807    public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) {
5808        // generate the magic numbers inside the header
5809
header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
5810        header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
5811        header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
5812        header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
5813        
5814        header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
5815
header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
5816
header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
5817
header[headerOffset++] = (byte) (this.targetJDK >> 16); // major low
5818

5819        constantPoolOffset = headerOffset;
5820        headerOffset += 2;
5821        this.constantPool.initialize(this);
5822        
5823        // Modifier manipulations for classfile
5824
int accessFlags = aType.getAccessFlags();
5825        if (aType.isPrivate()) { // rewrite private to non-public
5826
accessFlags &= ~ClassFileConstants.AccPublic;
5827        }
5828        if (aType.isProtected()) { // rewrite protected into public
5829
accessFlags |= ClassFileConstants.AccPublic;
5830        }
5831        // clear all bits that are illegal for a class or an interface
5832
accessFlags
5833            &= ~(
5834                ClassFileConstants.AccStrictfp
5835                    | ClassFileConstants.AccProtected
5836                    | ClassFileConstants.AccPrivate
5837                    | ClassFileConstants.AccStatic
5838                    | ClassFileConstants.AccSynchronized
5839                    | ClassFileConstants.AccNative);
5840                    
5841        // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
5842
if (!aType.isInterface()) { // class or enum
5843
accessFlags |= ClassFileConstants.AccSuper;
5844        }
5845        
5846        this.enclosingClassFile = parentClassFile;
5847        // innerclasses get their names computed at code gen time
5848

5849        // now we continue to generate the bytes inside the contents array
5850
contents[contentsOffset++] = (byte) (accessFlags >> 8);
5851        contents[contentsOffset++] = (byte) accessFlags;
5852        int classNameIndex = constantPool.literalIndexForType(aType);
5853        contents[contentsOffset++] = (byte) (classNameIndex >> 8);
5854        contents[contentsOffset++] = (byte) classNameIndex;
5855        int superclassNameIndex;
5856        if (aType.isInterface()) {
5857            superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
5858        } else {
5859            superclassNameIndex =
5860                (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass));
5861        }
5862        contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
5863        contents[contentsOffset++] = (byte) superclassNameIndex;
5864        ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
5865        int interfacesCount = superInterfacesBinding.length;
5866        contents[contentsOffset++] = (byte) (interfacesCount >> 8);
5867        contents[contentsOffset++] = (byte) interfacesCount;
5868        for (int i = 0; i < interfacesCount; i++) {
5869            int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i]);
5870            contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
5871            contents[contentsOffset++] = (byte) interfaceIndex;
5872        }
5873        this.creatingProblemType = createProblemType;
5874
5875        // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
5876
// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
5877
if (this.enclosingClassFile == null) {
5878            this.codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
5879        } else {
5880            ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
5881            this.codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
5882        }
5883    }
5884
5885    
5886    private boolean isRuntimeInvisible(Annotation annotation) {
5887        final TypeBinding annotationBinding = annotation.resolvedType;
5888        if (annotationBinding == null) {
5889            return false;
5890        }
5891        long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference
5892
if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
5893            return true; // by default the retention is CLASS
5894

5895        return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
5896    }
5897
5898    private boolean isRuntimeVisible(Annotation annotation) {
5899        final TypeBinding annotationBinding = annotation.resolvedType;
5900        if (annotationBinding == null) {
5901            return false;
5902        }
5903        long metaTagBits = annotationBinding.getAnnotationTagBits();
5904        if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
5905            return false; // by default the retention is CLASS
5906

5907        return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
5908    }
5909
5910    /**
5911     * INTERNAL USE-ONLY
5912     * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
5913     * for all inner types of the receiver.
5914     * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
5915     */

5916    public ClassFile outerMostEnclosingClassFile() {
5917        ClassFile current = this;
5918        while (current.enclosingClassFile != null)
5919            current = current.enclosingClassFile;
5920        return current;
5921    }
5922
5923    public void recordInnerClasses(TypeBinding binding) {
5924        if (this.innerClassesBindings == null) {
5925            this.innerClassesBindings = new HashSet JavaDoc(INNER_CLASSES_SIZE);
5926        }
5927        ReferenceBinding innerClass = (ReferenceBinding) binding;
5928        this.innerClassesBindings.add(innerClass.erasure());
5929        ReferenceBinding enclosingType = innerClass.enclosingType();
5930        while (enclosingType != null
5931                && enclosingType.isNestedType()) {
5932            this.innerClassesBindings.add(enclosingType.erasure());
5933            enclosingType = enclosingType.enclosingType();
5934        }
5935    }
5936
5937    public void reset(SourceTypeBinding typeBinding) {
5938        // the code stream is reinitialized for each method
5939
final CompilerOptions options = typeBinding.scope.compilerOptions();
5940        this.referenceBinding = typeBinding;
5941        this.targetJDK = options.targetJDK;
5942        this.produceAttributes = options.produceDebugAttributes;
5943        if (this.targetJDK >= ClassFileConstants.JDK1_6) {
5944            this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
5945        }
5946        this.bytes = null;
5947        this.constantPool.reset();
5948        this.codeStream.reset(this);
5949        this.constantPoolOffset = 0;
5950        this.contentsOffset = 0;
5951        this.creatingProblemType = false;
5952        this.enclosingClassFile = null;
5953        this.headerOffset = 0;
5954        this.methodCount = 0;
5955        this.methodCountOffset = 0;
5956        if (this.innerClassesBindings != null) {
5957            this.innerClassesBindings.clear();
5958        }
5959    }
5960
5961    /**
5962     * Resize the pool contents
5963     */

5964    private final void resizeContents(int minimalSize) {
5965        int length = this.contents.length;
5966        int toAdd = length;
5967        if (toAdd < minimalSize)
5968            toAdd = minimalSize;
5969        System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
5970    }
5971
5972    /**
5973     * INTERNAL USE-ONLY
5974     * This methods leaves the space for method counts recording.
5975     */

5976    public void setForMethodInfos() {
5977        // leave some space for the methodCount
5978
methodCountOffset = contentsOffset;
5979        contentsOffset += 2;
5980    }
5981}
5982
Popular Tags