Logo Search packages:      
Sourcecode: ecj version File versions

ClassFile.java

/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.Messages;

/**
 * Represents a class file wrapper on bytes, it is aware of its actual
 * type name.
 *
 * Public APIs are listed below:
 *
 * byte[] getBytes();
 *          Answer the actual bytes of the class file
 *
 * char[][] getCompoundName();
 *          Answer the compound name of the class file.
 *          For example, {{java}, {util}, {Hashtable}}.
 *
 * byte[] getReducedBytes();
 *          Answer a smaller byte format, which is only contains some structural 
 *      information. Those bytes are decodable with a regular class file reader, 
 *      such as DietClassFileReader
 */
00088 public class ClassFile
      implements TypeConstants, TypeIds {

      private byte[] bytes;
      public CodeStream codeStream;
      public ConstantPool constantPool;

      public int constantPoolOffset;

      // the header contains all the bytes till the end of the constant pool
      public byte[] contents;

      public int contentsOffset;

      protected boolean creatingProblemType;
      
      public ClassFile enclosingClassFile;
      public byte[] header;
      // that collection contains all the remaining bytes of the .class file
      public int headerOffset;
      public ReferenceBinding[] innerClassesBindings;
      public int methodCount;
      public int methodCountOffset;
      public int numberOfInnerClasses;
      // pool managment
      public boolean isShared = false;
      // used to generate private access methods
      // debug and stack map attributes
      public int produceAttributes;
      public SourceTypeBinding referenceBinding;
      public long targetJDK;
      public static final int INITIAL_CONTENTS_SIZE = 400;
      public static final int INITIAL_HEADER_SIZE = 1500;
      public static final int INNER_CLASSES_SIZE = 5;
      
      /**
       * INTERNAL USE-ONLY
       * Build all the directories and subdirectories corresponding to the packages names
       * into the directory specified in parameters.
       *
       * outputPath is formed like:
       *       c:\temp\ the last character is a file separator
       * relativeFileName is formed like:
       *     java\lang\String.class *
       * 
       * @param outputPath java.lang.String
       * @param relativeFileName java.lang.String
       * @return java.lang.String
       */
00137       public static String buildAllDirectoriesInto(
            String outputPath,
            String relativeFileName)
            throws IOException {
            char fileSeparatorChar = File.separatorChar;
            String fileSeparator = File.separator;
            File f;
            outputPath = outputPath.replace('/', fileSeparatorChar);
                  // these could be optimized out if we normalized paths once and for
                  // all
            relativeFileName = relativeFileName.replace('/', fileSeparatorChar);
            String outputDirPath, fileName;
            int separatorIndex = relativeFileName.lastIndexOf(fileSeparatorChar);
            if (separatorIndex == -1) {
                  if (outputPath.endsWith(fileSeparator)) {
                        outputDirPath = outputPath.substring(0, outputPath.length() - 1);
                        fileName = outputPath + relativeFileName;
                  } else {
                        outputDirPath = outputPath;
                        fileName = outputPath + fileSeparator + relativeFileName;
                  }
            } else {
                  if (outputPath.endsWith(fileSeparator)) {
                        outputDirPath = outputPath + 
                              relativeFileName.substring(0, separatorIndex);
                        fileName = outputPath + relativeFileName;
                  } else {
                        outputDirPath = outputPath + fileSeparator +
                              relativeFileName.substring(0, separatorIndex);
                        fileName = outputPath + fileSeparator + relativeFileName;
                  }
            }
            f = new File(outputDirPath);
            f.mkdirs();
            if (f.isDirectory()) {
                  return fileName;
            } else {
                  // the directory creation failed for some reason - retry using
                  // a slower algorithm so as to refine the diagnostic
                  if (outputPath.endsWith(fileSeparator)) {
                        outputPath = outputPath.substring(0, outputPath.length() - 1);
                  }
                  f = new File(outputPath);
                  boolean checkFileType = false;
                  if (f.exists()) {
                        checkFileType = true; // pre-existed
                  } else {
                        // we have to create that directory
                        if (!f.mkdirs()) {
                              if (f.exists()) {
                                    // someone else created f -- need to check its type
                                    checkFileType = true;
                              } else {
                                    // no one could create f -- complain
                              throw new IOException(Messages.bind(
                                    Messages.output_notValidAll, f.getAbsolutePath()));
                              }
                        }
                  }
                  if (checkFileType) {
                        if (!f.isDirectory()) {
                        throw new IOException(Messages.bind(
                              Messages.output_isFile, f.getAbsolutePath()));
                        }
                  }
                  StringBuffer outDir = new StringBuffer(outputPath);
                  outDir.append(fileSeparator);
                  StringTokenizer tokenizer =
                        new StringTokenizer(relativeFileName, fileSeparator);
                  String token = tokenizer.nextToken();
                  while (tokenizer.hasMoreTokens()) {
                        f = new File(outDir.append(token).append(fileSeparator).toString());
                        checkFileType = false; // reset
                        if (f.exists()) {
                              checkFileType = true; // this is suboptimal, but it catches corner cases
                                                              // in which a regular file pre-exists
                        } else {
                        // we have to create that directory
                        if (!f.mkdir()) {
                              if (f.exists()) {
                                    // someone else created f -- need to check its type
                                    checkFileType = true;
                              } else {
                                    // no one could create f -- complain
                                    throw new IOException(Messages.bind(
                                          Messages.output_notValid, 
                                                outDir.substring(outputPath.length() + 1, 
                                                      outDir.length() - 1),
                                                outputPath));
                              }
                        }
                        }
                  if (checkFileType) {
                        if (!f.isDirectory()) {
                              throw new IOException(Messages.bind(
                                    Messages.output_isFile, f.getAbsolutePath()));
                        }
                  }
                        token = tokenizer.nextToken();
                  }
                  // token contains the last one
                  return outDir.append(token).toString();
            }
      }
      /**
       * INTERNAL USE-ONLY
       * Request the creation of a ClassFile compatible representation of a problematic type
       *
       * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
       * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
       */
00248       public static void createProblemType(
            TypeDeclaration typeDeclaration,
            CompilationResult unitResult) {
            SourceTypeBinding typeBinding = typeDeclaration.binding;
            ClassFile classFile = ClassFile.getNewInstance(typeBinding);
            classFile.initialize(typeBinding, null, true);
      
            // TODO (olivier) handle cases where a field cannot be generated (name too long)
            // TODO (olivier) handle too many methods
            // inner attributes
            if (typeBinding.isMemberType())
                  classFile.recordEnclosingTypeAttributes(typeBinding);
      
            // add its fields
            FieldBinding[] fields = typeBinding.fields();
            if ((fields != null) && (fields != Binding.NO_FIELDS)) {
                  classFile.addFieldInfos();
            } else {
                  // we have to set the number of fields to be equals to 0
                  classFile.contents[classFile.contentsOffset++] = 0;
                  classFile.contents[classFile.contentsOffset++] = 0;
            }
            // leave some space for the methodCount
            classFile.setForMethodInfos();
            // add its user defined methods
            int problemsLength;
            CategorizedProblem[] problems = unitResult.getErrors();
            if (problems == null) {
                  problems = new CategorizedProblem[0];
            }
            CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
            System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
            
            AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods;
            if (methodDecls != null) {
                  if (typeBinding.isInterface()) {
                        // we cannot create problem methods for an interface. So we have to generate a clinit
                        // which should contain all the problem
                        classFile.addProblemClinit(problemsCopy);
                        for (int i = 0, length = methodDecls.length; i < length; i++) {
                              AbstractMethodDeclaration methodDecl = methodDecls[i];
                              MethodBinding method = methodDecl.binding;
                              if (method == null || method.isConstructor()) continue;
                              classFile.addAbstractMethod(methodDecl, method);
                        }           
                  } else {
                        for (int i = 0, length = methodDecls.length; i < length; i++) {
                              AbstractMethodDeclaration methodDecl = methodDecls[i];
                              MethodBinding method = methodDecl.binding;
                              if (method == null) continue;
                              if (method.isConstructor()) {
                                    classFile.addProblemConstructor(methodDecl, method, problemsCopy);
                              } else {
                                    classFile.addProblemMethod(methodDecl, method, problemsCopy);
                              }
                        }
                  }
                  // add abstract methods
                  classFile.addDefaultAbstractMethods();
            }           
            
            // propagate generation of (problem) member types
            if (typeDeclaration.memberTypes != null) {
                  for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
                        TypeDeclaration memberType = typeDeclaration.memberTypes[i];
                        if (memberType.binding != null) {
                              classFile.recordNestedMemberAttribute(memberType.binding);
                              ClassFile.createProblemType(memberType, unitResult);
                        }
                  }
            }
            classFile.addAttributes();
            unitResult.record(typeBinding.constantPoolName(), classFile);
      }
      public static ClassFile getNewInstance(SourceTypeBinding typeBinding) {
            LookupEnvironment env = typeBinding.scope.environment();
            return env.classFilePool.acquire(typeBinding);
      }
      /**
       * INTERNAL USE-ONLY
       * Search the line number corresponding to a specific position
       */
00330       public static final int searchLineNumber(int[] startLineIndexes, int position) {
            // this code is completely useless, but it is the same implementation than
            // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
            // if (startLineIndexes == null)
            //    return 1;
            int length = startLineIndexes.length;
            if (length == 0)
                  return 1;
            int g = 0, d = length - 1;
            int m = 0, start;
            while (g <= d) {
                  m = (g + d) / 2;
                  if (position < (start = startLineIndexes[m])) {
                        d = m - 1;
                  } else if (position > start) {
                        g = m + 1;
                  } else {
                        return m + 1;
                  }
            }
            if (position < startLineIndexes[m]) {
                  return m + 1;
            }
            return m + 2;
      }
      
      /**
       * INTERNAL USE-ONLY
       * outputPath is formed like:
       *       c:\temp\ the last character is a file separator
       * relativeFileName is formed like:
       *     java\lang\String.class
       * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
       * @param outputPath the given output directory
       * @param relativeFileName the given relative file name
       * @param classFile the given classFile to write
       * 
       */
00368       public static void writeToDisk(
            boolean generatePackagesStructure,
            String outputPath,
            String relativeFileName,
            ClassFile classFile)
            throws IOException {
                  
            BufferedOutputStream output = null;
            if (generatePackagesStructure) {
                  output = new BufferedOutputStream(
                        new FileOutputStream(
                                    new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
            } else {
                  String fileName = null;
                  char fileSeparatorChar = File.separatorChar;
                  String fileSeparator = File.separator;
                  // First we ensure that the outputPath exists
                  outputPath = outputPath.replace('/', fileSeparatorChar);
                  // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
                  int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
                  if (indexOfPackageSeparator == -1) {
                        if (outputPath.endsWith(fileSeparator)) {
                              fileName = outputPath + relativeFileName;
                        } else {
                              fileName = outputPath + fileSeparator + relativeFileName;
                        }
                  } else {
                        int length = relativeFileName.length();
                        if (outputPath.endsWith(fileSeparator)) {
                              fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
                        } else {
                              fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
                        }
                  }
                  output = new BufferedOutputStream(
                        new FileOutputStream(
                                    new File(fileName)));
            }
            try {
                  output.write(classFile.header, 0, classFile.headerOffset);
                  output.write(classFile.contents, 0, classFile.contentsOffset);
            } finally {
                  output.flush();
                  output.close();
            }
      }
      
      /**
       * INTERNAL USE-ONLY
       * This methods creates a new instance of the receiver.
       */
00419       protected ClassFile() {
            // default constructor for subclasses
      }
      
      public ClassFile(SourceTypeBinding typeBinding) {
            // default constructor for subclasses
            this.constantPool = new ConstantPool(this);
            final CompilerOptions options = typeBinding.scope.compilerOptions();
            this.targetJDK = options.targetJDK;
            this.produceAttributes = options.produceDebugAttributes;
            this.referenceBinding = typeBinding;
            if (this.targetJDK >= ClassFileConstants.JDK1_6) {
                  this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
                  this.codeStream = new StackMapFrameCodeStream(this);
            } else {
                  this.codeStream = new CodeStream(this);
            }
            this.initByteArrays();
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a boggus method.
       *
       * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
       */
00446       public void addAbstractMethod(
            AbstractMethodDeclaration method,
            MethodBinding methodBinding) {

            // force the modifiers to be public and abstract
            methodBinding.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;

            this.generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
            this.completeMethodInfo(methodAttributeOffset, attributeNumber);
      }

      /**
       * INTERNAL USE-ONLY
       * This methods generate all the attributes for the receiver.
       * For a class they could be:
       * - source file attribute
       * - inner classes attribute
       * - deprecated attribute
       */
00467       public void addAttributes() {
            // update the method count
            contents[methodCountOffset++] = (byte) (methodCount >> 8);
            contents[methodCountOffset] = (byte) methodCount;

            int attributeNumber = 0;
            // leave two bytes for the number of attributes and store the current offset
            int attributeOffset = contentsOffset;
            contentsOffset += 2;

            // source attribute
            if ((produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) {
                  String fullFileName =
                        new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
                  fullFileName = fullFileName.replace('\\', '/');
                  int lastIndex = fullFileName.lastIndexOf('/');
                  if (lastIndex != -1) {
                        fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
                  }
                  // check that there is enough space to write all the bytes for the field info corresponding
                  // to the @fieldBinding
                  if (contentsOffset + 8 >= contents.length) {
                        resizeContents(8);
                  }
                  int sourceAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SourceName);
                  contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
                  // The length of a source file attribute is 2. This is a fixed-length
                  // attribute
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 2;
                  // write the source file name
                  int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
                  contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
                  contents[contentsOffset++] = (byte) fileNameIndex;
                  attributeNumber++;
            }
            // Deprecated attribute
            if (referenceBinding.isDeprecated()) {
                  // check that there is enough space to write all the bytes for the field info corresponding
                  // to the @fieldBinding
                  if (contentsOffset + 6 >= contents.length) {
                        resizeContents(6);
                  }
                  int deprecatedAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
                  contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
                  // the length of a deprecated attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  attributeNumber++;
            }
            // Inner class attribute
            if (numberOfInnerClasses != 0) {
                  // Generate the inner class attribute
                  int exSize = 8 * numberOfInnerClasses + 8;
                  if (exSize + contentsOffset >= this.contents.length) {
                        resizeContents(exSize);
                  }
                  // Now we now the size of the attribute and the number of entries
                  // attribute name
                  int attributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
                  contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) attributeNameIndex;
                  int value = (numberOfInnerClasses << 3) + 2;
                  contents[contentsOffset++] = (byte) (value >> 24);
                  contents[contentsOffset++] = (byte) (value >> 16);
                  contents[contentsOffset++] = (byte) (value >> 8);
                  contents[contentsOffset++] = (byte) value;
                  contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
                  contents[contentsOffset++] = (byte) numberOfInnerClasses;
                  for (int i = 0; i < numberOfInnerClasses; i++) {
                        ReferenceBinding innerClass = innerClassesBindings[i];
                        int accessFlags = innerClass.getAccessFlags();
                        int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
                        // inner class index
                        contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
                        contents[contentsOffset++] = (byte) innerClassIndex;
                        // outer class index: anonymous and local have no outer class index
                        if (innerClass.isMemberType()) {
                              // member or member of local
                              int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
                              contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
                              contents[contentsOffset++] = (byte) outerClassIndex;
                        } else {
                              // equals to 0 if the innerClass is not a member type
                              contents[contentsOffset++] = 0;
                              contents[contentsOffset++] = 0;
                        }
                        // name index
                        if (!innerClass.isAnonymousType()) {
                              int nameIndex = constantPool.literalIndex(innerClass.sourceName());
                              contents[contentsOffset++] = (byte) (nameIndex >> 8);
                              contents[contentsOffset++] = (byte) nameIndex;
                        } else {
                              // equals to 0 if the innerClass is an anonymous type
                              contents[contentsOffset++] = 0;
                              contents[contentsOffset++] = 0;
                        }
                        // access flag
                        if (innerClass.isAnonymousType()) {
                              accessFlags &= ~ClassFileConstants.AccFinal;
                        } else if (innerClass.isMemberType() && innerClass.isInterface()) {
                              accessFlags |= ClassFileConstants.AccStatic; // implicitely static
                        }
                        contents[contentsOffset++] = (byte) (accessFlags >> 8);
                        contents[contentsOffset++] = (byte) accessFlags;
                  }
                  attributeNumber++;
            }
            // add signature attribute
            char[] genericSignature = referenceBinding.genericSignature();
            if (genericSignature != null) {
                  // check that there is enough space to write all the bytes for the field info corresponding
                  // to the @fieldBinding
                  if (contentsOffset + 8 >= contents.length) {
                        resizeContents(8);
                  }
                  int signatureAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SignatureName);
                  contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
                  // the length of a signature attribute is equals to 2
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 2;
                  int signatureIndex =
                        constantPool.literalIndex(genericSignature);
                  contents[contentsOffset++] = (byte) (signatureIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureIndex;
                  attributeNumber++;
            }
            if (targetJDK >= ClassFileConstants.JDK1_5
                        && this.referenceBinding.isNestedType()
                        && !this.referenceBinding.isMemberType()) {
                  // add enclosing method attribute (1.5 mode only)
                  if (contentsOffset + 10 >= contents.length) {
                        resizeContents(10);
                  }
                  int enclosingMethodAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
                  contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
                  // the length of a signature attribute is equals to 2
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 4;
                  
                  int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
                  contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
                  contents[contentsOffset++] = (byte) enclosingTypeIndex;
                  byte methodIndexByte1 = 0;
                  byte methodIndexByte2 = 0;
                  if (this.referenceBinding instanceof LocalTypeBinding) {
                        MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod;
                        if (methodBinding != null) {
                              int enclosingMethodIndex = constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature());
                              methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
                              methodIndexByte2 = (byte) enclosingMethodIndex;
                        }
                  }
                  contents[contentsOffset++] = methodIndexByte1;
                  contents[contentsOffset++] = methodIndexByte2;
                  attributeNumber++;                  
            }
            if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
                  TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
                  if (typeDeclaration != null) {
                        final Annotation[] annotations = typeDeclaration.annotations;
                        if (annotations != null) {
                              attributeNumber += generateRuntimeAnnotations(annotations);
                        }
                  }
            }
            
            if (this.referenceBinding.isHierarchyInconsistent()) {
                  // add an attribute for inconsistent hierarchy
                  if (contentsOffset + 6 >= contents.length) {
                        resizeContents(6);
                  }
                  int inconsistentHierarchyNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.InconsistentHierarchy);
                  contents[contentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8);
                  contents[contentsOffset++] = (byte) inconsistentHierarchyNameIndex;
                  // the length of an inconsistent hierarchy attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  attributeNumber++;
            }
            // update the number of attributes
            if (attributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            contents[attributeOffset++] = (byte) (attributeNumber >> 8);
            contents[attributeOffset] = (byte) attributeNumber;

            // resynchronize all offsets of the classfile
            header = constantPool.poolContent;
            headerOffset = constantPool.currentOffset;
            int constantPoolCount = constantPool.currentIndex;
            header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
            header[constantPoolOffset] = (byte) constantPoolCount;
      }

      /**
       * INTERNAL USE-ONLY
       * This methods generate all the default abstract method infos that correpond to
       * the abstract methods inherited from superinterfaces.
       */
