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