00687       public void addDefaultAbstractMethods() { // default abstract methods
            MethodBinding[] defaultAbstractMethods =
                  referenceBinding.getDefaultAbstractMethods();
            for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
                  generateMethodInfoHeader(defaultAbstractMethods[i]);
                  int methodAttributeOffset = contentsOffset;
                  int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
                  completeMethodInfo(methodAttributeOffset, attributeNumber);
            }
      }
      
      private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
            int attributesNumber = 0;
            // 4.7.2 only static constant fields get a ConstantAttribute
            // Generate the constantValueAttribute
            Constant fieldConstant = fieldBinding.constant();
            if (fieldConstant != Constant.NotAConstant){
                  if (contentsOffset + 8 >= contents.length) {
                        resizeContents(8);
                  }
                  // Now we generate the constant attribute corresponding to the fieldBinding
                  int constantValueNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
                  contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
                  contents[contentsOffset++] = (byte) constantValueNameIndex;
                  // The attribute length = 2 in case of a constantValue attribute
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 2;
                  attributesNumber++;
                  // Need to add the constant_value_index
                  switch (fieldConstant.typeID()) {
                        case T_boolean :
                              int booleanValueIndex =
                                    constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
                              contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
                              contents[contentsOffset++] = (byte) booleanValueIndex;
                              break;
                        case T_byte :
                        case T_char :
                        case T_int :
                        case T_short :
                              int integerValueIndex =
                                    constantPool.literalIndex(fieldConstant.intValue());
                              contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                              contents[contentsOffset++] = (byte) integerValueIndex;
                              break;
                        case T_float :
                              int floatValueIndex =
                                    constantPool.literalIndex(fieldConstant.floatValue());
                              contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
                              contents[contentsOffset++] = (byte) floatValueIndex;
                              break;
                        case T_double :
                              int doubleValueIndex =
                                    constantPool.literalIndex(fieldConstant.doubleValue());
                              contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
                              contents[contentsOffset++] = (byte) doubleValueIndex;
                              break;
                        case T_long :
                              int longValueIndex =
                                    constantPool.literalIndex(fieldConstant.longValue());
                              contents[contentsOffset++] = (byte) (longValueIndex >> 8);
                              contents[contentsOffset++] = (byte) longValueIndex;
                              break;
                        case T_JavaLangString :
                              int stringValueIndex =
                                    constantPool.literalIndex(
                                          ((StringConstant) fieldConstant).stringValue());
                              if (stringValueIndex == -1) {
                                    if (!creatingProblemType) {
                                          // report an error and abort: will lead to a problem type classfile creation
                                          TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
                                          FieldDeclaration[] fieldDecls = typeDeclaration.fields;
                                          for (int i = 0, max = fieldDecls.length; i < max; i++) {
                                                if (fieldDecls[i].binding == fieldBinding) {
                                                      // problem should abort
                                                      typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
                                                            fieldDecls[i]);
                                                }
                                          }
                                    } else {
                                          // already inside a problem type creation : no constant for this field
                                          contentsOffset = fieldAttributeOffset;
                                    }
                              } else {
                                    contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
                                    contents[contentsOffset++] = (byte) stringValueIndex;
                              }
                  }
            }
            if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
                  if (contentsOffset + 6 >= contents.length) {
                        resizeContents(6);
                  }
                  int syntheticAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
                  contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
                  // the length of a synthetic attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  attributesNumber++;
            }
            if (fieldBinding.isDeprecated()) {
                  if (contentsOffset + 6 >= contents.length) {
                        resizeContents(6);
                  }
                  int deprecatedAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
                  contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
                  // the length of a deprecated attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  attributesNumber++;
            }
            // add signature attribute
            char[] genericSignature = fieldBinding.genericSignature();
            if (genericSignature != null) {
                  // check that there is enough space to write all the bytes for the field info corresponding
                  // to the @fieldBinding
                  if (contentsOffset + 8 >= contents.length) {
                        resizeContents(8);
                  }
                  int signatureAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SignatureName);
                  contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
                  // the length of a signature attribute is equals to 2
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 2;
                  int signatureIndex =
                        constantPool.literalIndex(genericSignature);
                  contents[contentsOffset++] = (byte) (signatureIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureIndex;
                  attributesNumber++;
            }
            if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
                  FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
                  if (fieldDeclaration != null) {
                        Annotation[] annotations = fieldDeclaration.annotations;
                        if (annotations != null) {
                              attributesNumber += generateRuntimeAnnotations(annotations);
                        }
                  }
            }
            return attributesNumber;
      }

      /**
       * INTERNAL USE-ONLY
       * This methods generates the bytes for the given field binding
       * @param fieldBinding the given field binding
       */
00849       private void addFieldInfo(FieldBinding fieldBinding) {
            // check that there is enough space to write all the bytes for the field info corresponding
            // to the @fieldBinding
            if (contentsOffset + 8 >= contents.length) {
                  resizeContents(8);
            }
            // Now we can generate all entries into the byte array
            // First the accessFlags
            int accessFlags = fieldBinding.getAccessFlags();
            if (targetJDK < ClassFileConstants.JDK1_5) {
                // pre 1.5, synthetic was an attribute, not a modifier
                accessFlags &= ~ClassFileConstants.AccSynthetic;
            }           
            contents[contentsOffset++] = (byte) (accessFlags >> 8);
            contents[contentsOffset++] = (byte) accessFlags;
            // Then the nameIndex
            int nameIndex = constantPool.literalIndex(fieldBinding.name);
            contents[contentsOffset++] = (byte) (nameIndex >> 8);
            contents[contentsOffset++] = (byte) nameIndex;
            // Then the descriptorIndex
            int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
            contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
            contents[contentsOffset++] = (byte) descriptorIndex;
            int fieldAttributeOffset = contentsOffset;
            int attributeNumber = 0;
            // leave some space for the number of attributes
            contentsOffset += 2;
            attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
            if (contentsOffset + 2 >= contents.length) {
                  resizeContents(2);
            }
            contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[fieldAttributeOffset] = (byte) attributeNumber;
      }
      /**
       * INTERNAL USE-ONLY
       * This methods generate all the fields infos for the receiver.
       * This includes:
       * - a field info for each defined field of that class
       * - a field info for each synthetic field (e.g. this$0)
       */
      /**
       * INTERNAL USE-ONLY
       * This methods generate all the fields infos for the receiver.
       * This includes:
       * - a field info for each defined field of that class
       * - a field info for each synthetic field (e.g. this$0)
       */
00897       public void addFieldInfos() {
            SourceTypeBinding currentBinding = referenceBinding;
            FieldBinding[] syntheticFields = currentBinding.syntheticFields();
            int fieldCount =
                  currentBinding.fieldCount()
                        + (syntheticFields == null ? 0 : syntheticFields.length);

            // write the number of fields
            if (fieldCount > 0xFFFF) {
                  referenceBinding.scope.problemReporter().tooManyFields(referenceBinding.scope.referenceType());
            }
            contents[contentsOffset++] = (byte) (fieldCount >> 8);
            contents[contentsOffset++] = (byte) fieldCount;

            FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields;
            for (int i = 0, max = fieldDecls == null ? 0 : fieldDecls.length; i < max; i++) {
                  FieldDeclaration fieldDecl = fieldDecls[i];
                  if (fieldDecl.binding != null) {
                        addFieldInfo(fieldDecl.binding);
                  }
            }

            if (syntheticFields != null) {
                  for (int i = 0, max = syntheticFields.length; i < max; i++) {
                        addFieldInfo(syntheticFields[i]);
                  }
            }
      }

      /**
       * INTERNAL USE-ONLY
       * This methods stores the bindings for each inner class. They will be used to know which entries
       * have to be generated for the inner classes attributes.
       * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
       */
00932       private void addInnerClasses(ReferenceBinding refBinding) {
            // check first if that reference binding is there
            for (int i = 0; i < numberOfInnerClasses; i++) {
                  if (innerClassesBindings[i] == refBinding)
                        return;
            }
            int length = innerClassesBindings.length;
            if (numberOfInnerClasses == length) {
                  System.arraycopy(
                        innerClassesBindings,
                        0,
                        innerClassesBindings = new ReferenceBinding[length * 2],
                        0,
                        length);
            }
            innerClassesBindings[numberOfInnerClasses++] = refBinding;
      }

      private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) {
            // always clear the strictfp/native/abstract bit for a problem method
            generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
            int methodAttributeOffset = contentsOffset;
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            
            // Code attribute
            attributeNumber++;
            
            int codeAttributeOffset = contentsOffset;
            generateCodeAttributeHeader();
            StringBuffer buffer = new StringBuffer(25);
            buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
            buffer.insert(0, Messages.compilation_unresolvedProblem);
            String problemString = buffer.toString();
            
            codeStream.init(this);
            codeStream.preserveUnusedLocals = true;
            codeStream.initializeMaxLocals(methodBinding);

            // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
            codeStream.generateCodeAttributeForProblemMethod(problemString);
                        
            completeCodeAttributeForMissingAbstractProblemMethod(
                  methodBinding,
                  codeAttributeOffset,
                  compilationResult.getLineSeparatorPositions(),
                  problem.getSourceLineNumber());
                  
            completeMethodInfo(methodAttributeOffset, attributeNumber);
      }
      
      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem clinit method info that correspond to a boggus method.
       *
       * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
       */
00988       public void addProblemClinit(CategorizedProblem[] problems) {
            generateMethodInfoHeaderForClinit();
            // leave two spaces for the number of attributes
            contentsOffset -= 2;
            int attributeOffset = contentsOffset;
            contentsOffset += 2;
            int attributeNumber = 0;

            int codeAttributeOffset = contentsOffset;
            generateCodeAttributeHeader();
            codeStream.resetForProblemClinit(this);
            String problemString = "" ; //$NON-NLS-1$
            int problemLine = 0;
            if (problems != null) {
                  int max = problems.length;
                  StringBuffer buffer = new StringBuffer(25);
                  int count = 0;
                  for (int i = 0; i < max; i++) {
                        CategorizedProblem problem = problems[i];
                        if ((problem != null) && (problem.isError())) {
                              buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
                              count++;
                              if (problemLine == 0) {
                                    problemLine = problem.getSourceLineNumber();
                              }
                              problems[i] = null;
                        }
                  } // insert the top line afterwards, once knowing how many problems we have to consider
                  if (count > 1) {
                        buffer.insert(0, Messages.compilation_unresolvedProblems);
                  } else {
                        buffer.insert(0, Messages.compilation_unresolvedProblem);
                  }
                  problemString = buffer.toString();
            }

            // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
            codeStream.generateCodeAttributeForProblemMethod(problemString);
            attributeNumber++; // code attribute
            completeCodeAttributeForClinit(
                  codeAttributeOffset,
                  problemLine);
            if (contentsOffset + 2 >= contents.length) {
                  resizeContents(2);
            }
            contents[attributeOffset++] = (byte) (attributeNumber >> 8);
            contents[attributeOffset] = (byte) attributeNumber;
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a boggus constructor.
       *
       * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
       * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
       */
01045       public void addProblemConstructor(
            AbstractMethodDeclaration method,
            MethodBinding methodBinding,
            CategorizedProblem[] problems) {

            // always clear the strictfp/native/abstract bit for a problem method
            generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
            int methodAttributeOffset = contentsOffset;
            int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
            
            // Code attribute
            attributeNumber++;
            int codeAttributeOffset = contentsOffset;
            generateCodeAttributeHeader();
            codeStream.reset(method, this);
            String problemString = "" ; //$NON-NLS-1$
            int problemLine = 0;
            if (problems != null) {
                  int max = problems.length;
                  StringBuffer buffer = new StringBuffer(25);
                  int count = 0;
                  for (int i = 0; i < max; i++) {
                        CategorizedProblem problem = problems[i];
                        if ((problem != null) && (problem.isError())) {
                              buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
                              count++;
                              if (problemLine == 0) {
                                    problemLine = problem.getSourceLineNumber();
                              }
                        }
                  } // insert the top line afterwards, once knowing how many problems we have to consider
                  if (count > 1) {
                        buffer.insert(0, Messages.compilation_unresolvedProblems);
                  } else {
                        buffer.insert(0, Messages.compilation_unresolvedProblem);
                  }
                  problemString = buffer.toString();
            }

            // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
            codeStream.generateCodeAttributeForProblemMethod(problemString);
            completeCodeAttributeForProblemMethod(
                  method,
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions(),
                  problemLine);
            completeMethodInfo(methodAttributeOffset, attributeNumber);
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a boggus constructor.
       * Reset the position inside the contents byte array to the savedOffset.
       *
       * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
       * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
       * @param savedOffset <CODE>int</CODE>
       */
01109       public void addProblemConstructor(
            AbstractMethodDeclaration method,
            MethodBinding methodBinding,
            CategorizedProblem[] problems,
            int savedOffset) {
            // we need to move back the contentsOffset to the value at the beginning of the method
            contentsOffset = savedOffset;
            methodCount--; // we need to remove the method that causes the problem
            addProblemConstructor(method, methodBinding, problems);
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a boggus method.
       *
       * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
       * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
       */
01128       public void addProblemMethod(
            AbstractMethodDeclaration method,
            MethodBinding methodBinding,
            CategorizedProblem[] problems) {
            if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
                  method.abort(ProblemSeverities.AbortType, null);
            }
            // always clear the strictfp/native/abstract bit for a problem method
            generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
            int methodAttributeOffset = contentsOffset;
            int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
            
            // Code attribute
            attributeNumber++;
            
            int codeAttributeOffset = contentsOffset;
            generateCodeAttributeHeader();
            codeStream.reset(method, this);
            String problemString = "" ; //$NON-NLS-1$
            int problemLine = 0;
            if (problems != null) {
                  int max = problems.length;
                  StringBuffer buffer = new StringBuffer(25);
                  int count = 0;
                  for (int i = 0; i < max; i++) {
                        CategorizedProblem problem = problems[i];
                        if ((problem != null)
                              && (problem.isError())
                              && (problem.getSourceStart() >= method.declarationSourceStart)
                              && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
                              buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
                              count++;
                              if (problemLine == 0) {
                                    problemLine = problem.getSourceLineNumber();
                              }
                              problems[i] = null;
                        }
                  } // insert the top line afterwards, once knowing how many problems we have to consider
                  if (count > 1) {
                        buffer.insert(0, Messages.compilation_unresolvedProblems);
                  } else {
                        buffer.insert(0, Messages.compilation_unresolvedProblem);
                  }
                  problemString = buffer.toString();
            }

            // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
            codeStream.generateCodeAttributeForProblemMethod(problemString);
            completeCodeAttributeForProblemMethod(
                  method,
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions(),
                  problemLine);
            completeMethodInfo(methodAttributeOffset, attributeNumber);
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a boggus method.
       * Reset the position inside the contents byte array to the savedOffset.
       *
       * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
       * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
       * @param savedOffset <CODE>int</CODE>
       */
01199       public void addProblemMethod(
            AbstractMethodDeclaration method,
            MethodBinding methodBinding,
            CategorizedProblem[] problems,
            int savedOffset) {
            // we need to move back the contentsOffset to the value at the beginning of the method
            contentsOffset = savedOffset;
            methodCount--; // we need to remove the method that causes the problem
            addProblemMethod(method, methodBinding, problems);
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for all the special method infos.
       * They are:
       * - synthetic access methods
       * - default abstract methods
       */
01217       public void addSpecialMethods() {
          
            // add all methods (default abstract methods and synthetic)

            // default abstract methods
            generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);

            MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
            for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
                  generateMethodInfoHeader(defaultAbstractMethods[i]);
                  int methodAttributeOffset = contentsOffset;
                  int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
                  completeMethodInfo(methodAttributeOffset, attributeNumber);
            }
            // add synthetic methods infos
            SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
            if (syntheticMethods != null) {
                  for (int i = 0, max = syntheticMethods.length; i < max; i++) {
                        SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
                        switch (syntheticMethod.kind) {
                              case SyntheticMethodBinding.FieldReadAccess :
                                    // generate a method info to emulate an reading access to
                                    // a non-accessible field
                                    addSyntheticFieldReadAccessMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.FieldWriteAccess :
                                    // generate a method info to emulate an writing access to
                                    // a non-accessible field
                                    addSyntheticFieldWriteAccessMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.MethodAccess :
                              case SyntheticMethodBinding.SuperMethodAccess :
                              case SyntheticMethodBinding.BridgeMethod :
                                    // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
                                    addSyntheticMethodAccessMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.ConstructorAccess :
                                    // generate a method info to emulate an access to a non-accessible constructor
                                    addSyntheticConstructorAccessMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.EnumValues :
                                    // generate a method info to define <enum>#values()
                                    addSyntheticEnumValuesMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.EnumValueOf :
                                    // generate a method info to define <enum>#valueOf(String)
                                    addSyntheticEnumValueOfMethod(syntheticMethod);
                                    break;
                              case SyntheticMethodBinding.SwitchTable :
                                    // generate a method info to define the switch table synthetic method
                                    addSyntheticSwitchTable(syntheticMethod);
                        }
                  }
            }
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the bytes for a synthetic method that provides an access to a private constructor.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */
01279       public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }
            
      /**
       * INTERNAL USE-ONLY
       *  Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */   
01309       public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;               
      }

      /**
       * INTERNAL USE-ONLY
       *  Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */   
01339       public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForEnumValues(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;         
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a synthetic method that
       * generate an read access to a private field.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */
01370       public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }
      /**
       * INTERNAL USE-ONLY
       * Generate the byte for a problem method info that correspond to a synthetic method that
       * generate an write access to a private field.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */
01400       public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the bytes for a synthetic method that provides access to a private method.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
       */
01430       public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }

      public void addSyntheticSwitchTable(SyntheticMethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding);
            int methodAttributeOffset = this.contentsOffset;
            // this will add exception attribute, synthetic attribute, deprecated attribute,...
            int attributeNumber = generateMethodInfoAttribute(methodBinding);
            // Code attribute
            int codeAttributeOffset = contentsOffset;
            attributeNumber++; // add code attribute
            generateCodeAttributeHeader();
            codeStream.init(this);
            codeStream.generateSyntheticBodyForSwitchTable(methodBinding);
            completeCodeAttributeForSyntheticMethod(
                  true,
                  methodBinding,
                  codeAttributeOffset,
                  ((SourceTypeBinding) methodBinding.declaringClass)
                        .scope
                        .referenceCompilationUnit()
                        .compilationResult
                        .getLineSeparatorPositions());
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       *
       * @param codeAttributeOffset <CODE>int</CODE>
       */
01491       public void completeCodeAttribute(int codeAttributeOffset) {
            // reinitialize the localContents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // 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...
            int code_length = codeStream.position;
            if (code_length > 65535) {
                  codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
                        codeStream.methodDeclaration);
            }
            if (localContentsOffset + 20 >= this.contents.length) {
                  resizeContents(20);
            }
            int max_stack = codeStream.stackMax;
            this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            this.contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            this.contents[codeAttributeOffset + 9] = (byte) max_locals;
            this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            this.contents[codeAttributeOffset + 13] = (byte) code_length;

            // write the exception table
            ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
            int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
            for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
                  exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2; 
            }
            int exSize = exceptionHandlersCount * 8 + 2;
            if (exSize + localContentsOffset >= this.contents.length) {
                  resizeContents(exSize);
            }
            // there is no exception table, so we need to offset by 2 the current offset and move 
            // on the attribute generation
            this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
            this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
            for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
                  ExceptionLabel exceptionLabel = exceptionLabels[i];
                  if (exceptionLabel != null) {
                        int iRange = 0, maxRange = exceptionLabel.count;
                        if ((maxRange & 1) != 0) {
                              codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
                                          Messages.bind(Messages.abort_invalidExceptionAttribute, new String(codeStream.methodDeclaration.selector)), 
                                          codeStream.methodDeclaration);
                        }
                        while  (iRange < maxRange) {
                              int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
                              this.contents[localContentsOffset++] = (byte) (start >> 8);
                              this.contents[localContentsOffset++] = (byte) start;
                              int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
                              this.contents[localContentsOffset++] = (byte) (end >> 8);
                              this.contents[localContentsOffset++] = (byte) end;
                              int handlerPC = exceptionLabel.position;
                              this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
                              this.contents[localContentsOffset++] = (byte) handlerPC;
                              if (exceptionLabel.exceptionType == null) {
                                    // any exception handler
                                    this.contents[localContentsOffset++] = 0;
                                    this.contents[localContentsOffset++] = 0;
                              } else {
                                    int nameIndex;
                                    if (exceptionLabel.exceptionType == TypeBinding.NULL) {
                                          /* represents ClassNotFoundException, see class literal access*/
                                          nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
                                    } else {
                                          nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName());
                                    }
                                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) nameIndex;
                              }
                        }
                  }
            }
            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0;
            // leave two bytes for the attribute_length
            localContentsOffset += 2;
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            // first we handle the linenumber attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  /* Create and add the line number attribute (used for debugging) 
                   * Build the pairs of:
                   *    (bytecodePC lineNumber)
                   * according to the table of start line indexes and the pcToSourceMap table
                   * contained into the codestream
                   */
                  int[] pcToSourceMapTable;
                  if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
                        && (codeStream.pcToSourceMapSize != 0)) {
                        int lineNumberNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                        int lineNumberTableOffset = localContentsOffset;
                        localContentsOffset += 6;
                        // leave space for attribute_length and line_number_table_length
                        int numberOfEntries = 0;
                        int length = codeStream.pcToSourceMapSize;
                        for (int i = 0; i < length;) {
                              // write the entry
                              if (localContentsOffset + 4 >= this.contents.length) {
                                    resizeContents(4);
                              }
                              int pc = pcToSourceMapTable[i++];
                              this.contents[localContentsOffset++] = (byte) (pc >> 8);
                              this.contents[localContentsOffset++] = (byte) pc;
                              int lineNumber = pcToSourceMapTable[i++];
                              this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
                              this.contents[localContentsOffset++] = (byte) lineNumber;
                              numberOfEntries++;
                        }
                        // now we change the size of the line number attribute
                        int lineNumberAttr_length = numberOfEntries * 4 + 2;
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
                        this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
                        this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
                        attributeNumber++;
                  }
            }
            // then we do the local variable attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
                  int numberOfEntries = 0;
                  int localVariableNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
                  final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
                  int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
                  for (int i = 0; i < codeStream.allLocalsCounter; i++) {
                        maxOfEntries += 10 * codeStream.locals[i].initializationCount;
                  }
                  // reserve enough space
                  if (localContentsOffset + maxOfEntries >= this.contents.length) {
                        resizeContents(maxOfEntries);
                  }
                  this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
                  int localVariableTableOffset = localContentsOffset;
                  // leave space for attribute_length and local_variable_table_length
                  localContentsOffset += 6;
                  int nameIndex;
                  int descriptorIndex;
                  SourceTypeBinding declaringClassBinding = null;
                  if (!methodDeclarationIsStatic) {
                        numberOfEntries++;
                        this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
                        this.contents[localContentsOffset++] = 0;
                        this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                        this.contents[localContentsOffset++] = (byte) code_length;
                        nameIndex = constantPool.literalIndex(ConstantPool.This);
                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) nameIndex;
                        declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
                        descriptorIndex =
                              constantPool.literalIndex(
                                    declaringClassBinding.signature());
                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
                        this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
                        this.contents[localContentsOffset++] = 0;
                  }
                  // used to remember the local variable with a generic type
                  int genericLocalVariablesCounter = 0;
                  LocalVariableBinding[] genericLocalVariables = null;
                  int numberOfGenericEntries = 0;
                  
                  for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                        LocalVariableBinding localVariable = codeStream.locals[i];
                        final TypeBinding localVariableTypeBinding = localVariable.type;
                        boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
                        if (localVariable.initializationCount != 0 && isParameterizedType) {
                              if (genericLocalVariables == null) {
                                    // we cannot have more than max locals
                                    genericLocalVariables = new LocalVariableBinding[max];
                              }
                              genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
                        }
                        for (int j = 0; j < localVariable.initializationCount; j++) {
                              int startPC = localVariable.initializationPCs[j << 1];
                              int endPC = localVariable.initializationPCs[(j << 1) + 1];
                              if (startPC != endPC) { // only entries for non zero length
                                    if (endPC == -1) {
                                          localVariable.declaringScope.problemReporter().abortDueToInternalError(
                                                      Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)), 
                                                      (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
                                    }
                                    if (isParameterizedType) {
                                          numberOfGenericEntries++;
                                    }
                                    // now we can safely add the local entry
                                    numberOfEntries++;
                                    this.contents[localContentsOffset++] = (byte) (startPC >> 8);
                                    this.contents[localContentsOffset++] = (byte) startPC;
                                    int length = endPC - startPC;
                                    this.contents[localContentsOffset++] = (byte) (length >> 8);
                                    this.contents[localContentsOffset++] = (byte) length;
                                    nameIndex = constantPool.literalIndex(localVariable.name);
                                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) nameIndex;
                                    descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                    int resolvedPosition = localVariable.resolvedPosition;
                                    this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                    this.contents[localContentsOffset++] = (byte) resolvedPosition;
                              }
                        }
                  }
                  int value = numberOfEntries * 10 + 2;
                  this.contents[localVariableTableOffset++] = (byte) (value >> 24);
                  this.contents[localVariableTableOffset++] = (byte) (value >> 16);
                  this.contents[localVariableTableOffset++] = (byte) (value >> 8);
                  this.contents[localVariableTableOffset++] = (byte) value;
                  this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                  this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                  attributeNumber++;
                  
                  final boolean currentInstanceIsGeneric = 
                        !methodDeclarationIsStatic
                        && declaringClassBinding != null 
                        && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
                  if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
                        // add the local variable type table attribute
                        numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
                        maxOfEntries = 8 + numberOfGenericEntries * 10;
                        // reserve enough space
                        if (localContentsOffset + maxOfEntries >= this.contents.length) {
                              resizeContents(maxOfEntries);
                        }
                        int localVariableTypeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
                        this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
                        value = numberOfGenericEntries * 10 + 2;
                        this.contents[localContentsOffset++] = (byte) (value >> 24);
                        this.contents[localContentsOffset++] = (byte) (value >> 16);
                        this.contents[localContentsOffset++] = (byte) (value >> 8);
                        this.contents[localContentsOffset++] = (byte) value;
                        this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
                        this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
                        if (currentInstanceIsGeneric) {
                              this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                              this.contents[localContentsOffset++] = (byte) code_length;
                              nameIndex = constantPool.literalIndex(ConstantPool.This);
                              this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) nameIndex;
                              descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
                              this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) descriptorIndex;
                              this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
                              this.contents[localContentsOffset++] = 0;
                        }
                        
                        for (int i = 0; i < genericLocalVariablesCounter; i++) {
                              LocalVariableBinding localVariable = genericLocalVariables[i];
                              for (int j = 0; j < localVariable.initializationCount; j++) {
                                    int startPC = localVariable.initializationPCs[j << 1];
                                    int endPC = localVariable.initializationPCs[(j << 1) + 1];
                                    if (startPC != endPC) {
                                          // only entries for non zero length
                                          // now we can safely add the local entry
                                          this.contents[localContentsOffset++] = (byte) (startPC >> 8);
                                          this.contents[localContentsOffset++] = (byte) startPC;
                                          int length = endPC - startPC;
                                          this.contents[localContentsOffset++] = (byte) (length >> 8);
                                          this.contents[localContentsOffset++] = (byte) length;
                                          nameIndex = constantPool.literalIndex(localVariable.name);
                                          this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) nameIndex;
                                          descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
                                          this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                          int resolvedPosition = localVariable.resolvedPosition;
                                          this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                          this.contents[localContentsOffset++] = (byte) resolvedPosition;
                                    }
                              }
                        }
                        attributeNumber++;
                  }
            }

            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        int stackMapTableAttributeOffset = localContentsOffset;
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        if (localContentsOffset + 4 >= this.contents.length) {
                              resizeContents(4);
                        }
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        if (localContentsOffset + 2 >= this.contents.length) {
                              resizeContents(2);
                        }
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              // generate current frame
                              // need to find differences between the current frame and the previous frame
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            byte tag = (byte) info.tag;
                                                            this.contents[localContentsOffset++] = tag;
                                                            switch (tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            byte tag = (byte) info.tag;
                                                            this.contents[localContentsOffset++] = tag;
                                                            switch (tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        if (numberOfFrames != 0) {
                              this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                              this.contents[numberOfFramesOffset] = (byte) numberOfFrames;
      
                              int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                              this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                              this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                              this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                              this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                              attributeNumber++;
                        } else {
                              localContentsOffset = stackMapTableAttributeOffset;
                        }
                  }
            }

            this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;

            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       *
       * @param codeAttributeOffset <CODE>int</CODE>
       */
02171       public void completeCodeAttributeForClinit(int codeAttributeOffset) {
            // reinitialize the contents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // codeAttributeOffset is the position inside contents 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...
            int code_length = codeStream.position;
            if (code_length > 65535) {
                  codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
                        codeStream.methodDeclaration.scope.referenceType());
            }
            if (localContentsOffset + 20 >= this.contents.length) {
                  resizeContents(20);
            }
            int max_stack = codeStream.stackMax;
            this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            this.contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            this.contents[codeAttributeOffset + 9] = (byte) max_locals;
            this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            this.contents[codeAttributeOffset + 13] = (byte) code_length;

            // write the exception table
            ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
            int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
            for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
                  exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2; 
            }
            int exSize = exceptionHandlersCount * 8 + 2;
            if (exSize + localContentsOffset >= this.contents.length) {
                  resizeContents(exSize);
            }
            // there is no exception table, so we need to offset by 2 the current offset and move 
            // on the attribute generation
            this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
            this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
            for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
                  ExceptionLabel exceptionLabel = exceptionLabels[i];
                  if (exceptionLabel != null) {
                        int iRange = 0, maxRange = exceptionLabel.count;
                        if ((maxRange & 1) != 0) {
                              codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError(
                                          Messages.bind(Messages.abort_invalidExceptionAttribute, new String(codeStream.methodDeclaration.selector)), 
                                          codeStream.methodDeclaration);
                        }                       
                        while  (iRange < maxRange) {
                              int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
                              this.contents[localContentsOffset++] = (byte) (start >> 8);
                              this.contents[localContentsOffset++] = (byte) start;
                              int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
                              this.contents[localContentsOffset++] = (byte) (end >> 8);
                              this.contents[localContentsOffset++] = (byte) end;
                              int handlerPC = exceptionLabel.position;
                              this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
                              this.contents[localContentsOffset++] = (byte) handlerPC;
                              if (exceptionLabel.exceptionType == null) {
                                    // any exception handler
                                    this.contents[localContentsOffset++] = 0;
                                    this.contents[localContentsOffset++] = 0;
                              } else {
                                    int nameIndex;
                                    if (exceptionLabel.exceptionType == TypeBinding.NULL) {
                                          /* represents denote ClassNotFoundException, see class literal access*/
                                          nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
                                    } else {
                                          nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName());
                                    }
                                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) nameIndex;
                              }
                        }
                  }
            }
            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0;
            // leave two bytes for the attribute_length
            localContentsOffset += 2;
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            // first we handle the linenumber attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  /* Create and add the line number attribute (used for debugging) 
                   * Build the pairs of:
                   *    (bytecodePC lineNumber)
                   * according to the table of start line indexes and the pcToSourceMap table
                   * contained into the codestream
                   */
                  int[] pcToSourceMapTable;
                  if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
                        && (codeStream.pcToSourceMapSize != 0)) {
                        int lineNumberNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                        int lineNumberTableOffset = localContentsOffset;
                        localContentsOffset += 6;
                        // leave space for attribute_length and line_number_table_length
                        int numberOfEntries = 0;
                        int length = codeStream.pcToSourceMapSize;
                        for (int i = 0; i < length;) {
                              // write the entry
                              if (localContentsOffset + 4 >= this.contents.length) {
                                    resizeContents(4);
                              }
                              int pc = pcToSourceMapTable[i++];
                              this.contents[localContentsOffset++] = (byte) (pc >> 8);
                              this.contents[localContentsOffset++] = (byte) pc;
                              int lineNumber = pcToSourceMapTable[i++];
                              this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
                              this.contents[localContentsOffset++] = (byte) lineNumber;
                              numberOfEntries++;
                        }
                        // now we change the size of the line number attribute
                        int lineNumberAttr_length = numberOfEntries * 4 + 2;
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
                        this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
                        this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
                        this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
                        attributeNumber++;
                  }
            }
            // then we do the local variable attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
                  int numberOfEntries = 0;
                  //          codeAttribute.addLocalVariableTableAttribute(this);
                  if ((codeStream.pcToSourceMap != null)
                        && (codeStream.pcToSourceMapSize != 0)) {
                        int localVariableNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
                        int localVariableTableOffset = localContentsOffset;
                        localContentsOffset += 6;

                        // leave space for attribute_length and local_variable_table_length
                        int nameIndex;
                        int descriptorIndex;

                        // used to remember the local variable with a generic type
                        int genericLocalVariablesCounter = 0;
                        LocalVariableBinding[] genericLocalVariables = null;
                        int numberOfGenericEntries = 0;

                        for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                              LocalVariableBinding localVariable = codeStream.locals[i];
                              final TypeBinding localVariableTypeBinding = localVariable.type;
                              boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
                              if (localVariable.initializationCount != 0 && isParameterizedType) {
                                    if (genericLocalVariables == null) {
                                          // we cannot have more than max locals
                                          genericLocalVariables = new LocalVariableBinding[max];
                                    }
                                    genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
                              }
                              for (int j = 0; j < localVariable.initializationCount; j++) {
                                    int startPC = localVariable.initializationPCs[j << 1];
                                    int endPC = localVariable.initializationPCs[(j << 1) + 1];
                                    if (startPC != endPC) { // only entries for non zero length
                                          if (endPC == -1) {
                                                localVariable.declaringScope.problemReporter().abortDueToInternalError(
                                                      Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)), 
                                                      (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
                                          }
                                          if (localContentsOffset + 10 >= this.contents.length) {
                                                resizeContents(10);
                                          }
                                          // now we can safely add the local entry
                                          numberOfEntries++;
                                          if (isParameterizedType) {
                                                numberOfGenericEntries++;
                                          }
                                          this.contents[localContentsOffset++] = (byte) (startPC >> 8);
                                          this.contents[localContentsOffset++] = (byte) startPC;
                                          int length = endPC - startPC;
                                          this.contents[localContentsOffset++] = (byte) (length >> 8);
                                          this.contents[localContentsOffset++] = (byte) length;
                                          nameIndex = constantPool.literalIndex(localVariable.name);
                                          this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) nameIndex;
                                          descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                          this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                          int resolvedPosition = localVariable.resolvedPosition;
                                          this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                          this.contents[localContentsOffset++] = (byte) resolvedPosition;
                                    }
                              }
                        }
                        int value = numberOfEntries * 10 + 2;
                        this.contents[localVariableTableOffset++] = (byte) (value >> 24);
                        this.contents[localVariableTableOffset++] = (byte) (value >> 16);
                        this.contents[localVariableTableOffset++] = (byte) (value >> 8);
                        this.contents[localVariableTableOffset++] = (byte) value;
                        this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                        attributeNumber++;

                        if (genericLocalVariablesCounter != 0) {
                              // add the local variable type table attribute
                              // reserve enough space
                              int maxOfEntries = 8 + numberOfGenericEntries * 10;

                              if (localContentsOffset + maxOfEntries >= this.contents.length) {
                                    resizeContents(maxOfEntries);
                              }
                              int localVariableTypeNameIndex =
                                    constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
                              this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
                              value = numberOfGenericEntries * 10 + 2;
                              this.contents[localContentsOffset++] = (byte) (value >> 24);
                              this.contents[localContentsOffset++] = (byte) (value >> 16);
                              this.contents[localContentsOffset++] = (byte) (value >> 8);
                              this.contents[localContentsOffset++] = (byte) value;
                              this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
                              this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
                              for (int i = 0; i < genericLocalVariablesCounter; i++) {
                                    LocalVariableBinding localVariable = genericLocalVariables[i];
                                    for (int j = 0; j < localVariable.initializationCount; j++) {
                                          int startPC = localVariable.initializationPCs[j << 1];
                                          int endPC = localVariable.initializationPCs[(j << 1) + 1];
                                          if (startPC != endPC) { // only entries for non zero length
                                                // now we can safely add the local entry
                                                this.contents[localContentsOffset++] = (byte) (startPC >> 8);
                                                this.contents[localContentsOffset++] = (byte) startPC;
                                                int length = endPC - startPC;
                                                this.contents[localContentsOffset++] = (byte) (length >> 8);
                                                this.contents[localContentsOffset++] = (byte) length;
                                                nameIndex = constantPool.literalIndex(localVariable.name);
                                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                this.contents[localContentsOffset++] = (byte) nameIndex;
                                                descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
                                                this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                                this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                                int resolvedPosition = localVariable.resolvedPosition;
                                                this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                                this.contents[localContentsOffset++] = (byte) resolvedPosition;
                                          }
                                    }
                              }
                              attributeNumber++;
                        }
                  }
            }
            
            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        // generate all frames
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                        this.contents[numberOfFramesOffset] = (byte) numberOfFrames;

                        int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                        this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                        attributeNumber++;
                  }
            }
            
            // update the number of attributes
            // ensure first that there is enough space available inside the contents array
            if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       */
02803       public void completeCodeAttributeForClinit(
            int codeAttributeOffset,
            int problemLine) {
            // reinitialize the contents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // codeAttributeOffset is the position inside contents 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...
            int code_length = codeStream.position;
            if (code_length > 65535) {
                  codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
                        codeStream.methodDeclaration.scope.referenceType());
            }
            if (localContentsOffset + 20 >= this.contents.length) {
                  resizeContents(20);
            }
            int max_stack = codeStream.stackMax;
            this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            this.contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            this.contents[codeAttributeOffset + 9] = (byte) max_locals;
            this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            this.contents[codeAttributeOffset + 13] = (byte) code_length;

            // write the exception table
            this.contents[localContentsOffset++] = 0;
            this.contents[localContentsOffset++] = 0;

            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0; // leave two bytes for the attribute_length
            localContentsOffset += 2; // first we handle the linenumber attribute
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            // first we handle the linenumber attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  if (localContentsOffset + 20 >= this.contents.length) {
                        resizeContents(20);
                  }                 
                  /* Create and add the line number attribute (used for debugging) 
                      * Build the pairs of:
                      * (bytecodePC lineNumber)
                      * according to the table of start line indexes and the pcToSourceMap table
                      * contained into the codestream
                      */
                  int lineNumberNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                  this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 6;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 1;
                  // first entry at pc = 0
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
                  this.contents[localContentsOffset++] = (byte) problemLine;
                  // now we change the size of the line number attribute
                  attributeNumber++;
            }
            // then we do the local variable attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
                  int localVariableNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
                  if (localContentsOffset + 8 >= this.contents.length) {
                        resizeContents(8);
                  }
                  this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 2;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  attributeNumber++;
            }
            
            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        // generate all frames
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              // generate current frame
                              // need to find differences between the current frame and the previous frame
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                        this.contents[numberOfFramesOffset] = (byte) numberOfFrames;

                        int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                        this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                        attributeNumber++;
                  }
            }
            
            // update the number of attributes
            // ensure first that there is enough space available inside the contents array
            if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * 
       */
      public void completeCodeAttributeForMissingAbstractProblemMethod(
            MethodBinding binding,
            int codeAttributeOffset,
            int[] startLineIndexes,
            int problemLine) {
            // reinitialize the localContents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // 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...
            int max_stack = codeStream.stackMax;
            this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            this.contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            this.contents[codeAttributeOffset + 9] = (byte) max_locals;
            int code_length = codeStream.position;
            this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            this.contents[codeAttributeOffset + 13] = (byte) code_length;
            // write the exception table
            if (localContentsOffset + 50 >= this.contents.length) {
                  resizeContents(50);
            }
            this.contents[localContentsOffset++] = 0;
            this.contents[localContentsOffset++] = 0;
            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0; // leave two bytes for the attribute_length
            localContentsOffset += 2; // first we handle the linenumber attribute
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  if (localContentsOffset + 12 >= this.contents.length) {
                        resizeContents(12);
                  }
                  /* Create and add the line number attribute (used for debugging) 
                      * Build the pairs of:
                      * (bytecodePC lineNumber)
                      * according to the table of start line indexes and the pcToSourceMap table
                      * contained into the codestream
                      */
                  int lineNumberNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                  this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 6;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 1;
                  if (problemLine == 0) {
                        problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
                  }
                  // first entry at pc = 0
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
                  this.contents[localContentsOffset++] = (byte) problemLine;
                  // now we change the size of the line number attribute
                  attributeNumber++;
            }

            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        // generate all frames
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                        this.contents[numberOfFramesOffset] = (byte) numberOfFrames;

                        int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                        this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                        attributeNumber++;
                  }
            }
            
            // then we do the local variable attribute
            // update the number of attributes// ensure first that there is enough space available inside the localContents array
            if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       *
       * @param codeAttributeOffset <CODE>int</CODE>
       */
03696       public void completeCodeAttributeForProblemMethod(
            AbstractMethodDeclaration method,
            MethodBinding binding,
            int codeAttributeOffset,
            int[] startLineIndexes,
            int problemLine) {
            // reinitialize the localContents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // 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...
            int max_stack = codeStream.stackMax;
            this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            this.contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            this.contents[codeAttributeOffset + 9] = (byte) max_locals;
            int code_length = codeStream.position;
            this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            this.contents[codeAttributeOffset + 13] = (byte) code_length;
            // write the exception table
            if (localContentsOffset + 50 >= this.contents.length) {
                  resizeContents(50);
            }

            // write the exception table
            this.contents[localContentsOffset++] = 0;
            this.contents[localContentsOffset++] = 0;
            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0; // leave two bytes for the attribute_length
            localContentsOffset += 2; // first we handle the linenumber attribute
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  if (localContentsOffset + 20 >= this.contents.length) {
                        resizeContents(20);
                  }
                  /* Create and add the line number attribute (used for debugging) 
                      * Build the pairs of:
                      * (bytecodePC lineNumber)
                      * according to the table of start line indexes and the pcToSourceMap table
                      * contained into the codestream
                      */
                  int lineNumberNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                  this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 6;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 1;
                  if (problemLine == 0) {
                        problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
                  }
                  // first entry at pc = 0
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = 0;
                  this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
                  this.contents[localContentsOffset++] = (byte) problemLine;
                  // now we change the size of the line number attribute
                  attributeNumber++;
            }
            // then we do the local variable attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
                  // compute the resolved position for the arguments of the method
                  int argSize;
                  int numberOfEntries = 0;
                  //          codeAttribute.addLocalVariableTableAttribute(this);
                  int localVariableNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
                  if (localContentsOffset + 8 >= this.contents.length) {
                        resizeContents(8);
                  }
                  this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                  this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
                  int localVariableTableOffset = localContentsOffset;
                  localContentsOffset += 6;
                  // leave space for attribute_length and local_variable_table_length
                  int descriptorIndex;
                  int nameIndex;
                  SourceTypeBinding declaringClassBinding = null;
                  final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
                  if (!methodDeclarationIsStatic) {
                        numberOfEntries++;
                        if (localContentsOffset + 10 >= this.contents.length) {
                              resizeContents(10);
                        }
                        this.contents[localContentsOffset++] = 0;
                        this.contents[localContentsOffset++] = 0;
                        this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                        this.contents[localContentsOffset++] = (byte) code_length;
                        nameIndex = constantPool.literalIndex(ConstantPool.This);
                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) nameIndex;
                        declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
                        descriptorIndex =
                              constantPool.literalIndex(declaringClassBinding.signature());
                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
                        // the resolved position for this is always 0
                        this.contents[localContentsOffset++] = 0;
                        this.contents[localContentsOffset++] = 0;
                  }
                  // used to remember the local variable with a generic type
                  int genericLocalVariablesCounter = 0;
                  LocalVariableBinding[] genericLocalVariables = null;
                  int numberOfGenericEntries = 0;
                  
                  if (binding.isConstructor()) {
                        ReferenceBinding declaringClass = binding.declaringClass;
                        if (declaringClass.isNestedType()) {
                              NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
                              argSize = methodDeclaringClass.enclosingInstancesSlotSize;
                              SyntheticArgumentBinding[] syntheticArguments;
                              if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
                                    for (int i = 0, max = syntheticArguments.length; i < max; i++) {
                                          LocalVariableBinding localVariable = syntheticArguments[i];
                                          final TypeBinding localVariableTypeBinding = localVariable.type;
                                          if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
                                                if (genericLocalVariables == null) {
                                                      // we cannot have more than max locals
                                                      genericLocalVariables = new LocalVariableBinding[max];
                                                }
                                                genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
                                                numberOfGenericEntries++;                                               
                                          }
                                          if (localContentsOffset + 10 >= this.contents.length) {
                                                resizeContents(10);
                                          }
                                          // now we can safely add the local entry
                                          numberOfEntries++;
                                          this.contents[localContentsOffset++] = 0;
                                          this.contents[localContentsOffset++] = 0;
                                          this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                                          this.contents[localContentsOffset++] = (byte) code_length;
                                          nameIndex = constantPool.literalIndex(localVariable.name);
                                          this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) nameIndex;
                                          descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                          this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                          int resolvedPosition = localVariable.resolvedPosition;
                                          this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                          this.contents[localContentsOffset++] = (byte) resolvedPosition;
                                    }
                              }
                        } else {
                              argSize = 1;
                        }
                  } else {
                        argSize = binding.isStatic() ? 0 : 1;
                  }
                  
                  int genericArgumentsCounter = 0;
                  int[] genericArgumentsNameIndexes = null;
                  int[] genericArgumentsResolvedPositions = null;
                  TypeBinding[] genericArgumentsTypeBindings = null;

                  if (method.binding != null) {
                        TypeBinding[] parameters = method.binding.parameters;
                        Argument[] arguments = method.arguments;
                        if ((parameters != null) && (arguments != null)) {
                              for (int i = 0, max = parameters.length; i < max; i++) {
                                    TypeBinding argumentBinding = parameters[i];
                                    if (localContentsOffset + 10 >= this.contents.length) {
                                          resizeContents(10);
                                    }
                                    // now we can safely add the local entry
                                    numberOfEntries++;
                                    this.contents[localContentsOffset++] = 0;
                                    this.contents[localContentsOffset++] = 0;
                                    this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                                    this.contents[localContentsOffset++] = (byte) code_length;
                                    nameIndex = constantPool.literalIndex(arguments[i].name);
                                    this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) nameIndex;
                                    int resolvedPosition = argSize;
                                    if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
                                          if (genericArgumentsCounter == 0) {
                                                // we cannot have more than max locals
                                                genericArgumentsNameIndexes = new int[max];
                                                genericArgumentsResolvedPositions = new int[max];
                                                genericArgumentsTypeBindings = new TypeBinding[max];
                                          }
                                          genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
                                          genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
                                          genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
                                    }
                                    descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
                                    this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                    this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                    if ((argumentBinding == TypeBinding.LONG)
                                          || (argumentBinding == TypeBinding.DOUBLE))
                                          argSize += 2;
                                    else
                                          argSize++;
                                    this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                    this.contents[localContentsOffset++] = (byte) resolvedPosition;
                              }
                        }
                  }
                  int value = numberOfEntries * 10 + 2;
                  this.contents[localVariableTableOffset++] = (byte) (value >> 24);
                  this.contents[localVariableTableOffset++] = (byte) (value >> 16);
                  this.contents[localVariableTableOffset++] = (byte) (value >> 8);
                  this.contents[localVariableTableOffset++] = (byte) value;
                  this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                  this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                  attributeNumber++;
                  
                  final boolean currentInstanceIsGeneric = 
                        !methodDeclarationIsStatic
                        && declaringClassBinding != null
                        && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
                  if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
                        // add the local variable type table attribute
                        numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
                        // reserve enough space
                        int maxOfEntries = 8 + numberOfEntries * 10;
                        if (localContentsOffset + maxOfEntries >= this.contents.length) {
                              resizeContents(maxOfEntries);
                        }
                        int localVariableTypeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
                        this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
                        value = numberOfEntries * 10 + 2;
                        this.contents[localContentsOffset++] = (byte) (value >> 24);
                        this.contents[localContentsOffset++] = (byte) (value >> 16);
                        this.contents[localContentsOffset++] = (byte) (value >> 8);
                        this.contents[localContentsOffset++] = (byte) value;
                        this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[localContentsOffset++] = (byte) numberOfEntries;
                        if (currentInstanceIsGeneric) {
                              numberOfEntries++;
                              this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                              this.contents[localContentsOffset++] = (byte) code_length;
                              nameIndex = constantPool.literalIndex(ConstantPool.This);
                              this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) nameIndex;
                              descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
                              this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) descriptorIndex;
                              this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
                              this.contents[localContentsOffset++] = 0;
                        }
                        
                        for (int i = 0; i < genericLocalVariablesCounter; i++) {
                              LocalVariableBinding localVariable = genericLocalVariables[i];
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                              this.contents[localContentsOffset++] = (byte) code_length;
                              nameIndex = constantPool.literalIndex(localVariable.name);
                              this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) nameIndex;
                              descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
                              this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) descriptorIndex;
                              int resolvedPosition = localVariable.resolvedPosition;
                              this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                              this.contents[localContentsOffset++] = (byte) resolvedPosition;
                        }
                        for (int i = 0; i < genericArgumentsCounter; i++) {
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = 0;
                              this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                              this.contents[localContentsOffset++] = (byte) code_length;
                              nameIndex = genericArgumentsNameIndexes[i];
                              this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) nameIndex;
                              descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
                              this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                              this.contents[localContentsOffset++] = (byte) descriptorIndex;
                              int resolvedPosition = genericArgumentsResolvedPositions[i];
                              this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                              this.contents[localContentsOffset++] = (byte) resolvedPosition;
                        }                       
                        attributeNumber++;
                  }                 
            }
            
            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        // generate all frames
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                        this.contents[numberOfFramesOffset] = (byte) numberOfFrames;

                        int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                        this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                        attributeNumber++;
                  }
            }
            
            // update the number of attributes// ensure first that there is enough space available inside the localContents array
            if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       *
       * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
       * @param codeAttributeOffset <CODE>int</CODE>
       */
04359       public void completeCodeAttributeForSyntheticMethod(
            boolean hasExceptionHandlers,
            SyntheticMethodBinding binding,
            int codeAttributeOffset,
            int[] startLineIndexes) {
            // reinitialize the contents with the byte modified by the code stream
            this.contents = codeStream.bCodeStream;
            int localContentsOffset = codeStream.classFileOffset;
            // codeAttributeOffset is the position inside contents 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...
            int max_stack = codeStream.stackMax;
            contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
            contents[codeAttributeOffset + 7] = (byte) max_stack;
            int max_locals = codeStream.maxLocals;
            contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
            contents[codeAttributeOffset + 9] = (byte) max_locals;
            int code_length = codeStream.position;
            contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
            contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
            contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
            contents[codeAttributeOffset + 13] = (byte) code_length;
            if ((localContentsOffset + 40) >= this.contents.length) {
                  resizeContents(40);
            }
            
            if (hasExceptionHandlers) {
                  // write the exception table
                  ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
                  int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
                  for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
                        exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2; 
                  }
                  int exSize = exceptionHandlersCount * 8 + 2;
                  if (exSize + localContentsOffset >= this.contents.length) {
                        resizeContents(exSize);
                  }
                  // there is no exception table, so we need to offset by 2 the current offset and move 
                  // on the attribute generation
                  this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
                  this.contents[localContentsOffset++] = (byte) exceptionHandlersCount;
                  for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
                        ExceptionLabel exceptionLabel = exceptionLabels[i];
                        if (exceptionLabel != null) {
                              int iRange = 0, maxRange = exceptionLabel.count;
                              if ((maxRange & 1) != 0) {
                                    referenceBinding.scope.problemReporter().abortDueToInternalError(
                                                Messages.bind(Messages.abort_invalidExceptionAttribute, new String(binding.selector), 
                                                            referenceBinding.scope.problemReporter().referenceContext));
                              }
                              while  (iRange < maxRange) {
                                    int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
                                    this.contents[localContentsOffset++] = (byte) (start >> 8);
                                    this.contents[localContentsOffset++] = (byte) start;
                                    int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
                                    this.contents[localContentsOffset++] = (byte) (end >> 8);
                                    this.contents[localContentsOffset++] = (byte) end;
                                    int handlerPC = exceptionLabel.position;
                                    this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
                                    this.contents[localContentsOffset++] = (byte) handlerPC;
                                    if (exceptionLabel.exceptionType == null) {
                                          // any exception handler
                                          this.contents[localContentsOffset++] = 0;
                                          this.contents[localContentsOffset++] = 0;
                                    } else {
                                          int nameIndex;
                                          switch(exceptionLabel.exceptionType.id) {
                                                case T_null :
                                                      /* represents ClassNotFoundException, see class literal access*/
                                                      nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
                                                      break;
                                                case T_long :
                                                      /* represents NoSuchFieldError, see switch table generation*/
                                                      nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName);
                                                      break;
                                                default:
                                                      nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName());
                                          }
                                          this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                          this.contents[localContentsOffset++] = (byte) nameIndex;
                                    }
                              }
                        }
                  }
            } else {
                  // there is no exception table, so we need to offset by 2 the current offset and move 
                  // on the attribute generation
                  contents[localContentsOffset++] = 0;
                  contents[localContentsOffset++] = 0;
            }
            // debug attributes
            int codeAttributeAttributeOffset = localContentsOffset;
            int attributeNumber = 0;
            // leave two bytes for the attribute_length
            localContentsOffset += 2;
            if (localContentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }

            // first we handle the linenumber attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
                  if (localContentsOffset + 12 >= this.contents.length) {
                        resizeContents(12);
                  }           
                  int index = 0;
                  int lineNumberNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
                  contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
                  contents[localContentsOffset++] = (byte) lineNumberNameIndex;
                  int lineNumberTableOffset = localContentsOffset;
                  localContentsOffset += 6;
                  // leave space for attribute_length and line_number_table_length
                  // Seems like do would be better, but this preserves the existing behavior.
                  index = searchLineNumber(startLineIndexes, binding.sourceStart);
                  contents[localContentsOffset++] = 0;
                  contents[localContentsOffset++] = 0;
                  contents[localContentsOffset++] = (byte) (index >> 8);
                  contents[localContentsOffset++] = (byte) index;
                  // now we change the size of the line number attribute
                  contents[lineNumberTableOffset++] = 0;
                  contents[lineNumberTableOffset++] = 0;
                  contents[lineNumberTableOffset++] = 0;
                  contents[lineNumberTableOffset++] = 6;
                  contents[lineNumberTableOffset++] = 0;
                  contents[lineNumberTableOffset++] = 1;
                  attributeNumber++;
            }
            // then we do the local variable attribute
            if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
                  int numberOfEntries = 0;
                  int localVariableNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
                  if (localContentsOffset + 8 > this.contents.length) {
                        resizeContents(8);
                  }
                  contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                  contents[localContentsOffset++] = (byte) localVariableNameIndex;
                  int localVariableTableOffset = localContentsOffset;
                  localContentsOffset += 6;
                  // leave space for attribute_length and local_variable_table_length
                  int nameIndex;
                  int descriptorIndex;

                  // used to remember the local variable with a generic type
                  int genericLocalVariablesCounter = 0;
                  LocalVariableBinding[] genericLocalVariables = null;
                  int numberOfGenericEntries = 0;
                  
                  for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                        LocalVariableBinding localVariable = codeStream.locals[i];
                        final TypeBinding localVariableTypeBinding = localVariable.type;
                        boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
                        if (localVariable.initializationCount != 0 && isParameterizedType) {
                              if (genericLocalVariables == null) {
                                    // we cannot have more than max locals
                                    genericLocalVariables = new LocalVariableBinding[max];
                              }
                              genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
                        }
                        for (int j = 0; j < localVariable.initializationCount; j++) {
                              int startPC = localVariable.initializationPCs[j << 1];
                              int endPC = localVariable.initializationPCs[(j << 1) + 1];
                              if (startPC != endPC) { // only entries for non zero length
                                    if (endPC == -1) {
                                          localVariable.declaringScope.problemReporter().abortDueToInternalError(
                                                Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)), 
                                                (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
                                    }
                                    if (localContentsOffset + 10 > this.contents.length) {
                                          resizeContents(10);
                                    }
                                    // now we can safely add the local entry
                                    numberOfEntries++;
                                    if (isParameterizedType) {
                                          numberOfGenericEntries++;
                                    }
                                    contents[localContentsOffset++] = (byte) (startPC >> 8);
                                    contents[localContentsOffset++] = (byte) startPC;
                                    int length = endPC - startPC;
                                    contents[localContentsOffset++] = (byte) (length >> 8);
                                    contents[localContentsOffset++] = (byte) length;
                                    nameIndex = constantPool.literalIndex(localVariable.name);
                                    contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                    contents[localContentsOffset++] = (byte) nameIndex;
                                    descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                    contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                    contents[localContentsOffset++] = (byte) descriptorIndex;
                                    int resolvedPosition = localVariable.resolvedPosition;
                                    contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                    contents[localContentsOffset++] = (byte) resolvedPosition;
                              }
                        }
                  }
                  int value = numberOfEntries * 10 + 2;
                  contents[localVariableTableOffset++] = (byte) (value >> 24);
                  contents[localVariableTableOffset++] = (byte) (value >> 16);
                  contents[localVariableTableOffset++] = (byte) (value >> 8);
                  contents[localVariableTableOffset++] = (byte) value;
                  contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                  contents[localVariableTableOffset] = (byte) numberOfEntries;
                  attributeNumber++;

                  if (genericLocalVariablesCounter != 0) {
                        // add the local variable type table attribute
                        int maxOfEntries = 8 + numberOfGenericEntries * 10;
                        // reserve enough space
                        if (localContentsOffset + maxOfEntries >= this.contents.length) {
                              resizeContents(maxOfEntries);
                        }
                        int localVariableTypeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
                        contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
                        contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
                        value = numberOfGenericEntries * 10 + 2;
                        contents[localContentsOffset++] = (byte) (value >> 24);
                        contents[localContentsOffset++] = (byte) (value >> 16);
                        contents[localContentsOffset++] = (byte) (value >> 8);
                        contents[localContentsOffset++] = (byte) value;
                        contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
                        contents[localContentsOffset++] = (byte) numberOfGenericEntries;

                        for (int i = 0; i < genericLocalVariablesCounter; i++) {
                              LocalVariableBinding localVariable = genericLocalVariables[i];
                              for (int j = 0; j < localVariable.initializationCount; j++) {
                                    int startPC = localVariable.initializationPCs[j << 1];
                                    int endPC = localVariable.initializationPCs[(j << 1) + 1];
                                    if (startPC != endPC) { // only entries for non zero length
                                          // now we can safely add the local entry
                                          contents[localContentsOffset++] = (byte) (startPC >> 8);
                                          contents[localContentsOffset++] = (byte) startPC;
                                          int length = endPC - startPC;
                                          contents[localContentsOffset++] = (byte) (length >> 8);
                                          contents[localContentsOffset++] = (byte) length;
                                          nameIndex = constantPool.literalIndex(localVariable.name);
                                          contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                          contents[localContentsOffset++] = (byte) nameIndex;
                                          descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
                                          contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                          contents[localContentsOffset++] = (byte) descriptorIndex;
                                          int resolvedPosition = localVariable.resolvedPosition;
                                          contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
                                          contents[localContentsOffset++] = (byte) resolvedPosition;
                                    }
                              }
                        }
                        attributeNumber++;
                  }
            }
            
            if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
                  final Set framesPositions = ((StackMapFrameCodeStream) codeStream).framePositions;
                  final int framesPositionsSize = framesPositions.size();
                  int numberOfFrames = framesPositionsSize - 1; // -1 because last return doesn't count
                  if (numberOfFrames > 0) {
                        ArrayList framePositions = new ArrayList(framesPositionsSize);
                        framePositions.addAll(framesPositions);
                        Collections.sort(framePositions);
                        // add the stack map table attribute
                        if (localContentsOffset + 8 >= this.contents.length) {
                              resizeContents(8);
                        }
                        int stackMapTableAttributeNameIndex =
                              constantPool.literalIndex(AttributeNamesConstants.StackMapTableName);
                        this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
                        
                        int stackMapTableAttributeLengthOffset = localContentsOffset;
                        // generate the attribute
                        localContentsOffset += 4;
                        numberOfFrames = 0;
                        int numberOfFramesOffset = localContentsOffset;
                        localContentsOffset += 2;
                        // generate all frames
                        ArrayList frames = ((StackMapFrameCodeStream) codeStream).frames;
                        StackMapFrame currentFrame = (StackMapFrame) frames.get(0);
                        StackMapFrame prevFrame = null;
                        int framesSize = frames.size();
                        int frameIndex = 0;
                        for (int j = 0; j < framesPositionsSize && ((Integer) framePositions.get(j)).intValue() < code_length; j++) {
                              // select next frame
                              prevFrame = currentFrame;
                              currentFrame = null;
                              for (; frameIndex < framesSize; frameIndex++) {
                                    currentFrame = (StackMapFrame) frames.get(frameIndex);
                                    if (currentFrame.pc == ((Integer) framePositions.get(j)).intValue()) {
                                          break;
                                    }
                              }
                              if (currentFrame == null) break;
                              numberOfFrames++;
                              int offsetDelta = currentFrame.getOffsetDelta(prevFrame);
                              switch (currentFrame.getFrameType(prevFrame)) {
                                    case StackMapFrame.APPEND_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals);
                                          int numberOfLocals = currentFrame.getNumberOfLocals();
                                          for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) {
                                                if (localContentsOffset + 6 >= this.contents.length) {
                                                      resizeContents(6);
                                                }
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfDifferentLocals--;
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_FRAME :
                                          if (localContentsOffset + 1 >= this.contents.length) {
                                                resizeContents(1);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.SAME_FRAME_EXTENDED :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 251;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          break;
                                    case StackMapFrame.CHOP_FRAME :
                                          if (localContentsOffset + 3 >= this.contents.length) {
                                                resizeContents(3);
                                          }                                         
                                          numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame);
                                          this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;                                      
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS :
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta + 64);
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED :
                                          if (localContentsOffset + 6 >= this.contents.length) {
                                                resizeContents(6);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 247;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          if (currentFrame.stackItems[0] == null) {
                                                this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                          } else {
                                                switch(currentFrame.stackItems[0].id()) {
                                                      case T_boolean :
                                                      case T_byte :
                                                      case T_char :
                                                      case T_int :
                                                      case T_short :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                            break;
                                                      case T_float :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                            break;
                                                      case T_long :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                            break;
                                                      case T_double :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                            break;
                                                      case T_null :
                                                            this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                            break;
                                                      default:
                                                            VerificationTypeInfo info = currentFrame.stackItems[0];
                                                            this.contents[localContentsOffset++] = (byte) info.tag;
                                                            switch (info.tag) {
                                                                  case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                        int offset = info.offset;
                                                                        this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) offset;
                                                                        break;
                                                                  case VerificationTypeInfo.ITEM_OBJECT :
                                                                        int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                        this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                        this.contents[localContentsOffset++] = (byte) indexForType;
                                                            }
                                                }
                                          }
                                          break;
                                    default :
                                          // FULL_FRAME
                                          if (localContentsOffset + 5 >= this.contents.length) {
                                                resizeContents(5);
                                          }                                         
                                          this.contents[localContentsOffset++] = (byte) 255;
                                          this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
                                          this.contents[localContentsOffset++] = (byte) offsetDelta;
                                          int numberOfLocalOffset = localContentsOffset;
                                          localContentsOffset += 2; // leave two spots for number of locals
                                          int numberOfLocalEntries = 0;
                                          numberOfLocals = currentFrame.getNumberOfLocals();
                                          int numberOfEntries = 0;
                                          int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
                                          for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }                                         
                                                VerificationTypeInfo info = currentFrame.locals[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  i++;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  i++;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                      numberOfLocalEntries++;
                                                }
                                                numberOfEntries++;
                                          }
                                          if (localContentsOffset + 4 >= this.contents.length) {
                                                resizeContents(4);
                                          }                                         
                                          this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
                                          this.contents[numberOfLocalOffset] = (byte) numberOfEntries;
                                          int numberOfStackItems = currentFrame.numberOfStackItems;
                                          this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
                                          this.contents[localContentsOffset++] = (byte) numberOfStackItems;
                                          for (int i = 0; i < numberOfStackItems; i++) {
                                                if (localContentsOffset + 3 >= this.contents.length) {
                                                      resizeContents(3);
                                                }
                                                VerificationTypeInfo info = currentFrame.stackItems[i];
                                                if (info == null) {
                                                      this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
                                                } else {
                                                      switch(info.id()) {
                                                            case T_boolean :
                                                            case T_byte :
                                                            case T_char :
                                                            case T_int :
                                                            case T_short :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
                                                                  break;
                                                            case T_float :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
                                                                  break;
                                                            case T_long :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
                                                                  break;
                                                            case T_double :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
                                                                  break;
                                                            case T_null :
                                                                  this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
                                                                  break;
                                                            default:
                                                                  this.contents[localContentsOffset++] = (byte) info.tag;
                                                                  switch (info.tag) {
                                                                        case VerificationTypeInfo.ITEM_UNINITIALIZED :
                                                                              int offset = info.offset;
                                                                              this.contents[localContentsOffset++] = (byte) (offset >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) offset;
                                                                              break;
                                                                        case VerificationTypeInfo.ITEM_OBJECT :
                                                                              int indexForType = constantPool.literalIndexForType(info.constantPoolName());
                                                                              this.contents[localContentsOffset++] = (byte) (indexForType >> 8);
                                                                              this.contents[localContentsOffset++] = (byte) indexForType;
                                                                  }
                                                      }
                                                }
                                          }
                              }
                        }
                        
                        this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
                        this.contents[numberOfFramesOffset] = (byte) numberOfFrames;

                        int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4;
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
                        this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
                        this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
                        attributeNumber++;
                  }
            }
            
            // update the number of attributes
            // ensure first that there is enough space available inside the contents array
            if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[codeAttributeAttributeOffset] = (byte) attributeNumber;

            // update the attribute length
            int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
            contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
            contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
            contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
            contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
            contentsOffset = localContentsOffset;
      }

      /**
       * INTERNAL USE-ONLY
       * That method completes the creation of the code attribute by setting
       * - the attribute_length
       * - max_stack
       * - max_locals
       * - code_length
       * - exception table
       * - and debug attributes if necessary.
       *
       * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
       * @param codeAttributeOffset <CODE>int</CODE>
       */
04984       public void completeCodeAttributeForSyntheticMethod(
            SyntheticMethodBinding binding,
            int codeAttributeOffset,
            int[] startLineIndexes) {
            
            this.completeCodeAttributeForSyntheticMethod(
                        false,
                        binding,
                        codeAttributeOffset,
                        startLineIndexes);
      }

      /**
       * INTERNAL USE-ONLY
       * Complete the creation of a method info by setting up the number of attributes at the right offset.
       *
       * @param methodAttributeOffset <CODE>int</CODE>
       * @param attributeNumber <CODE>int</CODE> 
       */
05003       public void completeMethodInfo(
            int methodAttributeOffset,
            int attributeNumber) {
            // update the number of attributes
            contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
            contents[methodAttributeOffset] = (byte) attributeNumber;
      }
      
      /**
       * INTERNAL USE-ONLY
       * This methods returns a char[] representing the file name of the receiver
       *
       * @return char[]
       */
05017       public char[] fileName() {
            return constantPool.UTF8Cache.returnKeyFor(2);
      }

      private void generateAnnotation(Annotation annotation, int attributeOffset) {
            if (contentsOffset + 4 >= this.contents.length) {
                  resizeContents(4);
            }
            TypeBinding annotationTypeBinding = annotation.resolvedType;
            if (annotationTypeBinding == null) {
                  this.contentsOffset = attributeOffset;
                  return;
            }
            final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
            contents[contentsOffset++] = (byte) (typeIndex >> 8);
            contents[contentsOffset++] = (byte) typeIndex;
            if (annotation instanceof NormalAnnotation) {
                  NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
                  MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
                  if (memberValuePairs != null) {
                        final int memberValuePairsLength = memberValuePairs.length;
                        contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
                        contents[contentsOffset++] = (byte) memberValuePairsLength;
                        for (int i = 0; i < memberValuePairsLength; i++) {
                              MemberValuePair memberValuePair = memberValuePairs[i];
                              if (contentsOffset + 2 >= this.contents.length) {
                                    resizeContents(2);
                              }
                              final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
                              contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
                              contents[contentsOffset++] = (byte) elementNameIndex;
                              MethodBinding methodBinding = memberValuePair.binding;
                              if (methodBinding == null) {
                                    contentsOffset = attributeOffset;
                              } else {
                                    generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
                              }
                        }
                  } else {
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
                  }
            } else if (annotation instanceof SingleMemberAnnotation) {
                  SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
                  // this is a single member annotation (one member value)
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 1;
                  if (contentsOffset + 2 >= this.contents.length) {
                        resizeContents(2);
                  }
                  final int elementNameIndex = constantPool.literalIndex(VALUE);
                  contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
                  contents[contentsOffset++] = (byte) elementNameIndex;
                  MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding;
                  if (methodBinding == null) {
                        contentsOffset = attributeOffset;
                  } else {
                        generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
                  }
            } else {
                  // this is a marker annotation (no member value pairs)
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
            }
      }

      /**
       * INTERNAL USE-ONLY
       * That method generates the header of a code attribute.
       * - the index inside the constant pool for the attribute name ("Code")
       * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
       */
05089       public void generateCodeAttributeHeader() {
            if (contentsOffset + 20 >= this.contents.length) {
                  resizeContents(20);
            }
            int constantValueNameIndex =
                  constantPool.literalIndex(AttributeNamesConstants.CodeName);
            contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
            contents[contentsOffset++] = (byte) constantValueNameIndex;
            // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
            contentsOffset += 12;
      }

      private void generateElementValue(
                  Expression defaultValue,
                  TypeBinding memberValuePairReturnType,
                  int attributeOffset) {
            Constant constant = defaultValue.constant;
            TypeBinding defaultValueBinding = defaultValue.resolvedType;
            if (defaultValueBinding == null) {
                  contentsOffset = attributeOffset;
            } else {
                  if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
                        // automatic wrapping
                        if (contentsOffset + 3 >= this.contents.length) {
                              resizeContents(3);
                        }
                        contents[contentsOffset++] = (byte) '[';
                        contents[contentsOffset++] = (byte) 0;
                        contents[contentsOffset++] = (byte) 1;
                  }
                  if (constant != null && constant != Constant.NotAConstant) {
                        generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
                  } else {
                        generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
                  }
            }
      }

      /**
       * @param attributeOffset
       */
05130       private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
            if (contentsOffset + 3 >= this.contents.length) {
                  resizeContents(3);
            }
            switch (binding.id) {
                  case T_boolean :
                        contents[contentsOffset++] = (byte) 'Z';
                        int booleanValueIndex =
                              constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
                        contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
                        contents[contentsOffset++] = (byte) booleanValueIndex;
                        break;
                  case T_byte :
                        contents[contentsOffset++] = (byte) 'B';
                        int integerValueIndex =
                              constantPool.literalIndex(constant.intValue());
                        contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                        contents[contentsOffset++] = (byte) integerValueIndex;
                        break;
                  case T_char :
                        contents[contentsOffset++] = (byte) 'C';
                        integerValueIndex =
                              constantPool.literalIndex(constant.intValue());
                        contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                        contents[contentsOffset++] = (byte) integerValueIndex;
                        break;
                  case T_int :
                        contents[contentsOffset++] = (byte) 'I';
                        integerValueIndex =
                              constantPool.literalIndex(constant.intValue());
                        contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                        contents[contentsOffset++] = (byte) integerValueIndex;
                        break;
                  case T_short :
                        contents[contentsOffset++] = (byte) 'S';
                        integerValueIndex =
                              constantPool.literalIndex(constant.intValue());
                        contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                        contents[contentsOffset++] = (byte) integerValueIndex;
                        break;
                  case T_float :
                        contents[contentsOffset++] = (byte) 'F';
                        int floatValueIndex =
                              constantPool.literalIndex(constant.floatValue());
                        contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
                        contents[contentsOffset++] = (byte) floatValueIndex;
                        break;
                  case T_double :
                        contents[contentsOffset++] = (byte) 'D';
                        int doubleValueIndex =
                              constantPool.literalIndex(constant.doubleValue());
                        contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
                        contents[contentsOffset++] = (byte) doubleValueIndex;
                        break;
                  case T_long :
                        contents[contentsOffset++] = (byte) 'J';
                        int longValueIndex =
                              constantPool.literalIndex(constant.longValue());
                        contents[contentsOffset++] = (byte) (longValueIndex >> 8);
                        contents[contentsOffset++] = (byte) longValueIndex;
                        break;
                  case T_JavaLangString :
                        contents[contentsOffset++] = (byte) 's';
                        int stringValueIndex =
                              constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
                        if (stringValueIndex == -1) {
                              if (!creatingProblemType) {
                                    // report an error and abort: will lead to a problem type classfile creation
                                    TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
                                    typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
                              } else {
                                    // already inside a problem type creation : no attribute
                                    contentsOffset = attributeOffset;
                              }
                        } else {
                              contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
                              contents[contentsOffset++] = (byte) stringValueIndex;
                        }
            }
      }

      private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
            if (defaultValueBinding != null) {
                  if (defaultValueBinding.isEnum()) {
                        if (contentsOffset + 5 >= this.contents.length) {
                              resizeContents(5);
                        }
                        contents[contentsOffset++] = (byte) 'e';
                        FieldBinding fieldBinding = null;
                        if (defaultValue instanceof QualifiedNameReference) {
                              QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
                              fieldBinding = (FieldBinding) nameReference.binding;
                        } else if (defaultValue instanceof SingleNameReference) {
                              SingleNameReference nameReference = (SingleNameReference) defaultValue;
                              fieldBinding = (FieldBinding) nameReference.binding;
                        } else {
                              contentsOffset = attributeOffset;
                        }
                        if (fieldBinding != null) {
                              final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
                              final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
                              contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
                              contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
                              contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
                              contents[contentsOffset++] = (byte) enumConstantNameIndex;
                        }
                  } else if (defaultValueBinding.isAnnotationType()) {
                        if (contentsOffset + 1 >= this.contents.length) {
                              resizeContents(1);
                        }
                        contents[contentsOffset++] = (byte) '@';
                        generateAnnotation((Annotation) defaultValue, attributeOffset);
                  } else if (defaultValueBinding.isArrayType()) {
                        // array type
                        if (contentsOffset + 3 >= this.contents.length) {
                              resizeContents(3);
                        }
                        contents[contentsOffset++] = (byte) '[';
                        if (defaultValue instanceof ArrayInitializer) {
                              ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
                              int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
                              contents[contentsOffset++] = (byte) (arrayLength >> 8);
                              contents[contentsOffset++] = (byte) arrayLength;
                              for (int i = 0; i < arrayLength; i++) {
                                    generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
                              }
                        } else {
                              contentsOffset = attributeOffset;
                        }
                  } else {
                        // class type
                        if (contentsOffset + 3 >= this.contents.length) {
                              resizeContents(3);
                        }
                        contents[contentsOffset++] = (byte) 'c';
                        if (defaultValue instanceof ClassLiteralAccess) {
                              ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
                              final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
                              contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
                              contents[contentsOffset++] = (byte) classInfoIndex;
                        } else {
                              contentsOffset = attributeOffset;
                        }
                  }
            } else {
                  contentsOffset = attributeOffset;
            }
      }
      
      public int generateMethodInfoAttribute(MethodBinding methodBinding) {
            return generateMethodInfoAttribute(methodBinding, false);
      }

      public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
            int attributesNumber = generateMethodInfoAttribute(methodBinding);
            int attributeOffset = contentsOffset;
            if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) {
                  // add an annotation default attribute
                  int annotationDefaultNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
                  contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
                  contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
                  int attributeLengthOffset = contentsOffset;
                  contentsOffset += 4;
                  if (contentsOffset + 4 >= this.contents.length) {
                        resizeContents(4);
                  }
                  generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
                  if (contentsOffset != attributeOffset) {
                        int attributeLength = contentsOffset - attributeLengthOffset - 4;
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
                        contents[attributeLengthOffset++] = (byte) attributeLength;             
                        attributesNumber++;
                  }
            }
            return attributesNumber;
      }
      /**
       * INTERNAL USE-ONLY
       * That method generates the attributes of a code attribute.
       * They could be:
       * - an exception attribute for each try/catch found inside the method
       * - a deprecated attribute
       * - a synthetic attribute for synthetic access methods
       *
       * It returns the number of attributes created for the code attribute.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
       * @return <CODE>int</CODE>
       */
05322       public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
            // leave two bytes for the attribute_number
            contentsOffset += 2;
            if (contentsOffset + 2 >= this.contents.length) {
                  resizeContents(2);
            }
            // now we can handle all the attribute for that method info:
            // it could be:
            // - a CodeAttribute
            // - a ExceptionAttribute
            // - a DeprecatedAttribute
            // - a SyntheticAttribute

            // Exception attribute
            ReferenceBinding[] thrownsExceptions;
            int attributeNumber = 0;
            if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
                  // The method has a throw clause. So we need to add an exception attribute
                  // check that there is enough space to write all the bytes for the exception attribute
                  int length = thrownsExceptions.length;
                  int exSize = 8 + length * 2;
                  if (exSize + contentsOffset >= this.contents.length) {
                        resizeContents(exSize);
                  }
                  int exceptionNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
                  contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
                  contents[contentsOffset++] = (byte) exceptionNameIndex;
                  // The attribute length = length * 2 + 2 in case of a exception attribute
                  int attributeLength = length * 2 + 2;
                  contents[contentsOffset++] = (byte) (attributeLength >> 24);
                  contents[contentsOffset++] = (byte) (attributeLength >> 16);
                  contents[contentsOffset++] = (byte) (attributeLength >> 8);
                  contents[contentsOffset++] = (byte) attributeLength;
                  contents[contentsOffset++] = (byte) (length >> 8);
                  contents[contentsOffset++] = (byte) length;
                  for (int i = 0; i < length; i++) {
                        int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName());
                        contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
                        contents[contentsOffset++] = (byte) exceptionIndex;
                  }
                  attributeNumber++;
            }
            if (methodBinding.isDeprecated()) {
                  // Deprecated attribute
                  // Check that there is enough space to write the deprecated attribute
                  if (contentsOffset + 6 >= this.contents.length) {
                        resizeContents(6);
                  }
                  int deprecatedAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
                  contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
                  // the length of a deprecated attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;

                  attributeNumber++;
            }
            if (this.targetJDK < ClassFileConstants.JDK1_5 && methodBinding.isSynthetic()) {
                  // Synthetic attribute
                  // Check that there is enough space to write the deprecated attribute
                  if (contentsOffset + 6 >= this.contents.length) {
                        resizeContents(6);
                  }
                  int syntheticAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
                  contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
                  // the length of a synthetic attribute is equals to 0
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;

                  attributeNumber++;
            }
            // add signature attribute
            char[] genericSignature = methodBinding.genericSignature();
            if (genericSignature != null) {
                  // check that there is enough space to write all the bytes for the field info corresponding
                  // to the @fieldBinding
                  if (contentsOffset + 8 >= this.contents.length) {
                        resizeContents(8);
                  }
                  int signatureAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.SignatureName);
                  contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
                  // the length of a signature attribute is equals to 2
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 0;
                  contents[contentsOffset++] = 2;
                  int signatureIndex =
                        constantPool.literalIndex(genericSignature);
                  contents[contentsOffset++] = (byte) (signatureIndex >> 8);
                  contents[contentsOffset++] = (byte) signatureIndex;
                  attributeNumber++;
            }
            if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
                  AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
                  if (methodDeclaration != null) {
                        Annotation[] annotations = methodDeclaration.annotations;
                        if (annotations != null) {
                              attributeNumber += generateRuntimeAnnotations(annotations);
                        }
                        if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
                              Argument[] arguments = methodDeclaration.arguments;
                              if (arguments != null) {
                                    attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
                              }
                        }
                  }
            }
            return attributeNumber;
      }

      /**
       * INTERNAL USE-ONLY
       * That method generates the header of a method info:
       * The header consists in:
       * - the access flags
       * - the name index of the method name inside the constant pool
       * - the descriptor index of the signature of the method inside the constant pool.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
       */
05452       public void generateMethodInfoHeader(MethodBinding methodBinding) {
            generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
      }

      /**
       * INTERNAL USE-ONLY
       * That method generates the header of a method info:
       * The header consists in:
       * - the access flags
       * - the name index of the method name inside the constant pool
       * - the descriptor index of the signature of the method inside the constant pool.
       *
       * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
       * @param accessFlags the access flags
       */
05467       public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
            // check that there is enough space to write all the bytes for the method info corresponding
            // to the @methodBinding
            methodCount++; // add one more method
            if (contentsOffset + 10 >= this.contents.length) {
                  resizeContents(10);
            }
            if (targetJDK < ClassFileConstants.JDK1_5) {
                // pre 1.5, synthetic was an attribute, not a modifier
                accessFlags &= ~ClassFileConstants.AccSynthetic;
            }
            if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) {
                  accessFlags &= ~ClassFileConstants.AccPrivate;
            }
            contents[contentsOffset++] = (byte) (accessFlags >> 8);
            contents[contentsOffset++] = (byte) accessFlags;
            int nameIndex = constantPool.literalIndex(methodBinding.selector);
            contents[contentsOffset++] = (byte) (nameIndex >> 8);
            contents[contentsOffset++] = (byte) nameIndex;
            int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
            contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
            contents[contentsOffset++] = (byte) descriptorIndex;
      }
      /**
       * INTERNAL USE-ONLY
       * That method generates the method info header of a clinit:
       * The header consists in:
       * - the access flags (always default access + static)
       * - the name index of the method name (always <clinit>) inside the constant pool 
       * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
       */
05498       public void generateMethodInfoHeaderForClinit() {
            // check that there is enough space to write all the bytes for the method info corresponding
            // to the @methodBinding
            methodCount++; // add one more method
            if (contentsOffset + 10 >= this.contents.length) {
                  resizeContents(10);
            }
            contents[contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8);
            contents[contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic);
            int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
            contents[contentsOffset++] = (byte) (nameIndex >> 8);
            contents[contentsOffset++] = (byte) nameIndex;
            int descriptorIndex =
                  constantPool.literalIndex(ConstantPool.ClinitSignature);
            contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
            contents[contentsOffset++] = (byte) descriptorIndex;
            // We know that we won't get more than 1 attribute: the code attribute
            contents[contentsOffset++] = 0;
            contents[contentsOffset++] = 1;
      }

      /**
       * INTERNAL USE-ONLY
       * Generate the byte for problem method infos that correspond to missing abstract methods.
       * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
       *
       * @param methodDeclarations Array of all missing abstract methods
       */
05526       public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
            if (methodDeclarations != null) {
                  for (int i = 0, max = methodDeclarations.length; i < max; i++) {
                        MethodDeclaration methodDeclaration = methodDeclarations[i];
                        MethodBinding methodBinding = methodDeclaration.binding;
                        String readableName = new String(methodBinding.readableName());
                        CategorizedProblem[] problems = compilationResult.problems;
                        int problemsCount = compilationResult.problemCount;
                        for (int j = 0; j < problemsCount; j++) {
                              CategorizedProblem problem = problems[j];
                              if (problem != null
                                    && problem.getID() == IProblem.AbstractMethodMustBeImplemented
                                    && problem.getMessage().indexOf(readableName) != -1) {
                                          // we found a match
                                          addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
                                    }
                        }
                  }
            }
      }

      /**
       * @param annotations
       * @return the number of attributes created while dumping the annotations in the .class file
       */
05551       private int generateRuntimeAnnotations(final Annotation[] annotations) {
            int attributesNumber = 0;
            final int length = annotations.length;
            int visibleAnnotationsCounter = 0;
            int invisibleAnnotationsCounter = 0;
            
            for (int i = 0; i < length; i++) {
                  Annotation annotation = annotations[i];
                  if (isRuntimeInvisible(annotation)) {
                        invisibleAnnotationsCounter++;
                  } else if (isRuntimeVisible(annotation)) {
                        visibleAnnotationsCounter++;
                  }
            }

            if (invisibleAnnotationsCounter != 0) {
                  int annotationAttributeOffset = contentsOffset;
                  if (contentsOffset + 10 >= contents.length) {
                        resizeContents(10);
                  }
                  int runtimeInvisibleAnnotationsAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
                  contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
                  int attributeLengthOffset = contentsOffset;
                  contentsOffset += 4; // leave space for the attribute length
      
                  int annotationsLengthOffset = contentsOffset;
                  contentsOffset += 2; // leave space for the annotations length
            
                  contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
                  contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;

                  loop: for (int i = 0; i < length; i++) {
                        if (invisibleAnnotationsCounter == 0) break loop;
                        Annotation annotation = annotations[i];
                        if (isRuntimeInvisible(annotation)) {
                              generateAnnotation(annotation, annotationAttributeOffset);
                              invisibleAnnotationsCounter--;
                              if (this.contentsOffset == annotationAttributeOffset) {
                                    break loop;
                              }
                        }
                  }
                  if (contentsOffset != annotationAttributeOffset) {
                        int attributeLength = contentsOffset - attributeLengthOffset - 4;
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
                        contents[attributeLengthOffset++] = (byte) attributeLength;             
                        attributesNumber++;
                  } else {          
                        contentsOffset = annotationAttributeOffset;
                  }
            }
      
            if (visibleAnnotationsCounter != 0) {
                  int annotationAttributeOffset = contentsOffset;
                  if (contentsOffset + 10 >= contents.length) {
                        resizeContents(10);
                  }
                  int runtimeVisibleAnnotationsAttributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
                  contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
                  int attributeLengthOffset = contentsOffset;
                  contentsOffset += 4; // leave space for the attribute length
      
                  int annotationsLengthOffset = contentsOffset;
                  contentsOffset += 2; // leave space for the annotations length
            
                  contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
                  contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;

                  loop: for (int i = 0; i < length; i++) {
                        if (visibleAnnotationsCounter == 0) break loop;
                        Annotation annotation = annotations[i];
                        if (isRuntimeVisible(annotation)) {
                              visibleAnnotationsCounter--;
                              generateAnnotation(annotation, annotationAttributeOffset);
                              if (this.contentsOffset == annotationAttributeOffset) {
                                    break loop;
                              }
                        }
                  }
                  if (contentsOffset != annotationAttributeOffset) {
                        int attributeLength = contentsOffset - attributeLengthOffset - 4;
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
                        contents[attributeLengthOffset++] = (byte) attributeLength;             
                        attributesNumber++;
                  } else {
                        contentsOffset = annotationAttributeOffset;
                  }
            }
            return attributesNumber;
      }

      private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
            final int argumentsLength = arguments.length;
            final int VISIBLE_INDEX = 0;
            final int INVISIBLE_INDEX = 1;
            int invisibleParametersAnnotationsCounter = 0;
            int visibleParametersAnnotationsCounter = 0;
            int[][] annotationsCounters = new int[argumentsLength][2];
            for (int i = 0; i < argumentsLength; i++) {
                  Argument argument = arguments[i];
                  Annotation[] annotations = argument.annotations;
                  if (annotations != null) {
                        for (int j = 0, max2 = annotations.length; j < max2; j++) {
                              Annotation annotation = annotations[j];
                              if (isRuntimeInvisible(annotation)) {
                                    annotationsCounters[i][INVISIBLE_INDEX]++;
                                    invisibleParametersAnnotationsCounter++;
                              } else if (isRuntimeVisible(annotation)) {
                                    annotationsCounters[i][VISIBLE_INDEX]++;
                                    visibleParametersAnnotationsCounter++;
                              }
                        }
                  }
            }
            int attributesNumber = 0;
            int annotationAttributeOffset = contentsOffset;
            if (invisibleParametersAnnotationsCounter != 0) {
                  if (contentsOffset + 7 >= contents.length) {
                        resizeContents(7);
                  }
                  int attributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
                  contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) attributeNameIndex;
                  int attributeLengthOffset = contentsOffset;
                  contentsOffset += 4; // leave space for the attribute length

                  contents[contentsOffset++] = (byte) argumentsLength;
                  invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
                        if (contentsOffset + 2 >= contents.length) {
                              resizeContents(2);
                        }
                        if (invisibleParametersAnnotationsCounter == 0) {
                              contents[contentsOffset++] = (byte) 0;
                              contents[contentsOffset++] = (byte) 0;                            
                        } else {
                              final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
                              contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
                              contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
                              if (numberOfInvisibleAnnotations != 0) {
                                    Argument argument = arguments[i];
                                    Annotation[] annotations = argument.annotations;
                                    for (int j = 0, max = annotations.length; j < max; j++) {
                                          Annotation annotation = annotations[j];
                                          if (isRuntimeInvisible(annotation)) {
                                                generateAnnotation(annotation, annotationAttributeOffset);
                                                if (contentsOffset == annotationAttributeOffset) {
                                                      break invisibleLoop;
                                                }
                                                invisibleParametersAnnotationsCounter--;
                                          }
                                    }
                              }
                        }
                  }
                  if (contentsOffset != annotationAttributeOffset) {
                        int attributeLength = contentsOffset - attributeLengthOffset - 4;
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
                        contents[attributeLengthOffset++] = (byte) attributeLength;             
                        attributesNumber++;
                  } else {
                        contentsOffset = annotationAttributeOffset;
                  }
            }
            if (visibleParametersAnnotationsCounter != 0) {
                  if (contentsOffset + 7 >= contents.length) {
                        resizeContents(7);
                  }
                  int attributeNameIndex =
                        constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
                  contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
                  contents[contentsOffset++] = (byte) attributeNameIndex;
                  int attributeLengthOffset = contentsOffset;
                  contentsOffset += 4; // leave space for the attribute length

                  contents[contentsOffset++] = (byte) argumentsLength;
                  visibleLoop: for (int i = 0; i < argumentsLength; i++) {
                        if (contentsOffset + 2 >= contents.length) {
                              resizeContents(2);
                        }
                        if (visibleParametersAnnotationsCounter == 0) {
                              contents[contentsOffset++] = (byte) 0;
                              contents[contentsOffset++] = (byte) 0;                            
                        } else {
                              final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
                              contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
                              contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
                              if (numberOfVisibleAnnotations != 0) {
                                    Argument argument = arguments[i];
                                    Annotation[] annotations = argument.annotations;
                                    for (int j = 0, max = annotations.length; j < max; j++) {
                                          Annotation annotation = annotations[j];
                                          if (isRuntimeVisible(annotation)) {
                                                generateAnnotation(annotation, annotationAttributeOffset);
                                                if (contentsOffset == annotationAttributeOffset) {
                                                      break visibleLoop;
                                                }
                                                visibleParametersAnnotationsCounter--;
                                          }
                                    }
                              }
                        }
                  }
                  if (contentsOffset != annotationAttributeOffset) {
                        int attributeLength = contentsOffset - attributeLengthOffset - 4;
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
                        contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
                        contents[attributeLengthOffset++] = (byte) attributeLength;             
                        attributesNumber++;
                  } else {
                        contentsOffset = annotationAttributeOffset;
                  }
            }
            return attributesNumber;
      }
      
      /**
       * EXTERNAL API
       * Answer the actual bytes of the class file
       *
       * This method encodes the receiver structure into a byte array which is the content of the classfile.
       * Returns the byte array that represents the encoded structure of the receiver.
       *
       * @return byte[]
       */
05787       public byte[] getBytes() {
            if (this.bytes == null) {
                  this.bytes = new byte[this.headerOffset + this.contentsOffset];
                  System.arraycopy(this.header, 0, this.bytes, 0, this.headerOffset);
                  System.arraycopy(this.contents, 0, this.bytes, this.headerOffset, this.contentsOffset);
            }
            return this.bytes;
      }
      /**
       * EXTERNAL API
       * Answer the compound name of the class file.
       * @return char[][]
       * e.g. {{java}, {util}, {Hashtable}}.
       */
05801       public char[][] getCompoundName() {
            return CharOperation.splitOn('/', fileName());
      }

      protected void initByteArrays() {
            int members = referenceBinding.methods().length + referenceBinding.fields().length;
            this.header = new byte[INITIAL_HEADER_SIZE];
            this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
      }

      public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) {
            // generate the magic numbers inside the header
            header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
            header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
            header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
            header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
            
            header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
            header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
            header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
            header[headerOffset++] = (byte) (this.targetJDK >> 16); // major low

            constantPoolOffset = headerOffset;
            headerOffset += 2;
            this.constantPool.initialize(this);
            
            // Modifier manipulations for classfile
            int accessFlags = aType.getAccessFlags();
            if (aType.isPrivate()) { // rewrite private to non-public
                  accessFlags &= ~ClassFileConstants.AccPublic;
            }
            if (aType.isProtected()) { // rewrite protected into public
                  accessFlags |= ClassFileConstants.AccPublic;
            }
            // clear all bits that are illegal for a class or an interface
            accessFlags
                  &= ~(
                        ClassFileConstants.AccStrictfp
                              | ClassFileConstants.AccProtected
                              | ClassFileConstants.AccPrivate
                              | ClassFileConstants.AccStatic
                              | ClassFileConstants.AccSynchronized
                              | ClassFileConstants.AccNative);
                              
            // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
            if (!aType.isInterface()) { // class or enum
                  accessFlags |= ClassFileConstants.AccSuper;
            }
            
            this.enclosingClassFile = parentClassFile;
            // innerclasses get their names computed at code gen time

            // now we continue to generate the bytes inside the contents array
            contents[contentsOffset++] = (byte) (accessFlags >> 8);
            contents[contentsOffset++] = (byte) accessFlags;
            int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName());
            contents[contentsOffset++] = (byte) (classNameIndex >> 8);
            contents[contentsOffset++] = (byte) classNameIndex;
            int superclassNameIndex;
            if (aType.isInterface()) {
                  superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
            } else {
                  superclassNameIndex =
                        (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName()));
            }
            contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
            contents[contentsOffset++] = (byte) superclassNameIndex;
            ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
            int interfacesCount = superInterfacesBinding.length;
            contents[contentsOffset++] = (byte) (interfacesCount >> 8);
            contents[contentsOffset++] = (byte) interfacesCount;
            for (int i = 0; i < interfacesCount; i++) {
                  int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
                  contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
                  contents[contentsOffset++] = (byte) interfaceIndex;
            }
            innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
            this.creatingProblemType = createProblemType;

            // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
            // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
            if (this.enclosingClassFile == null) {
                  this.codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
            } else {
                  ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
                  this.codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
            }
      }

      
      private boolean isRuntimeInvisible(Annotation annotation) {
            final TypeBinding annotationBinding = annotation.resolvedType;
            if (annotationBinding == null) {
                  return false;
            }
            long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference
            if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
                  return true; // by default the retention is CLASS
                  
            return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
      }

      private boolean isRuntimeVisible(Annotation annotation) {
            final TypeBinding annotationBinding = annotation.resolvedType;
            if (annotationBinding == null) {
                  return false;
            }
            long metaTagBits = annotationBinding.getAnnotationTagBits();
            if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
                  return false; // by default the retention is CLASS
                  
            return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
      }

      /**
       * INTERNAL USE-ONLY
       * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
       * for all inner types of the receiver.
       * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
       */
05921       public ClassFile outerMostEnclosingClassFile() {
            ClassFile current = this;
            while (current.enclosingClassFile != null)
                  current = current.enclosingClassFile;
            return current;
      }

      /**
       * INTERNAL USE-ONLY
       * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
       * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
       *
       * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
       */
05935       public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
            // add all the enclosing types
            ReferenceBinding enclosingType = referenceBinding.enclosingType();
            int depth = 0;
            while (enclosingType != null) {
                  depth++;
                  enclosingType = enclosingType.enclosingType();
            }
            enclosingType = referenceBinding;
            ReferenceBinding enclosingTypes[];
            if (depth >= 2) {
                  enclosingTypes = new ReferenceBinding[depth];
                  for (int i = depth - 1; i >= 0; i--) {
                        enclosingTypes[i] = enclosingType;
                        enclosingType = enclosingType.enclosingType();
                  }
                  for (int i = 0; i < depth; i++) {
                        addInnerClasses(enclosingTypes[i]);
                  }
            } else {
                  addInnerClasses(referenceBinding);
            }
      }

      /**
       * INTERNAL USE-ONLY
       * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
       * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
       *
       * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
       */
05966       public void recordNestedLocalAttribute(ReferenceBinding binding) {
            // add all the enclosing types
            ReferenceBinding enclosingType = referenceBinding.enclosingType();
            int depth = 0;
            while (enclosingType != null) {
                  depth++;
                  enclosingType = enclosingType.enclosingType();
            }
            enclosingType = referenceBinding;
            ReferenceBinding enclosingTypes[];
            if (depth >= 2) {
                  enclosingTypes = new ReferenceBinding[depth];
                  for (int i = depth - 1; i >= 0; i--) {
                        enclosingTypes[i] = enclosingType;
                        enclosingType = enclosingType.enclosingType();
                  }
                  for (int i = 0; i < depth; i++)
                        addInnerClasses(enclosingTypes[i]);
            } else {
                  addInnerClasses(binding);
            }
      }

      /**
       * INTERNAL USE-ONLY
       * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
       * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
       *
       * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
       */
05996       public void recordNestedMemberAttribute(ReferenceBinding binding) {
            addInnerClasses(binding);
      }
      
      public void reset(SourceTypeBinding typeBinding) {
            // the code stream is reinitialized for each method
            final CompilerOptions options = typeBinding.scope.compilerOptions();
            this.referenceBinding = typeBinding;
            this.targetJDK = options.targetJDK;
            this.produceAttributes = options.produceDebugAttributes;
            if (this.targetJDK >= ClassFileConstants.JDK1_6) {
                  this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
            }
            this.bytes = null;
            this.constantPool.reset();
            this.codeStream.reset(this);
            this.constantPoolOffset = 0;
            this.contentsOffset = 0;
            this.creatingProblemType = false;
            this.enclosingClassFile = null;
            this.headerOffset = 0;
            this.methodCount = 0;
            this.methodCountOffset = 0;
            this.numberOfInnerClasses = 0;
      }

      /**
       * Resize the pool contents
       */
06025       private final void resizeContents(int minimalSize) {
            int length = this.contents.length;
            int toAdd = length;
            if (toAdd < minimalSize)
                  toAdd = minimalSize;
            System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
      }

      /**
       * INTERNAL USE-ONLY
       * This methods leaves the space for method counts recording.
       */
06037       public void setForMethodInfos() {
            // leave some space for the methodCount
            methodCountOffset = contentsOffset;
            contentsOffset += 2;
      }
}

Generated by  Doxygen 1.6.0   Back to index